# HG changeset patch # User Aziz K?ksal # Date 1197655701 -3600 # Node ID 6160ab7b1816fda24e45757fb2a5d0ee64f338ca # Parent 112c17300069142493a4760d7aa6efe364fc806e Refactored code related to settings. diff -r 112c17300069 -r 6160ab7b1816 trunk/src/config.d --- a/trunk/src/config.d Thu Dec 13 23:04:50 2007 +0100 +++ b/trunk/src/config.d Fri Dec 14 19:08:21 2007 +0100 @@ -1,2 +1,16 @@ -option langfile = "lang_en.d"; -option import_paths = []; +// Relative paths are resolved from the directory of dil's executable. + +// Path to the language file. +auto langfile = "lang_en.d"; +// An array of import paths to look for modules. +auto import_paths = []; +/* + Customizing error messages. + 1: file path to the source text. + 2: line number. + 3: column number. + 4: error message. +*/ +auto lexer_error = "{1}({2},{3})L: {4}"; +auto parser_error = "{1}({2},{3})P: {4}"; +auto semantic_error = "{1}({2},{3})S: {4}"; diff -r 112c17300069 -r 6160ab7b1816 trunk/src/dil/CompilerInfo.d --- a/trunk/src/dil/CompilerInfo.d Thu Dec 13 23:04:50 2007 +0100 +++ b/trunk/src/dil/CompilerInfo.d Fri Dec 14 19:08:21 2007 +0100 @@ -39,4 +39,5 @@ /// ditto const COMPILED_DATE = __TIMESTAMP__; -const DEFAULT_ALIGN_SIZE = 1; /// The global, default alignment size for struct fields. +/// The global, default alignment size for struct fields. +const DEFAULT_ALIGN_SIZE = 4; diff -r 112c17300069 -r 6160ab7b1816 trunk/src/dil/Settings.d --- a/trunk/src/dil/Settings.d Thu Dec 13 23:04:50 2007 +0100 +++ b/trunk/src/dil/Settings.d Fri Dec 14 19:08:21 2007 +0100 @@ -3,167 +3,20 @@ License: GPL3 +/ module dil.Settings; -import dil.Messages; -import dil.Parser, dil.SyntaxTree, dil.Declarations, dil.Expressions; -import dil.File; -import tango.io.FilePath; import common; struct GlobalSettings { static: - string language; /// Language of loaded messages catalogue. - string[] messages; /// Table of localized compiler messages. - string[] importPaths; /// Array of import paths to look for modules. - void load() - { - scope execPath = new FilePath(GetExecutableFilePath()); - auto fileName = execPath.file("config.d").toUtf8(); - auto sourceText = loadFile(fileName); - auto parser = new Parser(sourceText, fileName); - auto root = parser.start(); - - if (parser.errors.length || parser.lx.errors.length) - { - throw new Exception("There are errors in " ~ fileName ~ "."); - } - - foreach (decl; root.children) - { - auto v = Cast!(VariableDeclaration)(decl); - if (v is null) - continue; - auto vname = v.idents[0].str; - if (vname == "langfile") - { - auto e = v.values[0]; - if (!e) - throw new Exception("langfile variable has no value set."); - auto val = Cast!(StringExpression)(e); - if (val) - // Set fileName to d-file with messages table. - fileName = val.getString(); - } - else if (vname == "import_paths") - { - auto e = v.values[0]; - if (e is null) - throw new Exception("import_paths variable has no variable set."); - 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."); - } - } - - // Load messages - sourceText = loadFile(execPath.file(fileName).toUtf8()); - parser = new Parser(sourceText, fileName); - root = parser.start(); - - if (parser.errors.length || parser.lx.errors.length) - { - throw new Exception("There are errors in "~fileName~"."); - } - - char[][] messages; - foreach (decl; root.children) - { - auto v = Cast!(VariableDeclaration)(decl); - if (v is null) - continue; - if (v.idents[0].str == "messages") - { - auto e = v.values[0]; - if (!e) - throw new Exception("messages variable in "~fileName~" has no value set."); - 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."); - } - else if(v.idents[0].str == "lang_code") - { - auto e = v.values[0]; - if (!e) - throw new Exception("lang_code variable in "~fileName~" has no value set."); - if (auto str = Cast!(StringExpression)(e)) - GlobalSettings.language = str.getString(); - } - } - if (messages.length != MID.max+1) - throw new Exception(Format("messages table in {0} must exactly have {1} entries, but {2} were found.", fileName, MID.max+1, messages.length)); - GlobalSettings.messages = messages; - dil.Messages.SetMessages(messages); - } + /// Path to the language file. + string langFile = "lang_en.d"; + /// Language code of loaded messages catalogue. + string langCode = "en"; + /// Table of localized compiler messages. + string[] messages; + /// Array of import paths to look for modules. + string[] importPaths; + string lexerErrorFormat = "{1}({2},{3})L: {4}"; + string parserErrorFormat = "{1}({2},{3})L: {4}"; + string semanticErrorFormat = "{1}({2},{3})L: {4}"; } - -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 your platform."); diff -r 112c17300069 -r 6160ab7b1816 trunk/src/dil/SettingsLoader.d --- /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."); diff -r 112c17300069 -r 6160ab7b1816 trunk/src/main.d --- a/trunk/src/main.d Thu Dec 13 23:04:50 2007 +0100 +++ b/trunk/src/main.d Fri Dec 14 19:08:21 2007 +0100 @@ -3,11 +3,13 @@ License: GPL3 +/ module main; + import dil.Parser; import dil.Lexer; import dil.Token; import dil.Messages; import dil.Settings; +import dil.SettingsLoader; import dil.CompilerInfo; import dil.Declarations, dil.Expressions, dil.SyntaxTree; import dil.File; @@ -17,10 +19,13 @@ import common; import Integer = tango.text.convert.Integer; +import tango.io.File; +import tango.text.Util; +import tango.util.time.StopWatch; void main(char[][] args) { - GlobalSettings.load(); + dil.SettingsLoader.loadSettings(); if (args.length <= 1) return Stdout(helpMain()).newline; @@ -130,6 +135,26 @@ Stdout(token.srcText)(separator); } break; + case "profile": + if (args.length < 3) + break; + char[][] filePaths; + if (args[2] == "dstress") + { + auto text = cast(char[])(new File("dstress_files")).read(); + filePaths = split(text, "\0"); + } + else + filePaths = args[2..$]; + + StopWatch swatch; + swatch.start; + + foreach (filePath; filePaths) + (new Lexer(loadFile(filePath), null)).scanAll(); + + Stdout.formatln("Scanned in {:f10}s.", swatch.stop); + break; case "parse": if (args.length == 3) parse(args[2]); @@ -192,6 +217,14 @@ dil tok -t"module foo; void func(){}" dil tok main.d | grep ^[0-9]`; break; + case "stats", "statistics": + msg = "Gather statistics about D source files. +Usage: + dil stat file.d [file2.d, ...] + +Example: + dil stat src/dil/Parser.d src/dil/Lexer.d"; + break; default: msg = helpMain(); }