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