LCOV - code coverage report
Current view: top level - src/plugins/lua - lua.cpp (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 85 93 91.4 %
Date: 2019-09-12 12:28:41 Functions: 13 14 92.9 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief Plugin which acts as proxy and calls other plugins written in lua
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  *
       8             :  */
       9             : 
      10             : #ifndef SWIG_TYPE_TABLE
      11             : #error Build system error, SWIG_TYPE_TABLE is not defined
      12             : #endif
      13             : 
      14             : #include "lua.hpp"
      15             : #include <kdbhelper.h>
      16             : #include <kdbmacros.h>
      17             : 
      18             : #include <key.hpp>
      19             : #include <keyset.hpp>
      20             : #include <libgen.h>
      21             : 
      22             : #include <lua.hpp>
      23             : extern "C" {
      24             : #include <lualib.h>
      25             : }
      26             : #include "runtime.h"
      27             : 
      28             : using namespace ckdb;
      29             : #include <kdberrors.h>
      30             : 
      31             : #ifndef LUA_OK
      32             : #define LUA_OK 0
      33             : #endif
      34             : 
      35          13 : static void Lua_fromSWIG (lua_State * L, ckdb::Key * key)
      36             : {
      37          13 :         swig_type_info * ti = SWIG_TypeQuery (L, "kdb::Key *");
      38          13 :         if (key == NULL || ti == NULL)
      39           4 :                 lua_pushnil (L);
      40             :         else
      41          18 :                 SWIG_NewPointerObj (L, new kdb::Key (key), ti, 0);
      42          13 : }
      43             : 
      44           9 : static void Lua_fromSWIG (lua_State * L, ckdb::KeySet * keyset)
      45             : {
      46           9 :         swig_type_info * ti = SWIG_TypeQuery (L, "kdb::KeySet *");
      47           9 :         if (keyset == NULL || ti == NULL)
      48           0 :                 lua_pushnil (L);
      49             :         else
      50          18 :                 SWIG_NewPointerObj (L, new kdb::KeySet (keyset), ti, 0);
      51           9 : }
      52             : 
      53             : typedef struct
      54             : {
      55             :         lua_State * L;
      56             :         int printError;
      57             :         int shutdown;
      58             : } moduleData;
      59             : 
      60             : static void Lua_Shutdown (lua_State * L)
      61             : {
      62           5 :         if (L) lua_close (L);
      63             : }
      64             : 
      65           5 : static int Lua_Require (lua_State * L, const char * name)
      66             : {
      67           5 :         lua_getglobal (L, "require");
      68           5 :         lua_pushstring (L, name);
      69           5 :         int status = lua_pcall (L, 1, 1, 0);
      70           5 :         if (status == LUA_OK) lua_setglobal (L, name);
      71           5 :         return status;
      72             : }
      73             : 
      74          13 : static int Lua_CallFunction_Int (lua_State * L, int nargs, ckdb::Key * errorKey)
      75             : {
      76          13 :         int ret = -1;
      77          13 :         if (lua_pcall (L, nargs, 1, 0) != LUA_OK)
      78           1 :                 ELEKTRA_SET_VALIDATION_SEMANTIC_ERROR (errorKey, lua_tostring (L, -1));
      79             :         else
      80             :         {
      81          12 :                 if (!lua_isnumber (L, -1))
      82           0 :                         ELEKTRA_SET_VALIDATION_SEMANTIC_ERROR (errorKey, "Return value is no integer");
      83             :                 else
      84          12 :                         ret = lua_tonumber (L, -1);
      85             :         }
      86          13 :         return ret;
      87             : }
      88             : 
      89           5 : static int Lua_CallFunction_Helper1 (lua_State * L, const char * funcName, ckdb::Key * errorKey)
      90             : {
      91           5 :         int ret = 0;
      92           5 :         int top = lua_gettop (L);
      93           5 :         lua_getglobal (L, funcName);
      94           5 :         if (lua_isfunction (L, -1))
      95             :         {
      96           4 :                 Lua_fromSWIG (L, errorKey);
      97           4 :                 ret = Lua_CallFunction_Int (L, 1, errorKey);
      98             :         }
      99           5 :         lua_settop (L, top);
     100           5 :         return ret;
     101             : }
     102             : 
     103           9 : static int Lua_CallFunction_Helper2 (lua_State * L, const char * funcName, ckdb::KeySet * returned, ckdb::Key * parentKey)
     104             : {
     105           9 :         int ret = 0;
     106           9 :         int top = lua_gettop (L);
     107           9 :         lua_getglobal (L, funcName);
     108           9 :         if (lua_isfunction (L, -1))
     109             :         {
     110           9 :                 Lua_fromSWIG (L, returned);
     111           9 :                 Lua_fromSWIG (L, parentKey);
     112           9 :                 ret = Lua_CallFunction_Int (L, 2, parentKey);
     113             :         }
     114           9 :         lua_settop (L, top);
     115           9 :         return ret;
     116             : }
     117             : 
     118             : extern "C" {
     119        9352 : static void * Lua_alloc (void * ud ELEKTRA_UNUSED, void * ptr, size_t osize ELEKTRA_UNUSED, size_t nsize)
     120             : {
     121        9352 :         if (nsize == 0)
     122             :         {
     123        4545 :                 elektraFree (ptr);
     124        4545 :                 return NULL;
     125             :         }
     126        4807 :         return (elektraRealloc (&ptr, nsize) < 0) ? NULL : ptr;
     127             : }
     128             : 
     129          25 : int elektraLuaOpen (ckdb::Plugin * handle, ckdb::Key * errorKey)
     130             : {
     131          25 :         KeySet * config = elektraPluginGetConfig (handle);
     132             : 
     133          25 :         Key * script = ksLookupByName (config, "/script", 0);
     134          25 :         if (script == NULL || !strlen (keyString (script)))
     135             :         {
     136          20 :                 if (ksLookupByName (config, "/module", 0) != NULL)
     137             :                 {
     138             :                         return 0; // by convention: success if /module exists
     139             :                 }
     140           2 :                 ELEKTRA_SET_INSTALLATION_ERROR (errorKey, "No lua script set");
     141           2 :                 return -1;
     142             :         }
     143             : 
     144             :         /* create module data */
     145           5 :         moduleData * data = new moduleData;
     146             : 
     147             :         /* init new lua state */
     148           5 :         if ((data->L = lua_newstate (Lua_alloc, NULL)) == NULL)
     149             :         {
     150           0 :                 ELEKTRA_SET_OUT_OF_MEMORY_ERROR (errorKey, "Unable to create new lua state");
     151           0 :                 goto error;
     152             :         }
     153             : 
     154             :         /* load std. libs */
     155           5 :         luaL_openlibs (data->L);
     156             : 
     157             :         /* require kdb */
     158           5 :         if (Lua_Require (data->L, "kdb") != LUA_OK) goto error_print;
     159             : 
     160             :         /* load lua script */
     161           5 :         if (luaL_dofile (data->L, keyString (script))) goto error_print;
     162             : 
     163             :         /* store module data after everything is set up */
     164           5 :         elektraPluginSetData (handle, data);
     165             : 
     166             :         /* call lua function */
     167           5 :         return Lua_CallFunction_Helper2 (data->L, "elektraOpen", config, errorKey);
     168             : 
     169             : error_print:
     170           0 :         if (!lua_isnil (data->L, -1)) ELEKTRA_SET_INSTALLATION_ERROR (errorKey, lua_tostring (data->L, -1));
     171             : error:
     172             :         /* destroy lua */
     173           0 :         Lua_Shutdown (data->L);
     174           0 :         delete data;
     175           0 :         return -1;
     176             : }
     177             : 
     178          25 : int elektraLuaClose (ckdb::Plugin * handle, ckdb::Key * errorKey)
     179             : {
     180          25 :         moduleData * data = static_cast<moduleData *> (elektraPluginGetData (handle));
     181          25 :         if (data == NULL) return 0;
     182             : 
     183           5 :         int ret = Lua_CallFunction_Helper1 (data->L, "elektraClose", errorKey);
     184             : 
     185             :         /* destroy lua */
     186          10 :         Lua_Shutdown (data->L);
     187           5 :         delete data;
     188           5 :         return ret;
     189             : }
     190             : 
     191          20 : int elektraLuaGet (ckdb::Plugin * handle, ckdb::KeySet * returned, ckdb::Key * parentKey)
     192             : {
     193             : #define _MODULE_CONFIG_PATH "system/elektra/modules/lua"
     194          20 :         if (!strcmp (keyName (parentKey), _MODULE_CONFIG_PATH))
     195             :         {
     196             :                 KeySet * n;
     197             :                 ksAppend (returned,
     198          18 :                           n = ksNew (30, keyNew (_MODULE_CONFIG_PATH, KEY_VALUE, "lua interpreter waits for your orders", KEY_END),
     199             :                                      keyNew (_MODULE_CONFIG_PATH "/exports", KEY_END),
     200             :                                      keyNew (_MODULE_CONFIG_PATH "/exports/get", KEY_FUNC, elektraLuaGet, KEY_END),
     201             :                                      keyNew (_MODULE_CONFIG_PATH "/exports/set", KEY_FUNC, elektraLuaSet, KEY_END),
     202             :                                      keyNew (_MODULE_CONFIG_PATH "/exports/error", KEY_FUNC, elektraLuaError, KEY_END),
     203             :                                      keyNew (_MODULE_CONFIG_PATH "/exports/open", KEY_FUNC, elektraLuaOpen, KEY_END),
     204             :                                      keyNew (_MODULE_CONFIG_PATH "/exports/close", KEY_FUNC, elektraLuaClose, KEY_END),
     205             : #include ELEKTRA_README
     206          18 :                                      keyNew (_MODULE_CONFIG_PATH "/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END));
     207          18 :                 ksDel (n);
     208             :         }
     209             : 
     210          20 :         moduleData * data = static_cast<moduleData *> (elektraPluginGetData (handle));
     211          20 :         if (data != NULL) return Lua_CallFunction_Helper2 (data->L, "elektraGet", returned, parentKey);
     212             :         return 0;
     213             : }
     214             : 
     215           1 : int elektraLuaSet (ckdb::Plugin * handle, ckdb::KeySet * returned, ckdb::Key * parentKey)
     216             : {
     217           1 :         moduleData * data = static_cast<moduleData *> (elektraPluginGetData (handle));
     218           1 :         if (data != NULL) return Lua_CallFunction_Helper2 (data->L, "elektraSet", returned, parentKey);
     219             :         return 0;
     220             : }
     221             : 
     222           1 : int elektraLuaError (ckdb::Plugin * handle, ckdb::KeySet * returned, ckdb::Key * parentKey)
     223             : {
     224           1 :         moduleData * data = static_cast<moduleData *> (elektraPluginGetData (handle));
     225           1 :         if (data != NULL) return Lua_CallFunction_Helper2 (data->L, "elektraError", returned, parentKey);
     226             :         return 0;
     227             : }
     228             : 
     229          25 : ckdb::Plugin * ELEKTRA_PLUGIN_EXPORT
     230             : {
     231             :         // clang-format off
     232             :         return elektraPluginExport("lua",
     233             :                 ELEKTRA_PLUGIN_OPEN,  &elektraLuaOpen,
     234             :                 ELEKTRA_PLUGIN_CLOSE, &elektraLuaClose,
     235             :                 ELEKTRA_PLUGIN_GET,   &elektraLuaGet,
     236             :                 ELEKTRA_PLUGIN_SET,   &elektraLuaSet,
     237             :                 ELEKTRA_PLUGIN_ERROR, &elektraLuaError,
     238          25 :                 ELEKTRA_PLUGIN_END);
     239             : }
     240             : }
     241             : 

Generated by: LCOV version 1.13