summaryrefslogtreecommitdiff
path: root/tools/llvmc/ConfigData.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/llvmc/ConfigData.cpp')
-rw-r--r--tools/llvmc/ConfigData.cpp601
1 files changed, 246 insertions, 355 deletions
diff --git a/tools/llvmc/ConfigData.cpp b/tools/llvmc/ConfigData.cpp
index 94949c405d..d2e788bf12 100644
--- a/tools/llvmc/ConfigData.cpp
+++ b/tools/llvmc/ConfigData.cpp
@@ -13,391 +13,282 @@
//===------------------------------------------------------------------------===
#include "ConfigData.h"
+#include "ConfigLexer.h"
#include "CompilerDriver.h"
#include "Support/StringExtras.h"
#include <iostream>
+#include <fstream>
using namespace llvm;
-namespace {
+extern int ::Configlex();
-// This array of strings provides the input for ".ll" files (LLVM Assembly)
-// to the configuration file parser. This data is just "built-in" to
-// llvmc so it doesn't have to be read from a configuration file.
-static const char* LL_Data[] = {
- "lang.name=LLVM Assembly",
- "lang.translator.preprocesses=false",
- "lang.translator.optimizes=No",
- "lang.translator.groks_dash_O=No",
- "lang.preprocessor.needed=0",
- "preprocessor.prog=",
- "preprocessor.args=",
- "translator.prog=llvm-as",
- "translator.args=@in@ -o @out@",
- "optimizer.prog=opt",
- "optimizer.args=@in@ -o @out@",
- "assembler.prog=llc",
- "assembler.args=@in@ -o @out@",
- "linker.prog=llvm-link",
- "linker.args=@in@ -o @out@"
-};
-
-// This array of strings provides the input for ".st" files (Stacker).
-static const char* ST_Data[] = {
- "lang.name=Stacker",
- "lang.translator.preprocesses=false",
- "lang.translator.optimizes=true",
- "lang.translator.groks_dash_O=0",
- "lang.preprocessor.needed=0",
- "preprocessor.prog=cp",
- "preprocessor.args=@in@ @out@",
- "translator.prog=stkrc",
- "translator.args=@in@ -o @out@ -S 2048",
- "optimizer.prog=opt",
- "optimizer.args=@in@ -o @out@",
- "assembler.prog=llc",
- "assembler.args=@in@ -o @out@",
- "linker.prog=llvm-link",
- "linker.args=@in@ -o @out@"
-};
-
-class InputProvider {
- public:
- virtual bool getLine(std::string& line) = 0;
- virtual void error(const std::string& msg) = 0;
- virtual bool errorOccurred() = 0;
-};
-
-class StaticInputProvider : public InputProvider {
- public:
- StaticInputProvider(const char *data[], size_t count,
- const std::string& nam) {
- TheData = data;
- limit = count;
- where = 0;
- name = nam;
- errCount = 0;
- }
- virtual ~StaticInputProvider() {}
- virtual bool getLine(std::string& line) {
- if ( where >= limit ) return false;
- line = TheData[where++];
- return true;
- }
+namespace llvm {
+ ConfigLexerInfo ConfigLexerData;
+ InputProvider* ConfigLexerInput = 0;
+ unsigned ConfigLexerLine = 1;
- virtual void error(const std::string& msg) {
- std::cerr << name << ":" << where << ": Error: " << msg << "\n";
- errCount++;
+ InputProvider::~InputProvider() {}
+ void InputProvider::error(const std::string& msg) {
+ std::cerr << name << ":" << ConfigLexerLine << ": Error: " << msg << "\n";
+ errCount++;
+ }
+
+ void InputProvider::checkErrors() {
+ if (errCount > 0) {
+ std::cerr << name << " had " << errCount << " errors. Terminating.\n";
+ exit(errCount);
}
+ }
- virtual bool errorOccurred() { return errCount > 0; };
+}
- private:
- const char**TheData;
- size_t limit;
- size_t where;
- std::string name;
- size_t errCount;
-};
+namespace {
-inline bool recognize(const char*& p, const char*token) {
- while (*p == *token && *token != '\0')
- ++token, p++;
- return *token == '\0' && ((*p == '\0') || ( *p == '.' ) || (*p == '='));
-}
+ class FileInputProvider : public InputProvider {
+ public:
+ FileInputProvider(const std::string & fname)
+ : InputProvider(fname)
+ , F(fname.c_str()) {
+ ConfigLexerInput = this;
+ }
+ virtual ~FileInputProvider() { F.close(); ConfigLexerInput = 0; }
+ virtual unsigned read(char *buffer, unsigned max_size) {
+ if (F.good()) {
+ F.read(buffer,max_size);
+ if ( F.gcount() ) return F.gcount() - 1;
+ }
+ return 0;
+ }
+
+ bool okay() { return F.good(); }
+ private:
+ std::ifstream F;
+ };
+
+ struct ParseContext
+ {
+ int token;
+ InputProvider* provider;
+ CompilerDriver::ConfigData* confDat;
+ CompilerDriver::Action* action;
+
+ int next() { return token = Configlex(); }
+
+ bool next_is_real() {
+ token = Configlex();
+ return (token != EOLTOK) && (token != ERRORTOK) && (token != 0);
+ }
-inline bool getBoolean(const std::string& value) {
- switch (value[0]) {
- case 't':
- case 'T':
- case '1':
- case 'y':
- case 'Y':
- return true;
- default :
- return false;
- }
- return false;
-}
+ void eatLineRemnant() {
+ while (next_is_real()) ;
+ }
-inline void skipWhitespace( size_t& pos, const std::string& line ) {
- while (pos < line.size() && (
- line[pos] == ' ' || // Space
- line[pos] == '\t' || // Horizontal Tab
- line[pos] == '\n' || // New Line
- line[pos] == '\v' || // Vertical Tab
- line[pos] == '\f' || // Form Feed
- line[pos] == '\r') // Carriate Return
- )
- pos++;
-}
+ void error(const std::string& msg, bool skip = true) {
+ provider->error(msg);
+ if (skip)
+ eatLineRemnant();
+ }
-inline void parseArgs(CompilerDriver::Action& pat,
- const std::string& value,
- InputProvider& provider )
-{
- const char* p = value.c_str();
- const char* argStart = p;
- while (*p != '\0') {
- switch (*p) {
- case ' ':
- if (argStart != p)
- pat.args.push_back(std::string(argStart, p-argStart));
- argStart = ++p;
- break;
- case '@' :
- {
- if (argStart != p)
- pat.args.push_back(std::string(argStart,p-argStart));
- const char* token = ++p;
- while (*p != '@' && *p != 0)
- p++;
- if ( *p != '@' ) {
- provider.error("Unterminated substitution token");
- return;
- } else {
- p++;
- bool legal = false;
- switch (token[0]) {
- case 'i':
- if (token[1] == 'n' && token[2] == '@' ) {
- pat.inputAt = pat.args.size();
- pat.args.push_back("in");
- legal = true;
- argStart = p;
- }
- break;
- case 'o':
- if (token[1] == 'u' && token[2] == 't' && token[3] == '@') {
- pat.outputAt = pat.args.size();
- pat.args.push_back("out");
- legal = true;
- argStart = p;
- }
- break;
- default:
- break;
- }
- if (!legal) {
- provider.error("Invalid substitution token");
- return;
- }
+ std::string parseName() {
+ std::string result;
+ if (next() == EQUALS) {
+ while (next_is_real()) {
+ switch (token ) {
+ case STRING :
+ case OPTION :
+ result += ConfigLexerData.StringVal + " ";
+ break;
+ default:
+ error("Invalid name");
+ break;
}
}
- break;
- default :
- p++;
- break;
+ if (result.empty())
+ error("Name exepected");
+ else
+ result.erase(result.size()-1,1);
+ } else
+ error("= expected");
+ return result;
}
- }
-}
-CompilerDriver::ConfigData*
-ParseConfigData(InputProvider& provider) {
- std::string line;
- CompilerDriver::ConfigData data;
- while ( provider.getLine(line) ) {
- // Check line length first
- size_t lineLen = line.size();
- if (lineLen > 4096)
- provider.error("length of input line (" + utostr(lineLen) +
- ") is too long");
-
- // First, skip whitespace
- size_t stPos = 0;
- skipWhitespace(stPos, line);
-
- // See if there's a hash mark. It and everything after it is
- // ignored so lets delete that now.
- size_t hashPos = line.find('#');
- if (hashPos != std::string::npos)
- line.erase(hashPos);
-
- // Make sure we have something left to parse
- if (line.size() == 0)
- continue; // ignore full-line comment or whitespace line
-
- // Find the equals sign
- size_t eqPos = line.find('=');
- if (eqPos == std::string::npos)
- provider.error("Configuration directive is missing an =");
-
- // extract the item name
- std::string name(line, stPos, eqPos-stPos);
-
- // directives without names are illegal
- if (name.empty())
- provider.error("Configuration directive name is empty");
-
- // Skip whitespace in the value
- size_t valPos = eqPos + 1;
- skipWhitespace(valPos, line);
-
- // Skip white space at end of value
- size_t endPos = line.length() - 1;
- while (line[endPos] == ' ')
- endPos--;
-
- // extract the item value
- std::string value(line, valPos, endPos-valPos+1);
-
- // Get the configuration item as a char pointer
- const char*p = name.c_str();
-
- // Indicate we haven't found an invalid item yet.
- bool invalidItem = false;
-
- // Parse the contents by examining first character and
- // using the recognize function strategically
- switch (*p++) {
- case 'l' :
- // could it be "lang."
- if (*p == 'a') { // "lang." ?
- if (recognize(p,"ang")) {
- p++;
- switch (*p++) {
- case 'n':
- if (recognize(p,"ame"))
- data.langName = value;
- else
- invalidItem = true;
- break;
- case 't':
- if (recognize(p,"ranslator")) {
- p++;
- if (recognize(p,"preprocesses"))
- data.TranslatorPreprocesses = getBoolean(value);
- else if (recognize(p, "optimizes"))
- data.TranslatorOptimizes = getBoolean(value);
- else if (recognize(p, "groks_dash_O"))
- data.TranslatorGroksDashO = getBoolean(value);
- else
- invalidItem = true;
- }
- else
- invalidItem = true;
- break;
- case 'p':
- if (recognize(p,"reprocessor")) {
- p++;
- if (recognize(p,"needed")) {
- data.PreprocessorNeeded = getBoolean(value);
- } else
- invalidItem = true;
- }
- else
- invalidItem = true;
- break;
-
- default:
- invalidItem = true;
- break;
- }
- }
- } else if (*p == 'i') { // "linker." ?
- if (recognize(p,"inker")) {
- p++;
- if (recognize(p,"prog"))
- data.Linker.program = value;
- else if (recognize(p,"args"))
- parseArgs(data.Linker,value,provider);
- else
- invalidItem = true;
- }
- else
- invalidItem = true;
- } else {
- invalidItem = true;
+ bool parseBoolean() {
+ bool result = true;
+ if (next() == EQUALS) {
+ if (next() == FALSETOK) {
+ result = false;
+ } else if (token != TRUETOK) {
+ error("Expecting boolean value");
+ return false;
}
- break;
-
- case 'p' :
- if (*p == 'r') { // "preprocessor." ?
- if (recognize(p, "reprocessor")) {
- p++;
- if (recognize(p,"prog"))
- data.PreProcessor.program = value;
- else if (recognize(p,"args"))
- parseArgs(data.PreProcessor,value,provider);
- else
- invalidItem = true;
- } else
- invalidItem = true;
- } else {
- invalidItem = true;
+ if (next() != EOLTOK && token != 0) {
+ error("Extraneous tokens after boolean");
}
- break;
-
- case 't' :
- if (*p == 'r') { // "translator." ?
- if (recognize(p, "ranslator")) {
- p++;
- if (recognize(p,"prog"))
- data.Translator.program = value;
- else if (recognize(p,"args"))
- parseArgs(data.Translator,value,provider);
- else
- invalidItem = true;
- } else
- invalidItem = true;
- } else {
- invalidItem = true;
- }
- break;
-
- case 'o' :
- if (*p == 'p') { // "optimizer." ?
- if (recognize(p, "ptimizer")) {
- p++;
- if (recognize(p,"prog"))
- data.Optimizer.program = value;
- else if (recognize(p,"args"))
- parseArgs(data.Optimizer,value,provider);
- else
- invalidItem = true;
- } else
- invalidItem = true;
- } else {
- invalidItem = true;
+ }
+ else
+ error("Expecting '='");
+ return result;
+ }
+
+ void parseLang() {
+ if ( next() == NAME ) {
+ confDat->langName = parseName();
+ } else if (token == TRANSLATOR) {
+ switch (next()) {
+ case PREPROCESSES:
+ confDat->TranslatorPreprocesses = parseBoolean();
+ break;
+ case OPTIMIZES:
+ confDat->TranslatorOptimizes = parseBoolean();
+ break;
+ case GROKS_DASH_O:
+ confDat->TranslatorGroksDashO = parseBoolean();
+ break;
+ default:
+ error("Invalid lang.translator identifier");
+ break;
}
- break;
- case 'a' :
- if (*p == 's') { // "assembler." ?
- if (recognize(p, "ssembler")) {
- p++;
- if (recognize(p,"prog"))
- data.Assembler.program = value;
- else if (recognize(p,"args"))
- parseArgs(data.Assembler,value,provider);
- else
- invalidItem = true;
- } else
- invalidItem = true;
+ }
+ else if (token == PREPROCESSOR) {
+ if (next() == NEEDED)
+ confDat->PreprocessorNeeded = parseBoolean();
+ }
+ else {
+ error("Expecting valid identifier after 'lang.'");
+ }
+ }
+
+ void parseCommand(CompilerDriver::Action& action) {
+ if (next() == EQUALS) {
+ next();
+ if (token == EOLTOK) {
+ // no value (valid)
+ action.program.clear();
+ action.args.clear();
+ action.inputAt = 0;
+ action.outputAt = 0;
} else {
- invalidItem = true;
+ if (token == STRING || token == OPTION) {
+ action.program = ConfigLexerData.StringVal;
+ } else {
+ error("Expecting a program name");
+ }
+ while (next_is_real()) {
+ if (token == STRING || token == OPTION)
+ action.args.push_back(ConfigLexerData.StringVal);
+ else if (token == IN_SUBST) {
+ action.inputAt = action.args.size();
+ action.args.push_back("in");
+ } else if (token == OUT_SUBST) {
+ action.outputAt = action.args.size();
+ action.args.push_back("out");
+ } else
+ error("Expecting a program argument", false);
+ }
}
- break;
+ }
+ }
+
+ void parsePreProcessor() {
+ if (next() != COMMAND) {
+ error("Expecting 'command'");
+ return;
+ }
+ parseCommand(confDat->PreProcessor);
+ }
+
+ void parseTranslator() {
+ if (next() != COMMAND) {
+ error("Expecting 'command'");
+ return;
+ }
+ parseCommand(confDat->Translator);
+ }
+
+ void parseOptimizer() {
+ if (next() != COMMAND) {
+ error("Expecting 'command'");
+ return;
+ }
+ parseCommand(confDat->Optimizer);
+ }
+
+ void parseAssembler() {
+ if (next() != COMMAND) {
+ error("Expecting 'command'");
+ return;
+ }
+ parseCommand(confDat->Assembler);
+ }
+
+ void parseLinker() {
+ if (next() != COMMAND) {
+ error("Expecting 'command'");
+ return;
+ }
+ parseCommand(confDat->Linker);
+ }
+
+ void parseAssignment() {
+ switch (token) {
+ case LANG: return parseLang();
+ case PREPROCESSOR: return parsePreProcessor();
+ case TRANSLATOR: return parseTranslator();
+ case OPTIMIZER: return parseOptimizer();
+ case ASSEMBLER: return parseAssembler();
+ case LINKER: return parseLinker();
+ case EOLTOK: break; // just ignore
+ case ERRORTOK:
+ default:
+ error("Invalid top level configuration item identifier");
+ }
+ }
+
+ void parseFile() {
+ while ( next() != 0 ) {
+ parseAssignment();
+ }
+ provider->checkErrors();
}
- if (invalidItem)
- provider.error("Invalid configuration item: " + line.substr(stPos, eqPos-stPos));
+ };
+
+ void
+ ParseConfigData(InputProvider& provider, CompilerDriver::ConfigData& confDat) {
+ ParseContext ctxt;
+ ctxt.token = 0;
+ ctxt.provider = &provider;
+ ctxt.confDat = &confDat;
+ ctxt.action = 0;
+ ctxt.parseFile();
}
- return new CompilerDriver::ConfigData(data);
}
CompilerDriver::ConfigData*
-ReadConfigData(const std::string& ftype) {
- if ( ftype == "ll" ) {
- StaticInputProvider sip(LL_Data, sizeof(LL_Data)/sizeof(LL_Data[0]),
- "LLVM Assembly (internal)");
- return ParseConfigData(sip);
- } else if (ftype == "st") {
- StaticInputProvider sip(ST_Data, sizeof(ST_Data)/sizeof(ST_Data[0]),
- "Stacker (internal)");
- return ParseConfigData(sip);
+LLVMC_ConfigDataProvider::ReadConfigData(const std::string& ftype) {
+ CompilerDriver::ConfigData* result = 0;
+ if (configDir.empty()) {
+ FileInputProvider fip( std::string("/etc/llvm/") + ftype );
+ if (!fip.okay()) {
+ fip.error("Configuration for '" + ftype + "' is not available.");
+ fip.checkErrors();
+ }
+ else {
+ result = new CompilerDriver::ConfigData();
+ ParseConfigData(fip,*result);
+ }
+ } else {
+ FileInputProvider fip( configDir + "/" + ftype );
+ if (!fip.okay()) {
+ fip.error("Configuration for '" + ftype + "' is not available.");
+ fip.checkErrors();
+ }
+ else {
+ result = new CompilerDriver::ConfigData();
+ ParseConfigData(fip,*result);
+ }
}
- return 0;
-}
-
+ return result;
}
LLVMC_ConfigDataProvider::LLVMC_ConfigDataProvider()