add nexus_lua_error for unified LUA_ERR* -> ERR_LUA_* mapping, and lua configuration support
authorTero Marttila <terom@fixme.fi>
Wed, 01 Apr 2009 01:41:08 +0300
changeset 106 f00661136ac2
parent 105 b6b183fbf373
child 107 5c1eeb45c7f2
add nexus_lua_error for unified LUA_ERR* -> ERR_LUA_* mapping, and lua configuration support
config.lua
src/CMakeLists.txt
src/error.c
src/error.h
src/lua_config.c
src/lua_config.h
src/lua_console.c
src/lua_objs.c
src/lua_objs.h
src/nexus.c
src/nexus_lua.c
src/nexus_lua.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config.lua	Wed Apr 01 01:41:08 2009 +0300
@@ -0,0 +1,59 @@
+local conf = {
+    log_level   = "DEBUG",
+
+    name = {
+        nickname    = "SpBotDev",
+        username    = "spbot-dev",
+        realname    = "SpBot (development version)"
+    },
+
+    networks = {
+        PVLNet      = {
+            hostname    = "irc.fixme.fi",
+
+            channels    = {
+                "#test"
+            }
+        },
+    },
+
+    modules = {
+        irc_log     = {
+            path        = "src/modules/mod_irc_log.so",
+
+            conf        = {
+                db_info     = "dbname=spbot",
+                channel     = "PVLNet/#test",
+            }
+        }
+    },
+}
+
+-- apply general
+log_level(conf.log_level)
+
+-- apply conf_name
+client:set_defaults(conf.name.nickname, conf.name.username, conf.name.realname)
+
+-- apply conf_networks
+for network, settings in pairs(conf.networks) do
+    -- establish the irc_net
+    net = client:connect(network, settings.hostname)
+
+    -- join each channel
+    for i, channel in ipairs(settings.channels) do
+        net:join(channel)
+    end
+end
+
+-- apply conf_modules
+for name, settings in pairs(conf.modules) do
+    -- load the module
+    module = modules:load(name, settings.path)
+
+    -- apply confs
+    for key, value in pairs(settings.conf) do
+        module:conf(key, value)
+    end
+end
+
--- a/src/CMakeLists.txt	Wed Apr 01 00:57:34 2009 +0300
+++ b/src/CMakeLists.txt	Wed Apr 01 01:41:08 2009 +0300
@@ -12,7 +12,7 @@
 set (CORE_SOURCES error.c log.c)
 set (SOCK_SOURCES sock.c sock_tcp.c sock_gnutls.c sock_test.c line_proto.c)
 set (IRC_SOURCES irc_line.c irc_conn.c irc_net.c irc_chan.c chain.c irc_cmd.c irc_proto.c irc_client.c irc_user.c irc_queue.c)
-set (LUA_SOURCES nexus_lua.c lua_objs.c)
+set (LUA_SOURCES nexus_lua.c lua_objs.c lua_config.c)
 set (CONSOLE_SOURCES console.c lua_console.c)
 
 set (NEXUS_SOURCES nexus.c ${CORE_SOURCES} ${SOCK_SOURCES} ${IRC_SOURCES} ${LUA_SOURCES} ${CONSOLE_SOURCES} signals.c module.c config.c)
--- a/src/error.c	Wed Apr 01 00:57:34 2009 +0300
+++ b/src/error.c	Wed Apr 01 01:41:08 2009 +0300
@@ -77,10 +77,11 @@
     {   _ERR_INVALID,                       NULL,                                       0                   }
 
 }, _lua_error_desc[] = {
-    {   ERR_LUA_MEM,                        "lua: out of memory",                       ERR_EXTRA_NONE      },
-    {   ERR_LUA_SYNTAX,                     "lua: syntax error",                        ERR_EXTRA_NONE      },
-    {   ERR_LUA_RUN,                        "lua: runtime error",                       ERR_EXTRA_NONE      },
-    {   ERR_LUA_ERR,                        "lua: error handling error",                ERR_EXTRA_NONE      },
+    {   ERR_LUA_MEM,                        "lua: out of memory",                       ERR_EXTRA_STR       },
+    {   ERR_LUA_SYNTAX,                     "lua: syntax error",                        ERR_EXTRA_STR       },
+    {   ERR_LUA_RUN,                        "lua: runtime error",                       ERR_EXTRA_STR       },
+    {   ERR_LUA_ERR,                        "lua: error handling error",                ERR_EXTRA_STR       },
+    {   ERR_LUA_FILE,                       "lua: error loading file",                  ERR_EXTRA_STR       },
     {   _ERR_INVALID,                       NULL,                                       0                   }
 };
 
--- a/src/error.h	Wed Apr 01 00:57:34 2009 +0300
+++ b/src/error.h	Wed Apr 01 01:41:08 2009 +0300
@@ -99,6 +99,7 @@
     ERR_LUA_SYNTAX,
     ERR_LUA_RUN,
     ERR_LUA_ERR,
+    ERR_LUA_FILE,
 
     /** irc_chan errors */
     _ERR_IRC_CHAN   = 0x000d00,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lua_config.c	Wed Apr 01 01:41:08 2009 +0300
@@ -0,0 +1,16 @@
+#include "lua_config.h"
+
+#include <lua5.1/lauxlib.h>
+
+err_t lua_config_load (struct nexus_lua *lua, const char *path, struct error_info *err)
+{
+    // just use luaL_loadfile and translate the error code
+    if (nexus_lua_error(lua->st, luaL_loadfile(lua->st, path), err))
+        // XXX: pollute the stack
+        return ERROR_CODE(err);
+    
+    // execute it
+    // XXX; error handler with debug info
+    return nexus_lua_error(lua->st, lua_pcall(lua->st, 0, 0, 0), err);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lua_config.h	Wed Apr 01 01:41:08 2009 +0300
@@ -0,0 +1,19 @@
+#ifndef LUA_CONFIG_H
+#define LUA_CONFIG_H
+
+/**
+ * @file
+ *
+ * Read a lua configuration file into a nexus_lua state
+ */
+#include "error.h"
+#include "nexus_lua.h"
+
+/**
+ * Load a lua config file at the given path into the nexus's lua state.
+ *
+ * Path can also be given as NULL to load from stdin.
+ */
+err_t lua_config_load (struct nexus_lua *lua, const char *path, struct error_info *err);
+
+#endif /* LUA_CONFIG_H */
--- a/src/lua_console.c	Wed Apr 01 00:57:34 2009 +0300
+++ b/src/lua_console.c	Wed Apr 01 01:41:08 2009 +0300
@@ -30,31 +30,16 @@
     
 error:
     if (ret) {
-        const char *error = lua_tostring(L, -1);
-
-        switch (ret) {
-            case LUA_ERRSYNTAX:
-                log_error("syntax error: %s", error);
-                break;
-
-            case LUA_ERRRUN:
-                log_error("runtime error: %s", error);
-                break;
+        struct error_info err;
+        
+        // build the error_info
+        nexus_lua_error(L, ret, &err);
 
-            case LUA_ERRMEM:
-                log_error("memory allocation error: %s", error);
-                break;
-            
-            case LUA_ERRERR:
-                log_error("error handling error: %s", error);
-                break;
+        // log it
+        log_error("%s", error_msg(&err));
 
-            default:
-                log_error("unknown error: %s", error);
-                break;
-        };
-
-        lua_pop(L, 1);
+        // pop it
+        lua_pop(L, -1);
     }
 }
 
--- a/src/lua_objs.c	Wed Apr 01 00:57:34 2009 +0300
+++ b/src/lua_objs.c	Wed Apr 01 01:41:08 2009 +0300
@@ -589,15 +589,9 @@
     return 0;
 }
 
-err_t lua_objs_init (struct nexus_lua *lua)
+err_t lua_objs_init (struct nexus_lua *lua, struct error_info *err)
 {
     // call in protected mode
-    switch (lua_cpcall(lua->st, &_lua_objs_init, lua->nexus)) {
-        case 0:             return SUCCESS;
-        case LUA_ERRRUN:    return ERR_LUA_RUN;
-        case LUA_ERRMEM:    return ERR_LUA_MEM;
-        case LUA_ERRERR:    return ERR_LUA_ERR;
-        default:            return ERR_UNKNOWN;
-    }
+    return nexus_lua_error(lua->st, lua_cpcall(lua->st, &_lua_objs_init, lua->nexus), err);
 }
 
--- a/src/lua_objs.h	Wed Apr 01 00:57:34 2009 +0300
+++ b/src/lua_objs.h	Wed Apr 01 01:41:08 2009 +0300
@@ -11,6 +11,6 @@
 /**
  * Registers our lua runtime objects into the given lua state
  */
-err_t lua_objs_init (struct nexus_lua *lua);
+err_t lua_objs_init (struct nexus_lua *lua, struct error_info *err);
 
 #endif /* LUA_OBJS_H */
--- a/src/nexus.c	Wed Apr 01 00:57:34 2009 +0300
+++ b/src/nexus.c	Wed Apr 01 01:41:08 2009 +0300
@@ -1,5 +1,5 @@
 #include "nexus.h"
-#include "signals.h"
+#include "lua_config.h"
 #include "log.h"
 
 #include <stdlib.h>
@@ -16,15 +16,16 @@
     OPT_HELP            = 'h',
     OPT_DEFAULTS        = 'D',
     OPT_NETWORK         = 'n',
-    OPT_CHANNEL         = 'c',
     OPT_MODULE          = 'm',
-    OPT_CONFIG          = 'C',
+    OPT_CONF            = 'C',
     OPT_DEBUG           = 'd',
+    OPT_CONFIG          = 'c',
     
     /** Options without short names */
     _OPT_EXT_BEGIN      = 0x00ff,
     
     OPT_CONSOLE,
+    OPT_CHANNEL,
 };
 
 /**
@@ -36,13 +37,19 @@
     {"network",         1,  NULL,   OPT_NETWORK     },
     {"channel",         1,  NULL,   OPT_CHANNEL     },
     {"module",          1,  NULL,   OPT_MODULE      },
-    {"config",          1,  NULL,   OPT_CONFIG      },
+    {"conf",            1,  NULL,   OPT_CONF        },
     {"debug",           0,  NULL,   OPT_DEBUG       },
     {"console",         0,  NULL,   OPT_CONSOLE     },
+    {"config",          1,  NULL,   OPT_CONFIG      },
     {0,                 0,  0,      0               },
 };
 
 /**
+ * Short command-line option defintion
+ */
+const char *short_options = "hn:c:m:C:d";
+
+/**
  * Display --help output on stdout.
  *
  * If nexus is given, --config options for loaded modules are also listed
@@ -54,10 +61,11 @@
     printf(" --help / -h            display this message\n");
     printf(" --defaults / -D        set the IRC client default info using '<nickname>:<username>:<realname>'\n");
     printf(" --network / -n         add an IRC network using '<name>:<hostname>[:<port>[:ssl]]' format\n");
-    printf(" --channel / -c         add an IRC channel using '<network>:<channel>' format\n");
+    printf(" --channel              add an IRC channel using '<network>:<channel>' format\n");
     printf(" --module / -m          add a module using '<name>:<path>' format\n");
     printf(" --config / -C          add a module configuration option using '<mod_name>:<name>[:<value>]' format\n");
     printf(" --debug / -d           set logging level to DEBUG\n");
+    printf(" --config / -c          load a Lua config file from '<path>'\n");
     printf(" --console              use the interactive console\n");
     
     // dump loaded module configs
@@ -232,9 +240,9 @@
 }
 
 /**
- * Parse and apply a --config option, calling the module's conf func.
+ * Parse and apply a --conf option, calling the module's conf func.
  */
-static err_t apply_config (struct nexus *nexus, char *opt, struct error_info *err)
+static err_t apply_conf (struct nexus *nexus, char *opt, struct error_info *err)
 {
     struct module *module;
     const char *module_name, *conf_name;
@@ -294,6 +302,16 @@
 }
 
 /**
+ * Load the lua config file from \a path
+ */
+static err_t apply_config (struct nexus *nexus, char *path, struct error_info *err)
+{
+    log_info("loading lua config from %s", path);
+    
+    return lua_config_load(nexus->lua, path, err);
+}
+
+/**
  * Parse arguments and apply them to the given nexus
  */
 static err_t parse_args (struct nexus *nexus, int argc, char **argv, struct error_info *err)
@@ -301,7 +319,7 @@
     int opt, option_index;
     
     // parse options
-    while ((opt = getopt_long(argc, argv, "hn:c:m:C:", options, &option_index)) != -1) {
+    while ((opt = getopt_long(argc, argv, short_options, options, &option_index)) != -1) {
         switch (opt) {
             case OPT_HELP:
                 usage(nexus, argv[0]);
@@ -333,8 +351,8 @@
 
                 break;
 
-            case OPT_CONFIG:
-                if (apply_config(nexus, optarg, err))
+            case OPT_CONF:
+                if (apply_conf(nexus, optarg, err))
                     return ERROR_CODE(err);
 
                 break;
@@ -348,6 +366,12 @@
                     return ERROR_CODE(err);
                 
                 break;
+            
+            case OPT_CONFIG:
+                if (apply_config(nexus, optarg, err))
+                    return ERROR_CODE(err);
+
+                break;
 
             case '?':
                 usage(nexus, argv[0]);
--- a/src/nexus_lua.c	Wed Apr 01 00:57:34 2009 +0300
+++ b/src/nexus_lua.c	Wed Apr 01 01:41:08 2009 +0300
@@ -27,7 +27,7 @@
     luaL_openlibs(lua->st);
 
     // then our own things
-    if ((ERROR_CODE(err) = lua_objs_init(lua)))
+    if (lua_objs_init(lua, err))
         goto error;
 
     // ok
@@ -48,3 +48,18 @@
 
     free(lua);
 }
+
+err_t nexus_lua_error (lua_State *L, int ret, struct error_info *err)
+{
+    const char *error = lua_tostring(L, -1);
+
+    switch (ret) {
+        case 0:                 RETURN_SET_ERROR(err, SUCCESS);
+        case LUA_ERRSYNTAX:     RETURN_SET_ERROR_STR(err, ERR_LUA_SYNTAX, error);
+        case LUA_ERRRUN:        RETURN_SET_ERROR_STR(err, ERR_LUA_RUN, error);
+        case LUA_ERRMEM:        RETURN_SET_ERROR_STR(err, ERR_LUA_MEM, error);
+        case LUA_ERRERR:        RETURN_SET_ERROR_STR(err, ERR_LUA_ERR, error);
+        case LUA_ERRFILE:       RETURN_SET_ERROR_STR(err, ERR_LUA_FILE, error);
+        default:                RETURN_SET_ERROR_EXTRA(err, ERR_UNKNOWN, ret);
+    };
+}
--- a/src/nexus_lua.h	Wed Apr 01 00:57:34 2009 +0300
+++ b/src/nexus_lua.h	Wed Apr 01 01:41:08 2009 +0300
@@ -31,4 +31,13 @@
  */
 void nexus_lua_destroy (struct nexus_lua *lua);
 
+/**
+ * Handle a Lua error by converting the given error code into a ERR_LUA_* code, inspecting the error object at
+ * the top of the stack.
+ *
+ * Please note that the resulting error_info points into strings inside the lua stack - once you pop the error, the
+ * error_info might not be valid anymore.
+ */
+err_t nexus_lua_error (lua_State *L, int ret, struct error_info *err);
+
 #endif /* NEXUS_LUA_H */