xref: /kvmtool/include/kvm/parse-options.h (revision dfb8fd674f5fba45932df92b2045a42d291477d8)
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_UINTEGER(s, l, v, h)            \
113 {                                           \
114 	.type = OPTION_UINTEGER,            \
115 	.short_name = (s),                  \
116 	.long_name = (l),                   \
117 	.value = check_vtype(v, unsigned int *), \
118 	.help = (h)                         \
119 }
120 
121 #define OPT_U64(s, l, v, h)                 \
122 {                                           \
123 	.type = OPTION_U64,                 \
124 	.short_name = (s),                  \
125 	.long_name = (l),                   \
126 	.value = check_vtype(v, u64 *),     \
127 	.help = (h)                         \
128 }
129 
130 #define OPT_STRING(s, l, v, a, h)           \
131 {                                           \
132 	.type = OPTION_STRING,              \
133 	.short_name = (s),                  \
134 	.long_name = (l),                   \
135 	.value = check_vtype(v, const char **), (a), \
136 	.help = (h)                         \
137 }
138 
139 #define OPT_BOOLEAN(s, l, v, h)             \
140 {                                           \
141 	.type = OPTION_BOOLEAN,             \
142 	.short_name = (s),                  \
143 	.long_name = (l),                   \
144 	.value = check_vtype(v, bool *),    \
145 	.help = (h)                         \
146 }
147 
148 #define OPT_INCR(s, l, v, h)                \
149 {                                           \
150 	.type = OPTION_INCR,	            \
151 	.short_name = (s),                  \
152 	.long_name = (l),                   \
153 	.value = check_vtype(v, int *),     \
154 	.help = (h)                         \
155 }
156 
157 #define OPT_GROUP(h)                        \
158 {                                           \
159 	.type = OPTION_GROUP,               \
160 	.help = (h)                         \
161 }
162 
163 #define OPT_CALLBACK(s, l, v, a, h, f, p)   \
164 {					    \
165 	.type = OPTION_CALLBACK,	    \
166 	.short_name = (s),		    \
167 	.long_name = (l),		    \
168 	.value = (v),			    \
169 	(a),				    \
170 	.help = (h),			    \
171 	.callback = (f),		    \
172 	.ptr = (p),			    \
173 }
174 
175 #define OPT_CALLBACK_NOOPT(s, l, v, a, h, f, p) \
176 {					    \
177 	.type = OPTION_CALLBACK,	    \
178 	.short_name = (s),		    \
179 	.long_name = (l),		    \
180 	.value = (v),			    \
181 	(a),				    \
182 	.help = (h),			    \
183 	.callback = (f),		    \
184 	.flags = PARSE_OPT_NOARG,	    \
185 	.ptr = (p),			    \
186 }
187 
188 #define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d, p) \
189 {					    \
190 	.type = OPTION_CALLBACK,	    \
191 	.short_name = (s),		    \
192 	.long_name = (l),		    \
193 	.value = (v), (a),		    \
194 	.help = (h),			    \
195 	.callback = (f),		    \
196 	.defval = (intptr_t)d,		    \
197 	.flags = PARSE_OPT_LASTARG_DEFAULT, \
198 	.ptr = (p)			    \
199 }
200 
201 #define OPT_END() { .type = OPTION_END }
202 
203 #define OPT_ARCH(cmd, cfg)		    \
204 	OPT_ARCH_##cmd(OPT_GROUP("Arch-specific options:"), &(cfg)->arch)
205 
206 enum {
207 	PARSE_OPT_HELP = -1,
208 	PARSE_OPT_DONE,
209 	PARSE_OPT_UNKNOWN,
210 };
211 
212 /*
213  * It's okay for the caller to consume argv/argc in the usual way.
214  * Other fields of that structure are private to parse-options and should not
215  * be modified in any way.
216  **/
217 struct parse_opt_ctx_t {
218 	const char **argv;
219 	const char **out;
220 	int argc, cpidx;
221 	const char *opt;
222 	int flags;
223 };
224 
225 /* global functions */
226 void usage_with_options(const char * const *usagestr,
227 		const struct option *opts) NORETURN;
228 int parse_options(int argc, const char **argv, const struct option *options,
229 		const char * const usagestr[], int flags);
230 #endif
231