X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=tools%2Fllvmc%2FConfiguration.cpp;h=a381d56e1cde2a0b4f112fc19c315ed0ccbbcb50;hb=c0e9bec9fc000584947045800239b3fb0f44bc84;hp=d2e788bf12b9bba6271e76792a2dbab515b4d7c3;hpb=68fb37ad67d59051585cb7245f802f5c753c074f;p=oota-llvm.git diff --git a/tools/llvmc/Configuration.cpp b/tools/llvmc/Configuration.cpp index d2e788bf12b..a381d56e1cd 100644 --- a/tools/llvmc/Configuration.cpp +++ b/tools/llvmc/Configuration.cpp @@ -1,4 +1,4 @@ -//===- ConfigData.cpp - Configuration Data Mgmt -----------------*- C++ -*-===// +//===- Configuration.cpp - Configuration Data Mgmt --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,25 +12,30 @@ // //===------------------------------------------------------------------------=== -#include "ConfigData.h" +#include "Configuration.h" #include "ConfigLexer.h" #include "CompilerDriver.h" +#include "Config/config.h" +#include "Support/CommandLine.h" #include "Support/StringExtras.h" #include #include using namespace llvm; -extern int ::Configlex(); +namespace sys { + // From CompilerDriver.cpp (for now) + extern bool FileReadable(const std::string& fname); +} namespace llvm { - ConfigLexerInfo ConfigLexerData; + ConfigLexerInfo ConfigLexerState; InputProvider* ConfigLexerInput = 0; - unsigned ConfigLexerLine = 1; InputProvider::~InputProvider() {} void InputProvider::error(const std::string& msg) { - std::cerr << name << ":" << ConfigLexerLine << ": Error: " << msg << "\n"; + std::cerr << name << ":" << ConfigLexerState.lineNum << ": Error: " << + msg << "\n"; errCount++; } @@ -66,17 +71,34 @@ namespace { std::ifstream F; }; - struct ParseContext + cl::opt DumpTokens("dump-tokens", cl::Optional, cl::Hidden, cl::init(false), + cl::desc("Dump lexical tokens (debug use only).")); + + struct Parser { - int token; + Parser() { + token = EOFTOK; + provider = 0; + confDat = 0; + ConfigLexerState.lineNum = 1; + ConfigLexerState.in_value = false; + ConfigLexerState.StringVal.clear(); + ConfigLexerState.IntegerVal = 0; + }; + + ConfigLexerTokens token; InputProvider* provider; CompilerDriver::ConfigData* confDat; - CompilerDriver::Action* action; - int next() { return token = Configlex(); } + int next() { + token = Configlex(); + if (DumpTokens) + std::cerr << token << "\n"; + return token; + } bool next_is_real() { - token = Configlex(); + next(); return (token != EOLTOK) && (token != ERRORTOK) && (token != 0); } @@ -97,7 +119,7 @@ namespace { switch (token ) { case STRING : case OPTION : - result += ConfigLexerData.StringVal + " "; + result += ConfigLexerState.StringVal + " "; break; default: error("Invalid name"); @@ -131,123 +153,230 @@ namespace { 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"); + bool parseSubstitution(CompilerDriver::StringVector& optList) { + switch (token) { + case IN_SUBST: optList.push_back("%in%"); break; + case OUT_SUBST: optList.push_back("%out%"); break; + case TIME_SUBST: optList.push_back("%time%"); break; + case STATS_SUBST: optList.push_back("%stats%"); break; + case OPT_SUBST: optList.push_back("%opt%"); break; + case TARGET_SUBST: optList.push_back("%target%"); break; + default: + return false; + } + return true; + } + + void parseOptionList(CompilerDriver::StringVector& optList ) { + if (next() == EQUALS) { + while (next_is_real()) { + if (token == STRING || token == OPTION) + optList.push_back(ConfigLexerState.StringVal); + else if (!parseSubstitution(optList)) { + error("Expecting a program argument or substitution", false); break; + } } - } - else if (token == PREPROCESSOR) { - if (next() == NEEDED) - confDat->PreprocessorNeeded = parseBoolean(); - } - else { - error("Expecting valid identifier after 'lang.'"); + } else + error("Expecting '='"); + } + + void parseLang() { + switch (next() ) { + case NAME: + confDat->langName = parseName(); + break; + case OPT1: + parseOptionList(confDat->opts[CompilerDriver::OPT_FAST_COMPILE]); + break; + case OPT2: + parseOptionList(confDat->opts[CompilerDriver::OPT_SIMPLE]); + break; + case OPT3: + parseOptionList(confDat->opts[CompilerDriver::OPT_AGGRESSIVE]); + break; + case OPT4: + parseOptionList(confDat->opts[CompilerDriver::OPT_LINK_TIME]); + break; + case OPT5: + parseOptionList( + confDat->opts[CompilerDriver::OPT_AGGRESSIVE_LINK_TIME]); + break; + default: + error("Expecting 'name' or 'optN' after 'lang.'"); + break; } } void parseCommand(CompilerDriver::Action& action) { if (next() == EQUALS) { - next(); - if (token == EOLTOK) { + if (next() == EOLTOK) { // no value (valid) action.program.clear(); action.args.clear(); - action.inputAt = 0; - action.outputAt = 0; } else { if (token == STRING || token == OPTION) { - action.program = ConfigLexerData.StringVal; + action.program = ConfigLexerState.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); + if (token == STRING || token == OPTION) { + action.args.push_back(ConfigLexerState.StringVal); + } else if (!parseSubstitution(action.args)) { + error("Expecting a program argument or substitution", false); + break; + } } } } } - void parsePreProcessor() { - if (next() != COMMAND) { - error("Expecting 'command'"); - return; + void parsePreprocessor() { + switch (next()) { + case COMMAND: + parseCommand(confDat->PreProcessor); + break; + case REQUIRED: + if (parseBoolean()) + confDat->PreProcessor.set(CompilerDriver::REQUIRED_FLAG); + else + confDat->PreProcessor.clear(CompilerDriver::REQUIRED_FLAG); + break; + default: + error("Expecting 'command' or 'required'"); + break; } - parseCommand(confDat->PreProcessor); } void parseTranslator() { - if (next() != COMMAND) { - error("Expecting 'command'"); - return; + switch (next()) { + case COMMAND: + parseCommand(confDat->Translator); + break; + case REQUIRED: + if (parseBoolean()) + confDat->Translator.set(CompilerDriver::REQUIRED_FLAG); + else + confDat->Translator.clear(CompilerDriver::REQUIRED_FLAG); + break; + case PREPROCESSES: + if (parseBoolean()) + confDat->Translator.set(CompilerDriver::PREPROCESSES_FLAG); + else + confDat->Translator.clear(CompilerDriver::PREPROCESSES_FLAG); + break; + case OPTIMIZES: + if (parseBoolean()) + confDat->Translator.set(CompilerDriver::OPTIMIZES_FLAG); + else + confDat->Translator.clear(CompilerDriver::OPTIMIZES_FLAG); + break; + case GROKS_DASH_O: + if (parseBoolean()) + confDat->Translator.set(CompilerDriver::GROKS_DASH_O_FLAG); + else + confDat->Translator.clear(CompilerDriver::GROKS_DASH_O_FLAG); + break; + case OUTPUT_IS_ASM: + if (parseBoolean()) + confDat->Translator.set(CompilerDriver::OUTPUT_IS_ASM_FLAG); + else + confDat->Translator.clear(CompilerDriver::OUTPUT_IS_ASM_FLAG); + break; + + default: + error("Expecting 'command', 'required', 'preprocesses', " + "'groks_dash_O' or 'optimizes'"); + break; } - parseCommand(confDat->Translator); } void parseOptimizer() { - if (next() != COMMAND) { - error("Expecting 'command'"); - return; + switch (next()) { + case COMMAND: + parseCommand(confDat->Optimizer); + break; + case PREPROCESSES: + if (parseBoolean()) + confDat->Optimizer.set(CompilerDriver::PREPROCESSES_FLAG); + else + confDat->Optimizer.clear(CompilerDriver::PREPROCESSES_FLAG); + break; + case TRANSLATES: + if (parseBoolean()) + confDat->Optimizer.set(CompilerDriver::TRANSLATES_FLAG); + else + confDat->Optimizer.clear(CompilerDriver::TRANSLATES_FLAG); + break; + case GROKS_DASH_O: + if (parseBoolean()) + confDat->Optimizer.set(CompilerDriver::GROKS_DASH_O_FLAG); + else + confDat->Optimizer.clear(CompilerDriver::GROKS_DASH_O_FLAG); + break; + case OUTPUT_IS_ASM: + if (parseBoolean()) + confDat->Translator.set(CompilerDriver::OUTPUT_IS_ASM_FLAG); + else + confDat->Translator.clear(CompilerDriver::OUTPUT_IS_ASM_FLAG); + break; + default: + error("Expecting 'command' or 'groks_dash_O'"); + break; } - parseCommand(confDat->Optimizer); } void parseAssembler() { - if (next() != COMMAND) { - error("Expecting 'command'"); - return; + switch(next()) { + case COMMAND: + parseCommand(confDat->Assembler); + break; + default: + error("Expecting 'command'"); + break; } - parseCommand(confDat->Assembler); } void parseLinker() { - if (next() != COMMAND) { - error("Expecting 'command'"); - return; + switch(next()) { + case COMMAND: + parseCommand(confDat->Linker); + break; + case GROKS_DASH_O: + if (parseBoolean()) + confDat->Linker.set(CompilerDriver::GROKS_DASH_O_FLAG); + else + confDat->Linker.clear(CompilerDriver::GROKS_DASH_O_FLAG); + break; + default: + error("Expecting 'command'"); + break; } - 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 LANG: parseLang(); break; + case PREPROCESSOR: parsePreprocessor(); break; + case TRANSLATOR: parseTranslator(); break; + case OPTIMIZER: parseOptimizer(); break; + case ASSEMBLER: parseAssembler(); break; + case LINKER: parseLinker(); break; case EOLTOK: break; // just ignore case ERRORTOK: default: - error("Invalid top level configuration item identifier"); + error("Invalid top level configuration item"); + break; } } void parseFile() { - while ( next() != 0 ) { - parseAssignment(); + while ( next() != EOFTOK ) { + if (token == ERRORTOK) + error("Invalid token"); + else if (token != EOLTOK) + parseAssignment(); } provider->checkErrors(); } @@ -255,39 +384,58 @@ namespace { void ParseConfigData(InputProvider& provider, CompilerDriver::ConfigData& confDat) { - ParseContext ctxt; - ctxt.token = 0; - ctxt.provider = &provider; - ctxt.confDat = &confDat; - ctxt.action = 0; - ctxt.parseFile(); + Parser p; + p.token = EOFTOK; + p.provider = &provider; + p.confDat = &confDat; + p.parseFile(); } } CompilerDriver::ConfigData* LLVMC_ConfigDataProvider::ReadConfigData(const std::string& ftype) { CompilerDriver::ConfigData* result = 0; + std::string dir_name; 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); + // Try the environment variable + const char* conf = getenv("LLVM_CONFIG_DIR"); + if (conf) { + dir_name = conf; + dir_name += "/"; + if (!::sys::FileReadable(dir_name + ftype)) + throw "Configuration file for '" + ftype + "' is not available."; + } else { + // Try the user's home directory + const char* home = getenv("HOME"); + if (home) { + dir_name = home; + dir_name += "/.llvm/etc/"; + if (!::sys::FileReadable(dir_name + ftype)) { + // Okay, try the LLVM installation directory + dir_name = LLVM_ETCDIR; + dir_name += "/"; + if (!::sys::FileReadable(dir_name + ftype)) { + // Okay, try the "standard" place + dir_name = "/etc/llvm/"; + if (!::sys::FileReadable(dir_name + ftype)) { + throw "Configuration file for '" + ftype + "' is not available."; + } + } + } + } } } 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); + dir_name = configDir + "/"; + if (!::sys::FileReadable(dir_name + ftype)) { + throw "Configuration file for '" + ftype + "' is not available."; } } + FileInputProvider fip( dir_name + ftype ); + if (!fip.okay()) { + throw "Configuration file for '" + ftype + "' is not available."; + } + result = new CompilerDriver::ConfigData(); + ParseConfigData(fip,*result); return result; }