comparison trunk/src/dil/Settings.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 3bb94ba21490
children f203c5248d0b
comparison
equal deleted inserted replaced
512:112c17300069 513:6160ab7b1816
1 /++ 1 /++
2 Author: Aziz Köksal 2 Author: Aziz Köksal
3 License: GPL3 3 License: GPL3
4 +/ 4 +/
5 module dil.Settings; 5 module dil.Settings;
6 import dil.Messages;
7 import dil.Parser, dil.SyntaxTree, dil.Declarations, dil.Expressions;
8 import dil.File;
9 import tango.io.FilePath;
10 import common; 6 import common;
11 7
12 struct GlobalSettings 8 struct GlobalSettings
13 { 9 {
14 static: 10 static:
15 string language; /// Language of loaded messages catalogue. 11 /// Path to the language file.
16 string[] messages; /// Table of localized compiler messages. 12 string langFile = "lang_en.d";
17 string[] importPaths; /// Array of import paths to look for modules. 13 /// Language code of loaded messages catalogue.
18 void load() 14 string langCode = "en";
19 { 15 /// Table of localized compiler messages.
20 scope execPath = new FilePath(GetExecutableFilePath()); 16 string[] messages;
21 auto fileName = execPath.file("config.d").toUtf8(); 17 /// Array of import paths to look for modules.
22 auto sourceText = loadFile(fileName); 18 string[] importPaths;
23 auto parser = new Parser(sourceText, fileName); 19 string lexerErrorFormat = "{1}({2},{3})L: {4}";
24 auto root = parser.start(); 20 string parserErrorFormat = "{1}({2},{3})L: {4}";
25 21 string semanticErrorFormat = "{1}({2},{3})L: {4}";
26 if (parser.errors.length || parser.lx.errors.length)
27 {
28 throw new Exception("There are errors in " ~ fileName ~ ".");
29 }
30
31 foreach (decl; root.children)
32 {
33 auto v = Cast!(VariableDeclaration)(decl);
34 if (v is null)
35 continue;
36 auto vname = v.idents[0].str;
37 if (vname == "langfile")
38 {
39 auto e = v.values[0];
40 if (!e)
41 throw new Exception("langfile variable has no value set.");
42 auto val = Cast!(StringExpression)(e);
43 if (val)
44 // Set fileName to d-file with messages table.
45 fileName = val.getString();
46 }
47 else if (vname == "import_paths")
48 {
49 auto e = v.values[0];
50 if (e is null)
51 throw new Exception("import_paths variable has no variable set.");
52 if (auto array = Cast!(ArrayInitializer)(e))
53 {
54 foreach (value; array.values)
55 if (auto str = Cast!(StringExpression)(value))
56 GlobalSettings.importPaths ~= str.getString();
57 }
58 else
59 throw new Exception("import_paths variable is set to "~e.classinfo.name~" instead of an ArrayInitializer.");
60 }
61 }
62
63 // Load messages
64 sourceText = loadFile(execPath.file(fileName).toUtf8());
65 parser = new Parser(sourceText, fileName);
66 root = parser.start();
67
68 if (parser.errors.length || parser.lx.errors.length)
69 {
70 throw new Exception("There are errors in "~fileName~".");
71 }
72
73 char[][] messages;
74 foreach (decl; root.children)
75 {
76 auto v = Cast!(VariableDeclaration)(decl);
77 if (v is null)
78 continue;
79 if (v.idents[0].str == "messages")
80 {
81 auto e = v.values[0];
82 if (!e)
83 throw new Exception("messages variable in "~fileName~" has no value set.");
84 if (auto array = Cast!(ArrayInitializer)(e))
85 {
86 foreach (value; array.values)
87 {
88 if (auto str = Cast!(StringExpression)(value))
89 messages ~= str.getString();
90 }
91 }
92 else
93 throw new Exception("messages variable is set to "~e.classinfo.name~" instead of an ArrayInitializer.");
94 }
95 else if(v.idents[0].str == "lang_code")
96 {
97 auto e = v.values[0];
98 if (!e)
99 throw new Exception("lang_code variable in "~fileName~" has no value set.");
100 if (auto str = Cast!(StringExpression)(e))
101 GlobalSettings.language = str.getString();
102 }
103 }
104 if (messages.length != MID.max+1)
105 throw new Exception(Format("messages table in {0} must exactly have {1} entries, but {2} were found.", fileName, MID.max+1, messages.length));
106 GlobalSettings.messages = messages;
107 dil.Messages.SetMessages(messages);
108 }
109 } 22 }
110
111 version(Windows)
112 {
113 private extern(Windows) uint GetModuleFileNameA(void*, char*, uint);
114 /++
115 Get the fully qualified path to this executable.
116 +/
117 char[] GetExecutableFilePath()
118 {
119 alias GetModuleFileNameA GetModuleFileName;
120 char[] buffer = new char[256];
121 uint count;
122
123 while (1)
124 {
125 if (buffer is null)
126 return null;
127
128 count = GetModuleFileName(null, buffer.ptr, buffer.length);
129 if (count == 0)
130 return null;
131 if (buffer.length != count && buffer[count] == 0)
132 break;
133 // Increase size of buffer
134 buffer.length = buffer.length * 2;
135 }
136 assert(buffer[count] == 0);
137 // Reduce buffer to the actual length of the string (excluding '\0'.)
138 if (count < buffer.length)
139 buffer.length = count;
140 return buffer;
141 }
142 }
143 else version(linux)
144 {
145 private extern(C) size_t readlink(char* path, char* buf, size_t bufsize);
146 /++
147 Get the fully qualified path to this executable.
148 +/
149 char[] GetExecutableFilePath()
150 {
151 char[] buffer = new char[256];
152 size_t count;
153
154 while (1)
155 {
156 // This won't work on very old Linux systems.
157 count = readlink("/proc/self/exe".ptr, buffer.ptr, buffer.length);
158 if (count == -1)
159 return null;
160 if (count < buffer.length)
161 break;
162 buffer.length = buffer.length * 2;
163 }
164 buffer.length = count;
165 return buffer;
166 }
167 }
168 else
169 static assert(0, "GetExecutableFilePath() is not implemented on your platform.");