--- a/src/lua_objs.c Wed Apr 01 00:27:03 2009 +0300
+++ b/src/lua_objs.c Wed Apr 01 00:27:39 2009 +0300
@@ -39,6 +39,27 @@
}
/**
+ * Convenience function to create a new metatable for a type, a userdata for that type, and register it as a global
+ */
+static void* lua_obj_create_global_type (lua_State *L, const char *type_name, const struct luaL_Reg methods[], const char *global_name, size_t size)
+{
+ // allocate the global object
+ void *obj = lua_newuserdata(L, size);
+
+ // create the type metatable
+ lua_obj_create_type(L, type_name, methods);
+
+ // set the userdata's metatable
+ lua_setmetatable(L, -2);
+
+ // store it as a global
+ lua_setglobal(L, global_name);
+
+ // ok
+ return obj;
+}
+
+/**
* Convenience function to get a userdata with the given type metatable name as the first argument for a function
*/
static void* lua_obj_get_obj (lua_State *L, const char *func, const char *name)
@@ -48,6 +69,9 @@
// validate the userdata arg
if ((ud = luaL_checkudata(L, 1, name)) == NULL) {
luaL_error(L, "bad type argument to %s: `%s` expected", func, name);
+
+ // XXX: needs a __noreturn__ attribute
+ return NULL;
} else {
// ok
@@ -311,25 +335,184 @@
};
/**
- * Initializes a lua_irc_client wrapper for the given client in the give lua state. This registers a set of globals for
- * 'client' and 'networks'.
+ * Initialize the evirc.client type for lua_client, and registers an instance bound to the given irc_client at
+ * 'client'.
*/
static void lua_client_init (lua_State *L, struct irc_client *client)
{
// allocate the global "client" object
- struct lua_client *lua_client = lua_newuserdata(L, sizeof(*lua_client));
+ struct lua_client *lua_client = lua_obj_create_global_type(L, "evirc.client", lua_client_methods, "client", sizeof(*lua_client));
- // create the type metatable
- lua_obj_create_type(L, "evirc.client", lua_client_methods);
-
- // set the client userdata's metatable
- lua_setmetatable(L, -2);
-
// initialize it
lua_client->client = client;
+}
- // store it as a global
- lua_setglobal(L, "client");
+/**
+ * Wrapper for module
+ */
+struct lua_module {
+ struct module *module;
+};
+
+/**
+ * Create a lua_module userdata from the given module and push it onto the stack, returning 1.
+ */
+static int lua_module_create (lua_State *L, struct module *module)
+{
+ // create the new obj
+ struct lua_module *lua_module = lua_obj_create_obj(L, "spbot.module", sizeof(*lua_module));
+
+ // initialize
+ lua_module->module = module;
+
+ // ok
+ return 1;
+}
+
+static int lua_module_conf (lua_State *L)
+{
+ struct lua_module *lua_module = lua_obj_get_obj(L, __func__, "spbot.module");
+ const struct config_option *option;
+ struct config_value value;
+ struct error_info err;
+
+ // XXX: come up with some better way...
+ struct nexus *nexus = lua_module->module->modules->nexus;
+
+ // the config name
+ const char *conf_name = luaL_checkstring(L, 2);
+
+ // the config value
+ // XXX: support lua_chan
+ const char *conf_value = luaL_checkstring(L, 3);
+
+ // mutable version of the conf_value
+ char conf_value_buf[strlen(conf_value) + 1];
+ strcpy(conf_value_buf, conf_value);
+
+ // look it up
+ if ((option = module_conf_lookup(lua_module->module, conf_name, &err)) == NULL)
+ return luaL_error(L, "module_conf_lookup: %s/%s: %s", module_name(lua_module->module), conf_name, error_msg(&err));
+
+ // parse it
+ if (config_parse(option, nexus, &value, conf_value_buf, &err))
+ return luaL_error(L, "config_parse: %s/%s: %s", option->name, conf_value_buf, error_msg(&err));
+
+ // apply it
+ if (module_conf(lua_module->module, option, &value, &err))
+ return luaL_error(L, "module_conf: %s/%s/%s: %s", module_name(lua_module->module), option->name, conf_value_buf, error_msg(&err));
+
+ // ok
+ return 0;
+}
+
+static const struct luaL_Reg lua_module_methods[] = {
+ { "conf", &lua_module_conf },
+ { NULL, NULL }
+};
+
+/**
+ * Initialize the lua_module object type
+ */
+static void lua_module_init (lua_State *L)
+{
+ lua_obj_create_type(L, "spbot.module", lua_module_methods);
+}
+
+/**
+ * Wrapper for modules
+ */
+struct lua_modules {
+ struct modules *modules;
+};
+
+static int lua_modules_load (lua_State *L)
+{
+ struct lua_modules *lua_modules = lua_obj_get_obj(L, __func__, "spbot.modules");
+ struct module *module;
+ struct module_info info;
+ struct error_info err;
+
+ // the module name/path
+ info.name = luaL_checkstring(L, 2);
+ info.path = luaL_checkstring(L, 3);
+
+ // load
+ if (module_load(lua_modules->modules, &module, &info, &err))
+ return luaL_error(L, "module_load: %s/%s: %s", info.name, info.path, error_msg(&err));
+
+ // wrap
+ return lua_module_create(L, module);
+}
+
+static int lua_modules_module (lua_State *L)
+{
+ struct lua_modules *lua_modules = lua_obj_get_obj(L, __func__, "spbot.modules");
+ struct module *module;
+
+ // the module name
+ const char *name = luaL_checkstring(L, 2);
+
+ // look it up
+ if ((module = module_get(lua_modules->modules, name)) == NULL)
+ return luaL_error(L, "module_get: %s: no such module", name);
+
+ // wrap
+ return lua_module_create(L, module);
+}
+
+static const struct luaL_Reg lua_modules_methods[] = {
+ { "load", &lua_modules_load },
+ { "module", &lua_modules_module },
+ { NULL, NULL }
+};
+
+/**
+ * Initialize the spbot.modules type for lua_modules, and registers an instance bound to the given modules list at
+ * 'modules'.
+ */
+static void lua_modules_init (lua_State *L, struct modules *modules)
+{
+ // allocate the global "modules" object
+ struct lua_modules *lua_modules = lua_obj_create_global_type(L, "spbot.modules", lua_modules_methods, "modules", sizeof(*lua_modules));
+
+ // initialize it
+ lua_modules->modules = modules;
+}
+
+/**
+ * Wrapper for nexus
+ */
+struct lua_nexus {
+ struct nexus *nexus;
+};
+
+static int lua_nexus_shutdown (lua_State *L)
+{
+ struct lua_nexus *lua_nexus = lua_obj_get_obj(L, __func__, "spbot.nexus");
+
+ // just shut it down
+ nexus_shutdown(lua_nexus->nexus);
+
+ return 0;
+}
+
+static const struct luaL_Reg lua_nexus_methods[] = {
+ { "shutdown", &lua_nexus_shutdown },
+ { NULL, NULL }
+};
+
+/**
+ * Initialize the spbot.nexus type for lua_nexus, and registers an instance bound to the given nexus list at
+ * 'nexus'.
+ */
+static void lua_nexus_init (lua_State *L, struct nexus *nexus)
+{
+ // allocate the global "nexus" object
+ struct lua_nexus *lua_nexus = lua_obj_create_global_type(L, "spbot.nexus", lua_nexus_methods, "nexus", sizeof(*lua_nexus));
+
+ // initialize it
+ lua_nexus->nexus = nexus;
}
/**
@@ -344,6 +527,9 @@
luaL_error(L, "lua_touserdata: NULL");
// init the various bits
+ lua_nexus_init(L, nexus);
+ lua_modules_init(L, nexus->modules);
+ lua_module_init(L);
lua_client_init(L, nexus->client);
lua_net_init(L);
lua_chan_init(L);