mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 21:21:48 +03:00
Moves the special handling of reading from stdin out of the semantic routines to the DMD driver itself. All references to `__stdin.d` have also been removed from the frontend implementation.
This commit is contained in:
parent
032e24446b
commit
02a64d2e13
8 changed files with 96 additions and 63 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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<const char* > modFileAliasStrings = Array<const char* >(), Array<ImportPathInfo > imppath = Array<ImportPathInfo >(), Array<const char* > fileImppath = Array<const char* >(), _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<const char* > runargs = Array<const char* >(), Array<const char* > cppswitches = Array<const char* >(), const char* cpp = nullptr, Array<const char* > objfiles = Array<const char* >(), Array<const char* > linkswitches = Array<const char* >(), Array<bool > linkswitchIsForCC = Array<bool >(), Array<const char* > libfiles = Array<const char* >(), Array<const char* > dllfiles = Array<const char* >(), _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<const char* > modFileAliasStrings = Array<const char* >(), Array<ImportPathInfo > imppath = Array<ImportPathInfo >(), Array<const char* > fileImppath = Array<const char* >(), _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<const char* > runargs = Array<const char* >(), Array<const char* > cppswitches = Array<const char* >(), const char* cpp = nullptr, Array<const char* > objfiles = Array<const char* >(), Array<const char* > linkswitches = Array<const char* >(), Array<bool > linkswitchIsForCC = Array<bool >(), Array<const char* > libfiles = Array<const char* >(), Array<const char* > dllfiles = Array<const char* >(), _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),
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
12
compiler/test/fail_compilation/fail21045.d
Normal file
12
compiler/test/fail_compilation/fail21045.d
Normal file
|
@ -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;
|
Loading…
Add table
Add a link
Reference in a new issue