/* * Copyright 2008-2009 Katholieke Universiteit Leuven * * Use of this software is governed by the MIT license * * Written by Sven Verdoolaege, K.U.Leuven, Departement * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium */ #ifndef ISL_ARG_H #define ISL_ARG_H #include #include #if defined(__cplusplus) extern "C" { #endif struct isl_arg_choice { const char *name; unsigned value; }; struct isl_arg_flags { const char *name; unsigned mask; unsigned value; }; enum isl_arg_type { isl_arg_end, isl_arg_alias, isl_arg_arg, isl_arg_bool, isl_arg_child, isl_arg_choice, isl_arg_flags, isl_arg_footer, isl_arg_int, isl_arg_user, isl_arg_long, isl_arg_ulong, isl_arg_str, isl_arg_str_list, isl_arg_version }; struct isl_args; struct isl_arg { enum isl_arg_type type; char short_name; const char *long_name; const char *argument_name; #define ISL_ARG_OFFSET_NONE ((size_t) -1) size_t offset; const char *help_msg; #define ISL_ARG_SINGLE_DASH (1 << 0) #define ISL_ARG_BOOL_ARG (1 << 1) #define ISL_ARG_HIDDEN (1 << 2) unsigned flags; union { struct { struct isl_arg_choice *choice; unsigned default_value; unsigned default_selected; int (*set)(void *opt, unsigned val); } choice; struct { struct isl_arg_flags *flags; unsigned default_value; } flags; struct { unsigned default_value; int (*set)(void *opt, unsigned val); } b; struct { int default_value; } i; struct { long default_value; long default_selected; int (*set)(void *opt, long val); } l; struct { unsigned long default_value; } ul; struct { const char *default_value; } str; struct { size_t offset_n; } str_list; struct { struct isl_args *child; } child; struct { void (*print_version)(void); } version; struct { int (*init)(void*); void (*clear)(void*); } user; } u; }; struct isl_args { size_t options_size; struct isl_arg *args; }; #define ISL_ARGS_START(s,name) \ struct isl_arg name ## LIST[]; \ struct isl_args name = { sizeof(s), name ## LIST }; \ struct isl_arg name ## LIST[] = { #define ISL_ARGS_END \ { isl_arg_end } }; #define ISL_ARG_ALIAS(l) { \ .type = isl_arg_alias, \ .long_name = l, \ }, #define ISL_ARG_ARG(st,f,a,d) { \ .type = isl_arg_arg, \ .argument_name = a, \ .offset = offsetof(st, f), \ .u = { .str = { .default_value = d } } \ }, #define ISL_ARG_FOOTER(h) { \ .type = isl_arg_footer, \ .help_msg = h, \ }, #define ISL_ARG_CHOICE(st,f,s,l,c,d,h) { \ .type = isl_arg_choice, \ .short_name = s, \ .long_name = l, \ .offset = offsetof(st, f), \ .help_msg = h, \ .u = { .choice = { .choice = c, .default_value = d, \ .default_selected = d, .set = NULL } } \ }, #define ISL_ARG_OPT_CHOICE(st,f,s,l,c,d,ds,h) { \ .type = isl_arg_choice, \ .short_name = s, \ .long_name = l, \ .offset = offsetof(st, f), \ .help_msg = h, \ .u = { .choice = { .choice = c, .default_value = d, \ .default_selected = ds, .set = NULL } } \ }, #define ISL_ARG_PHANTOM_USER_CHOICE_F(s,l,c,setter,d,h,fl) { \ .type = isl_arg_choice, \ .short_name = s, \ .long_name = l, \ .offset = ISL_ARG_OFFSET_NONE, \ .help_msg = h, \ .flags = fl, \ .u = { .choice = { .choice = c, .default_value = d, \ .default_selected = d, .set = setter } } \ }, #define ISL_ARG_USER_OPT_CHOICE(st,f,s,l,c,setter,d,ds,h) { \ .type = isl_arg_choice, \ .short_name = s, \ .long_name = l, \ .offset = offsetof(st, f), \ .help_msg = h, \ .u = { .choice = { .choice = c, .default_value = d, \ .default_selected = ds, .set = setter } } \ }, #define _ISL_ARG_BOOL_F(o,s,l,setter,d,h,fl) { \ .type = isl_arg_bool, \ .short_name = s, \ .long_name = l, \ .offset = o, \ .help_msg = h, \ .flags = fl, \ .u = { .b = { .default_value = d, .set = setter } } \ }, #define ISL_ARG_BOOL_F(st,f,s,l,d,h,fl) \ _ISL_ARG_BOOL_F(offsetof(st, f),s,l,NULL,d,h,fl) #define ISL_ARG_BOOL(st,f,s,l,d,h) \ ISL_ARG_BOOL_F(st,f,s,l,d,h,0) #define ISL_ARG_PHANTOM_BOOL_F(s,l,setter,h,fl) \ _ISL_ARG_BOOL_F(ISL_ARG_OFFSET_NONE,s,l,setter,0,h,fl) #define ISL_ARG_PHANTOM_BOOL(s,l,setter,h) \ ISL_ARG_PHANTOM_BOOL_F(s,l,setter,h,0) #define ISL_ARG_INT_F(st,f,s,l,a,d,h,fl) { \ .type = isl_arg_int, \ .short_name = s, \ .long_name = l, \ .argument_name = a, \ .offset = offsetof(st, f), \ .help_msg = h, \ .flags = fl, \ .u = { .i = { .default_value = d } } \ }, #define ISL_ARG_INT(st,f,s,l,a,d,h) \ ISL_ARG_INT_F(st,f,s,l,a,d,h,0) #define ISL_ARG_LONG(st,f,s,lo,d,h) { \ .type = isl_arg_long, \ .short_name = s, \ .long_name = lo, \ .offset = offsetof(st, f), \ .help_msg = h, \ .u = { .l = { .default_value = d, .default_selected = d, \ .set = NULL } } \ }, #define ISL_ARG_USER_LONG(st,f,s,lo,setter,d,h) { \ .type = isl_arg_long, \ .short_name = s, \ .long_name = lo, \ .offset = offsetof(st, f), \ .help_msg = h, \ .u = { .l = { .default_value = d, .default_selected = d, \ .set = setter } } \ }, #define ISL_ARG_OPT_LONG(st,f,s,lo,d,ds,h) { \ .type = isl_arg_long, \ .short_name = s, \ .long_name = lo, \ .offset = offsetof(st, f), \ .help_msg = h, \ .u = { .l = { .default_value = d, .default_selected = ds, \ .set = NULL } } \ }, #define ISL_ARG_ULONG(st,f,s,l,d,h) { \ .type = isl_arg_ulong, \ .short_name = s, \ .long_name = l, \ .offset = offsetof(st, f), \ .help_msg = h, \ .u = { .ul = { .default_value = d } } \ }, #define ISL_ARG_STR_F(st,f,s,l,a,d,h,fl) { \ .type = isl_arg_str, \ .short_name = s, \ .long_name = l, \ .argument_name = a, \ .offset = offsetof(st, f), \ .help_msg = h, \ .flags = fl, \ .u = { .str = { .default_value = d } } \ }, #define ISL_ARG_STR(st,f,s,l,a,d,h) \ ISL_ARG_STR_F(st,f,s,l,a,d,h,0) #define ISL_ARG_STR_LIST(st,f_n,f_l,s,l,a,h) { \ .type = isl_arg_str_list, \ .short_name = s, \ .long_name = l, \ .argument_name = a, \ .offset = offsetof(st, f_l), \ .help_msg = h, \ .u = { .str_list = { .offset_n = offsetof(st, f_n) } } \ }, #define _ISL_ARG_CHILD(o,l,c,h,fl) { \ .type = isl_arg_child, \ .long_name = l, \ .offset = o, \ .help_msg = h, \ .flags = fl, \ .u = { .child = { .child = c } } \ }, #define ISL_ARG_CHILD(st,f,l,c,h) \ _ISL_ARG_CHILD(offsetof(st, f),l,c,h,0) #define ISL_ARG_GROUP_F(l,c,h,fl) \ _ISL_ARG_CHILD(ISL_ARG_OFFSET_NONE,l,c,h,fl) #define ISL_ARG_GROUP(l,c,h) \ ISL_ARG_GROUP_F(l,c,h,0) #define ISL_ARG_FLAGS(st,f,s,l,c,d,h) { \ .type = isl_arg_flags, \ .short_name = s, \ .long_name = l, \ .offset = offsetof(st, f), \ .help_msg = h, \ .u = { .flags = { .flags = c, .default_value = d } } \ }, #define ISL_ARG_USER(st,f,i,c) { \ .type = isl_arg_user, \ .offset = offsetof(st, f), \ .u = { .user = { .init = i, .clear = c} } \ }, #define ISL_ARG_VERSION(print) { \ .type = isl_arg_version, \ .u = { .version = { .print_version = print } } \ }, #define ISL_ARG_ALL (1 << 0) #define ISL_ARG_SKIP_HELP (1 << 1) void isl_args_set_defaults(struct isl_args *args, void *opt); void isl_args_free(struct isl_args *args, void *opt); int isl_args_parse(struct isl_args *args, int argc, char **argv, void *opt, unsigned flags); #define ISL_ARG_DECL(prefix,st,args) \ extern struct isl_args args; \ st *prefix ## _new_with_defaults(void); \ void prefix ## _free(st *opt); \ int prefix ## _parse(st *opt, int argc, char **argv, unsigned flags); #define ISL_ARG_DEF(prefix,st,args) \ st *prefix ## _new_with_defaults() \ { \ st *opt = (st *)calloc(1, sizeof(st)); \ if (opt) \ isl_args_set_defaults(&(args), opt); \ return opt; \ } \ \ void prefix ## _free(st *opt) \ { \ isl_args_free(&(args), opt); \ } \ \ int prefix ## _parse(st *opt, int argc, char **argv, unsigned flags) \ { \ return isl_args_parse(&(args), argc, argv, opt, flags); \ } #if defined(__cplusplus) } #endif #endif