diff options
Diffstat (limited to 'm_config.c')
-rw-r--r-- | m_config.c | 212 |
1 files changed, 101 insertions, 111 deletions
diff --git a/m_config.c b/m_config.c index 7d85f547e3..3f7d32407d 100644 --- a/m_config.c +++ b/m_config.c @@ -8,6 +8,7 @@ #include <stdio.h> #include <errno.h> #include <string.h> +#include "talloc.h" #ifdef MP_DEBUG #include <assert.h> #endif @@ -34,12 +35,33 @@ m_config_add_option(m_config_t *config, const m_option_t *arg, const char* prefi static int list_options(m_option_t *opt, char* name, char *param); -m_config_t* -m_config_new(void) { +static void m_option_save(const m_config_t *config, const m_option_t *opt, + void *dst) +{ + if (opt->type->save) { + void *src = opt->new ? (char*)config->optstruct + opt->offset : opt->p; + opt->type->save(opt, dst, src); + } +} + +static void m_option_set(const m_config_t *config, const m_option_t *opt, + void *src) +{ + if (opt->type->set) { + void *dst = opt->new ? (char*)config->optstruct + opt->offset : opt->p; + opt->type->set(opt, dst, src); + } +} + + + +m_config_t *m_config_new(void *optstruct, + int includefunc(m_option_t *conf, char *filename)) +{ m_config_t* config; static int initialized = 0; static m_option_type_t profile_opt_type; - static m_option_t ref_opts[] = { + static const m_option_t ref_opts[] = { { "profile", NULL, &profile_opt_type, CONF_NOSAVE, 0, 0, NULL }, { "show-profile", show_profile, CONF_TYPE_PRINT_FUNC, CONF_NOCFG, 0, 0, NULL }, { "list-options", list_options, CONF_TYPE_PRINT_FUNC, CONF_NOCFG, 0, 0, NULL }, @@ -47,7 +69,7 @@ m_config_new(void) { }; int i; - config = calloc(1,sizeof(m_config_t)); + config = talloc_zero(NULL, m_config_t); config->lvl = 1; // 0 Is the defaults if(!initialized) { initialized = 1; @@ -55,56 +77,32 @@ m_config_new(void) { profile_opt_type.parse = parse_profile; profile_opt_type.set = set_profile; } - config->self_opts = malloc(sizeof(ref_opts)); - memcpy(config->self_opts,ref_opts,sizeof(ref_opts)); - for(i = 0 ; config->self_opts[i].name ; i++) - config->self_opts[i].priv = config; - m_config_register_options(config,config->self_opts); + m_option_t *self_opts = talloc_memdup(config, ref_opts, sizeof(ref_opts)); + for (i = 0; self_opts[i].name; i++) + self_opts[i].priv = config; + m_config_register_options(config, self_opts); + if (includefunc) { + struct m_option *p = talloc_ptrtype(config, p); + *p = (struct m_option){"include", includefunc, CONF_TYPE_FUNC_PARAM, + CONF_NOSAVE, 0, 0, config}; + m_config_add_option(config, p, NULL); + } + config->optstruct = optstruct; return config; } -void -m_config_free(m_config_t* config) { - m_config_option_t *i = config->opts, *ct; - m_config_save_slot_t *sl,*st; - m_profile_t *p,*pn; - int j; - -#ifdef MP_DEBUG - assert(config != NULL); -#endif - - while(i) { - if (i->flags & M_CFG_OPT_ALIAS) - sl = NULL; - else - sl = i->slots; - while(sl) { - m_option_free(i->opt,sl->data); - st = sl->prev; - free(sl); - sl = st; - } - if(i->name != i->opt->name) - free(i->name); - ct = i->next; - free(i); - i = ct; - } - for(p = config->profiles ; p ; p = pn) { - pn = p->next; - free(p->name); - if(p->desc) free(p->desc); - for(j = 0 ; j < p->num_opts ; j++) { - free(p->opts[2*j]); - if(p->opts[2*j+1]) free(p->opts[2*j+1]); +void m_config_free(m_config_t* config) +{ + m_config_option_t *opt; + for (opt = config->opts; opt; opt = opt->next) { + if (opt->flags & M_CFG_OPT_ALIAS) + continue; + m_config_save_slot_t *sl; + for (sl = opt->slots; sl; sl = sl->prev) + m_option_free(opt->opt, sl->data); } - free(p->opts); - free(p); - } - free(config->self_opts); - free(config); + talloc_free(config); } void @@ -130,10 +128,11 @@ m_config_push(m_config_t* config) { continue; // Update the current status - m_option_save(co->opt,co->slots->data,co->opt->p); + m_option_save(config, co->opt, co->slots->data); // Allocate a new slot - slot = calloc(1,sizeof(m_config_save_slot_t) + co->opt->type->size); + slot = talloc_zero_size(co, sizeof(m_config_save_slot_t) + + co->opt->type->size); slot->lvl = config->lvl; slot->prev = co->slots; co->slots = slot; @@ -164,17 +163,17 @@ m_config_pop(m_config_t* config) { if(co->flags & M_CFG_OPT_ALIAS) continue; if(co->slots->lvl > config->lvl) - mp_msg(MSGT_CFGPARSER, MSGL_WARN,MSGTR_SaveSlotTooOld,config->lvl,co->slots->lvl); + mp_tmsg(MSGT_CFGPARSER, MSGL_WARN,"Save slot found from lvl %d is too old: %d !!!\n",config->lvl,co->slots->lvl); while(co->slots->lvl >= config->lvl) { m_option_free(co->opt,co->slots->data); slot = co->slots; co->slots = slot->prev; - free(slot); + talloc_free(slot); pop++; } if(pop) // We removed some ctx -> set the previous value - m_option_set(co->opt,co->opt->p,co->slots->data); + m_option_set(config, co->opt, co->slots->data); } config->lvl--; @@ -193,14 +192,12 @@ m_config_add_option(m_config_t *config, const m_option_t *arg, const char* prefi #endif // Allocate a new entry for this option - co = calloc(1,sizeof(m_config_option_t) + arg->type->size); + co = talloc_zero_size(config, sizeof(m_config_option_t) + arg->type->size); co->opt = arg; // Fill in the full name if(prefix && strlen(prefix) > 0) { - int l = strlen(prefix) + 1 + strlen(arg->name) + 1; - co->name = malloc(l); - sprintf(co->name,"%s:%s",prefix,arg->name); + co->name = talloc_asprintf(co, "%s:%s", prefix, arg->name); } else co->name = arg->name; @@ -214,9 +211,11 @@ m_config_add_option(m_config_t *config, const m_option_t *arg, const char* prefi } else { m_config_option_t *i; // Check if there is already an option pointing to this address - if(arg->p) { + if(arg->p || arg->new && arg->offset >= 0) { for(i = config->opts ; i ; i = i->next ) { - if(i->opt->p == arg->p) { // So we don't save the same vars more than 1 time + if (arg->new ? (i->opt->new && i->opt->offset == arg->offset) + : (!i->opt->new && i->opt->p == arg->p)) { + // So we don't save the same vars more than 1 time co->slots = i->slots; co->flags |= M_CFG_OPT_ALIAS; break; @@ -224,22 +223,28 @@ m_config_add_option(m_config_t *config, const m_option_t *arg, const char* prefi } } if(!(co->flags & M_CFG_OPT_ALIAS)) { - // Allocate a slot for the defaults - sl = calloc(1,sizeof(m_config_save_slot_t) + arg->type->size); - m_option_save(arg,sl->data,(void**)arg->p); - // Hack to avoid too much trouble with dynamically allocated data : - // We always use a dynamic version - if((arg->type->flags & M_OPT_TYPE_DYNAMIC) && arg->p && (*(void**)arg->p)) { - *(void**)arg->p = NULL; - m_option_set(arg,arg->p,sl->data); + // Allocate a slot for the defaults + sl = talloc_zero_size(co, sizeof(m_config_save_slot_t) + + arg->type->size); + m_option_save(config, arg, sl->data); + // Hack to avoid too much trouble with dynamically allocated data : + // We always use a dynamic version + if ((arg->type->flags & M_OPT_TYPE_DYNAMIC)) { + char **hackptr = arg->new ? (char*)config->optstruct + arg->offset + : arg->p; + if (hackptr && *hackptr) { + *hackptr = NULL; + m_option_set(config, arg, sl->data); + } + } + sl->lvl = 0; + sl->prev = NULL; + co->slots = talloc_zero_size(co, sizeof(m_config_save_slot_t) + + arg->type->size); + co->slots->prev = sl; + co->slots->lvl = config->lvl; + m_option_copy(co->opt, co->slots->data, sl->data); } - sl->lvl = 0; - sl->prev = NULL; - co->slots = calloc(1,sizeof(m_config_save_slot_t) + arg->type->size); - co->slots->prev = sl; - co->slots->lvl = config->lvl; - m_option_copy(co->opt,co->slots->data,sl->data); - } // !M_OPT_ALIAS } co->next = config->opts; config->opts = co; @@ -301,11 +306,11 @@ m_config_parse_option(m_config_t *config, char* arg, char* param,int set) { // Check if this option isn't forbidden in the current mode if((config->mode == M_CONFIG_FILE) && (co->opt->flags & M_OPT_NOCFG)) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR,MSGTR_InvalidCfgfileOption,arg); + mp_tmsg(MSGT_CFGPARSER, MSGL_ERR,"The %s option can't be used in a config file.\n",arg); return M_OPT_INVALID; } if((config->mode == M_COMMAND_LINE) && (co->opt->flags & M_OPT_NOCMD)) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR,MSGTR_InvalidCmdlineOption,arg); + mp_tmsg(MSGT_CFGPARSER, MSGL_ERR,"The %s option can't be used on the command line.\n",arg); return M_OPT_INVALID; } // During command line preparse set only pre-parse options @@ -333,11 +338,11 @@ m_config_parse_option(m_config_t *config, char* arg, char* param,int set) { sr = m_config_parse_option(config,n,lst[2*i+1],set); if(sr < 0){ if(sr == M_OPT_UNKNOWN){ - mp_msg(MSGT_CFGPARSER, MSGL_ERR,MSGTR_InvalidSuboption,co->name,lst[2*i]); + mp_tmsg(MSGT_CFGPARSER, MSGL_ERR,"Error: option '%s' has no suboption '%s'.\n",co->name,lst[2*i]); r = M_OPT_INVALID; } else if(sr == M_OPT_MISSING_PARAM){ - mp_msg(MSGT_CFGPARSER, MSGL_ERR,MSGTR_MissingSuboptionParameter,lst[2*i],co->name); + mp_tmsg(MSGT_CFGPARSER, MSGL_ERR,"Error: suboption '%s' of '%s' must have a parameter!\n",lst[2*i],co->name); r = M_OPT_INVALID; } else r = sr; @@ -355,7 +360,7 @@ m_config_parse_option(m_config_t *config, char* arg, char* param,int set) { return r; // Set the option if(set) { - m_option_set(co->opt,co->opt->p,co->slots->data); + m_option_set(config, co->opt, co->slots->data); co->flags |= M_CFG_OPT_SET; } @@ -374,7 +379,7 @@ m_config_check_option(m_config_t *config, char* arg, char* param) { mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Checking %s=%s\n",arg,param); r=m_config_parse_option(config,arg,param,0); if(r==M_OPT_MISSING_PARAM){ - mp_msg(MSGT_CFGPARSER, MSGL_ERR,MSGTR_MissingOptionParameter,arg); + mp_tmsg(MSGT_CFGPARSER, MSGL_ERR,"Error: option '%s' must have a parameter!\n",arg); return M_OPT_INVALID; } return r; @@ -398,20 +403,6 @@ m_config_get_option(m_config_t *config, char* arg) { return NULL; } -const void* -m_config_get_option_ptr(m_config_t *config, char* arg) { - const m_option_t* conf; - -#ifdef MP_DEBUG - assert(config != NULL); - assert(arg != NULL); -#endif - - conf = m_config_get_option(config,arg); - if(!conf) return NULL; - return conf->p; -} - void m_config_print_option_list(m_config_t *config) { char min[50],max[50]; @@ -420,7 +411,7 @@ m_config_print_option_list(m_config_t *config) { if(!config->opts) return; - mp_msg(MSGT_CFGPARSER, MSGL_INFO, MSGTR_OptionListHeader); + mp_tmsg(MSGT_CFGPARSER, MSGL_INFO, "\n Name Type Min Max Global CL Cfg\n\n"); for(co = config->opts ; co ; co = co->next) { const m_option_t* opt = co->opt; if(opt->type->flags & M_OPT_TYPE_HAS_CHILD) continue; @@ -442,7 +433,7 @@ m_config_print_option_list(m_config_t *config) { opt->flags & CONF_NOCFG ? "No" : "Yes"); count++; } - mp_msg(MSGT_CFGPARSER, MSGL_INFO, MSGTR_TotalOptions,count); + mp_tmsg(MSGT_CFGPARSER, MSGL_INFO, "\nTotal: %d options\n",count); } m_profile_t* @@ -457,8 +448,8 @@ m_profile_t* m_config_add_profile(m_config_t* config, char* name) { m_profile_t* p = m_config_get_profile(config,name); if(p) return p; - p = calloc(1,sizeof(m_profile_t)); - p->name = strdup(name); + p = talloc_zero(config, m_profile_t); + p->name = talloc_strdup(p, name); p->next = config->profiles; config->profiles = p; return p; @@ -466,8 +457,8 @@ m_config_add_profile(m_config_t* config, char* name) { void m_profile_set_desc(m_profile_t* p, char* desc) { - if(p->desc) free(p->desc); - p->desc = desc ? strdup(desc) : NULL; + talloc_free(p->desc); + p->desc = talloc_strdup(p, desc); } int @@ -475,10 +466,9 @@ m_config_set_profile_option(m_config_t* config, m_profile_t* p, char* name, char* val) { int i = m_config_check_option(config,name,val); if(i < 0) return i; - if(p->opts) p->opts = realloc(p->opts,2*(p->num_opts+2)*sizeof(char*)); - else p->opts = malloc(2*(p->num_opts+2)*sizeof(char*)); - p->opts[p->num_opts*2] = strdup(name); - p->opts[p->num_opts*2+1] = val ? strdup(val) : NULL; + p->opts = talloc_realloc(p, p->opts, char *, 2*(p->num_opts+2)); + p->opts[p->num_opts*2] = talloc_strdup(p, name); + p->opts[p->num_opts*2+1] = talloc_strdup(p, val); p->num_opts++; p->opts[p->num_opts*2] = p->opts[p->num_opts*2+1] = NULL; return 1; @@ -488,7 +478,7 @@ void m_config_set_profile(m_config_t* config, m_profile_t* p) { int i; if(config->profile_depth > MAX_PROFILE_DEPTH) { - mp_msg(MSGT_CFGPARSER, MSGL_WARN, MSGTR_ProfileInclusionTooDeep); + mp_tmsg(MSGT_CFGPARSER, MSGL_WARN, "WARNING: Profile inclusion too deep.\n"); return; } config->profile_depth++; @@ -506,10 +496,10 @@ parse_profile(const m_option_t *opt, const char *name, char *param, void *dst, i if(param && !strcmp(param,"help")) { m_profile_t* p; if(!config->profiles) { - mp_msg(MSGT_CFGPARSER, MSGL_INFO, MSGTR_NoProfileDefined); + mp_tmsg(MSGT_CFGPARSER, MSGL_INFO, "No profiles have been defined.\n"); return M_OPT_EXIT-1; } - mp_msg(MSGT_CFGPARSER, MSGL_INFO, MSGTR_AvailableProfiles); + mp_tmsg(MSGT_CFGPARSER, MSGL_INFO, "Available profiles:\n"); for(p = config->profiles ; p ; p = p->next) mp_msg(MSGT_CFGPARSER, MSGL_INFO, "\t%s\t%s\n",p->name, p->desc ? p->desc : ""); @@ -522,7 +512,7 @@ parse_profile(const m_option_t *opt, const char *name, char *param, void *dst, i if(!list || !list[0]) return M_OPT_INVALID; for(i = 0 ; list[i] ; i++) if(!m_config_get_profile(config,list[i])) { - mp_msg(MSGT_CFGPARSER, MSGL_WARN, MSGTR_UnknownProfile, + mp_tmsg(MSGT_CFGPARSER, MSGL_WARN, "Unknown profile '%s'.\n", list[i]); r = M_OPT_INVALID; } @@ -556,11 +546,11 @@ show_profile(m_option_t *opt, char* name, char *param) { int i,j; if(!param) return M_OPT_MISSING_PARAM; if(!(p = m_config_get_profile(config,param))) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, MSGTR_UnknownProfile, param); + mp_tmsg(MSGT_CFGPARSER, MSGL_ERR, "Unknown profile '%s'.\n", param); return M_OPT_EXIT-1; } if(!config->profile_depth) - mp_msg(MSGT_CFGPARSER, MSGL_INFO, MSGTR_Profile, param, + mp_tmsg(MSGT_CFGPARSER, MSGL_INFO, "Profile %s: %s\n", param, p->desc ? p->desc : ""); config->profile_depth++; for(i = 0 ; i < p->num_opts ; i++) { |