| /* |
| * 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 <stddef.h> |
| #include <stdlib.h> |
| |
| #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 |