terom@83: #include "config.h" terom@83: terom@83: #include terom@100: #include terom@83: terom@100: const struct config_option* config_lookup (const struct config_option *options, const char *name, struct error_info *err) terom@83: { terom@100: const struct config_option *option; terom@83: terom@83: // find the matching config opt terom@83: for (option = options; option->name && option->type; option++) { terom@83: if (strcmp(option->name, name) == 0) terom@100: return option; terom@100: } terom@100: terom@100: // not found terom@100: SET_ERROR_STR(err, ERR_MODULE_CONF, "unknown configuration option"); terom@100: terom@100: return NULL; terom@100: } terom@100: terom@100: /** terom@100: * Parse a raw value for a CONFIG_IRC_CHAN into an irc_chan terom@100: */ terom@100: static struct irc_chan* config_parse_irc_chan (struct nexus *nexus, char *raw_value, struct error_info *err) terom@100: { terom@100: const char *network, *channel; terom@100: struct irc_chan *chan; terom@100: terom@100: // parse required args terom@100: if ((network = strsep(&raw_value, "/")) == NULL) terom@100: JUMP_SET_ERROR_STR(err, ERR_MODULE_CONF, "invalid for CONFIG_IRC_CHAN value"); terom@100: terom@100: if ((channel = strsep(&raw_value, "/")) == NULL) terom@100: JUMP_SET_ERROR_STR(err, ERR_MODULE_CONF, "invalid for CONFIG_IRC_CHAN value"); terom@100: terom@100: // extraneous stuff? terom@100: if (raw_value) terom@100: JUMP_SET_ERROR_STR(err, ERR_MODULE_CONF, "trailing data for CONFIG_IRC_CHAN value"); terom@100: terom@100: // get the channel? terom@100: if ((chan = irc_client_get_chan(nexus->client, network, channel)) == NULL) terom@100: JUMP_SET_ERROR_STR(err, ERR_MODULE_CONF, "unknown network/channel name for CONFIG_IRC_CHAN value"); terom@100: terom@100: // ok terom@100: return chan; terom@100: terom@100: error: terom@100: return NULL; terom@100: } terom@100: terom@100: err_t config_parse (const struct config_option *option, struct nexus *nexus, struct config_value *value, char *raw_value, struct error_info *err) terom@100: { terom@100: // parse the value terom@100: switch (option->type) { terom@100: case CONFIG_STRING: terom@100: // simple! terom@100: value->string = raw_value; terom@83: break; terom@100: terom@100: case CONFIG_IRC_CHAN: terom@100: // parse the value terom@100: if (!(value->irc_chan = config_parse_irc_chan(nexus, raw_value, err))) terom@100: return ERROR_CODE(err); terom@100: terom@100: break; terom@100: terom@100: default: terom@100: NOT_REACHED(); terom@83: } terom@83: terom@100: // copy the type terom@100: value->type = option->type; terom@100: terom@100: // ok terom@100: return SUCCESS; terom@100: } terom@100: terom@100: err_t config_apply_opt (const struct config_option *option, void *ctx, const struct config_value *value, struct error_info *err) terom@100: { terom@100: // wrong type? terom@100: if (option->type != value->type) terom@100: // XXX: info about type names terom@100: return SET_ERROR(err, ERR_CONFIG_TYPE); terom@100: terom@100: // null? terom@100: if (!value) terom@100: RETURN_SET_ERROR_STR(err, ERR_CONFIG_REQUIRED, option->name); terom@100: terom@100: // call the handler terom@100: switch (option->type) { terom@100: case CONFIG_STRING: return option->func.string(ctx, value->string, err); terom@100: case CONFIG_IRC_CHAN: return option->func.irc_chan(ctx, value->irc_chan, err); terom@100: default: NOT_REACHED(); terom@100: } terom@100: } terom@100: terom@100: err_t config_apply (const struct config_option *options, void *ctx, const char *name, const struct config_value *value, struct error_info *err) terom@100: { terom@100: const struct config_option *option; terom@100: terom@83: // no matching option found? terom@100: if (!(option = config_lookup(options, name, err))) terom@100: return ERROR_CODE(err); terom@100: terom@100: // apply it terom@100: return config_apply_opt(option, ctx, value, err); terom@100: } terom@83: terom@100: err_t config_apply_string (const struct config_option *options, void *ctx, const char *name, char *value, struct error_info *err) terom@100: { terom@100: struct config_value conf_value = { CONFIG_STRING, { .string = value } }; terom@100: terom@100: return config_apply(options, ctx, name, &conf_value, err); terom@83: } terom@100: terom@100: err_t config_apply_irc_chan (const struct config_option *options, void *ctx, const char *name, struct irc_chan *value, struct error_info *err) terom@100: { terom@100: struct config_value conf_value = { CONFIG_STRING, { .irc_chan = value } }; terom@100: terom@100: return config_apply(options, ctx, name, &conf_value, err); terom@100: } terom@100: terom@100: err_t config_apply_raw (const struct config_option *options, struct nexus *nexus, void *ctx, const char *name, char *raw_value, struct error_info *err) terom@100: { terom@100: const struct config_option *option; terom@100: struct config_value value; terom@100: terom@100: // no matching option found? terom@100: if (!(option = config_lookup(options, name, err))) terom@100: return ERROR_CODE(err); terom@100: terom@100: // parse it terom@100: if (config_parse(option, nexus, &value, raw_value, err)) terom@100: return ERROR_CODE(err); terom@100: terom@100: // apply it terom@100: return config_apply_opt(option, ctx, &value, err); terom@100: } terom@100: