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