command_line.cpp 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "common/command_line.h"
  5. #include <memory>
  6. #include "llvm/ADT/DenseMap.h"
  7. #include "llvm/ADT/PointerIntPair.h"
  8. #include "llvm/Support/FormatVariadic.h"
  9. namespace Carbon::CommandLine {
  10. auto operator<<(llvm::raw_ostream& output, ParseResult result)
  11. -> llvm::raw_ostream& {
  12. switch (result) {
  13. case ParseResult::Error:
  14. return output << "Error";
  15. case ParseResult::MetaSuccess:
  16. return output << "MetaSuccess";
  17. case ParseResult::Success:
  18. return output << "Success";
  19. }
  20. CARBON_FATAL("Corrupt parse result!");
  21. }
  22. auto operator<<(llvm::raw_ostream& output, ArgKind kind) -> llvm::raw_ostream& {
  23. switch (kind) {
  24. case ArgKind::Flag:
  25. return output << "Boolean";
  26. case ArgKind::Integer:
  27. return output << "Integer";
  28. case ArgKind::String:
  29. return output << "String";
  30. case ArgKind::OneOf:
  31. return output << "OneOf";
  32. case ArgKind::MetaActionOnly:
  33. return output << "MetaActionOnly";
  34. case ArgKind::Invalid:
  35. return output << "Invalid";
  36. }
  37. CARBON_FATAL("Corrupt argument kind!");
  38. }
  39. auto operator<<(llvm::raw_ostream& output, CommandKind kind)
  40. -> llvm::raw_ostream& {
  41. switch (kind) {
  42. case CommandKind::Invalid:
  43. return output << "Invalid";
  44. case CommandKind::RequiresSubcommand:
  45. return output << "RequiresSubcommand";
  46. case CommandKind::Action:
  47. return output << "Action";
  48. case CommandKind::MetaAction:
  49. return output << "MetaAction";
  50. }
  51. CARBON_FATAL("Corrupt command kind!");
  52. }
  53. Arg::Arg(const ArgInfo& info) : info(info) {}
  54. Arg::~Arg() {
  55. switch (kind) {
  56. case Kind::Flag:
  57. case Kind::Integer:
  58. case Kind::String:
  59. case Kind::MetaActionOnly:
  60. case Kind::Invalid:
  61. // Nothing to do!
  62. break;
  63. case Kind::OneOf:
  64. value_strings.~decltype(value_strings)();
  65. value_action.~ValueActionT();
  66. if (has_default) {
  67. default_action.~DefaultActionT();
  68. }
  69. break;
  70. }
  71. }
  72. Command::Command(const CommandInfo& info, Command* parent)
  73. : info(info), parent(parent) {}
  74. class MetaPrinter {
  75. public:
  76. explicit MetaPrinter(llvm::raw_ostream& out) : out_(out) {}
  77. // Registers this meta printer with a command through the provided builder.
  78. //
  79. // This adds meta subcommands or options to print both help and version
  80. // information for the command.
  81. void RegisterWithCommand(const Command& command, CommandBuilder& builder);
  82. void PrintHelp(const Command& command) const;
  83. void PrintHelpForSubcommandName(const Command& command,
  84. llvm::StringRef subcommand_name) const;
  85. void PrintVersion(const Command& command) const;
  86. void PrintSubcommands(const Command& command) const;
  87. private:
  88. // The indent is calibrated to allow a short and long option after a two
  89. // character indent on the prior line to be visually recognized as separate
  90. // from the hanging indent.
  91. //
  92. // Visual guide: | -x, --extract
  93. // | Hanging indented.
  94. static constexpr llvm::StringRef BlockIndent = " ";
  95. // Width limit for parent command options in usage rendering.
  96. static constexpr int MaxParentOptionUsageWidth = 8;
  97. // Width limit for the leaf command options in usage rendering.
  98. static constexpr int MaxLeafOptionUsageWidth = 16;
  99. static constexpr CommandInfo HelpCommandInfo = {
  100. .name = "help",
  101. .help = R"""(
  102. Prints help information for the command, including a description, command line
  103. usage, and details of each subcommand and option that can be provided.
  104. )""",
  105. .help_short = R"""(
  106. Prints help information.
  107. )""",
  108. };
  109. static constexpr ArgInfo HelpArgInfo = {
  110. .name = "help",
  111. .value_name = "(full|short)",
  112. .help = R"""(
  113. Prints help information for the command, including a description, command line
  114. usage, and details of each option that can be provided.
  115. )""",
  116. .help_short = HelpCommandInfo.help_short,
  117. };
  118. // Provide a customized description for help on a subcommand to avoid
  119. // confusion with the top-level help.
  120. static constexpr CommandInfo SubHelpCommandInfo = {
  121. .name = "help",
  122. .help = R"""(
  123. Prints help information for the subcommand, including a description, command
  124. line usage, and details of each further subcommand and option that can be
  125. provided.
  126. )""",
  127. .help_short = R"""(
  128. Prints subcommand help information.
  129. )""",
  130. };
  131. static constexpr ArgInfo SubHelpArgInfo = {
  132. .name = "help",
  133. .value_name = "(full|short)",
  134. .help = R"""(
  135. Prints help information for the subcommand, including a description, command
  136. line usage, and details of each option that can be provided.
  137. )""",
  138. .help_short = SubHelpCommandInfo.help_short,
  139. };
  140. static constexpr ArgInfo HelpSubcommandArgInfo = {
  141. .name = "subcommand",
  142. .help = R"""(
  143. Which subcommand to print help information for.
  144. )""",
  145. };
  146. static constexpr CommandInfo VersionCommandInfo = {
  147. .name = "version",
  148. .help = R"""(
  149. Prints the version of this command.
  150. )""",
  151. };
  152. static constexpr ArgInfo VersionArgInfo = {
  153. .name = "version",
  154. .help = VersionCommandInfo.help,
  155. };
  156. // A general helper for rendering a text block.
  157. void PrintTextBlock(llvm::StringRef indent, llvm::StringRef text) const;
  158. // Helpers for version and build information printing.
  159. void PrintRawVersion(const Command& command, llvm::StringRef indent) const;
  160. void PrintRawBuildInfo(const Command& command, llvm::StringRef indent) const;
  161. // Helpers for printing components of help and usage output for arguments,
  162. // including options and positional arguments.
  163. void PrintArgValueUsage(const Arg& arg) const;
  164. void PrintOptionUsage(const Arg& option) const;
  165. void PrintOptionShortName(const Arg& arg) const;
  166. void PrintArgShortValues(const Arg& arg) const;
  167. void PrintArgLongValues(const Arg& arg, llvm::StringRef indent) const;
  168. void PrintArgHelp(const Arg& arg, llvm::StringRef indent) const;
  169. // Helpers for printing command usage summaries.
  170. void PrintRawUsageCommandAndOptions(
  171. const Command& command,
  172. int max_option_width = MaxLeafOptionUsageWidth) const;
  173. void PrintRawUsage(const Command& command, llvm::StringRef indent) const;
  174. void PrintUsage(const Command& command) const;
  175. // Helpers to print various sections of `PrintHelp` that only occur within
  176. // that output.
  177. void PrintHelpSubcommands(const Command& command) const;
  178. void PrintHelpPositionalArgs(const Command& command) const;
  179. void PrintHelpOptions(const Command& command) const;
  180. llvm::raw_ostream& out_;
  181. // A flag that may be configured during command line parsing to select between
  182. // long and short form help output.
  183. bool short_help_ = false;
  184. // The requested subcommand to print help information for.
  185. llvm::StringRef help_subcommand_;
  186. };
  187. void MetaPrinter::RegisterWithCommand(const Command& command,
  188. CommandBuilder& builder) {
  189. bool is_subcommand = command.parent;
  190. bool has_subcommands = !command.subcommands.empty();
  191. // If this command has subcommands, we prefer that model for access meta
  192. // actions, but still silently support using the flags. But we never want to
  193. // *add* subcommands if they aren't already being used.
  194. if (has_subcommands) {
  195. builder.AddSubcommand(
  196. is_subcommand ? SubHelpCommandInfo : HelpCommandInfo,
  197. [&](CommandBuilder& sub_b) {
  198. sub_b.AddStringPositionalArg(HelpSubcommandArgInfo, [&](auto& arg_b) {
  199. arg_b.Set(&help_subcommand_);
  200. });
  201. sub_b.Meta([this, &command]() {
  202. if (help_subcommand_.empty()) {
  203. PrintHelp(command);
  204. } else {
  205. PrintHelpForSubcommandName(command, help_subcommand_);
  206. }
  207. });
  208. });
  209. // Only add version printing support if there is a version string
  210. // configured for this command.
  211. if (!command.info.version.empty()) {
  212. builder.AddSubcommand(VersionCommandInfo, [&](CommandBuilder& sub_b) {
  213. sub_b.Meta([this, &command]() { PrintVersion(command); });
  214. });
  215. }
  216. }
  217. builder.AddOneOfOption(
  218. is_subcommand ? SubHelpArgInfo : HelpArgInfo, [&](auto& arg_b) {
  219. arg_b.HelpHidden(has_subcommands);
  220. arg_b.SetOneOf(
  221. {
  222. arg_b.OneOfValue("full", false).Default(true),
  223. arg_b.OneOfValue("short", true),
  224. },
  225. &short_help_);
  226. arg_b.MetaAction([this, &command]() { PrintHelp(command); });
  227. });
  228. // Only add version printing support if there is a version string configured
  229. // for this command.
  230. if (!command.info.version.empty()) {
  231. builder.AddMetaActionOption(VersionArgInfo, [&](auto& arg_b) {
  232. arg_b.HelpHidden(has_subcommands);
  233. arg_b.MetaAction([this, &command]() { PrintVersion(command); });
  234. });
  235. }
  236. }
  237. void MetaPrinter::PrintHelp(const Command& command) const {
  238. // TODO: begin using the short setting to customize the output.
  239. (void)short_help_;
  240. const CommandInfo& info = command.info;
  241. if (!info.version.empty()) {
  242. // We use the version string as a header for the command help when present.
  243. PrintRawVersion(command, /*indent=*/"");
  244. out_ << "\n";
  245. }
  246. if (!command.info.help.empty()) {
  247. PrintTextBlock("", info.help);
  248. out_ << "\n";
  249. }
  250. if (!info.build_info.empty()) {
  251. out_ << "Build info:\n";
  252. PrintRawBuildInfo(command, /*indent=*/" ");
  253. out_ << "\n";
  254. }
  255. PrintUsage(command);
  256. PrintHelpSubcommands(command);
  257. PrintHelpPositionalArgs(command);
  258. PrintHelpOptions(command);
  259. if (!info.help_epilogue.empty()) {
  260. out_ << "\n";
  261. PrintTextBlock("", info.help_epilogue);
  262. }
  263. // End with a blank line for the long help to make it easier to separate from
  264. // anything that follows in the shell.
  265. out_ << "\n";
  266. }
  267. void MetaPrinter::PrintHelpForSubcommandName(
  268. const Command& command, llvm::StringRef subcommand_name) const {
  269. for (const auto& subcommand : command.subcommands) {
  270. if (subcommand->info.name == subcommand_name) {
  271. PrintHelp(*subcommand);
  272. return;
  273. }
  274. }
  275. out_ << "ERROR: Could not find a subcommand named '" << subcommand_name
  276. << "'.\n";
  277. }
  278. void MetaPrinter::PrintVersion(const Command& command) const {
  279. CARBON_CHECK(
  280. !command.info.version.empty(),
  281. "Printing should not be enabled without a version string configured.");
  282. PrintRawVersion(command, /*indent=*/"");
  283. if (!command.info.build_info.empty()) {
  284. out_ << "\n";
  285. // If there is build info to print, we also render that without any indent.
  286. PrintRawBuildInfo(command, /*indent=*/"");
  287. }
  288. }
  289. void MetaPrinter::PrintSubcommands(const Command& command) const {
  290. for (const auto& subcommand :
  291. llvm::ArrayRef(command.subcommands).drop_back()) {
  292. out_ << "'" << subcommand->info.name << "', ";
  293. }
  294. if (command.subcommands.size() > 1) {
  295. out_ << "or ";
  296. }
  297. out_ << "'" << command.subcommands.back()->info.name << "'";
  298. }
  299. void MetaPrinter::PrintRawVersion(const Command& command,
  300. llvm::StringRef indent) const {
  301. // Newlines are trimmed from the version string an a closing newline added but
  302. // no other formatting is performed.
  303. out_ << indent << command.info.version.trim('\n') << "\n";
  304. }
  305. void MetaPrinter::PrintRawBuildInfo(const Command& command,
  306. llvm::StringRef indent) const {
  307. // Print the build info line-by-line without any wrapping in case it
  308. // contains line-oriented formatted text, but drop leading and trailing blank
  309. // lines.
  310. llvm::SmallVector<llvm::StringRef, 128> lines;
  311. command.info.build_info.trim('\n').split(lines, "\n");
  312. for (auto line : lines) {
  313. out_ << indent << line << "\n";
  314. }
  315. }
  316. void MetaPrinter::PrintTextBlock(llvm::StringRef indent,
  317. llvm::StringRef text) const {
  318. // Strip leading and trailing newlines to make it easy to use multiline raw
  319. // string literals that will naturally have those.
  320. text = text.trim('\n');
  321. // For empty text, print nothing at all. The caller formatting will work to
  322. // handle this gracefully.
  323. if (text.empty()) {
  324. return;
  325. }
  326. // Remove line breaks from the text that would typically be removed when
  327. // rendering it as Markdown. The goal is to preserve:
  328. //
  329. // - Blank lines as paragraph separators.
  330. // - Line breaks after list items or other structural components in Markdown.
  331. // - Fenced regions exactly as they appear.
  332. //
  333. // And within paragraphs (including those nested in lists), reflow the
  334. // paragraph intelligently to the column width. There are TODOs below about
  335. // both lists and reflowing.
  336. llvm::SmallVector<llvm::StringRef, 128> input_lines;
  337. text.split(input_lines, "\n");
  338. for (int i = 0, size = input_lines.size(); i < size;) {
  339. if (input_lines[i].empty()) {
  340. // Blank lines are preserved.
  341. out_ << "\n";
  342. ++i;
  343. continue;
  344. }
  345. if (input_lines[i].starts_with("```")) {
  346. // Fenced regions are preserved verbatim.
  347. llvm::StringRef fence =
  348. input_lines[i].slice(0, input_lines[i].find_first_not_of("`"));
  349. do {
  350. out_ << indent << input_lines[i] << "\n";
  351. ++i;
  352. } while (i < size && !input_lines[i].starts_with(fence));
  353. if (i >= size) {
  354. // Don't error on malformed text blocks, just print what we've got.
  355. break;
  356. }
  357. // Including the close of the fence.
  358. out_ << indent << input_lines[i] << "\n";
  359. ++i;
  360. continue;
  361. }
  362. if (input_lines[i].starts_with(" ")) {
  363. // Indented code blocks ar preserved verbatim, but we don't support tabs
  364. // in the indent for simplicity.
  365. do {
  366. out_ << indent << input_lines[i] << "\n";
  367. ++i;
  368. } while (i < size && input_lines[i].starts_with(" "));
  369. continue;
  370. }
  371. // TODO: Detect other Markdown structures, especially lists and tables.
  372. // Otherwise, collect all of the lines until the end or the next blank line
  373. // as a block of text.
  374. //
  375. // TODO: This is where we should re-flow.
  376. llvm::StringRef space = indent;
  377. do {
  378. out_ << space << input_lines[i].trim();
  379. space = " ";
  380. ++i;
  381. } while (i < size && !input_lines[i].empty());
  382. out_ << "\n";
  383. }
  384. }
  385. void MetaPrinter::PrintArgValueUsage(const Arg& arg) const {
  386. if (!arg.info.value_name.empty()) {
  387. out_ << arg.info.value_name;
  388. return;
  389. }
  390. if (arg.kind == Arg::Kind::OneOf) {
  391. out_ << "(";
  392. llvm::ListSeparator sep("|");
  393. for (llvm::StringRef value_string : arg.value_strings) {
  394. out_ << sep << value_string;
  395. }
  396. out_ << ")";
  397. return;
  398. }
  399. out_ << "...";
  400. }
  401. void MetaPrinter::PrintOptionUsage(const Arg& option) const {
  402. if (option.kind == Arg::Kind::Flag) {
  403. out_ << "--" << (option.default_flag ? "no-" : "") << option.info.name;
  404. return;
  405. }
  406. out_ << "--" << option.info.name;
  407. if (option.kind != Arg::Kind::MetaActionOnly) {
  408. out_ << (option.has_default ? "[" : "") << "=";
  409. PrintArgValueUsage(option);
  410. if (option.has_default) {
  411. out_ << "]";
  412. }
  413. }
  414. }
  415. void MetaPrinter::PrintOptionShortName(const Arg& arg) const {
  416. CARBON_CHECK(!arg.info.short_name.empty(), "No short name to use.");
  417. out_ << "-" << arg.info.short_name;
  418. }
  419. void MetaPrinter::PrintArgShortValues(const Arg& arg) const {
  420. CARBON_CHECK(
  421. arg.kind == Arg::Kind::OneOf,
  422. "Only one-of arguments have interesting value snippets to print.");
  423. llvm::ListSeparator sep;
  424. for (llvm::StringRef value_string : arg.value_strings) {
  425. out_ << sep << value_string;
  426. }
  427. }
  428. void MetaPrinter::PrintArgLongValues(const Arg& arg,
  429. llvm::StringRef indent) const {
  430. out_ << indent << "Possible values:\n";
  431. // TODO: It would be good to add help text for each value and then print it
  432. // here.
  433. for (int i : llvm::seq<int>(0, arg.value_strings.size())) {
  434. llvm::StringRef value_string = arg.value_strings[i];
  435. out_ << indent << "- " << value_string;
  436. if (arg.has_default && i == arg.default_value_index) {
  437. out_ << " (default)";
  438. }
  439. out_ << "\n";
  440. }
  441. }
  442. void MetaPrinter::PrintArgHelp(const Arg& arg, llvm::StringRef indent) const {
  443. // Print out the main help text.
  444. PrintTextBlock(indent, arg.info.help);
  445. // Then print out any help based on the values.
  446. switch (arg.kind) {
  447. case Arg::Kind::Integer:
  448. if (arg.has_default) {
  449. out_ << "\n";
  450. out_ << indent << "Default value: " << arg.default_integer << "\n";
  451. }
  452. break;
  453. case Arg::Kind::String:
  454. if (arg.has_default) {
  455. out_ << "\n";
  456. out_ << indent << "Default value: " << arg.default_string << "\n";
  457. }
  458. break;
  459. case Arg::Kind::OneOf:
  460. out_ << "\n";
  461. PrintArgLongValues(arg, indent);
  462. break;
  463. case Arg::Kind::Flag:
  464. case Arg::Kind::MetaActionOnly:
  465. // No value help.
  466. break;
  467. case Arg::Kind::Invalid:
  468. CARBON_FATAL("Argument configured without any action or kind!");
  469. }
  470. }
  471. void MetaPrinter::PrintRawUsageCommandAndOptions(const Command& command,
  472. int max_option_width) const {
  473. // Recursively print parent usage first with a compressed width.
  474. if (command.parent) {
  475. PrintRawUsageCommandAndOptions(*command.parent, MaxParentOptionUsageWidth);
  476. out_ << " ";
  477. }
  478. out_ << command.info.name;
  479. // Buffer the options rendering so we can limit its length.
  480. std::string buffer_str;
  481. llvm::raw_string_ostream buffer_out(buffer_str);
  482. MetaPrinter buffer_printer(buffer_out);
  483. bool have_short_flags = false;
  484. for (const auto& arg : command.options) {
  485. if (static_cast<int>(buffer_str.size()) > max_option_width) {
  486. break;
  487. }
  488. // We can summarize positive boolean flags with a short name using a
  489. // sequence of short names in a single rendered argument.
  490. if (arg->kind == Arg::Kind::Flag && !arg->default_flag &&
  491. !arg->info.short_name.empty()) {
  492. if (!have_short_flags) {
  493. have_short_flags = true;
  494. buffer_out << "-";
  495. }
  496. buffer_out << arg->info.short_name;
  497. }
  498. }
  499. llvm::StringRef space = have_short_flags ? " " : "";
  500. for (const auto& option : command.options) {
  501. if (static_cast<int>(buffer_str.size()) > max_option_width) {
  502. break;
  503. }
  504. if (option->is_help_hidden || option->meta_action) {
  505. // Skip hidden and options with meta actions attached.
  506. continue;
  507. }
  508. if (option->kind == Arg::Kind::Flag && !option->default_flag &&
  509. !option->info.short_name.empty()) {
  510. // Handled with short names above.
  511. continue;
  512. }
  513. buffer_out << space;
  514. buffer_printer.PrintOptionUsage(*option);
  515. space = " ";
  516. }
  517. if (!buffer_str.empty()) {
  518. if (static_cast<int>(buffer_str.size()) <= max_option_width) {
  519. out_ << " [" << buffer_str << "]";
  520. } else {
  521. out_ << " [OPTIONS]";
  522. }
  523. }
  524. }
  525. void MetaPrinter::PrintRawUsage(const Command& command,
  526. llvm::StringRef indent) const {
  527. if (!command.info.usage.empty()) {
  528. PrintTextBlock(indent, command.info.usage);
  529. return;
  530. }
  531. if (command.kind != Command::Kind::RequiresSubcommand) {
  532. // We're a valid leaf command, so synthesize a full usage line.
  533. out_ << indent;
  534. PrintRawUsageCommandAndOptions(command);
  535. if (!command.positional_args.empty()) {
  536. bool open_optional = false;
  537. for (int i : llvm::seq<int>(0, command.positional_args.size())) {
  538. out_ << " ";
  539. if (i != 0 && command.positional_args[i - 1]->is_append) {
  540. out_ << "-- ";
  541. }
  542. const auto& arg = command.positional_args[i];
  543. if (!arg->is_required && !open_optional) {
  544. out_ << "[";
  545. open_optional = true;
  546. }
  547. out_ << "<" << arg->info.name << ">";
  548. if (arg->is_append) {
  549. out_ << "...";
  550. }
  551. }
  552. if (open_optional) {
  553. out_ << "]";
  554. }
  555. }
  556. out_ << "\n";
  557. }
  558. // If we have subcommands, also recurse into them so each one can print their
  559. // usage lines.
  560. for (const auto& subcommand : command.subcommands) {
  561. if (subcommand->is_help_hidden ||
  562. subcommand->kind == Command::Kind::MetaAction) {
  563. continue;
  564. }
  565. PrintRawUsage(*subcommand, indent);
  566. }
  567. }
  568. void MetaPrinter::PrintUsage(const Command& command) const {
  569. if (!command.parent) {
  570. out_ << "Usage:\n";
  571. } else {
  572. out_ << "Subcommand '" << command.info.name << "' usage:\n";
  573. }
  574. PrintRawUsage(command, " ");
  575. }
  576. void MetaPrinter::PrintHelpSubcommands(const Command& command) const {
  577. bool first_subcommand = true;
  578. for (const auto& subcommand : command.subcommands) {
  579. if (subcommand->is_help_hidden) {
  580. continue;
  581. }
  582. if (first_subcommand) {
  583. first_subcommand = false;
  584. if (!command.parent) {
  585. out_ << "\nSubcommands:";
  586. } else {
  587. out_ << "\nSubcommand '" << command.info.name << "' subcommands:";
  588. }
  589. }
  590. out_ << "\n";
  591. out_ << " " << subcommand->info.name << "\n";
  592. PrintTextBlock(BlockIndent, subcommand->info.help);
  593. }
  594. }
  595. void MetaPrinter::PrintHelpPositionalArgs(const Command& command) const {
  596. bool first_positional_arg = true;
  597. for (const auto& positional_arg : command.positional_args) {
  598. if (positional_arg->is_help_hidden) {
  599. continue;
  600. }
  601. if (first_positional_arg) {
  602. first_positional_arg = false;
  603. if (!command.parent) {
  604. out_ << "\nPositional arguments:";
  605. } else {
  606. out_ << "\nSubcommand '" << command.info.name
  607. << "' positional arguments:";
  608. }
  609. }
  610. out_ << "\n";
  611. out_ << " " << positional_arg->info.name << "\n";
  612. PrintArgHelp(*positional_arg, BlockIndent);
  613. }
  614. }
  615. void MetaPrinter::PrintHelpOptions(const Command& command) const {
  616. bool first_option = true;
  617. for (const auto& option : command.options) {
  618. if (option->is_help_hidden) {
  619. continue;
  620. }
  621. if (first_option) {
  622. first_option = false;
  623. if (!command.parent && command.subcommands.empty()) {
  624. // Only one command level.
  625. out_ << "\nOptions:";
  626. } else if (!command.parent) {
  627. out_ << "\nCommand options:";
  628. } else {
  629. out_ << "\nSubcommand '" << command.info.name << "' options:";
  630. }
  631. }
  632. out_ << "\n";
  633. out_ << " ";
  634. if (!option->info.short_name.empty()) {
  635. PrintOptionShortName(*option);
  636. out_ << ", ";
  637. } else {
  638. out_ << " ";
  639. }
  640. PrintOptionUsage(*option);
  641. out_ << "\n";
  642. PrintArgHelp(*option, BlockIndent);
  643. }
  644. }
  645. class Parser {
  646. public:
  647. explicit Parser(llvm::raw_ostream& out, llvm::raw_ostream& errors,
  648. const CommandInfo& command_info,
  649. llvm::function_ref<void(CommandBuilder&)> build);
  650. auto Parse(llvm::ArrayRef<llvm::StringRef> unparsed_args) -> ParseResult;
  651. private:
  652. friend CommandBuilder;
  653. // For the option and subcommand maps, we use somewhat large small size
  654. // buffers (16) as there is no real size pressure on these and its nice to
  655. // avoid heap allocation in the small cases.
  656. using OptionMapT =
  657. llvm::SmallDenseMap<llvm::StringRef, llvm::PointerIntPair<Arg*, 1, bool>,
  658. 16>;
  659. using SubcommandMapT = llvm::SmallDenseMap<llvm::StringRef, Command*, 16>;
  660. // This table is sized to be 128 so that it can hold ASCII characters. We
  661. // don't need any more than this and using a direct table indexed by the
  662. // character's numeric value makes for a convenient map.
  663. using ShortOptionTableT = std::array<OptionMapT::mapped_type*, 128>;
  664. void PopulateMaps(const Command& command);
  665. void SetOptionDefault(const Arg& option);
  666. auto ParseNegatedFlag(const Arg& flag, std::optional<llvm::StringRef> value)
  667. -> bool;
  668. auto ParseFlag(const Arg& flag, std::optional<llvm::StringRef> value) -> bool;
  669. auto ParseIntegerArgValue(const Arg& arg, llvm::StringRef value) -> bool;
  670. auto ParseStringArgValue(const Arg& arg, llvm::StringRef value) -> bool;
  671. auto ParseOneOfArgValue(const Arg& arg, llvm::StringRef value) -> bool;
  672. auto ParseArg(const Arg& arg, bool short_spelling,
  673. std::optional<llvm::StringRef> value, bool negated_name = false)
  674. -> bool;
  675. auto SplitValue(llvm::StringRef& unparsed_arg)
  676. -> std::optional<llvm::StringRef>;
  677. auto ParseLongOption(llvm::StringRef unparsed_arg) -> bool;
  678. auto ParseShortOptionSeq(llvm::StringRef unparsed_arg) -> bool;
  679. auto FinalizeParsedOptions() -> bool;
  680. auto ParsePositionalArg(llvm::StringRef unparsed_arg) -> bool;
  681. auto ParseSubcommand(llvm::StringRef unparsed_arg) -> bool;
  682. auto ParsePositionalSuffix(llvm::ArrayRef<llvm::StringRef> unparsed_args)
  683. -> bool;
  684. auto FinalizeParse() -> ParseResult;
  685. // When building a command, it registers arguments and potentially subcommands
  686. // that are meta actions to print things to standard out, so we build a meta
  687. // printer for that here.
  688. MetaPrinter meta_printer_;
  689. // Most parsing output goes to an error stream, and we also provide an
  690. // error-oriented meta printer for when that is useful during parsing.
  691. llvm::raw_ostream& errors_;
  692. MetaPrinter error_meta_printer_;
  693. Command root_command_;
  694. const Command* command_;
  695. OptionMapT option_map_;
  696. ShortOptionTableT short_option_table_;
  697. SubcommandMapT subcommand_map_;
  698. int positional_arg_index_ = 0;
  699. bool appending_to_positional_arg_ = false;
  700. ActionT arg_meta_action_;
  701. };
  702. void Parser::PopulateMaps(const Command& command) {
  703. option_map_.clear();
  704. for (const auto& option : command.options) {
  705. option_map_.insert({option->info.name, {option.get(), false}});
  706. }
  707. short_option_table_.fill(nullptr);
  708. for (auto& map_entry : option_map_) {
  709. const Arg* option = map_entry.second.getPointer();
  710. if (option->info.short_name.empty()) {
  711. continue;
  712. }
  713. CARBON_CHECK(option->info.short_name.size() == 1,
  714. "Short option names must have exactly one character.");
  715. unsigned char short_char = option->info.short_name[0];
  716. CARBON_CHECK(short_char < short_option_table_.size(),
  717. "Short option name outside of the expected range.");
  718. short_option_table_[short_char] = &map_entry.second;
  719. }
  720. subcommand_map_.clear();
  721. for (const auto& subcommand : command.subcommands) {
  722. subcommand_map_.insert({subcommand->info.name, subcommand.get()});
  723. }
  724. }
  725. void Parser::SetOptionDefault(const Arg& option) {
  726. CARBON_CHECK(option.has_default, "No default value available!");
  727. switch (option.kind) {
  728. case Arg::Kind::Flag:
  729. *option.flag_storage = option.default_flag;
  730. break;
  731. case Arg::Kind::Integer:
  732. *option.integer_storage = option.default_integer;
  733. break;
  734. case Arg::Kind::String:
  735. *option.string_storage = option.default_string;
  736. break;
  737. case Arg::Kind::OneOf:
  738. option.default_action(option);
  739. break;
  740. case Arg::Kind::MetaActionOnly:
  741. CARBON_FATAL("Can't set a default value for a meta action!");
  742. case Arg::Kind::Invalid:
  743. CARBON_FATAL("Option configured without any action or kind!");
  744. }
  745. }
  746. auto Parser::ParseNegatedFlag(const Arg& flag,
  747. std::optional<llvm::StringRef> value) -> bool {
  748. if (flag.kind != Arg::Kind::Flag) {
  749. errors_ << "ERROR: Cannot use a negated flag name by prefixing it with "
  750. "'no-' when it isn't a boolean flag argument.\n";
  751. return false;
  752. }
  753. if (value) {
  754. errors_ << "ERROR: Cannot specify a value when using a flag name prefixed "
  755. "with 'no-' -- that prefix implies a value of 'false'.\n";
  756. return false;
  757. }
  758. *flag.flag_storage = false;
  759. return true;
  760. }
  761. auto Parser::ParseFlag(const Arg& flag, std::optional<llvm::StringRef> value)
  762. -> bool {
  763. CARBON_CHECK(flag.kind == Arg::Kind::Flag, "Incorrect kind: {0}", flag.kind);
  764. if (!value || *value == "true") {
  765. *flag.flag_storage = true;
  766. } else if (*value == "false") {
  767. *flag.flag_storage = false;
  768. } else {
  769. errors_ << "ERROR: Invalid value specified for the boolean flag '--"
  770. << flag.info.name << "': " << *value << "\n";
  771. return false;
  772. }
  773. return true;
  774. }
  775. auto Parser::ParseIntegerArgValue(const Arg& arg, llvm::StringRef value)
  776. -> bool {
  777. CARBON_CHECK(arg.kind == Arg::Kind::Integer, "Incorrect kind: {0}", arg.kind);
  778. int integer_value;
  779. // Note that this method returns *true* on error!
  780. if (value.getAsInteger(/*Radix=*/0, integer_value)) {
  781. errors_ << "ERROR: Cannot parse value for option '--" << arg.info.name
  782. << "' as an integer: " << value << "\n";
  783. return false;
  784. }
  785. if (!arg.is_append) {
  786. *arg.integer_storage = integer_value;
  787. } else {
  788. arg.integer_sequence->push_back(integer_value);
  789. }
  790. return true;
  791. }
  792. auto Parser::ParseStringArgValue(const Arg& arg, llvm::StringRef value)
  793. -> bool {
  794. CARBON_CHECK(arg.kind == Arg::Kind::String, "Incorrect kind: {0}", arg.kind);
  795. if (!arg.is_append) {
  796. *arg.string_storage = value;
  797. } else {
  798. arg.string_sequence->push_back(value);
  799. }
  800. return true;
  801. }
  802. auto Parser::ParseOneOfArgValue(const Arg& arg, llvm::StringRef value) -> bool {
  803. CARBON_CHECK(arg.kind == Arg::Kind::OneOf, "Incorrect kind: {0}", arg.kind);
  804. if (!arg.value_action(arg, value)) {
  805. errors_ << "ERROR: Option '--" << arg.info.name << "=";
  806. llvm::printEscapedString(value, errors_);
  807. errors_ << "' has an invalid value '";
  808. llvm::printEscapedString(value, errors_);
  809. errors_ << "'; valid values are: ";
  810. for (auto value_string : arg.value_strings.drop_back()) {
  811. errors_ << "'" << value_string << "', ";
  812. }
  813. if (arg.value_strings.size() > 1) {
  814. errors_ << "or ";
  815. }
  816. errors_ << "'" << arg.value_strings.back() << "'\n";
  817. return false;
  818. }
  819. return true;
  820. }
  821. auto Parser::ParseArg(const Arg& arg, bool short_spelling,
  822. std::optional<llvm::StringRef> value, bool negated_name)
  823. -> bool {
  824. // If this argument has a meta action, replace the current meta action with
  825. // it.
  826. if (arg.meta_action) {
  827. arg_meta_action_ = arg.meta_action;
  828. }
  829. // Boolean flags have special parsing logic.
  830. if (negated_name) {
  831. return ParseNegatedFlag(arg, value);
  832. }
  833. if (arg.kind == Arg::Kind::Flag) {
  834. return ParseFlag(arg, value);
  835. }
  836. std::string name;
  837. if (short_spelling) {
  838. name = llvm::formatv("'-{0}' (short for '--{1}')", arg.info.short_name,
  839. arg.info.name);
  840. } else {
  841. name = llvm::formatv("'--{0}'", arg.info.name);
  842. }
  843. if (!value) {
  844. // We can't have a positional argument without a value, so we know this is
  845. // an option and handle it as such.
  846. if (arg.kind == Arg::Kind::MetaActionOnly) {
  847. // Nothing further to do here, this is only a meta-action.
  848. return true;
  849. }
  850. if (!arg.has_default) {
  851. errors_ << "ERROR: Option " << name
  852. << " requires a value to be provided and none was.\n";
  853. return false;
  854. }
  855. SetOptionDefault(arg);
  856. return true;
  857. }
  858. // There is a value to parse as part of the argument.
  859. switch (arg.kind) {
  860. case Arg::Kind::Integer:
  861. return ParseIntegerArgValue(arg, *value);
  862. case Arg::Kind::String:
  863. return ParseStringArgValue(arg, *value);
  864. case Arg::Kind::OneOf:
  865. return ParseOneOfArgValue(arg, *value);
  866. case Arg::Kind::MetaActionOnly:
  867. errors_ << "ERROR: Option " << name
  868. << " cannot be used with a value, and '" << *value
  869. << "' was provided.\n";
  870. // TODO: improve message
  871. return false;
  872. case Arg::Kind::Flag:
  873. case Arg::Kind::Invalid:
  874. CARBON_FATAL("Invalid kind!");
  875. }
  876. }
  877. auto Parser::SplitValue(llvm::StringRef& unparsed_arg)
  878. -> std::optional<llvm::StringRef> {
  879. // Split out a value if present.
  880. std::optional<llvm::StringRef> value;
  881. auto index = unparsed_arg.find('=');
  882. if (index != llvm::StringRef::npos) {
  883. value = unparsed_arg.substr(index + 1);
  884. unparsed_arg = unparsed_arg.substr(0, index);
  885. }
  886. return value;
  887. }
  888. auto Parser::ParseLongOption(llvm::StringRef unparsed_arg) -> bool {
  889. CARBON_CHECK(unparsed_arg.starts_with("--") && unparsed_arg.size() > 2,
  890. "Must only be called on a potential long option.");
  891. // Walk past the double dash.
  892. unparsed_arg = unparsed_arg.drop_front(2);
  893. bool negated_name = unparsed_arg.consume_front("no-");
  894. std::optional<llvm::StringRef> value = SplitValue(unparsed_arg);
  895. auto option_it = option_map_.find(unparsed_arg);
  896. if (option_it == option_map_.end()) {
  897. errors_ << "ERROR: Unknown option '--" << (negated_name ? "no-" : "")
  898. << unparsed_arg << "'\n";
  899. // TODO: improve error
  900. return false;
  901. }
  902. // Mark this option as parsed.
  903. option_it->second.setInt(true);
  904. // Parse this specific option and any value.
  905. const Arg& option = *option_it->second.getPointer();
  906. return ParseArg(option, /*short_spelling=*/false, value, negated_name);
  907. }
  908. auto Parser::ParseShortOptionSeq(llvm::StringRef unparsed_arg) -> bool {
  909. CARBON_CHECK(unparsed_arg.starts_with("-") && unparsed_arg.size() > 1,
  910. "Must only be called on a potential short option sequence.");
  911. unparsed_arg = unparsed_arg.drop_front();
  912. std::optional<llvm::StringRef> value = SplitValue(unparsed_arg);
  913. if (value && unparsed_arg.size() != 1) {
  914. errors_ << "ERROR: Cannot provide a value to the group of multiple short "
  915. "options '-"
  916. << unparsed_arg
  917. << "=...'; values must be provided to a single option, using "
  918. "either the short or long spelling.\n";
  919. return false;
  920. }
  921. for (unsigned char c : unparsed_arg) {
  922. auto* arg_entry =
  923. (c < short_option_table_.size()) ? short_option_table_[c] : nullptr;
  924. if (!arg_entry) {
  925. errors_ << "ERROR: Unknown short option '" << c << "'\n";
  926. return false;
  927. }
  928. // Mark this argument as parsed.
  929. arg_entry->setInt(true);
  930. // Parse the argument, including the value if this is the last.
  931. const Arg& arg = *arg_entry->getPointer();
  932. if (!ParseArg(arg, /*short_spelling=*/true, value)) {
  933. return false;
  934. }
  935. }
  936. return true;
  937. }
  938. auto Parser::FinalizeParsedOptions() -> bool {
  939. llvm::SmallVector<const Arg*> missing_options;
  940. for (const auto& option_entry : option_map_) {
  941. const Arg* option = option_entry.second.getPointer();
  942. if (!option_entry.second.getInt()) {
  943. // If the argument has a default value and isn't a meta-action, we need to
  944. // act on that when it isn't passed.
  945. if (option->has_default && !option->meta_action) {
  946. SetOptionDefault(*option);
  947. }
  948. // Remember any missing required arguments, we'll diagnose those.
  949. if (option->is_required) {
  950. missing_options.push_back(option);
  951. }
  952. }
  953. }
  954. if (missing_options.empty()) {
  955. return true;
  956. }
  957. // Sort the missing arguments by name to provide a stable and deterministic
  958. // error message. We know there can't be duplicate names because these came
  959. // from a may keyed on the name, so this provides a total ordering.
  960. std::sort(missing_options.begin(), missing_options.end(),
  961. [](const Arg* lhs, const Arg* rhs) {
  962. return lhs->info.name < rhs->info.name;
  963. });
  964. for (const Arg* option : missing_options) {
  965. errors_ << "ERROR: Required option '--" << option->info.name
  966. << "' not provided.\n";
  967. }
  968. return false;
  969. }
  970. auto Parser::ParsePositionalArg(llvm::StringRef unparsed_arg) -> bool {
  971. if (static_cast<size_t>(positional_arg_index_) >=
  972. command_->positional_args.size()) {
  973. errors_ << "ERROR: Completed parsing all "
  974. << command_->positional_args.size()
  975. << " configured positional arguments, and found an additional "
  976. "positional argument: '"
  977. << unparsed_arg << "'\n";
  978. return false;
  979. }
  980. const Arg& arg = *command_->positional_args[positional_arg_index_];
  981. // Mark that we'll keep appending here until a `--` marker. When already
  982. // appending this is redundant but harmless.
  983. appending_to_positional_arg_ = arg.is_append;
  984. if (!appending_to_positional_arg_) {
  985. // If we're not continuing to append to a current positional arg,
  986. // increment the positional arg index to find the next argument we
  987. // should use here.
  988. ++positional_arg_index_;
  989. }
  990. return ParseArg(arg, /*short_spelling=*/false, unparsed_arg);
  991. }
  992. auto Parser::ParseSubcommand(llvm::StringRef unparsed_arg) -> bool {
  993. auto subcommand_it = subcommand_map_.find(unparsed_arg);
  994. if (subcommand_it == subcommand_map_.end()) {
  995. errors_ << "ERROR: Invalid subcommand '" << unparsed_arg
  996. << "'. Available subcommands: ";
  997. error_meta_printer_.PrintSubcommands(*command_);
  998. errors_ << "\n";
  999. return false;
  1000. }
  1001. // Before we recurse into the subcommand, verify that all the required
  1002. // arguments for this command were in fact parsed.
  1003. if (!FinalizeParsedOptions()) {
  1004. return false;
  1005. }
  1006. // Recurse into the subcommand, tracking the active command.
  1007. command_ = subcommand_it->second;
  1008. PopulateMaps(*command_);
  1009. return true;
  1010. }
  1011. auto Parser::FinalizeParse() -> ParseResult {
  1012. // If an argument action is provided, we run that and consider the parse
  1013. // meta-successful rather than verifying required arguments were provided and
  1014. // the (sub)command action.
  1015. if (arg_meta_action_) {
  1016. arg_meta_action_();
  1017. return ParseResult::MetaSuccess;
  1018. }
  1019. // Verify we're not missing any arguments.
  1020. if (!FinalizeParsedOptions()) {
  1021. return ParseResult::Error;
  1022. }
  1023. // If we were appending to a positional argument, mark that as complete.
  1024. llvm::ArrayRef positional_args = command_->positional_args;
  1025. if (appending_to_positional_arg_) {
  1026. CARBON_CHECK(
  1027. static_cast<size_t>(positional_arg_index_) < positional_args.size(),
  1028. "Appending to a positional argument with an invalid index: {0}",
  1029. positional_arg_index_);
  1030. ++positional_arg_index_;
  1031. }
  1032. // See if any positional args are required and unparsed.
  1033. auto unparsed_positional_args = positional_args.slice(positional_arg_index_);
  1034. if (!unparsed_positional_args.empty()) {
  1035. // There are un-parsed positional arguments, make sure they aren't required.
  1036. const Arg& missing_arg = *unparsed_positional_args.front();
  1037. if (missing_arg.is_required) {
  1038. errors_ << "ERROR: Not all required positional arguments were provided. "
  1039. "First missing and required positional argument: '"
  1040. << missing_arg.info.name << "'\n";
  1041. return ParseResult::Error;
  1042. }
  1043. for (const auto& arg_ptr : unparsed_positional_args) {
  1044. CARBON_CHECK(
  1045. !arg_ptr->is_required,
  1046. "Cannot have required positional parameters after an optional one.");
  1047. }
  1048. }
  1049. switch (command_->kind) {
  1050. case Command::Kind::Invalid:
  1051. CARBON_FATAL("Should never have a parser with an invalid command!");
  1052. case Command::Kind::RequiresSubcommand:
  1053. errors_ << "ERROR: No subcommand specified. Available subcommands: ";
  1054. error_meta_printer_.PrintSubcommands(*command_);
  1055. errors_ << "\n";
  1056. return ParseResult::Error;
  1057. case Command::Kind::Action:
  1058. // All arguments have been successfully parsed, run any action for the
  1059. // most specific selected command. Only the leaf command's action is run.
  1060. command_->action();
  1061. return ParseResult::Success;
  1062. case Command::Kind::MetaAction:
  1063. command_->action();
  1064. return ParseResult::MetaSuccess;
  1065. }
  1066. }
  1067. auto Parser::ParsePositionalSuffix(
  1068. llvm::ArrayRef<llvm::StringRef> unparsed_args) -> bool {
  1069. CARBON_CHECK(
  1070. !command_->positional_args.empty(),
  1071. "Cannot do positional suffix parsing without positional arguments!");
  1072. CARBON_CHECK(
  1073. !unparsed_args.empty() && unparsed_args.front() == "--",
  1074. "Must be called with a suffix of arguments starting with a `--` that "
  1075. "switches to positional suffix parsing.");
  1076. // Once we're in the positional suffix, we can track empty positional
  1077. // arguments.
  1078. bool empty_positional = false;
  1079. while (!unparsed_args.empty()) {
  1080. llvm::StringRef unparsed_arg = unparsed_args.front();
  1081. unparsed_args = unparsed_args.drop_front();
  1082. if (unparsed_arg != "--") {
  1083. if (!ParsePositionalArg(unparsed_arg)) {
  1084. return false;
  1085. }
  1086. empty_positional = false;
  1087. continue;
  1088. }
  1089. if (appending_to_positional_arg_ || empty_positional) {
  1090. ++positional_arg_index_;
  1091. if (static_cast<size_t>(positional_arg_index_) >=
  1092. command_->positional_args.size()) {
  1093. errors_
  1094. << "ERROR: Completed parsing all "
  1095. << command_->positional_args.size()
  1096. << " configured positional arguments, but found a subsequent `--` "
  1097. "and have no further positional arguments to parse beyond it.\n";
  1098. return false;
  1099. }
  1100. }
  1101. appending_to_positional_arg_ = false;
  1102. empty_positional = true;
  1103. }
  1104. return true;
  1105. }
  1106. Parser::Parser(llvm::raw_ostream& out, llvm::raw_ostream& errors,
  1107. const CommandInfo& command_info,
  1108. llvm::function_ref<void(CommandBuilder&)> build)
  1109. : meta_printer_(out),
  1110. errors_(errors),
  1111. error_meta_printer_(errors),
  1112. root_command_(command_info) {
  1113. // Run the command building lambda on a builder for the root command.
  1114. CommandBuilder builder(root_command_, meta_printer_);
  1115. build(builder);
  1116. builder.Finalize();
  1117. command_ = &root_command_;
  1118. }
  1119. auto Parser::Parse(llvm::ArrayRef<llvm::StringRef> unparsed_args)
  1120. -> ParseResult {
  1121. PopulateMaps(*command_);
  1122. while (!unparsed_args.empty()) {
  1123. llvm::StringRef unparsed_arg = unparsed_args.front();
  1124. // Peak at the front for an exact `--` argument that switches to a
  1125. // positional suffix parsing without dropping this argument.
  1126. if (unparsed_arg == "--") {
  1127. if (command_->positional_args.empty()) {
  1128. errors_ << "ERROR: Cannot meaningfully end option and subcommand "
  1129. "arguments with a `--` argument when there are no "
  1130. "positional arguments to parse.\n";
  1131. return ParseResult::Error;
  1132. }
  1133. if (static_cast<size_t>(positional_arg_index_) >=
  1134. command_->positional_args.size()) {
  1135. errors_ << "ERROR: Switched to purely positional arguments with a `--` "
  1136. "argument despite already having parsed all positional "
  1137. "arguments for this command.\n";
  1138. return ParseResult::Error;
  1139. }
  1140. if (!ParsePositionalSuffix(unparsed_args)) {
  1141. return ParseResult::Error;
  1142. }
  1143. // No more unparsed arguments to handle.
  1144. break;
  1145. }
  1146. // Now that we're not switching parse modes, drop the current unparsed
  1147. // argument and parse it.
  1148. unparsed_args = unparsed_args.drop_front();
  1149. if (unparsed_arg.starts_with("--")) {
  1150. // Note that the exact argument "--" has been handled above already.
  1151. if (!ParseLongOption(unparsed_arg)) {
  1152. return ParseResult::Error;
  1153. }
  1154. continue;
  1155. }
  1156. if (unparsed_arg.starts_with("-") && unparsed_arg.size() > 1) {
  1157. if (!ParseShortOptionSeq(unparsed_arg)) {
  1158. return ParseResult::Error;
  1159. }
  1160. continue;
  1161. }
  1162. CARBON_CHECK(
  1163. command_->positional_args.empty() || command_->subcommands.empty(),
  1164. "Cannot have both positional arguments and subcommands!");
  1165. if (command_->positional_args.empty() && command_->subcommands.empty()) {
  1166. errors_ << "ERROR: Found unexpected positional argument or subcommand: '"
  1167. << unparsed_arg << "'\n";
  1168. return ParseResult::Error;
  1169. }
  1170. if (!command_->positional_args.empty()) {
  1171. if (!ParsePositionalArg(unparsed_arg)) {
  1172. return ParseResult::Error;
  1173. }
  1174. continue;
  1175. }
  1176. if (!ParseSubcommand(unparsed_arg)) {
  1177. return ParseResult::Error;
  1178. }
  1179. }
  1180. return FinalizeParse();
  1181. }
  1182. void ArgBuilder::Required(bool is_required) { arg_.is_required = is_required; }
  1183. void ArgBuilder::HelpHidden(bool is_help_hidden) {
  1184. arg_.is_help_hidden = is_help_hidden;
  1185. }
  1186. ArgBuilder::ArgBuilder(Arg& arg) : arg_(arg) {}
  1187. void FlagBuilder::Default(bool flag_value) {
  1188. arg_.has_default = true;
  1189. arg_.default_flag = flag_value;
  1190. }
  1191. void FlagBuilder::Set(bool* flag) { arg_.flag_storage = flag; }
  1192. void IntegerArgBuilder::Default(int integer_value) {
  1193. arg_.has_default = true;
  1194. arg_.default_integer = integer_value;
  1195. }
  1196. void IntegerArgBuilder::Set(int* integer) {
  1197. arg_.is_append = false;
  1198. arg_.integer_storage = integer;
  1199. }
  1200. void IntegerArgBuilder::Append(llvm::SmallVectorImpl<int>* sequence) {
  1201. arg_.is_append = true;
  1202. arg_.integer_sequence = sequence;
  1203. }
  1204. void StringArgBuilder::Default(llvm::StringRef string_value) {
  1205. arg_.has_default = true;
  1206. arg_.default_string = string_value;
  1207. }
  1208. void StringArgBuilder::Set(llvm::StringRef* string) {
  1209. arg_.is_append = false;
  1210. arg_.string_storage = string;
  1211. }
  1212. void StringArgBuilder::Append(
  1213. llvm::SmallVectorImpl<llvm::StringRef>* sequence) {
  1214. arg_.is_append = true;
  1215. arg_.string_sequence = sequence;
  1216. }
  1217. static auto IsValidName(llvm::StringRef name) -> bool {
  1218. if (name.size() <= 1) {
  1219. return false;
  1220. }
  1221. if (!llvm::isAlnum(name.front())) {
  1222. return false;
  1223. }
  1224. if (!llvm::isAlnum(name.back())) {
  1225. return false;
  1226. }
  1227. for (char c : name.drop_front().drop_back()) {
  1228. if (c != '-' && c != '_' && !llvm::isAlnum(c)) {
  1229. return false;
  1230. }
  1231. }
  1232. // We disallow names starting with "no-" as we will parse those for boolean
  1233. // flags.
  1234. return !name.starts_with("no-");
  1235. }
  1236. void CommandBuilder::AddFlag(const ArgInfo& info,
  1237. llvm::function_ref<void(FlagBuilder&)> build) {
  1238. FlagBuilder builder(AddArgImpl(info, Arg::Kind::Flag));
  1239. // All boolean flags have an implicit default of `false`, although it can be
  1240. // overridden in the build callback.
  1241. builder.Default(false);
  1242. build(builder);
  1243. }
  1244. void CommandBuilder::AddIntegerOption(
  1245. const ArgInfo& info, llvm::function_ref<void(IntegerArgBuilder&)> build) {
  1246. IntegerArgBuilder builder(AddArgImpl(info, Arg::Kind::Integer));
  1247. build(builder);
  1248. }
  1249. void CommandBuilder::AddStringOption(
  1250. const ArgInfo& info, llvm::function_ref<void(StringArgBuilder&)> build) {
  1251. StringArgBuilder builder(AddArgImpl(info, Arg::Kind::String));
  1252. build(builder);
  1253. }
  1254. void CommandBuilder::AddOneOfOption(
  1255. const ArgInfo& info, llvm::function_ref<void(OneOfArgBuilder&)> build) {
  1256. OneOfArgBuilder builder(AddArgImpl(info, Arg::Kind::OneOf));
  1257. build(builder);
  1258. }
  1259. void CommandBuilder::AddMetaActionOption(
  1260. const ArgInfo& info, llvm::function_ref<void(ArgBuilder&)> build) {
  1261. ArgBuilder builder(AddArgImpl(info, Arg::Kind::MetaActionOnly));
  1262. build(builder);
  1263. }
  1264. void CommandBuilder::AddIntegerPositionalArg(
  1265. const ArgInfo& info, llvm::function_ref<void(IntegerArgBuilder&)> build) {
  1266. AddPositionalArgImpl(info, Arg::Kind::Integer, [build](Arg& arg) {
  1267. IntegerArgBuilder builder(arg);
  1268. build(builder);
  1269. });
  1270. }
  1271. void CommandBuilder::AddStringPositionalArg(
  1272. const ArgInfo& info, llvm::function_ref<void(StringArgBuilder&)> build) {
  1273. AddPositionalArgImpl(info, Arg::Kind::String, [build](Arg& arg) {
  1274. StringArgBuilder builder(arg);
  1275. build(builder);
  1276. });
  1277. }
  1278. void CommandBuilder::AddOneOfPositionalArg(
  1279. const ArgInfo& info, llvm::function_ref<void(OneOfArgBuilder&)> build) {
  1280. AddPositionalArgImpl(info, Arg::Kind::OneOf, [build](Arg& arg) {
  1281. OneOfArgBuilder builder(arg);
  1282. build(builder);
  1283. });
  1284. }
  1285. void CommandBuilder::AddSubcommand(
  1286. const CommandInfo& info, llvm::function_ref<void(CommandBuilder&)> build) {
  1287. CARBON_CHECK(IsValidName(info.name), "Invalid subcommand name: {0}",
  1288. info.name);
  1289. CARBON_CHECK(subcommand_names_.insert(info.name).second,
  1290. "Added a duplicate subcommand: {0}", info.name);
  1291. CARBON_CHECK(
  1292. command_.positional_args.empty(),
  1293. "Cannot add subcommands to a command with a positional argument.");
  1294. command_.subcommands.emplace_back(new Command(info, &command_));
  1295. CommandBuilder builder(*command_.subcommands.back(), meta_printer_);
  1296. build(builder);
  1297. builder.Finalize();
  1298. }
  1299. void CommandBuilder::HelpHidden(bool is_help_hidden) {
  1300. command_.is_help_hidden = is_help_hidden;
  1301. }
  1302. void CommandBuilder::RequiresSubcommand() {
  1303. CARBON_CHECK(!command_.subcommands.empty(),
  1304. "Cannot require subcommands unless there are subcommands.");
  1305. CARBON_CHECK(command_.positional_args.empty(),
  1306. "Cannot require subcommands and have a positional argument.");
  1307. CARBON_CHECK(command_.kind == Kind::Invalid,
  1308. "Already established the kind of this command as: {0}",
  1309. command_.kind);
  1310. command_.kind = Kind::RequiresSubcommand;
  1311. }
  1312. void CommandBuilder::Do(ActionT action) {
  1313. CARBON_CHECK(command_.kind == Kind::Invalid,
  1314. "Already established the kind of this command as: {0}",
  1315. command_.kind);
  1316. command_.kind = Kind::Action;
  1317. command_.action = std::move(action);
  1318. }
  1319. void CommandBuilder::Meta(ActionT action) {
  1320. CARBON_CHECK(command_.kind == Kind::Invalid,
  1321. "Already established the kind of this command as: {0}",
  1322. command_.kind);
  1323. command_.kind = Kind::MetaAction;
  1324. command_.action = std::move(action);
  1325. }
  1326. CommandBuilder::CommandBuilder(Command& command, MetaPrinter& meta_printer)
  1327. : command_(command), meta_printer_(meta_printer) {}
  1328. auto CommandBuilder::AddArgImpl(const ArgInfo& info, Arg::Kind kind) -> Arg& {
  1329. CARBON_CHECK(IsValidName(info.name), "Invalid argument name: {0}", info.name);
  1330. CARBON_CHECK(arg_names_.insert(info.name).second,
  1331. "Added a duplicate argument name: {0}", info.name);
  1332. command_.options.emplace_back(new Arg(info));
  1333. Arg& arg = *command_.options.back();
  1334. arg.kind = kind;
  1335. return arg;
  1336. }
  1337. void CommandBuilder::AddPositionalArgImpl(
  1338. const ArgInfo& info, Arg::Kind kind, llvm::function_ref<void(Arg&)> build) {
  1339. CARBON_CHECK(IsValidName(info.name), "Invalid argument name: {0}", info.name);
  1340. CARBON_CHECK(
  1341. command_.subcommands.empty(),
  1342. "Cannot add a positional argument to a command with subcommands.");
  1343. command_.positional_args.emplace_back(new Arg(info));
  1344. Arg& arg = *command_.positional_args.back();
  1345. arg.kind = kind;
  1346. build(arg);
  1347. CARBON_CHECK(!arg.is_help_hidden,
  1348. "Cannot have a help-hidden positional argument.");
  1349. if (arg.is_required && command_.positional_args.size() > 1) {
  1350. CARBON_CHECK((*std::prev(command_.positional_args.end(), 2))->is_required,
  1351. "A required positional argument cannot be added after an "
  1352. "optional one.");
  1353. }
  1354. }
  1355. void CommandBuilder::Finalize() {
  1356. meta_printer_.RegisterWithCommand(command_, *this);
  1357. }
  1358. auto Parse(llvm::ArrayRef<llvm::StringRef> unparsed_args,
  1359. llvm::raw_ostream& out, llvm::raw_ostream& errors,
  1360. const CommandInfo& command_info,
  1361. llvm::function_ref<void(CommandBuilder&)> build) -> ParseResult {
  1362. // Build a parser, which includes building the command description provided by
  1363. // the user.
  1364. Parser parser(out, errors, command_info, build);
  1365. // Now parse the arguments provided using that parser.
  1366. return parser.Parse(unparsed_args);
  1367. }
  1368. } // namespace Carbon::CommandLine