15 #define UNUSED(x) (void)(x) 17 #define ISVAR(o) ((o.type & PARAM_ACTION_VAR) == PARAM_ACTION_VAR) 18 #define ISFUNC(o) ((o.type & PARAM_ACTION_FUNC) == PARAM_ACTION_FUNC) 19 #define CANARG(o) ((o.type & PARAM_OPTION_ARG_YES) == PARAM_OPTION_ARG_YES) 20 #define MAYARG(o) ((o.type & PARAM_OPTION_ARG_MAYBE) == PARAM_OPTION_ARG_MAYBE) 21 #define REQUIREARG(o) (CANARG(o) && !MAYARG(o)) 22 #define NOARG(o) ((o.type & PARAM_OPTION_ARG_YES) == 0) 23 #define TYPEBOOL(o) ((o.type & PARAM_OPTION_BOOL) == PARAM_OPTION_BOOL) 24 #define TYPEINT(o) ((o.type & ARG_TYPE_DOUBLE) == ARG_TYPE_INT) 25 #define TYPESTR(o) ((o.type & ARG_TYPE_DOUBLE) == ARG_TYPE_STR) 26 #define TYPEDOUBLE(o) ((o.type & ARG_TYPE_DOUBLE) == ARG_TYPE_DOUBLE) 29 # define MIN(a, b) (a > b ? b : a) 32 # define MAX(a, b) (a < b ? b : a) 44 #define TYPLESSVAR struct _typeless 45 #define SETBOOL(var, v) var.type=1; var.b=(short int)(v); 46 #define SETINT(var, v) var.type=2; var.i=(long int)(v); 47 #define SETDOUBLE(var, v) var.type=3; var.d=(long double)(v); 48 #define SETSTR(var, v) var.type=4; var.s=(char *)(v); 49 #define SETVOID(var, v) var.type=5; var.s=(void *)(v); 50 #define SETFAILED(var) var.type=6; 51 #define SETNULL(var) var.type=0; 52 #define ISNULL(var) (var.type==0?1:0) 53 #define ISBOOL(var) (var.type==1?1:0) 54 #define ISINT(var) (var.type==2?1:0) 55 #define ISDOUBLE(var) (var.type==3?1:0) 56 #define ISSTR(var) (var.type==4?1:0) 57 #define ISVOID(var) (var.type==5?1:0) 58 #define ISFAILED(var) (var.type==6?1:0) 59 #define GETVAL(var, t) (var.type==1?(t)var.b:(var.type==2?(t)var.i:(var.type==3?(t)var.d:(var.type==4?(t)var.s:(var.type==5?(t)var.s:(t)NULL))))) 60 #define GETNULL(var) ((void *)NULL) 61 #define GETBOOL(var) ((short int)var.b) 62 #define GETINT(var) ((long int)var.i) 63 #define GETDOUBLE(var) ((long double)var.d) 64 #define GETSTR(var) ((char *)var.s) 65 #define GETVOID(var) ((void *)var.s) 67 #define BIT_SET(b, o) ((o & b) == b) 68 #define IS_FAIL_ON_UNKNOWN(o) (BIT_SET(FAIL_ON_UNKNOWN, o)) 69 #define ARG(o) (TYPESTR(o)?arg_str:(TYPEINT(o)?arg_int:(TYPEDOUBLE(o)?arg_double:(TYPEBOOL(o)?arg_bool:"")))) 71 short int check_bool(
const char *s,
size_t len);
79 static char arg_bool[] =
"=BOOLEAN";
80 static char arg_int[] =
"=INTEGER";
81 static char arg_str[] =
"=STRING";
82 static char arg_double[] =
"=DECIMAL";
83 static char bool_no[] =
"[no-]";
85 for(i = 0; o[i].
type != 0; i++)
87 if(o[i].shortopt != 0 || o[i].longopt != NULL)
89 int j = printf(
" %c%c%c %s%s%s%c%s%c",
90 (o[i].shortopt != 0 ?
'-':
' '),
91 (o[i].shortopt != 0 ? o[i].shortopt :
' '),
92 (o[i].shortopt != 0 && o[i].longopt != NULL ?
',' :
' '),
93 (o[i].longopt != NULL ?
"--" :
""),
99 printf(
"%*s\t%s\n",
MAX(39 - j, 2),
"",
_(gettext(o[i].help_text)));
107 static char arg_bool[] =
"=BOOLEAN";
108 static char arg_int[] =
"=INTEGER";
109 static char arg_str[] =
"=STRING";
110 static char arg_double[] =
"=DECIMAL";
112 for(i = 0; o[i].
type != 0; i++)
114 if(o[i].configname != NULL)
116 int j = printf(
" %s%c%s%c",
120 (
MAYARG(o[i]) ?
']' : 0));
121 printf(
"%*s\t%s\n",
MAX(39 - j, 2),
"",
_(gettext(o[i].help_text)));
128 size_t n_o_in, n_add, i;
130 for(n_o_in = 0; (*o_in)[n_o_in].type != 0; n_o_in++);
133 if(add == NULL)
return n_o_in;
134 for(n_add = 0; add[n_add].
type != 0; n_add++);
137 for(i = 0; i < n_add; i++)
138 (*o_in)[n_o_in + i] = add[i];
139 return n_o_in + n_add;
145 if(strcasecmp(s,
"true") == 0 || strcasecmp(s,
"yes") == 0 || strcasecmp(s,
"y") == 0 || strcmp(s,
"1") == 0 || strcasecmp(s,
"false") == 0 || strcasecmp(s,
"no") == 0 || strcasecmp(s,
"n") == 0 || strcmp(s,
"0") == 0)
154 if(strcasecmp(s,
"true") == 0 || strcasecmp(s,
"yes") == 0 || strcasecmp(s,
"y") == 0 || strcmp(s,
"1") == 0)
156 else if(strcasecmp(s,
"false") == 0 || strcasecmp(s,
"no") == 0 || strcasecmp(s,
"n") == 0 || strcmp(s,
"0") == 0)
203 printf(
_(
"argument %s for option --%s is not a boolean\n"), (
char *)arg, o.
longopt);
220 printf(
_(
"argument %s for option --%s is not a number\n"), (
char *)arg, o.
longopt);
232 printf(
_(
"argument %s for option --%s is not a number\n"), (
char *)arg, o.
longopt);
246 for(i = 1; i < argc; i++)
248 if(argv[i][0] ==
'-' && argv[i][1] ==
'-' &&
str_len(argv[i]) == 2)
250 else if(argv[i][0] ==
'-' && argv[i][1] ==
'-')
252 for(j = 0; (*o)[j].type != 0; j++)
256 if(
TYPEBOOL((*o)[j]) && strncmp(argv[i] + prefix,
"no-", 3) == 0)
258 int optlen =
MIN(
_len(argv[i] + prefix,
'='),
str_len(argv[i] + prefix));
259 if(strncmp(argv[i] + prefix, (*o)[j].longopt,
MAX(optlen,
str_len((*o)[j].longopt))) == 0)
262 if(argv[i][prefix + optlen] ==
'=')
266 printf(
_(
"option --%s does not accept any arguments\n"), (*o)[j].longopt);
271 if(((
option_func_t)(*o)[j].ptr)((*o)[j], argv[i] + prefix + optlen + 1, o) != 0)
274 else if(
ISVAR((*o)[j]))
276 var =
check_arg((*o)[j], argv[i] + prefix + optlen + 1);
283 printf(
_(
"option --%s requires an argument\n"), (*o)[j].longopt);
292 if(((
option_func_t)(*o)[j].ptr)((*o)[j], (prefix > 2 ? (
void *)0 : (
void *)1), o) != 0)
295 else if(
ISVAR((*o)[j]))
304 if(((
option_func_t)(*o)[j].ptr)((*o)[j], (*o)[j].default_value, o) != 0)
307 else if(
ISVAR((*o)[j]))
309 SETVOID(var, (int64_t)(*o)[j].default_value);
318 if((*o)[j].type == 0)
320 printf(
_(
"no such option %s\n"), argv[i]);
324 else if(argv[i][0] ==
'-' &&
str_len(argv[i]) == 2)
326 for(j = 0; (*o)[j].type != 0; j++)
328 if(argv[i][1] == (*o)[j].shortopt)
331 if(
CANARG((*o)[j]) && (i + 1) < argc && argv[i + 1][0] !=
'-')
335 if(((
option_func_t)(*o)[j].ptr)((*o)[j], (
void *)argv[++i], o) != 0)
338 else if(
ISVAR((*o)[j]))
346 printf(
_(
"option -%c requires an argument\n"), (*o)[j].shortopt);
356 else if(
ISVAR((*o)[j]))
365 if(((
option_func_t)(*o)[j].ptr)((*o)[j], (*o)[j].default_value, o) != 0)
368 else if(
ISVAR((*o)[j]))
370 SETVOID(var, (int64_t)(*o)[j].default_value);
378 if((*o)[j].type == 0)
380 printf(
_(
"no such option %s\n"), argv[i]);
384 else if(argv[i][0] ==
'-')
386 printf(
_(
"%s is not a valid option\n"), argv[i]);
397 if(file == NULL || *o == NULL)
400 FILE *fp = fopen(file,
"r");
404 char *line, *key, *val, *ptr;
405 line = key = val = NULL;
406 ssize_t readsize = 0;
411 while((readsize = getline(&line, &s, fp)) != -1)
413 if(line[readsize - 1] ==
'\n')
414 line[--readsize] =
'\0';
416 key = malloc(readsize + 1);
417 ptr = val = malloc(readsize + 1);
419 if(sscanf(line,
" %[^%#= ] = %[^#] ", key, val) >= 2)
422 while(val[vallen - 1] ==
' ' || val[vallen - 1] ==
'\t')
424 val[vallen - 1] =
'\0';
428 for(n = 0; (*o)[n].type != 0; n++)
430 if((*o)[n].configname != NULL && strcmp(key, (*o)[n].configname) == 0)
432 if(val[0] ==
'"' && val[vallen - 1] ==
'"')
438 char *val2 = strdup(val);
441 if(((
option_func_t)(*o)[n].ptr)((*o)[n], (
void *)val2, o) != 0)
449 else if(
ISVAR((*o)[n]))
468 printf(
_(
"no such option %s\n"), key);
475 line = key = val = ptr = NULL;
long double char_to_double(const char *s, int len)
int _len(const char *s, char m)
short int check_bool(const char *s, size_t len)
#define SETDOUBLE(var, v)
#define str_len(s)
Shorthand for counting '\0' terminating strings. See _len for more info.
int getparam(option_t **o, int argc, char **argv)
int applyopt(option_t **o_all, option_t o, TYPLESSVAR arg)
void print_options_help(option_t *o)
int readconfig(option_t **o, const char *file, int options)
TYPLESSVAR check_arg(option_t o, void *arg)
size_t add_config_options(option_t **o_in, option_t add[])
short int check_double(const char *s, int len)
int(* option_func_t)(option_t, void *, option_t **)
unsigned long long char_to_int(const char *s, int i, uint8_t base)
#define IS_FAIL_ON_UNKNOWN(o)
short int char_to_bool(const char *s, size_t len)
#define UNUSED(x)
Used to indicate that a function does not use a certain parameter.
short int check_int(const char *s, int len, uint8_t base)
void print_options_config(option_t *o)