1//===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "llvm/ADT/STLExtras.h" 11#include "llvm/ADT/SmallString.h" 12#include "llvm/ADT/Twine.h" 13#include "llvm/TableGen/Error.h" 14#include "llvm/TableGen/Record.h" 15#include "llvm/TableGen/TableGenBackend.h" 16#include <map> 17 18using namespace llvm; 19 20static int StrCmpOptionName(const char *A, const char *B) { 21 char a = *A, b = *B; 22 while (a == b) { 23 if (a == '\0') 24 return 0; 25 26 a = *++A; 27 b = *++B; 28 } 29 30 if (a == '\0') // A is a prefix of B. 31 return 1; 32 if (b == '\0') // B is a prefix of A. 33 return -1; 34 35 // Otherwise lexicographic. 36 return (a < b) ? -1 : 1; 37} 38 39static int CompareOptionRecords(const void *Av, const void *Bv) { 40 const Record *A = *(const Record*const*) Av; 41 const Record *B = *(const Record*const*) Bv; 42 43 // Sentinel options precede all others and are only ordered by precedence. 44 bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel"); 45 bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel"); 46 if (ASent != BSent) 47 return ASent ? -1 : 1; 48 49 // Compare options by name, unless they are sentinels. 50 if (!ASent) 51 if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(), 52 B->getValueAsString("Name").c_str())) 53 return Cmp; 54 55 if (!ASent) { 56 std::vector<std::string> APrefixes = A->getValueAsListOfStrings("Prefixes"); 57 std::vector<std::string> BPrefixes = B->getValueAsListOfStrings("Prefixes"); 58 59 for (std::vector<std::string>::const_iterator APre = APrefixes.begin(), 60 AEPre = APrefixes.end(), 61 BPre = BPrefixes.begin(), 62 BEPre = BPrefixes.end(); 63 APre != AEPre && 64 BPre != BEPre; 65 ++APre, ++BPre) { 66 if (int Cmp = StrCmpOptionName(APre->c_str(), BPre->c_str())) 67 return Cmp; 68 } 69 } 70 71 // Then by the kind precedence; 72 int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence"); 73 int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence"); 74 if (APrec == BPrec && 75 A->getValueAsListOfStrings("Prefixes") == 76 B->getValueAsListOfStrings("Prefixes")) { 77 PrintError(A->getLoc(), Twine("Option is equivilent to")); 78 PrintError(B->getLoc(), Twine("Other defined here")); 79 PrintFatalError("Equivalent Options found."); 80 } 81 return APrec < BPrec ? -1 : 1; 82} 83 84static const std::string getOptionName(const Record &R) { 85 // Use the record name unless EnumName is defined. 86 if (isa<UnsetInit>(R.getValueInit("EnumName"))) 87 return R.getName(); 88 89 return R.getValueAsString("EnumName"); 90} 91 92static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) { 93 OS << '"'; 94 OS.write_escaped(Str); 95 OS << '"'; 96 return OS; 97} 98 99/// OptParserEmitter - This tablegen backend takes an input .td file 100/// describing a list of options and emits a data structure for parsing and 101/// working with those options when given an input command line. 102namespace clang { 103void EmitOptParser(RecordKeeper &Records, raw_ostream &OS, bool GenDefs) { 104 // Get the option groups and options. 105 const std::vector<Record*> &Groups = 106 Records.getAllDerivedDefinitions("OptionGroup"); 107 std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option"); 108 109 if (GenDefs) 110 emitSourceFileHeader("Option Parsing Definitions", OS); 111 else 112 emitSourceFileHeader("Option Parsing Table", OS); 113 114 array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords); 115 if (GenDefs) { 116 // Generate prefix groups. 117 typedef SmallVector<SmallString<2>, 2> PrefixKeyT; 118 typedef std::map<PrefixKeyT, std::string> PrefixesT; 119 PrefixesT Prefixes; 120 Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0")); 121 unsigned CurPrefix = 0; 122 for (unsigned i = 0, e = Opts.size(); i != e; ++i) { 123 const Record &R = *Opts[i]; 124 std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes"); 125 PrefixKeyT prfkey(prf.begin(), prf.end()); 126 unsigned NewPrefix = CurPrefix + 1; 127 if (Prefixes.insert(std::make_pair(prfkey, (Twine("prefix_") + 128 Twine(NewPrefix)).str())).second) 129 CurPrefix = NewPrefix; 130 } 131 132 OS << "#ifndef PREFIX\n"; 133 OS << "#error \"Define PREFIX prior to including this file!\"\n"; 134 OS << "#endif\n\n"; 135 136 // Dump prefixes. 137 OS << "/////////\n"; 138 OS << "// Prefixes\n\n"; 139 OS << "#define COMMA ,\n"; 140 for (PrefixesT::const_iterator I = Prefixes.begin(), E = Prefixes.end(); 141 I != E; ++I) { 142 OS << "PREFIX("; 143 144 // Prefix name. 145 OS << I->second; 146 147 // Prefix values. 148 OS << ", {"; 149 for (PrefixKeyT::const_iterator PI = I->first.begin(), 150 PE = I->first.end(); PI != PE; ++PI) { 151 OS << "\"" << *PI << "\" COMMA "; 152 } 153 OS << "0})\n"; 154 } 155 OS << "#undef COMMA\n"; 156 OS << "\n"; 157 158 OS << "#ifndef OPTION\n"; 159 OS << "#error \"Define OPTION prior to including this file!\"\n"; 160 OS << "#endif\n\n"; 161 162 OS << "/////////\n"; 163 OS << "// Groups\n\n"; 164 for (unsigned i = 0, e = Groups.size(); i != e; ++i) { 165 const Record &R = *Groups[i]; 166 167 // Start a single option entry. 168 OS << "OPTION("; 169 170 // The option prefix; 171 OS << "0"; 172 173 // The option string. 174 OS << ", \"" << R.getValueAsString("Name") << '"'; 175 176 // The option identifier name. 177 OS << ", "<< getOptionName(R); 178 179 // The option kind. 180 OS << ", Group"; 181 182 // The containing option group (if any). 183 OS << ", "; 184 if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) 185 OS << getOptionName(*DI->getDef()); 186 else 187 OS << "INVALID"; 188 189 // The other option arguments (unused for groups). 190 OS << ", INVALID, 0, 0"; 191 192 // The option help text. 193 if (!isa<UnsetInit>(R.getValueInit("HelpText"))) { 194 OS << ",\n"; 195 OS << " "; 196 write_cstring(OS, R.getValueAsString("HelpText")); 197 } else 198 OS << ", 0"; 199 200 // The option meta-variable name (unused). 201 OS << ", 0)\n"; 202 } 203 OS << "\n"; 204 205 OS << "//////////\n"; 206 OS << "// Options\n\n"; 207 for (unsigned i = 0, e = Opts.size(); i != e; ++i) { 208 const Record &R = *Opts[i]; 209 210 // Start a single option entry. 211 OS << "OPTION("; 212 213 // The option prefix; 214 std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes"); 215 OS << Prefixes[PrefixKeyT(prf.begin(), prf.end())] << ", "; 216 217 // The option string. 218 write_cstring(OS, R.getValueAsString("Name")); 219 220 // The option identifier name. 221 OS << ", "<< getOptionName(R); 222 223 // The option kind. 224 OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name"); 225 226 // The containing option group (if any). 227 OS << ", "; 228 if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) 229 OS << getOptionName(*DI->getDef()); 230 else 231 OS << "INVALID"; 232 233 // The option alias (if any). 234 OS << ", "; 235 if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias"))) 236 OS << getOptionName(*DI->getDef()); 237 else 238 OS << "INVALID"; 239 240 // The option flags. 241 const ListInit *LI = R.getValueAsListInit("Flags"); 242 if (LI->empty()) { 243 OS << ", 0"; 244 } else { 245 OS << ", "; 246 for (unsigned i = 0, e = LI->size(); i != e; ++i) { 247 if (i) 248 OS << " | "; 249 OS << cast<DefInit>(LI->getElement(i))->getDef()->getName(); 250 } 251 } 252 253 // The option parameter field. 254 OS << ", " << R.getValueAsInt("NumArgs"); 255 256 // The option help text. 257 if (!isa<UnsetInit>(R.getValueInit("HelpText"))) { 258 OS << ",\n"; 259 OS << " "; 260 write_cstring(OS, R.getValueAsString("HelpText")); 261 } else 262 OS << ", 0"; 263 264 // The option meta-variable name. 265 OS << ", "; 266 if (!isa<UnsetInit>(R.getValueInit("MetaVarName"))) 267 write_cstring(OS, R.getValueAsString("MetaVarName")); 268 else 269 OS << "0"; 270 271 OS << ")\n"; 272 } 273 } 274} 275} // end namespace clang 276