--- a/src/CMakeLists.txt Sun Apr 19 04:52:12 2009 +0300
+++ b/src/CMakeLists.txt Sun Apr 19 06:20:59 2009 +0300
@@ -13,7 +13,7 @@
set (CORE_SOURCES error.c log.c str.c)
set (SOCK_SOURCES sock.c sock_fd.c sock_tcp.c sock_gnutls.c sock_test.c sock_fifo.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 lua_config.c lua_irc.c)
+set (LUA_SOURCES nexus_lua.c lua_objs.c lua_config.c lua_irc.c lua_func.c lua_type.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.h Sun Apr 19 04:52:12 2009 +0300
+++ b/src/error.h Sun Apr 19 06:20:59 2009 +0300
@@ -227,6 +227,7 @@
/**
* Macro used to mark code segments that should never be executed (e.g. switch-default), kind of like assert
*/
-#define NOT_REACHED() assert(false)
+#include <stdlib.h>
+#define NOT_REACHED() abort()
#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lua_func.c Sun Apr 19 06:20:59 2009 +0300
@@ -0,0 +1,169 @@
+#include "lua_func.h"
+#include "error.h"
+
+#include <lua5.1/lauxlib.h>
+
+/**
+ * Pushes onto the stack the value at t[i]
+ */
+static void lua_getindex (lua_State *L, int t, int i)
+{
+ lua_pushinteger(L, i);
+ lua_gettable(L, t);
+}
+
+/**
+ * Pushes onto the stack either:
+ * * the value at t[name]
+ * * the value at t[index]
+ *
+ * Returns the new index, or 0, if neither could be found
+ */
+static int lua_arg_lookup (lua_State *L, int t, const char *name, int index)
+{
+ // try name
+ lua_getfield(L, t, name);
+
+ if (!lua_isnil(L, -1))
+ return lua_gettop(L);
+ else
+ lua_pop(L, 1);
+
+ // try index
+ lua_getindex(L, t, index);
+
+ if (!lua_isnil(L, -1))
+ return lua_gettop(L);
+
+ else
+ lua_pop(L, 1);
+
+ // not found
+ return 0;
+}
+
+static const char *_lua_arg_string (lua_State *L, int index, const char *name, const char *def)
+{
+ const char *value;
+
+ // use default?
+ if (lua_isnoneornil(L, index) && def != (const char *) LUA_ARG_REQUIRED)
+ return def;
+
+ // value given?
+ if ((value = lua_tostring(L, index)))
+ return value;
+
+ // error
+ luaL_error(L, "missing value for required string argument <%d:%s>", index, name); return NULL;
+}
+
+static bool _lua_arg_bool (lua_State *L, int index, const char *name, int def)
+{
+ (void) name;
+
+ // use default?
+ if (lua_isnoneornil(L, index) && def != LUA_ARG_REQUIRED)
+ return def;
+
+ // value given
+ return lua_toboolean(L, index);
+}
+
+/**
+ * Look up the arg index to use for the given index/name.
+ *
+ * If no value is found for the corresponding index, returns zero.
+ */
+static int lua_arg_index (lua_State *L, int nargs, int index, const char *name)
+{
+ // lookup from table?
+ if (name && lua_istable(L, 2)) {
+ // push the value from the field onto the stack
+ lua_getfield(L, 2, name);
+
+ // no named field?
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 1);
+
+ lua_getindex(L, 2, index - 1);
+ }
+
+ // no index field?
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 1);
+
+ return 0;
+ }
+
+ // found either a named or indexed arg
+ return lua_gettop(L);
+
+ } else if (index <= nargs) {
+ // use the same index
+ return index;
+
+ } else {
+ // no index
+ return 0;
+ }
+}
+
+const char *lua_arg_string (lua_State *L, int nargs, int index, const char *name, const char *def)
+{
+ return _lua_arg_string(L, lua_arg_index(L, nargs, index, name), name, def);
+}
+
+bool lua_arg_bool (lua_State *L, int nargs, int index, const char *name, int def)
+{
+ return _lua_arg_bool(L, lua_arg_index(L, nargs, index, name), name, def);
+}
+
+void lua_args_parse (lua_State *L, const struct lua_func *func, void **obj_ptr, ...)
+{
+ int argidx = 1, argtbl = 0, idx;
+ const struct lua_func_arg *arg;
+ va_list vargs;
+
+ // first, the obj argument
+ if (func->type) {
+ *obj_ptr = lua_obj_get_obj(L, func->name, func->type);
+ argidx++;
+ }
+
+ // were we given a table of arguments?
+ if (lua_istable(L, argidx))
+ argtbl = argidx++;
+
+ // parse the args
+ va_start(vargs, obj_ptr);
+
+ for (arg = func->args, idx = 1; arg->name && arg->type; arg++, idx++) {
+ int index;
+
+ // map index
+ if (!argtbl)
+ // direct
+ index = argidx++;
+
+ else
+ // lookup from table
+ index = lua_arg_lookup(L, argtbl, arg->name, idx);
+
+ // apply
+ switch (arg->type) {
+ case LUA_ARG_STRING:
+ *va_arg(vargs, const char **) = _lua_arg_string(L, index, arg->name, arg->def.string);
+ break;
+
+ case LUA_ARG_BOOL:
+ *va_arg(vargs, bool *) = _lua_arg_bool(L, index, arg->name, arg->def.boolean);
+ break;
+
+ default:
+ NOT_REACHED();
+ };
+ }
+
+ va_end(vargs);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lua_func.h Sun Apr 19 06:20:59 2009 +0300
@@ -0,0 +1,88 @@
+#ifndef LUA_FUNC_H
+#define LUA_FUNC_H
+
+/**
+ * @file
+ *
+ * Convenience functions for working with lua C functions
+ */
+#include "lua_type.h"
+#include <stdbool.h>
+
+/**
+ * Lua function argument types
+ */
+enum lua_arg_type {
+ LUA_ARG_INVALID,
+
+ LUA_ARG_STRING,
+ LUA_ARG_BOOL,
+};
+
+/**
+ * Function argument def
+ */
+struct lua_func_arg {
+ /** Argument name */
+ const char *name;
+
+ /** Expected type */
+ enum lua_arg_type type;
+
+ /** Default value */
+ union {
+ const char *string;
+ int boolean;
+ } def;
+};
+
+/**
+ * Function def
+ */
+struct lua_func {
+ /** Type name, or NULL */
+ const char *type;
+
+ /** Function name */
+ const char *name;
+
+ /** Help string */
+ const char *help;
+
+ /** Arguments */
+ const struct lua_func_arg args[];
+};
+
+/**
+ * Used as the "invalid" default value
+ */
+#define LUA_ARG_REQUIRED (-1)
+#define LUA_ARG_STRING_REQUIRED ((const char *) (-1))
+
+/**
+ * Define a function argument
+ */
+#define LUA_FUNC_ARG_STRING(name, def) { (name), LUA_ARG_STRING, { .string = (def) } }
+#define LUA_FUNC_ARG_BOOL(name, def) { (name), LUA_ARG_BOOL, { .boolean = (def) } }
+
+/**
+ * Define a function
+ */
+#define LUA_FUNC(type, name, help, ...) { (type), (name), (help), { __VA_ARGS__, { NULL, 0, { 0 } } } }
+
+/**
+ * Parse and return a string argument
+ */
+const char *lua_arg_string (lua_State *L, int nargs, int index, const char *name, const char *def);
+
+/**
+ * Parse and return a boolean argument
+ */
+bool lua_arg_bool (lua_State *L, int nargs, int index, const char *name, int def);
+
+/**
+ * Parse function arguments as defined
+ */
+void lua_args_parse (lua_State *L, const struct lua_func *func, void **obj_ptr, ...);
+
+#endif
--- a/src/lua_irc.c Sun Apr 19 04:52:12 2009 +0300
+++ b/src/lua_irc.c Sun Apr 19 06:20:59 2009 +0300
@@ -1,4 +1,5 @@
#include "lua_irc.h"
+#include "lua_func.h"
#include <stdlib.h>
#include <string.h>
@@ -147,31 +148,61 @@
lua_obj_create_type(L, "evirc.net", lua_net_methods);
}
+static struct lua_func lua_client_set_defaults_func = LUA_FUNC("evirc.client", "set_defaults",
+ "set the default settings to use for evirc.client.connect",
+
+ LUA_FUNC_ARG_STRING("nickname", LUA_ARG_STRING_REQUIRED ),
+ LUA_FUNC_ARG_STRING("username", LUA_ARG_STRING_REQUIRED ),
+ LUA_FUNC_ARG_STRING("realname", LUA_ARG_STRING_REQUIRED ),
+ LUA_FUNC_ARG_STRING("service", IRC_PORT ),
+ LUA_FUNC_ARG_STRING("service_ssl", IRC_SSL_PORT )
+);
+
static int lua_client_set_defaults (lua_State *L)
{
- int nargs = lua_gettop(L);
- struct lua_client *lua_client = lua_obj_get_obj(L, __func__, "evirc.client");
+ struct lua_client *lua_client;
+ const char *nickname, *username, *realname, *service, *service_ssl;
- // required args
- lua_client->defaults.register_info.nickname = lua_arg_string(L, nargs, 2, "nickname", LUA_ARG_STRING_REQUIRED);
- lua_client->defaults.register_info.username = lua_arg_string(L, nargs, 3, "username", LUA_ARG_STRING_REQUIRED);
- lua_client->defaults.register_info.realname = lua_arg_string(L, nargs, 4, "realname", LUA_ARG_STRING_REQUIRED);
+ // parse args
+ lua_args_parse(L, &lua_client_set_defaults_func, (void *) &lua_client,
+ &nickname, &username, &realname, &service, &service_ssl
+ );
- // optional args
- lua_client->defaults.service = lua_arg_string(L, nargs, 5, "service", IRC_PORT);
- lua_client->defaults.service_ssl = lua_arg_string(L, nargs, 6, "service_ssl", IRC_SSL_PORT);
+ // set
+ struct irc_client_defaults defaults = {
+ .register_info = {
+ .nickname = nickname,
+ .username = username,
+ .realname = realname
+ },
+ .service = service,
+ .service_ssl = service_ssl
+ };
// invoke
- irc_client_set_defaults(lua_client->client, &lua_client->defaults);
+ // XXX: needs to be copied
+ irc_client_set_defaults(lua_client->client, &defaults);
// ok
return 0;
}
+static struct lua_func lua_client_connect_func = LUA_FUNC("evirc.client", "connect",
+ "Create and return a new IRC network",
+
+ LUA_FUNC_ARG_STRING("network", LUA_ARG_STRING_REQUIRED ),
+ LUA_FUNC_ARG_STRING("hostname", LUA_ARG_STRING_REQUIRED ),
+ LUA_FUNC_ARG_STRING("service", NULL ),
+ LUA_FUNC_ARG_BOOL( "ssl", false ),
+ LUA_FUNC_ARG_STRING("ssl_cafile", NULL ),
+ LUA_FUNC_ARG_BOOL( "ssl_verify", false ),
+ LUA_FUNC_ARG_STRING("ssl_cert", NULL ),
+ LUA_FUNC_ARG_STRING("ssl_pkey", NULL )
+);
+
static int lua_client_connect (lua_State *L)
{
- int nargs = lua_gettop(L);
- struct lua_client *lua_client = lua_obj_get_obj(L, __func__, "evirc.client");
+ struct lua_client *lua_client;
struct irc_net_info net_info;
const char *ssl_cafile = NULL, *ssl_cert = NULL, *ssl_pkey = NULL;
bool use_ssl = false, ssl_verify = false;
@@ -181,19 +212,11 @@
// init net_info
memset(&net_info, 0, sizeof(net_info));
- // required args
- net_info.network = lua_arg_string(L, nargs, 2, "network", LUA_ARG_STRING_REQUIRED);
- net_info.hostname = lua_arg_string(L, nargs, 3, "hostname", LUA_ARG_STRING_REQUIRED);
-
- // optional args
- net_info.service = lua_arg_string(L, nargs, 4, "service", NULL);
-
- // ssl stuff
- use_ssl = lua_arg_bool (L, nargs, 5, "use_ssl", false);
- ssl_cafile = lua_arg_string(L, nargs, 6, "ssl_cafile", NULL);
- ssl_verify = lua_arg_bool (L, nargs, 7, "ssl_verify", false);
- ssl_cert = lua_arg_string(L, nargs, 8, "ssl_cert", NULL);
- ssl_pkey = lua_arg_string(L, nargs, 9, "ssl_pkey", NULL);
+ // parse args
+ lua_args_parse(L, &lua_client_connect_func, (void *) &lua_client,
+ &net_info.network, &net_info.hostname, &net_info.service,
+ &use_ssl, &ssl_cafile, &ssl_verify, &ssl_cert, &ssl_pkey
+ );
// SSL?
if (use_ssl || ssl_cafile || ssl_verify || ssl_cert || ssl_pkey) {
--- a/src/lua_objs.c Sun Apr 19 04:52:12 2009 +0300
+++ b/src/lua_objs.c Sun Apr 19 06:20:59 2009 +0300
@@ -5,151 +5,6 @@
#include <stdlib.h>
#include <string.h>
-void lua_obj_create_type (lua_State *L, const char *name, const struct luaL_Reg methods[])
-{
- luaL_newmetatable(L, name);
-
- // set the metatable __index to itself
- lua_pushvalue(L, -1);
- lua_setfield(L, -1, "__index");
-
- // register the methods to the metatable
- luaL_register(L, NULL, methods);
-}
-
-void* lua_obj_create_obj (lua_State *L, const char *name, size_t size)
-{
- // create the new userdata on the stack
- void *ud = lua_newuserdata(L, size);
-
- // get the type and set it
- luaL_getmetatable(L, name);
- lua_setmetatable(L, -2);
-
- // ok
- return ud;
-}
-
-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;
-}
-
-void* lua_obj_get_obj (lua_State *L, const char *func, const char *name)
-{
- void *ud;
-
- // 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
- return ud;
-
- }
-}
-
-static void lua_getindex (lua_State *L, int t, int i)
-{
- lua_pushinteger(L, i);
- lua_gettable(L, t);
-}
-
-/**
- * Look up the arg index to use for the given index/name.
- *
- * If no value is found for the corresponding index, returns zero.
- */
-static int lua_arg_index (lua_State *L, int nargs, int index, const char *name)
-{
- // lookup from table?
- if (name && lua_istable(L, 2)) {
- // push the value from the field onto the stack
- lua_getfield(L, 2, name);
-
- // no named field?
- if (lua_isnil(L, -1)) {
- lua_pop(L, 1);
-
- lua_getindex(L, 2, index - 1);
- }
-
- // no index field?
- if (lua_isnil(L, -1)) {
- lua_pop(L, 1);
-
- return 0;
- }
-
- // found either a named or indexed arg
- return lua_gettop(L);
-
- } else if (index <= nargs) {
- // use the same index
- return index;
-
- } else {
- // no index
- return 0;
- }
-}
-
-const char *lua_arg_string (lua_State *L, int nargs, int index, const char *name, const char *def)
-{
- const char *value;
-
- // map index
- index = lua_arg_index(L, nargs, index, name);
-
- // use default?
- if (lua_isnoneornil(L, index) && def != (const char *) LUA_ARG_REQUIRED)
- return def;
-
- // value given?
- if ((value = lua_tostring(L, index)))
- return value;
-
- // error
- luaL_error(L, "missing value for required string argument <%d:%s>", index, name);
-}
-
-bool lua_arg_bool (lua_State *L, int nargs, int index, const char *name, int def)
-{
- bool value;
-
- // map index
- index = lua_arg_index(L, nargs, index, name);
-
- // use default?
- if (lua_isnoneornil(L, index) && def != LUA_ARG_REQUIRED)
- return def;
-
- // value given?
- value = lua_toboolean(L, index);
-
- return value;
-
- // error
- // luaL_error(L, "missing value of required boolean argument <%d:%s>", index, name);
-}
-
/**
* Wrapper for module
*/
--- a/src/lua_objs.h Sun Apr 19 04:52:12 2009 +0300
+++ b/src/lua_objs.h Sun Apr 19 06:20:59 2009 +0300
@@ -11,41 +11,8 @@
#include <lua5.1/lua.h>
#include <lua5.1/lauxlib.h>
-/**
- * Register a new metatable for a named type, this leaves the metatable on the stack.
- */
-void lua_obj_create_type (lua_State *L, const char *name, const struct luaL_Reg methods[]);
-
-/**
- * Create a new userdata with the given type metatable name, return the pointer, and keep it on the stack.
- */
-void* lua_obj_create_obj (lua_State *L, const char *name, size_t size);
-
-/**
- * Create a new metatable for a type, a userdata for that type, and register it as a global
- */
-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);
-
-/**
- * Get a userdata with the given type metatable name as the first argument for a function.
- */
-void* lua_obj_get_obj (lua_State *L, const char *func, const char *name);
-
-/**
- * Used as the "invalid" default value
- */
-#define LUA_ARG_REQUIRED (-1)
-#define LUA_ARG_STRING_REQUIRED ((const char *) (-1))
-
-/**
- * Parse and return a string argument
- */
-const char *lua_arg_string (lua_State *L, int nargs, int index, const char *name, const char *def);
-
-/**
- * Parse and return a boolean argument
- */
-bool lua_arg_bool (lua_State *L, int nargs, int index, const char *name, int def);
+// XXX: remove
+#include "lua_type.h"
/**
* Registers our lua runtime objects into the given lua state.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lua_type.c Sun Apr 19 06:20:59 2009 +0300
@@ -0,0 +1,64 @@
+#include "lua_type.h"
+
+#include <lua5.1/lauxlib.h>
+
+void lua_obj_create_type (lua_State *L, const char *name, const struct luaL_Reg methods[])
+{
+ luaL_newmetatable(L, name);
+
+ // set the metatable __index to itself
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -1, "__index");
+
+ // register the methods to the metatable
+ luaL_register(L, NULL, methods);
+}
+
+void* lua_obj_create_obj (lua_State *L, const char *name, size_t size)
+{
+ // create the new userdata on the stack
+ void *ud = lua_newuserdata(L, size);
+
+ // get the type and set it
+ luaL_getmetatable(L, name);
+ lua_setmetatable(L, -2);
+
+ // ok
+ return ud;
+}
+
+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;
+}
+
+void* lua_obj_get_obj (lua_State *L, const char *func, const char *name)
+{
+ void *ud;
+
+ // 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
+ return ud;
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lua_type.h Sun Apr 19 06:20:59 2009 +0300
@@ -0,0 +1,34 @@
+#ifndef LUA_TYPE_H
+#define LUA_TYPE_H
+
+/**
+ * @file
+ *
+ * Convenience functions for defining "types" in lua
+ */
+#include <lua5.1/lua.h>
+
+// XXX: remove
+#include <lua5.1/lauxlib.h>
+
+/**
+ * Register a new metatable for a named type, this leaves the metatable on the stack.
+ */
+void lua_obj_create_type (lua_State *L, const char *name, const struct luaL_Reg methods[]);
+
+/**
+ * Create a new userdata with the given type metatable name, return the pointer, and keep it on the stack.
+ */
+void* lua_obj_create_obj (lua_State *L, const char *name, size_t size);
+
+/**
+ * Create a new metatable for a type, a userdata for that type, and register it as a global
+ */
+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);
+
+/**
+ * Get a userdata with the given type metatable name as the first argument for a function.
+ */
+void* lua_obj_get_obj (lua_State *L, const char *func, const char *name);
+
+#endif