# HG changeset patch # User Tero Marttila # Date 1239392629 -10800 # Node ID 52ffbdb6bba183bd1d499a30335c453377b294eb # Parent 4682ebbc564472a2401746d652df497ba9907289 start implementing multiple args for lua_module_conf diff -r 4682ebbc5644 -r 52ffbdb6bba1 src/config.c --- 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? diff -r 4682ebbc5644 -r 52ffbdb6bba1 src/config.h --- 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 '/' 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 diff -r 4682ebbc5644 -r 52ffbdb6bba1 src/lua_objs.c --- 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)