diff --git a/compiler/src/dmd/dmodule.d b/compiler/src/dmd/dmodule.d index 6c7416856a..1d14c085d3 100644 --- a/compiler/src/dmd/dmodule.d +++ b/compiler/src/dmd/dmodule.d @@ -58,12 +58,10 @@ import dmd.visitor; version (Windows) { - import core.sys.windows.winbase : getpid = GetCurrentProcessId; enum PathSeparator = '\\'; } else version (Posix) { - import core.sys.posix.unistd : getpid; enum PathSeparator = '/'; } else @@ -577,12 +575,6 @@ extern (C++) final class Module : Package else { const(char)[] argdoc; - OutBuffer buf; - if (arg == "__stdin.d") - { - buf.printf("__stdin_%d.d", getpid()); - arg = buf[]; - } if (global.params.preservePaths) argdoc = arg; else diff --git a/compiler/src/dmd/file_manager.d b/compiler/src/dmd/file_manager.d index fc7824f039..8a6ec998e6 100644 --- a/compiler/src/dmd/file_manager.d +++ b/compiler/src/dmd/file_manager.d @@ -16,7 +16,6 @@ import dmd.root.stringtable : StringTable; import dmd.root.file : File, Buffer; import dmd.root.filename : FileName, isDirSeparator; import dmd.root.string : toDString; -import dmd.errors; import dmd.globals; import dmd.identifier; import dmd.location; @@ -184,9 +183,6 @@ nothrow: scope(exit) FileName.free(sdi.ptr); const sd = FileName.forceExt(filename, mars_ext); - // Special file name representing `stdin`, always assume its presence - if (sd == "__stdin.d") - return sd; if (checkLocal && FileName.exists(sd) == 1) return sd; scope(exit) FileName.free(sd.ptr); @@ -312,20 +308,12 @@ nothrow: if (auto val = files.lookup(name)) // if `name` is cached return val.value; // return its contents - OutBuffer buf; - if (name == "__stdin.d") // special name for reading from stdin - { - if (readFromStdin(buf)) - fatal(); - } - else - { - if (FileName.exists(name) != 1) // if not an ordinary file - return null; + if (FileName.exists(name) != 1) // if not an ordinary file + return null; - if (File.read(name, buf)) - return null; // failed - } + OutBuffer buf; + if (File.read(name, buf)) + return null; // failed buf.write32(0); // terminating dchar 0 @@ -351,36 +339,3 @@ nothrow: return val == null ? null : val.value; } } - -private bool readFromStdin(ref OutBuffer sink) nothrow -{ - import core.stdc.stdio; - import dmd.errors; - - enum BufIncrement = 128 * 1024; - - for (size_t j; 1; ++j) - { - char[] buffer = sink.allocate(BufIncrement); - - // Fill up buffer - size_t filled = 0; - do - { - filled += fread(buffer.ptr + filled, 1, buffer.length - filled, stdin); - if (ferror(stdin)) - { - import core.stdc.errno; - error(Loc.initial, "cannot read from stdin, errno = %d", errno); - return true; - } - if (feof(stdin)) // successful completion - { - sink.setsize(j * BufIncrement + filled); - return false; - } - } while (filled < BufIncrement); - } - - assert(0); -} diff --git a/compiler/src/dmd/frontend.h b/compiler/src/dmd/frontend.h index 437761d36c..730d53e489 100644 --- a/compiler/src/dmd/frontend.h +++ b/compiler/src/dmd/frontend.h @@ -8412,6 +8412,7 @@ struct ImportPathInfo final struct Param final { bool obj; + bool readStdin; bool multiobj; bool trace; bool tracegc; @@ -8499,6 +8500,7 @@ struct Param final bool parsingUnittestsRequired(); Param() : obj(true), + readStdin(), multiobj(), trace(), tracegc(), @@ -8577,8 +8579,9 @@ struct Param final timeTraceFile() { } - Param(bool obj, bool multiobj = false, bool trace = false, bool tracegc = false, bool vcg_ast = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool useUnitTests = false, bool useInline = false, bool release = false, bool preservePaths = false, DiagnosticReporting useWarnings = (DiagnosticReporting)2u, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool ignoreUnsupportedPragmas = true, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool useGC = true, bool betterC = false, bool addMain = false, bool allInst = false, bool bitfields = false, CppStdRevision cplusplus = (CppStdRevision)201103u, Help help = Help(), Verbose v = Verbose(), FeatureState useDIP25 = (FeatureState)2u, FeatureState useDIP1000 = (FeatureState)0u, bool ehnogc = false, bool useDIP1021 = false, FeatureState fieldwise = (FeatureState)0u, bool fixAliasThis = false, FeatureState rvalueRefParam = (FeatureState)0u, FeatureState safer = (FeatureState)0u, FeatureState noSharedAccess = (FeatureState)0u, bool previewIn = false, bool inclusiveInContracts = false, bool shortenedMethods = true, bool fixImmutableConv = false, bool fix16997 = true, FeatureState dtorFields = (FeatureState)0u, FeatureState systemVariables = (FeatureState)0u, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, CLIIdentifierTable dIdentifierTable = (CLIIdentifierTable)0u, CLIIdentifierTable cIdentifierTable = (CLIIdentifierTable)0u, _d_dynamicArray< const char > argv0 = {}, Array modFileAliasStrings = Array(), Array imppath = Array(), Array fileImppath = Array(), _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, Output ddoc = Output(), Output dihdr = Output(), Output cxxhdr = Output(), Output json = Output(), JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, Output makeDeps = Output(), Output mixinOut = Output(), Output moduleDeps = Output(), bool debugEnabled = false, bool run = false, Array runargs = Array(), Array cppswitches = Array(), const char* cpp = nullptr, Array objfiles = Array(), Array linkswitches = Array(), Array linkswitchIsForCC = Array(), Array libfiles = Array(), Array dllfiles = Array(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}, bool fullyQualifiedObjectFiles = false, bool timeTrace = false, uint32_t timeTraceGranularityUs = 500u, const char* timeTraceFile = nullptr) : + Param(bool obj, bool readStdin = false, bool multiobj = false, bool trace = false, bool tracegc = false, bool vcg_ast = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool useUnitTests = false, bool useInline = false, bool release = false, bool preservePaths = false, DiagnosticReporting useWarnings = (DiagnosticReporting)2u, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool ignoreUnsupportedPragmas = true, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool useGC = true, bool betterC = false, bool addMain = false, bool allInst = false, bool bitfields = false, CppStdRevision cplusplus = (CppStdRevision)201103u, Help help = Help(), Verbose v = Verbose(), FeatureState useDIP25 = (FeatureState)2u, FeatureState useDIP1000 = (FeatureState)0u, bool ehnogc = false, bool useDIP1021 = false, FeatureState fieldwise = (FeatureState)0u, bool fixAliasThis = false, FeatureState rvalueRefParam = (FeatureState)0u, FeatureState safer = (FeatureState)0u, FeatureState noSharedAccess = (FeatureState)0u, bool previewIn = false, bool inclusiveInContracts = false, bool shortenedMethods = true, bool fixImmutableConv = false, bool fix16997 = true, FeatureState dtorFields = (FeatureState)0u, FeatureState systemVariables = (FeatureState)0u, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, CLIIdentifierTable dIdentifierTable = (CLIIdentifierTable)0u, CLIIdentifierTable cIdentifierTable = (CLIIdentifierTable)0u, _d_dynamicArray< const char > argv0 = {}, Array modFileAliasStrings = Array(), Array imppath = Array(), Array fileImppath = Array(), _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, Output ddoc = Output(), Output dihdr = Output(), Output cxxhdr = Output(), Output json = Output(), JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, Output makeDeps = Output(), Output mixinOut = Output(), Output moduleDeps = Output(), bool debugEnabled = false, bool run = false, Array runargs = Array(), Array cppswitches = Array(), const char* cpp = nullptr, Array objfiles = Array(), Array linkswitches = Array(), Array linkswitchIsForCC = Array(), Array libfiles = Array(), Array dllfiles = Array(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}, bool fullyQualifiedObjectFiles = false, bool timeTrace = false, uint32_t timeTraceGranularityUs = 500u, const char* timeTraceFile = nullptr) : obj(obj), + readStdin(readStdin), multiobj(multiobj), trace(trace), tracegc(tracegc), diff --git a/compiler/src/dmd/globals.d b/compiler/src/dmd/globals.d index 900c554e5f..132683e624 100644 --- a/compiler/src/dmd/globals.d +++ b/compiler/src/dmd/globals.d @@ -160,6 +160,7 @@ extern (C++) struct ImportPathInfo { extern (C++) struct Param { bool obj = true; // write object file + bool readStdin; // saw "-" on command line, read source file from stdin bool multiobj; // break one object file into multiple ones bool trace; // insert profiling hooks bool tracegc; // instrument calls to 'new' diff --git a/compiler/src/dmd/globals.h b/compiler/src/dmd/globals.h index 69fe709f4b..59952a2c10 100644 --- a/compiler/src/dmd/globals.h +++ b/compiler/src/dmd/globals.h @@ -168,6 +168,7 @@ struct ImportPathInfo struct Param { d_bool obj; // write object file + d_bool readStdin; // read source file from stdin d_bool multiobj; // break one object file into multiple ones d_bool trace; // insert profiling hooks d_bool tracegc; // instrument calls to 'new' diff --git a/compiler/src/dmd/main.d b/compiler/src/dmd/main.d index 2d77d72575..cf3382a774 100644 --- a/compiler/src/dmd/main.d +++ b/compiler/src/dmd/main.d @@ -353,7 +353,7 @@ private int tryMain(size_t argc, const(char)** argv, ref Param params) { fatal(); } - if (files.length == 0) + if (files.length == 0 && !params.readStdin) { if (params.jsonFieldFlags) { diff --git a/compiler/src/dmd/mars.d b/compiler/src/dmd/mars.d index 17d6965f53..743caf79ba 100644 --- a/compiler/src/dmd/mars.d +++ b/compiler/src/dmd/mars.d @@ -59,6 +59,13 @@ import dmd.semantic3; import dmd.target; import dmd.utils; +version (Windows) + import core.sys.windows.winbase : getpid = GetCurrentProcessId; +else version (Posix) + import core.sys.posix.unistd : getpid; +else + static assert(0); + /** * Print DMD's logo on stdout */ @@ -1734,7 +1741,7 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param break; } if (runarg == "-") - files.push("__stdin.d"); + params.readStdin = true; else files.push(arguments[i + 1]); params.runargs.setDim(length - 1); @@ -1751,7 +1758,7 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param } } else if (p[1] == '\0') - files.push("__stdin.d"); + params.readStdin = true; else { Lerror: @@ -1937,10 +1944,38 @@ bool createModules(ref Strings files, ref Strings libmodules, ref Param params, modules.push(m); if (firstmodule) { - global.params.objfiles.push(m.objfile.toChars()); + params.objfiles.push(m.objfile.toChars()); firstmodule = false; } } + + // Special module representing `stdin` + if (params.readStdin) + { + Module m; + if (createModule("__stdin.d", libmodules, params, target, eSink, m)) + return true; + if (m is null) + return false; + + modules.push(m); + + // Set the source file contents of the module + OutBuffer buf; + buf.readFromStdin(); + m.src = cast(ubyte[])buf.extractSlice(); + + // Give unique outfile name + OutBuffer namebuf; + namebuf.printf("__stdin_%d", getpid()); + + auto filename = FileName.forceExt(namebuf.extractSlice(), target.obj_ext); + m.objfile = FileName(filename); + + if (firstmodule) + params.objfiles.push(m.objfile.toChars()); + } + return false; } @@ -1959,3 +1994,37 @@ Module moduleWithEmptyMain() result.semantic3(null); return result; } + +private void readFromStdin(ref OutBuffer sink) nothrow +{ + import core.stdc.stdio; + import dmd.errors; + + enum BufIncrement = 128 * 1024; + + for (size_t j; 1; ++j) + { + char[] buffer = sink.allocate(BufIncrement + 16); + + // Fill up buffer + size_t filled = 0; + do + { + filled += fread(buffer.ptr + filled, 1, buffer.length - filled, stdin); + if (ferror(stdin)) + { + import core.stdc.errno; + error(Loc.initial, "cannot read from stdin, errno = %d", errno); + fatal(); + } + if (feof(stdin)) // successful completion + { + memset(buffer.ptr + filled, '\0', 16); + sink.setsize(j * BufIncrement + filled); + return; + } + } while (filled < BufIncrement); + } + + assert(0); +} diff --git a/compiler/test/fail_compilation/fail21045.d b/compiler/test/fail_compilation/fail21045.d new file mode 100644 index 0000000000..c43eda3f97 --- /dev/null +++ b/compiler/test/fail_compilation/fail21045.d @@ -0,0 +1,12 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/fail21045.d(12): Error: unable to read module `__stdin` +fail_compilation/fail21045.d(12): Expected '__stdin.d' or '__stdin/package.d' in one of the following import paths: +import path[0] = fail_compilation +import path[1] = $p:druntime/import$ +import path[2] = $p:phobos$ +--- +*/ + +import __stdin;