1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 21843b4e0SJosh Poimboeuf #ifndef __SUBCMD_PARSE_OPTIONS_H 31843b4e0SJosh Poimboeuf #define __SUBCMD_PARSE_OPTIONS_H 44b6ab94eSJosh Poimboeuf 5d5f805c0SArnaldo Carvalho de Melo #include <linux/kernel.h> 64b6ab94eSJosh Poimboeuf #include <stdbool.h> 74b6ab94eSJosh Poimboeuf #include <stdint.h> 84b6ab94eSJosh Poimboeuf 94b6ab94eSJosh Poimboeuf enum parse_opt_type { 104b6ab94eSJosh Poimboeuf /* special types */ 114b6ab94eSJosh Poimboeuf OPTION_END, 124b6ab94eSJosh Poimboeuf OPTION_ARGUMENT, 134b6ab94eSJosh Poimboeuf OPTION_GROUP, 144b6ab94eSJosh Poimboeuf /* options with no arguments */ 154b6ab94eSJosh Poimboeuf OPTION_BIT, 164b6ab94eSJosh Poimboeuf OPTION_BOOLEAN, 174b6ab94eSJosh Poimboeuf OPTION_INCR, 184b6ab94eSJosh Poimboeuf OPTION_SET_UINT, 194b6ab94eSJosh Poimboeuf OPTION_SET_PTR, 204b6ab94eSJosh Poimboeuf /* options with arguments (usually) */ 214b6ab94eSJosh Poimboeuf OPTION_STRING, 224b6ab94eSJosh Poimboeuf OPTION_INTEGER, 234b6ab94eSJosh Poimboeuf OPTION_LONG, 244ba8b3ebSArnaldo Carvalho de Melo OPTION_ULONG, 254b6ab94eSJosh Poimboeuf OPTION_CALLBACK, 264b6ab94eSJosh Poimboeuf OPTION_U64, 274b6ab94eSJosh Poimboeuf OPTION_UINTEGER, 284b6ab94eSJosh Poimboeuf }; 294b6ab94eSJosh Poimboeuf 304b6ab94eSJosh Poimboeuf enum parse_opt_flags { 314b6ab94eSJosh Poimboeuf PARSE_OPT_KEEP_DASHDASH = 1, 324b6ab94eSJosh Poimboeuf PARSE_OPT_STOP_AT_NON_OPTION = 2, 334b6ab94eSJosh Poimboeuf PARSE_OPT_KEEP_ARGV0 = 4, 344b6ab94eSJosh Poimboeuf PARSE_OPT_KEEP_UNKNOWN = 8, 354b6ab94eSJosh Poimboeuf PARSE_OPT_NO_INTERNAL_HELP = 16, 364b6ab94eSJosh Poimboeuf }; 374b6ab94eSJosh Poimboeuf 384b6ab94eSJosh Poimboeuf enum parse_opt_option_flags { 394b6ab94eSJosh Poimboeuf PARSE_OPT_OPTARG = 1, 404b6ab94eSJosh Poimboeuf PARSE_OPT_NOARG = 2, 414b6ab94eSJosh Poimboeuf PARSE_OPT_NONEG = 4, 424b6ab94eSJosh Poimboeuf PARSE_OPT_HIDDEN = 8, 434b6ab94eSJosh Poimboeuf PARSE_OPT_LASTARG_DEFAULT = 16, 444b6ab94eSJosh Poimboeuf PARSE_OPT_DISABLED = 32, 454b6ab94eSJosh Poimboeuf PARSE_OPT_EXCLUSIVE = 64, 464b6ab94eSJosh Poimboeuf PARSE_OPT_NOEMPTY = 128, 474b6ab94eSJosh Poimboeuf PARSE_OPT_NOBUILD = 256, 484b6ab94eSJosh Poimboeuf PARSE_OPT_CANSKIP = 512, 494b6ab94eSJosh Poimboeuf }; 504b6ab94eSJosh Poimboeuf 514b6ab94eSJosh Poimboeuf struct option; 524b6ab94eSJosh Poimboeuf typedef int parse_opt_cb(const struct option *, const char *arg, int unset); 534b6ab94eSJosh Poimboeuf 544b6ab94eSJosh Poimboeuf /* 554b6ab94eSJosh Poimboeuf * `type`:: 564b6ab94eSJosh Poimboeuf * holds the type of the option, you must have an OPTION_END last in your 574b6ab94eSJosh Poimboeuf * array. 584b6ab94eSJosh Poimboeuf * 594b6ab94eSJosh Poimboeuf * `short_name`:: 604b6ab94eSJosh Poimboeuf * the character to use as a short option name, '\0' if none. 614b6ab94eSJosh Poimboeuf * 624b6ab94eSJosh Poimboeuf * `long_name`:: 634b6ab94eSJosh Poimboeuf * the long option name, without the leading dashes, NULL if none. 644b6ab94eSJosh Poimboeuf * 654b6ab94eSJosh Poimboeuf * `value`:: 664b6ab94eSJosh Poimboeuf * stores pointers to the values to be filled. 674b6ab94eSJosh Poimboeuf * 684b6ab94eSJosh Poimboeuf * `argh`:: 694b6ab94eSJosh Poimboeuf * token to explain the kind of argument this option wants. Keep it 7065c9fee2SIngo Molnar * homogeneous across the repository. 714b6ab94eSJosh Poimboeuf * 724b6ab94eSJosh Poimboeuf * `help`:: 734b6ab94eSJosh Poimboeuf * the short help associated to what the option does. 744b6ab94eSJosh Poimboeuf * Must never be NULL (except for OPTION_END). 754b6ab94eSJosh Poimboeuf * OPTION_GROUP uses this pointer to store the group header. 764b6ab94eSJosh Poimboeuf * 774b6ab94eSJosh Poimboeuf * `flags`:: 784b6ab94eSJosh Poimboeuf * mask of parse_opt_option_flags. 7965c9fee2SIngo Molnar * PARSE_OPT_OPTARG: says that the argument is optional (not for BOOLEANs) 804b6ab94eSJosh Poimboeuf * PARSE_OPT_NOARG: says that this option takes no argument, for CALLBACKs 814b6ab94eSJosh Poimboeuf * PARSE_OPT_NONEG: says that this option cannot be negated 824b6ab94eSJosh Poimboeuf * PARSE_OPT_HIDDEN this option is skipped in the default usage, showed in 834b6ab94eSJosh Poimboeuf * the long one. 844b6ab94eSJosh Poimboeuf * 854b6ab94eSJosh Poimboeuf * `callback`:: 864b6ab94eSJosh Poimboeuf * pointer to the callback to use for OPTION_CALLBACK. 874b6ab94eSJosh Poimboeuf * 884b6ab94eSJosh Poimboeuf * `defval`:: 894b6ab94eSJosh Poimboeuf * default value to fill (*->value) with for PARSE_OPT_OPTARG. 904b6ab94eSJosh Poimboeuf * OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in 914b6ab94eSJosh Poimboeuf * the value when met. 924b6ab94eSJosh Poimboeuf * CALLBACKS can use it like they want. 934b6ab94eSJosh Poimboeuf * 944b6ab94eSJosh Poimboeuf * `set`:: 954b6ab94eSJosh Poimboeuf * whether an option was set by the user 964b6ab94eSJosh Poimboeuf */ 974b6ab94eSJosh Poimboeuf struct option { 984b6ab94eSJosh Poimboeuf enum parse_opt_type type; 994b6ab94eSJosh Poimboeuf int short_name; 1004b6ab94eSJosh Poimboeuf const char *long_name; 1014b6ab94eSJosh Poimboeuf void *value; 1024b6ab94eSJosh Poimboeuf const char *argh; 1034b6ab94eSJosh Poimboeuf const char *help; 1044b6ab94eSJosh Poimboeuf const char *build_opt; 1054b6ab94eSJosh Poimboeuf 1064b6ab94eSJosh Poimboeuf int flags; 1074b6ab94eSJosh Poimboeuf parse_opt_cb *callback; 1084b6ab94eSJosh Poimboeuf intptr_t defval; 1094b6ab94eSJosh Poimboeuf bool *set; 1104b6ab94eSJosh Poimboeuf void *data; 111369a2478SNamhyung Kim const struct option *parent; 1124b6ab94eSJosh Poimboeuf }; 1134b6ab94eSJosh Poimboeuf 1144b6ab94eSJosh Poimboeuf #define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v ) 1154b6ab94eSJosh Poimboeuf 1164b6ab94eSJosh Poimboeuf #define OPT_END() { .type = OPTION_END } 117369a2478SNamhyung Kim #define OPT_PARENT(p) { .type = OPTION_END, .parent = (p) } 1184b6ab94eSJosh Poimboeuf #define OPT_ARGUMENT(l, h) { .type = OPTION_ARGUMENT, .long_name = (l), .help = (h) } 1194b6ab94eSJosh Poimboeuf #define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } 1204b6ab94eSJosh Poimboeuf #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) } 1214b6ab94eSJosh Poimboeuf #define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) } 1224b6ab94eSJosh Poimboeuf #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) } 1234b6ab94eSJosh Poimboeuf #define OPT_BOOLEAN_SET(s, l, v, os, h) \ 1244b6ab94eSJosh Poimboeuf { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), \ 1254b6ab94eSJosh Poimboeuf .value = check_vtype(v, bool *), .help = (h), \ 1264b6ab94eSJosh Poimboeuf .set = check_vtype(os, bool *)} 1274b6ab94eSJosh Poimboeuf #define OPT_INCR(s, l, v, h) { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) } 1284b6ab94eSJosh Poimboeuf #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) } 1294b6ab94eSJosh Poimboeuf #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) } 1304b6ab94eSJosh Poimboeuf #define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) } 1314b6ab94eSJosh Poimboeuf #define OPT_UINTEGER(s, l, v, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h) } 132b75f299dSRiccardo Mancini #define OPT_UINTEGER_OPTARG(s, l, v, d, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h), .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d) } 1334b6ab94eSJosh Poimboeuf #define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) } 1344ba8b3ebSArnaldo Carvalho de Melo #define OPT_ULONG(s, l, v, h) { .type = OPTION_ULONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned long *), .help = (h) } 1354b6ab94eSJosh Poimboeuf #define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) } 136f7ee6595SSoramichi AKIYAMA #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) } 1374b6ab94eSJosh Poimboeuf #define OPT_STRING_OPTARG(s, l, v, a, h, d) \ 1384b6ab94eSJosh Poimboeuf { .type = OPTION_STRING, .short_name = (s), .long_name = (l), \ 139f7ee6595SSoramichi AKIYAMA .value = check_vtype(v, const char **), .argh =(a), .help = (h), \ 1404b6ab94eSJosh Poimboeuf .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d) } 141b66fb1daSJiri Olsa #define OPT_STRING_OPTARG_SET(s, l, v, os, a, h, d) \ 142b66fb1daSJiri Olsa { .type = OPTION_STRING, .short_name = (s), .long_name = (l), \ 143f7ee6595SSoramichi AKIYAMA .value = check_vtype(v, const char **), .argh = (a), .help = (h), \ 144b66fb1daSJiri Olsa .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d), \ 145b66fb1daSJiri Olsa .set = check_vtype(os, bool *)} 146f7ee6595SSoramichi AKIYAMA #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} 1474b6ab94eSJosh Poimboeuf #define OPT_DATE(s, l, v, h) \ 1484b6ab94eSJosh Poimboeuf { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb } 1494b6ab94eSJosh Poimboeuf #define OPT_CALLBACK(s, l, v, a, h, f) \ 150f7ee6595SSoramichi AKIYAMA { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = (a), .help = (h), .callback = (f) } 151636eb4d0SArnaldo Carvalho de Melo #define OPT_CALLBACK_SET(s, l, v, os, a, h, f) \ 152636eb4d0SArnaldo Carvalho de Melo { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = (a), .help = (h), .callback = (f), .set = check_vtype(os, bool *)} 1534b6ab94eSJosh Poimboeuf #define OPT_CALLBACK_NOOPT(s, l, v, a, h, f) \ 154f7ee6595SSoramichi AKIYAMA { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = (a), .help = (h), .callback = (f), .flags = PARSE_OPT_NOARG } 1554b6ab94eSJosh Poimboeuf #define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \ 156f7ee6595SSoramichi AKIYAMA { .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 } 1574b6ab94eSJosh Poimboeuf #define OPT_CALLBACK_DEFAULT_NOOPT(s, l, v, a, h, f, d) \ 1584b6ab94eSJosh Poimboeuf { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l),\ 159f7ee6595SSoramichi AKIYAMA .value = (v), .arg = (a), .help = (h), .callback = (f), .defval = (intptr_t)d,\ 1604b6ab94eSJosh Poimboeuf .flags = PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NOARG} 1614b6ab94eSJosh Poimboeuf #define OPT_CALLBACK_OPTARG(s, l, v, d, a, h, f) \ 1624b6ab94eSJosh Poimboeuf { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), \ 163f7ee6595SSoramichi AKIYAMA .value = (v), .argh = (a), .help = (h), .callback = (f), \ 1644b6ab94eSJosh Poimboeuf .flags = PARSE_OPT_OPTARG, .data = (d) } 1654b6ab94eSJosh Poimboeuf 1664b6ab94eSJosh Poimboeuf /* parse_options() will filter out the processed options and leave the 1674b6ab94eSJosh Poimboeuf * non-option argments in argv[]. 1684b6ab94eSJosh Poimboeuf * Returns the number of arguments left in argv[]. 1694b6ab94eSJosh Poimboeuf * 1704b6ab94eSJosh Poimboeuf * NOTE: parse_options() and parse_options_subcommand() may call exit() in the 1714b6ab94eSJosh Poimboeuf * case of an error (or for 'special' options like --list-cmds or --list-opts). 1724b6ab94eSJosh Poimboeuf */ 1734b6ab94eSJosh Poimboeuf extern int parse_options(int argc, const char **argv, 1744b6ab94eSJosh Poimboeuf const struct option *options, 1754b6ab94eSJosh Poimboeuf const char * const usagestr[], int flags); 1764b6ab94eSJosh Poimboeuf 1774b6ab94eSJosh Poimboeuf extern int parse_options_subcommand(int argc, const char **argv, 1784b6ab94eSJosh Poimboeuf const struct option *options, 1794b6ab94eSJosh Poimboeuf const char *const subcommands[], 1804b6ab94eSJosh Poimboeuf const char *usagestr[], int flags); 1814b6ab94eSJosh Poimboeuf 182*d59fec29SJosh Poimboeuf extern __noreturn void usage_with_options(const char * const *usagestr, 1834b6ab94eSJosh Poimboeuf const struct option *options); 184*d59fec29SJosh Poimboeuf extern __noreturn __attribute__((format(printf,3,4))) 1854b6ab94eSJosh Poimboeuf void usage_with_options_msg(const char * const *usagestr, 1864b6ab94eSJosh Poimboeuf const struct option *options, 1874b6ab94eSJosh Poimboeuf const char *fmt, ...); 1884b6ab94eSJosh Poimboeuf 1894b6ab94eSJosh Poimboeuf /*----- incremantal advanced APIs -----*/ 1904b6ab94eSJosh Poimboeuf 1914b6ab94eSJosh Poimboeuf enum { 1924b6ab94eSJosh Poimboeuf PARSE_OPT_HELP = -1, 1934b6ab94eSJosh Poimboeuf PARSE_OPT_DONE, 1944b6ab94eSJosh Poimboeuf PARSE_OPT_LIST_OPTS, 1954b6ab94eSJosh Poimboeuf PARSE_OPT_LIST_SUBCMDS, 1964b6ab94eSJosh Poimboeuf PARSE_OPT_UNKNOWN, 1974b6ab94eSJosh Poimboeuf }; 1984b6ab94eSJosh Poimboeuf 1994b6ab94eSJosh Poimboeuf /* 2004b6ab94eSJosh Poimboeuf * It's okay for the caller to consume argv/argc in the usual way. 2014b6ab94eSJosh Poimboeuf * Other fields of that structure are private to parse-options and should not 2024b6ab94eSJosh Poimboeuf * be modified in any way. 2034b6ab94eSJosh Poimboeuf */ 2044b6ab94eSJosh Poimboeuf struct parse_opt_ctx_t { 2054b6ab94eSJosh Poimboeuf const char **argv; 2064b6ab94eSJosh Poimboeuf const char **out; 2074b6ab94eSJosh Poimboeuf int argc, cpidx; 2084b6ab94eSJosh Poimboeuf const char *opt; 2094b6ab94eSJosh Poimboeuf const struct option *excl_opt; 2104b6ab94eSJosh Poimboeuf int flags; 2114b6ab94eSJosh Poimboeuf }; 2124b6ab94eSJosh Poimboeuf 2134b6ab94eSJosh Poimboeuf extern int parse_options_usage(const char * const *usagestr, 2144b6ab94eSJosh Poimboeuf const struct option *opts, 2154b6ab94eSJosh Poimboeuf const char *optstr, 2164b6ab94eSJosh Poimboeuf bool short_opt); 2174b6ab94eSJosh Poimboeuf 2184b6ab94eSJosh Poimboeuf 2194b6ab94eSJosh Poimboeuf /*----- some often used options -----*/ 2204b6ab94eSJosh Poimboeuf extern int parse_opt_abbrev_cb(const struct option *, const char *, int); 2214b6ab94eSJosh Poimboeuf extern int parse_opt_approxidate_cb(const struct option *, const char *, int); 2224b6ab94eSJosh Poimboeuf extern int parse_opt_verbosity_cb(const struct option *, const char *, int); 2234b6ab94eSJosh Poimboeuf 2244b6ab94eSJosh Poimboeuf #define OPT__VERBOSE(var) OPT_BOOLEAN('v', "verbose", (var), "be verbose") 2254b6ab94eSJosh Poimboeuf #define OPT__QUIET(var) OPT_BOOLEAN('q', "quiet", (var), "be quiet") 2264b6ab94eSJosh Poimboeuf #define OPT__VERBOSITY(var) \ 2274b6ab94eSJosh Poimboeuf { OPTION_CALLBACK, 'v', "verbose", (var), NULL, "be more verbose", \ 2284b6ab94eSJosh Poimboeuf PARSE_OPT_NOARG, &parse_opt_verbosity_cb, 0 }, \ 2294b6ab94eSJosh Poimboeuf { OPTION_CALLBACK, 'q', "quiet", (var), NULL, "be more quiet", \ 2304b6ab94eSJosh Poimboeuf PARSE_OPT_NOARG, &parse_opt_verbosity_cb, 0 } 2314b6ab94eSJosh Poimboeuf #define OPT__DRY_RUN(var) OPT_BOOLEAN('n', "dry-run", (var), "dry run") 2324b6ab94eSJosh Poimboeuf #define OPT__ABBREV(var) \ 2334b6ab94eSJosh Poimboeuf { OPTION_CALLBACK, 0, "abbrev", (var), "n", \ 2344b6ab94eSJosh Poimboeuf "use <n> digits to display SHA-1s", \ 2354b6ab94eSJosh Poimboeuf PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 } 2364b6ab94eSJosh Poimboeuf 2374b6ab94eSJosh Poimboeuf extern const char *parse_options_fix_filename(const char *prefix, const char *file); 2384b6ab94eSJosh Poimboeuf 2394b6ab94eSJosh Poimboeuf void set_option_flag(struct option *opts, int sopt, const char *lopt, int flag); 2404b6ab94eSJosh Poimboeuf void set_option_nobuild(struct option *opts, int shortopt, const char *longopt, 2414b6ab94eSJosh Poimboeuf const char *build_opt, bool can_skip); 2421843b4e0SJosh Poimboeuf 2431843b4e0SJosh Poimboeuf #endif /* __SUBCMD_PARSE_OPTIONS_H */ 244