diff --git a/src/dmd/backend/dwarfdbginf.d b/src/dmd/backend/dwarfdbginf.d index d6c2054caaf7..72e1bf1669ec 100644 --- a/src/dmd/backend/dwarfdbginf.d +++ b/src/dmd/backend/dwarfdbginf.d @@ -1126,7 +1126,7 @@ static if (ELFOBJ || MACHOBJ) version (MARS) { debug_info.buf.write("Digital Mars D "); - debug_info.buf.write(config._version); // DW_AT_producer + debug_info.buf.writeString(config._version); // DW_AT_producer // DW_AT_language debug_info.buf.writeByte((config.fulltypes == CVDWARF_D) ? DW_LANG_D : DW_LANG_C89); } diff --git a/src/dmd/backend/elfobj.d b/src/dmd/backend/elfobj.d index dd02345db0f9..4051ac3d4ff3 100644 --- a/src/dmd/backend/elfobj.d +++ b/src/dmd/backend/elfobj.d @@ -1500,10 +1500,11 @@ void Obj_compiler() enum n = compilerHeader.length; char[n + maxVersionLength] compiler = compilerHeader; - assert(config._version.length < maxVersionLength); + assert(config._version.length + 1 < maxVersionLength); const newLength = n + config._version.length; compiler[n .. newLength] = config._version; - comment_data.write(compiler[0 .. newLength]); + compiler[newLength] = 0; + comment_data.write(compiler[0 .. newLength + 1]); //dbg_printf("Comment data size %d\n",comment_data.length()); } diff --git a/src/dmd/dmsc.d b/src/dmd/dmsc.d index 76c1ce716610..7900a49d43c5 100644 --- a/src/dmd/dmsc.d +++ b/src/dmd/dmsc.d @@ -100,7 +100,7 @@ void backend_init() params.useModuleInfo && Module.moduleinfo, params.useTypeInfo && Type.dtypeinfo, params.useExceptions && ClassDeclaration.throwable, - global._version + global.versionString() ); debug diff --git a/src/dmd/globals.d b/src/dmd/globals.d index d35d8e5112ed..0f46beb6e425 100644 --- a/src/dmd/globals.d +++ b/src/dmd/globals.d @@ -316,7 +316,8 @@ extern (C++) struct Global Array!(const(char)*)* path; // Array of char*'s which form the import lookup path Array!(const(char)*)* filePath; // Array of char*'s which form the file import lookup path - string _version; + private enum string _version = import("VERSION"); + private enum uint _versionNumber = parseVersionNumber(_version); const(char)[] vendor; // Compiler backend name Param params; @@ -371,8 +372,6 @@ extern (C++) struct Global extern (C++) void _init() { - _version = import("VERSION") ~ '\0'; - version (MARS) { vendor = "Digital Mars D"; @@ -460,41 +459,51 @@ extern (C++) struct Global } /** - Returns: the version as the number that would be returned for __VERSION__ - */ - extern(C++) uint versionNumber() + * Computes the version number __VERSION__ from the compiler version string. + */ + extern (D) private static uint parseVersionNumber(string version_) { - import core.stdc.ctype; - __gshared uint cached = 0; - if (cached == 0) + // + // parse _version + // + uint major = 0; + uint minor = 0; + bool point = false; + // skip initial 'v' + foreach (const c; version_[1..$]) { - // - // parse _version - // - uint major = 0; - uint minor = 0; - bool point = false; - for (const(char)* p = _version.ptr + 1;; p++) + if ('0' <= c && c <= '9') // isdigit { - const c = *p; - if (isdigit(cast(char)c)) - { - minor = minor * 10 + c - '0'; - } - else if (c == '.') - { - if (point) - break; // ignore everything after second '.' - point = true; - major = minor; - minor = 0; - } - else - break; + minor = minor * 10 + c - '0'; } - cached = major * 1000 + minor; + else if (c == '.') + { + if (point) + break; // ignore everything after second '.' + point = true; + major = minor; + minor = 0; + } + else + break; } - return cached; + return major * 1000 + minor; + } + + /** + Returns: the version as the number that would be returned for __VERSION__ + */ + extern(C++) uint versionNumber() + { + return _versionNumber; + } + + /** + Returns: compiler version string. + */ + extern(C++) string versionString() + { + return _version; } /** diff --git a/src/dmd/globals.h b/src/dmd/globals.h index eb773d692c88..c7a6e134213a 100644 --- a/src/dmd/globals.h +++ b/src/dmd/globals.h @@ -281,7 +281,6 @@ struct Global Array *path; // Array of char*'s which form the import lookup path Array *filePath; // Array of char*'s which form the file import lookup path - DString version; // Compiler version string DString vendor; // Compiler backend name Param params; @@ -317,6 +316,11 @@ struct Global Returns: the version as the number that would be returned for __VERSION__ */ unsigned versionNumber(); + + /** + Returns: the compiler version string. + */ + DString versionString(); }; extern Global global; diff --git a/src/dmd/json.d b/src/dmd/json.d index 939107133e48..e2bb0c8c67bb 100644 --- a/src/dmd/json.d +++ b/src/dmd/json.d @@ -829,7 +829,7 @@ public: { objectStart(); requiredProperty("vendor", global.vendor); - requiredProperty("version", global._version); + requiredProperty("version", global.versionString()); property("__VERSION__", global.versionNumber()); requiredProperty("interface", determineCompilerInterface()); property("size_t", size_t.sizeof); diff --git a/src/dmd/mars.d b/src/dmd/mars.d index bd63e7a1b298..06ddd179f180 100644 --- a/src/dmd/mars.d +++ b/src/dmd/mars.d @@ -73,7 +73,7 @@ private void logo() { printf("DMD%llu D Compiler %.*s\n%.*s %.*s\n", cast(ulong)size_t.sizeof * 8, - cast(int) global._version.length - 1, global._version.ptr, + cast(int) global.versionString().length, global.versionString().ptr, cast(int)global.copyright.length, global.copyright.ptr, cast(int)global.written.length, global.written.ptr ); @@ -93,7 +93,7 @@ extern(C) void printInternalFailure(FILE* stream) "with, preferably, a reduced, reproducible example and the information below.\n" ~ "DustMite (https://github.com/CyberShadow/DustMite/wiki) can help with the reduction.\n" ~ "---\n").ptr, stream); - stream.fprintf("DMD %.*s\n", cast(int) global._version.length - 1, global._version.ptr); + stream.fprintf("DMD %.*s\n", cast(int) global.versionString().length, global.versionString().ptr); stream.printPredefinedVersions; stream.printGlobalConfigs(); fputs("---\n".ptr, stream); @@ -1310,7 +1310,7 @@ private void printPredefinedVersions(FILE* stream) extern(C) void printGlobalConfigs(FILE* stream) { stream.fprintf("binary %.*s\n", cast(int)global.params.argv0.length, global.params.argv0.ptr); - stream.fprintf("version %.*s\n", cast(int) global._version.length - 1, global._version.ptr); + stream.fprintf("version %.*s\n", cast(int) global.versionString().length, global.versionString().ptr); const iniOutput = global.inifilename ? global.inifilename : "(none)"; stream.fprintf("config %.*s\n", cast(int)iniOutput.length, iniOutput.ptr); // Print DFLAGS environment variable diff --git a/src/tests/cxxfrontend.c b/src/tests/cxxfrontend.c index f042efef5b76..52535e2a451f 100644 --- a/src/tests/cxxfrontend.c +++ b/src/tests/cxxfrontend.c @@ -105,6 +105,14 @@ void test_tokens() assert(strcmp(Token::toChars(TOKvectorarray), "vectorarray") == 0); } +void test_compiler_globals() +{ + // only check constant prefix of version + assert(strncmp(global.versionString().ptr, "v2.", 3) == 0); + unsigned versionNumber = global.versionNumber(); + assert(versionNumber >= 2060 && versionNumber <= 3000); +} + /**********************************/ class TestVisitor : public Visitor @@ -457,6 +465,7 @@ int main(int argc, char **argv) frontend_init(); test_tokens(); + test_compiler_globals(); test_visitors(); test_semantic(); test_expression();