2 #include "parse-options.h"
9 static int opterror(const struct option
*opt
, const char *reason
, int flags
)
11 if (flags
& OPT_SHORT
)
12 return error("switch `%c' %s", opt
->short_name
, reason
);
13 if (flags
& OPT_UNSET
)
14 return error("option `no-%s' %s", opt
->long_name
, reason
);
15 return error("option `%s' %s", opt
->long_name
, reason
);
18 static int get_arg(struct parse_opt_ctx_t
*p
, const struct option
*opt
,
19 int flags
, const char **arg
)
24 } else if ((opt
->flags
& PARSE_OPT_LASTARG_DEFAULT
) && (p
->argc
== 1 ||
25 **(p
->argv
+ 1) == '-')) {
26 *arg
= (const char *)opt
->defval
;
27 } else if (p
->argc
> 1) {
31 return opterror(opt
, "requires a value", flags
);
35 static int get_value(struct parse_opt_ctx_t
*p
,
36 const struct option
*opt
, int flags
)
38 const char *s
, *arg
= NULL
;
39 const int unset
= flags
& OPT_UNSET
;
42 return opterror(opt
, "takes no value", flags
);
43 if (unset
&& (opt
->flags
& PARSE_OPT_NONEG
))
44 return opterror(opt
, "isn't available", flags
);
45 if (opt
->flags
& PARSE_OPT_DISABLED
)
46 return opterror(opt
, "is not usable", flags
);
48 if (opt
->flags
& PARSE_OPT_EXCLUSIVE
) {
49 if (p
->excl_opt
&& p
->excl_opt
!= opt
) {
52 if (((flags
& OPT_SHORT
) && p
->excl_opt
->short_name
) ||
53 p
->excl_opt
->long_name
== NULL
) {
54 scnprintf(msg
, sizeof(msg
), "cannot be used with switch `%c'",
55 p
->excl_opt
->short_name
);
57 scnprintf(msg
, sizeof(msg
), "cannot be used with %s",
58 p
->excl_opt
->long_name
);
60 opterror(opt
, msg
, flags
);
65 if (!(flags
& OPT_SHORT
) && p
->opt
) {
68 if (!(opt
->flags
& PARSE_OPT_NOARG
))
76 return opterror(opt
, "takes no value", flags
);
93 *(int *)opt
->value
&= ~opt
->defval
;
95 *(int *)opt
->value
|= opt
->defval
;
99 *(bool *)opt
->value
= unset
? false : true;
101 *(bool *)opt
->set
= true;
105 *(int *)opt
->value
= unset
? 0 : *(int *)opt
->value
+ 1;
108 case OPTION_SET_UINT
:
109 *(unsigned int *)opt
->value
= unset
? 0 : opt
->defval
;
113 *(void **)opt
->value
= unset
? NULL
: (void *)opt
->defval
;
118 *(const char **)opt
->value
= NULL
;
119 else if (opt
->flags
& PARSE_OPT_OPTARG
&& !p
->opt
)
120 *(const char **)opt
->value
= (const char *)opt
->defval
;
122 return get_arg(p
, opt
, flags
, (const char **)opt
->value
);
125 case OPTION_CALLBACK
:
127 return (*opt
->callback
)(opt
, NULL
, 1) ? (-1) : 0;
128 if (opt
->flags
& PARSE_OPT_NOARG
)
129 return (*opt
->callback
)(opt
, NULL
, 0) ? (-1) : 0;
130 if (opt
->flags
& PARSE_OPT_OPTARG
&& !p
->opt
)
131 return (*opt
->callback
)(opt
, NULL
, 0) ? (-1) : 0;
132 if (get_arg(p
, opt
, flags
, &arg
))
134 return (*opt
->callback
)(opt
, arg
, 0) ? (-1) : 0;
138 *(int *)opt
->value
= 0;
141 if (opt
->flags
& PARSE_OPT_OPTARG
&& !p
->opt
) {
142 *(int *)opt
->value
= opt
->defval
;
145 if (get_arg(p
, opt
, flags
, &arg
))
147 *(int *)opt
->value
= strtol(arg
, (char **)&s
, 10);
149 return opterror(opt
, "expects a numerical value", flags
);
152 case OPTION_UINTEGER
:
154 *(unsigned int *)opt
->value
= 0;
157 if (opt
->flags
& PARSE_OPT_OPTARG
&& !p
->opt
) {
158 *(unsigned int *)opt
->value
= opt
->defval
;
161 if (get_arg(p
, opt
, flags
, &arg
))
163 *(unsigned int *)opt
->value
= strtol(arg
, (char **)&s
, 10);
165 return opterror(opt
, "expects a numerical value", flags
);
170 *(long *)opt
->value
= 0;
173 if (opt
->flags
& PARSE_OPT_OPTARG
&& !p
->opt
) {
174 *(long *)opt
->value
= opt
->defval
;
177 if (get_arg(p
, opt
, flags
, &arg
))
179 *(long *)opt
->value
= strtol(arg
, (char **)&s
, 10);
181 return opterror(opt
, "expects a numerical value", flags
);
186 *(u64
*)opt
->value
= 0;
189 if (opt
->flags
& PARSE_OPT_OPTARG
&& !p
->opt
) {
190 *(u64
*)opt
->value
= opt
->defval
;
193 if (get_arg(p
, opt
, flags
, &arg
))
195 *(u64
*)opt
->value
= strtoull(arg
, (char **)&s
, 10);
197 return opterror(opt
, "expects a numerical value", flags
);
201 case OPTION_ARGUMENT
:
204 die("should not happen, someone must be hit on the forehead");
208 static int parse_short_opt(struct parse_opt_ctx_t
*p
, const struct option
*options
)
210 for (; options
->type
!= OPTION_END
; options
++) {
211 if (options
->short_name
== *p
->opt
) {
212 p
->opt
= p
->opt
[1] ? p
->opt
+ 1 : NULL
;
213 return get_value(p
, options
, OPT_SHORT
);
219 static int parse_long_opt(struct parse_opt_ctx_t
*p
, const char *arg
,
220 const struct option
*options
)
222 const char *arg_end
= strchr(arg
, '=');
223 const struct option
*abbrev_option
= NULL
, *ambiguous_option
= NULL
;
224 int abbrev_flags
= 0, ambiguous_flags
= 0;
227 arg_end
= arg
+ strlen(arg
);
229 for (; options
->type
!= OPTION_END
; options
++) {
233 if (!options
->long_name
)
236 rest
= skip_prefix(arg
, options
->long_name
);
237 if (options
->type
== OPTION_ARGUMENT
) {
241 return opterror(options
, "takes no value", flags
);
244 p
->out
[p
->cpidx
++] = arg
- 2;
248 if (!prefixcmp(options
->long_name
, "no-")) {
250 * The long name itself starts with "no-", so
251 * accept the option without "no-" so that users
252 * do not have to enter "no-no-" to get the
255 rest
= skip_prefix(arg
, options
->long_name
+ 3);
260 /* Abbreviated case */
261 if (!prefixcmp(options
->long_name
+ 3, arg
)) {
267 if (!strncmp(options
->long_name
, arg
, arg_end
- arg
)) {
271 * If this is abbreviated, it is
272 * ambiguous. So when there is no
273 * exact match later, we need to
276 ambiguous_option
= abbrev_option
;
277 ambiguous_flags
= abbrev_flags
;
279 if (!(flags
& OPT_UNSET
) && *arg_end
)
280 p
->opt
= arg_end
+ 1;
281 abbrev_option
= options
;
282 abbrev_flags
= flags
;
285 /* negated and abbreviated very much? */
286 if (!prefixcmp("no-", arg
)) {
291 if (strncmp(arg
, "no-", 3))
294 rest
= skip_prefix(arg
+ 3, options
->long_name
);
295 /* abbreviated and negated? */
296 if (!rest
&& !prefixcmp(options
->long_name
, arg
+ 3))
307 return get_value(p
, options
, flags
);
310 if (ambiguous_option
)
311 return error("Ambiguous option: %s "
312 "(could be --%s%s or --%s%s)",
314 (ambiguous_flags
& OPT_UNSET
) ? "no-" : "",
315 ambiguous_option
->long_name
,
316 (abbrev_flags
& OPT_UNSET
) ? "no-" : "",
317 abbrev_option
->long_name
);
319 return get_value(p
, abbrev_option
, abbrev_flags
);
323 static void check_typos(const char *arg
, const struct option
*options
)
328 if (!prefixcmp(arg
, "no-")) {
329 error ("did you mean `--%s` (with two dashes ?)", arg
);
333 for (; options
->type
!= OPTION_END
; options
++) {
334 if (!options
->long_name
)
336 if (!prefixcmp(options
->long_name
, arg
)) {
337 error ("did you mean `--%s` (with two dashes ?)", arg
);
343 void parse_options_start(struct parse_opt_ctx_t
*ctx
,
344 int argc
, const char **argv
, int flags
)
346 memset(ctx
, 0, sizeof(*ctx
));
347 ctx
->argc
= argc
- 1;
348 ctx
->argv
= argv
+ 1;
350 ctx
->cpidx
= ((flags
& PARSE_OPT_KEEP_ARGV0
) != 0);
352 if ((flags
& PARSE_OPT_KEEP_UNKNOWN
) &&
353 (flags
& PARSE_OPT_STOP_AT_NON_OPTION
))
354 die("STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together");
357 static int usage_with_options_internal(const char * const *,
358 const struct option
*, int);
360 int parse_options_step(struct parse_opt_ctx_t
*ctx
,
361 const struct option
*options
,
362 const char * const usagestr
[])
364 int internal_help
= !(ctx
->flags
& PARSE_OPT_NO_INTERNAL_HELP
);
365 int excl_short_opt
= 1;
368 /* we must reset ->opt, unknown short option leave it dangling */
371 for (; ctx
->argc
; ctx
->argc
--, ctx
->argv
++) {
373 if (*arg
!= '-' || !arg
[1]) {
374 if (ctx
->flags
& PARSE_OPT_STOP_AT_NON_OPTION
)
376 ctx
->out
[ctx
->cpidx
++] = ctx
->argv
[0];
382 if (internal_help
&& *ctx
->opt
== 'h')
383 return usage_with_options_internal(usagestr
, options
, 0);
384 switch (parse_short_opt(ctx
, options
)) {
386 return parse_options_usage(usagestr
, options
, arg
, 1);
395 check_typos(arg
, options
);
397 if (internal_help
&& *ctx
->opt
== 'h')
398 return usage_with_options_internal(usagestr
, options
, 0);
400 switch (parse_short_opt(ctx
, options
)) {
402 return parse_options_usage(usagestr
, options
, arg
, 1);
404 /* fake a short option thing to hide the fact that we may have
405 * started to parse aggregated stuff
407 * This is leaky, too bad.
409 ctx
->argv
[0] = strdup(ctx
->opt
- 1);
410 *(char *)ctx
->argv
[0] = '-';
421 if (!arg
[2]) { /* "--" */
422 if (!(ctx
->flags
& PARSE_OPT_KEEP_DASHDASH
)) {
430 if (internal_help
&& !strcmp(arg
, "help-all"))
431 return usage_with_options_internal(usagestr
, options
, 1);
432 if (internal_help
&& !strcmp(arg
, "help"))
433 return usage_with_options_internal(usagestr
, options
, 0);
434 if (!strcmp(arg
, "list-opts"))
435 return PARSE_OPT_LIST_OPTS
;
436 if (!strcmp(arg
, "list-cmds"))
437 return PARSE_OPT_LIST_SUBCMDS
;
438 switch (parse_long_opt(ctx
, arg
, options
)) {
440 return parse_options_usage(usagestr
, options
, arg
, 0);
451 if (!(ctx
->flags
& PARSE_OPT_KEEP_UNKNOWN
))
452 return PARSE_OPT_UNKNOWN
;
453 ctx
->out
[ctx
->cpidx
++] = ctx
->argv
[0];
456 return PARSE_OPT_DONE
;
459 parse_options_usage(usagestr
, options
, arg
, excl_short_opt
);
460 if ((excl_short_opt
&& ctx
->excl_opt
->short_name
) ||
461 ctx
->excl_opt
->long_name
== NULL
) {
462 char opt
= ctx
->excl_opt
->short_name
;
463 parse_options_usage(NULL
, options
, &opt
, 1);
465 parse_options_usage(NULL
, options
, ctx
->excl_opt
->long_name
, 0);
467 return PARSE_OPT_HELP
;
470 int parse_options_end(struct parse_opt_ctx_t
*ctx
)
472 memmove(ctx
->out
+ ctx
->cpidx
, ctx
->argv
, ctx
->argc
* sizeof(*ctx
->out
));
473 ctx
->out
[ctx
->cpidx
+ ctx
->argc
] = NULL
;
474 return ctx
->cpidx
+ ctx
->argc
;
477 int parse_options_subcommand(int argc
, const char **argv
, const struct option
*options
,
478 const char *const subcommands
[], const char *usagestr
[], int flags
)
480 struct parse_opt_ctx_t ctx
;
482 perf_header__set_cmdline(argc
, argv
);
484 /* build usage string if it's not provided */
485 if (subcommands
&& !usagestr
[0]) {
486 struct strbuf buf
= STRBUF_INIT
;
488 strbuf_addf(&buf
, "perf %s [<options>] {", argv
[0]);
489 for (int i
= 0; subcommands
[i
]; i
++) {
491 strbuf_addstr(&buf
, "|");
492 strbuf_addstr(&buf
, subcommands
[i
]);
494 strbuf_addstr(&buf
, "}");
496 usagestr
[0] = strdup(buf
.buf
);
497 strbuf_release(&buf
);
500 parse_options_start(&ctx
, argc
, argv
, flags
);
501 switch (parse_options_step(&ctx
, options
, usagestr
)) {
506 case PARSE_OPT_LIST_OPTS
:
507 while (options
->type
!= OPTION_END
) {
508 printf("--%s ", options
->long_name
);
512 case PARSE_OPT_LIST_SUBCMDS
:
513 for (int i
= 0; subcommands
[i
]; i
++)
514 printf("%s ", subcommands
[i
]);
516 default: /* PARSE_OPT_UNKNOWN */
517 if (ctx
.argv
[0][1] == '-') {
518 error("unknown option `%s'", ctx
.argv
[0] + 2);
520 error("unknown switch `%c'", *ctx
.opt
);
522 usage_with_options(usagestr
, options
);
525 return parse_options_end(&ctx
);
528 int parse_options(int argc
, const char **argv
, const struct option
*options
,
529 const char * const usagestr
[], int flags
)
531 return parse_options_subcommand(argc
, argv
, options
, NULL
,
532 (const char **) usagestr
, flags
);
535 #define USAGE_OPTS_WIDTH 24
538 static void print_option_help(const struct option
*opts
, int full
)
543 if (opts
->type
== OPTION_GROUP
) {
546 fprintf(stderr
, "%s\n", opts
->help
);
549 if (!full
&& (opts
->flags
& PARSE_OPT_HIDDEN
))
551 if (opts
->flags
& PARSE_OPT_DISABLED
)
554 pos
= fprintf(stderr
, " ");
555 if (opts
->short_name
)
556 pos
+= fprintf(stderr
, "-%c", opts
->short_name
);
558 pos
+= fprintf(stderr
, " ");
560 if (opts
->long_name
&& opts
->short_name
)
561 pos
+= fprintf(stderr
, ", ");
563 pos
+= fprintf(stderr
, "--%s", opts
->long_name
);
565 switch (opts
->type
) {
566 case OPTION_ARGUMENT
:
571 case OPTION_UINTEGER
:
572 if (opts
->flags
& PARSE_OPT_OPTARG
)
574 pos
+= fprintf(stderr
, "[=<n>]");
576 pos
+= fprintf(stderr
, "[<n>]");
578 pos
+= fprintf(stderr
, " <n>");
580 case OPTION_CALLBACK
:
581 if (opts
->flags
& PARSE_OPT_NOARG
)
586 if (opts
->flags
& PARSE_OPT_OPTARG
)
588 pos
+= fprintf(stderr
, "[=<%s>]", opts
->argh
);
590 pos
+= fprintf(stderr
, "[<%s>]", opts
->argh
);
592 pos
+= fprintf(stderr
, " <%s>", opts
->argh
);
594 if (opts
->flags
& PARSE_OPT_OPTARG
)
596 pos
+= fprintf(stderr
, "[=...]");
598 pos
+= fprintf(stderr
, "[...]");
600 pos
+= fprintf(stderr
, " ...");
603 default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */
609 case OPTION_SET_UINT
:
614 if (pos
<= USAGE_OPTS_WIDTH
)
615 pad
= USAGE_OPTS_WIDTH
- pos
;
618 pad
= USAGE_OPTS_WIDTH
;
620 fprintf(stderr
, "%*s%s\n", pad
+ USAGE_GAP
, "", opts
->help
);
623 int usage_with_options_internal(const char * const *usagestr
,
624 const struct option
*opts
, int full
)
627 return PARSE_OPT_HELP
;
629 fprintf(stderr
, "\n usage: %s\n", *usagestr
++);
630 while (*usagestr
&& **usagestr
)
631 fprintf(stderr
, " or: %s\n", *usagestr
++);
633 fprintf(stderr
, "%s%s\n",
634 **usagestr
? " " : "",
639 if (opts
->type
!= OPTION_GROUP
)
642 for ( ; opts
->type
!= OPTION_END
; opts
++)
643 print_option_help(opts
, full
);
647 return PARSE_OPT_HELP
;
650 void usage_with_options(const char * const *usagestr
,
651 const struct option
*opts
)
654 usage_with_options_internal(usagestr
, opts
, 0);
658 int parse_options_usage(const char * const *usagestr
,
659 const struct option
*opts
,
660 const char *optstr
, bool short_opt
)
665 fprintf(stderr
, "\n usage: %s\n", *usagestr
++);
666 while (*usagestr
&& **usagestr
)
667 fprintf(stderr
, " or: %s\n", *usagestr
++);
669 fprintf(stderr
, "%s%s\n",
670 **usagestr
? " " : "",
677 for ( ; opts
->type
!= OPTION_END
; opts
++) {
679 if (opts
->short_name
== *optstr
)
684 if (opts
->long_name
== NULL
)
687 if (!prefixcmp(optstr
, opts
->long_name
))
689 if (!prefixcmp(optstr
, "no-") &&
690 !prefixcmp(optstr
+ 3, opts
->long_name
))
694 if (opts
->type
!= OPTION_END
)
695 print_option_help(opts
, 0);
697 return PARSE_OPT_HELP
;
701 int parse_opt_verbosity_cb(const struct option
*opt
,
702 const char *arg __maybe_unused
,
705 int *target
= opt
->value
;
708 /* --no-quiet, --no-verbose */
710 else if (opt
->short_name
== 'v') {
724 void set_option_flag(struct option
*opts
, int shortopt
, const char *longopt
,
727 for (; opts
->type
!= OPTION_END
; opts
++) {
728 if ((shortopt
&& opts
->short_name
== shortopt
) ||
729 (opts
->long_name
&& longopt
&&
730 !strcmp(opts
->long_name
, longopt
))) {