LCOV - code coverage report
Current view: top level - build directory/src/plugins/haskell - haskell.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 29 39 74.4 %
Date: 2019-09-12 12:28:41 Functions: 6 7 85.7 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief Source for haskell plugin
       5             :  *
       6             :  * Gets configured by cmake as this is the base file for other haskell plugins.
       7             :  * See the cmake macro add_haskell_plugin for details.
       8             :  *
       9             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
      10             :  */
      11             : 
      12             : #include "Haskell_stub.h"
      13             : #include "haskell.h"
      14             : 
      15             : #include <kdbhelper.h>
      16             : #include <kdbpluginprocess.h>
      17             : #include <stdio.h>
      18             : 
      19          24 : int elektraHaskellOpen (Plugin * handle, Key * errorKey)
      20             : {
      21          24 :         ElektraPluginProcess * pp = elektraPluginGetData (handle);
      22          24 :         if (pp == NULL)
      23             :         {
      24          22 :                 if ((pp = elektraPluginProcessInit (errorKey)) == NULL) return ELEKTRA_PLUGIN_STATUS_ERROR;
      25          22 :                 elektraPluginSetData (handle, pp);
      26          22 :                 if (!elektraPluginProcessIsParent (pp)) elektraPluginProcessStart (handle, pp);
      27             :         }
      28          24 :         if (elektraPluginProcessIsParent (pp)) return elektraPluginProcessOpen (pp, errorKey);
      29             : 
      30           0 :         char *argv[] = { "haskell", 0 }, **argvPtr = argv;
      31           0 :         int argc = 1;
      32             :         // Startup the haskell runtime with some dummy args
      33             :         // Subsequent init calls are ignored by the runtime
      34           0 :         hs_init (&argc, &argvPtr);
      35           0 :         return hs_elektraHaskellOpen (handle, errorKey);
      36             : }
      37             : 
      38          24 : int elektraHaskellClose (Plugin * handle, Key * errorKey)
      39             : {
      40          24 :         ElektraPluginProcess * pp = elektraPluginGetData (handle);
      41          24 :         if (elektraPluginProcessIsParent (pp))
      42             :         {
      43          24 :                 ElektraPluginProcessCloseResult result = elektraPluginProcessClose (pp, errorKey);
      44          24 :                 if (result.cleanedUp) elektraPluginSetData (handle, NULL);
      45          24 :                 return result.result;
      46             :         }
      47             : 
      48           0 :         int ret = hs_elektraHaskellClose (handle, errorKey);
      49             :         // Shutdown the haskell runtime
      50             :         // Due to an unfortunate bug within GHC's ffi implementation we cannot
      51             :         // restart the runtime if it got closed once during elektra's runtime
      52             :         // in the same process.
      53             :         // Therefore we use the plugin process library to launch the runtime
      54             :         // in a separate process.
      55             :         // https://downloads.haskell.org/~ghc/8.2.2/docs/html/users_guide/bugs.html#infelicities-ffi
      56           0 :         hs_exit ();
      57           0 :         return ret;
      58             : }
      59             : 
      60          22 : int elektraHaskellGet (Plugin * handle, KeySet * returned, Key * parentKey)
      61             : {
      62          22 :         if (!elektraStrCmp (keyName (parentKey), "system/elektra/modules/haskell"))
      63             :         {
      64          20 :                 KeySet * contract = ksNew (
      65             :                         30,
      66             :                         keyNew ("system/elektra/modules/haskell", KEY_VALUE, "haskell plugin waits for your orders", KEY_END),
      67             :                         keyNew ("system/elektra/modules/haskell/exports", KEY_END),
      68             :                         keyNew ("system/elektra/modules/haskell/exports/open", KEY_FUNC, elektraHaskellOpen, KEY_END),
      69             :                         keyNew ("system/elektra/modules/haskell/exports/close", KEY_FUNC, elektraHaskellClose, KEY_END),
      70             :                         keyNew ("system/elektra/modules/haskell/exports/get", KEY_FUNC, elektraHaskellGet, KEY_END),
      71             :                         keyNew ("system/elektra/modules/haskell/exports/set", KEY_FUNC, elektraHaskellSet, KEY_END),
      72             :                         keyNew ("system/elektra/modules/haskell/exports/error", KEY_FUNC, elektraHaskellError, KEY_END),
      73             : // clang-format off
      74             : #include ELEKTRA_README
      75             :                         // clang-format on
      76             :                         keyNew ("system/elektra/modules/haskell/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END);
      77          20 :                 ksAppend (returned, contract);
      78          20 :                 ksDel (contract);
      79             : 
      80          20 :                 return ELEKTRA_PLUGIN_STATUS_SUCCESS;
      81             :         }
      82             : 
      83           2 :         ElektraPluginProcess * pp = elektraPluginGetData (handle);
      84           2 :         if (elektraPluginProcessIsParent (pp)) return elektraPluginProcessSend (pp, ELEKTRA_PLUGINPROCESS_GET, returned, parentKey);
      85             : 
      86           0 :         return hs_elektraHaskellGet (handle, returned, parentKey);
      87             : }
      88             : 
      89           2 : int elektraHaskellSet (Plugin * handle, KeySet * returned, Key * parentKey)
      90             : {
      91           2 :         ElektraPluginProcess * pp = elektraPluginGetData (handle);
      92           2 :         if (elektraPluginProcessIsParent (pp)) return elektraPluginProcessSend (pp, ELEKTRA_PLUGINPROCESS_SET, returned, parentKey);
      93             : 
      94           0 :         return hs_elektraHaskellSet (handle, returned, parentKey);
      95             : }
      96             : 
      97           2 : int elektraHaskellError (Plugin * handle, KeySet * returned, Key * parentKey)
      98             : {
      99           2 :         ElektraPluginProcess * pp = elektraPluginGetData (handle);
     100           2 :         if (elektraPluginProcessIsParent (pp)) return elektraPluginProcessSend (pp, ELEKTRA_PLUGINPROCESS_ERROR, returned, parentKey);
     101             : 
     102           0 :         return hs_elektraHaskellError (handle, returned, parentKey);
     103             : }
     104             : 
     105             : // clang-format off
     106          22 : Plugin * ELEKTRA_PLUGIN_EXPORT
     107             : {
     108          22 :         return elektraPluginExport ("haskell",
     109             :                 ELEKTRA_PLUGIN_OPEN,    &elektraHaskellOpen,
     110             :                 ELEKTRA_PLUGIN_CLOSE,   &elektraHaskellClose,
     111             :                 ELEKTRA_PLUGIN_GET,             &elektraHaskellGet,
     112             :                 ELEKTRA_PLUGIN_SET,             &elektraHaskellSet,
     113             :                 ELEKTRA_PLUGIN_ERROR,   &elektraHaskellError,
     114             :                 ELEKTRA_PLUGIN_END);
     115             : }

Generated by: LCOV version 1.13