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