diff options
author | Namhyung Kim <namhyung@kernel.org> | 2016-10-23 23:00:02 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2016-10-25 09:12:16 -0400 |
commit | 369a2478973a416a2c42a37a8cf7031872a6d926 (patch) | |
tree | 2f59cd5560b246452d6702e8caefc162c4235a69 | |
parent | 8a06b0be6507f97f3aa92ca814335b8b65fd3de2 (diff) |
tools lib subcmd: Suppport cascading options
Sometimes subcommand have common options and it can only handled in the
upper level command unless it duplicates the options.
This patch adds a parent field and fallback to the parent if the given
argument was not found in the current options.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/20161024030003.28534-1-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/lib/subcmd/parse-options.c | 14 | ||||
-rw-r--r-- | tools/lib/subcmd/parse-options.h | 2 |
2 files changed, 16 insertions, 0 deletions
diff --git a/tools/lib/subcmd/parse-options.c b/tools/lib/subcmd/parse-options.c index 981bb4481fd5..3284bb14ae78 100644 --- a/tools/lib/subcmd/parse-options.c +++ b/tools/lib/subcmd/parse-options.c | |||
@@ -314,12 +314,19 @@ static int get_value(struct parse_opt_ctx_t *p, | |||
314 | 314 | ||
315 | static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options) | 315 | static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options) |
316 | { | 316 | { |
317 | retry: | ||
317 | for (; options->type != OPTION_END; options++) { | 318 | for (; options->type != OPTION_END; options++) { |
318 | if (options->short_name == *p->opt) { | 319 | if (options->short_name == *p->opt) { |
319 | p->opt = p->opt[1] ? p->opt + 1 : NULL; | 320 | p->opt = p->opt[1] ? p->opt + 1 : NULL; |
320 | return get_value(p, options, OPT_SHORT); | 321 | return get_value(p, options, OPT_SHORT); |
321 | } | 322 | } |
322 | } | 323 | } |
324 | |||
325 | if (options->parent) { | ||
326 | options = options->parent; | ||
327 | goto retry; | ||
328 | } | ||
329 | |||
323 | return -2; | 330 | return -2; |
324 | } | 331 | } |
325 | 332 | ||
@@ -333,6 +340,7 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg, | |||
333 | if (!arg_end) | 340 | if (!arg_end) |
334 | arg_end = arg + strlen(arg); | 341 | arg_end = arg + strlen(arg); |
335 | 342 | ||
343 | retry: | ||
336 | for (; options->type != OPTION_END; options++) { | 344 | for (; options->type != OPTION_END; options++) { |
337 | const char *rest; | 345 | const char *rest; |
338 | int flags = 0; | 346 | int flags = 0; |
@@ -426,6 +434,12 @@ match: | |||
426 | } | 434 | } |
427 | if (abbrev_option) | 435 | if (abbrev_option) |
428 | return get_value(p, abbrev_option, abbrev_flags); | 436 | return get_value(p, abbrev_option, abbrev_flags); |
437 | |||
438 | if (options->parent) { | ||
439 | options = options->parent; | ||
440 | goto retry; | ||
441 | } | ||
442 | |||
429 | return -2; | 443 | return -2; |
430 | } | 444 | } |
431 | 445 | ||
diff --git a/tools/lib/subcmd/parse-options.h b/tools/lib/subcmd/parse-options.h index d60cab2726da..8866ac438b34 100644 --- a/tools/lib/subcmd/parse-options.h +++ b/tools/lib/subcmd/parse-options.h | |||
@@ -109,11 +109,13 @@ struct option { | |||
109 | intptr_t defval; | 109 | intptr_t defval; |
110 | bool *set; | 110 | bool *set; |
111 | void *data; | 111 | void *data; |
112 | const struct option *parent; | ||
112 | }; | 113 | }; |
113 | 114 | ||
114 | #define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v ) | 115 | #define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v ) |
115 | 116 | ||
116 | #define OPT_END() { .type = OPTION_END } | 117 | #define OPT_END() { .type = OPTION_END } |
118 | #define OPT_PARENT(p) { .type = OPTION_END, .parent = (p) } | ||
117 | #define OPT_ARGUMENT(l, h) { .type = OPTION_ARGUMENT, .long_name = (l), .help = (h) } | 119 | #define OPT_ARGUMENT(l, h) { .type = OPTION_ARGUMENT, .long_name = (l), .help = (h) } |
118 | #define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } | 120 | #define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } |
119 | #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) } | 121 | #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) } |