//===- Configuration.cpp - Configuration Data Mgmt --------------*- C++ -*-===//
-//
+//
// The LLVM Compiler Infrastructure
//
-// This file was developed by Reid Spencer and is distributed under the
+// This file was developed by Reid Spencer and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
-//
+//
//===----------------------------------------------------------------------===//
//
// This file implements the parsing of configuration files for the LLVM Compiler
// Driver (llvmc).
//
-//===------------------------------------------------------------------------===
+//===----------------------------------------------------------------------===//
#include "Configuration.h"
#include "ConfigLexer.h"
InputProvider::~InputProvider() {}
void InputProvider::error(const std::string& msg) {
- std::cerr << name << ":" << ConfigLexerState.lineNum << ": Error: " <<
+ std::cerr << name << ":" << ConfigLexerState.lineNum << ": Error: " <<
msg << "\n";
errCount++;
}
class FileInputProvider : public InputProvider {
public:
FileInputProvider(const std::string & fname)
- : InputProvider(fname)
+ : InputProvider(fname)
, F(fname.c_str()) {
ConfigLexerInput = this;
}
std::ifstream F;
};
- cl::opt<bool> DumpTokens("dump-tokens", cl::Optional, cl::Hidden, cl::init(false),
- cl::desc("Dump lexical tokens (debug use only)."));
+ cl::opt<bool> DumpTokens("dump-tokens", cl::Optional, cl::Hidden,
+ cl::init(false), cl::desc("Dump lexical tokens (debug use only)."));
struct Parser
{
InputProvider* provider;
CompilerDriver::ConfigData* confDat;
- inline int next() {
+ inline int next() {
token = Configlex();
- if (DumpTokens)
+ if (DumpTokens)
std::cerr << token << "\n";
return token;
}
- inline bool next_is_real() {
+ inline bool next_is_real() {
next();
return (token != EOLTOK) && (token != ERRORTOK) && (token != 0);
}
eatLineRemnant();
}
+ bool parseCompleteItem(std::string& result) {
+ result.clear();
+ while (next_is_real()) {
+ switch (token ) {
+ case LLVMGCCDIR_SUBST:
+ case LLVMGCCARCH_SUBST:
+ case STRING :
+ case OPTION :
+ result += ConfigLexerState.StringVal;
+ break;
+ case SEPARATOR:
+ result += ".";
+ break;
+ case SPACE:
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+ }
+
std::string parseName() {
std::string result;
if (next() == EQUALS) {
- while (next_is_real()) {
- switch (token ) {
- case STRING :
- case OPTION :
- result += ConfigLexerState.StringVal + " ";
- break;
- default:
- error("Invalid name");
- break;
- }
- }
+ if (parseCompleteItem(result))
+ eatLineRemnant();
if (result.empty())
error("Name exepected");
- else
- result.erase(result.size()-1,1);
} else
- error("= expected");
+ error("Expecting '='");
return result;
}
bool parseBoolean() {
bool result = true;
if (next() == EQUALS) {
- if (next() == FALSETOK) {
+ if (next() == SPACE)
+ next();
+ if (token == FALSETOK) {
result = false;
} else if (token != TRUETOK) {
error("Expecting boolean value");
bool parseSubstitution(CompilerDriver::StringVector& optList) {
switch (token) {
case ARGS_SUBST: optList.push_back("%args%"); break;
+ case BINDIR_SUBST: optList.push_back("%bindir%"); break;
case DEFS_SUBST: optList.push_back("%defs%"); break;
- case FORCE_SUBST: optList.push_back("%force%"); break;
case IN_SUBST: optList.push_back("%in%"); break;
case INCLS_SUBST: optList.push_back("%incls%"); break;
+ case LIBDIR_SUBST: optList.push_back("%libdir%"); break;
case LIBS_SUBST: optList.push_back("%libs%"); break;
case OPT_SUBST: optList.push_back("%opt%"); break;
case OUT_SUBST: optList.push_back("%out%"); break;
case STATS_SUBST: optList.push_back("%stats%"); break;
case TIME_SUBST: optList.push_back("%time%"); break;
case VERBOSE_SUBST: optList.push_back("%verbose%"); break;
+ case FOPTS_SUBST: optList.push_back("%fOpts%"); break;
+ case MOPTS_SUBST: optList.push_back("%Mopts%"); break;
+ case WOPTS_SUBST: optList.push_back("%Wopts%"); break;
default:
return false;
}
}
void parseVersion() {
- if (next() == EQUALS) {
- while (next_is_real()) {
- if (token == STRING || token == OPTION)
- confDat->version = ConfigLexerState.StringVal;
- else
- error("Expecting a version string");
- }
- } else
+ if (next() != EQUALS)
error("Expecting '='");
+ while (next_is_real()) {
+ if (token == STRING || token == OPTION)
+ confDat->version = ConfigLexerState.StringVal;
+ else
+ error("Expecting a version string");
+ }
+ }
+
+ void parseLibs() {
+ if (next() != EQUALS)
+ error("Expecting '='");
+ std::string lib;
+ while (parseCompleteItem(lib)) {
+ if (!lib.empty()) {
+ confDat->libpaths.push_back(lib);
+ }
+ }
}
void parseLang() {
+ if (next() != SEPARATOR)
+ error("Expecting '.'");
switch (next() ) {
- case NAME:
- confDat->langName = parseName();
+ case LIBS:
+ parseLibs();
+ break;
+ case NAME:
+ confDat->langName = parseName();
break;
- case OPT1:
- parseOptionList(confDat->opts[CompilerDriver::OPT_FAST_COMPILE]);
+ case OPT1:
+ parseOptionList(confDat->opts[CompilerDriver::OPT_FAST_COMPILE]);
break;
- case OPT2:
- parseOptionList(confDat->opts[CompilerDriver::OPT_SIMPLE]);
+ case OPT2:
+ parseOptionList(confDat->opts[CompilerDriver::OPT_SIMPLE]);
break;
- case OPT3:
- parseOptionList(confDat->opts[CompilerDriver::OPT_AGGRESSIVE]);
+ case OPT3:
+ parseOptionList(confDat->opts[CompilerDriver::OPT_AGGRESSIVE]);
break;
- case OPT4:
- parseOptionList(confDat->opts[CompilerDriver::OPT_LINK_TIME]);
+ case OPT4:
+ parseOptionList(confDat->opts[CompilerDriver::OPT_LINK_TIME]);
break;
- case OPT5:
+ case OPT5:
parseOptionList(
confDat->opts[CompilerDriver::OPT_AGGRESSIVE_LINK_TIME]);
break;
- default:
- error("Expecting 'name' or 'optN' after 'lang.'");
+ default:
+ error("Expecting 'name' or 'optN' after 'lang.'");
break;
}
}
+ bool parseProgramName(std::string& str) {
+ str.clear();
+ do {
+ switch (token) {
+ case BINDIR_SUBST:
+ case LLVMGCC_SUBST:
+ case LLVMGXX_SUBST:
+ case LLVMCC1_SUBST:
+ case LLVMCC1PLUS_SUBST:
+ case OPTION:
+ case STRING:
+ case ARGS_SUBST:
+ case DEFS_SUBST:
+ case IN_SUBST:
+ case INCLS_SUBST:
+ case LIBS_SUBST:
+ case OPT_SUBST:
+ case OUT_SUBST:
+ case STATS_SUBST:
+ case TARGET_SUBST:
+ case TIME_SUBST:
+ case VERBOSE_SUBST:
+ case FOPTS_SUBST:
+ case MOPTS_SUBST:
+ case WOPTS_SUBST:
+ str += ConfigLexerState.StringVal;
+ break;
+ case SEPARATOR:
+ str += ".";
+ break;
+ case ASSEMBLY:
+ str += "assembly";
+ break;
+ case BYTECODE:
+ str += "bytecode";
+ break;
+ case TRUETOK:
+ str += "true";
+ break;
+ case FALSETOK:
+ str += "false";
+ break;
+ default:
+ break;
+ }
+ next();
+ } while (token != SPACE && token != EOFTOK && token != EOLTOK &&
+ token != ERRORTOK);
+ return !str.empty();
+ }
+
void parseCommand(CompilerDriver::Action& action) {
- if (next() == EQUALS) {
- if (next() == EOLTOK) {
+ if (next() != EQUALS)
+ error("Expecting '='");
+ switch (next()) {
+ case EOLTOK:
// no value (valid)
action.program.clear();
action.args.clear();
- } else {
- if (token == STRING || token == OPTION) {
- action.program.set_file(ConfigLexerState.StringVal);
- } else {
+ break;
+ case SPACE:
+ next();
+ /* FALL THROUGH */
+ default:
+ {
+ std::string progname;
+ if (parseProgramName(progname))
+ action.program.set(progname);
+ else
error("Expecting a program name");
- }
+
+ // Get the options
+ std::string anOption;
while (next_is_real()) {
- 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;
+ switch (token) {
+ case STRING:
+ case OPTION:
+ anOption += ConfigLexerState.StringVal;
+ break;
+ case ASSEMBLY:
+ anOption += "assembly";
+ break;
+ case BYTECODE:
+ anOption += "bytecode";
+ break;
+ case TRUETOK:
+ anOption += "true";
+ break;
+ case FALSETOK:
+ anOption += "false";
+ break;
+ case SEPARATOR:
+ anOption += ".";
+ break;
+ case SPACE:
+ action.args.push_back(anOption);
+ anOption.clear();
+ break;
+ default:
+ if (!parseSubstitution(action.args))
+ error("Expecting a program argument or substitution", false);
+ break;
}
}
}
}
void parsePreprocessor() {
+ if (next() != SEPARATOR)
+ error("Expecting '.'");
switch (next()) {
case COMMAND:
parseCommand(confDat->PreProcessor);
bool parseOutputFlag() {
if (next() == EQUALS) {
- if (next() == ASSEMBLY) {
+ if (next() == SPACE)
+ next();
+ if (token == ASSEMBLY) {
return true;
} else if (token == BYTECODE) {
return false;
}
void parseTranslator() {
+ if (next() != SEPARATOR)
+ error("Expecting '.'");
switch (next()) {
- case COMMAND:
+ case COMMAND:
parseCommand(confDat->Translator);
break;
case REQUIRED:
case PREPROCESSES:
if (parseBoolean())
confDat->Translator.set(CompilerDriver::PREPROCESSES_FLAG);
- else
+ else
confDat->Translator.clear(CompilerDriver::PREPROCESSES_FLAG);
break;
case OUTPUT:
}
void parseOptimizer() {
+ if (next() != SEPARATOR)
+ error("Expecting '.'");
switch (next()) {
case COMMAND:
parseCommand(confDat->Optimizer);
confDat->Translator.clear(CompilerDriver::OUTPUT_IS_ASM_FLAG);
break;
default:
- error(std::string("Expecting 'command', 'preprocesses', ") +
- "'translates' or 'output' but found '" +
+ error(std::string("Expecting 'command', 'preprocesses', "
+ "'translates' or 'output' but found '") +
ConfigLexerState.StringVal + "' instead");
break;
}
}
void parseAssembler() {
+ if (next() != SEPARATOR)
+ error("Expecting '.'");
switch(next()) {
case COMMAND:
parseCommand(confDat->Assembler);
}
void parseLinker() {
+ if (next() != SEPARATOR)
+ error("Expecting '.'");
switch(next()) {
case LIBS:
break; //FIXME
void parseAssignment() {
switch (token) {
- case VERSION: parseVersion(); break;
+ case VERSION_TOK: parseVersion(); break;
case LANG: parseLang(); break;
case PREPROCESSOR: parsePreprocessor(); break;
case TRANSLATOR: parseTranslator(); break;
case LINKER: parseLinker(); break;
case EOLTOK: break; // just ignore
case ERRORTOK:
- default:
+ default:
error("Invalid top level configuration item");
break;
}
}
};
- void
- ParseConfigData(InputProvider& provider, CompilerDriver::ConfigData& confDat) {
- Parser p;
- p.token = EOFTOK;
- p.provider = &provider;
- p.confDat = &confDat;
- p.parseFile();
+void
+ParseConfigData(InputProvider& provider, CompilerDriver::ConfigData& confDat) {
+ 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;
sys::Path confFile;
- if (configDir.is_empty()) {
+ if (configDir.isEmpty()) {
// Try the environment variable
const char* conf = getenv("LLVM_CONFIG_DIR");
if (conf) {
- confFile.set_directory(conf);
- confFile.append_file(ftype);
- if (!confFile.readable())
- throw std::string("Configuration file for '") + ftype +
+ confFile.set(conf);
+ confFile.appendComponent(ftype);
+ if (!confFile.canRead())
+ throw std::string("Configuration file for '") + ftype +
"' is not available.";
} else {
// Try the user's home directory
confFile = sys::Path::GetUserHomeDirectory();
- if (!confFile.is_empty()) {
- confFile.append_directory(".llvm");
- confFile.append_directory("etc");
- confFile.append_file(ftype);
- if (!confFile.readable())
+ if (!confFile.isEmpty()) {
+ confFile.appendComponent(".llvm");
+ confFile.appendComponent("etc");
+ confFile.appendComponent(ftype);
+ if (!confFile.canRead())
confFile.clear();
}
- if (!confFile.is_empty()) {
+ if (confFile.isEmpty()) {
// Okay, try the LLVM installation directory
confFile = sys::Path::GetLLVMConfigDir();
- confFile.append_file(ftype);
- if (!confFile.readable()) {
+ confFile.appendComponent(ftype);
+ if (!confFile.canRead()) {
// Okay, try the "standard" place
confFile = sys::Path::GetLLVMDefaultConfigDir();
- confFile.append_file(ftype);
- if (!confFile.readable()) {
- throw std::string("Configuration file for '") + ftype +
+ confFile.appendComponent(ftype);
+ if (!confFile.canRead()) {
+ throw std::string("Configuration file for '") + ftype +
"' is not available.";
}
}
}
} else {
confFile = configDir;
- confFile.append_file(ftype);
- if (!confFile.readable())
- throw std::string("Configuration file for '") + ftype +
+ confFile.appendComponent(ftype);
+ if (!confFile.canRead())
+ throw std::string("Configuration file for '") + ftype +
"' is not available.";
}
- FileInputProvider fip( confFile.get() );
+ FileInputProvider fip( confFile.toString() );
if (!fip.okay()) {
- throw std::string("Configuration file for '") + ftype +
+ throw std::string("Configuration file for '") + ftype +
"' is not available.";
}
result = new CompilerDriver::ConfigData();
Configurations.clear();
}
-CompilerDriver::ConfigData*
+CompilerDriver::ConfigData*
LLVMC_ConfigDataProvider::ProvideConfigData(const std::string& filetype) {
CompilerDriver::ConfigData* result = 0;
if (!Configurations.empty()) {
}
return result; // Might return 0
}
-
-// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab