diff trunk/src/dil/SettingsLoader.d @ 513:6160ab7b1816

Refactored code related to settings.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Fri, 14 Dec 2007 19:08:21 +0100
parents
children 7cb97346bc6f
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/SettingsLoader.d	Fri Dec 14 19:08:21 2007 +0100
@@ -0,0 +1,180 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module dil.SettingsLoader;
+
+import dil.Settings;
+import dil.Messages;
+import dil.Parser, dil.SyntaxTree, dil.Declarations, dil.Expressions;
+import dil.File;
+import tango.io.FilePath;
+import common;
+
+void loadSettings()
+{
+  scope execPath = new FilePath(GetExecutableFilePath());
+
+  // Load config.d
+  auto filePath = execPath.file("config.d").toUtf8();
+  auto sourceText = loadFile(filePath);
+  auto parser = new Parser(sourceText, filePath);
+  auto root = parser.start();
+
+  if (parser.errors.length || parser.lx.errors.length)
+    throw new Exception("There are errors in " ~ filePath ~ ".");
+
+  foreach (decl; root.children)
+  {
+    auto v = Cast!(VariableDeclaration)(decl);
+    if (v is null)
+      continue;
+
+    auto variableName = v.idents[0].str;
+    auto e = v.values[0];
+    if (!e)
+      throw new Exception(variableName ~ " variable has no value set.");
+
+    switch (variableName)
+    {
+    case "langfile":
+      if (auto val = Cast!(StringExpression)(e))
+        GlobalSettings.langFile = val.getString();
+      break;
+    case "import_paths":
+      if (auto array = Cast!(ArrayInitializer)(e))
+      {
+        foreach (value; array.values)
+          if (auto str = Cast!(StringExpression)(value))
+            GlobalSettings.importPaths ~= str.getString();
+      }
+      else
+        throw new Exception("import_paths variable is set to "~e.classinfo.name~" instead of an ArrayInitializer.");
+      break;
+    case "lexer_error":
+      if (auto val = Cast!(StringExpression)(e))
+        GlobalSettings.lexerErrorFormat = val.getString();
+      break;
+    case "parser_error":
+      if (auto val = Cast!(StringExpression)(e))
+        GlobalSettings.parserErrorFormat = val.getString();
+      break;
+    case "semantic_error":
+      if (auto val = Cast!(StringExpression)(e))
+        GlobalSettings.semanticErrorFormat = val.getString();
+      break;
+    default:
+    }
+  }
+
+  // Load language file.
+  filePath = GlobalSettings.langFile;
+  sourceText = loadFile(execPath.file(filePath).toUtf8());
+  parser = new Parser(sourceText, filePath);
+  root = parser.start();
+
+  if (parser.errors.length || parser.lx.errors.length)
+    throw new Exception("There are errors in "~filePath~".");
+
+  char[][] messages;
+  foreach (decl; root.children)
+  {
+    auto v = Cast!(VariableDeclaration)(decl);
+    if (v is null)
+      continue;
+
+    auto variableName = v.idents[0].str;
+    auto e = v.values[0];
+    if (!e)
+      throw new Exception(variableName~" variable in "~filePath~" has no value set.");
+
+    switch (variableName)
+    {
+    case "messages":
+      if (auto array = Cast!(ArrayInitializer)(e))
+      {
+        foreach (value; array.values)
+        {
+          if (auto str = Cast!(StringExpression)(value))
+            messages ~= str.getString();
+        }
+      }
+      else
+        throw new Exception("messages variable is set to "~e.classinfo.name~" instead of an ArrayInitializer.");
+      break;
+    case "lang_code":
+      if (auto str = Cast!(StringExpression)(e))
+          GlobalSettings.langCode = str.getString();
+      break;
+    default:
+    }
+  }
+  if (messages.length != MID.max+1)
+    throw new Exception(
+      Format(
+        "messages table in {0} must exactly have {1} entries, but {2} were found.",
+        filePath, MID.max+1, messages.length)
+      );
+  GlobalSettings.messages = messages;
+  dil.Messages.SetMessages(messages);
+}
+
+version(Windows)
+{
+private extern(Windows) uint GetModuleFileNameA(void*, char*, uint);
+/++
+  Get the fully qualified path to this executable.
++/
+char[] GetExecutableFilePath()
+{
+  alias GetModuleFileNameA GetModuleFileName;
+  char[] buffer = new char[256];
+  uint count;
+
+  while (1)
+  {
+    if (buffer is null)
+      return null;
+
+    count = GetModuleFileName(null, buffer.ptr, buffer.length);
+    if (count == 0)
+      return null;
+    if (buffer.length != count && buffer[count] == 0)
+      break;
+    // Increase size of buffer
+    buffer.length = buffer.length * 2;
+  }
+  assert(buffer[count] == 0);
+  // Reduce buffer to the actual length of the string (excluding '\0'.)
+  if (count < buffer.length)
+    buffer.length = count;
+  return buffer;
+}
+}
+else version(linux)
+{
+private extern(C) size_t readlink(char* path, char* buf, size_t bufsize);
+/++
+  Get the fully qualified path to this executable.
++/
+char[] GetExecutableFilePath()
+{
+  char[] buffer = new char[256];
+  size_t count;
+
+  while (1)
+  {
+    // This won't work on very old Linux systems.
+    count = readlink("/proc/self/exe".ptr, buffer.ptr, buffer.length);
+    if (count == -1)
+      return null;
+    if (count < buffer.length)
+      break;
+    buffer.length = buffer.length * 2;
+  }
+  buffer.length = count;
+  return buffer;
+}
+}
+else
+  static assert(0, "GetExecutableFilePath() is not implemented on this platform.");