Home | History | Annotate | Line # | Download | only in isl
      1 /*
      2  * Copyright 2008-2009 Katholieke Universiteit Leuven
      3  *
      4  * Use of this software is governed by the MIT license
      5  *
      6  * Written by Sven Verdoolaege, K.U.Leuven, Departement
      7  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
      8  */
      9 
     10 #ifndef ISL_ARG_H
     11 #define ISL_ARG_H
     12 
     13 #include <stddef.h>
     14 #include <stdlib.h>
     15 
     16 #if defined(__cplusplus)
     17 extern "C" {
     18 #endif
     19 
     20 struct isl_arg_choice {
     21 	const char	*name;
     22 	unsigned	 value;
     23 };
     24 
     25 struct isl_arg_flags {
     26 	const char	*name;
     27 	unsigned	 mask;
     28 	unsigned	 value;
     29 };
     30 
     31 enum isl_arg_type {
     32 	isl_arg_end,
     33 	isl_arg_alias,
     34 	isl_arg_arg,
     35 	isl_arg_bool,
     36 	isl_arg_child,
     37 	isl_arg_choice,
     38 	isl_arg_flags,
     39 	isl_arg_footer,
     40 	isl_arg_int,
     41 	isl_arg_user,
     42 	isl_arg_long,
     43 	isl_arg_ulong,
     44 	isl_arg_str,
     45 	isl_arg_str_list,
     46 	isl_arg_version
     47 };
     48 
     49 struct isl_args;
     50 
     51 struct isl_arg {
     52 	enum isl_arg_type	 type;
     53 	char			 short_name;
     54 	const char		*long_name;
     55 	const char		*argument_name;
     56 #define ISL_ARG_OFFSET_NONE	((size_t) -1)
     57 	size_t			 offset;
     58 	const char		*help_msg;
     59 #define ISL_ARG_SINGLE_DASH	(1 << 0)
     60 #define ISL_ARG_BOOL_ARG	(1 << 1)
     61 #define ISL_ARG_HIDDEN		(1 << 2)
     62 	unsigned		 flags;
     63 	union {
     64 	struct {
     65 		struct isl_arg_choice	*choice;
     66 		unsigned	 	 default_value;
     67 		unsigned	 	 default_selected;
     68 		int (*set)(void *opt, unsigned val);
     69 	} choice;
     70 	struct {
     71 		struct isl_arg_flags	*flags;
     72 		unsigned	 	 default_value;
     73 	} flags;
     74 	struct {
     75 		unsigned		 default_value;
     76 		int (*set)(void *opt, unsigned val);
     77 	} b;
     78 	struct {
     79 		int			default_value;
     80 	} i;
     81 	struct {
     82 		long		 	default_value;
     83 		long		 	default_selected;
     84 		int (*set)(void *opt, long val);
     85 	} l;
     86 	struct {
     87 		unsigned long		default_value;
     88 	} ul;
     89 	struct {
     90 		const char		*default_value;
     91 	} str;
     92 	struct {
     93 		size_t			 offset_n;
     94 	} str_list;
     95 	struct {
     96 		struct isl_args		*child;
     97 	} child;
     98 	struct {
     99 		void (*print_version)(void);
    100 	} version;
    101 	struct {
    102 		int (*init)(void*);
    103 		void (*clear)(void*);
    104 	} user;
    105 	} u;
    106 };
    107 
    108 struct isl_args {
    109 	size_t			 options_size;
    110 	struct isl_arg		*args;
    111 };
    112 
    113 #define ISL_ARGS_START(s,name)						\
    114 	struct isl_arg name ## LIST[];					\
    115 	struct isl_args name = { sizeof(s), name ## LIST };		\
    116 	struct isl_arg name ## LIST[] = {
    117 #define ISL_ARGS_END							\
    118 	{ isl_arg_end } };
    119 
    120 #define ISL_ARG_ALIAS(l)	{					\
    121 	.type = isl_arg_alias,						\
    122 	.long_name = l,							\
    123 },
    124 #define ISL_ARG_ARG(st,f,a,d)	{					\
    125 	.type = isl_arg_arg,						\
    126 	.argument_name = a,						\
    127 	.offset = offsetof(st, f),					\
    128 	.u = { .str = { .default_value = d } }				\
    129 },
    130 #define ISL_ARG_FOOTER(h)	{					\
    131 	.type = isl_arg_footer,						\
    132 	.help_msg = h,							\
    133 },
    134 #define ISL_ARG_CHOICE(st,f,s,l,c,d,h)	{				\
    135 	.type = isl_arg_choice,						\
    136 	.short_name = s,						\
    137 	.long_name = l,							\
    138 	.offset = offsetof(st, f),					\
    139 	.help_msg = h,							\
    140 	.u = { .choice = { .choice = c, .default_value = d,		\
    141 			    .default_selected = d, .set = NULL } }	\
    142 },
    143 #define ISL_ARG_OPT_CHOICE(st,f,s,l,c,d,ds,h)	{			\
    144 	.type = isl_arg_choice,						\
    145 	.short_name = s,						\
    146 	.long_name = l,							\
    147 	.offset = offsetof(st, f),					\
    148 	.help_msg = h,							\
    149 	.u = { .choice = { .choice = c, .default_value = d,		\
    150 			    .default_selected = ds, .set = NULL } }	\
    151 },
    152 #define ISL_ARG_PHANTOM_USER_CHOICE_F(s,l,c,setter,d,h,fl)	{	\
    153 	.type = isl_arg_choice,						\
    154 	.short_name = s,						\
    155 	.long_name = l,							\
    156 	.offset = ISL_ARG_OFFSET_NONE,					\
    157 	.help_msg = h,							\
    158 	.flags = fl,							\
    159 	.u = { .choice = { .choice = c, .default_value = d,		\
    160 			    .default_selected = d, .set = setter } }	\
    161 },
    162 #define ISL_ARG_USER_OPT_CHOICE(st,f,s,l,c,setter,d,ds,h)	{	\
    163 	.type = isl_arg_choice,						\
    164 	.short_name = s,						\
    165 	.long_name = l,							\
    166 	.offset = offsetof(st, f),					\
    167 	.help_msg = h,							\
    168 	.u = { .choice = { .choice = c, .default_value = d,		\
    169 			    .default_selected = ds, .set = setter } }	\
    170 },
    171 #define _ISL_ARG_BOOL_F(o,s,l,setter,d,h,fl)	{			\
    172 	.type = isl_arg_bool,						\
    173 	.short_name = s,						\
    174 	.long_name = l,							\
    175 	.offset = o,							\
    176 	.help_msg = h,							\
    177 	.flags = fl,							\
    178 	.u = { .b = { .default_value = d, .set = setter } }		\
    179 },
    180 #define ISL_ARG_BOOL_F(st,f,s,l,d,h,fl)					\
    181 	_ISL_ARG_BOOL_F(offsetof(st, f),s,l,NULL,d,h,fl)
    182 #define ISL_ARG_BOOL(st,f,s,l,d,h)					\
    183 	ISL_ARG_BOOL_F(st,f,s,l,d,h,0)
    184 #define ISL_ARG_PHANTOM_BOOL_F(s,l,setter,h,fl)				\
    185 	_ISL_ARG_BOOL_F(ISL_ARG_OFFSET_NONE,s,l,setter,0,h,fl)
    186 #define ISL_ARG_PHANTOM_BOOL(s,l,setter,h)				\
    187 	ISL_ARG_PHANTOM_BOOL_F(s,l,setter,h,0)
    188 #define ISL_ARG_INT_F(st,f,s,l,a,d,h,fl)	{			\
    189 	.type = isl_arg_int,						\
    190 	.short_name = s,						\
    191 	.long_name = l,							\
    192 	.argument_name = a,						\
    193 	.offset = offsetof(st, f),					\
    194 	.help_msg = h,							\
    195 	.flags = fl,							\
    196 	.u = { .i = { .default_value = d } }				\
    197 },
    198 #define ISL_ARG_INT(st,f,s,l,a,d,h)					\
    199 	ISL_ARG_INT_F(st,f,s,l,a,d,h,0)
    200 #define ISL_ARG_LONG(st,f,s,lo,d,h)	{				\
    201 	.type = isl_arg_long,						\
    202 	.short_name = s,						\
    203 	.long_name = lo,						\
    204 	.offset = offsetof(st, f),					\
    205 	.help_msg = h,							\
    206 	.u = { .l = { .default_value = d, .default_selected = d,	\
    207 		      .set = NULL } }					\
    208 },
    209 #define ISL_ARG_USER_LONG(st,f,s,lo,setter,d,h)	{			\
    210 	.type = isl_arg_long,						\
    211 	.short_name = s,						\
    212 	.long_name = lo,						\
    213 	.offset = offsetof(st, f),					\
    214 	.help_msg = h,							\
    215 	.u = { .l = { .default_value = d, .default_selected = d,	\
    216 		      .set = setter } }					\
    217 },
    218 #define ISL_ARG_OPT_LONG(st,f,s,lo,d,ds,h)	{			\
    219 	.type = isl_arg_long,						\
    220 	.short_name = s,						\
    221 	.long_name = lo,						\
    222 	.offset = offsetof(st, f),					\
    223 	.help_msg = h,							\
    224 	.u = { .l = { .default_value = d, .default_selected = ds,	\
    225 		      .set = NULL } }					\
    226 },
    227 #define ISL_ARG_ULONG(st,f,s,l,d,h)	{				\
    228 	.type = isl_arg_ulong,						\
    229 	.short_name = s,						\
    230 	.long_name = l,							\
    231 	.offset = offsetof(st, f),					\
    232 	.help_msg = h,							\
    233 	.u = { .ul = { .default_value = d } }				\
    234 },
    235 #define ISL_ARG_STR_F(st,f,s,l,a,d,h,fl)	{			\
    236 	.type = isl_arg_str,						\
    237 	.short_name = s,						\
    238 	.long_name = l,							\
    239 	.argument_name = a,						\
    240 	.offset = offsetof(st, f),					\
    241 	.help_msg = h,							\
    242 	.flags = fl,							\
    243 	.u = { .str = { .default_value = d } }				\
    244 },
    245 #define ISL_ARG_STR(st,f,s,l,a,d,h)					\
    246 	ISL_ARG_STR_F(st,f,s,l,a,d,h,0)
    247 #define ISL_ARG_STR_LIST(st,f_n,f_l,s,l,a,h)	{			\
    248 	.type = isl_arg_str_list,					\
    249 	.short_name = s,						\
    250 	.long_name = l,							\
    251 	.argument_name = a,						\
    252 	.offset = offsetof(st, f_l),					\
    253 	.help_msg = h,							\
    254 	.u = { .str_list = { .offset_n = offsetof(st, f_n) } }		\
    255 },
    256 #define _ISL_ARG_CHILD(o,l,c,h,fl)	{				\
    257 	.type = isl_arg_child,						\
    258 	.long_name = l,							\
    259 	.offset = o,							\
    260 	.help_msg = h,							\
    261 	.flags = fl,							\
    262 	.u = { .child = { .child = c } }				\
    263 },
    264 #define ISL_ARG_CHILD(st,f,l,c,h)					\
    265 	_ISL_ARG_CHILD(offsetof(st, f),l,c,h,0)
    266 #define ISL_ARG_GROUP_F(l,c,h,fl)					\
    267 	_ISL_ARG_CHILD(ISL_ARG_OFFSET_NONE,l,c,h,fl)
    268 #define ISL_ARG_GROUP(l,c,h)						\
    269 	ISL_ARG_GROUP_F(l,c,h,0)
    270 #define ISL_ARG_FLAGS(st,f,s,l,c,d,h)	{				\
    271 	.type = isl_arg_flags,						\
    272 	.short_name = s,						\
    273 	.long_name = l,							\
    274 	.offset = offsetof(st, f),					\
    275 	.help_msg = h,							\
    276 	.u = { .flags = { .flags = c, .default_value = d } }		\
    277 },
    278 #define ISL_ARG_USER(st,f,i,c) {					\
    279 	.type = isl_arg_user,						\
    280 	.offset = offsetof(st, f),					\
    281 	.u = { .user = { .init = i, .clear = c} }			\
    282 },
    283 #define ISL_ARG_VERSION(print) {					\
    284 	.type = isl_arg_version,					\
    285 	.u = { .version = { .print_version = print } }			\
    286 },
    287 
    288 #define ISL_ARG_ALL		(1 << 0)
    289 #define ISL_ARG_SKIP_HELP	(1 << 1)
    290 
    291 void isl_args_set_defaults(struct isl_args *args, void *opt);
    292 void isl_args_free(struct isl_args *args, void *opt);
    293 int isl_args_parse(struct isl_args *args, int argc, char **argv, void *opt,
    294 	unsigned flags);
    295 
    296 #define ISL_ARG_DECL(prefix,st,args)					\
    297 extern struct isl_args args;						\
    298 st *prefix ## _new_with_defaults(void);					\
    299 void prefix ## _free(st *opt);						\
    300 int prefix ## _parse(st *opt, int argc, char **argv, unsigned flags);
    301 
    302 #define ISL_ARG_DEF(prefix,st,args)					\
    303 st *prefix ## _new_with_defaults()					\
    304 {									\
    305 	st *opt = (st *)calloc(1, sizeof(st));				\
    306 	if (opt)							\
    307 		isl_args_set_defaults(&(args), opt);			\
    308 	return opt;							\
    309 }									\
    310 									\
    311 void prefix ## _free(st *opt)						\
    312 {									\
    313 	isl_args_free(&(args), opt);					\
    314 }									\
    315 									\
    316 int prefix ## _parse(st *opt, int argc, char **argv, unsigned flags)	\
    317 {									\
    318 	return isl_args_parse(&(args), argc, argv, opt, flags);		\
    319 }
    320 
    321 #if defined(__cplusplus)
    322 }
    323 #endif
    324 
    325 #endif
    326