Since several tools and examples want JIT support, factor out the process of
[oota-llvm.git] / tools / llvmc / Configuration.cpp
index a381d56e1cde2a0b4f112fc19c315ed0ccbbcb50..6b5d33975f2c0a4f2a57c0e5317bf772f5661dc5 100644 (file)
@@ -15,9 +15,9 @@
 #include "Configuration.h"
 #include "ConfigLexer.h"
 #include "CompilerDriver.h"
-#include "Config/config.h"
-#include "Support/CommandLine.h"
-#include "Support/StringExtras.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/ADT/StringExtras.h"
 #include <iostream>
 #include <fstream>
 
@@ -25,7 +25,7 @@ using namespace llvm;
 
 namespace sys {
   // From CompilerDriver.cpp (for now)
-  extern bool FileReadable(const std::string& fname);
+  extern bool FileIsReadable(const std::string& fname);
 }
 
 namespace llvm {
@@ -90,19 +90,19 @@ namespace {
     InputProvider* provider;
     CompilerDriver::ConfigData* confDat;
 
-    int next() { 
+    inline int next() { 
       token = Configlex();
       if (DumpTokens) 
         std::cerr << token << "\n";
       return token;
     }
 
-    bool next_is_real() { 
+    inline bool next_is_real() { 
       next();
       return (token != EOLTOK) && (token != ERRORTOK) && (token != 0);
     }
 
-    void eatLineRemnant() {
+    inline void eatLineRemnant() {
       while (next_is_real()) ;
     }
 
@@ -155,12 +155,18 @@ namespace {
 
     bool parseSubstitution(CompilerDriver::StringVector& optList) {
       switch (token) {
+        case ARGS_SUBST:        optList.push_back("%args%"); 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 OUT_SUBST:         optList.push_back("%out%"); break;
-        case TIME_SUBST:        optList.push_back("%time%"); break;
-        case STATS_SUBST:       optList.push_back("%stats%"); break;
+        case INCLS_SUBST:       optList.push_back("%incls%"); 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 TARGET_SUBST:      optList.push_back("%target%"); 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;
         default:
           return false;
       }
@@ -181,6 +187,18 @@ namespace {
         error("Expecting '='");
     }
 
+    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
+        error("Expecting '='");
+    }
+
     void parseLang() {
       switch (next() ) {
         case NAME: 
@@ -216,7 +234,7 @@ namespace {
           action.args.clear();
         } else {
           if (token == STRING || token == OPTION) {
-            action.program = ConfigLexerState.StringVal;
+            action.program.set_file(ConfigLexerState.StringVal);
           } else {
             error("Expecting a program name");
           }
@@ -244,11 +262,31 @@ namespace {
             confDat->PreProcessor.clear(CompilerDriver::REQUIRED_FLAG);
           break;
         default:
-          error("Expecting 'command' or 'required'");
+          error("Expecting 'command' or 'required' but found '" +
+              ConfigLexerState.StringVal);
           break;
       }
     }
 
+    bool parseOutputFlag() {
+      if (next() == EQUALS) {
+        if (next() == ASSEMBLY) {
+          return true;
+        } else if (token == BYTECODE) {
+          return false;
+        } else {
+          error("Expecting output type value");
+          return false;
+        }
+        if (next() != EOLTOK && token != 0) {
+          error("Extraneous tokens after output value");
+        }
+      }
+      else
+        error("Expecting '='");
+      return false;
+    }
+
     void parseTranslator() {
       switch (next()) {
         case COMMAND: 
@@ -266,28 +304,17 @@ namespace {
           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())
+        case OUTPUT:
+          if (parseOutputFlag())
             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'");
+          error("Expecting 'command', 'required', 'preprocesses', or "
+                "'output' but found '" + ConfigLexerState.StringVal +
+                "' instead");
           break;
       }
     }
@@ -309,20 +336,22 @@ namespace {
           else
             confDat->Optimizer.clear(CompilerDriver::TRANSLATES_FLAG);
           break;
-        case GROKS_DASH_O:
+        case REQUIRED:
           if (parseBoolean())
-            confDat->Optimizer.set(CompilerDriver::GROKS_DASH_O_FLAG);
+            confDat->Optimizer.set(CompilerDriver::REQUIRED_FLAG);
           else
-            confDat->Optimizer.clear(CompilerDriver::GROKS_DASH_O_FLAG);
+            confDat->Optimizer.clear(CompilerDriver::REQUIRED_FLAG);
           break;
-        case OUTPUT_IS_ASM:
-          if (parseBoolean())
+        case OUTPUT:
+          if (parseOutputFlag())
             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'");
+          error(std::string("Expecting 'command', 'preprocesses', ") +
+              "'translates' or 'output' but found '" + 
+              ConfigLexerState.StringVal + "' instead");
           break;
       }
     }
@@ -340,23 +369,19 @@ namespace {
 
     void parseLinker() {
       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;
+        case LIBS:
+          break; //FIXME
+        case LIBPATHS:
+          break; //FIXME
         default:
-          error("Expecting 'command'");
+          error("Expecting 'libs' or 'libpaths'");
           break;
       }
     }
 
     void parseAssignment() {
       switch (token) {
+        case VERSION:       parseVersion(); break;
         case LANG:          parseLang(); break;
         case PREPROCESSOR:  parsePreprocessor(); break;
         case TRANSLATOR:    parseTranslator(); break;
@@ -395,57 +420,58 @@ namespace {
 CompilerDriver::ConfigData*
 LLVMC_ConfigDataProvider::ReadConfigData(const std::string& ftype) {
   CompilerDriver::ConfigData* result = 0;
-  std::string dir_name;
-  if (configDir.empty()) {
+  sys::Path confFile;
+  if (configDir.is_empty()) {
     // 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.";
+      confFile.set_directory(conf);
+      confFile.append_file(ftype);
+      if (!confFile.readable())
+        throw std::string("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.";
-            }
+      confFile = sys::Path::GetUserHomeDirectory();
+      if (!confFile.is_empty()) {
+        confFile.append_directory(".llvm");
+        confFile.append_directory("etc");
+        confFile.append_file(ftype);
+        if (!confFile.readable())
+          confFile.clear();
+      }
+      if (!confFile.is_empty()) {
+        // Okay, try the LLVM installation directory
+        confFile = sys::Path::GetLLVMConfigDir();
+        confFile.append_file(ftype);
+        if (!confFile.readable()) {
+          // Okay, try the "standard" place
+          confFile = sys::Path::GetLLVMDefaultConfigDir();
+          confFile.append_file(ftype);
+          if (!confFile.readable()) {
+            throw std::string("Configuration file for '") + ftype + 
+                              "' is not available.";
           }
         }
       }
     }
   } else {
-    dir_name = configDir + "/";
-    if (!::sys::FileReadable(dir_name + ftype)) {
-      throw "Configuration file for '" + ftype + "' is not available.";
-    }
+    confFile = configDir;
+    confFile.append_file(ftype);
+    if (!confFile.readable())
+      throw std::string("Configuration file for '") + ftype + 
+                        "' is not available.";
   }
-  FileInputProvider fip( dir_name + ftype );
+  FileInputProvider fip( confFile.get() );
   if (!fip.okay()) {
-    throw "Configuration file for '" + ftype + "' is not available.";
+    throw std::string("Configuration file for '") + ftype + 
+                      "' is not available.";
   }
   result = new CompilerDriver::ConfigData();
   ParseConfigData(fip,*result);
   return result;
 }
 
-LLVMC_ConfigDataProvider::LLVMC_ConfigDataProvider() 
-  : Configurations() 
-  , configDir() 
-{
-  Configurations.clear();
-}
-
 LLVMC_ConfigDataProvider::~LLVMC_ConfigDataProvider()
 {
   ConfigDataMap::iterator cIt = Configurations.begin();
@@ -471,7 +497,7 @@ LLVMC_ConfigDataProvider::ProvideConfigData(const std::string& filetype) {
     // The configuration data doesn't exist, we have to go read it.
     result = ReadConfigData(filetype);
     // If we got one, cache it
-    if ( result != 0 )
+    if (result != 0)
       Configurations.insert(std::make_pair(filetype,result));
   }
   return result; // Might return 0