isl_arg_parse: support grouping of options within the same structure
[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_int,
40         isl_arg_user,
41         isl_arg_long,
42         isl_arg_ulong,
43         isl_arg_str,
44         isl_arg_version
45 };
46
47 struct isl_arg {
48         enum isl_arg_type        type;
49         char                     short_name;
50         const char              *long_name;
51         const char              *argument_name;
52         size_t                   offset;
53         const char              *help_msg;
54 #define ISL_ARG_SINGLE_DASH     (1 << 0)
55 #define ISL_ARG_BOOL_ARG        (1 << 1)
56 #define ISL_ARG_HIDDEN          (1 << 2)
57         unsigned                 flags;
58         union {
59         struct {
60                 struct isl_arg_choice   *choice;
61                 unsigned                 default_value;
62                 unsigned                 default_selected;
63                 int (*set)(void *opt, unsigned val);
64         } choice;
65         struct {
66                 struct isl_arg_flags    *flags;
67                 unsigned                 default_value;
68         } flags;
69         struct {
70                 unsigned                 default_value;
71                 int (*set)(void *opt, unsigned val);
72         } b;
73         struct {
74                 int                     default_value;
75         } i;
76         struct {
77                 long                    default_value;
78                 long                    default_selected;
79                 int (*set)(void *opt, long val);
80         } l;
81         struct {
82                 unsigned long           default_value;
83         } ul;
84         struct {
85                 const char              *default_value;
86         } str;
87         struct {
88                 struct isl_arg          *child;
89                 size_t                   size;
90         } child;
91         struct {
92                 void (*print_version)(void);
93         } version;
94         struct {
95                 int (*init)(void*);
96                 void (*clear)(void*);
97         } user;
98         } u;
99 };
100
101 #define ISL_ARG_ALIAS(l)        {                                       \
102         .type = isl_arg_alias,                                          \
103         .long_name = l,                                                 \
104 },
105 #define ISL_ARG_ARG(st,f,a,d)   {                                       \
106         .type = isl_arg_arg,                                            \
107         .argument_name = a,                                             \
108         .offset = offsetof(st, f),                                      \
109         .u = { .str = { .default_value = d } }                          \
110 },
111 #define ISL_ARG_CHOICE(st,f,s,l,c,d,h)  {                               \
112         .type = isl_arg_choice,                                         \
113         .short_name = s,                                                \
114         .long_name = l,                                                 \
115         .offset = offsetof(st, f),                                      \
116         .help_msg = h,                                                  \
117         .u = { .choice = { .choice = c, .default_value = d,             \
118                             .default_selected = d, .set = NULL } }      \
119 },
120 #define ISL_ARG_OPT_CHOICE(st,f,s,l,c,d,ds,h)   {                       \
121         .type = isl_arg_choice,                                         \
122         .short_name = s,                                                \
123         .long_name = l,                                                 \
124         .offset = offsetof(st, f),                                      \
125         .help_msg = h,                                                  \
126         .u = { .choice = { .choice = c, .default_value = d,             \
127                             .default_selected = ds, .set = NULL } }     \
128 },
129 #define ISL_ARG_USER_OPT_CHOICE(st,f,s,l,c,setter,d,ds,h)       {       \
130         .type = isl_arg_choice,                                         \
131         .short_name = s,                                                \
132         .long_name = l,                                                 \
133         .offset = offsetof(st, f),                                      \
134         .help_msg = h,                                                  \
135         .u = { .choice = { .choice = c, .default_value = d,             \
136                             .default_selected = ds, .set = setter } }   \
137 },
138 #define _ISL_ARG_BOOL_F(o,s,l,setter,d,h,fl)    {                       \
139         .type = isl_arg_bool,                                           \
140         .short_name = s,                                                \
141         .long_name = l,                                                 \
142         .offset = o,                                                    \
143         .help_msg = h,                                                  \
144         .flags = fl,                                                    \
145         .u = { .b = { .default_value = d, .set = setter } }             \
146 },
147 #define ISL_ARG_BOOL_F(st,f,s,l,d,h,fl)                                 \
148         _ISL_ARG_BOOL_F(offsetof(st, f),s,l,NULL,d,h,fl)
149 #define ISL_ARG_BOOL(st,f,s,l,d,h)                                      \
150         ISL_ARG_BOOL_F(st,f,s,l,d,h,0)
151 #define ISL_ARG_PHANTOM_BOOL_F(s,l,setter,h,fl)                         \
152         _ISL_ARG_BOOL_F(-1,s,l,setter,0,h,fl)
153 #define ISL_ARG_PHANTOM_BOOL(s,l,setter,h)                              \
154         ISL_ARG_PHANTOM_BOOL_F(s,l,setter,h,0)
155 #define ISL_ARG_INT_F(st,f,s,l,a,d,h,fl)        {                       \
156         .type = isl_arg_int,                                            \
157         .short_name = s,                                                \
158         .long_name = l,                                                 \
159         .argument_name = a,                                             \
160         .offset = offsetof(st, f),                                      \
161         .help_msg = h,                                                  \
162         .flags = fl,                                                    \
163         .u = { .ul = { .default_value = d } }                           \
164 },
165 #define ISL_ARG_INT(st,f,s,l,a,d,h)                                     \
166         ISL_ARG_INT_F(st,f,s,l,a,d,h,0)
167 #define ISL_ARG_LONG(st,f,s,lo,d,h)     {                               \
168         .type = isl_arg_long,                                           \
169         .short_name = s,                                                \
170         .long_name = lo,                                                \
171         .offset = offsetof(st, f),                                      \
172         .help_msg = h,                                                  \
173         .u = { .l = { .default_value = d, .default_selected = d,        \
174                       .set = NULL } }                                   \
175 },
176 #define ISL_ARG_USER_LONG(st,f,s,lo,setter,d,h) {                       \
177         .type = isl_arg_long,                                           \
178         .short_name = s,                                                \
179         .long_name = lo,                                                \
180         .offset = offsetof(st, f),                                      \
181         .help_msg = h,                                                  \
182         .u = { .l = { .default_value = d, .default_selected = d,        \
183                       .set = setter } }                                 \
184 },
185 #define ISL_ARG_OPT_LONG(st,f,s,lo,d,ds,h)      {                       \
186         .type = isl_arg_long,                                           \
187         .short_name = s,                                                \
188         .long_name = lo,                                                \
189         .offset = offsetof(st, f),                                      \
190         .help_msg = h,                                                  \
191         .u = { .l = { .default_value = d, .default_selected = ds,       \
192                       .set = NULL } }                                   \
193 },
194 #define ISL_ARG_ULONG(st,f,s,l,d,h)     {                               \
195         .type = isl_arg_ulong,                                          \
196         .short_name = s,                                                \
197         .long_name = l,                                                 \
198         .offset = offsetof(st, f),                                      \
199         .help_msg = h,                                                  \
200         .u = { .ul = { .default_value = d } }                           \
201 },
202 #define ISL_ARG_STR(st,f,s,l,a,d,h)     {                               \
203         .type = isl_arg_str,                                            \
204         .short_name = s,                                                \
205         .long_name = l,                                                 \
206         .argument_name = a,                                             \
207         .offset = offsetof(st, f),                                      \
208         .help_msg = h,                                                  \
209         .u = { .str = { .default_value = d } }                          \
210 },
211 #define _ISL_ARG_CHILD(o,sz,l,c,h,fl)   {                               \
212         .type = isl_arg_child,                                          \
213         .long_name = l,                                                 \
214         .offset = o,                                                    \
215         .help_msg = h,                                                  \
216         .flags = fl,                                                    \
217         .u = { .child = { .child = c, .size = sz } }                    \
218 },
219 #define ISL_ARG_CHILD(st,f,l,c,h)                                       \
220         _ISL_ARG_CHILD(offsetof(st, f),sizeof(*((st *)NULL)->f),l,c,h,0)
221 #define ISL_ARG_GROUP_F(c,h,fl)                                         \
222         _ISL_ARG_CHILD(-1,0,NULL,c,h,fl)
223 #define ISL_ARG_GROUP(c,h)                                              \
224         ISL_ARG_GROUP_F(c,h,0)
225 #define ISL_ARG_FLAGS(st,f,s,l,c,d,h)   {                               \
226         .type = isl_arg_flags,                                          \
227         .short_name = s,                                                \
228         .long_name = l,                                                 \
229         .offset = offsetof(st, f),                                      \
230         .help_msg = h,                                                  \
231         .u = { .flags = { .flags = c, .default_value = d } }            \
232 },
233 #define ISL_ARG_USER(st,f,i,c) {                                        \
234         .type = isl_arg_user,                                           \
235         .offset = offsetof(st, f),                                      \
236         .u = { .user = { .init = i, .clear = c} }                       \
237 },
238 #define ISL_ARG_VERSION(print) {                                        \
239         .type = isl_arg_version,                                        \
240         .u = { .version = { .print_version = print } }                  \
241 },
242 #define ISL_ARG_END     { isl_arg_end }
243
244 #define ISL_ARG_ALL     (1 << 0)
245
246 void isl_arg_set_defaults(struct isl_arg *arg, void *opt);
247 void isl_arg_free(struct isl_arg *arg, void *opt);
248 int isl_arg_parse(struct isl_arg *arg, int argc, char **argv, void *opt,
249         unsigned flags);
250
251 #define ISL_ARG_DECL(prefix,st,arg)                                     \
252 extern struct isl_arg arg[];                                            \
253 st *prefix ## _new_with_defaults();                                     \
254 void prefix ## _free(st *opt);                                          \
255 int prefix ## _parse(st *opt, int argc, char **argv, unsigned flags);
256
257 #define ISL_ARG_DEF(prefix,st,arg)                                      \
258 st *prefix ## _new_with_defaults()                                      \
259 {                                                                       \
260         st *opt = (st *)calloc(1, sizeof(st));                          \
261         if (opt)                                                        \
262                 isl_arg_set_defaults(arg, opt);                         \
263         return opt;                                                     \
264 }                                                                       \
265                                                                         \
266 void prefix ## _free(st *opt)                                           \
267 {                                                                       \
268         isl_arg_free(arg, opt);                                         \
269 }                                                                       \
270                                                                         \
271 int prefix ## _parse(st *opt, int argc, char **argv, unsigned flags)    \
272 {                                                                       \
273         return isl_arg_parse(arg, argc, argv, opt, flags);              \
274 }
275
276 #if defined(__cplusplus)
277 }
278 #endif
279
280 #endif