summaryrefslogtreecommitdiffstats
path: root/cfgparser.c
diff options
context:
space:
mode:
Diffstat (limited to 'cfgparser.c')
-rw-r--r--cfgparser.c1548
1 files changed, 0 insertions, 1548 deletions
diff --git a/cfgparser.c b/cfgparser.c
deleted file mode 100644
index 1872c203f9..0000000000
--- a/cfgparser.c
+++ /dev/null
@@ -1,1548 +0,0 @@
-/*
- * command line and config file parser
- * by Szabolcs Berecz <szabi@inf.elte.hu>
- * (C) 2001
- *
- * subconfig support by alex
- */
-
-//#define DEBUG
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <math.h>
-
-#include "config.h"
-
-#ifndef NEW_CONFIG
-
-#ifdef USE_SETLOCALE
-#include <locale.h>
-#endif
-
-#include "mp_msg.h"
-
-#define COMMAND_LINE 0
-#define CONFIG_FILE 1
-
-#define LIST_SEPARATOR ','
-
-#define CONFIG_GLOBAL (1<<0)
-#define CONFIG_RUNNING (1<<1)
-
-#define SET_GLOBAL(c) (c->flags |= CONFIG_GLOBAL)
-#ifdef GLOBAL_OPTIONS_ONLY
-#define UNSET_GLOBAL(c)
-#else
-#define UNSET_GLOBAL(c) (c->flags &= (!CONFIG_GLOBAL))
-#endif
-#define IS_GLOBAL(c) (c->flags & CONFIG_GLOBAL)
-#define SET_RUNNING(c) (c->flags |= CONFIG_RUNNING)
-#define IS_RUNNING(c) (c->flags & CONFIG_RUNNING)
-
-#define MAX_RECURSION_DEPTH 8
-
-#ifdef MP_DEBUG
-#include <assert.h>
-#endif
-
-#include "cfgparser.h"
-#include "playtree.h"
-
-static void m_config_list_options(m_config_t *config);
-static void m_config_error(int err,char* opt,char* val);
-
-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_PRINT_INDIRECT :
- 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 save 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[sl].opt)
- return;
- }
-
- 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 :
- if(param)
- save->param.as_pointer = strdup(param);
- case CONF_TYPE_FUNC :
- break;
- case CONF_TYPE_STRING_LIST :
- save[sl].param.as_pointer = *((char***)conf->p);
- break;
- case CONF_TYPE_POSITION :
- save[sl].param.as_off_t = *((off_t*)conf->p);
- break;
- default :
- mp_msg(MSGT_CFGPARSER,MSGL_ERR,"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_STRING_LIST :
- *((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 &&
- ((save->param.as_pointer == NULL || iter->param.as_pointer == NULL) || 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) {
- mp_msg(MSGT_CFGPARSER,MSGL_ERR,"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;
- case CONF_TYPE_POSITION :
- *((off_t*)save->opt->p) = save->param.as_off_t;
- break;
- default :
- mp_msg(MSGT_CFGPARSER,MSGL_WARN,"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
-
- 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;
- }
- SET_GLOBAL(config); // 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);
-
- if (mode != COMMAND_LINE && mode != CONFIG_FILE) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "init_conf: wrong mode!\n");
- return -1;
- }
-#endif
- config->parser_mode = mode;
- return 1;
-}
-
-static int config_is_entry_option(m_config_t *config, char *opt, char *param) {
- play_tree_t* entry = NULL;
-
-#ifdef MP_DEBUG
- assert(config->pt != NULL);
-#endif
-
- if(strcasecmp(opt,"playlist") == 0) { // We handle playlist here
- if(!param)
- return ERR_MISSING_PARAM;
- entry = parse_playlist_file(param);
- if(!entry) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Playlist parsing failed: %s\n",param);
- return 1;
- }
- }
-
- if(! IS_RUNNING(config)) {
- if(strcasecmp(opt,"vcd") == 0) {
- char* s;
- if(!param)
- return ERR_MISSING_PARAM;
- s = (char*)malloc((strlen(param) + 6 + 1)*sizeof(char));
- sprintf(s,"vcd://%s",param);
- entry = play_tree_new();
- play_tree_add_file(entry,s);
- free(s);
- } else if(strcasecmp(opt,"dvd") == 0) {
- char* s;
- if(!param)
- return ERR_MISSING_PARAM;
- s = (char*)malloc((strlen(param) + 6 + 1)*sizeof(char));
- sprintf(s,"dvd://%s",param);
- entry = play_tree_new();
- play_tree_add_file(entry,s);
- free(s);
- } else if(strcasecmp(opt,"tv") == 0) {
- char *s,*pr,*prs;
- char *ps,*pe,*channel=NULL;
- char *as;
- int on=0;
- if(!param)
- return ERR_MISSING_PARAM;
- ps = param;
- pe = strchr(param,':');
- pr = prs = (char*)malloc((strlen(param)+1)*sizeof(char));
- pr[0] = '\0';
- while(ps) {
- if(!pe)
- pe = ps + strlen(ps);
-
- as = strchr(ps,'=');
- if(as && as[1] != '\0' && pe-as > 0)
- as++;
- else
- as = NULL;
- if( !as && pe-ps == 2 && strncasecmp("on",ps,2) == 0 )
- on = 1;
- else if(as && as-ps == 8 && strncasecmp("channel",ps,6) == 0 && pe-as > 0) {
- channel = (char*)realloc(channel,(pe-as+1)*sizeof(char));
- strncpy(channel,as,pe-as);
- channel[pe-as] = '\0';
- } else if(pe-ps > 0) {
- if(prs != pr) {
- prs[0] = ':';
- prs++;
- }
- strncpy(prs,ps,pe-ps);
- prs += pe-ps;
- prs[0] = '\0';
- }
-
- if(pe[0] != '\0') {
- ps = pe+1;
- pe = strchr(ps,':');
- } else
- ps = NULL;
- }
-
- if(on) {
- int l=5;
-
- if(channel)
- l += strlen(channel);
- s = (char*) malloc((l+1)*sizeof(char));
- if(channel)
- sprintf(s,"tv://%s",channel);
- else
- sprintf(s,"tv://");
- entry = play_tree_new();
- play_tree_add_file(entry,s);
- if(strlen(pr) > 0)
- play_tree_set_param(entry,"tv",pr);
- free(s);
- }
- free(pr);
- if(channel)
- free(channel);
-
- }
- }
-
- if(entry) {
- if(config->last_entry)
- play_tree_append_entry(config->last_entry,entry);
- else
- play_tree_set_child(config->pt,entry);
- config->last_entry = entry;
- if(config->parser_mode == COMMAND_LINE)
- UNSET_GLOBAL(config);
- return 1;
- } else
- return 0;
-}
-
-
-
-static int config_read_option(m_config_t *config,config_t** conf_list, char *opt, char *param)
-{
- int i=0,nconf = 0;
- long tmp_int;
- off_t tmp_off;
- double tmp_float;
- int dummy;
- int ret = -1;
- char *endptr;
- config_t* conf=NULL;
-
-#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[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))
- goto option_found;
- if (!strcasecmp(opt, conf[i].name))
- goto option_found;
- }
- }
- if (config->parser_mode == CONFIG_FILE)
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "invalid option: %s\n",opt);
- ret = ERR_NOT_AN_OPTION;
- goto out;
- option_found :
- 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 && 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 && 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;
- }
- ret = config_is_entry_option(config,opt,param);
- if(ret != 0)
- return ret;
- else
- ret = -1;
- if(! IS_RUNNING(config) && ! IS_GLOBAL(config) &&
- ! (conf[i].flags & CONF_GLOBAL) && conf[i].type != CONF_TYPE_SUBCONFIG )
- 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 (config->parser_mode == CONFIG_FILE) {
- if (!strcasecmp(param, "yes") || /* any other language? */
- !strcasecmp(param, "ja") ||
- !strcasecmp(param, "si") ||
- !strcasecmp(param, "igen") ||
- !strcasecmp(param, "y") ||
- !strcasecmp(param, "j") ||
- !strcasecmp(param, "i") ||
- !strcmp(param, "1"))
- *((int *) conf[i].p) = conf[i].max;
- else if (!strcasecmp(param, "no") ||
- !strcasecmp(param, "nein") ||
- !strcasecmp(param, "nicht") ||
- !strcasecmp(param, "nem") ||
- !strcasecmp(param, "n") ||
- !strcmp(param, "0"))
- *((int *) conf[i].p) = conf[i].min;
- else {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "invalid parameter for flag: %s\n", param);
- ret = ERR_OUT_OF_RANGE;
- goto out;
- }
- ret = 1;
- } else { /* parser_mode == COMMAND_LINE */
- *((int *) conf[i].p) = conf[i].max;
- ret = 0;
- }
- break;
- case CONF_TYPE_INT:
- if (param == NULL)
- goto err_missing_param;
-
- tmp_int = strtol(param, &endptr, 0);
- if (*endptr) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be an integer: %s\n", param);
- ret = ERR_OUT_OF_RANGE;
- goto out;
- }
-
- if (conf[i].flags & CONF_MIN)
- if (tmp_int < conf[i].min) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be >= %d: %s\n", (int) conf[i].min, param);
- ret = ERR_OUT_OF_RANGE;
- goto out;
- }
-
- if (conf[i].flags & CONF_MAX)
- if (tmp_int > conf[i].max) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be <= %d: %s\n", (int) conf[i].max, param);
- ret = ERR_OUT_OF_RANGE;
- goto out;
- }
-
- *((int *) conf[i].p) = tmp_int;
- ret = 1;
- break;
- case CONF_TYPE_FLOAT:
- if (param == NULL)
- goto err_missing_param;
- /* <olo@altkom.com.pl> Use portable C locale for parsing floats: */
-#ifdef USE_SETLOCALE
- setlocale(LC_NUMERIC, "C");
-#endif
- tmp_float = strtod(param, &endptr);
-
- switch(*endptr) {
- case ':':
- case '/':
- tmp_float /= strtod(endptr+1, &endptr);
- default:
- break;
- }
-#ifdef USE_SETLOCALE
- setlocale(LC_NUMERIC, "");
-#endif
-
- if (*endptr) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be a floating point number"
- " or a ratio (numerator[:/]denominator): %s\n", param);
- ret = ERR_MISSING_PARAM;
- goto out;
- }
-
- if (conf[i].flags & CONF_MIN)
- if (tmp_float < conf[i].min) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be >= %f: %s\n", conf[i].min, param);
- ret = ERR_OUT_OF_RANGE;
- goto out;
- }
-
- if (conf[i].flags & CONF_MAX)
- if (tmp_float > conf[i].max) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be <= %f: %s\n", conf[i].max, param);
- ret = ERR_OUT_OF_RANGE;
- goto out;
- }
-
- *((float *) conf[i].p) = tmp_float;
- ret = 1;
- break;
- case CONF_TYPE_STRING:
- if (param == NULL)
- goto err_missing_param;
-
- if (conf[i].flags & CONF_MIN)
- if (strlen(param) < conf[i].min) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be >= %d chars: %s\n",
- (int) conf[i].min, param);
- ret = ERR_OUT_OF_RANGE;
- goto out;
- }
-
- if (conf[i].flags & CONF_MAX)
- if (strlen(param) > conf[i].max) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be <= %d chars: %s\n",
- (int) conf[i].max, param);
- ret = ERR_OUT_OF_RANGE;
- goto out;
- }
- *((char **) conf[i].p) = strdup(param);
- ret = 1;
- break;
- case CONF_TYPE_STRING_LIST:
- if (param == NULL)
- goto err_missing_param;
- else {
- int n = 0,len;
- char *ptr = param, *last_ptr, **res;
-
- while(ptr[0] != '\0') {
- last_ptr = ptr;
- ptr = strchr(ptr,LIST_SEPARATOR);
- if(!ptr) {
-// if(strlen(last_ptr) > 0)
- n++;
- break;
- }
- ptr++;
- n++;
- }
- if(n == 0)
- goto err_missing_param;
- else if( (conf[i].flags & CONF_MIN && n < conf[i].min) ||
- (conf[i].flags & CONF_MAX && n > conf[i].max) ) {
- ret = ERR_OUT_OF_RANGE;
- goto out;
- }
- ret = 1;
- res = malloc((n+2)*sizeof(char*));
- ptr = param;
- n = 0;
-// while(ptr[0] != '\0') {
- while(1) {
- last_ptr = ptr;
- ptr = strchr(ptr,LIST_SEPARATOR);
- if(!ptr) {
- //if(strlen(last_ptr) > 0)
- {
- res[n] = strdup(last_ptr);
- n++;
- }
- break;
- }
- len = ptr - last_ptr;
- res[n] = (char*)malloc(len + 1);
- if(len) strncpy(res[n],last_ptr,len);
- res[n][len] = '\0';
- ptr++;
- n++;
- }
- res[n] = NULL;
- *((char ***) conf[i].p) = res;
- }
- break;
- case CONF_TYPE_FUNC_PARAM:
- if (param == NULL)
- goto err_missing_param;
- if ((((cfg_func_param_t) conf[i].p)(conf + i, param)) < 0) {
- ret = ERR_FUNC_ERR;
- goto out;
- }
- ret = 1;
- break;
- case CONF_TYPE_FUNC_FULL:
- if (param!=NULL && param[0]=='-'){
- 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)(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)(conf + i)) < 0) {
- ret = ERR_FUNC_ERR;
- goto out;
- }
- ret = 0;
- break;
- case CONF_TYPE_SUBCONFIG:
- {
- char *subparam;
- char *subopt;
- int subconf_optnr;
- config_t *subconf;
- config_t *sublist[] = { NULL , NULL };
- char *token;
- char *p;
-
- if (param == NULL)
- goto err_missing_param;
-
- subparam = malloc(strlen(param)+1);
- subopt = malloc(strlen(param)+1);
- p = strdup(param); // In case that param is a static string (cf man strtok)
-
- subconf = conf[i].p;
- sublist[0] = subconf;
- for (subconf_optnr = 0; subconf[subconf_optnr].name != NULL; subconf_optnr++)
- /* NOTHING */;
- config->sub_conf = opt;
- token = strtok(p, (char *)&(":"));
- while(token)
- {
- int sscanf_ret;
- /* clear out */
- subopt[0] = subparam[0] = 0;
-
- sscanf_ret = sscanf(token, "%[^=]=%[^:]", 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);
- switch(sscanf_ret)
- {
- case 1:
- subparam[0] = 0;
- case 2:
- 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);
- goto out;
- }
- break;
- default:
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid subconfig argument! ('%s')\n", token);
- ret = ERR_NOT_AN_OPTION;
- goto out;
- }
- token = strtok(NULL, (char *)&(":"));
- }
- config->sub_conf = NULL;
- free(subparam);
- free(subopt);
- free(p);
- ret = 1;
- break;
- }
- case CONF_TYPE_PRINT:
- mp_msg(MSGT_CFGPARSER, MSGL_INFO, "%s", (char *) conf[i].p);
- exit(1);
- case CONF_TYPE_PRINT_INDIRECT:
- mp_msg(MSGT_CFGPARSER, MSGL_INFO, "%s", *(char **) conf[i].p);
- exit(1);
- case CONF_TYPE_POSITION:
- if (param == NULL)
- goto err_missing_param;
-
- if (sscanf(param, sizeof(off_t) == sizeof(int) ?
- "%d%c" : "%lld%c", &tmp_off, (char *)&dummy) != 1) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be an integer: %s\n", param);
- ret = ERR_OUT_OF_RANGE;
- goto out;
- }
-
- if (conf[i].flags & CONF_MIN)
- if (tmp_off < conf[i].min) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- (sizeof(off_t) == sizeof(int) ?
- "parameter must be >= %d: %s\n" :
- "parameter must be >= %lld: %s\n"),
- (off_t) conf[i].min, param);
- ret = ERR_OUT_OF_RANGE;
- goto out;
- }
-
- if (conf[i].flags & CONF_MAX)
- if (tmp_off > conf[i].max) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- (sizeof(off_t) == sizeof(int) ?
- "parameter must be <= %d: %s\n" :
- "parameter must be <= %lld: %s\n"),
- (off_t) conf[i].max, param);
- ret = ERR_OUT_OF_RANGE;
- goto out;
- }
-
- *((off_t *) conf[i].p) = tmp_off;
- ret = 1;
- break;
- default:
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Unknown config type specified in conf-mplayer.h!\n");
- break;
- }
-out:
- if(ret >= 0 && ! IS_RUNNING(config) && ! IS_GLOBAL(config) && ! (conf[i].flags & CONF_GLOBAL) && conf[i].type != CONF_TYPE_SUBCONFIG ) {
- play_tree_t* dest = config->last_entry ? config->last_entry : config->last_parent;
- char* o;
-#ifdef MP_DEBUG
- assert(dest != NULL);
-#endif
- if(config->sub_conf) {
- o = (char*)malloc((strlen(config->sub_conf) + 1 + strlen(opt) + 1)*sizeof(char));
- sprintf(o,"%s:%s",config->sub_conf,opt);
- } else
- o =strdup(opt);
-
- if(ret == 0)
- play_tree_set_param(dest,o,NULL);
- else if(ret > 0)
- play_tree_set_param(dest,o,param);
- free(o);
- m_config_pop(config);
- }
- return ret;
-err_missing_param:
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "missing parameter for option: %s\n", opt);
- ret = ERR_MISSING_PARAM;
- goto out;
-}
-
-int m_config_set_option(m_config_t *config,char *opt, char *param) {
- char *e;
-#ifdef MP_DEBUG
- assert(config != NULL);
- assert(config->opt_list != NULL);
- assert(opt != NULL);
-#endif
- mp_msg(MSGT_CFGPARSER, MSGL_DBG2, "Setting option %s=%s\n",opt,param);
- e = strchr(opt,':');
- if(e && e[1] != '\0') {
- int ret;
- config_t* opt_list[] = { NULL, NULL };
- char* s = (char*)malloc((e-opt+1)*sizeof(char));
- strncpy(s,opt,e-opt);
- s[e-opt] = '\0';
- opt_list[0] = m_config_get_option_ptr(config,s);
- if(!opt_list[0]) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,"m_config_set_option %s=%s : no %s subconfig\n",opt,param,s);
- free(s);
- return ERR_NOT_AN_OPTION;
- }
- e++;
- s = (char*)realloc(s,strlen(e) + 1);
- strcpy(s,e);
- ret = config_read_option(config,opt_list,s,param);
- free(s);
- return ret;
- }
-
- 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 mp_msg(MSGT_CFGPARSER,MSGL_INFO,"%s(%d): ", conffile, line_num)
-#define MAX_LINE_LEN 10000
-#define MAX_OPT_LEN 1000
-#define MAX_PARAM_LEN 1000
- FILE *fp;
- char *line;
- char opt[MAX_OPT_LEN + 1];
- char param[MAX_PARAM_LEN + 1];
- char c; /* for the "" and '' check */
- int tmp;
- int line_num = 0;
- int line_pos; /* line pos */
- int opt_pos; /* opt pos */
- int param_pos; /* param pos */
- int ret = 1;
- int errors = 0;
-
-#ifdef MP_DEBUG
- assert(config != NULL);
- // assert(conf_list != NULL);
-#endif
- if (++config->recursion_depth > 1)
- mp_msg(MSGT_CFGPARSER,MSGL_INFO,"Reading config file: %s", conffile);
-
- if (config->recursion_depth > MAX_RECURSION_DEPTH) {
- mp_msg(MSGT_CFGPARSER,MSGL_ERR,": too deep 'include'. check your configfiles\n");
- ret = -1;
- goto out;
- }
-
- if (init_conf(config, CONFIG_FILE) == -1) {
- ret = -1;
- goto out;
- }
-
- if ((line = (char *) malloc(MAX_LINE_LEN + 1)) == NULL) {
- mp_msg(MSGT_CFGPARSER,MSGL_FATAL,"\ncan't get memory for 'line': %s", strerror(errno));
- ret = -1;
- goto out;
- }
-
- if ((fp = fopen(conffile, "r")) == NULL) {
- if (config->recursion_depth > 1)
- mp_msg(MSGT_CFGPARSER,MSGL_ERR,": %s\n", strerror(errno));
- free(line);
- ret = 0;
- goto out;
- }
- if (config->recursion_depth > 1)
- mp_msg(MSGT_CFGPARSER,MSGL_INFO,"\n");
-
- while (fgets(line, MAX_LINE_LEN, fp)) {
- if (errors >= 16) {
- mp_msg(MSGT_CFGPARSER,MSGL_FATAL,"too many errors\n");
- goto out;
- }
-
- line_num++;
- line_pos = 0;
-
- /* skip whitespaces */
- while (isspace(line[line_pos]))
- ++line_pos;
-
- /* EOL / comment */
- if (line[line_pos] == '\0' || line[line_pos] == '#')
- continue;
-
- /* read option. */
- for (opt_pos = 0; isprint(line[line_pos]) &&
- line[line_pos] != ' ' &&
- line[line_pos] != '#' &&
- line[line_pos] != '='; /* NOTHING */) {
- opt[opt_pos++] = line[line_pos++];
- if (opt_pos >= MAX_OPT_LEN) {
- PRINT_LINENUM;
- mp_msg(MSGT_CFGPARSER,MSGL_ERR,"too long option\n");
- errors++;
- ret = -1;
- goto nextline;
- }
- }
- if (opt_pos == 0) {
- PRINT_LINENUM;
- mp_msg(MSGT_CFGPARSER,MSGL_ERR,"parse error\n");
- ret = -1;
- errors++;
- continue;
- }
- opt[opt_pos] = '\0';
-
-#ifdef MP_DEBUG
- PRINT_LINENUM;
- mp_msg(MSGT_CFGPARSER,MSGL_INFO,"option: %s\n", opt);
-#endif
-
- /* skip whitespaces */
- while (isspace(line[line_pos]))
- ++line_pos;
-
- /* check '=' */
- if (line[line_pos++] != '=') {
- PRINT_LINENUM;
- mp_msg(MSGT_CFGPARSER,MSGL_ERR,"option without parameter\n");
- ret = -1;
- errors++;
- continue;
- }
-
- /* whitespaces... */
- while (isspace(line[line_pos]))
- ++line_pos;
-
- /* read the parameter */
- if (line[line_pos] == '"' || line[line_pos] == '\'') {
- c = line[line_pos];
- ++line_pos;
- for (param_pos = 0; line[line_pos] != c; /* NOTHING */) {
- param[param_pos++] = line[line_pos++];
- if (param_pos >= MAX_PARAM_LEN) {
- PRINT_LINENUM;
- mp_msg(MSGT_CFGPARSER,MSGL_ERR,"too long parameter\n");
- ret = -1;
- errors++;
- goto nextline;
- }
- }
- line_pos++; /* skip the closing " or ' */
- } else {
- for (param_pos = 0; isprint(line[line_pos]) && !isspace(line[line_pos])
- && line[line_pos] != '#'; /* NOTHING */) {
- param[param_pos++] = line[line_pos++];
- if (param_pos >= MAX_PARAM_LEN) {
- PRINT_LINENUM;
- mp_msg(MSGT_CFGPARSER,MSGL_ERR,"too long parameter\n");
- ret = -1;
- errors++;
- goto nextline;
- }
- }
- }
- param[param_pos] = '\0';
-
- /* did we read a parameter? */
- if (param_pos == 0) {
- PRINT_LINENUM;
- mp_msg(MSGT_CFGPARSER,MSGL_ERR,"option without parameter\n");
- ret = -1;
- errors++;
- continue;
- }
-
-#ifdef MP_DEBUG
- PRINT_LINENUM;
- mp_msg(MSGT_CFGPARSER,MSGL_INFO,"parameter: %s\n", param);
-#endif
-
- /* now, check if we have some more chars on the line */
- /* whitespace... */
- while (isspace(line[line_pos]))
- ++line_pos;
-
- /* EOL / comment */
- if (line[line_pos] != '\0' && line[line_pos] != '#') {
- PRINT_LINENUM;
- mp_msg(MSGT_CFGPARSER,MSGL_WARN,"extra characters on line: %s\n", line+line_pos);
- ret = -1;
- }
-
- tmp = m_config_set_option(config, opt, param);
- switch (tmp) {
- case ERR_NOT_AN_OPTION:
- case ERR_MISSING_PARAM:
- case ERR_OUT_OF_RANGE:
- case ERR_FUNC_ERR:
- PRINT_LINENUM;
- mp_msg(MSGT_CFGPARSER,MSGL_INFO,"%s\n", opt);
- ret = -1;
- errors++;
- continue;
- /* break */
- }
-nextline:
- ;
- }
-
- free(line);
- fclose(fp);
-out:
- --config->recursion_depth;
- return ret;
-}
-
-int m_config_parse_command_line(m_config_t *config, int argc, char **argv)
-{
- int i;
- int tmp;
- char *opt;
- int no_more_opts = 0;
-
-#ifdef MP_DEBUG
- assert(config != NULL);
- assert(config->pt != NULL);
- assert(argv != NULL);
- assert(argc >= 1);
-#endif
-
- 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 */
- ++config->recursion_depth;
-
- for (i = 1; i < argc; i++) {
- //next:
- opt = argv[i];
- /* check for -- (no more options id.) except --help! */
- if ((*opt == '-') && (*(opt+1) == '-') && (*(opt+2) != 'h'))
- {
- no_more_opts = 1;
- if (i+1 >= argc)
- {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "You added '--' but no filenames presented!\n");
- goto err_out;
- }
- continue;
- }
- if((opt[0] == '{') && (opt[1] == '\0'))
- {
- play_tree_t* entry = play_tree_new();
- UNSET_GLOBAL(config);
- 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 */
- {
- /* remove trailing '-' */
- opt++;
-
- mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "this_opt = option: %s\n", opt);
- // We handle here some specific option
- if(strcasecmp(opt,"list-options") == 0) {
- m_config_list_options(config);
- exit(1);
- // Loop option when it apply to a group
- } else if(strcasecmp(opt,"loop") == 0 &&
- (! config->last_entry || config->last_entry->child) ) {
- int l;
- char* end;
- l = strtol(argv[i+1],&end,0);
- if(!end)
- tmp = ERR_OUT_OF_RANGE;
- else {
- play_tree_t* pt = config->last_entry ? config->last_entry : config->last_parent;
- l = l <= 0 ? -1 : l;
- pt->loop = l;
- tmp = 1;
- }
- } else // All normal options
- tmp = m_config_set_option(config, opt, argv[i + 1]);
-
- switch (tmp) {
- case ERR_NOT_AN_OPTION:
- case ERR_MISSING_PARAM:
- case ERR_OUT_OF_RANGE:
- case ERR_FUNC_ERR:
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Error: ");
- m_config_error(tmp,opt,argv[i+1]);
- goto err_out;
- default:
- i += tmp;
- break;
- }
- }
- else /* filename */
- {