parse-options.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. #include "util.h"
  2. #include "parse-options.h"
  3. #include "cache.h"
  4. #include "header.h"
  5. #define OPT_SHORT 1
  6. #define OPT_UNSET 2
  7. static int opterror(const struct option *opt, const char *reason, int flags)
  8. {
  9. if (flags & OPT_SHORT)
  10. return error("switch `%c' %s", opt->short_name, reason);
  11. if (flags & OPT_UNSET)
  12. return error("option `no-%s' %s", opt->long_name, reason);
  13. return error("option `%s' %s", opt->long_name, reason);
  14. }
  15. static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
  16. int flags, const char **arg)
  17. {
  18. if (p->opt) {
  19. *arg = p->opt;
  20. p->opt = NULL;
  21. } else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 ||
  22. **(p->argv + 1) == '-')) {
  23. *arg = (const char *)opt->defval;
  24. } else if (p->argc > 1) {
  25. p->argc--;
  26. *arg = *++p->argv;
  27. } else
  28. return opterror(opt, "requires a value", flags);
  29. return 0;
  30. }
  31. static int get_value(struct parse_opt_ctx_t *p,
  32. const struct option *opt, int flags)
  33. {
  34. const char *s, *arg = NULL;
  35. const int unset = flags & OPT_UNSET;
  36. if (unset && p->opt)
  37. return opterror(opt, "takes no value", flags);
  38. if (unset && (opt->flags & PARSE_OPT_NONEG))
  39. return opterror(opt, "isn't available", flags);
  40. if (opt->flags & PARSE_OPT_DISABLED)
  41. return opterror(opt, "is not usable", flags);
  42. if (opt->flags & PARSE_OPT_EXCLUSIVE) {
  43. if (p->excl_opt && p->excl_opt != opt) {
  44. char msg[128];
  45. if (((flags & OPT_SHORT) && p->excl_opt->short_name) ||
  46. p->excl_opt->long_name == NULL) {
  47. scnprintf(msg, sizeof(msg), "cannot be used with switch `%c'",
  48. p->excl_opt->short_name);
  49. } else {
  50. scnprintf(msg, sizeof(msg), "cannot be used with %s",
  51. p->excl_opt->long_name);
  52. }
  53. opterror(opt, msg, flags);
  54. return -3;
  55. }
  56. p->excl_opt = opt;
  57. }
  58. if (!(flags & OPT_SHORT) && p->opt) {
  59. switch (opt->type) {
  60. case OPTION_CALLBACK:
  61. if (!(opt->flags & PARSE_OPT_NOARG))
  62. break;
  63. /* FALLTHROUGH */
  64. case OPTION_BOOLEAN:
  65. case OPTION_INCR:
  66. case OPTION_BIT:
  67. case OPTION_SET_UINT:
  68. case OPTION_SET_PTR:
  69. return opterror(opt, "takes no value", flags);
  70. case OPTION_END:
  71. case OPTION_ARGUMENT:
  72. case OPTION_GROUP:
  73. case OPTION_STRING:
  74. case OPTION_INTEGER:
  75. case OPTION_UINTEGER:
  76. case OPTION_LONG:
  77. case OPTION_U64:
  78. default:
  79. break;
  80. }
  81. }
  82. switch (opt->type) {
  83. case OPTION_BIT:
  84. if (unset)
  85. *(int *)opt->value &= ~opt->defval;
  86. else
  87. *(int *)opt->value |= opt->defval;
  88. return 0;
  89. case OPTION_BOOLEAN:
  90. *(bool *)opt->value = unset ? false : true;
  91. if (opt->set)
  92. *(bool *)opt->set = true;
  93. return 0;
  94. case OPTION_INCR:
  95. *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1;
  96. return 0;
  97. case OPTION_SET_UINT:
  98. *(unsigned int *)opt->value = unset ? 0 : opt->defval;
  99. return 0;
  100. case OPTION_SET_PTR:
  101. *(void **)opt->value = unset ? NULL : (void *)opt->defval;
  102. return 0;
  103. case OPTION_STRING:
  104. if (unset)
  105. *(const char **)opt->value = NULL;
  106. else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
  107. *(const char **)opt->value = (const char *)opt->defval;
  108. else
  109. return get_arg(p, opt, flags, (const char **)opt->value);
  110. return 0;
  111. case OPTION_CALLBACK:
  112. if (unset)
  113. return (*opt->callback)(opt, NULL, 1) ? (-1) : 0;
  114. if (opt->flags & PARSE_OPT_NOARG)
  115. return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
  116. if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
  117. return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
  118. if (get_arg(p, opt, flags, &arg))
  119. return -1;
  120. return (*opt->callback)(opt, arg, 0) ? (-1) : 0;
  121. case OPTION_INTEGER:
  122. if (unset) {
  123. *(int *)opt->value = 0;
  124. return 0;
  125. }
  126. if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
  127. *(int *)opt->value = opt->defval;
  128. return 0;
  129. }
  130. if (get_arg(p, opt, flags, &arg))
  131. return -1;
  132. *(int *)opt->value = strtol(arg, (char **)&s, 10);
  133. if (*s)
  134. return opterror(opt, "expects a numerical value", flags);
  135. return 0;
  136. case OPTION_UINTEGER:
  137. if (unset) {
  138. *(unsigned int *)opt->value = 0;
  139. return 0;
  140. }
  141. if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
  142. *(unsigned int *)opt->value = opt->defval;
  143. return 0;
  144. }
  145. if (get_arg(p, opt, flags, &arg))
  146. return -1;
  147. *(unsigned int *)opt->value = strtol(arg, (char **)&s, 10);
  148. if (*s)
  149. return opterror(opt, "expects a numerical value", flags);
  150. return 0;
  151. case OPTION_LONG:
  152. if (unset) {
  153. *(long *)opt->value = 0;
  154. return 0;
  155. }
  156. if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
  157. *(long *)opt->value = opt->defval;
  158. return 0;
  159. }
  160. if (get_arg(p, opt, flags, &arg))
  161. return -1;
  162. *(long *)opt->value = strtol(arg, (char **)&s, 10);
  163. if (*s)
  164. return opterror(opt, "expects a numerical value", flags);
  165. return 0;
  166. case OPTION_U64:
  167. if (unset) {
  168. *(u64 *)opt->value = 0;
  169. return 0;
  170. }
  171. if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
  172. *(u64 *)opt->value = opt->defval;
  173. return 0;
  174. }
  175. if (get_arg(p, opt, flags, &arg))
  176. return -1;
  177. *(u64 *)opt->value = strtoull(arg, (char **)&s, 10);
  178. if (*s)
  179. return opterror(opt, "expects a numerical value", flags);
  180. return 0;
  181. case OPTION_END:
  182. case OPTION_ARGUMENT:
  183. case OPTION_GROUP:
  184. default:
  185. die("should not happen, someone must be hit on the forehead");
  186. }
  187. }
  188. static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options)
  189. {
  190. for (; options->type != OPTION_END; options++) {
  191. if (options->short_name == *p->opt) {
  192. p->opt = p->opt[1] ? p->opt + 1 : NULL;
  193. return get_value(p, options, OPT_SHORT);
  194. }
  195. }
  196. return -2;
  197. }
  198. static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
  199. const struct option *options)
  200. {
  201. const char *arg_end = strchr(arg, '=');
  202. const struct option *abbrev_option = NULL, *ambiguous_option = NULL;
  203. int abbrev_flags = 0, ambiguous_flags = 0;
  204. if (!arg_end)
  205. arg_end = arg + strlen(arg);
  206. for (; options->type != OPTION_END; options++) {
  207. const char *rest;
  208. int flags = 0;
  209. if (!options->long_name)
  210. continue;
  211. rest = skip_prefix(arg, options->long_name);
  212. if (options->type == OPTION_ARGUMENT) {
  213. if (!rest)
  214. continue;
  215. if (*rest == '=')
  216. return opterror(options, "takes no value", flags);
  217. if (*rest)
  218. continue;
  219. p->out[p->cpidx++] = arg - 2;
  220. return 0;
  221. }
  222. if (!rest) {
  223. if (!prefixcmp(options->long_name, "no-")) {
  224. /*
  225. * The long name itself starts with "no-", so
  226. * accept the option without "no-" so that users
  227. * do not have to enter "no-no-" to get the
  228. * negation.
  229. */
  230. rest = skip_prefix(arg, options->long_name + 3);
  231. if (rest) {
  232. flags |= OPT_UNSET;
  233. goto match;
  234. }
  235. /* Abbreviated case */
  236. if (!prefixcmp(options->long_name + 3, arg)) {
  237. flags |= OPT_UNSET;
  238. goto is_abbreviated;
  239. }
  240. }
  241. /* abbreviated? */
  242. if (!strncmp(options->long_name, arg, arg_end - arg)) {
  243. is_abbreviated:
  244. if (abbrev_option) {
  245. /*
  246. * If this is abbreviated, it is
  247. * ambiguous. So when there is no
  248. * exact match later, we need to
  249. * error out.
  250. */
  251. ambiguous_option = abbrev_option;
  252. ambiguous_flags = abbrev_flags;
  253. }
  254. if (!(flags & OPT_UNSET) && *arg_end)
  255. p->opt = arg_end + 1;
  256. abbrev_option = options;
  257. abbrev_flags = flags;
  258. continue;
  259. }
  260. /* negated and abbreviated very much? */
  261. if (!prefixcmp("no-", arg)) {
  262. flags |= OPT_UNSET;
  263. goto is_abbreviated;
  264. }
  265. /* negated? */
  266. if (strncmp(arg, "no-", 3))
  267. continue;
  268. flags |= OPT_UNSET;
  269. rest = skip_prefix(arg + 3, options->long_name);
  270. /* abbreviated and negated? */
  271. if (!rest && !prefixcmp(options->long_name, arg + 3))
  272. goto is_abbreviated;
  273. if (!rest)
  274. continue;
  275. }
  276. match:
  277. if (*rest) {
  278. if (*rest != '=')
  279. continue;
  280. p->opt = rest + 1;
  281. }
  282. return get_value(p, options, flags);
  283. }
  284. if (ambiguous_option)
  285. return error("Ambiguous option: %s "
  286. "(could be --%s%s or --%s%s)",
  287. arg,
  288. (ambiguous_flags & OPT_UNSET) ? "no-" : "",
  289. ambiguous_option->long_name,
  290. (abbrev_flags & OPT_UNSET) ? "no-" : "",
  291. abbrev_option->long_name);
  292. if (abbrev_option)
  293. return get_value(p, abbrev_option, abbrev_flags);
  294. return -2;
  295. }
  296. static void check_typos(const char *arg, const struct option *options)
  297. {
  298. if (strlen(arg) < 3)
  299. return;
  300. if (!prefixcmp(arg, "no-")) {
  301. error ("did you mean `--%s` (with two dashes ?)", arg);
  302. exit(129);
  303. }
  304. for (; options->type != OPTION_END; options++) {
  305. if (!options->long_name)
  306. continue;
  307. if (!prefixcmp(options->long_name, arg)) {
  308. error ("did you mean `--%s` (with two dashes ?)", arg);
  309. exit(129);
  310. }
  311. }
  312. }
  313. void parse_options_start(struct parse_opt_ctx_t *ctx,
  314. int argc, const char **argv, int flags)
  315. {
  316. memset(ctx, 0, sizeof(*ctx));
  317. ctx->argc = argc - 1;
  318. ctx->argv = argv + 1;
  319. ctx->out = argv;
  320. ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);
  321. ctx->flags = flags;
  322. if ((flags & PARSE_OPT_KEEP_UNKNOWN) &&
  323. (flags & PARSE_OPT_STOP_AT_NON_OPTION))
  324. die("STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together");
  325. }
  326. static int usage_with_options_internal(const char * const *,
  327. const struct option *, int);
  328. int parse_options_step(struct parse_opt_ctx_t *ctx,
  329. const struct option *options,
  330. const char * const usagestr[])
  331. {
  332. int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
  333. int excl_short_opt = 1;
  334. const char *arg;
  335. /* we must reset ->opt, unknown short option leave it dangling */
  336. ctx->opt = NULL;
  337. for (; ctx->argc; ctx->argc--, ctx->argv++) {
  338. arg = ctx->argv[0];
  339. if (*arg != '-' || !arg[1]) {
  340. if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
  341. break;
  342. ctx->out[ctx->cpidx++] = ctx->argv[0];
  343. continue;
  344. }
  345. if (arg[1] != '-') {
  346. ctx->opt = ++arg;
  347. if (internal_help && *ctx->opt == 'h')
  348. return usage_with_options_internal(usagestr, options, 0);
  349. switch (parse_short_opt(ctx, options)) {
  350. case -1:
  351. return parse_options_usage(usagestr, options, arg, 1);
  352. case -2:
  353. goto unknown;
  354. case -3:
  355. goto exclusive;
  356. default:
  357. break;
  358. }
  359. if (ctx->opt)
  360. check_typos(arg, options);
  361. while (ctx->opt) {
  362. if (internal_help && *ctx->opt == 'h')
  363. return usage_with_options_internal(usagestr, options, 0);
  364. arg = ctx->opt;
  365. switch (parse_short_opt(ctx, options)) {
  366. case -1:
  367. return parse_options_usage(usagestr, options, arg, 1);
  368. case -2:
  369. /* fake a short option thing to hide the fact that we may have
  370. * started to parse aggregated stuff
  371. *
  372. * This is leaky, too bad.
  373. */
  374. ctx->argv[0] = strdup(ctx->opt - 1);
  375. *(char *)ctx->argv[0] = '-';
  376. goto unknown;
  377. case -3:
  378. goto exclusive;
  379. default:
  380. break;
  381. }
  382. }
  383. continue;
  384. }
  385. if (!arg[2]) { /* "--" */
  386. if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) {
  387. ctx->argc--;
  388. ctx->argv++;
  389. }
  390. break;
  391. }
  392. arg += 2;
  393. if (internal_help && !strcmp(arg, "help-all"))
  394. return usage_with_options_internal(usagestr, options, 1);
  395. if (internal_help && !strcmp(arg, "help"))
  396. return usage_with_options_internal(usagestr, options, 0);
  397. if (!strcmp(arg, "list-opts"))
  398. return PARSE_OPT_LIST_OPTS;
  399. if (!strcmp(arg, "list-cmds"))
  400. return PARSE_OPT_LIST_SUBCMDS;
  401. switch (parse_long_opt(ctx, arg, options)) {
  402. case -1:
  403. return parse_options_usage(usagestr, options, arg, 0);
  404. case -2:
  405. goto unknown;
  406. case -3:
  407. excl_short_opt = 0;
  408. goto exclusive;
  409. default:
  410. break;
  411. }
  412. continue;
  413. unknown:
  414. if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN))
  415. return PARSE_OPT_UNKNOWN;
  416. ctx->out[ctx->cpidx++] = ctx->argv[0];
  417. ctx->opt = NULL;
  418. }
  419. return PARSE_OPT_DONE;
  420. exclusive:
  421. parse_options_usage(usagestr, options, arg, excl_short_opt);
  422. if ((excl_short_opt && ctx->excl_opt->short_name) ||
  423. ctx->excl_opt->long_name == NULL) {
  424. char opt = ctx->excl_opt->short_name;
  425. parse_options_usage(NULL, options, &opt, 1);
  426. } else {
  427. parse_options_usage(NULL, options, ctx->excl_opt->long_name, 0);
  428. }
  429. return PARSE_OPT_HELP;
  430. }
  431. int parse_options_end(struct parse_opt_ctx_t *ctx)
  432. {
  433. memmove(ctx->out + ctx->cpidx, ctx->argv, ctx->argc * sizeof(*ctx->out));
  434. ctx->out[ctx->cpidx + ctx->argc] = NULL;
  435. return ctx->cpidx + ctx->argc;
  436. }
  437. int parse_options_subcommand(int argc, const char **argv, const struct option *options,
  438. const char *const subcommands[], const char *usagestr[], int flags)
  439. {
  440. struct parse_opt_ctx_t ctx;
  441. perf_header__set_cmdline(argc, argv);
  442. /* build usage string if it's not provided */
  443. if (subcommands && !usagestr[0]) {
  444. struct strbuf buf = STRBUF_INIT;
  445. strbuf_addf(&buf, "perf %s [<options>] {", argv[0]);
  446. for (int i = 0; subcommands[i]; i++) {
  447. if (i)
  448. strbuf_addstr(&buf, "|");
  449. strbuf_addstr(&buf, subcommands[i]);
  450. }
  451. strbuf_addstr(&buf, "}");
  452. usagestr[0] = strdup(buf.buf);
  453. strbuf_release(&buf);
  454. }
  455. parse_options_start(&ctx, argc, argv, flags);
  456. switch (parse_options_step(&ctx, options, usagestr)) {
  457. case PARSE_OPT_HELP:
  458. exit(129);
  459. case PARSE_OPT_DONE:
  460. break;
  461. case PARSE_OPT_LIST_OPTS:
  462. while (options->type != OPTION_END) {
  463. printf("--%s ", options->long_name);
  464. options++;
  465. }
  466. exit(130);
  467. case PARSE_OPT_LIST_SUBCMDS:
  468. for (int i = 0; subcommands[i]; i++)
  469. printf("%s ", subcommands[i]);
  470. exit(130);
  471. default: /* PARSE_OPT_UNKNOWN */
  472. if (ctx.argv[0][1] == '-') {
  473. error("unknown option `%s'", ctx.argv[0] + 2);
  474. } else {
  475. error("unknown switch `%c'", *ctx.opt);
  476. }
  477. usage_with_options(usagestr, options);
  478. }
  479. return parse_options_end(&ctx);
  480. }
  481. int parse_options(int argc, const char **argv, const struct option *options,
  482. const char * const usagestr[], int flags)
  483. {
  484. return parse_options_subcommand(argc, argv, options, NULL,
  485. (const char **) usagestr, flags);
  486. }
  487. #define USAGE_OPTS_WIDTH 24
  488. #define USAGE_GAP 2
  489. static void print_option_help(const struct option *opts, int full)
  490. {
  491. size_t pos;
  492. int pad;
  493. if (opts->type == OPTION_GROUP) {
  494. fputc('\n', stderr);
  495. if (*opts->help)
  496. fprintf(stderr, "%s\n", opts->help);
  497. return;
  498. }
  499. if (!full && (opts->flags & PARSE_OPT_HIDDEN))
  500. return;
  501. if (opts->flags & PARSE_OPT_DISABLED)
  502. return;
  503. pos = fprintf(stderr, " ");
  504. if (opts->short_name)
  505. pos += fprintf(stderr, "-%c", opts->short_name);
  506. else
  507. pos += fprintf(stderr, " ");
  508. if (opts->long_name && opts->short_name)
  509. pos += fprintf(stderr, ", ");
  510. if (opts->long_name)
  511. pos += fprintf(stderr, "--%s", opts->long_name);
  512. switch (opts->type) {
  513. case OPTION_ARGUMENT:
  514. break;
  515. case OPTION_LONG:
  516. case OPTION_U64:
  517. case OPTION_INTEGER:
  518. case OPTION_UINTEGER:
  519. if (opts->flags & PARSE_OPT_OPTARG)
  520. if (opts->long_name)
  521. pos += fprintf(stderr, "[=<n>]");
  522. else
  523. pos += fprintf(stderr, "[<n>]");
  524. else
  525. pos += fprintf(stderr, " <n>");
  526. break;
  527. case OPTION_CALLBACK:
  528. if (opts->flags & PARSE_OPT_NOARG)
  529. break;
  530. /* FALLTHROUGH */
  531. case OPTION_STRING:
  532. if (opts->argh) {
  533. if (opts->flags & PARSE_OPT_OPTARG)
  534. if (opts->long_name)
  535. pos += fprintf(stderr, "[=<%s>]", opts->argh);
  536. else
  537. pos += fprintf(stderr, "[<%s>]", opts->argh);
  538. else
  539. pos += fprintf(stderr, " <%s>", opts->argh);
  540. } else {
  541. if (opts->flags & PARSE_OPT_OPTARG)
  542. if (opts->long_name)
  543. pos += fprintf(stderr, "[=...]");
  544. else
  545. pos += fprintf(stderr, "[...]");
  546. else
  547. pos += fprintf(stderr, " ...");
  548. }
  549. break;
  550. default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */
  551. case OPTION_END:
  552. case OPTION_GROUP:
  553. case OPTION_BIT:
  554. case OPTION_BOOLEAN:
  555. case OPTION_INCR:
  556. case OPTION_SET_UINT:
  557. case OPTION_SET_PTR:
  558. break;
  559. }
  560. if (pos <= USAGE_OPTS_WIDTH)
  561. pad = USAGE_OPTS_WIDTH - pos;
  562. else {
  563. fputc('\n', stderr);
  564. pad = USAGE_OPTS_WIDTH;
  565. }
  566. fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
  567. }
  568. int usage_with_options_internal(const char * const *usagestr,
  569. const struct option *opts, int full)
  570. {
  571. if (!usagestr)
  572. return PARSE_OPT_HELP;
  573. fprintf(stderr, "\n usage: %s\n", *usagestr++);
  574. while (*usagestr && **usagestr)
  575. fprintf(stderr, " or: %s\n", *usagestr++);
  576. while (*usagestr) {
  577. fprintf(stderr, "%s%s\n",
  578. **usagestr ? " " : "",
  579. *usagestr);
  580. usagestr++;
  581. }
  582. if (opts->type != OPTION_GROUP)
  583. fputc('\n', stderr);
  584. for ( ; opts->type != OPTION_END; opts++)
  585. print_option_help(opts, full);
  586. fputc('\n', stderr);
  587. return PARSE_OPT_HELP;
  588. }
  589. void usage_with_options(const char * const *usagestr,
  590. const struct option *opts)
  591. {
  592. exit_browser(false);
  593. usage_with_options_internal(usagestr, opts, 0);
  594. exit(129);
  595. }
  596. int parse_options_usage(const char * const *usagestr,
  597. const struct option *opts,
  598. const char *optstr, bool short_opt)
  599. {
  600. if (!usagestr)
  601. goto opt;
  602. fprintf(stderr, "\n usage: %s\n", *usagestr++);
  603. while (*usagestr && **usagestr)
  604. fprintf(stderr, " or: %s\n", *usagestr++);
  605. while (*usagestr) {
  606. fprintf(stderr, "%s%s\n",
  607. **usagestr ? " " : "",
  608. *usagestr);
  609. usagestr++;
  610. }
  611. fputc('\n', stderr);
  612. opt:
  613. for ( ; opts->type != OPTION_END; opts++) {
  614. if (short_opt) {
  615. if (opts->short_name == *optstr)
  616. break;
  617. continue;
  618. }
  619. if (opts->long_name == NULL)
  620. continue;
  621. if (!prefixcmp(optstr, opts->long_name))
  622. break;
  623. if (!prefixcmp(optstr, "no-") &&
  624. !prefixcmp(optstr + 3, opts->long_name))
  625. break;
  626. }
  627. if (opts->type != OPTION_END)
  628. print_option_help(opts, 0);
  629. return PARSE_OPT_HELP;
  630. }
  631. int parse_opt_verbosity_cb(const struct option *opt,
  632. const char *arg __maybe_unused,
  633. int unset)
  634. {
  635. int *target = opt->value;
  636. if (unset)
  637. /* --no-quiet, --no-verbose */
  638. *target = 0;
  639. else if (opt->short_name == 'v') {
  640. if (*target >= 0)
  641. (*target)++;
  642. else
  643. *target = 1;
  644. } else {
  645. if (*target <= 0)
  646. (*target)--;
  647. else
  648. *target = -1;
  649. }
  650. return 0;
  651. }
  652. void set_option_flag(struct option *opts, int shortopt, const char *longopt,
  653. int flag)
  654. {
  655. for (; opts->type != OPTION_END; opts++) {
  656. if ((shortopt && opts->short_name == shortopt) ||
  657. (opts->long_name && longopt &&
  658. !strcmp(opts->long_name, longopt))) {
  659. opts->flags |= flag;
  660. break;
  661. }
  662. }
  663. }