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