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