blob: a09ba083f3e033cc13f47a836d735b676b6239af [file] [log] [blame]
Daniel Dunbar2d6a8fb2009-11-18 21:29:51 +00001//===- 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 "OptParserEmitter.h"
11#include "Record.h"
12#include "llvm/ADT/STLExtras.h"
13using namespace llvm;
14
15static int StrCmpOptionName(const char *A, const char *B) {
16 char a = *A, b = *B;
17 while (a == b) {
18 if (a == '\0')
19 return 0;
20
21 a = *++A;
22 b = *++B;
23 }
24
25 if (a == '\0') // A is a prefix of B.
26 return 1;
27 if (b == '\0') // B is a prefix of A.
28 return -1;
29
30 // Otherwise lexicographic.
31 return (a < b) ? -1 : 1;
32}
33
34static int CompareOptionRecords(const void *Av, const void *Bv) {
35 const Record *A = *(Record**) Av;
36 const Record *B = *(Record**) Bv;
37
38 // Compare options by name first.
39 if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(),
40 B->getValueAsString("Name").c_str()))
41 return Cmp;
42
43 // Then by the kind precedence;
44 int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence");
45 int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence");
46 assert(APrec != BPrec && "Options are equivalent!");
47 return APrec < BPrec ? -1 : 1;
48}
49
50static const std::string getOptionName(const Record &R) {
51 // Use the record name unless EnumName is defined.
52 if (dynamic_cast<UnsetInit*>(R.getValueInit("EnumName")))
53 return R.getName();
54
55 return R.getValueAsString("EnumName");
56}
57
58static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
59 OS << '"';
60 OS.write_escaped(Str);
61 OS << '"';
62 return OS;
63}
64
65void OptParserEmitter::run(raw_ostream &OS) {
66 // Get the option groups and options.
67 const std::vector<Record*> &Groups =
68 Records.getAllDerivedDefinitions("OptionGroup");
69 std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");
70
71 if (GenDefs) {
72 OS << "\
73//=== TableGen'erated File - Option Parsing Definitions ---------*- C++ -*-===//\n \
74//\n\
75// Option Parsing Definitions\n\
76//\n\
77// Automatically generated file, do not edit!\n\
78//\n\
79//===----------------------------------------------------------------------===//\n";
80 } else {
81 OS << "\
82//=== TableGen'erated File - Option Parsing Table ---------------*- C++ -*-===//\n \
83//\n\
84// Option Parsing Definitions\n\
85//\n\
86// Automatically generated file, do not edit!\n\
87//\n\
88//===----------------------------------------------------------------------===//\n";
89 }
90 OS << "\n";
91
92 array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
93 if (GenDefs) {
94 OS << "#ifndef OPTION\n";
95 OS << "#error \"Define OPTION prior to including this file!\"\n";
96 OS << "#endif\n\n";
97
98 OS << "/////////\n";
99 OS << "// Groups\n\n";
100 for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
101 const Record &R = *Groups[i];
102
103 // Start a single option entry.
104 OS << "OPTION(";
105
106 // The option string.
107 OS << '"' << R.getValueAsString("Name") << '"';
108
109 // The option identifier name.
110 OS << ", "<< getOptionName(R);
111
112 // The option kind.
113 OS << ", Group";
114
115 // The containing option group (if any).
116 OS << ", ";
117 if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
118 OS << getOptionName(*DI->getDef());
119 else
120 OS << "INVALID";
121
122 // The other option arguments (unused for groups).
123 OS << ", INVALID, 0, 0, 0, 0)\n";
124 }
125 OS << "\n";
126
127 OS << "//////////\n";
128 OS << "// Options\n\n";
129 for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
130 const Record &R = *Opts[i];
131
132 // Start a single option entry.
133 OS << "OPTION(";
134
135 // The option string.
136 write_cstring(OS, R.getValueAsString("Name"));
137
138 // The option identifier name.
139 OS << ", "<< getOptionName(R);
140
141 // The option kind.
142 OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
143
144 // The containing option group (if any).
145 OS << ", ";
146 if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
147 OS << getOptionName(*DI->getDef());
148 else
149 OS << "INVALID";
150
151 // The option alias (if any).
152 OS << ", ";
153 if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Alias")))
154 OS << getOptionName(*DI->getDef());
155 else
156 OS << "INVALID";
157
158 // The option flags.
159 const ListInit *LI = R.getValueAsListInit("Flags");
160 if (LI->empty()) {
161 OS << ", 0";
162 } else {
163 OS << ", ";
164 for (unsigned i = 0, e = LI->size(); i != e; ++i) {
165 if (i)
166 OS << " | ";
167 OS << dynamic_cast<DefInit*>(LI->getElement(i))->getDef()->getName();
168 }
169 }
170
171 // The option parameter field.
172 OS << ", " << R.getValueAsInt("NumArgs");
173
174 // The option help text.
175 if (!dynamic_cast<UnsetInit*>(R.getValueInit("HelpText"))) {
176 OS << ",\n";
177 OS << " ";
178 write_cstring(OS, R.getValueAsString("HelpText"));
179 } else
180 OS << ", 0";
181
182 // The option meta-variable name.
183 OS << ", ";
184 if (!dynamic_cast<UnsetInit*>(R.getValueInit("MetaVarName")))
185 write_cstring(OS, R.getValueAsString("MetaVarName"));
186 else
187 OS << "0";
188
189 OS << ")\n";
190 }
191 }
192}