--- a/src/config.c Wed Apr 08 02:25:30 2009 +0300
+++ b/src/config.c Fri Apr 10 22:43:49 2009 +0300
@@ -19,6 +19,18 @@
return NULL;
}
+int config_params_count (const struct config_option *option)
+{
+ const struct config_param *param;
+ int count = 0;
+
+ // handle each param
+ for (param = option->params; param->name && param->type; param++)
+ count++;
+
+ return count;
+}
+
/**
* Parse a raw value for a CONFIG_IRC_CHAN into an irc_chan
*/
@@ -51,15 +63,8 @@
return NULL;
}
-err_t config_parse (const struct config_option *option, struct nexus *nexus, struct config_value *value, char *raw_value, struct error_info *err)
+err_t config_parse_param (const struct config_param *param, struct nexus *nexus, struct config_value *value, char *raw_value, struct error_info *err)
{
- // use the first param
- const struct config_param *param = &option->params[0];
-
- // must have exactly one param
- if (!param->type || (param + 1)->type)
- return SET_ERROR(err, ERR_CONFIG_PARAMS);
-
// parse the value
switch (param->type) {
case CONFIG_STRING:
@@ -74,6 +79,10 @@
break;
+ case CONFIG_USER:
+ // fail
+ return SET_ERROR_STR(err, ERR_CONFIG_TYPE, "user type can't be parsed");
+
default:
NOT_REACHED();
}
@@ -85,6 +94,19 @@
return SUCCESS;
}
+err_t config_parse (const struct config_option *option, struct nexus *nexus, struct config_value *value, char *raw_value, struct error_info *err)
+{
+ // use the first param
+ const struct config_param *param = &option->params[0];
+
+ // must have exactly one param
+ if (!param->type || (param + 1)->type)
+ return SET_ERROR(err, ERR_CONFIG_PARAMS);
+
+ // parse it
+ return config_parse_param(param, nexus, value, raw_value, err);
+}
+
err_t config_check_param (const struct config_param *param, const struct config_value *value, struct error_info *err)
{
// no value given?
--- a/src/config.h Wed Apr 08 02:25:30 2009 +0300
+++ b/src/config.h Fri Apr 10 22:43:49 2009 +0300
@@ -168,16 +168,30 @@
*/
const struct config_option* config_lookup (const struct config_option *options, const char *name, struct error_info *err);
+/**
+ * Returns the number of params that an option has
+ *
+ * @param option the option to count
+ * @return the number of params
+ */
+int config_params_count (const struct config_option *option);
+
// XXX: move this into nexus
#include "nexus.h"
/**
- * Parse a raw value into a suitable configuration value for a single-param option, based on the config option type.
+ * Parse a raw value into a suitable configuration value for the given param, based on its type.
*
* Since this needs to access the application state, you need to pass in the nexus as an argument.
*
* Formats supported:
* CONFIG_IRC_CHAN - uses a '<network>/<channel>' format and irc_client_get_chan
*
+ */
+err_t config_parse_param (const struct config_param *param, struct nexus *nexus, struct config_value *value, char *raw_value, struct error_info *err);
+
+/**
+ * Parse a raw value into a suitable configuration value for a single-param option, based on the config option type.
+ *
* @param option the option to parse the value for, use config_lookup to find it
* @param nexus the application state
* @param value the returned value, if succesfull
--- a/src/lua_objs.c Wed Apr 08 02:25:30 2009 +0300
+++ b/src/lua_objs.c Fri Apr 10 22:43:49 2009 +0300
@@ -103,92 +103,121 @@
return 0;
}
-/**
- * Parse and apply the given config option value as a raw value to the given module's option
- */
-static int _lua_module_conf_raw_str (lua_State *L, struct lua_module *lua_module, struct nexus *nexus,
- const struct config_option *option, const char *conf_value)
-{
- struct config_value value;
- struct error_info err;
-
- // mutable version of the conf_value
- char conf_value_buf[strlen(conf_value) + 1];
- strcpy(conf_value_buf, conf_value);
-
- // parse it as a raw value
- 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 while conf_value_buf is still in scope
- if (module_conf(lua_module->module, option, &value, &err))
- return luaL_error(L, "module_conf: %s/%s: %s", module_name(lua_module->module), option->name, error_msg(&err));
-
- // ok
- return 0;
-}
-
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 values[2] = {
- CONFIG_VALUE_END,
- CONFIG_VALUE_END
- }, *value = &values[0];
+ struct config_value values[CONFIG_VALUES_MAX], *value = values;
+ char *value_bufs[CONFIG_VALUES_MAX], **value_buf = value_bufs;
struct error_info err;
+ bool is_err = true;
+
+ // number of arguments given
+ int nargs = lua_gettop(L), argidx = 2;
+
+ // init to zero
+ memset(values, 0, sizeof(values));
+ memset(value_bufs, 0, sizeof(value_bufs));
// 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);
+ const char *conf_name = luaL_checkstring(L, argidx++);
// 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));
-
- // the config value
- switch (lua_type(L, 3)) {
- case LUA_TSTRING:
- // parse+apply it as a raw string
- return _lua_module_conf_raw_str(L, lua_module, nexus, option, lua_tostring(L, 3));
-
- case LUA_TUSERDATA:
- // some kind of userdata, use its metatable to figure out what type it is
- if (!lua_getmetatable(L, 3))
- return luaL_error(L, "config value is userdata without metatable");
-
- // get the target metatable
- lua_getfield(L, LUA_REGISTRYINDEX, "evirc.chan");
- // is it a chan?
- if (!lua_rawequal(L, -1, -2))
- return luaL_error(L, "config value is userdata of unknown type");
-
- // pop the metatables
- lua_pop(L, 2);
+ // maximum number of arguments accepted
+ int maxargs = config_params_count(option);
- // get the irc_chan
- struct lua_chan *lua_chan = lua_touserdata(L, 3);
+ // too many arguments?
+ if (nargs > maxargs)
+ return luaL_error(L, "lua_module_conf: too many arguments (>%d) given (%d)", maxargs, nargs - 3);
+
+ // the current param
+ const struct config_param *param = option->params;
- // build the value
- value->type = CONFIG_IRC_CHAN;
- value->irc_chan = lua_chan->chan;
+ // apply each given argument
+ for (; argidx <= nargs; argidx++, value++, param++) {
+ // the config value
+ switch (lua_type(L, argidx)) {
+ case LUA_TSTRING: {
+ // string arg
+ const char *arg_str = lua_tostring(L, argidx);
+
+ // copy it as a mutable string buffer
+ if ((*value_buf = strdup(arg_str)) == NULL) {
+ lua_pushfstring(L, "strdup");
+ goto error;
+ }
+
+ // parse it as a raw value
+ if (config_parse_param(param, nexus, value, *value_buf, &err)) {
+ lua_pushfstring(L, "config_parse: %s/%s: %s", option->name, *value_buf, error_msg(&err));
+ goto error;
+ }
+
+ // seek to next value_buf
+ value_buf++;
+
+ } break;
+
+ case LUA_TUSERDATA:
+ // some kind of userdata, use its metatable to figure out what type it is
+ if (!lua_getmetatable(L, argidx)) {
+ lua_pushfstring(L, "config value is userdata without metatable");
+ goto error;
+ }
+
+ // get the target metatable
+ lua_getfield(L, LUA_REGISTRYINDEX, "evirc.chan");
+
+ // is it a chan?
+ if (!lua_rawequal(L, -1, -2)) {
+ lua_pushfstring(L, "config value is userdata of unknown type");
+ goto error;
+ }
+
+ // pop the metatables
+ lua_pop(L, 2);
+
+ // get the irc_chan
+ struct lua_chan *lua_chan = lua_touserdata(L, argidx);
+
+ // build the value
+ value->type = CONFIG_IRC_CHAN;
+ value->irc_chan = lua_chan->chan;
+
+ break;
- break;
-
- default:
- return luaL_error(L, "config value is of unknown lua type '%s'", lua_typename(L, 3));
+ default:
+ lua_pushfstring(L, "config value is of unknown lua type '%s'", lua_typename(L, argidx));
+ goto error;
+ }
+ }
+
+ // apply it
+ if (module_conf(lua_module->module, option, values, &err)) {
+ lua_pushfstring(L, "module_conf: %s/%s: %s", module_name(lua_module->module), option->name, error_msg(&err));
+ goto error;
}
- // apply it
- if (module_conf(lua_module->module, option, values, &err))
- return luaL_error(L, "module_conf: %s/%s: %s", module_name(lua_module->module), option->name, error_msg(&err));
-
// ok
- return 0;
+ is_err = false;
+
+error:
+ // release any allocated strings
+ for (value_buf = value_bufs; value_buf <= value_bufs + CONFIG_VALUES_MAX && *value_buf; value_buf++)
+ free(*value_buf);
+
+ // either error or successful return
+ if (is_err)
+ return lua_error(L);
+ else
+ return 0;
}
static int lua_module_unload (lua_State *L)