xref: /kvmtool/include/kvm/parse-options.h (revision 1dc24dcc723991c63fb7747ff829b1e1eb38975f)
1 #ifndef __PARSE_OPTIONS_H__
2 #define __PARSE_OPTIONS_H__
3 
4 #include <inttypes.h>
5 #include <kvm/util.h>
6 
7 enum parse_opt_type {
8 	/* special types */
9 	OPTION_END,
10 	OPTION_ARGUMENT,
11 	OPTION_GROUP,
12 	/* options with no arguments */
13 	OPTION_BIT,
14 	OPTION_BOOLEAN,
15 	OPTION_INCR,
16 	OPTION_SET_UINT,
17 	OPTION_SET_PTR,
18 	/* options with arguments (usually) */
19 	OPTION_STRING,
20 	OPTION_INTEGER,
21 	OPTION_LONG,
22 	OPTION_CALLBACK,
23 	OPTION_U64,
24 	OPTION_UINTEGER,
25 };
26 
27 enum parse_opt_flags {
28 	PARSE_OPT_KEEP_DASHDASH = 1,
29 	PARSE_OPT_STOP_AT_NON_OPTION = 2,
30 	PARSE_OPT_KEEP_ARGV0 = 4,
31 	PARSE_OPT_KEEP_UNKNOWN = 8,
32 	PARSE_OPT_NO_INTERNAL_HELP = 16,
33 };
34 
35 enum parse_opt_option_flags {
36 	PARSE_OPT_OPTARG  = 1,
37 	PARSE_OPT_NOARG   = 2,
38 	PARSE_OPT_NONEG   = 4,
39 	PARSE_OPT_HIDDEN  = 8,
40 	PARSE_OPT_LASTARG_DEFAULT = 16,
41 };
42 
43 struct option;
44 typedef int parse_opt_cb(const struct option *, const char *arg, int unset);
45 /*
46  * `type`::
47  *   holds the type of the option, you must have an OPTION_END last in your
48  *   array.
49  *
50  * `short_name`::
51  *   the character to use as a short option name, '\0' if none.
52  *
53  * `long_name`::
54  *   the long option name, without the leading dashes, NULL if none.
55  *
56  * `value`::
57  *   stores pointers to the values to be filled.
58  *
59  * `argh`::
60  *   token to explain the kind of argument this option wants. Keep it
61  *   homogenous across the repository.
62  *
63  * `help`::
64  *   the short help associated to what the option does.
65  *   Must never be NULL (except for OPTION_END).
66  *   OPTION_GROUP uses this pointer to store the group header.
67  *
68  * `flags`::
69  *   mask of parse_opt_option_flags.
70  *   PARSE_OPT_OPTARG: says that the argument is optionnal (not for BOOLEANs)
71  *   PARSE_OPT_NOARG: says that this option takes no argument, for CALLBACKs
72  *   PARSE_OPT_NONEG: says that this option cannot be negated
73  *   PARSE_OPT_HIDDEN this option is skipped in the default usage, showed in
74  *                    the long one.
75  *
76  * `callback`::
77  *   pointer to the callback to use for OPTION_CALLBACK.
78  *
79  * `defval`::
80  *   default value to fill (*->value) with for PARSE_OPT_OPTARG.
81  *   OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in
82  *   the value when met.
83  *   CALLBACKS can use it like they want.
84  */
85 struct option {
86 enum parse_opt_type type;
87 int short_name;
88 const char *long_name;
89 void *value;
90 const char *argh;
91 const char *help;
92 void *ptr;
93 
94 int flags;
95 parse_opt_cb *callback;
96 intptr_t defval;
97 };
98 
99 #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
100 #define check_vtype(v, type) \
101 	(BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v)
102 
103 #define OPT_INTEGER(s, l, v, h)             \
104 {                                           \
105 	.type = OPTION_INTEGER,             \
106 	.short_name = (s),                  \
107 	.long_name = (l),                   \
108 	.value = check_vtype(v, int *),     \
109 	.help = (h)                         \
110 }
111 
112 #define OPT_U64(s, l, v, h)                 \
113 {                                           \
114 	.type = OPTION_U64,                 \
115 	.short_name = (s),                  \
116 	.long_name = (l),                   \
117 	.value = check_vtype(v, u64 *),     \
118 	.help = (h)                         \
119 }
120 
121 #define OPT_STRING(s, l, v, a, h)           \
122 {                                           \
123 	.type = OPTION_STRING,              \
124 	.short_name = (s),                  \
125 	.long_name = (l),                   \
126 	.value = check_vtype(v, const char **), (a), \
127 	.help = (h)                         \
128 }
129 
130 #define OPT_BOOLEAN(s, l, v, h)             \
131 {                                           \
132 	.type = OPTION_BOOLEAN,             \
133 	.short_name = (s),                  \
134 	.long_name = (l),                   \
135 	.value = check_vtype(v, bool *),    \
136 	.help = (h)                         \
137 }
138 
139 #define OPT_INCR(s, l, v, h)                \
140 {                                           \
141 	.type = OPTION_INCR,	            \
142 	.short_name = (s),                  \
143 	.long_name = (l),                   \
144 	.value = check_vtype(v, int *),     \
145 	.help = (h)                         \
146 }
147 
148 #define OPT_GROUP(h)                        \
149 {                                           \
150 	.type = OPTION_GROUP,               \
151 	.help = (h)                         \
152 }
153 
154 #define OPT_CALLBACK(s, l, v, a, h, f, p)   \
155 {					    \
156 	.type = OPTION_CALLBACK,	    \
157 	.short_name = (s),		    \
158 	.long_name = (l),		    \
159 	.value = (v),			    \
160 	(a),				    \
161 	.help = (h),			    \
162 	.callback = (f),		    \
163 	.ptr = (p),			    \
164 }
165 
166 #define OPT_CALLBACK_NOOPT(s, l, v, a, h, f, p) \
167 {					    \
168 	.type = OPTION_CALLBACK,	    \
169 	.short_name = (s),		    \
170 	.long_name = (l),		    \
171 	.value = (v),			    \
172 	(a),				    \
173 	.help = (h),			    \
174 	.callback = (f),		    \
175 	.flags = PARSE_OPT_NOARG,	    \
176 	.ptr = (p),			    \
177 }
178 
179 #define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d, p) \
180 {					    \
181 	.type = OPTION_CALLBACK,	    \
182 	.short_name = (s),		    \
183 	.long_name = (l),		    \
184 	.value = (v), (a),		    \
185 	.help = (h),			    \
186 	.callback = (f),		    \
187 	.defval = (intptr_t)d,		    \
188 	.flags = PARSE_OPT_LASTARG_DEFAULT, \
189 	.ptr = (p)			    \
190 }
191 
192 #define OPT_END() { .type = OPTION_END }
193 
194 enum {
195 	PARSE_OPT_HELP = -1,
196 	PARSE_OPT_DONE,
197 	PARSE_OPT_UNKNOWN,
198 };
199 
200 /*
201  * It's okay for the caller to consume argv/argc in the usual way.
202  * Other fields of that structure are private to parse-options and should not
203  * be modified in any way.
204  **/
205 struct parse_opt_ctx_t {
206 	const char **argv;
207 	const char **out;
208 	int argc, cpidx;
209 	const char *opt;
210 	int flags;
211 };
212 
213 /* global functions */
214 void usage_with_options(const char * const *usagestr,
215 		const struct option *opts) NORETURN;
216 int parse_options(int argc, const char **argv, const struct option *options,
217 		const char * const usagestr[], int flags);
218 #endif
219