perf tools: Remove 'perf' from subcmd function and variable names
[linux-2.6-block.git] / tools / perf / util / parse-options.c
CommitLineData
07800601 1#include "util.h"
901421a5 2#include "subcmd-util.h"
07800601
IM
3#include "parse-options.h"
4#include "cache.h"
56e6f602 5#include "header.h"
096d3558 6#include "subcmd-config.h"
869c55b0 7#include <linux/string.h>
07800601
IM
8
9#define OPT_SHORT 1
10#define OPT_UNSET 2
11
901421a5 12char *error_buf;
01b19455 13
07800601
IM
14static int opterror(const struct option *opt, const char *reason, int flags)
15{
16 if (flags & OPT_SHORT)
17 return error("switch `%c' %s", opt->short_name, reason);
18 if (flags & OPT_UNSET)
19 return error("option `no-%s' %s", opt->long_name, reason);
20 return error("option `%s' %s", opt->long_name, reason);
21}
22
48e1cab1
WN
23static void optwarning(const struct option *opt, const char *reason, int flags)
24{
25 if (flags & OPT_SHORT)
26 warning("switch `%c' %s", opt->short_name, reason);
27 else if (flags & OPT_UNSET)
28 warning("option `no-%s' %s", opt->long_name, reason);
29 else
30 warning("option `%s' %s", opt->long_name, reason);
31}
32
07800601
IM
33static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
34 int flags, const char **arg)
35{
48e1cab1
WN
36 const char *res;
37
07800601 38 if (p->opt) {
48e1cab1 39 res = p->opt;
07800601 40 p->opt = NULL;
5a4b1817
FW
41 } else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 ||
42 **(p->argv + 1) == '-')) {
48e1cab1 43 res = (const char *)opt->defval;
07800601
IM
44 } else if (p->argc > 1) {
45 p->argc--;
48e1cab1 46 res = *++p->argv;
07800601
IM
47 } else
48 return opterror(opt, "requires a value", flags);
48e1cab1
WN
49 if (arg)
50 *arg = res;
07800601
IM
51 return 0;
52}
53
54static int get_value(struct parse_opt_ctx_t *p,
55 const struct option *opt, int flags)
56{
233f0b95 57 const char *s, *arg = NULL;
07800601 58 const int unset = flags & OPT_UNSET;
0c8c2077 59 int err;
07800601
IM
60
61 if (unset && p->opt)
62 return opterror(opt, "takes no value", flags);
63 if (unset && (opt->flags & PARSE_OPT_NONEG))
64 return opterror(opt, "isn't available", flags);
d152d1be
NK
65 if (opt->flags & PARSE_OPT_DISABLED)
66 return opterror(opt, "is not usable", flags);
07800601 67
42bd71d0 68 if (opt->flags & PARSE_OPT_EXCLUSIVE) {
5594b557 69 if (p->excl_opt && p->excl_opt != opt) {
42bd71d0
NK
70 char msg[128];
71
72 if (((flags & OPT_SHORT) && p->excl_opt->short_name) ||
73 p->excl_opt->long_name == NULL) {
74 scnprintf(msg, sizeof(msg), "cannot be used with switch `%c'",
75 p->excl_opt->short_name);
76 } else {
77 scnprintf(msg, sizeof(msg), "cannot be used with %s",
78 p->excl_opt->long_name);
79 }
80 opterror(opt, msg, flags);
81 return -3;
82 }
83 p->excl_opt = opt;
84 }
07800601
IM
85 if (!(flags & OPT_SHORT) && p->opt) {
86 switch (opt->type) {
87 case OPTION_CALLBACK:
88 if (!(opt->flags & PARSE_OPT_NOARG))
89 break;
90 /* FALLTHROUGH */
91 case OPTION_BOOLEAN:
c0555642 92 case OPTION_INCR:
07800601 93 case OPTION_BIT:
edb7c60e 94 case OPTION_SET_UINT:
07800601
IM
95 case OPTION_SET_PTR:
96 return opterror(opt, "takes no value", flags);
83a0944f
IM
97 case OPTION_END:
98 case OPTION_ARGUMENT:
99 case OPTION_GROUP:
100 case OPTION_STRING:
101 case OPTION_INTEGER:
c100edbe 102 case OPTION_UINTEGER:
83a0944f 103 case OPTION_LONG:
6ba85cea 104 case OPTION_U64:
07800601
IM
105 default:
106 break;
107 }
108 }
109
48e1cab1
WN
110 if (opt->flags & PARSE_OPT_NOBUILD) {
111 char reason[128];
112 bool noarg = false;
113
114 err = snprintf(reason, sizeof(reason),
115 opt->flags & PARSE_OPT_CANSKIP ?
116 "is being ignored because %s " :
117 "is not available because %s",
118 opt->build_opt);
119 reason[sizeof(reason) - 1] = '\0';
120
121 if (err < 0)
122 strncpy(reason, opt->flags & PARSE_OPT_CANSKIP ?
123 "is being ignored" :
124 "is not available",
125 sizeof(reason));
126
127 if (!(opt->flags & PARSE_OPT_CANSKIP))
128 return opterror(opt, reason, flags);
129
130 err = 0;
131 if (unset)
132 noarg = true;
133 if (opt->flags & PARSE_OPT_NOARG)
134 noarg = true;
135 if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
136 noarg = true;
137
138 switch (opt->type) {
139 case OPTION_BOOLEAN:
140 case OPTION_INCR:
141 case OPTION_BIT:
142 case OPTION_SET_UINT:
143 case OPTION_SET_PTR:
144 case OPTION_END:
145 case OPTION_ARGUMENT:
146 case OPTION_GROUP:
147 noarg = true;
148 break;
149 case OPTION_CALLBACK:
150 case OPTION_STRING:
151 case OPTION_INTEGER:
152 case OPTION_UINTEGER:
153 case OPTION_LONG:
154 case OPTION_U64:
155 default:
156 break;
157 }
158
159 if (!noarg)
160 err = get_arg(p, opt, flags, NULL);
161 if (err)
162 return err;
163
164 optwarning(opt, reason, flags);
165 return 0;
166 }
167
07800601
IM
168 switch (opt->type) {
169 case OPTION_BIT:
170 if (unset)
171 *(int *)opt->value &= ~opt->defval;
172 else
173 *(int *)opt->value |= opt->defval;
174 return 0;
175
176 case OPTION_BOOLEAN:
c0555642 177 *(bool *)opt->value = unset ? false : true;
167faf32
AH
178 if (opt->set)
179 *(bool *)opt->set = true;
c0555642
IM
180 return 0;
181
182 case OPTION_INCR:
07800601
IM
183 *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1;
184 return 0;
185
edb7c60e
ACM
186 case OPTION_SET_UINT:
187 *(unsigned int *)opt->value = unset ? 0 : opt->defval;
07800601
IM
188 return 0;
189
190 case OPTION_SET_PTR:
191 *(void **)opt->value = unset ? NULL : (void *)opt->defval;
192 return 0;
193
194 case OPTION_STRING:
0c8c2077 195 err = 0;
07800601
IM
196 if (unset)
197 *(const char **)opt->value = NULL;
198 else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
199 *(const char **)opt->value = (const char *)opt->defval;
200 else
0c8c2077
WN
201 err = get_arg(p, opt, flags, (const char **)opt->value);
202
203 /* PARSE_OPT_NOEMPTY: Allow NULL but disallow empty string. */
204 if (opt->flags & PARSE_OPT_NOEMPTY) {
205 const char *val = *(const char **)opt->value;
206
207 if (!val)
208 return err;
209
210 /* Similar to unset if we are given an empty string. */
211 if (val[0] == '\0') {
212 *(const char **)opt->value = NULL;
213 return 0;
214 }
215 }
216
217 return err;
07800601
IM
218
219 case OPTION_CALLBACK:
220 if (unset)
221 return (*opt->callback)(opt, NULL, 1) ? (-1) : 0;
222 if (opt->flags & PARSE_OPT_NOARG)
223 return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
224 if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
225 return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
226 if (get_arg(p, opt, flags, &arg))
227 return -1;
228 return (*opt->callback)(opt, arg, 0) ? (-1) : 0;
229
230 case OPTION_INTEGER:
231 if (unset) {
232 *(int *)opt->value = 0;
233 return 0;
234 }
235 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
236 *(int *)opt->value = opt->defval;
237 return 0;
238 }
239 if (get_arg(p, opt, flags, &arg))
240 return -1;
241 *(int *)opt->value = strtol(arg, (char **)&s, 10);
242 if (*s)
243 return opterror(opt, "expects a numerical value", flags);
e61078a0
PZ
244 return 0;
245
c100edbe
ACM
246 case OPTION_UINTEGER:
247 if (unset) {
248 *(unsigned int *)opt->value = 0;
249 return 0;
250 }
251 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
252 *(unsigned int *)opt->value = opt->defval;
253 return 0;
254 }
255 if (get_arg(p, opt, flags, &arg))
256 return -1;
257 *(unsigned int *)opt->value = strtol(arg, (char **)&s, 10);
258 if (*s)
259 return opterror(opt, "expects a numerical value", flags);
260 return 0;
261
e61078a0
PZ
262 case OPTION_LONG:
263 if (unset) {
264 *(long *)opt->value = 0;
265 return 0;
266 }
267 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
268 *(long *)opt->value = opt->defval;
269 return 0;
270 }
271 if (get_arg(p, opt, flags, &arg))
272 return -1;
273 *(long *)opt->value = strtol(arg, (char **)&s, 10);
274 if (*s)
275 return opterror(opt, "expects a numerical value", flags);
07800601
IM
276 return 0;
277
6ba85cea
ACM
278 case OPTION_U64:
279 if (unset) {
280 *(u64 *)opt->value = 0;
281 return 0;
282 }
283 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
284 *(u64 *)opt->value = opt->defval;
285 return 0;
286 }
287 if (get_arg(p, opt, flags, &arg))
288 return -1;
289 *(u64 *)opt->value = strtoull(arg, (char **)&s, 10);
290 if (*s)
291 return opterror(opt, "expects a numerical value", flags);
292 return 0;
293
83a0944f
IM
294 case OPTION_END:
295 case OPTION_ARGUMENT:
296 case OPTION_GROUP:
07800601
IM
297 default:
298 die("should not happen, someone must be hit on the forehead");
299 }
300}
301
302static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options)
303{
304 for (; options->type != OPTION_END; options++) {
305 if (options->short_name == *p->opt) {
306 p->opt = p->opt[1] ? p->opt + 1 : NULL;
307 return get_value(p, options, OPT_SHORT);
308 }
309 }
310 return -2;
311}
312
313static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
314 const struct option *options)
315{
316 const char *arg_end = strchr(arg, '=');
317 const struct option *abbrev_option = NULL, *ambiguous_option = NULL;
318 int abbrev_flags = 0, ambiguous_flags = 0;
319
320 if (!arg_end)
321 arg_end = arg + strlen(arg);
322
323 for (; options->type != OPTION_END; options++) {
324 const char *rest;
325 int flags = 0;
326
327 if (!options->long_name)
328 continue;
329
330 rest = skip_prefix(arg, options->long_name);
331 if (options->type == OPTION_ARGUMENT) {
332 if (!rest)
333 continue;
334 if (*rest == '=')
335 return opterror(options, "takes no value", flags);
336 if (*rest)
337 continue;
338 p->out[p->cpidx++] = arg - 2;
339 return 0;
340 }
341 if (!rest) {
4bc43796
AH
342 if (!prefixcmp(options->long_name, "no-")) {
343 /*
344 * The long name itself starts with "no-", so
345 * accept the option without "no-" so that users
346 * do not have to enter "no-no-" to get the
347 * negation.
348 */
349 rest = skip_prefix(arg, options->long_name + 3);
350 if (rest) {
351 flags |= OPT_UNSET;
352 goto match;
353 }
354 /* Abbreviated case */
355 if (!prefixcmp(options->long_name + 3, arg)) {
356 flags |= OPT_UNSET;
357 goto is_abbreviated;
358 }
359 }
07800601
IM
360 /* abbreviated? */
361 if (!strncmp(options->long_name, arg, arg_end - arg)) {
362is_abbreviated:
363 if (abbrev_option) {
364 /*
365 * If this is abbreviated, it is
366 * ambiguous. So when there is no
367 * exact match later, we need to
368 * error out.
369 */
370 ambiguous_option = abbrev_option;
371 ambiguous_flags = abbrev_flags;
372 }
373 if (!(flags & OPT_UNSET) && *arg_end)
374 p->opt = arg_end + 1;
375 abbrev_option = options;
376 abbrev_flags = flags;
377 continue;
378 }
379 /* negated and abbreviated very much? */
380 if (!prefixcmp("no-", arg)) {
381 flags |= OPT_UNSET;
382 goto is_abbreviated;
383 }
384 /* negated? */
385 if (strncmp(arg, "no-", 3))
386 continue;
387 flags |= OPT_UNSET;
388 rest = skip_prefix(arg + 3, options->long_name);
389 /* abbreviated and negated? */
390 if (!rest && !prefixcmp(options->long_name, arg + 3))
391 goto is_abbreviated;
392 if (!rest)
393 continue;
394 }
4bc43796 395match:
07800601
IM
396 if (*rest) {
397 if (*rest != '=')
398 continue;
399 p->opt = rest + 1;
400 }
401 return get_value(p, options, flags);
402 }
403
404 if (ambiguous_option)
405 return error("Ambiguous option: %s "
406 "(could be --%s%s or --%s%s)",
407 arg,
408 (ambiguous_flags & OPT_UNSET) ? "no-" : "",
409 ambiguous_option->long_name,
410 (abbrev_flags & OPT_UNSET) ? "no-" : "",
411 abbrev_option->long_name);
412 if (abbrev_option)
413 return get_value(p, abbrev_option, abbrev_flags);
414 return -2;
415}
416
417static void check_typos(const char *arg, const struct option *options)
418{
419 if (strlen(arg) < 3)
420 return;
421
422 if (!prefixcmp(arg, "no-")) {
423 error ("did you mean `--%s` (with two dashes ?)", arg);
424 exit(129);
425 }
426
427 for (; options->type != OPTION_END; options++) {
428 if (!options->long_name)
429 continue;
430 if (!prefixcmp(options->long_name, arg)) {
431 error ("did you mean `--%s` (with two dashes ?)", arg);
432 exit(129);
433 }
434 }
435}
436
408cf34c
JP
437static void parse_options_start(struct parse_opt_ctx_t *ctx,
438 int argc, const char **argv, int flags)
07800601
IM
439{
440 memset(ctx, 0, sizeof(*ctx));
441 ctx->argc = argc - 1;
442 ctx->argv = argv + 1;
443 ctx->out = argv;
444 ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);
445 ctx->flags = flags;
446 if ((flags & PARSE_OPT_KEEP_UNKNOWN) &&
447 (flags & PARSE_OPT_STOP_AT_NON_OPTION))
448 die("STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together");
449}
450
451static int usage_with_options_internal(const char * const *,
161d9041
ACM
452 const struct option *, int,
453 struct parse_opt_ctx_t *);
07800601 454
408cf34c
JP
455static int parse_options_step(struct parse_opt_ctx_t *ctx,
456 const struct option *options,
457 const char * const usagestr[])
07800601
IM
458{
459 int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
42bd71d0
NK
460 int excl_short_opt = 1;
461 const char *arg;
07800601
IM
462
463 /* we must reset ->opt, unknown short option leave it dangling */
464 ctx->opt = NULL;
465
466 for (; ctx->argc; ctx->argc--, ctx->argv++) {
42bd71d0 467 arg = ctx->argv[0];
07800601
IM
468 if (*arg != '-' || !arg[1]) {
469 if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
470 break;
471 ctx->out[ctx->cpidx++] = ctx->argv[0];
472 continue;
473 }
474
475 if (arg[1] != '-') {
42bd71d0 476 ctx->opt = ++arg;
161d9041
ACM
477 if (internal_help && *ctx->opt == 'h') {
478 return usage_with_options_internal(usagestr, options, 0, ctx);
479 }
07800601
IM
480 switch (parse_short_opt(ctx, options)) {
481 case -1:
42bd71d0 482 return parse_options_usage(usagestr, options, arg, 1);
07800601
IM
483 case -2:
484 goto unknown;
42bd71d0
NK
485 case -3:
486 goto exclusive;
83a0944f
IM
487 default:
488 break;
07800601
IM
489 }
490 if (ctx->opt)
42bd71d0 491 check_typos(arg, options);
07800601
IM
492 while (ctx->opt) {
493 if (internal_help && *ctx->opt == 'h')
161d9041 494 return usage_with_options_internal(usagestr, options, 0, ctx);
ac697625 495 arg = ctx->opt;
07800601
IM
496 switch (parse_short_opt(ctx, options)) {
497 case -1:
ac697625 498 return parse_options_usage(usagestr, options, arg, 1);
07800601
IM
499 case -2:
500 /* fake a short option thing to hide the fact that we may have
501 * started to parse aggregated stuff
502 *
503 * This is leaky, too bad.
504 */
505 ctx->argv[0] = strdup(ctx->opt - 1);
506 *(char *)ctx->argv[0] = '-';
507 goto unknown;
42bd71d0
NK
508 case -3:
509 goto exclusive;
83a0944f
IM
510 default:
511 break;
07800601
IM
512 }
513 }
514 continue;
515 }
516
517 if (!arg[2]) { /* "--" */
518 if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) {
519 ctx->argc--;
520 ctx->argv++;
521 }
522 break;
523 }
524
42bd71d0
NK
525 arg += 2;
526 if (internal_help && !strcmp(arg, "help-all"))
161d9041 527 return usage_with_options_internal(usagestr, options, 1, ctx);
42bd71d0 528 if (internal_help && !strcmp(arg, "help"))
161d9041 529 return usage_with_options_internal(usagestr, options, 0, ctx);
42bd71d0 530 if (!strcmp(arg, "list-opts"))
09a71b97 531 return PARSE_OPT_LIST_OPTS;
42bd71d0 532 if (!strcmp(arg, "list-cmds"))
09a71b97 533 return PARSE_OPT_LIST_SUBCMDS;
42bd71d0 534 switch (parse_long_opt(ctx, arg, options)) {
07800601 535 case -1:
42bd71d0 536 return parse_options_usage(usagestr, options, arg, 0);
07800601
IM
537 case -2:
538 goto unknown;
42bd71d0
NK
539 case -3:
540 excl_short_opt = 0;
541 goto exclusive;
83a0944f
IM
542 default:
543 break;
07800601
IM
544 }
545 continue;
546unknown:
547 if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN))
548 return PARSE_OPT_UNKNOWN;
549 ctx->out[ctx->cpidx++] = ctx->argv[0];
550 ctx->opt = NULL;
551 }
552 return PARSE_OPT_DONE;
42bd71d0
NK
553
554exclusive:
555 parse_options_usage(usagestr, options, arg, excl_short_opt);
556 if ((excl_short_opt && ctx->excl_opt->short_name) ||
557 ctx->excl_opt->long_name == NULL) {
558 char opt = ctx->excl_opt->short_name;
559 parse_options_usage(NULL, options, &opt, 1);
560 } else {
561 parse_options_usage(NULL, options, ctx->excl_opt->long_name, 0);
562 }
563 return PARSE_OPT_HELP;
07800601
IM
564}
565
408cf34c 566static int parse_options_end(struct parse_opt_ctx_t *ctx)
07800601
IM
567{
568 memmove(ctx->out + ctx->cpidx, ctx->argv, ctx->argc * sizeof(*ctx->out));
569 ctx->out[ctx->cpidx + ctx->argc] = NULL;
570 return ctx->cpidx + ctx->argc;
571}
572
09a71b97
RR
573int parse_options_subcommand(int argc, const char **argv, const struct option *options,
574 const char *const subcommands[], const char *usagestr[], int flags)
07800601
IM
575{
576 struct parse_opt_ctx_t ctx;
577
09a71b97
RR
578 /* build usage string if it's not provided */
579 if (subcommands && !usagestr[0]) {
901421a5
JP
580 char *buf = NULL;
581
582 astrcatf(&buf, "%s %s [<options>] {", subcmd_config.exec_name, argv[0]);
09a71b97 583
09a71b97
RR
584 for (int i = 0; subcommands[i]; i++) {
585 if (i)
901421a5
JP
586 astrcat(&buf, "|");
587 astrcat(&buf, subcommands[i]);
09a71b97 588 }
901421a5 589 astrcat(&buf, "}");
09a71b97 590
901421a5 591 usagestr[0] = buf;
09a71b97
RR
592 }
593
07800601
IM
594 parse_options_start(&ctx, argc, argv, flags);
595 switch (parse_options_step(&ctx, options, usagestr)) {
596 case PARSE_OPT_HELP:
597 exit(129);
598 case PARSE_OPT_DONE:
599 break;
09a71b97 600 case PARSE_OPT_LIST_OPTS:
4d8061fa 601 while (options->type != OPTION_END) {
3ef1e65c
YS
602 if (options->long_name)
603 printf("--%s ", options->long_name);
4d8061fa
NK
604 options++;
605 }
ed457520 606 putchar('\n');
4d8061fa 607 exit(130);
09a71b97 608 case PARSE_OPT_LIST_SUBCMDS:
3a03005f
YS
609 if (subcommands) {
610 for (int i = 0; subcommands[i]; i++)
611 printf("%s ", subcommands[i]);
612 }
ed457520 613 putchar('\n');
09a71b97 614 exit(130);
07800601 615 default: /* PARSE_OPT_UNKNOWN */
901421a5
JP
616 if (ctx.argv[0][1] == '-')
617 astrcatf(&error_buf, "unknown option `%s'",
618 ctx.argv[0] + 2);
619 else
620 astrcatf(&error_buf, "unknown switch `%c'", *ctx.opt);
07800601
IM
621 usage_with_options(usagestr, options);
622 }
623
624 return parse_options_end(&ctx);
625}
626
09a71b97
RR
627int parse_options(int argc, const char **argv, const struct option *options,
628 const char * const usagestr[], int flags)
629{
630 return parse_options_subcommand(argc, argv, options, NULL,
631 (const char **) usagestr, flags);
632}
633
07800601
IM
634#define USAGE_OPTS_WIDTH 24
635#define USAGE_GAP 2
636
ac697625
NK
637static void print_option_help(const struct option *opts, int full)
638{
639 size_t pos;
640 int pad;
641
642 if (opts->type == OPTION_GROUP) {
643 fputc('\n', stderr);
644 if (*opts->help)
645 fprintf(stderr, "%s\n", opts->help);
646 return;
647 }
648 if (!full && (opts->flags & PARSE_OPT_HIDDEN))
649 return;
d152d1be
NK
650 if (opts->flags & PARSE_OPT_DISABLED)
651 return;
ac697625
NK
652
653 pos = fprintf(stderr, " ");
654 if (opts->short_name)
655 pos += fprintf(stderr, "-%c", opts->short_name);
656 else
657 pos += fprintf(stderr, " ");
658
659 if (opts->long_name && opts->short_name)
660 pos += fprintf(stderr, ", ");
661 if (opts->long_name)
662 pos += fprintf(stderr, "--%s", opts->long_name);
663
664 switch (opts->type) {
665 case OPTION_ARGUMENT:
666 break;
667 case OPTION_LONG:
668 case OPTION_U64:
669 case OPTION_INTEGER:
670 case OPTION_UINTEGER:
671 if (opts->flags & PARSE_OPT_OPTARG)
672 if (opts->long_name)
673 pos += fprintf(stderr, "[=<n>]");
674 else
675 pos += fprintf(stderr, "[<n>]");
676 else
677 pos += fprintf(stderr, " <n>");
678 break;
679 case OPTION_CALLBACK:
680 if (opts->flags & PARSE_OPT_NOARG)
681 break;
682 /* FALLTHROUGH */
683 case OPTION_STRING:
684 if (opts->argh) {
685 if (opts->flags & PARSE_OPT_OPTARG)
686 if (opts->long_name)
687 pos += fprintf(stderr, "[=<%s>]", opts->argh);
688 else
689 pos += fprintf(stderr, "[<%s>]", opts->argh);
690 else
691 pos += fprintf(stderr, " <%s>", opts->argh);
692 } else {
693 if (opts->flags & PARSE_OPT_OPTARG)
694 if (opts->long_name)
695 pos += fprintf(stderr, "[=...]");
696 else
697 pos += fprintf(stderr, "[...]");
698 else
699 pos += fprintf(stderr, " ...");
700 }
701 break;
702 default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */
703 case OPTION_END:
704 case OPTION_GROUP:
705 case OPTION_BIT:
706 case OPTION_BOOLEAN:
707 case OPTION_INCR:
708 case OPTION_SET_UINT:
709 case OPTION_SET_PTR:
710 break;
711 }
712
713 if (pos <= USAGE_OPTS_WIDTH)
714 pad = USAGE_OPTS_WIDTH - pos;
715 else {
716 fputc('\n', stderr);
717 pad = USAGE_OPTS_WIDTH;
718 }
719 fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
48e1cab1
WN
720 if (opts->flags & PARSE_OPT_NOBUILD)
721 fprintf(stderr, "%*s(not built-in because %s)\n",
722 USAGE_OPTS_WIDTH + USAGE_GAP, "",
723 opts->build_opt);
ac697625
NK
724}
725
869c55b0
ACM
726static int option__cmp(const void *va, const void *vb)
727{
728 const struct option *a = va, *b = vb;
729 int sa = tolower(a->short_name), sb = tolower(b->short_name), ret;
730
731 if (sa == 0)
732 sa = 'z' + 1;
733 if (sb == 0)
734 sb = 'z' + 1;
735
736 ret = sa - sb;
737
738 if (ret == 0) {
739 const char *la = a->long_name ?: "",
740 *lb = b->long_name ?: "";
741 ret = strcmp(la, lb);
742 }
743
744 return ret;
745}
746
747static struct option *options__order(const struct option *opts)
748{
749 int nr_opts = 0;
750 const struct option *o = opts;
751 struct option *ordered;
752
753 for (o = opts; o->type != OPTION_END; o++)
754 ++nr_opts;
755
756 ordered = memdup(opts, sizeof(*o) * (nr_opts + 1));
757 if (ordered == NULL)
758 goto out;
759
760 qsort(ordered, nr_opts, sizeof(*o), option__cmp);
761out:
762 return ordered;
763}
764
161d9041
ACM
765static bool option__in_argv(const struct option *opt, const struct parse_opt_ctx_t *ctx)
766{
767 int i;
768
769 for (i = 1; i < ctx->argc; ++i) {
770 const char *arg = ctx->argv[i];
771
f4efcce3
ACM
772 if (arg[0] != '-') {
773 if (arg[1] == '\0') {
774 if (arg[0] == opt->short_name)
775 return true;
776 continue;
777 }
778
779 if (opt->long_name && strcmp(opt->long_name, arg) == 0)
780 return true;
781
782 if (opt->help && strcasestr(opt->help, arg) != NULL)
783 return true;
784
161d9041 785 continue;
f4efcce3 786 }
161d9041
ACM
787
788 if (arg[1] == opt->short_name ||
789 (arg[1] == '-' && opt->long_name && strcmp(opt->long_name, arg + 2) == 0))
790 return true;
791 }
792
793 return false;
794}
795
408cf34c
JP
796static int usage_with_options_internal(const char * const *usagestr,
797 const struct option *opts, int full,
798 struct parse_opt_ctx_t *ctx)
07800601 799{
869c55b0
ACM
800 struct option *ordered;
801
07800601
IM
802 if (!usagestr)
803 return PARSE_OPT_HELP;
804
01b19455
NK
805 setup_pager();
806
901421a5
JP
807 if (error_buf) {
808 fprintf(stderr, " Error: %s\n", error_buf);
809 zfree(&error_buf);
01b19455
NK
810 }
811
3a134ae9 812 fprintf(stderr, "\n Usage: %s\n", *usagestr++);
07800601 813 while (*usagestr && **usagestr)
6e6b754f 814 fprintf(stderr, " or: %s\n", *usagestr++);
07800601
IM
815 while (*usagestr) {
816 fprintf(stderr, "%s%s\n",
817 **usagestr ? " " : "",
818 *usagestr);
819 usagestr++;
820 }
821
822 if (opts->type != OPTION_GROUP)
823 fputc('\n', stderr);
824
869c55b0
ACM
825 ordered = options__order(opts);
826 if (ordered)
827 opts = ordered;
828
161d9041
ACM
829 for ( ; opts->type != OPTION_END; opts++) {
830 if (ctx && ctx->argc > 1 && !option__in_argv(opts, ctx))
831 continue;
ac697625 832 print_option_help(opts, full);
161d9041 833 }
07800601 834
07800601
IM
835 fputc('\n', stderr);
836
869c55b0
ACM
837 free(ordered);
838
07800601
IM
839 return PARSE_OPT_HELP;
840}
841
842void usage_with_options(const char * const *usagestr,
843 const struct option *opts)
844{
161d9041 845 usage_with_options_internal(usagestr, opts, 0, NULL);
07800601
IM
846 exit(129);
847}
848
c7118369
NK
849void usage_with_options_msg(const char * const *usagestr,
850 const struct option *opts, const char *fmt, ...)
851{
852 va_list ap;
901421a5 853 char *tmp = error_buf;
c7118369 854
c7118369 855 va_start(ap, fmt);
901421a5
JP
856 if (vasprintf(&error_buf, fmt, ap) == -1)
857 die("vasprintf failed");
c7118369
NK
858 va_end(ap);
859
901421a5
JP
860 free(tmp);
861
c7118369
NK
862 usage_with_options_internal(usagestr, opts, 0, NULL);
863 exit(129);
864}
865
07800601 866int parse_options_usage(const char * const *usagestr,
ac697625
NK
867 const struct option *opts,
868 const char *optstr, bool short_opt)
07800601 869{
ac697625 870 if (!usagestr)
cc03c542 871 goto opt;
ac697625 872
3a134ae9 873 fprintf(stderr, "\n Usage: %s\n", *usagestr++);
ac697625
NK
874 while (*usagestr && **usagestr)
875 fprintf(stderr, " or: %s\n", *usagestr++);
876 while (*usagestr) {
877 fprintf(stderr, "%s%s\n",
878 **usagestr ? " " : "",
879 *usagestr);
880 usagestr++;
881 }
882 fputc('\n', stderr);
883
cc03c542 884opt:
ac697625
NK
885 for ( ; opts->type != OPTION_END; opts++) {
886 if (short_opt) {
a5f4a693
NK
887 if (opts->short_name == *optstr) {
888 print_option_help(opts, 0);
ac697625 889 break;
a5f4a693 890 }
ac697625
NK
891 continue;
892 }
893
894 if (opts->long_name == NULL)
895 continue;
896
a5f4a693
NK
897 if (!prefixcmp(opts->long_name, optstr))
898 print_option_help(opts, 0);
899 if (!prefixcmp("no-", optstr) &&
900 !prefixcmp(opts->long_name, optstr + 3))
901 print_option_help(opts, 0);
ac697625
NK
902 }
903
ac697625 904 return PARSE_OPT_HELP;
07800601
IM
905}
906
907
1d037ca1
IT
908int parse_opt_verbosity_cb(const struct option *opt,
909 const char *arg __maybe_unused,
07800601
IM
910 int unset)
911{
912 int *target = opt->value;
913
914 if (unset)
915 /* --no-quiet, --no-verbose */
916 *target = 0;
917 else if (opt->short_name == 'v') {
918 if (*target >= 0)
919 (*target)++;
920 else
921 *target = 1;
922 } else {
923 if (*target <= 0)
924 (*target)--;
925 else
926 *target = -1;
927 }
928 return 0;
929}
d152d1be 930
48e1cab1
WN
931static struct option *
932find_option(struct option *opts, int shortopt, const char *longopt)
d152d1be
NK
933{
934 for (; opts->type != OPTION_END; opts++) {
935 if ((shortopt && opts->short_name == shortopt) ||
936 (opts->long_name && longopt &&
48e1cab1
WN
937 !strcmp(opts->long_name, longopt)))
938 return opts;
d152d1be 939 }
48e1cab1
WN
940 return NULL;
941}
942
943void set_option_flag(struct option *opts, int shortopt, const char *longopt,
944 int flag)
945{
946 struct option *opt = find_option(opts, shortopt, longopt);
947
948 if (opt)
949 opt->flags |= flag;
950 return;
951}
952
953void set_option_nobuild(struct option *opts, int shortopt,
954 const char *longopt,
955 const char *build_opt,
956 bool can_skip)
957{
958 struct option *opt = find_option(opts, shortopt, longopt);
959
960 if (!opt)
961 return;
962
963 opt->flags |= PARSE_OPT_NOBUILD;
964 opt->flags |= can_skip ? PARSE_OPT_CANSKIP : 0;
965 opt->build_opt = build_opt;
d152d1be 966}