diff options
author | albeu <albeu@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2002-11-12 01:56:42 +0000 |
---|---|---|
committer | albeu <albeu@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2002-11-12 01:56:42 +0000 |
commit | 126725660d4bebbab8570221c5681dc01d98fe86 (patch) | |
tree | 3ebdca9acf6fae38bfdba5b4159fbd16177da828 | |
parent | 0f622e2d6fe735d727b9d8fd12cea22e03fd954b (diff) | |
download | mpv-126725660d4bebbab8570221c5681dc01d98fe86.tar.bz2 mpv-126725660d4bebbab8570221c5681dc01d98fe86.tar.xz |
New config system + cleanup of header inter dependency
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@8165 b3059339-0415-0410-9bf9-f77b7e298cf2
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | asxparser.c | 3 | ||||
-rw-r--r-- | asxparser.h | 1 | ||||
-rw-r--r-- | cfg-mplayer.h | 4 | ||||
-rw-r--r-- | cfgparser.c | 5 | ||||
-rw-r--r-- | cfgparser.h | 21 | ||||
-rwxr-xr-x | configure | 16 | ||||
-rw-r--r-- | input/input.c | 1 | ||||
-rw-r--r-- | libmpdemux/stream.h | 2 | ||||
-rw-r--r-- | libvo/vo_aa.c | 4 | ||||
-rw-r--r-- | m_config.c | 347 | ||||
-rw-r--r-- | m_config.h | 87 | ||||
-rw-r--r-- | m_option.c | 1008 | ||||
-rw-r--r-- | m_option.h | 222 | ||||
-rw-r--r-- | mencoder.c | 32 | ||||
-rw-r--r-- | mplayer.c | 22 | ||||
-rw-r--r-- | parser-cfg.c | 211 | ||||
-rw-r--r-- | parser-mecmd.c | 153 | ||||
-rw-r--r-- | parser-mecmd.h | 18 | ||||
-rw-r--r-- | parser-mpcmd.c | 284 | ||||
-rw-r--r-- | playtree.c | 1 | ||||
-rw-r--r-- | playtree.h | 11 | ||||
-rw-r--r-- | playtreeparser.c | 1 | ||||
-rw-r--r-- | playtreeparser.h | 7 |
24 files changed, 2441 insertions, 26 deletions
@@ -26,9 +26,9 @@ endif # a BSD compatible 'install' program INSTALL = install -SRCS_COMMON = cpudetect.c codec-cfg.c cfgparser.c my_profile.c spudec.c playtree.c playtreeparser.c asxparser.c vobsub.c subreader.c sub_cc.c find_sub.c -SRCS_MENCODER = mencoder.c mp_msg-mencoder.c $(SRCS_COMMON) libao2/afmt.c divx4_vbr.c libvo/aclib.c libvo/osd.c libvo/sub.c libvo/font_load.c libvo/font_load_ft.c xvid_vbr.c -SRCS_MPLAYER = mplayer.c mp_msg.c $(SRCS_COMMON) mixer.c +SRCS_COMMON = cpudetect.c codec-cfg.c cfgparser.c my_profile.c spudec.c playtree.c playtreeparser.c asxparser.c vobsub.c subreader.c sub_cc.c find_sub.c m_config.c m_option.c parser-cfg.c +SRCS_MENCODER = mencoder.c mp_msg-mencoder.c $(SRCS_COMMON) libao2/afmt.c divx4_vbr.c libvo/aclib.c libvo/osd.c libvo/sub.c libvo/font_load.c libvo/font_load_ft.c xvid_vbr.c parser-mecmd.c +SRCS_MPLAYER = mplayer.c mp_msg.c $(SRCS_COMMON) mixer.c parser-mpcmd.c ifeq ($(UNRARLIB),yes) SRCS_COMMON += unrarlib.c diff --git a/asxparser.c b/asxparser.c index cdc503b9d4..2b1c175ab1 100644 --- a/asxparser.c +++ b/asxparser.c @@ -1,3 +1,4 @@ +#include "config.h" #include <stdlib.h> #include <stdio.h> @@ -5,7 +6,9 @@ #include <string.h> #include <unistd.h> +#include "playtree.h" #include "playtreeparser.h" +#include "libmpdemux/stream.h" #include "asxparser.h" #include "mp_msg.h" #include "cfgparser.h" diff --git a/asxparser.h b/asxparser.h index 91b2f7eb88..256f10239c 100644 --- a/asxparser.h +++ b/asxparser.h @@ -1,5 +1,4 @@ -#include "playtree.h" typedef struct _ASX_Parser_t ASX_Parser_t; diff --git a/cfg-mplayer.h b/cfg-mplayer.h index 60d18cdd22..541ffe3aff 100644 --- a/cfg-mplayer.h +++ b/cfg-mplayer.h @@ -252,8 +252,8 @@ static config_t mplayer_opts[]={ {"x", &opt_screen_size_x, CONF_TYPE_INT, CONF_RANGE, 0, 4096, NULL}, {"y", &opt_screen_size_y, CONF_TYPE_INT, CONF_RANGE, 0, 4096, NULL}, // set screen dimensions (when not detectable or virtual!=visible) - {"screenw", &vo_screenwidth, CONF_TYPE_INT, CONF_RANGE, 0, 4096, NULL}, - {"screenh", &vo_screenheight, CONF_TYPE_INT, CONF_RANGE, 0, 4096, NULL}, + {"screenw", &vo_screenwidth, CONF_TYPE_INT, CONF_RANGE|CONF_OLD, 0, 4096, NULL}, + {"screenh", &vo_screenheight, CONF_TYPE_INT, CONF_RANGE|CONF_OLD, 0, 4096, NULL}, // Geometry string {"geometry", &vo_geometry, CONF_TYPE_STRING, 0, 0, 0, NULL}, // set aspect ratio of monitor - usefull for 16:9 TVout diff --git a/cfgparser.c b/cfgparser.c index 38bb5e8a7a..1dde14ed89 100644 --- a/cfgparser.c +++ b/cfgparser.c @@ -19,6 +19,8 @@ #include "config.h" +#ifndef NEW_CONFIG + #ifdef USE_SETLOCALE #include <locale.h> #endif @@ -50,6 +52,7 @@ #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); @@ -1536,3 +1539,5 @@ static void m_config_error(int err,char* opt,char* val) { break; } } + +#endif diff --git a/cfgparser.h b/cfgparser.h index c2deb3af2e..2e627246d3 100644 --- a/cfgparser.h +++ b/cfgparser.h @@ -2,6 +2,14 @@ * command line and config file parser */ +#ifdef NEW_CONFIG +#ifdef MP_DEBUG +#warning "NEW_CONFIG defined but still using the old cfgparser.h" +#endif +#include "m_config.h" +#include "m_option.h" +#else + #ifndef __CONFIG_H #define __CONFIG_H @@ -32,13 +40,14 @@ #define CONF_NOCMD (1<<3) #define CONF_GLOBAL (1<<4) #define CONF_NOSAVE (1<<5) +#define CONF_OLD (1<<6) typedef struct config config_t; typedef struct m_config m_config_t; typedef struct config_save config_save_t; -#include "playtree.h" +struct play_tree; typedef void (*cfg_default_func_t)(config_t *, char*); @@ -62,9 +71,9 @@ struct m_config { int parser_mode; /* COMMAND_LINE or CONFIG_FILE */ int flags; char* sub_conf; // When we save a subconfig - play_tree_t* pt; // play tree we use for playlist option, etc - play_tree_t* last_entry; // last added entry - play_tree_t* last_parent; // if last_entry is NULL we must create child of this + struct play_tree* pt; // play tree we use for playlist option, etc + struct play_tree* last_entry; // last added entry + struct play_tree* last_parent; // if last_entry is NULL we must create child of this int recursion_depth; }; @@ -97,7 +106,7 @@ int m_config_parse_config_file(m_config_t *config, char *conffile); */ int m_config_parse_command_line(m_config_t* config, int argc, char **argv); -m_config_t* m_config_new(play_tree_t* pt); +m_config_t* m_config_new(struct play_tree* pt); void m_config_free(m_config_t* config); @@ -190,3 +199,5 @@ float m_config_get_float (m_config_t *config, char* arg,int* err_ret); #endif /* __CONFIG_H */ + +#endif /* NEW_CONFIG */ @@ -151,6 +151,7 @@ Optional features: --disable-cdparanoia Disable cdparanoia support [autodetect] --enable-freetype Enable freetype2 font rendering support [disabled] --disable-unrarlib Disable Unique RAR File Library [enabled] + --enable-new-conf Enable new config stuff [disabled] Codecs: --enable-gif enable gif89a output support [autodetect] @@ -1013,6 +1014,7 @@ _cdparanoia=auto _big_endian=auto _freetype=no _shared_pp=no +_new_conf=no for ac_option do case "$ac_option" in @@ -1193,6 +1195,9 @@ for ac_option do --enable-shared-pp) _shared_pp=yes ;; --disable-shared-pp) _shared_pp=no ;; + --enable-new-conf) _new_conf=yes ;; + --disable-new-conf) _new_conf=no ;; + --language=*) LINGUAS=`echo $ac_option | cut -d '=' -f 2` ;; @@ -4235,6 +4240,14 @@ else fi echores "$_shared_pp" +echocheck "New config" +if test "$_new_conf" = yes ; then + _def_new_conf='#define NEW_CONFIG 1' +else + _def_new_conf='#undef NEW_CONFIG' +fi +echores "$_new_conf" + # --------------- GUI specific tests begin ------------------- echocheck "GUI" echo "$_gui" @@ -4969,6 +4982,9 @@ $_def_vidix /* enables / disables new input joystick support */ $_def_joystick +/* enables / disables new config */ +$_def_new_conf + /* Extension defines */ $_def_3dnow // only define if you have 3DNOW (AMD k6-2, AMD Athlon, iDT WinChip, etc.) $_def_3dnowex // only define if you have 3DNOWEX (AMD Athlon, etc.) diff --git a/input/input.c b/input/input.c index 5b4d408a0d..4277d607b3 100644 --- a/input/input.c +++ b/input/input.c @@ -24,6 +24,7 @@ #include "../linux/getch2.h" #include "../linux/keycodes.h" #include "../linux/timer.h" +#include "../mp_msg.h" #include "../cfgparser.h" #include "joystick.h" diff --git a/libmpdemux/stream.h b/libmpdemux/stream.h index b051df2875..8df08fad50 100644 --- a/libmpdemux/stream.h +++ b/libmpdemux/stream.h @@ -31,7 +31,7 @@ int vcd_seek_to_track(int fd,int track); void vcd_read_toc(int fd); -typedef struct { +typedef struct stream_st { int fd; // file descriptor, see man open(2) int type; // see STREAMTYPE_* unsigned int buf_pos,buf_len; diff --git a/libvo/vo_aa.c b/libvo/vo_aa.c index d64446a80f..78c5bb2f20 100644 --- a/libvo/vo_aa.c +++ b/libvo/vo_aa.c @@ -510,7 +510,7 @@ uninit(void) { if (strstr(c->driver->name,"Curses") || strstr(c->driver->name,"Linux")){ freopen("/dev/tty", "w", stderr); - m_config_set_flag(mconfig,"quiet",0); /* enable mplayer outputs */ + m_config_set_option(mconfig,"quiet",NULL); /* enable mplayer outputs */ } #ifdef USE_OSD if(vo_font_save) { @@ -729,7 +729,7 @@ static uint32_t preinit(const char *arg) if ((strstr(c->driver->name,"Curses")) || (strstr(c->driver->name,"Linux"))){ freopen("/dev/null", "w", stderr); - m_config_set_flag(mconfig,"quiet",0); /* disable mplayer outputs */ + m_config_set_option(mconfig,"noquiet",NULL); /* disable mplayer outputs */ /* disable console blanking */ printf("\033[9;0]"); } diff --git a/m_config.c b/m_config.c new file mode 100644 index 0000000000..b32d60c699 --- /dev/null +++ b/m_config.c @@ -0,0 +1,347 @@ + +#include "config.h" + +#ifdef NEW_CONFIG + +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#ifdef MP_DEBUG +#include <assert.h> +#endif + + +#include "m_config.h" +#include "m_option.h" +#include "mp_msg.h" + +m_config_t* +m_config_new(void) { + m_config_t* config; + + config = (m_config_t*)calloc(1,sizeof(m_config_t)); + config->lvl = 1; // 0 Is the defaults + 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; + +#ifdef MP_DEBUG + assert(config != NULL); +#endif + + while(i) { + 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); + ct = i; + } + free(config); +} + +void +m_config_push(m_config_t* config) { + m_config_option_t *co; + m_config_save_slot_t *slot; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->lvl > 0); +#endif + + config->lvl++; + + for(co = config->opts ; co ; co = co->next ) { + if(co->opt->type->flags & M_OPT_TYPE_HAS_CHILD) + continue; + if(co->opt->flags & (M_OPT_GLOBAL|M_OPT_NOSAVE)) + continue; + if((co->opt->flags & M_OPT_OLD) && !co->flags) + continue; + + // Update the current status + m_option_save(co->opt,co->slots->data,co->opt->p); + + // Allocate a new slot + slot = (m_config_save_slot_t*)calloc(1,sizeof(m_config_save_slot_t) + co->opt->type->size); + slot->lvl = config->lvl; + slot->prev = co->slots; + co->slots = slot; + m_option_copy(co->opt,co->slots->data,co->slots->prev->data); + // Reset our flags + co->flags=0; + } + + mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Config pushed level is now %d\n",config->lvl); +} + +void +m_config_pop(m_config_t* config) { + m_config_option_t *co; + m_config_save_slot_t *slot; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->lvl > 1); +#endif + + for(co = config->opts ; co ; co = co->next ) { + int pop = 0; + if(co->opt->type->flags & M_OPT_TYPE_HAS_CHILD) + continue; + if(co->opt->flags & (M_OPT_GLOBAL|M_OPT_NOSAVE)) + continue; + if(co->slots->lvl > config->lvl) + mp_msg(MSGT_CFGPARSER, MSGL_WARN,"Too old save slot found from lvl %d : %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); + pop++; + } + if(pop) // We removed some ctx -> set the previous value + m_option_set(co->opt,co->opt->p,co->slots->data); + } + + config->lvl--; + mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Config poped level=%d\n",config->lvl); +} + +static void +m_config_add_option(m_config_t *config, m_option_t *arg, char* prefix) { + m_config_option_t *co; + m_config_save_slot_t* sl; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->lvl > 0); + assert(arg != NULL); +#endif + + // Allocate a new entry for this option + co = (m_config_option_t*)calloc(1,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 = (char*) malloc(l); + sprintf(co->name,"%s:%s",prefix,arg->name); + } else + co->name = arg->name; + + // Option with childs -> add them + if(arg->type->flags & M_OPT_TYPE_HAS_CHILD) { + m_option_t *ol = arg->p; + int i; + for(i = 0 ; ol[i].name != NULL ; i++) + m_config_add_option(config,&ol[i], co->name); + } else { + // Allocate a slot for the defaults + sl = (m_config_save_slot_t*)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 dynamicly 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); + } + sl->lvl = 0; + co->slots = (m_config_save_slot_t*)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); + } + co->next = config->opts; + config->opts = co; +} + +int +m_config_register_options(m_config_t *config, m_option_t *args) { + int i; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->lvl > 0); + assert(args != NULL); +#endif + + for(i = 0 ; args[i].name != NULL ; i++) + m_config_add_option(config,&args[i],NULL); + + return 1; +} + +static m_config_option_t* +m_config_get_co(m_config_t *config, char* arg) { + m_config_option_t *co; + + for(co = config->opts ; co ; co = co->next ) { + int l = strlen(co->name) - 1; + if((co->opt->type->flags & M_OPT_TYPE_ALLOW_WILDCARD) && + (co->name[l] == '*')) { + if(strncasecmp(co->name,arg,l) == 0) + return co; + } else if(strcasecmp(co->name,arg) == 0) + return co; + } + return NULL; +} + +static int +m_config_parse_option(m_config_t *config, char* arg, char* param,int set) { + m_config_option_t *co; + int r = 0; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->lvl > 0); + assert(arg != NULL); +#endif + + co = m_config_get_co(config,arg); + if(!co) + return M_OPT_UNKNOW; + +#ifdef MP_DEBUG + // This is the only mandatory function + assert(co->opt->type->parse); +#endif + + // Check if this option isn't forbiden in the current mode + if((config->mode == M_CONFIG_FILE) && (co->opt->flags & M_OPT_NOCFG)) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR,"The %s option can't be used in a config file\n",config->lvl); + return M_OPT_INVALID; + } + if((config->mode == M_COMMAND_LINE) && (co->opt->flags & M_OPT_NOCMD)) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR,"The %s option can't be used on the command line\n",config->lvl); + return M_OPT_INVALID; + } + + // Option with childs are a bit different to parse + if(co->opt->type->flags & M_OPT_TYPE_HAS_CHILD) { + char** lst = NULL; + int i,sr; + // Parse the child options + r = m_option_parse(co->opt,arg,param,&lst,config->mode); + // Set them now + for(i = 0 ; lst && lst[2*i] ; i++) { + int l = strlen(co->name) + 1 + strlen(lst[2*i]) + 1; + if(r >= 0) { + // Build the full name + char n[l]; + sprintf(n,"%s:%s",co->name,lst[2*i]); + sr = m_config_parse_option(config,n,lst[2*i+1],set); + if(sr < 0) r = sr; + } + free(lst[2*i]); + free(lst[2*i+1]); + } + if(lst) free(lst); + } else + r = m_option_parse(co->opt,arg,param,set ? co->slots->data : NULL,config->mode); + + // Parsing failed ? + if(r < 0) + return r; + // Set the option + if(set) { + m_option_set(co->opt,co->opt->p,co->slots->data); + co->flags = 1; + } + + return r; +} + +int +m_config_set_option(m_config_t *config, char* arg, char* param) { + mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Setting %s=%s\n",arg,param); + return m_config_parse_option(config,arg,param,1); +} + +int +m_config_check_option(m_config_t *config, char* arg, char* param) { + mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Checking %s=%s\n",arg,param); + return m_config_parse_option(config,arg,param,0); +} + + +m_option_t* +m_config_get_option(m_config_t *config, char* arg) { + m_config_option_t *co; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->lvl > 0); + assert(arg != NULL); +#endif + + co = m_config_get_co(config,arg); + if(co) + return co->opt; + else + return NULL; +} + +void* +m_config_get_option_ptr(m_config_t *config, char* arg) { + 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]; + m_config_option_t* co; + int count = 0; + + if(!config->opts) return; + + printf("\n Name Type Min Max Global CL Cfg\n\n"); + for(co = config->opts ; co ; co = co->next) { + m_option_t* opt = co->opt; + if(opt->type->flags & M_OPT_TYPE_HAS_CHILD) continue; + if(opt->flags & M_OPT_MIN) + sprintf(min,"%-8.0f",opt->min); + else + strcpy(min,"No"); + if(opt->flags & M_OPT_MAX) + sprintf(max,"%-8.0f",opt->max); + else + strcpy(max,"No"); + printf(" %-20.20s %-15.15s %-10.10s %-10.10s %-3.3s %-3.3s %-3.3s\n", + co->name, + co->opt->type->name, + min, + max, + opt->flags & CONF_GLOBAL ? "Yes" : "No", + opt->flags & CONF_NOCMD ? "No" : "Yes", + opt->flags & CONF_NOCFG ? "No" : "Yes"); + count++; + } + printf("\nTotal: %d options\n",count); +} + +#endif // NEW_CONFIG diff --git a/m_config.h b/m_config.h new file mode 100644 index 0000000000..30375d12d3 --- /dev/null +++ b/m_config.h @@ -0,0 +1,87 @@ + +#ifndef NEW_CONFIG +#warning "Including m_config.h but NEW_CONFIG is disabled" +#else + +typedef struct m_config_option m_config_option_t; +typedef struct m_config_save_slot m_config_save_slot_t; +struct m_option; +struct m_option_type; + +struct m_config_save_slot { + m_config_save_slot_t* prev; + int lvl; + unsigned char data[0]; +}; + +struct m_config_option { + m_config_option_t* next; + char* name; // Full name (ie option:subopt) + struct m_option* opt; + m_config_save_slot_t* slots; + unsigned int flags; // currently it only tell if the option was set +}; + +typedef struct m_config { + m_config_option_t* opts; + int lvl; // Current stack level + int mode; +} m_config_t; + + +//////////////////////////// Functions /////////////////////////////////// + +m_config_t* +m_config_new(void); + +void +m_config_free(m_config_t* config); + +void +m_config_push(m_config_t* config); + +void +m_config_pop(m_config_t* config); + +int +m_config_register_options(m_config_t *config, struct m_option *args); + +int +m_config_set_option(m_config_t *config, char* arg, char* param); + +int +m_config_check_option(m_config_t *config, char* arg, char* param); + +struct m_option* +m_config_get_option(m_config_t *config, char* arg); + +///////////////////////////////////////////////////////////////////////////////////// +/////////////////////////// Backward compat. stuff //////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////// + +typedef struct config config_t; +struct config { + char *name; + void *p; + struct m_option_type* type; + unsigned int flags; + float min,max; + void* priv; +}; + + +#define CONF_MIN (1<<0) +#define CONF_MAX (1<<1) +#define CONF_RANGE (CONF_MIN|CONF_MAX) +#define CONF_NOCFG (1<<2) +#define CONF_NOCMD (1<<3) +#define CONF_GLOBAL (1<<4) +#define CONF_NOSAVE (1<<5) +#define CONF_OLD (1<<6) + +#define ERR_NOT_AN_OPTION -1 +#define ERR_MISSING_PARAM -2 +#define ERR_OUT_OF_RANGE -3 +#define ERR_FUNC_ERR -4 + +#endif diff --git a/m_option.c b/m_option.c new file mode 100644 index 0000000000..a5824895ee --- /dev/null +++ b/m_option.c @@ -0,0 +1,1008 @@ + +#include "config.h" + +#ifdef NEW_CONFIG + +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <stdio.h> +#include <stdarg.h> +#include <inttypes.h> + +#include "m_option.h" +//#include "m_config.h" +#include "mp_msg.h" + +// Default function that just do a memcpy + +static void copy_opt(m_option_t* opt,void* dst,void* src) { + if(dst && src) + memcpy(dst,src,opt->type->size); +} + +// Helper for the print funcs (from man printf) +static char* dup_printf(const char *fmt, ...) { + /* Guess we need no more than 50 bytes. */ + int n, size = 50; + char *p; + va_list ap; + if ((p = malloc (size)) == NULL) + return NULL; + while (1) { + /* Try to print in the allocated space. */ + va_start(ap, fmt); + n = vsnprintf (p, size, fmt, ap); + va_end(ap); + /* If that worked, return the string. */ + if (n > -1 && n < size) + return p; + /* Else try again with more space. */ + if (n > -1) /* glibc 2.1 */ + size = n+1; /* precisely what is needed */ + else /* glibc 2.0 */ + size *= 2; /* twice the old size */ + if ((p = realloc (p, size)) == NULL) + return NULL; + } +} + + +// Flag + +#define VAL(x) (*(int*)(x)) + +static int parse_flag(m_option_t* opt,char *name, char *param, void* dst, int src) { + if (src == M_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")) { + if(dst) VAL(dst) = opt->max; + } else if (!strcasecmp(param, "no") || + !strcasecmp(param, "nein") || + !strcasecmp(param, "nicht") || + !strcasecmp(param, "nem") || + !strcasecmp(param, "n") || + !strcmp(param, "0")) { + if(dst) VAL(dst) = opt->min; + } else { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "invalid parameter for %s flag: %s\n",name, param); + return M_OPT_INVALID; + } + return 1; + } else { + if(dst) VAL(dst) = opt->max; + return 0; + } +} + +static char* print_flag(m_option_t* opt, void* val) { + if(VAL(val) == opt->min) + return strdup("no"); + else + return strdup("yes"); +} + +m_option_type_t m_option_type_flag = { + "Flag", + "need yes or no in config files", + sizeof(int), + 0, + parse_flag, + print_flag, + copy_opt, + copy_opt, + NULL, + NULL +}; + +// Integer + +static int parse_int(m_option_t* opt,char *name, char *param, void* dst, int src) { + long tmp_int; + char *endptr; + src = 0; + + if (param == NULL) + return M_OPT_MISSING_PARAM; + + tmp_int = strtol(param, &endptr, 0); + if (*endptr) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be an integer: %s\n",name, param); + return M_OPT_INVALID; + } + + if ((opt->flags & M_OPT_MIN) && (tmp_int < opt->min)) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be >= %d: %s\n", name, (int) opt->min, param); + return M_OPT_OUT_OF_RANGE; + } + + if ((opt->flags & M_OPT_MAX) && (tmp_int > opt->max)) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be <= %d: %s\n",name, (int) opt->max, param); + return M_OPT_OUT_OF_RANGE; + } + + if(dst) VAL(dst) = tmp_int; + + return 1; +} + +static char* print_int(m_option_t* opt, void* val) { + opt = NULL; + return dup_printf("%d",VAL(val)); +} + +m_option_type_t m_option_type_int = { + "Integer", + "", + sizeof(int), + 0, + parse_int, + print_int, + copy_opt, + copy_opt, + NULL, + NULL +}; + +// Float + +#undef VAL +#define VAL(x) (*(float*)(x)) + +static int parse_float(m_option_t* opt,char *name, char *param, void* dst, int src) { + float tmp_float; + char* endptr; + src = 0; + + if (param == NULL) + return M_OPT_MISSING_PARAM; + + tmp_float = strtod(param, &endptr); + + switch(*endptr) { + case ':': + case '/': + tmp_float /= strtod(endptr+1, &endptr); + break; + case '.': + case ',': + /* we also handle floats specified with + * non-locale decimal point ::atmos + */ + if(tmp_float<0) + tmp_float -= 1.0/pow(10,strlen(endptr+1)) * strtod(endptr+1, &endptr); + else + tmp_float += 1.0/pow(10,strlen(endptr+1)) * strtod(endptr+1, &endptr); + break; + } + + if (*endptr) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be a floating point " + "number or a ratio (numerator[:/]denominator): %s\n",name, param); + return M_OPT_INVALID; + } + + if (opt->flags & M_OPT_MIN) + if (tmp_float < opt->min) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be >= %f: %s\n", name, opt->min, param); + return M_OPT_OUT_OF_RANGE; + } + + if (opt->flags & M_OPT_MAX) + if (tmp_float > opt->max) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be <= %f: %s\n", name, opt->max, param); + return M_OPT_OUT_OF_RANGE; + } + + if(dst) VAL(dst) = tmp_float; + return 1; +} + +static char* print_float(m_option_t* opt, void* val) { + opt = NULL; + return dup_printf("%f",VAL(val)); +} + +m_option_type_t m_option_type_float = { + "Float", + "floating point number or ratio (numerator[:/]denominator)", + sizeof(float), + 0, + parse_float, + print_float, + copy_opt, + copy_opt, + NULL, + NULL +}; + +///////////// Position +#undef VAL +#define VAL(x) (*(off_t*)(x)) + +static int parse_position(m_option_t* opt,char *name, char *param, void* dst, int src) { + off_t tmp_off; + char dummy; + + if (param == NULL) + return M_OPT_MISSING_PARAM; + if (sscanf(param, sizeof(off_t) == sizeof(int) ? + "%d%c" : "%lld%c |