parse-options.c 19 KB

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