lua-bindings: first shot at Murphy.include/Murphy.try_include, for more modular confi...
authorKrisztian Litkey <kli@iki.fi>
Wed, 4 Dec 2013 23:31:29 +0000 (01:31 +0200)
committerKrisztian Litkey <kli@iki.fi>
Wed, 4 Dec 2013 23:31:29 +0000 (01:31 +0200)
src/core/lua-bindings/lua-lua.c
src/core/lua-bindings/lua-murphy.c
src/core/lua-bindings/murphy.h
src/plugins/plugin-lua.c

index 7d18857..609bc4a 100644 (file)
@@ -27,6 +27,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <unistd.h>
+
 #include <lualib.h>
 #include <lauxlib.h>
 
 #include <murphy/core/lua-bindings/murphy.h>
 
 
+static int include_file(lua_State *L, int try_only)
+{
+    const char *file, *dir;;
+    char        path[PATH_MAX];
+    int         narg;
+
+    narg = lua_gettop(L);
+
+    switch (narg) {
+    case 1:
+        if (lua_type(L, -1) != LUA_TSTRING)
+            return luaL_error(L, "expecting <string> for inclusion");
+        break;
+    case 2:
+        if (lua_type(L, -2) != LUA_TUSERDATA ||
+            lua_type(L, -1) != LUA_TSTRING)
+            return luaL_error(L, "expecting <murphy>, <string> for inclusion");
+        break;
+    default:
+        return luaL_error(L, "expecting <string> for inclusion");
+    }
+
+    /*
+     * XXX TODO:
+     * Maybe it'd make sense to support searching a set of user-configurable
+     * include diretories if the given path is not an absolute one.
+     */
+
+    file = lua_tostring(L, -1);
+
+    if (file[0] != '/') {
+        if ((dir = mrp_lua_get_murphy_lua_config_dir()) != NULL) {
+            if (snprintf(path, sizeof(path),
+                         "%s/%s", dir, file) < (ssize_t)sizeof(path))
+                file = path;
+            else {
+                mrp_log_error("too long include file name");
+                lua_settop(L, 0);
+
+                return -1;
+            }
+        }
+    }
+
+    if (try_only && access(file, R_OK) < 0) {
+        lua_settop(L, 0);
+
+        return 0;
+    }
+
+
+    if (!luaL_loadfile(L, file) && !lua_pcall(L, 0, 0, 0)) {
+        lua_settop(L, 0);
+
+        return 0;
+    }
+
+    mrp_log_error("failed to include Lua file '%s'.", file);
+    mrp_log_error("%s", lua_tostring(L, -1));
+    lua_settop(L, 0);
+
+    return -1;
+}
+
+
+static int tryinclude_luafile(lua_State *L)
+{
+    return include_file(L, TRUE);
+}
+
+
+static int include_luafile(lua_State *L)
+{
+    return include_file(L, FALSE);
+}
+
+
 static int open_lualib(lua_State *L)
 {
     struct {
@@ -87,4 +166,7 @@ static int open_lualib(lua_State *L)
 }
 
 
-MURPHY_REGISTER_LUA_BINDINGS(murphy, NULL, { "open_lualib", open_lualib });
+MURPHY_REGISTER_LUA_BINDINGS(murphy, NULL,
+                             { "open_lualib", open_lualib        },
+                             { "include"    , include_luafile    },
+                             { "try_include", tryinclude_luafile });
index 00a5990..3f9f860 100644 (file)
@@ -27,6 +27,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <unistd.h>
+
 #include <lualib.h>
 #include <lauxlib.h>
 
@@ -42,6 +44,8 @@ static mrp_context_t *context;
 static MRP_LIST_HOOK(bindings);
 static MRP_LIST_HOOK(pending);
 static int debug_level;
+static char *config_file;
+static char *config_dir;
 
 static void setup_allocator(lua_State *L);
 
@@ -183,6 +187,15 @@ lua_State *mrp_lua_set_murphy_context(mrp_context_t *ctx)
 }
 
 
+void mrp_lua_set_murphy_lua_config_file(const char *path)
+{
+    if (config_file == NULL && path != NULL) {
+        config_file = mrp_strdup(path);
+        mrp_log_info("Lua config file is: '%s'.", config_file);
+    }
+}
+
+
 mrp_context_t *mrp_lua_check_murphy_context(lua_State *L, int index)
 {
     mrp_lua_murphy_t *m;
@@ -211,6 +224,56 @@ lua_State *mrp_lua_get_lua_state(void)
         return NULL;
 }
 
+const char *mrp_lua_get_murphy_lua_config_dir(void)
+{
+    char   *base, dir[PATH_MAX];
+    size_t  offs, len;
+
+    if (config_file == NULL)
+        return NULL;
+
+    if (config_dir == NULL) {
+        if (config_file[0] != '/') {
+            if (getcwd(dir, sizeof(dir)) == NULL)
+                return NULL;
+            else {
+                offs = strlen(dir);
+
+                if (offs >= sizeof(dir) - 1)
+                    return NULL;
+
+                dir[offs++] = '/';
+                dir[offs]   = '\0';
+            }
+        }
+        else
+            offs = 0;
+
+        base = strrchr(config_file, '/');
+
+        if (base != NULL)
+            while (base > config_file && base[-1] == '/')
+                base--;
+
+        if (base != NULL && base > config_file) {
+            len = base - config_file;
+
+            if (sizeof(dir) - offs - 1 <= len)
+                return NULL;
+
+            strncpy(dir + offs, config_file, len);
+            offs += len;
+            dir[offs] = '\0';
+
+            config_dir = mrp_strdup(dir);
+
+            mrp_log_info("Lua config directory is '%s'.", config_dir);
+        }
+    }
+
+    return config_dir;
+}
+
 
 /*
  * runtime debugging
index 7a12b52..42b5263 100644 (file)
@@ -74,12 +74,18 @@ typedef struct {
 /** Set murphy context for the bindings. */
 lua_State *mrp_lua_set_murphy_context(mrp_context_t *ctx);
 
+/** Set the path to the main Lua configuration file. */
+void mrp_lua_set_murphy_lua_config_file(const char *path);
+
 /** Get murphy context for the bindings. */
 mrp_context_t *mrp_lua_get_murphy_context(void);
 
 /** Get the common Lua state for the bindings. */
 lua_State *mrp_lua_get_lua_state(void);
 
+/** Get the main Lua configuration directory. */
+const char *mrp_lua_get_murphy_lua_config_dir(void);
+
 /** Register the given lua murphy bindings. */
 int mrp_lua_register_murphy_bindings(mrp_lua_bindings_t *b);
 
index 6487a81..b0eb446 100644 (file)
@@ -157,6 +157,8 @@ static int plugin_init(mrp_plugin_t *plugin)
         else
             mrp_log_info("plugin-lua: resolver Lua support disabled.");
 
+        mrp_lua_set_murphy_lua_config_file(cfg);
+
         if (load_config(L, cfg))
             return TRUE;
         else