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