isl_arg_parse: support string list arguments
[platform/upstream/isl.git] / include / isl / arg.h
1 /*
2  * Copyright 2008-2009 Katholieke Universiteit Leuven
3  *
4  * Use of this software is governed by the GNU LGPLv2.1 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
279 void isl_args_set_defaults(struct isl_args *args, void *opt);
280 void isl_args_free(struct isl_args *args, void *opt);
281 int isl_args_parse(struct isl_args *args, int argc, char **argv, void *opt,
282         unsigned flags);
283
284 #define ISL_ARG_DECL(prefix,st,args)                                    \
285 extern struct isl_args args;                                            \
286 st *prefix ## _new_with_defaults(void);                                 \
287 void prefix ## _free(st *opt);                                          \
288 int prefix ## _parse(st *opt, int argc, char **argv, unsigned flags);
289
290 #define ISL_ARG_DEF(prefix,st,args)                                     \
291 st *prefix ## _new_with_defaults()                                      \
292 {                                                                       \
293         st *opt = (st *)calloc(1, sizeof(st));                          \
294         if (opt)                                                        \
295                 isl_args_set_defaults(&(args), opt);                    \
296         return opt;                                                     \
297 }                                                                       \
298                                                                         \
299 void prefix ## _free(st *opt)                                           \
300 {                                                                       \
301         isl_args_free(&(args), opt);                                    \
302 }                                                                       \
303                                                                         \
304 int prefix ## _parse(st *opt, int argc, char **argv, unsigned flags)    \
305 {                                                                       \
306         return isl_args_parse(&(args), argc, argv, opt, flags);         \
307 }
308
309 #if defined(__cplusplus)
310 }
311 #endif
312
313 #endif