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