1226586Sdim//===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===// 2226586Sdim// 3226586Sdim// The LLVM Compiler Infrastructure 4226586Sdim// 5226586Sdim// This file is distributed under the University of Illinois Open Source 6226586Sdim// License. See LICENSE.TXT for details. 7226586Sdim// 8226586Sdim//===----------------------------------------------------------------------===// 9226586Sdim 10249423Sdim#include "llvm/ADT/STLExtras.h" 11249423Sdim#include "llvm/ADT/SmallString.h" 12249423Sdim#include "llvm/ADT/Twine.h" 13243830Sdim#include "llvm/TableGen/Error.h" 14226586Sdim#include "llvm/TableGen/Record.h" 15239462Sdim#include "llvm/TableGen/TableGenBackend.h" 16243830Sdim#include <map> 17243830Sdim 18226586Sdimusing namespace llvm; 19226586Sdim 20226586Sdimstatic int StrCmpOptionName(const char *A, const char *B) { 21226586Sdim char a = *A, b = *B; 22226586Sdim while (a == b) { 23226586Sdim if (a == '\0') 24226586Sdim return 0; 25226586Sdim 26226586Sdim a = *++A; 27226586Sdim b = *++B; 28226586Sdim } 29226586Sdim 30226586Sdim if (a == '\0') // A is a prefix of B. 31226586Sdim return 1; 32226586Sdim if (b == '\0') // B is a prefix of A. 33226586Sdim return -1; 34226586Sdim 35226586Sdim // Otherwise lexicographic. 36226586Sdim return (a < b) ? -1 : 1; 37226586Sdim} 38226586Sdim 39226586Sdimstatic int CompareOptionRecords(const void *Av, const void *Bv) { 40243830Sdim const Record *A = *(const Record*const*) Av; 41243830Sdim const Record *B = *(const Record*const*) Bv; 42226586Sdim 43226586Sdim // Sentinel options precede all others and are only ordered by precedence. 44226586Sdim bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel"); 45226586Sdim bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel"); 46226586Sdim if (ASent != BSent) 47226586Sdim return ASent ? -1 : 1; 48226586Sdim 49226586Sdim // Compare options by name, unless they are sentinels. 50226586Sdim if (!ASent) 51226586Sdim if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(), 52226586Sdim B->getValueAsString("Name").c_str())) 53226586Sdim return Cmp; 54226586Sdim 55243830Sdim if (!ASent) { 56243830Sdim std::vector<std::string> APrefixes = A->getValueAsListOfStrings("Prefixes"); 57243830Sdim std::vector<std::string> BPrefixes = B->getValueAsListOfStrings("Prefixes"); 58243830Sdim 59243830Sdim for (std::vector<std::string>::const_iterator APre = APrefixes.begin(), 60243830Sdim AEPre = APrefixes.end(), 61243830Sdim BPre = BPrefixes.begin(), 62243830Sdim BEPre = BPrefixes.end(); 63243830Sdim APre != AEPre && 64243830Sdim BPre != BEPre; 65243830Sdim ++APre, ++BPre) { 66243830Sdim if (int Cmp = StrCmpOptionName(APre->c_str(), BPre->c_str())) 67243830Sdim return Cmp; 68243830Sdim } 69243830Sdim } 70243830Sdim 71226586Sdim // Then by the kind precedence; 72226586Sdim int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence"); 73226586Sdim int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence"); 74243830Sdim if (APrec == BPrec && 75243830Sdim A->getValueAsListOfStrings("Prefixes") == 76243830Sdim B->getValueAsListOfStrings("Prefixes")) { 77243830Sdim PrintError(A->getLoc(), Twine("Option is equivilent to")); 78243830Sdim PrintError(B->getLoc(), Twine("Other defined here")); 79243830Sdim PrintFatalError("Equivalent Options found."); 80243830Sdim } 81226586Sdim return APrec < BPrec ? -1 : 1; 82226586Sdim} 83226586Sdim 84226586Sdimstatic const std::string getOptionName(const Record &R) { 85226586Sdim // Use the record name unless EnumName is defined. 86243830Sdim if (isa<UnsetInit>(R.getValueInit("EnumName"))) 87226586Sdim return R.getName(); 88226586Sdim 89226586Sdim return R.getValueAsString("EnumName"); 90226586Sdim} 91226586Sdim 92226586Sdimstatic raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) { 93226586Sdim OS << '"'; 94226586Sdim OS.write_escaped(Str); 95226586Sdim OS << '"'; 96226586Sdim return OS; 97226586Sdim} 98226586Sdim 99239462Sdim/// OptParserEmitter - This tablegen backend takes an input .td file 100239462Sdim/// describing a list of options and emits a data structure for parsing and 101239462Sdim/// working with those options when given an input command line. 102239462Sdimnamespace clang { 103239462Sdimvoid EmitOptParser(RecordKeeper &Records, raw_ostream &OS, bool GenDefs) { 104226586Sdim // Get the option groups and options. 105226586Sdim const std::vector<Record*> &Groups = 106226586Sdim Records.getAllDerivedDefinitions("OptionGroup"); 107226586Sdim std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option"); 108226586Sdim 109226586Sdim if (GenDefs) 110239462Sdim emitSourceFileHeader("Option Parsing Definitions", OS); 111226586Sdim else 112239462Sdim emitSourceFileHeader("Option Parsing Table", OS); 113226586Sdim 114226586Sdim array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords); 115226586Sdim if (GenDefs) { 116243830Sdim // Generate prefix groups. 117243830Sdim typedef SmallVector<SmallString<2>, 2> PrefixKeyT; 118243830Sdim typedef std::map<PrefixKeyT, std::string> PrefixesT; 119243830Sdim PrefixesT Prefixes; 120243830Sdim Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0")); 121243830Sdim unsigned CurPrefix = 0; 122243830Sdim for (unsigned i = 0, e = Opts.size(); i != e; ++i) { 123243830Sdim const Record &R = *Opts[i]; 124243830Sdim std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes"); 125243830Sdim PrefixKeyT prfkey(prf.begin(), prf.end()); 126243830Sdim unsigned NewPrefix = CurPrefix + 1; 127243830Sdim if (Prefixes.insert(std::make_pair(prfkey, (Twine("prefix_") + 128243830Sdim Twine(NewPrefix)).str())).second) 129243830Sdim CurPrefix = NewPrefix; 130243830Sdim } 131243830Sdim 132243830Sdim OS << "#ifndef PREFIX\n"; 133243830Sdim OS << "#error \"Define PREFIX prior to including this file!\"\n"; 134243830Sdim OS << "#endif\n\n"; 135243830Sdim 136243830Sdim // Dump prefixes. 137243830Sdim OS << "/////////\n"; 138243830Sdim OS << "// Prefixes\n\n"; 139243830Sdim OS << "#define COMMA ,\n"; 140243830Sdim for (PrefixesT::const_iterator I = Prefixes.begin(), E = Prefixes.end(); 141243830Sdim I != E; ++I) { 142243830Sdim OS << "PREFIX("; 143243830Sdim 144243830Sdim // Prefix name. 145243830Sdim OS << I->second; 146243830Sdim 147243830Sdim // Prefix values. 148243830Sdim OS << ", {"; 149243830Sdim for (PrefixKeyT::const_iterator PI = I->first.begin(), 150243830Sdim PE = I->first.end(); PI != PE; ++PI) { 151243830Sdim OS << "\"" << *PI << "\" COMMA "; 152243830Sdim } 153243830Sdim OS << "0})\n"; 154243830Sdim } 155243830Sdim OS << "#undef COMMA\n"; 156243830Sdim OS << "\n"; 157243830Sdim 158226586Sdim OS << "#ifndef OPTION\n"; 159226586Sdim OS << "#error \"Define OPTION prior to including this file!\"\n"; 160226586Sdim OS << "#endif\n\n"; 161226586Sdim 162226586Sdim OS << "/////////\n"; 163226586Sdim OS << "// Groups\n\n"; 164226586Sdim for (unsigned i = 0, e = Groups.size(); i != e; ++i) { 165226586Sdim const Record &R = *Groups[i]; 166226586Sdim 167226586Sdim // Start a single option entry. 168226586Sdim OS << "OPTION("; 169226586Sdim 170243830Sdim // The option prefix; 171243830Sdim OS << "0"; 172243830Sdim 173226586Sdim // The option string. 174243830Sdim OS << ", \"" << R.getValueAsString("Name") << '"'; 175226586Sdim 176226586Sdim // The option identifier name. 177226586Sdim OS << ", "<< getOptionName(R); 178226586Sdim 179226586Sdim // The option kind. 180226586Sdim OS << ", Group"; 181226586Sdim 182226586Sdim // The containing option group (if any). 183226586Sdim OS << ", "; 184243830Sdim if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) 185226586Sdim OS << getOptionName(*DI->getDef()); 186226586Sdim else 187226586Sdim OS << "INVALID"; 188226586Sdim 189226586Sdim // The other option arguments (unused for groups). 190226586Sdim OS << ", INVALID, 0, 0"; 191226586Sdim 192226586Sdim // The option help text. 193243830Sdim if (!isa<UnsetInit>(R.getValueInit("HelpText"))) { 194226586Sdim OS << ",\n"; 195226586Sdim OS << " "; 196226586Sdim write_cstring(OS, R.getValueAsString("HelpText")); 197226586Sdim } else 198226586Sdim OS << ", 0"; 199226586Sdim 200226586Sdim // The option meta-variable name (unused). 201226586Sdim OS << ", 0)\n"; 202226586Sdim } 203226586Sdim OS << "\n"; 204226586Sdim 205226586Sdim OS << "//////////\n"; 206226586Sdim OS << "// Options\n\n"; 207226586Sdim for (unsigned i = 0, e = Opts.size(); i != e; ++i) { 208226586Sdim const Record &R = *Opts[i]; 209226586Sdim 210226586Sdim // Start a single option entry. 211226586Sdim OS << "OPTION("; 212226586Sdim 213243830Sdim // The option prefix; 214243830Sdim std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes"); 215243830Sdim OS << Prefixes[PrefixKeyT(prf.begin(), prf.end())] << ", "; 216243830Sdim 217226586Sdim // The option string. 218226586Sdim write_cstring(OS, R.getValueAsString("Name")); 219226586Sdim 220226586Sdim // The option identifier name. 221226586Sdim OS << ", "<< getOptionName(R); 222226586Sdim 223226586Sdim // The option kind. 224226586Sdim OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name"); 225226586Sdim 226226586Sdim // The containing option group (if any). 227226586Sdim OS << ", "; 228243830Sdim if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) 229226586Sdim OS << getOptionName(*DI->getDef()); 230226586Sdim else 231226586Sdim OS << "INVALID"; 232226586Sdim 233226586Sdim // The option alias (if any). 234226586Sdim OS << ", "; 235243830Sdim if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias"))) 236226586Sdim OS << getOptionName(*DI->getDef()); 237226586Sdim else 238226586Sdim OS << "INVALID"; 239226586Sdim 240226586Sdim // The option flags. 241226586Sdim const ListInit *LI = R.getValueAsListInit("Flags"); 242226586Sdim if (LI->empty()) { 243226586Sdim OS << ", 0"; 244226586Sdim } else { 245226586Sdim OS << ", "; 246226586Sdim for (unsigned i = 0, e = LI->size(); i != e; ++i) { 247226586Sdim if (i) 248226586Sdim OS << " | "; 249243830Sdim OS << cast<DefInit>(LI->getElement(i))->getDef()->getName(); 250226586Sdim } 251226586Sdim } 252226586Sdim 253226586Sdim // The option parameter field. 254226586Sdim OS << ", " << R.getValueAsInt("NumArgs"); 255226586Sdim 256226586Sdim // The option help text. 257243830Sdim if (!isa<UnsetInit>(R.getValueInit("HelpText"))) { 258226586Sdim OS << ",\n"; 259226586Sdim OS << " "; 260226586Sdim write_cstring(OS, R.getValueAsString("HelpText")); 261226586Sdim } else 262226586Sdim OS << ", 0"; 263226586Sdim 264226586Sdim // The option meta-variable name. 265226586Sdim OS << ", "; 266243830Sdim if (!isa<UnsetInit>(R.getValueInit("MetaVarName"))) 267226586Sdim write_cstring(OS, R.getValueAsString("MetaVarName")); 268226586Sdim else 269226586Sdim OS << "0"; 270226586Sdim 271226586Sdim OS << ")\n"; 272226586Sdim } 273226586Sdim } 274226586Sdim} 275239462Sdim} // end namespace clang 276