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 */ 229