diff options
Diffstat (limited to 'cfgparser.c')
-rw-r--r-- | cfgparser.c | 534 |
1 files changed, 449 insertions, 85 deletions
diff --git a/cfgparser.c b/cfgparser.c index efa42ad367..69b87b777e 100644 --- a/cfgparser.c +++ b/cfgparser.c @@ -15,6 +15,7 @@ #include <fcntl.h> #include <string.h> #include <errno.h> +#include "config.h" #include "mp_msg.h" @@ -23,84 +24,345 @@ #define MAX_RECURSION_DEPTH 8 -#ifdef DEBUG +#ifdef MP_DEBUG #include <assert.h> #endif #include "cfgparser.h" -static struct config *config; -static int nr_options; /* number of options in 'conf' */ -static int parser_mode; /* COMMAND_LINE or CONFIG_FILE */ -static int recursion_depth = 0; -static int init_conf(struct config *conf, int mode) -{ -#ifdef DEBUG - assert(conf != NULL); + +static void +m_config_save_option(m_config_t* config, config_t* conf,char* opt, char *param) { + config_save_t* save; + int sl=0; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->cs_level >= 0); + assert(conf != NULL); + assert(opt != NULL); + assert( ! (conf->flags & CONF_NOSAVE)); +#endif + + switch(conf->type) { + case CONF_TYPE_PRINT : + case CONF_TYPE_SUBCONFIG : + return; + default : + } + + mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Saving option %s\n",opt); + + save = config->config_stack[config->cs_level]; + + if(save) { + for(sl = 0; save[sl].opt != NULL; sl++){ + // Check to not allocate the same arg two times + if(save[sl].opt == conf && (save[sl].opt_name == NULL || strcasecmp(save[sl].opt_name,opt) == 0)) + break; + } + + } + if(save == NULL || save[sl].opt == NULL) { + save = (config_save_t*)realloc(save,(sl+2)*sizeof(config_save_t)); + if(save == NULL) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Can't allocate %d bytes of memory : %s\n",(sl+2)*sizeof(config_save_t),strerror(errno)); + return; + } + memset(&save[sl],0,2*sizeof(config_save_t)); + save[sl].opt = conf; + } + + + switch(conf->type) { + case CONF_TYPE_FLAG : + case CONF_TYPE_INT : + save[sl].param.as_int = *((int*)conf->p); + break; + case CONF_TYPE_FLOAT : + save[sl].param.as_float = *((float*)conf->p); + break; + case CONF_TYPE_STRING : + save[sl].param.as_pointer = *((char**)conf->p); + break; + case CONF_TYPE_FUNC_FULL : + if(strcasecmp(conf->name,opt) != 0) save->opt_name = strdup(opt); + case CONF_TYPE_FUNC_PARAM : + save->param.as_pointer = strdup(param); + case CONF_TYPE_FUNC : + break; + default : + printf("Should never append in m_config_save_option : conf->type=%d\n",conf->type); + } + + config->config_stack[config->cs_level] = save; +} + +static int +m_config_revert_option(m_config_t* config, config_save_t* save) { + char* arg = NULL; + config_save_t* iter=NULL; + int i=-1; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->cs_level >= 0); + assert(save != NULL); +#endif + + + arg = save->opt_name ? save->opt_name : save->opt->name; + mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Reverting option %s\n",arg); + + if(save->opt->default_func) + save->opt->default_func(save->opt,arg); + + switch(save->opt->type) { + case CONF_TYPE_FLAG : + case CONF_TYPE_INT : + *((int*)save->opt->p) = save->param.as_int; + break; + case CONF_TYPE_FLOAT : + *((float*)save->opt->p) = save->param.as_float; + break; + case CONF_TYPE_STRING : + *((char**)save->opt->p) = save->param.as_pointer; + break; + case CONF_TYPE_FUNC_PARAM : + case CONF_TYPE_FUNC_FULL : + case CONF_TYPE_FUNC : + if(config->cs_level > 0) { + for(i = config->cs_level - 1 ; i >= 0 ; i--){ + if(config->config_stack[i] == NULL) continue; + for(iter = config->config_stack[i]; iter != NULL && iter->opt != NULL ; iter++) { + if(iter->opt == save->opt && + strcasecmp(save->param.as_pointer,iter->param.as_pointer) == 0 && + (save->opt_name == NULL || + (iter->opt_name && strcasecmp(save->opt_name,iter->opt_name)))) break; + } + } + } + free(save->param.as_pointer); + if(save->opt_name) free(save->opt_name); + save->opt_name = save->param.as_pointer = NULL; + if(i < 0) break; + arg = iter->opt_name ? iter->opt_name : iter->opt->name; + switch(iter->opt->type) { + case CONF_TYPE_FUNC : + if ((((cfg_func_t) iter->opt->p)(iter->opt)) < 0) + return -1; + break; + case CONF_TYPE_FUNC_PARAM : + if (iter->param.as_pointer == NULL) { + printf("We lost param for option %s?\n",iter->opt->name); + return -1; + } + if ((((cfg_func_param_t) iter->opt->p)(iter->opt, (char*)iter->param.as_pointer)) < 0) + return -1; + break; + case CONF_TYPE_FUNC_FULL : + if (iter->param.as_pointer != NULL && ((char*)iter->param.as_pointer)[0]=='-'){ + if( ((cfg_func_arg_param_t) iter->opt->p)(iter->opt, arg, NULL) < 0) + return -1; + }else { + if (((cfg_func_arg_param_t) save->opt->p)(iter->opt, arg, (char*)iter->param.as_pointer) < 0) + return -1; + + } + break; + } + break; + default : + printf("Why do we reverse this : name=%s type=%d ?\n",save->opt->name,save->opt->type); + } + + return 1; +} + +void +m_config_push(m_config_t* config) { + +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->cs_level >= 0); #endif - /* calculate the number of options in 'conf' */ - for (nr_options = 0; conf[nr_options].name != NULL; nr_options++) - /* NOTHING */; + config->cs_level++; + config->config_stack = (config_save_t**)realloc(config->config_stack ,sizeof(config_save_t*)*(config->cs_level+1)); + if(config->config_stack == NULL) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Can't allocate %d bytes of memory : %s\n",sizeof(config_save_t*)*(config->cs_level+1),strerror(errno)); + config->cs_level = -1; + return; + } + config->config_stack[config->cs_level] = NULL; + mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Config pushed level=%d\n",config->cs_level); +} + +int +m_config_pop(m_config_t* config) { + int i,ret= 1; + config_save_t* cs; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->cs_level > 0); +#endif + + if(config->config_stack[config->cs_level] != NULL) { + cs = config->config_stack[config->cs_level]; + for(i=0; cs[i].opt != NULL ; i++ ) { + if (m_config_revert_option(config,&cs[i]) < 0) + ret = -1; + } + free(config->config_stack[config->cs_level]); + } + config->config_stack = (config_save_t**)realloc(config->config_stack ,sizeof(config_save_t*)*config->cs_level); + config->cs_level--; + if(config->cs_level > 0 && config->config_stack == NULL) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Can't allocate %d bytes of memory : %s\n",sizeof(config_save_t*)*config->cs_level,strerror(errno)); + config->cs_level = -1; + return -1; + } + mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Config poped level=%d\n",config->cs_level); + return ret; +} + +m_config_t* +m_config_new(play_tree_t* pt) { + m_config_t* config; + +#ifdef MP_DEBUG + assert(pt != NULL); +#endif + + config = (m_config_t*)calloc(1,sizeof(m_config_t)); + if(config == NULL) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Can't allocate %d bytes of memory : %s\n",sizeof(m_config_t),strerror(errno)); + return NULL; + } + config->config_stack = (config_save_t**)calloc(1,sizeof(config_save_t*)); + if(config->config_stack == NULL) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Can't allocate %d bytes of memory : %s\n",sizeof(config_save_t*),strerror(errno)); + free(config); + return NULL; + } + config->global = 1; // We always start with global options + config->pt = pt; + return config; +} + +void +m_config_free(m_config_t* config) { + +#ifdef MP_DEBUG + assert(config != NULL); +#endif + + free(config->opt_list); + free(config->config_stack); + free(config); +} + + +static int init_conf(m_config_t *config, int mode) +{ +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->pt != NULL); + assert(config->last_entry == NULL || config->last_entry->parent == config->pt); - config = conf; -#ifdef DEBUG if (mode != COMMAND_LINE && mode != CONFIG_FILE) { mp_msg(MSGT_CFGPARSER, MSGL_ERR, "init_conf: wrong mode!\n"); return -1; } #endif - parser_mode = mode; + config->parser_mode = mode; + config->global = 1; return 1; } -static int read_option(struct config *conf, int conf_optnr, char *opt, char *param) + +static int config_read_option(m_config_t *config,config_t** conf_list, char *opt, char *param) { - int i; + int i=0,nconf = 0; long tmp_int; double tmp_float; int ret = -1; char *endptr; + config_t* conf=NULL; - mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "read_option: conf=%p optnr=%d opt='%s' param='%s'\n", - conf, conf_optnr, opt, param); - for (i = 0; i < conf_optnr; i++) { - int namelength; - /* allow 'aa*' in config.name */ - namelength=strlen(conf[i].name); - if ( (conf[i].name[namelength-1]=='*') && - !memcmp(opt, conf[i].name, namelength-1)) - break; - - - if (!strcasecmp(opt, conf[i].name)) +#ifdef MP_DEBUG + assert(config != NULL); + assert(conf_list != NULL); + assert(opt != NULL); +#endif + + mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "read_option: conf=%p opt='%s' param='%s'\n", + conf, opt, param); + for(nconf = 0 ; conf_list&& conf_list[nconf] != NULL; nconf++) { + conf = conf_list[nconf]; + for (i = 0; conf[i].name != NULL; i++) { + int namelength; + /* allow 'aa*' in config.name */ + namelength=strlen(conf[i].name); + if ( (conf[i].name[namelength-1]=='*') && + !memcmp(opt, conf[i].name, namelength-1)) + break; + if (!strcasecmp(opt, conf[i].name)) break; + } } - if (i == conf_optnr) { - if (parser_mode == CONFIG_FILE) - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "invalid option: %s\n", opt); + if (conf[i].name == NULL) { + if (config->parser_mode == CONFIG_FILE) + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "invalid option:\n"); ret = ERR_NOT_AN_OPTION; goto out; } mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "read_option: name='%s' p=%p type=%d\n", conf[i].name, conf[i].p, conf[i].type); - if (conf[i].flags & CONF_NOCFG && parser_mode == CONFIG_FILE) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "this option can only be used on command line: %s\n", opt); + if (conf[i].flags & CONF_NOCFG && config->parser_mode == CONFIG_FILE) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "this option can only be used on command line:\n", opt); ret = ERR_NOT_AN_OPTION; goto out; } - if (conf[i].flags & CONF_NOCMD && parser_mode == COMMAND_LINE) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "this option can only be used in config file: %s\n", opt); + if (conf[i].flags & CONF_NOCMD && config->parser_mode == COMMAND_LINE) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "this option can only be used in config file:\n", opt); ret = ERR_NOT_AN_OPTION; goto out; } - + if(strcasecmp(opt,"playlist") == 0) { // We handle playlist here + play_tree_t* list; +#ifdef MP_DEBUG + assert(config->pt != NULL); +#endif + if(!param) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "playlist option need a filename\n"); + ret = ERR_MISSING_PARAM; + goto out; + } + list = parse_playlist_file(param); + if(list) { + if(config->last_entry) { + play_tree_append_entry(config->last_entry,list); + } + else + play_tree_set_child(config->pt,list); + config->last_entry = list; + } + if(config->parser_mode == COMMAND_LINE) + config->global = 0; + return 1; + } + if(config->global == 0 && ! (conf[i].flags & CONF_GLOBAL) ) + m_config_push(config); + if( !(conf[i].flags & CONF_NOSAVE) && ! (conf[i].flags & CONF_GLOBAL) ) + m_config_save_option(config,&conf[i],opt,param); switch (conf[i].type) { case CONF_TYPE_FLAG: /* flags need a parameter in config file */ - if (parser_mode == CONFIG_FILE) { + if (config->parser_mode == CONFIG_FILE) { if (!strcasecmp(param, "yes") || /* any other language? */ !strcasecmp(param, "ja") || !strcasecmp(param, "si") || @@ -214,7 +476,7 @@ static int read_option(struct config *conf, int conf_optnr, char *opt, char *par case CONF_TYPE_FUNC_PARAM: if (param == NULL) goto err_missing_param; - if ((((cfg_func_param_t) conf[i].p)(config + i, param)) < 0) { + if ((((cfg_func_param_t) conf[i].p)(conf + i, param)) < 0) { ret = ERR_FUNC_ERR; goto out; } @@ -222,17 +484,17 @@ static int read_option(struct config *conf, int conf_optnr, char *opt, char *par break; case CONF_TYPE_FUNC_FULL: if (param!=NULL && param[0]=='-'){ - ret=((cfg_func_arg_param_t) conf[i].p)(config + i, opt, NULL); + ret=((cfg_func_arg_param_t) conf[i].p)(conf + i, opt, NULL); if (ret>=0) ret=0; /* if we return >=0: param is processed again (if there is any) */ }else{ - ret=((cfg_func_arg_param_t) conf[i].p)(config + i, opt, param); + ret=((cfg_func_arg_param_t) conf[i].p)(conf + i, opt, param); /* if we return 0: need no param, precess it again */ /* if we return 1: accepted param */ } break; case CONF_TYPE_FUNC: - if ((((cfg_func_t) conf[i].p)(config + i)) < 0) { + if ((((cfg_func_t) conf[i].p)(conf + i)) < 0) { ret = ERR_FUNC_ERR; goto out; } @@ -243,9 +505,9 @@ static int read_option(struct config *conf, int conf_optnr, char *opt, char *par char *subparam; char *subopt; int subconf_optnr; - struct config *subconf; + config_t *subconf; + config_t *sublist[] = { NULL , NULL }; char *token; - int sscanf_ret; if (param == NULL) goto err_missing_param; @@ -254,16 +516,17 @@ static int read_option(struct config *conf, int conf_optnr, char *opt, char *par subopt = malloc(strlen(param)+1); subconf = conf[i].p; + sublist[0] = subconf; for (subconf_optnr = 0; subconf[subconf_optnr].name != NULL; subconf_optnr++) /* NOTHING */; token = strtok(param, (char *)&(":")); while(token) { + int sscanf_ret; /* clear out */ subopt[0] = subparam[0] = 0; -// sscanf_ret = sscanf(token, "%[^=]=%[^\n\0]", subopt, subparam); sscanf_ret = sscanf(token, "%[^=]=%s", subopt, subparam); mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "token: '%s', i=%d, subopt='%s', subparam='%s' (ret: %d)\n", token, i, subopt, subparam, sscanf_ret); @@ -272,7 +535,7 @@ static int read_option(struct config *conf, int conf_optnr, char *opt, char *par case 1: subparam[0] = 0; case 2: - if ((ret = read_option((struct config *)subconf, subconf_optnr, subopt, subparam)) < 0) + if ((ret = config_read_option(config,sublist, subopt, subparam)) < 0) { mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Subconfig parsing returned error: %d in token: %s\n", ret, token); @@ -300,6 +563,17 @@ static int read_option(struct config *conf, int conf_optnr, char *opt, char *par break; } out: + if(config->global == 0 && ! (conf[i].flags & CONF_GLOBAL)) { + play_tree_t* dest = config->last_entry ? config->last_entry : config->last_parent; +#ifdef MP_DEBUG + assert(dest != NULL); +#endif + if(ret == 0) + play_tree_set_param(dest,opt,NULL); + else if(ret > 0) + play_tree_set_param(dest,opt,param); + m_config_pop(config); + } return ret; err_missing_param: mp_msg(MSGT_CFGPARSER, MSGL_ERR, "missing parameter for option: %s\n", opt); @@ -307,7 +581,17 @@ err_missing_param: goto out; } -int parse_config_file(struct config *conf, char *conffile) +int m_config_set_option(m_config_t *config,char *opt, char *param) { + +#ifdef MP_DEBUG + assert(config != NULL); + assert(opt != NULL); +#endif + mp_msg(MSGT_CFGPARSER, MSGL_DBG2, "Setting option %s=%s\n",opt,param); + return config_read_option(config,config->opt_list,opt,param); +} + +int m_config_parse_config_file(m_config_t *config, char *conffile) { #define PRINT_LINENUM printf("%s(%d): ", conffile, line_num) #define MAX_LINE_LEN 1000 @@ -326,19 +610,20 @@ int parse_config_file(struct config *conf, char *conffile) int ret = 1; int errors = 0; -#ifdef DEBUG - assert(conffile != NULL); +#ifdef MP_DEBUG + assert(config != NULL); + // assert(conf_list != NULL); #endif - if (++recursion_depth > 1) + if (++config->recursion_depth > 1) printf("Reading config file: %s", conffile); - if (recursion_depth > MAX_RECURSION_DEPTH) { + if (config->recursion_depth > MAX_RECURSION_DEPTH) { printf(": too deep 'include'. check your configfiles\n"); ret = -1; goto out; } - if (init_conf(conf, CONFIG_FILE) == -1) { + if (init_conf(config, CONFIG_FILE) == -1) { ret = -1; goto out; } @@ -350,13 +635,13 @@ int parse_config_file(struct config *conf, char *conffile) } if ((fp = fopen(conffile, "r")) == NULL) { - if (recursion_depth > 1) + if (config->recursion_depth > 1) printf(": %s\n", strerror(errno)); free(line); ret = 0; goto out; } - if (recursion_depth > 1) + if (config->recursion_depth > 1) printf("\n"); while (fgets(line, MAX_LINE_LEN, fp)) { @@ -399,7 +684,7 @@ int parse_config_file(struct config *conf, char *conffile) } opt[opt_pos] = '\0'; -#ifdef DEBUG +#ifdef MP_DEBUG PRINT_LINENUM; printf("option: %s\n", opt); #endif @@ -460,7 +745,7 @@ int parse_config_file(struct config *conf, char *conffile) continue; } -#ifdef DEBUG +#ifdef MP_DEBUG PRINT_LINENUM; printf("parameter: %s\n", param); #endif @@ -477,7 +762,7 @@ int parse_config_file(struct config *conf, char *conffile) ret = -1; } - tmp = read_option(config, nr_options, opt, param); + tmp = m_config_set_option(config, opt, param); switch (tmp) { case ERR_NOT_AN_OPTION: case ERR_MISSING_PARAM: @@ -497,33 +782,34 @@ nextline: free(line); fclose(fp); out: - --recursion_depth; + --config->recursion_depth; return ret; } -int parse_command_line(struct config *conf, int argc, char **argv, char **envp, char ***filenames) +int m_config_parse_command_line(m_config_t *config, int argc, char **argv, char **envp) { int i; - char **f = NULL; - int f_nr = 0; int tmp; char *opt; int no_more_opts = 0; -#ifdef DEBUG +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->pt != NULL); assert(argv != NULL); assert(envp != NULL); assert(argc >= 1); #endif - - if (init_conf(conf, COMMAND_LINE) == -1) - return -1; - + + if (init_conf(config, COMMAND_LINE) == -1) + return -1; + if(config->last_parent == NULL) + config->last_parent = config->pt; /* in order to work recursion detection properly in parse_config_file */ - ++recursion_depth; + ++config->recursion_depth; for (i = 1; i < argc; i++) { -next: + //next: opt = argv[i]; /* check for -- (no more options id.) except --help! */ if ((*opt == '-') && (*(opt+1) == '-') && (*(opt+2) != 'h')) @@ -534,9 +820,32 @@ next: mp_msg(MSGT_CFGPARSER, MSGL_ERR, "You added '--' but no filenames presented!\n"); goto err_out; } - i++; - goto next; + continue; } + if((opt[0] == '{') && (opt[1] == '\0')) + { + play_tree_t* entry = play_tree_new(); + config->global = 0; + if(config->last_entry == NULL) { + play_tree_set_child(config->last_parent,entry); + } else { + play_tree_append_entry(config->last_entry,entry); + config->last_entry = NULL; + } + config->last_parent = entry; + continue; + } + + if((opt[0] == '}') && (opt[1] == '\0')) + { + if( ! config->last_parent || ! config->last_parent->parent) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "too much }-\n"); + goto err_out; + } + config->last_entry = config->last_parent; + config->last_parent = config->last_entry->parent; + continue; + } if ((no_more_opts == 0) && (*opt == '-') && (*(opt+1) != 0)) /* option */ { @@ -544,8 +853,7 @@ next: opt++; mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "this_opt = option: %s\n", opt); - - tmp = read_option(config, nr_options, opt, argv[i + 1]); + tmp = m_config_set_option(config, opt, argv[i + 1]); switch (tmp) { case ERR_NOT_AN_OPTION: @@ -562,26 +870,82 @@ next: } else /* filename */ { - mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "this_opt = filename: %s\n", opt); - + play_tree_t* entry = play_tree_new(); + mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Adding file %s\n",argv[i]); + play_tree_add_file(entry,argv[i]); /* opt is not an option -> treat it as a filename */ - if (!(f = (char **) realloc(f, sizeof(*f) * (f_nr + 2)))) - goto err_out_mem; - - f[f_nr++] = argv[i]; + config->global = 0; // We start entry specific options + if(config->last_entry == NULL) + play_tree_set_child(config->last_parent,entry); + else + play_tree_append_entry(config->last_entry,entry); + config->last_entry = entry; } } - if (f) - f[f_nr] = NULL; - if (filenames) - *filenames = f; - --recursion_depth; - return f_nr; //filenames_nr; + --config->recursion_depth; + if(config->last_parent != config->pt) + mp_msg(MSGT_CFGPARSER, MSGL_ERR,"Missing }- ?\n"); + config->global = 1; + return 1; +#if 0 err_out_mem: mp_msg(MSGT_CFGPARSER, MSGL_ERR, "can't allocate memory for filenames (%s)\n", strerror(errno)); +#endif err_out: - --recursion_depth; + --config->recursion_depth; + config->global = 1; mp_msg(MSGT_CFGPARSER, MSGL_ERR, "command line: %s\n", argv[i]); return -1; } + +void +m_config_register_options(m_config_t *config,config_t *args) { + int list_len = 0; + config_t** conf_list = config->opt_list; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(args != NULL); +#endif + + if(conf_list) { + for ( ; conf_list[list_len] != NULL; list_len++) + /* NOTHING */; + } + + conf_list = (config_t**)realloc(conf_list,sizeof(struct conf*)*(list_len+2)); + if(conf_list == NULL) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Can't allocate %d bytes of memory : %s\n",sizeof(struct conf*)*(list_len+2),strerror(errno)); + return; + } + conf_list[list_len] = args; + conf_list[list_len+1] = NULL; + + config->opt_list = conf_list; +} + +config_t* +m_config_get_option(m_config_t *config, char* arg) { + int i; + config_t *conf; + config_t **conf_list; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(arg != NULL); +#endif + + conf_list = config->opt_list; + if(conf_list) { + for(conf = conf_list[0]; conf != NULL ; conf ++) { + for(i=0; conf[i].name != NULL; i++) { + if(strcasecmp(conf[i].name,arg) == 0) + return &conf[i]; + } + } + } + return NULL; +} + + |