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 | , |
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 (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 | |