diff options
Diffstat (limited to 'tools/lib/subcmd/parse-options.h')
-rw-r--r-- | tools/lib/subcmd/parse-options.h | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/tools/lib/subcmd/parse-options.h b/tools/lib/subcmd/parse-options.h new file mode 100644 index 000000000000..dec893f10477 --- /dev/null +++ b/tools/lib/subcmd/parse-options.h | |||
@@ -0,0 +1,228 @@ | |||
1 | #ifndef __PERF_PARSE_OPTIONS_H | ||
2 | #define __PERF_PARSE_OPTIONS_H | ||
3 | |||
4 | #include <stdbool.h> | ||
5 | #include <stdint.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 | PARSE_OPT_DISABLED = 32, | ||
42 | PARSE_OPT_EXCLUSIVE = 64, | ||
43 | PARSE_OPT_NOEMPTY = 128, | ||
44 | PARSE_OPT_NOBUILD = 256, | ||
45 | PARSE_OPT_CANSKIP = 512, | ||
46 | }; | ||
47 | |||
48 | struct option; | ||
49 | typedef int parse_opt_cb(const struct option *, const char *arg, int unset); | ||
50 | |||
51 | /* | ||
52 | * `type`:: | ||
53 | * holds the type of the option, you must have an OPTION_END last in your | ||
54 | * array. | ||
55 | * | ||
56 | * `short_name`:: | ||
57 | * the character to use as a short option name, '\0' if none. | ||
58 | * | ||
59 | * `long_name`:: | ||
60 | * the long option name, without the leading dashes, NULL if none. | ||
61 | * | ||
62 | * `value`:: | ||
63 | * stores pointers to the values to be filled. | ||
64 | * | ||
65 | * `argh`:: | ||
66 | * token to explain the kind of argument this option wants. Keep it | ||
67 | * homogenous across the repository. | ||
68 | * | ||
69 | * `help`:: | ||
70 | * the short help associated to what the option does. | ||
71 | * Must never be NULL (except for OPTION_END). | ||
72 | * OPTION_GROUP uses this pointer to store the group header. | ||
73 | * | ||
74 | * `flags`:: | ||
75 | * mask of parse_opt_option_flags. | ||
76 | * PARSE_OPT_OPTARG: says that the argument is optionnal (not for BOOLEANs) | ||
77 | * PARSE_OPT_NOARG: says that this option takes no argument, for CALLBACKs | ||
78 | * PARSE_OPT_NONEG: says that this option cannot be negated | ||
79 | * PARSE_OPT_HIDDEN this option is skipped in the default usage, showed in | ||
80 | * the long one. | ||
81 | * | ||
82 | * `callback`:: | ||
83 | * pointer to the callback to use for OPTION_CALLBACK. | ||
84 | * | ||
85 | * `defval`:: | ||
86 | * default value to fill (*->value) with for PARSE_OPT_OPTARG. | ||
87 | * OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in | ||
88 | * the value when met. | ||
89 | * CALLBACKS can use it like they want. | ||
90 | * | ||
91 | * `set`:: | ||
92 | * whether an option was set by the user | ||
93 | */ | ||
94 | struct option { | ||
95 | enum parse_opt_type type; | ||
96 | int short_name; | ||
97 | const char *long_name; | ||
98 | void *value; | ||
99 | const char *argh; | ||
100 | const char *help; | ||
101 | const char *build_opt; | ||
102 | |||
103 | int flags; | ||
104 | parse_opt_cb *callback; | ||
105 | intptr_t defval; | ||
106 | bool *set; | ||
107 | void *data; | ||
108 | }; | ||
109 | |||
110 | #define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v ) | ||
111 | |||
112 | #define OPT_END() { .type = OPTION_END } | ||
113 | #define OPT_ARGUMENT(l, h) { .type = OPTION_ARGUMENT, .long_name = (l), .help = (h) } | ||
114 | #define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } | ||
115 | #define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) } | ||
116 | #define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) } | ||
117 | #define OPT_BOOLEAN_FLAG(s, l, v, h, f) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h), .flags = (f) } | ||
118 | #define OPT_BOOLEAN_SET(s, l, v, os, h) \ | ||
119 | { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), \ | ||
120 | .value = check_vtype(v, bool *), .help = (h), \ | ||
121 | .set = check_vtype(os, bool *)} | ||
122 | #define OPT_INCR(s, l, v, h) { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) } | ||
123 | #define OPT_SET_UINT(s, l, v, h, i) { .type = OPTION_SET_UINT, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h), .defval = (i) } | ||
124 | #define OPT_SET_PTR(s, l, v, h, p) { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) } | ||
125 | #define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) } | ||
126 | #define OPT_UINTEGER(s, l, v, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h) } | ||
127 | #define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) } | ||
128 | #define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) } | ||
129 | #define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) } | ||
130 | #define OPT_STRING_OPTARG(s, l, v, a, h, d) \ | ||
131 | { .type = OPTION_STRING, .short_name = (s), .long_name = (l), \ | ||
132 | .value = check_vtype(v, const char **), (a), .help = (h), \ | ||
133 | .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d) } | ||
134 | #define OPT_STRING_NOEMPTY(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h), .flags = PARSE_OPT_NOEMPTY} | ||
135 | #define OPT_DATE(s, l, v, h) \ | ||
136 | { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb } | ||
137 | #define OPT_CALLBACK(s, l, v, a, h, f) \ | ||
138 | { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f) } | ||
139 | #define OPT_CALLBACK_NOOPT(s, l, v, a, h, f) \ | ||
140 | { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .flags = PARSE_OPT_NOARG } | ||
141 | #define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \ | ||
142 | { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT } | ||
143 | #define OPT_CALLBACK_DEFAULT_NOOPT(s, l, v, a, h, f, d) \ | ||
144 | { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l),\ | ||
145 | .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d,\ | ||
146 | .flags = PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NOARG} | ||
147 | #define OPT_CALLBACK_OPTARG(s, l, v, d, a, h, f) \ | ||
148 | { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), \ | ||
149 | .value = (v), (a), .help = (h), .callback = (f), \ | ||
150 | .flags = PARSE_OPT_OPTARG, .data = (d) } | ||
151 | |||
152 | /* parse_options() will filter out the processed options and leave the | ||
153 | * non-option argments in argv[]. | ||
154 | * Returns the number of arguments left in argv[]. | ||
155 | * | ||
156 | * NOTE: parse_options() and parse_options_subcommand() may call exit() in the | ||
157 | * case of an error (or for 'special' options like --list-cmds or --list-opts). | ||
158 | */ | ||
159 | extern int parse_options(int argc, const char **argv, | ||
160 | const struct option *options, | ||
161 | const char * const usagestr[], int flags); | ||
162 | |||
163 | extern int parse_options_subcommand(int argc, const char **argv, | ||
164 | const struct option *options, | ||
165 | const char *const subcommands[], | ||
166 | const char *usagestr[], int flags); | ||
167 | |||
168 | extern NORETURN void usage_with_options(const char * const *usagestr, | ||
169 | const struct option *options); | ||
170 | extern NORETURN __attribute__((format(printf,3,4))) | ||
171 | void usage_with_options_msg(const char * const *usagestr, | ||
172 | const struct option *options, | ||
173 | const char *fmt, ...); | ||
174 | |||
175 | /*----- incremantal advanced APIs -----*/ | ||
176 | |||
177 | enum { | ||
178 | PARSE_OPT_HELP = -1, | ||
179 | PARSE_OPT_DONE, | ||
180 | PARSE_OPT_LIST_OPTS, | ||
181 | PARSE_OPT_LIST_SUBCMDS, | ||
182 | PARSE_OPT_UNKNOWN, | ||
183 | }; | ||
184 | |||
185 | /* | ||
186 | * It's okay for the caller to consume argv/argc in the usual way. | ||
187 | * Other fields of that structure are private to parse-options and should not | ||
188 | * be modified in any way. | ||
189 | */ | ||
190 | struct parse_opt_ctx_t { | ||
191 | const char **argv; | ||
192 | const char **out; | ||
193 | int argc, cpidx; | ||
194 | const char *opt; | ||
195 | const struct option *excl_opt; | ||
196 | int flags; | ||
197 | }; | ||
198 | |||
199 | extern int parse_options_usage(const char * const *usagestr, | ||
200 | const struct option *opts, | ||
201 | const char *optstr, | ||
202 | bool short_opt); | ||
203 | |||
204 | |||
205 | /*----- some often used options -----*/ | ||
206 | extern int parse_opt_abbrev_cb(const struct option *, const char *, int); | ||
207 | extern int parse_opt_approxidate_cb(const struct option *, const char *, int); | ||
208 | extern int parse_opt_verbosity_cb(const struct option *, const char *, int); | ||
209 | |||
210 | #define OPT__VERBOSE(var) OPT_BOOLEAN('v', "verbose", (var), "be verbose") | ||
211 | #define OPT__QUIET(var) OPT_BOOLEAN('q', "quiet", (var), "be quiet") | ||
212 | #define OPT__VERBOSITY(var) \ | ||
213 | { OPTION_CALLBACK, 'v', "verbose", (var), NULL, "be more verbose", \ | ||
214 | PARSE_OPT_NOARG, &parse_opt_verbosity_cb, 0 }, \ | ||
215 | { OPTION_CALLBACK, 'q', "quiet", (var), NULL, "be more quiet", \ | ||
216 | PARSE_OPT_NOARG, &parse_opt_verbosity_cb, 0 } | ||
217 | #define OPT__DRY_RUN(var) OPT_BOOLEAN('n', "dry-run", (var), "dry run") | ||
218 | #define OPT__ABBREV(var) \ | ||
219 | { OPTION_CALLBACK, 0, "abbrev", (var), "n", \ | ||
220 | "use <n> digits to display SHA-1s", \ | ||
221 | PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 } | ||
222 | |||
223 | extern const char *parse_options_fix_filename(const char *prefix, const char *file); | ||
224 | |||
225 | void set_option_flag(struct option *opts, int sopt, const char *lopt, int flag); | ||
226 | void set_option_nobuild(struct option *opts, int shortopt, const char *longopt, | ||
227 | const char *build_opt, bool can_skip); | ||
228 | #endif /* __PERF_PARSE_OPTIONS_H */ | ||