src/lua_objs.c
branchnew-lib-errors
changeset 219 cefec18b8268
parent 218 5229a5d098b2
equal deleted inserted replaced
218:5229a5d098b2 219:cefec18b8268
     1 #include "lua_objs.h"
       
     2 #include "lua_irc.h"
       
     3 #include "lua_func.h"
       
     4 #include "lua_thread.h"
       
     5 #include "log.h"
       
     6 
       
     7 #include <stdlib.h>
       
     8 #include <string.h>
       
     9 
       
    10 /**
       
    11  * Wrapper for module
       
    12  */
       
    13 struct lua_module {
       
    14     struct module *module;
       
    15 };
       
    16 
       
    17 static struct lua_type lua_module_type = LUA_TYPE("spbot.module");
       
    18 
       
    19 /**
       
    20  * Create a lua_module userdata from the given module and push it onto the stack, returning 1.
       
    21  *
       
    22  * The given module should be a reference of its own right.
       
    23  */
       
    24 static int lua_module_create (lua_State *L, struct module *module)
       
    25 {
       
    26     // create the new obj
       
    27     struct lua_module *lua_module = lua_type_create(L, &lua_module_type, sizeof(*lua_module));
       
    28 
       
    29     // initialize
       
    30     lua_module->module = module;
       
    31 
       
    32     // ok
       
    33     return 1;
       
    34 }
       
    35 
       
    36 /**
       
    37  * module_put() our module reference
       
    38  */
       
    39 static int lua_module__gc (lua_State *L)
       
    40 {
       
    41     struct lua_module *lua_module = lua_type_get(L, &lua_module_type, 1);
       
    42     
       
    43     // put it
       
    44     module_put(lua_module->module);
       
    45 
       
    46     return 0;
       
    47 }
       
    48 
       
    49 static int lua_module_conf (lua_State *L)
       
    50 {
       
    51     struct lua_module *lua_module = lua_type_get(L, &lua_module_type, 1);
       
    52     const struct config_option *option;
       
    53     struct error_info err;
       
    54     bool is_err = true;
       
    55 
       
    56     // the list of given config values, and temporary storage for string values
       
    57     struct config_value values[CONFIG_VALUES_MAX], *value = values;
       
    58     char *value_bufs[CONFIG_VALUES_MAX], **value_buf = value_bufs;
       
    59 
       
    60     // number of arguments given
       
    61     int nargs = lua_gettop(L), argidx = 2;
       
    62 
       
    63     // init to zero
       
    64     memset(values, 0, sizeof(values));
       
    65     memset(value_bufs, 0, sizeof(value_bufs));
       
    66 
       
    67     // XXX: come up with some better way...
       
    68     struct nexus *nexus = lua_module->module->modules->nexus;
       
    69 
       
    70     // the config name
       
    71     const char *conf_name = luaL_checkstring(L, argidx++);
       
    72 
       
    73     // look it up
       
    74     if ((option = module_conf_lookup(lua_module->module, conf_name, &err)) == NULL)
       
    75         return luaL_error(L, "module_conf_lookup: %s/%s: %s", module_name(lua_module->module), conf_name, error_msg(&err));
       
    76 
       
    77     // maximum number of arguments accepted
       
    78     int maxargs = config_params_count(option);
       
    79 
       
    80     // too many arguments?
       
    81     if (nargs - argidx > maxargs)
       
    82         return luaL_error(L, "lua_module_conf: too many arguments (>%d) given (%d)", maxargs, nargs - argidx);
       
    83     
       
    84     // the current param
       
    85     const struct config_param *param = option->params;
       
    86 
       
    87     // apply each given argument to the correct param, storing it in value
       
    88     for (; argidx <= nargs; argidx++, value++, param++) {
       
    89         // the given config value
       
    90         switch (lua_type(L, argidx)) {
       
    91             case LUA_TNONE:
       
    92             case LUA_TNIL:
       
    93                 // no value
       
    94                 value->type = CONFIG_NULL;
       
    95 
       
    96                 break;
       
    97 
       
    98             case LUA_TSTRING: {
       
    99                 // string arg
       
   100                 const char *arg_str = lua_tostring(L, argidx);
       
   101 
       
   102                 // copy it as a mutable string buffer
       
   103                 if ((*value_buf = strdup(arg_str)) == NULL) {
       
   104                     lua_pushfstring(L, "strdup");
       
   105                     goto error;
       
   106                 }
       
   107 
       
   108                 // parse it as a raw value
       
   109                 if (config_parse_param(param, nexus, value, *value_buf, &err)) {
       
   110                     lua_pushfstring(L, "config_parse: %s/%s: %s", option->name, *value_buf, error_msg(&err));
       
   111                     goto error;
       
   112                 }
       
   113 
       
   114                 // seek to next value_buf
       
   115                 value_buf++;
       
   116 
       
   117             } break;
       
   118     
       
   119             case LUA_TUSERDATA:
       
   120                 // some kind of userdata, use its metatable to figure out what type it is
       
   121                 if (!lua_getmetatable(L, argidx)) {
       
   122                     lua_pushfstring(L, "config value is userdata without metatable");
       
   123                     goto error;
       
   124                 }
       
   125 
       
   126                 // get the target metatable
       
   127                 lua_getfield(L, LUA_REGISTRYINDEX, "evirc.chan");
       
   128 
       
   129                 // is it a chan?
       
   130                 if (!lua_rawequal(L, -1, -2)) {
       
   131                     lua_pushfstring(L, "config value is userdata of unknown type");
       
   132                     goto error;
       
   133                 }
       
   134 
       
   135                 // pop the metatables
       
   136                 lua_pop(L, 2);
       
   137 
       
   138                 // get the irc_chan
       
   139                 struct lua_chan *lua_chan = lua_touserdata(L, argidx);
       
   140 
       
   141                 // build the value
       
   142                 value->type = CONFIG_IRC_CHAN;
       
   143                 value->irc_chan = lua_chan->chan;
       
   144                 
       
   145                 break;
       
   146             
       
   147             default:
       
   148                 lua_pushfstring(L, "config value is of unknown lua type '%s'", lua_typename(L, argidx));
       
   149                 goto error;
       
   150 
       
   151         }
       
   152     }
       
   153 
       
   154     // apply it
       
   155     if (module_conf(lua_module->module, option, values, &err)) {
       
   156         lua_pushfstring(L, "module_conf: %s/%s: %s", module_name(lua_module->module), option->name, error_msg(&err));
       
   157         goto error;
       
   158     }
       
   159     
       
   160     // ok
       
   161     is_err = false;
       
   162 
       
   163 error:
       
   164     // release any allocated strings
       
   165     for (value_buf = value_bufs; value_buf <= value_bufs + CONFIG_VALUES_MAX && *value_buf; value_buf++)
       
   166         free(*value_buf);
       
   167     
       
   168     // either error or successful return
       
   169     if (is_err)
       
   170         return lua_error(L);
       
   171     else
       
   172         return 0;
       
   173 }
       
   174 
       
   175 static int lua_module_unload (lua_State *L)
       
   176 {
       
   177     struct lua_module *lua_module = lua_type_get(L, &lua_module_type, 1);
       
   178     struct error_info err;
       
   179 
       
   180     // just unload it
       
   181     if ((ERROR_CODE(&err) = module_unload(lua_module->module)))
       
   182         return luaL_error(L, "module_unload: %s: %s", module_name(lua_module->module), error_msg(&err));
       
   183 
       
   184     // ok
       
   185     return 0;
       
   186 }
       
   187 
       
   188 static struct lua_method lua_module_methods[] = LUA_METHODS(
       
   189         LUA_METHOD("__gc",      lua_module__gc,     NULL    ),
       
   190         LUA_METHOD("conf",      lua_module_conf,    NULL    ),
       
   191         LUA_METHOD("unload",    lua_module_unload,  NULL    )
       
   192 );
       
   193 
       
   194 /**
       
   195  * Wrapper for modules
       
   196  */
       
   197 struct lua_modules {
       
   198     struct modules *modules;
       
   199     
       
   200     // strdup'd path for module_path
       
   201     // XXX: remove when gc'd
       
   202     char *path;
       
   203 };
       
   204 
       
   205 static struct lua_type lua_modules_type = LUA_TYPE("spbot.modules");
       
   206 
       
   207 static int lua_modules__gc (lua_State *L)
       
   208 {
       
   209     struct lua_modules *lua_modules = lua_type_get(L, &lua_modules_type, 1);
       
   210     
       
   211     // remove the modules path if it was set by us
       
   212     if (lua_modules->path && modules_path(lua_modules->modules, NULL) == lua_modules->path)
       
   213         modules_path(lua_modules->modules, "");
       
   214 
       
   215     // release any strdup'd path
       
   216     free(lua_modules->path);
       
   217 
       
   218     // ok
       
   219     return 0;
       
   220 }
       
   221 
       
   222 static int lua_modules_path (lua_State *L)
       
   223 {
       
   224     struct lua_modules *lua_modules = lua_type_get(L, &lua_modules_type, 1);
       
   225     char *path = NULL;
       
   226     const char *old_path;
       
   227     
       
   228     if (!lua_isnoneornil(L, 2)) {
       
   229         // the new path
       
   230         if ((path = strdup(luaL_checkstring(L, 2))) == NULL)
       
   231             return luaL_error(L, "strdup");
       
   232     }
       
   233 
       
   234     // set or get
       
   235     old_path = modules_path(lua_modules->modules, path);
       
   236 
       
   237     // return the old path
       
   238     if (old_path)
       
   239         lua_pushstring(L, old_path);
       
   240     else
       
   241         lua_pushnil(L);
       
   242 
       
   243     if (path) {
       
   244         // replace the old path
       
   245         free(lua_modules->path); 
       
   246         lua_modules->path = path;
       
   247     }
       
   248 
       
   249     // ok
       
   250     return 1;
       
   251 }
       
   252 
       
   253 static int lua_modules_load (lua_State *L)
       
   254 {
       
   255     struct lua_modules *lua_modules = lua_type_get(L, &lua_modules_type, 1);
       
   256     struct module *module;
       
   257     struct module_info info;
       
   258     struct error_info err;
       
   259 
       
   260     // the module name/path
       
   261     info.name = luaL_checkstring(L, 2);
       
   262     info.path = lua_isnoneornil(L, 3) ? NULL : luaL_checkstring(L, 3);
       
   263 
       
   264     // load and get a new reference
       
   265     if (module_load(lua_modules->modules, &module, &info, &err))
       
   266         return luaL_error(L, "module_load: %s/%s: %s", info.name, info.path, error_msg(&err));
       
   267 
       
   268     // wrap
       
   269     return lua_module_create(L, module);
       
   270 }
       
   271 
       
   272 static int lua_modules_module (lua_State *L)
       
   273 {
       
   274     struct lua_modules *lua_modules = lua_type_get(L, &lua_modules_type, 1);
       
   275     struct module *module;
       
   276     
       
   277     // the module name
       
   278     const char *name = luaL_checkstring(L, 2);
       
   279 
       
   280     // look it up, as a new reference
       
   281     if ((module = modules_get(lua_modules->modules, name)) == NULL)
       
   282         return luaL_error(L, "module_get: %s: no such module", name);
       
   283 
       
   284     // wrap
       
   285     return lua_module_create(L, module);
       
   286 }
       
   287 
       
   288 static struct lua_method lua_modules_methods[] = LUA_METHODS(
       
   289         LUA_METHOD("__gc",      lua_modules__gc,    NULL    ),
       
   290         LUA_METHOD("path",      lua_modules_path,   NULL    ),
       
   291         LUA_METHOD("load",      lua_modules_load,   NULL    ),
       
   292         LUA_METHOD("module",    lua_modules_module, NULL    )
       
   293     );
       
   294 
       
   295 
       
   296 
       
   297 /**
       
   298  * Initialize the spbot.modules type for lua_modules, and registers an instance bound to the given modules list at
       
   299  * 'modules'.
       
   300  */
       
   301 static void lua_modules_init (lua_State *L, struct modules *modules)
       
   302 {
       
   303     // allocate the global "modules" object
       
   304     struct lua_modules *lua_modules = lua_type_register_global(L, &lua_modules_type, lua_modules_methods, "modules", sizeof(*lua_modules));
       
   305     
       
   306     // initialize it
       
   307     lua_modules->modules = modules;
       
   308 }
       
   309 
       
   310 /**
       
   311  * Wrapper for nexus
       
   312  */
       
   313 struct lua_nexus {
       
   314     struct nexus *nexus;
       
   315 };
       
   316 
       
   317 static struct lua_type lua_nexus_type = LUA_TYPE("spbot.nexus");
       
   318 
       
   319 static int lua_nexus_shutdown (lua_State *L)
       
   320 {
       
   321     struct lua_nexus *lua_nexus = lua_type_get(L, &lua_nexus_type, 1);
       
   322 
       
   323     // just shut it down
       
   324     nexus_shutdown(lua_nexus->nexus);
       
   325 
       
   326     return 0;
       
   327 }
       
   328 
       
   329 static int lua_nexus_load_config (lua_State *L)
       
   330 {
       
   331     struct lua_nexus *lua_nexus = lua_type_get(L, &lua_nexus_type, 1);
       
   332     struct error_info err;
       
   333 
       
   334     const char *path = luaL_checkstring(L, 2);
       
   335     
       
   336     // just load it
       
   337     if (nexus_load_config(lua_nexus->nexus, path, &err))
       
   338         return luaL_error(L, "nexus_load_config(%s): %s", path, error_msg(&err));
       
   339 
       
   340     return 0;
       
   341 }
       
   342 
       
   343 static struct lua_func lua_nexus_sleep_func = LUA_FUNC(&lua_nexus_type, "sleep",
       
   344         "Schedules itself to resume after the given delay (in seconds) and yields",
       
   345 
       
   346         LUA_FUNC_ARG_INT("tv_sec",  LUA_ARG_REQUIRED)
       
   347     );
       
   348 
       
   349 static void lua_nexus_sleep_wakeup (evutil_socket_t fd, short what, void *arg)
       
   350 {
       
   351     lua_State *L = arg;
       
   352 
       
   353     (void) fd;
       
   354     (void) what;
       
   355 
       
   356     // resume the thread that called lua_nexus_sleep
       
   357     lua_thread_resume_state(L);
       
   358 }
       
   359 
       
   360 static int lua_nexus_sleep (lua_State *L)
       
   361 {
       
   362     struct lua_nexus *lua_nexus;
       
   363     long tv_sec;
       
   364 
       
   365     // parse args
       
   366     lua_args_parse(L, &lua_nexus_sleep_func, (void *) &lua_nexus, &tv_sec);
       
   367 
       
   368     // build tv
       
   369     struct timeval tv = { tv_sec, 0 };
       
   370     
       
   371     // schedule wakeup
       
   372     // use a pure-timeout event
       
   373     if (event_base_once(lua_nexus->nexus->ev_base, -1, EV_TIMEOUT, lua_nexus_sleep_wakeup, L, &tv))
       
   374         return luaL_error(L, "event_base_once");
       
   375 
       
   376     // yield
       
   377     return lua_thread_yield_state(L);
       
   378 }
       
   379 
       
   380 static struct lua_method lua_nexus_methods[] = LUA_METHODS(
       
   381         LUA_METHOD("shutdown",      lua_nexus_shutdown,     NULL                    ),
       
   382         LUA_METHOD("load_config",   lua_nexus_load_config,  NULL                    ),
       
   383         LUA_METHOD("sleep",         lua_nexus_sleep,        &lua_nexus_sleep_func   )
       
   384     );
       
   385 
       
   386 /**
       
   387  * Initialize the spbot.nexus type for lua_nexus, and registers an instance bound to the given nexus list at
       
   388  * 'nexus'.
       
   389  */
       
   390 static void lua_nexus_init (lua_State *L, struct nexus *nexus)
       
   391 {
       
   392     // allocate the global "nexus" object
       
   393     struct lua_nexus *lua_nexus = lua_type_register_global(L, &lua_nexus_type, lua_nexus_methods, "nexus", sizeof(*lua_nexus));
       
   394     
       
   395     // initialize it
       
   396     lua_nexus->nexus = nexus;
       
   397 }
       
   398 
       
   399 
       
   400 /**
       
   401  * Global functions
       
   402  */
       
   403 static int lua_log_level (lua_State *L)
       
   404 {
       
   405     // log level as a string
       
   406     enum log_level new_level = luaL_checkoption(L, 1, NULL, log_level_names);
       
   407 
       
   408     // set it
       
   409     set_log_level(new_level);
       
   410 
       
   411     // ok
       
   412     return 0;
       
   413 }
       
   414 
       
   415 static int lua_log (lua_State *L)
       
   416 {
       
   417     // log level as a string
       
   418     enum log_level level = luaL_checkoption(L, 1, NULL, log_level_names);
       
   419     
       
   420     // log message
       
   421     const char *msg = luaL_checkstring(L, 2);
       
   422 
       
   423     // log it
       
   424     _log_msg(level, "lua", "%s", msg);
       
   425 
       
   426     // ok
       
   427     return 0;
       
   428 }
       
   429 
       
   430 static const struct luaL_Reg lua_global_functions[] = {
       
   431     {   "log_level",    lua_log_level               },
       
   432     {   "log",          lua_log                     },
       
   433     {   NULL,           NULL                        }
       
   434 };
       
   435 
       
   436 static void lua_global_init (lua_State *L)
       
   437 {
       
   438     const struct luaL_Reg *reg;
       
   439 
       
   440     for (reg = lua_global_functions; reg->name && reg->func; reg++) {
       
   441         // put the function on the stack
       
   442         lua_pushcfunction(L, reg->func);
       
   443 
       
   444         // set the global
       
   445         lua_setglobal(L, reg->name);
       
   446     }
       
   447 }
       
   448 
       
   449 void lua_objs_init (struct nexus_lua *lua)
       
   450 {
       
   451     // register types
       
   452     lua_type_register(lua->st, &lua_module_type, lua_module_methods);
       
   453     
       
   454     // globals
       
   455     lua_nexus_init(lua->st, lua->nexus);
       
   456     lua_modules_init(lua->st, lua->nexus->modules);
       
   457     
       
   458     // global functions
       
   459     lua_global_init(lua->st);
       
   460 }
       
   461 
       
   462