diff --git a/src/dmd/globals.d b/src/dmd/globals.d index 357513461929..23e60e9331b3 100644 --- a/src/dmd/globals.d +++ b/src/dmd/globals.d @@ -362,6 +362,44 @@ struct Global _version = (import("VERSION") ~ '\0').ptr; compiler.vendor = "Digital Mars D"; } + + /** + Returns: the version as the number that would be returned for __VERSION__ + */ + extern(C++) uint versionNumber() + { + import core.stdc.ctype; + __gshared static uint cached = 0; + if (cached == 0) + { + // + // parse _version + // + uint major = 0; + uint minor = 0; + bool point = false; + for (const(char)* p = _version + 1;; p++) + { + 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; + } + cached = major * 1000 + minor; + } + return cached; + } } // Because int64_t and friends may be any integral type of the diff --git a/src/dmd/globals.h b/src/dmd/globals.h index 6b533bdee236..539ceb3b4a00 100644 --- a/src/dmd/globals.h +++ b/src/dmd/globals.h @@ -257,6 +257,11 @@ struct Global void increaseErrorCount(); void _init(); + + /** + Returns: the version as the number that would be returned for __VERSION__ + */ + unsigned versionNumber(); }; extern Global global; diff --git a/src/dmd/json.d b/src/dmd/json.d index 913ca2f17017..a1dd19c0d299 100644 --- a/src/dmd/json.d +++ b/src/dmd/json.d @@ -228,6 +228,13 @@ public: buf.writestring(" : "); } + /** + Write the given string object property only if `s` is not null. + + Params: + name = the name of the object property + s = the string value of the object property + */ void property(const(char)* name, const(char)* s) { if (s is null) @@ -237,6 +244,23 @@ public: comma(); } + /** + Write the given string object property. + + Params: + name = the name of the object property + s = the string value of the object property + */ + void requiredProperty(const(char)* name, const(char)* s) + { + propertyStart(name); + if (s is null) + buf.writestring("null"); + else + value(s); + comma(); + } + void property(const(char)* name, int i) { propertyStart(name); @@ -826,8 +850,61 @@ public: private void generateCompilerInfo() { objectStart(); - property("binary", global.params.argv0); - property("version", global._version); + requiredProperty("vendor", global.compiler.vendor); + requiredProperty("version", global._version); + property("__VERSION__", global.versionNumber()); + requiredProperty("interface", determineCompilerInterface()); + property("size_t", size_t.sizeof); + propertyStart("platforms"); + arrayStart(); + if (global.params.isWindows) + { + item("windows"); + } + else + { + item("posix"); + if (global.params.isLinux) + item("linux"); + else if (global.params.isOSX) + item("osx"); + else if (global.params.isFreeBSD) + { + item("freebsd"); + item("bsd"); + } + else if (global.params.isOpenBSD) + { + item("openbsd"); + item("bsd"); + } + else if (global.params.isSolaris) + { + item("solaris"); + item("bsd"); + } + } + arrayEnd(); + + propertyStart("architectures"); + arrayStart(); + if (global.params.is64bit) + item("x86_64"); + else + version(X86) item("x86"); + arrayEnd(); + + propertyStart("predefinedVersions"); + arrayStart(); + if (global.versionids) + { + foreach (const versionid; *global.versionids) + { + item(versionid.toChars()); + } + } + arrayEnd(); + propertyBool("supportsIncludeImports", true); objectEnd(); } @@ -839,18 +916,50 @@ public: private void generateBuildInfo() { objectStart(); - property("cwd", getcwd(null, 0)); - property("config", global.inifilename ? global.inifilename : null); - if (global.params.lib) { - property("library", global.params.libname); - } + requiredProperty("cwd", getcwd(null, 0)); + requiredProperty("argv0", global.params.argv0); + requiredProperty("config", global.inifilename); + requiredProperty("libName", global.params.libname); + propertyStart("importPaths"); arrayStart(); - foreach (importPath; *global.params.imppath) + if (global.params.imppath) { - item(importPath); + foreach (importPath; *global.params.imppath) + { + item(importPath); + } + } + arrayEnd(); + + propertyStart("objectFiles"); + arrayStart(); + foreach (objfile; global.params.objfiles) + { + item(objfile); } arrayEnd(); + + propertyStart("libraryFiles"); + arrayStart(); + foreach (lib; global.params.libfiles) + { + item(lib); + } + arrayEnd(); + + propertyStart("ddocFiles"); + arrayStart(); + foreach (ddocFile; global.params.ddocfiles) + { + item(ddocFile); + } + arrayEnd(); + + requiredProperty("mapFile", global.params.mapfile); + requiredProperty("resourceFile", global.params.resfile); + requiredProperty("defFile", global.params.deffile); + objectEnd(); } @@ -867,9 +976,8 @@ public: foreach (m; Module.amodules) { objectStart(); - if(m.md) - property("name", m.md.toChars()); - property("file", m.srcfile.toChars()); + requiredProperty("name", m.md ? m.md.toChars() : null); + requiredProperty("file", m.srcfile.toChars()); propertyBool("isRoot", m.isRoot()); if(m.contentImportedFiles.dim > 0) { @@ -968,3 +1076,20 @@ JsonFieldFlags tryParseJsonField(const(char)* fieldName) } return JsonFieldFlags.none; } + +/** +Determines and returns the compiler interface which is one of `dmd`, `ldc`, +`gdc` or `sdc`. Returns `null` if no interface can be determined. +*/ +private const(char)* determineCompilerInterface() +{ + if (!strcmp(global.compiler.vendor, "Digital Mars D")) + return "dmd"; + if (!strcmp(global.compiler.vendor, "LDC")) + return "ldc"; + if (!strcmp(global.compiler.vendor, "GNU")) + return "gdc"; + if (!strcmp(global.compiler.vendor, "SDC")) + return "sdc"; + return null; +} diff --git a/src/dmd/lexer.d b/src/dmd/lexer.d index ab55746dc441..841dfe9b56b3 100644 --- a/src/dmd/lexer.d +++ b/src/dmd/lexer.d @@ -517,27 +517,8 @@ class Lexer } else if (id == Id.VERSIONX) { - uint major = 0; - uint minor = 0; - bool point = false; - for (const(char)* p = global._version + 1; 1; p++) - { - 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; - } t.value = TOK.int64Literal; - t.unsvalue = major * 1000 + minor; + t.unsvalue = global.versionNumber(); } else if (id == Id.EOFX) { diff --git a/test/compilable/extra-files/json2.out b/test/compilable/extra-files/json2.out index a927a46f0684..e639f665d240 100644 --- a/test/compilable/extra-files/json2.out +++ b/test/compilable/extra-files/json2.out @@ -1,16 +1,40 @@ { "buildInfo": { + "argv0": "VALUE_REMOVED_FOR_TEST", "config": "VALUE_REMOVED_FOR_TEST", "cwd": "VALUE_REMOVED_FOR_TEST", + "ddocFiles": [], + "defFile": null, "importPaths": [ "compilable", "../../druntime/import", "../../phobos" - ] + ], + "libName": "VALUE_REMOVED_FOR_TEST", + "libraryFiles": [ + "VALUES_REMOVED_FOR_TEST" + ], + "mapFile": "VALUE_REMOVED_FOR_TEST", + "objectFiles": [ + "VALUES_REMOVED_FOR_TEST" + ], + "resourceFile": null }, "compilerInfo": { - "binary": "VALUE_REMOVED_FOR_TEST", + "__VERSION__": 0, + "architectures": [ + "VALUES_REMOVED_FOR_TEST" + ], + "interface": "dmd", + "platforms": [ + "VALUES_REMOVED_FOR_TEST" + ], + "predefinedVersions": [ + "VALUES_REMOVED_FOR_TEST" + ], + "size_t": 0, "supportsIncludeImports": true, + "vendor": "VALUE_REMOVED_FOR_TEST", "version": "VALUE_REMOVED_FOR_TEST" }, "modules": [ @@ -32,7 +56,8 @@ "modules": [ { "file": "compilable/json2.d", - "isRoot": true + "isRoot": true, + "name": null }, { "file": "compilable/json.d", diff --git a/test/compilable/extra-files/jsonCompilerInfo.out b/test/compilable/extra-files/jsonCompilerInfo.out index c841853fa0d0..a6349e5d3ac4 100644 --- a/test/compilable/extra-files/jsonCompilerInfo.out +++ b/test/compilable/extra-files/jsonCompilerInfo.out @@ -1,7 +1,19 @@ { "compilerInfo": { - "binary": "VALUE_REMOVED_FOR_TEST", + "__VERSION__": 0, + "architectures": [ + "VALUES_REMOVED_FOR_TEST" + ], + "interface": "dmd", + "platforms": [ + "VALUES_REMOVED_FOR_TEST" + ], + "predefinedVersions": [ + "VALUES_REMOVED_FOR_TEST" + ], + "size_t": 0, "supportsIncludeImports": true, + "vendor": "VALUE_REMOVED_FOR_TEST", "version": "VALUE_REMOVED_FOR_TEST" } } \ No newline at end of file diff --git a/test/compilable/extra-files/json_nosource.out b/test/compilable/extra-files/json_nosource.out index c841853fa0d0..a6349e5d3ac4 100644 --- a/test/compilable/extra-files/json_nosource.out +++ b/test/compilable/extra-files/json_nosource.out @@ -1,7 +1,19 @@ { "compilerInfo": { - "binary": "VALUE_REMOVED_FOR_TEST", + "__VERSION__": 0, + "architectures": [ + "VALUES_REMOVED_FOR_TEST" + ], + "interface": "dmd", + "platforms": [ + "VALUES_REMOVED_FOR_TEST" + ], + "predefinedVersions": [ + "VALUES_REMOVED_FOR_TEST" + ], + "size_t": 0, "supportsIncludeImports": true, + "vendor": "VALUE_REMOVED_FOR_TEST", "version": "VALUE_REMOVED_FOR_TEST" } } \ No newline at end of file diff --git a/test/sanitize_json.d b/test/sanitize_json.d index 4bbbdde5a37b..761f6487db5e 100644 --- a/test/sanitize_json.d +++ b/test/sanitize_json.d @@ -83,7 +83,7 @@ void sanitize(JSONValue root) void removeString(JSONValue* value) { - assert(value.type == JSON_TYPE.STRING); + assert(value.type == JSON_TYPE.STRING || value.type == JSON_TYPE.NULL); *value = JSONValue("VALUE_REMOVED_FOR_TEST"); } void removeNumber(JSONValue* value) @@ -96,17 +96,28 @@ void removeStringIfExists(JSONValue* value) if (value !is null) removeString(value); } +void removeArray(JSONValue* value) +{ + assert(value.type == JSON_TYPE.ARRAY); + *value = JSONValue([JSONValue("VALUES_REMOVED_FOR_TEST")]); +} void sanitizeCompilerInfo(ref JSONValue[string] buildInfo) { - removeString(&buildInfo["binary"]); removeString(&buildInfo["version"]); + removeNumber(&buildInfo["__VERSION__"]); + removeString(&buildInfo["vendor"]); + removeNumber(&buildInfo["size_t"]); + removeArray(&buildInfo["platforms"]); + removeArray(&buildInfo["architectures"]); + removeArray(&buildInfo["predefinedVersions"]); } void sanitizeBuildInfo(ref JSONValue[string] buildInfo) { removeString(&buildInfo["cwd"]); - removeStringIfExists("config" in buildInfo); - removeStringIfExists("lib" in buildInfo); + removeString(&buildInfo["argv0"]); + removeString(&buildInfo["config"]); + removeString(&buildInfo["libName"]); { auto importPaths = buildInfo["importPaths"].array; foreach(ref path; importPaths) @@ -114,6 +125,9 @@ void sanitizeBuildInfo(ref JSONValue[string] buildInfo) path = JSONValue(normalizeFile(path.str)); } } + removeArray(&buildInfo["objectFiles"]); + removeArray(&buildInfo["libraryFiles"]); + removeString(&buildInfo["mapFile"]); } void sanitizeSyntaxNode(ref JSONValue value) {