OptParserEmitter.cpp revision 226586
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 10226586Sdim#include "OptParserEmitter.h" 11226586Sdim#include "llvm/TableGen/Record.h" 12226586Sdim#include "llvm/ADT/STLExtras.h" 13226586Sdimusing namespace llvm; 14226586Sdim 15226586Sdimstatic int StrCmpOptionName(const char *A, const char *B) { 16226586Sdim char a = *A, b = *B; 17226586Sdim while (a == b) { 18226586Sdim if (a == '\0') 19226586Sdim return 0; 20226586Sdim 21226586Sdim a = *++A; 22226586Sdim b = *++B; 23226586Sdim } 24226586Sdim 25226586Sdim if (a == '\0') // A is a prefix of B. 26226586Sdim return 1; 27226586Sdim if (b == '\0') // B is a prefix of A. 28226586Sdim return -1; 29226586Sdim 30226586Sdim // Otherwise lexicographic. 31226586Sdim return (a < b) ? -1 : 1; 32226586Sdim} 33226586Sdim 34226586Sdimstatic int CompareOptionRecords(const void *Av, const void *Bv) { 35226586Sdim const Record *A = *(Record**) Av; 36226586Sdim const Record *B = *(Record**) Bv; 37226586Sdim 38226586Sdim // Sentinel options precede all others and are only ordered by precedence. 39226586Sdim bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel"); 40226586Sdim bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel"); 41226586Sdim if (ASent != BSent) 42226586Sdim return ASent ? -1 : 1; 43226586Sdim 44226586Sdim // Compare options by name, unless they are sentinels. 45226586Sdim if (!ASent) 46226586Sdim if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(), 47226586Sdim B->getValueAsString("Name").c_str())) 48226586Sdim return Cmp; 49226586Sdim 50226586Sdim // Then by the kind precedence; 51226586Sdim int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence"); 52226586Sdim int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence"); 53226586Sdim assert(APrec != BPrec && "Options are equivalent!"); 54226586Sdim return APrec < BPrec ? -1 : 1; 55226586Sdim} 56226586Sdim 57226586Sdimstatic const std::string getOptionName(const Record &R) { 58226586Sdim // Use the record name unless EnumName is defined. 59226586Sdim if (dynamic_cast<UnsetInit*>(R.getValueInit("EnumName"))) 60226586Sdim return R.getName(); 61226586Sdim 62226586Sdim return R.getValueAsString("EnumName"); 63226586Sdim} 64226586Sdim 65226586Sdimstatic raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) { 66226586Sdim OS << '"'; 67226586Sdim OS.write_escaped(Str); 68226586Sdim OS << '"'; 69226586Sdim return OS; 70226586Sdim} 71226586Sdim 72226586Sdimvoid OptParserEmitter::run(raw_ostream &OS) { 73226586Sdim // Get the option groups and options. 74226586Sdim const std::vector<Record*> &Groups = 75226586Sdim Records.getAllDerivedDefinitions("OptionGroup"); 76226586Sdim std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option"); 77226586Sdim 78226586Sdim if (GenDefs) 79226586Sdim EmitSourceFileHeader("Option Parsing Definitions", OS); 80226586Sdim else 81226586Sdim EmitSourceFileHeader("Option Parsing Table", OS); 82226586Sdim 83226586Sdim array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords); 84226586Sdim if (GenDefs) { 85226586Sdim OS << "#ifndef OPTION\n"; 86226586Sdim OS << "#error \"Define OPTION prior to including this file!\"\n"; 87226586Sdim OS << "#endif\n\n"; 88226586Sdim 89226586Sdim OS << "/////////\n"; 90226586Sdim OS << "// Groups\n\n"; 91226586Sdim for (unsigned i = 0, e = Groups.size(); i != e; ++i) { 92226586Sdim const Record &R = *Groups[i]; 93226586Sdim 94226586Sdim // Start a single option entry. 95226586Sdim OS << "OPTION("; 96226586Sdim 97226586Sdim // The option string. 98226586Sdim OS << '"' << R.getValueAsString("Name") << '"'; 99226586Sdim 100226586Sdim // The option identifier name. 101226586Sdim OS << ", "<< getOptionName(R); 102226586Sdim 103226586Sdim // The option kind. 104226586Sdim OS << ", Group"; 105226586Sdim 106226586Sdim // The containing option group (if any). 107226586Sdim OS << ", "; 108226586Sdim if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group"))) 109226586Sdim OS << getOptionName(*DI->getDef()); 110226586Sdim else 111226586Sdim OS << "INVALID"; 112226586Sdim 113226586Sdim // The other option arguments (unused for groups). 114226586Sdim OS << ", INVALID, 0, 0"; 115226586Sdim 116226586Sdim // The option help text. 117226586Sdim if (!dynamic_cast<UnsetInit*>(R.getValueInit("HelpText"))) { 118226586Sdim OS << ",\n"; 119226586Sdim OS << " "; 120226586Sdim write_cstring(OS, R.getValueAsString("HelpText")); 121226586Sdim } else 122226586Sdim OS << ", 0"; 123226586Sdim 124226586Sdim // The option meta-variable name (unused). 125226586Sdim OS << ", 0)\n"; 126226586Sdim } 127226586Sdim OS << "\n"; 128226586Sdim 129226586Sdim OS << "//////////\n"; 130226586Sdim OS << "// Options\n\n"; 131226586Sdim for (unsigned i = 0, e = Opts.size(); i != e; ++i) { 132226586Sdim const Record &R = *Opts[i]; 133226586Sdim 134226586Sdim // Start a single option entry. 135226586Sdim OS << "OPTION("; 136226586Sdim 137226586Sdim // The option string. 138226586Sdim write_cstring(OS, R.getValueAsString("Name")); 139226586Sdim 140226586Sdim // The option identifier name. 141226586Sdim OS << ", "<< getOptionName(R); 142226586Sdim 143226586Sdim // The option kind. 144226586Sdim OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name"); 145226586Sdim 146226586Sdim // The containing option group (if any). 147226586Sdim OS << ", "; 148226586Sdim if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group"))) 149226586Sdim OS << getOptionName(*DI->getDef()); 150226586Sdim else 151226586Sdim OS << "INVALID"; 152226586Sdim 153226586Sdim // The option alias (if any). 154226586Sdim OS << ", "; 155226586Sdim if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Alias"))) 156226586Sdim OS << getOptionName(*DI->getDef()); 157226586Sdim else 158226586Sdim OS << "INVALID"; 159226586Sdim 160226586Sdim // The option flags. 161226586Sdim const ListInit *LI = R.getValueAsListInit("Flags"); 162226586Sdim if (LI->empty()) { 163226586Sdim OS << ", 0"; 164226586Sdim } else { 165226586Sdim OS << ", "; 166226586Sdim for (unsigned i = 0, e = LI->size(); i != e; ++i) { 167226586Sdim if (i) 168226586Sdim OS << " | "; 169226586Sdim OS << dynamic_cast<DefInit*>(LI->getElement(i))->getDef()->getName(); 170226586Sdim } 171226586Sdim } 172226586Sdim 173226586Sdim // The option parameter field. 174226586Sdim OS << ", " << R.getValueAsInt("NumArgs"); 175226586Sdim 176226586Sdim // The option help text. 177226586Sdim if (!dynamic_cast<UnsetInit*>(R.getValueInit("HelpText"))) { 178226586Sdim OS << ",\n"; 179226586Sdim OS << " "; 180226586Sdim write_cstring(OS, R.getValueAsString("HelpText")); 181226586Sdim } else 182226586Sdim OS << ", 0"; 183226586Sdim 184226586Sdim // The option meta-variable name. 185226586Sdim OS << ", "; 186226586Sdim if (!dynamic_cast<UnsetInit*>(R.getValueInit("MetaVarName"))) 187226586Sdim write_cstring(OS, R.getValueAsString("MetaVarName")); 188226586Sdim else 189226586Sdim OS << "0"; 190226586Sdim 191226586Sdim OS << ")\n"; 192226586Sdim } 193226586Sdim } 194226586Sdim} 195