#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 <unistd.h>
#include "m_option.h"
//#include "m_config.h"
#include "mp_msg.h"
// Don't free for 'production' atm
#ifndef MP_DEBUG
#define NO_FREE
#endif
m_option_t* m_option_list_find(m_option_t* list,char* name) {
int i;
for(i = 0 ; list[i].name ; i++) {
int l = strlen(list[i].name) - 1;
if((list[i].type->flags & M_OPT_TYPE_ALLOW_WILDCARD) &&
(l > 0) && (list[i].name[l] == '*')) {
if(strncasecmp(list[i].name,name,l) == 0)
return &list[i];
} else if(strcasecmp(list[i].name,name) == 0)
return &list[i];
}
return NULL;
}
// 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", &tmp_off, &dummy) != 1) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be an integer: %s\n",opt->name,param);
return M_OPT_INVALID;
}
if (opt->flags & M_OPT_MIN)
if (tmp_off < opt->min) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
(sizeof(off_t) == sizeof(int) ?
"The %s option must be >= %d: %s\n" :
"The %s option must be >= %lld: %s\n"),
(off_t) opt->min, param);
return M_OPT_OUT_OF_RANGE;
}
if (opt->flags & M_OPT_MAX)
if (tmp_off > opt->max) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
(sizeof(off_t) == sizeof(int) ?
"The %s option must be <= %d: %s\n" :
"The %s option must be <= %lld: %s\n"),
(off_t) opt->max, param);
return M_OPT_OUT_OF_RANGE;
}
if(dst)
VAL(dst) = tmp_off;
return 1;
}
static char* print_position(m_option_t* opt, void* val) {
return dup_printf(sizeof(off_t) == sizeof(int) ? "%d" : "%lld",VAL(val));
}
m_option_type_t m_option_type_position = {
"Position",
"Integer (off_t)",
sizeof(off_t),
0,
parse_position,
print_position,
copy_opt,
copy_opt,
NULL,
NULL
};
///////////// String
#undef VAL
#define VAL(x) (*(char**)(x))
static int parse_str(m_option_t* opt,char *name, char *param, void* dst, int src) {
if (param == NULL)
return M_OPT_MISSING_PARAM;
if ((opt->flags & M_OPT_MIN) && (strlen(param) < opt->min)) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be >= %d chars: %s\n",
(int) opt->min, param);
return M_OPT_OUT_OF_RANGE;
}
if ((opt->flags & M_OPT_MAX) && (strlen(param) > opt->max)) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be <= %d chars: %s\n",
(int) opt->max, param);
return M_OPT_OUT_OF_RANGE;
}
if(dst) {
if(VAL(dst))
free(VAL(dst));
VAL(dst) = strdup(param);
}
return 1;
}
static char* print_str(m_option_t* opt, void* val) {
return (val && VAL(val) && strlen(VAL(val)) > 0) ? strdup(VAL(val)) : NULL;
}
static void copy_str(m_option_t* opt,void* dst, void* src) {
if(dst && src) {
#ifndef NO_FREE
if(VAL(dst)) free(VAL(dst)); //FIXME!!!
#endif
VAL(dst) = VAL(src) ? strdup(VAL(src)) : NULL
|