1356843Sdim//===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===//
2356843Sdim//
3356843Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4356843Sdim// See https://llvm.org/LICENSE.txt for license information.
5356843Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6356843Sdim//
7356843Sdim//===----------------------------------------------------------------------===//
8356843Sdim
9356843Sdim#include "OptEmitter.h"
10356843Sdim#include "llvm/ADT/STLExtras.h"
11356843Sdim#include "llvm/ADT/SmallString.h"
12356843Sdim#include "llvm/ADT/Twine.h"
13356843Sdim#include "llvm/TableGen/Error.h"
14356843Sdim#include "llvm/TableGen/Record.h"
15356843Sdim#include "llvm/TableGen/TableGenBackend.h"
16356843Sdim#include <cctype>
17356843Sdim#include <cstring>
18356843Sdim#include <map>
19356843Sdim
20356843Sdimusing namespace llvm;
21356843Sdim
22356843Sdim/// OptParserEmitter - This tablegen backend takes an input .td file
23356843Sdim/// describing a list of options and emits a RST man page.
24356843Sdimnamespace llvm {
25356843Sdimvoid EmitOptRST(RecordKeeper &Records, raw_ostream &OS) {
26356843Sdim  llvm::StringMap<std::vector<Record *>> OptionsByGroup;
27356843Sdim  std::vector<Record *> OptionsWithoutGroup;
28356843Sdim
29356843Sdim  // Get the options.
30356843Sdim  std::vector<Record *> Opts = Records.getAllDerivedDefinitions("Option");
31356843Sdim  array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
32356843Sdim
33356843Sdim  // Get the option groups.
34356843Sdim  const std::vector<Record *> &Groups =
35356843Sdim      Records.getAllDerivedDefinitions("OptionGroup");
36356843Sdim  for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
37356843Sdim    const Record &R = *Groups[i];
38356843Sdim    OptionsByGroup.try_emplace(R.getValueAsString("Name"));
39356843Sdim  }
40356843Sdim
41356843Sdim  // Map options to their group.
42356843Sdim  for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
43356843Sdim    const Record &R = *Opts[i];
44356843Sdim    if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
45356843Sdim      OptionsByGroup[DI->getDef()->getValueAsString("Name")].push_back(Opts[i]);
46356843Sdim    } else {
47356843Sdim      OptionsByGroup["options"].push_back(Opts[i]);
48356843Sdim    }
49356843Sdim  }
50356843Sdim
51356843Sdim  // Print options under their group.
52356843Sdim  for (const auto &KV : OptionsByGroup) {
53356843Sdim    std::string GroupName = KV.getKey().upper();
54356843Sdim    OS << GroupName << '\n';
55356843Sdim    OS << std::string(GroupName.size(), '-') << '\n';
56356843Sdim    OS << '\n';
57356843Sdim
58356843Sdim    for (Record *R : KV.getValue()) {
59356843Sdim      OS << ".. option:: ";
60356843Sdim
61356843Sdim      // Print the prefix.
62356843Sdim      std::vector<StringRef> Prefixes = R->getValueAsListOfStrings("Prefixes");
63356843Sdim      if (!Prefixes.empty())
64356843Sdim        OS << Prefixes[0];
65356843Sdim
66356843Sdim      // Print the option name.
67356843Sdim      OS << R->getValueAsString("Name");
68356843Sdim
69356843Sdim      // Print the meta-variable.
70356843Sdim      if (!isa<UnsetInit>(R->getValueInit("MetaVarName"))) {
71356843Sdim        OS << '=';
72356843Sdim        OS.write_escaped(R->getValueAsString("MetaVarName"));
73356843Sdim      }
74356843Sdim
75356843Sdim      OS << "\n\n";
76356843Sdim
77356843Sdim      // The option help text.
78356843Sdim      if (!isa<UnsetInit>(R->getValueInit("HelpText"))) {
79356843Sdim        OS << ' ';
80356843Sdim        OS.write_escaped(R->getValueAsString("HelpText"));
81356843Sdim        OS << "\n\n";
82356843Sdim      }
83356843Sdim    }
84356843Sdim  }
85356843Sdim}
86356843Sdim} // end namespace llvm
87