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