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