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 size_t offset; 57 const char *help_msg; 58 #define ISL_ARG_SINGLE_DASH (1 << 0) 59 #define ISL_ARG_BOOL_ARG (1 << 1) 60 #define ISL_ARG_HIDDEN (1 << 2) 61 unsigned flags; 62 union { 63 struct { 64 struct isl_arg_choice *choice; 65 unsigned default_value; 66 unsigned default_selected; 67 int (*set)(void *opt, unsigned val); 68 } choice; 69 struct { 70 struct isl_arg_flags *flags; 71 unsigned default_value; 72 } flags; 73 struct { 74 unsigned default_value; 75 int (*set)(void *opt, unsigned val); 76 } b; 77 struct { 78 int default_value; 79 } i; 80 struct { 81 long default_value; 82 long default_selected; 83 int (*set)(void *opt, long val); 84 } l; 85 struct { 86 unsigned long default_value; 87 } ul; 88 struct { 89 const char *default_value; 90 } str; 91 struct { 92 size_t offset_n; 93 } str_list; 94 struct { 95 struct isl_args *child; 96 } child; 97 struct { 98 void (*print_version)(void); 99 } version; 100 struct { 101 int (*init)(void*); 102 void (*clear)(void*); 103 } user; 104 } u; 105 }; 106 107 struct isl_args { 108 size_t options_size; 109 struct isl_arg *args; 110 }; 111 112 #define ISL_ARGS_START(s,name) \ 113 struct isl_arg name ## LIST[]; \ 114 struct isl_args name = { sizeof(s), name ## LIST }; \ 115 struct isl_arg name ## LIST[] = { 116 #define ISL_ARGS_END \ 117 { isl_arg_end } }; 118 119 #define ISL_ARG_ALIAS(l) { \ 120 .type = isl_arg_alias, \ 121 .long_name = l, \ 122 }, 123 #define ISL_ARG_ARG(st,f,a,d) { \ 124 .type = isl_arg_arg, \ 125 .argument_name = a, \ 126 .offset = offsetof(st, f), \ 127 .u = { .str = { .default_value = d } } \ 128 }, 129 #define ISL_ARG_FOOTER(h) { \ 130 .type = isl_arg_footer, \ 131 .help_msg = h, \ 132 }, 133 #define ISL_ARG_CHOICE(st,f,s,l,c,d,h) { \ 134 .type = isl_arg_choice, \ 135 .short_name = s, \ 136 .long_name = l, \ 137 .offset = offsetof(st, f), \ 138 .help_msg = h, \ 139 .u = { .choice = { .choice = c, .default_value = d, \ 140 .default_selected = d, .set = NULL } } \ 141 }, 142 #define ISL_ARG_OPT_CHOICE(st,f,s,l,c,d,ds,h) { \ 143 .type = isl_arg_choice, \ 144 .short_name = s, \ 145 .long_name = l, \ 146 .offset = offsetof(st, f), \ 147 .help_msg = h, \ 148 .u = { .choice = { .choice = c, .default_value = d, \ 149 .default_selected = ds, .set = NULL } } \ 150 }, 151 #define ISL_ARG_USER_OPT_CHOICE(st,f,s,l,c,setter,d,ds,h) { \ 152 .type = isl_arg_choice, \ 153 .short_name = s, \ 154 .long_name = l, \ 155 .offset = offsetof(st, f), \ 156 .help_msg = h, \ 157 .u = { .choice = { .choice = c, .default_value = d, \ 158 .default_selected = ds, .set = setter } } \ 159 }, 160 #define _ISL_ARG_BOOL_F(o,s,l,setter,d,h,fl) { \ 161 .type = isl_arg_bool, \ 162 .short_name = s, \ 163 .long_name = l, \ 164 .offset = o, \ 165 .help_msg = h, \ 166 .flags = fl, \ 167 .u = { .b = { .default_value = d, .set = setter } } \ 168 }, 169 #define ISL_ARG_BOOL_F(st,f,s,l,d,h,fl) \ 170 _ISL_ARG_BOOL_F(offsetof(st, f),s,l,NULL,d,h,fl) 171 #define ISL_ARG_BOOL(st,f,s,l,d,h) \ 172 ISL_ARG_BOOL_F(st,f,s,l,d,h,0) 173 #define ISL_ARG_PHANTOM_BOOL_F(s,l,setter,h,fl) \ 174 _ISL_ARG_BOOL_F(-1,s,l,setter,0,h,fl) 175 #define ISL_ARG_PHANTOM_BOOL(s,l,setter,h) \ 176 ISL_ARG_PHANTOM_BOOL_F(s,l,setter,h,0) 177 #define ISL_ARG_INT_F(st,f,s,l,a,d,h,fl) { \ 178 .type = isl_arg_int, \ 179 .short_name = s, \ 180 .long_name = l, \ 181 .argument_name = a, \ 182 .offset = offsetof(st, f), \ 183 .help_msg = h, \ 184 .flags = fl, \ 185 .u = { .ul = { .default_value = d } } \ 186 }, 187 #define ISL_ARG_INT(st,f,s,l,a,d,h) \ 188 ISL_ARG_INT_F(st,f,s,l,a,d,h,0) 189 #define ISL_ARG_LONG(st,f,s,lo,d,h) { \ 190 .type = isl_arg_long, \ 191 .short_name = s, \ 192 .long_name = lo, \ 193 .offset = offsetof(st, f), \ 194 .help_msg = h, \ 195 .u = { .l = { .default_value = d, .default_selected = d, \ 196 .set = NULL } } \ 197 }, 198 #define ISL_ARG_USER_LONG(st,f,s,lo,setter,d,h) { \ 199 .type = isl_arg_long, \ 200 .short_name = s, \ 201 .long_name = lo, \ 202 .offset = offsetof(st, f), \ 203 .help_msg = h, \ 204 .u = { .l = { .default_value = d, .default_selected = d, \ 205 .set = setter } } \ 206 }, 207 #define ISL_ARG_OPT_LONG(st,f,s,lo,d,ds,h) { \ 208 .type = isl_arg_long, \ 209 .short_name = s, \ 210 .long_name = lo, \ 211 .offset = offsetof(st, f), \ 212 .help_msg = h, \ 213 .u = { .l = { .default_value = d, .default_selected = ds, \ 214 .set = NULL } } \ 215 }, 216 #define ISL_ARG_ULONG(st,f,s,l,d,h) { \ 217 .type = isl_arg_ulong, \ 218 .short_name = s, \ 219 .long_name = l, \ 220 .offset = offsetof(st, f), \ 221 .help_msg = h, \ 222 .u = { .ul = { .default_value = d } } \ 223 }, 224 #define ISL_ARG_STR_F(st,f,s,l,a,d,h,fl) { \ 225 .type = isl_arg_str, \ 226 .short_name = s, \ 227 .long_name = l, \ 228 .argument_name = a, \ 229 .offset = offsetof(st, f), \ 230 .help_msg = h, \ 231 .flags = fl, \ 232 .u = { .str = { .default_value = d } } \ 233 }, 234 #define ISL_ARG_STR(st,f,s,l,a,d,h) \ 235 ISL_ARG_STR_F(st,f,s,l,a,d,h,0) 236 #define ISL_ARG_STR_LIST(st,f_n,f_l,s,l,a,h) { \ 237 .type = isl_arg_str_list, \ 238 .short_name = s, \ 239 .long_name = l, \ 240 .argument_name = a, \ 241 .offset = offsetof(st, f_l), \ 242 .help_msg = h, \ 243 .u = { .str_list = { .offset_n = offsetof(st, f_n) } } \ 244 }, 245 #define _ISL_ARG_CHILD(o,l,c,h,fl) { \ 246 .type = isl_arg_child, \ 247 .long_name = l, \ 248 .offset = o, \ 249 .help_msg = h, \ 250 .flags = fl, \ 251 .u = { .child = { .child = c } } \ 252 }, 253 #define ISL_ARG_CHILD(st,f,l,c,h) \ 254 _ISL_ARG_CHILD(offsetof(st, f),l,c,h,0) 255 #define ISL_ARG_GROUP_F(c,h,fl) \ 256 _ISL_ARG_CHILD(-1,NULL,c,h,fl) 257 #define ISL_ARG_GROUP(c,h) \ 258 ISL_ARG_GROUP_F(c,h,0) 259 #define ISL_ARG_FLAGS(st,f,s,l,c,d,h) { \ 260 .type = isl_arg_flags, \ 261 .short_name = s, \ 262 .long_name = l, \ 263 .offset = offsetof(st, f), \ 264 .help_msg = h, \ 265 .u = { .flags = { .flags = c, .default_value = d } } \ 266 }, 267 #define ISL_ARG_USER(st,f,i,c) { \ 268 .type = isl_arg_user, \ 269 .offset = offsetof(st, f), \ 270 .u = { .user = { .init = i, .clear = c} } \ 271 }, 272 #define ISL_ARG_VERSION(print) { \ 273 .type = isl_arg_version, \ 274 .u = { .version = { .print_version = print } } \ 275 }, 276 277 #define ISL_ARG_ALL (1 << 0) 278 #define ISL_ARG_SKIP_HELP (1 << 1) 279 280 void isl_args_set_defaults(struct isl_args *args, void *opt); 281 void isl_args_free(struct isl_args *args, void *opt); 282 int isl_args_parse(struct isl_args *args, int argc, char **argv, void *opt, 283 unsigned flags); 284 285 #define ISL_ARG_DECL(prefix,st,args) \ 286 extern struct isl_args args; \ 287 st *prefix ## _new_with_defaults(void); \ 288 void prefix ## _free(st *opt); \ 289 int prefix ## _parse(st *opt, int argc, char **argv, unsigned flags); 290 291 #define ISL_ARG_DEF(prefix,st,args) \ 292 st *prefix ## _new_with_defaults() \ 293 { \ 294 st *opt = (st *)calloc(1, sizeof(st)); \ 295 if (opt) \ 296 isl_args_set_defaults(&(args), opt); \ 297 return opt; \ 298 } \ 299 \ 300 void prefix ## _free(st *opt) \ 301 { \ 302 isl_args_free(&(args), opt); \ 303 } \ 304 \ 305 int prefix ## _parse(st *opt, int argc, char **argv, unsigned flags) \ 306 { \ 307 return isl_args_parse(&(args), argc, argv, opt, flags); \ 308 } 309 310 #if defined(__cplusplus) 311 } 312 #endif 313 314 #endif 315