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