1 | //===- OptionRSTEmitter.cpp - Table Driven Command Line Option Parsing ----===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "Common/OptEmitter.h" |
10 | #include "llvm/ADT/STLExtras.h" |
11 | #include "llvm/ADT/StringMap.h" |
12 | #include "llvm/TableGen/Record.h" |
13 | #include "llvm/TableGen/TableGenBackend.h" |
14 | |
15 | using namespace llvm; |
16 | |
17 | /// This tablegen backend takes an input .td file describing a list of options |
18 | /// and emits a RST man page. |
19 | static void emitOptionRst(const RecordKeeper &Records, raw_ostream &OS) { |
20 | llvm::StringMap<std::vector<const Record *>> OptionsByGroup; |
21 | |
22 | // Get the options. |
23 | std::vector<const Record *> Opts = Records.getAllDerivedDefinitions(ClassName: "Option" ); |
24 | llvm::sort(C&: Opts, Comp: IsOptionRecordsLess); |
25 | |
26 | // Get the option groups. |
27 | for (const Record *R : Records.getAllDerivedDefinitions(ClassName: "OptionGroup" )) |
28 | OptionsByGroup.try_emplace(Key: R->getValueAsString(FieldName: "Name" )); |
29 | |
30 | // Map options to their group. |
31 | for (const Record *R : Opts) { |
32 | if (const DefInit *DI = dyn_cast<DefInit>(Val: R->getValueInit(FieldName: "Group" ))) |
33 | OptionsByGroup[DI->getDef()->getValueAsString(FieldName: "Name" )].push_back(x: R); |
34 | else |
35 | OptionsByGroup["options" ].push_back(x: R); |
36 | } |
37 | |
38 | // Print options under their group. |
39 | for (const auto &KV : OptionsByGroup) { |
40 | std::string GroupName = KV.getKey().upper(); |
41 | OS << GroupName << '\n'; |
42 | OS << std::string(GroupName.size(), '-') << '\n'; |
43 | OS << '\n'; |
44 | |
45 | for (const Record *R : KV.getValue()) { |
46 | OS << ".. option:: " ; |
47 | |
48 | // Print the prefix. |
49 | std::vector<StringRef> Prefixes = R->getValueAsListOfStrings(FieldName: "Prefixes" ); |
50 | if (!Prefixes.empty()) |
51 | OS << Prefixes[0]; |
52 | |
53 | // Print the option name. |
54 | OS << R->getValueAsString(FieldName: "Name" ); |
55 | |
56 | StringRef MetaVarName; |
57 | // Print the meta-variable. |
58 | if (!isa<UnsetInit>(Val: R->getValueInit(FieldName: "MetaVarName" ))) { |
59 | MetaVarName = R->getValueAsString(FieldName: "MetaVarName" ); |
60 | } else if (!isa<UnsetInit>(Val: R->getValueInit(FieldName: "Values" ))) |
61 | MetaVarName = "<value>" ; |
62 | |
63 | if (!MetaVarName.empty()) { |
64 | OS << '='; |
65 | OS.write_escaped(Str: MetaVarName); |
66 | } |
67 | |
68 | OS << "\n\n" ; |
69 | |
70 | std::string HelpText; |
71 | // The option help text. |
72 | if (!isa<UnsetInit>(Val: R->getValueInit(FieldName: "HelpText" ))) { |
73 | HelpText = R->getValueAsString(FieldName: "HelpText" ).trim().str(); |
74 | if (!HelpText.empty() && HelpText.back() != '.') |
75 | HelpText.push_back(c: '.'); |
76 | } |
77 | |
78 | if (!isa<UnsetInit>(Val: R->getValueInit(FieldName: "Values" ))) { |
79 | SmallVector<StringRef> Values; |
80 | SplitString(Source: R->getValueAsString(FieldName: "Values" ), OutFragments&: Values, Delimiters: "," ); |
81 | HelpText += (" " + MetaVarName + " must be '" ).str(); |
82 | |
83 | if (Values.size() > 1) { |
84 | HelpText += join(Begin: Values.begin(), End: Values.end() - 1, Separator: "', '" ); |
85 | HelpText += "' or '" ; |
86 | } |
87 | HelpText += (Values.back() + "'." ).str(); |
88 | } |
89 | |
90 | if (!HelpText.empty()) { |
91 | OS << ' '; |
92 | OS.write_escaped(Str: HelpText); |
93 | OS << "\n\n" ; |
94 | } |
95 | } |
96 | } |
97 | } |
98 | |
99 | static TableGen::Emitter::Opt X("gen-opt-rst" , emitOptionRst, |
100 | "Generate option RST" ); |
101 | |