@@ -157,7 +157,7 @@ Compiler::paintAsType (UnionExp *, Expression *expr, Type *type)
- core.stdc.*: For all gcc library builtins. */
void
-Compiler::loadModule (Module *m)
+Compiler::onParseModule (Module *m)
{
ModuleDeclaration *md = m->md;
@@ -180,3 +180,13 @@ Compiler::loadModule (Module *m)
d_add_builtin_module (m);
}
}
+
+/* A callback function that is called once an imported module is parsed.
+ If the callback returns true, then it tells the front-end that the
+ driver intends on compiling the import. */
+
+bool
+Compiler::onImport (Module *)
+{
+ return false;
+}
@@ -980,7 +980,6 @@ d_parse_file (void)
m->importedFrom = m;
m->parse ();
- Compiler::loadModule (m);
if (m->isDocFile)
{
@@ -1,4 +1,4 @@
-3a7ebef73cc01d4a877a95cf95cd3776c9e3ee66
+609c3ce2d5d5d8a3dc4ba12c5e6e1100873f9ed1
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
@@ -27,12 +27,17 @@ extern Module *entrypoint;
// Module in which the D main is
extern Module *rootHasMain;
+extern bool includeImports;
+// array of module patterns used to include/exclude imported modules
+extern Array<const char*> includeModulePatterns;
+extern Array<Module *> compiledImports;
+
struct Compiler
{
// CTFE support for cross-compilation.
static Expression *paintAsType(UnionExp *, Expression *, Type *);
// Backend
- static void loadModule(Module *);
static void genCmain(Scope *);
static bool onImport(Module *);
+ static void onParseModule(Module *);
};
@@ -145,6 +145,20 @@ int Declaration::checkModify(Loc loc, Scope *sc, Type *, Expression *e1, int fla
}
}
+ if (e1 && e1->op == TOKthis && isField())
+ {
+ VarDeclaration *vthis = e1->isThisExp()->var;
+ for (Scope *scx = sc; scx; scx = scx->enclosing)
+ {
+ if (scx->func == vthis->parent && (scx->flags & SCOPEcontract))
+ {
+ if (!flag)
+ error(loc, "cannot modify parameter `this` in contract");
+ return 2; // do not report type related errors
+ }
+ }
+ }
+
if (v && (isCtorinit() || isField()))
{
// It's only modifiable if inside the right constructor
@@ -375,8 +375,15 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident)
m = m->parse();
- Compiler::loadModule(m);
-
+ // Call onImport here because if the module is going to be compiled then we
+ // need to determine it early because it affects semantic analysis. This is
+ // being done after parsing the module so the full module name can be taken
+ // from whatever was declared in the file.
+ if (!m->isRoot() && Compiler::onImport(m))
+ {
+ m->importedFrom = m;
+ assert(m->isRoot());
+ }
return m;
}
@@ -736,6 +743,7 @@ Module *Module::parse()
// Add to global array of all modules
amodules.push(this);
}
+ Compiler::onParseModule(this);
return this;
}
@@ -3344,6 +3344,13 @@ public:
return setError();
}
+ // https://issues.dlang.org/show_bug.cgi?id=18719
+ // If `exp` is a call expression to another constructor
+ // then it means that all struct/class fields will be
+ // initialized after this call.
+ for (size_t i = 0; i < sc->fieldinit_dim; i++)
+ sc->fieldinit[i] |= CSXthis_ctor;
+
if (!sc->intypeof && !(sc->callSuper & CSXhalt))
{
if (sc->noctor || sc->callSuper & CSXlabel)
@@ -2181,7 +2181,6 @@ void FuncDeclaration::semantic3(Scope *sc)
sc2->flags = (sc2->flags & ~SCOPEcontract) | SCOPErequire;
// BUG: need to error if accessing out parameters
- // BUG: need to treat parameters as const
// BUG: need to disallow returns and throws
// BUG: verify that all in and ref parameters are read
freq = ::semantic(freq, sc2);
@@ -2213,7 +2212,6 @@ void FuncDeclaration::semantic3(Scope *sc)
sc2 = scout; //push
sc2->flags = (sc2->flags & ~SCOPEcontract) | SCOPEensure;
- // BUG: need to treat parameters as const
// BUG: need to disallow returns and throws
if (fensure && f->next->ty != Tvoid)
buildResultVar(scout, f->next);
@@ -28,9 +28,9 @@ struct Array
public:
Array()
{
- data.ptr = SMALLARRAYCAP ? &smallarray[0] : NULL;
+ data.ptr = NULL;
length = 0;
- data.length = SMALLARRAYCAP;
+ data.length = 0;
}
~Array()
new file mode 100644
@@ -0,0 +1,43 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail18143.d(20): Error: variable `fail18143.S.a` cannot modify parameter `this` in contract
+fail_compilation/fail18143.d(21): Error: variable `fail18143.S.a` cannot modify parameter `this` in contract
+fail_compilation/fail18143.d(25): Error: variable `fail18143.S.a` cannot modify parameter `this` in contract
+fail_compilation/fail18143.d(26): Error: variable `fail18143.S.a` cannot modify parameter `this` in contract
+fail_compilation/fail18143.d(35): Error: variable `fail18143.C.a` cannot modify parameter `this` in contract
+fail_compilation/fail18143.d(36): Error: variable `fail18143.C.a` cannot modify parameter `this` in contract
+fail_compilation/fail18143.d(40): Error: variable `fail18143.C.a` cannot modify parameter `this` in contract
+fail_compilation/fail18143.d(41): Error: variable `fail18143.C.a` cannot modify parameter `this` in contract
+---
+*/
+
+struct S
+{
+ int a;
+
+ this(int n)
+ in { a = n; } // error, modifying this.a in contract
+ out { a = n; } // error, modifying this.a in contract
+ do { }
+
+ void foo(int n)
+ in { a = n; } // error, modifying this.a in contract
+ out { a = n; } // error, modifying this.a in contract
+ do { }
+}
+
+class C
+{
+ int a;
+
+ this(int n)
+ in { a = n; } // error, modifying this.a in contract
+ out { a = n; } // error, modifying this.a in contract
+ do { }
+
+ void foo(int n)
+ in { a = n; } // error, modifying this.a in contract
+ out { a = n; } // error, modifying this.a in contract
+ do { }
+}
new file mode 100644
@@ -0,0 +1,41 @@
+// https://issues.dlang.org/show_bug.cgi?id=18719
+
+// REQUIRED_ARGS:
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail18719.d(30): Error: immutable field `x` initialized multiple times
+ Previous initialization is here.
+---
+*/
+
+struct S
+{
+ int x = -1;
+ this(int y) immutable
+ {
+ x = y;
+ import std.stdio;
+ writeln("Ctor called with ", y);
+ }
+ void opAssign(int) immutable;
+}
+
+class C
+{
+ S x;
+ this() immutable
+ {
+ this(42); /* Initializes x. */
+ x = 13; /* Breaking immutable, or ok? */
+ }
+ this(int x) immutable
+ {
+ this.x = x;
+ }
+}
+
+void main()
+{
+ new immutable C;
+}
@@ -1,4 +1,4 @@
-38873fe6ee70fe8e2b7a41b7c3663e090e27d61b
+3dd5df6864b3849450d3657e219b90909663a513
The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository.
@@ -39,6 +39,16 @@ version (unittest)
initializeTests();
}
+version (unittest) private bool clockSupported(ClockType c)
+{
+ // Skip unsupported clocks on older linux kernels, assume that only
+ // CLOCK_MONOTONIC and CLOCK_REALTIME exist, as that is the lowest
+ // common denominator supported by all versions of Linux pre-2.6.12.
+ version (Linux_Pre_2639)
+ return c == ClockType.normal || c == ClockType.precise;
+ else
+ return true;
+}
/++
Effectively a namespace to make it clear that the methods it contains are
@@ -95,10 +105,13 @@ public:
foreach (ct; AliasSeq!(ClockType.coarse, ClockType.precise, ClockType.second))
{
scope(failure) writefln("ClockType.%s", ct);
- auto value1 = Clock.currTime!ct;
- auto value2 = Clock.currTime!ct(UTC());
- assert(value1 <= value2, format("%s %s", value1, value2));
- assert(abs(value1 - value2) <= seconds(2));
+ static if (clockSupported(ct))
+ {
+ auto value1 = Clock.currTime!ct;
+ auto value2 = Clock.currTime!ct(UTC());
+ assert(value1 <= value2, format("%s %s (ClockType: %s)", value1, value2, ct));
+ assert(abs(value1 - value2) <= seconds(2), format("ClockType.%s", ct));
+ }
}
}
@@ -270,10 +283,13 @@ public:
foreach (ct; AliasSeq!(ClockType.coarse, ClockType.precise, ClockType.second))
{
scope(failure) writefln("ClockType.%s", ct);
- auto value1 = Clock.currStdTime!ct;
- auto value2 = Clock.currStdTime!ct;
- assert(value1 <= value2, format("%s %s", value1, value2));
- assert(abs(value1 - value2) <= limit);
+ static if (clockSupported(ct))
+ {
+ auto value1 = Clock.currStdTime!ct;
+ auto value2 = Clock.currStdTime!ct;
+ assert(value1 <= value2, format("%s %s (ClockType: %s)", value1, value2, ct));
+ assert(abs(value1 - value2) <= limit);
+ }
}
}
@@ -164,6 +164,16 @@ class FileException : Exception
+/
immutable uint errno;
+ private this(in char[] name, in char[] msg, string file, size_t line, uint errno) @safe pure
+ {
+ if (msg.empty)
+ super(name.idup, file, line);
+ else
+ super(text(name, ": ", msg), file, line);
+
+ this.errno = errno;
+ }
+
/++
Constructor which takes an error message.
@@ -175,12 +185,7 @@ class FileException : Exception
+/
this(in char[] name, in char[] msg, string file = __FILE__, size_t line = __LINE__) @safe pure
{
- if (msg.empty)
- super(name.idup, file, line);
- else
- super(text(name, ": ", msg), file, line);
-
- errno = 0;
+ this(name, msg, file, line, 0);
}
/++
@@ -200,8 +205,7 @@ class FileException : Exception
string file = __FILE__,
size_t line = __LINE__) @safe
{
- this(name, sysErrorString(errno), file, line);
- this.errno = errno;
+ this(name, sysErrorString(errno), file, line, errno);
}
else version (Posix) this(in char[] name,
uint errno = .errno,
@@ -209,8 +213,7 @@ class FileException : Exception
size_t line = __LINE__) @trusted
{
import std.exception : errnoString;
- this(name, errnoString(errno), file, line);
- this.errno = errno;
+ this(name, errnoString(errno), file, line, errno);
}
}
@@ -37,48 +37,55 @@ else version (CRuntime_DigitalMars)
// Specific to the way Digital Mars C does stdio
version = DIGITAL_MARS_STDIO;
}
-
-version (CRuntime_Glibc)
+else version (CRuntime_Glibc)
{
// Specific to the way Gnu C does stdio
version = GCC_IO;
- version = HAS_GETDELIM;
}
else version (CRuntime_Bionic)
{
version = GENERIC_IO;
- version = HAS_GETDELIM;
}
else version (CRuntime_Musl)
{
version = GENERIC_IO;
- version = HAS_GETDELIM;
}
-
-version (OSX)
+else version (CRuntime_UClibc)
+{
+ // uClibc supports GCC IO
+ version = GCC_IO;
+}
+else version (OSX)
+{
+ version = GENERIC_IO;
+}
+else version (iOS)
+{
+ version = GENERIC_IO;
+}
+else version (TVOS)
+{
+ version = GENERIC_IO;
+}
+else version (WatchOS)
{
version = GENERIC_IO;
- version = HAS_GETDELIM;
}
else version (FreeBSD)
{
version = GENERIC_IO;
- version = HAS_GETDELIM;
}
else version (NetBSD)
{
version = GENERIC_IO;
- version = HAS_GETDELIM;
}
else version (DragonFlyBSD)
{
version = GENERIC_IO;
- version = HAS_GETDELIM;
}
else version (Solaris)
{
version = GENERIC_IO;
- version = NO_GETDELIM;
}
// Character type used for operating system filesystem APIs
@@ -105,6 +112,11 @@ version (Windows)
import core.sys.windows.windows : HANDLE;
}
+version (Posix)
+{
+ static import core.sys.posix.stdio; // getdelim
+}
+
version (DIGITAL_MARS_STDIO)
{
extern (C)
@@ -244,11 +256,19 @@ else
static assert(0, "unsupported C I/O system");
}
-version (HAS_GETDELIM) extern(C) nothrow @nogc
+static if (__traits(compiles, core.sys.posix.stdio.getdelim))
{
- ptrdiff_t getdelim(char**, size_t*, int, FILE*);
- // getline() always comes together with getdelim()
- ptrdiff_t getline(char**, size_t*, FILE*);
+ extern(C) nothrow @nogc
+ {
+ // @@@DEPRECATED_2.104@@@
+ deprecated("To be removed after 2.104. Use core.sys.posix.stdio.getdelim instead.")
+ ptrdiff_t getdelim(char**, size_t*, int, FILE*);
+
+ // @@@DEPRECATED_2.104@@@
+ // getline() always comes together with getdelim()
+ deprecated("To be removed after 2.104. Use core.sys.posix.stdio.getline instead.")
+ ptrdiff_t getline(char**, size_t*, FILE*);
+ }
}
//------------------------------------------------------------------------------
@@ -4718,59 +4738,142 @@ private struct ReadlnAppender
}
// Private implementation of readln
-version (DIGITAL_MARS_STDIO)
-private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orientation /*ignored*/)
+private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orientation orientation)
{
- FLOCK(fps);
- scope(exit) FUNLOCK(fps);
+ version (DIGITAL_MARS_STDIO)
+ {
+ FLOCK(fps);
+ scope(exit) FUNLOCK(fps);
- /* Since fps is now locked, we can create an "unshared" version
- * of fp.
- */
- auto fp = cast(_iobuf*) fps;
+ /* Since fps is now locked, we can create an "unshared" version
+ * of fp.
+ */
+ auto fp = cast(_iobuf*) fps;
- ReadlnAppender app;
- app.initialize(buf);
+ ReadlnAppender app;
+ app.initialize(buf);
- if (__fhnd_info[fp._file] & FHND_WCHAR)
- { /* Stream is in wide characters.
- * Read them and convert to chars.
- */
- static assert(wchar_t.sizeof == 2);
- for (int c = void; (c = FGETWC(fp)) != -1; )
+ if (__fhnd_info[fp._file] & FHND_WCHAR)
+ { /* Stream is in wide characters.
+ * Read them and convert to chars.
+ */
+ static assert(wchar_t.sizeof == 2);
+ for (int c = void; (c = FGETWC(fp)) != -1; )
+ {
+ if ((c & ~0x7F) == 0)
+ {
+ app.putchar(cast(char) c);
+ if (c == terminator)
+ break;
+ }
+ else
+ {
+ if (c >= 0xD800 && c <= 0xDBFF)
+ {
+ int c2 = void;
+ if ((c2 = FGETWC(fp)) != -1 ||
+ c2 < 0xDC00 && c2 > 0xDFFF)
+ {
+ StdioException("unpaired UTF-16 surrogate");
+ }
+ c = ((c - 0xD7C0) << 10) + (c2 - 0xDC00);
+ }
+ app.putdchar(cast(dchar) c);
+ }
+ }
+ if (ferror(fps))
+ StdioException();
+ }
+
+ else if (fp._flag & _IONBF)
{
- if ((c & ~0x7F) == 0)
+ /* Use this for unbuffered I/O, when running
+ * across buffer boundaries, or for any but the common
+ * cases.
+ */
+ L1:
+ int c;
+ while ((c = FGETC(fp)) != -1)
{
app.putchar(cast(char) c);
if (c == terminator)
- break;
+ {
+ buf = app.data;
+ return buf.length;
+ }
+
}
- else
- {
- if (c >= 0xD800 && c <= 0xDBFF)
+
+ if (ferror(fps))
+ StdioException();
+ }
+ else
+ {
+ int u = fp._cnt;
+ char* p = fp._ptr;
+ int i;
+ if (fp._flag & _IOTRAN)
+ { /* Translated mode ignores \r and treats ^Z as end-of-file
+ */
+ char c;
+ while (1)
{
- int c2 = void;
- if ((c2 = FGETWC(fp)) != -1 ||
- c2 < 0xDC00 && c2 > 0xDFFF)
+ if (i == u) // if end of buffer
+ goto L1; // give up
+ c = p[i];
+ i++;
+ if (c != '\r')
{
- StdioException("unpaired UTF-16 surrogate");
+ if (c == terminator)
+ break;
+ if (c != 0x1A)
+ continue;
+ goto L1;
+ }
+ else
+ { if (i != u && p[i] == terminator)
+ break;
+ goto L1;
}
- c = ((c - 0xD7C0) << 10) + (c2 - 0xDC00);
}
- app.putdchar(cast(dchar) c);
+ app.putonly(p[0 .. i]);
+ app.buf[i - 1] = cast(char) terminator;
+ if (terminator == '\n' && c == '\r')
+ i++;
}
+ else
+ {
+ while (1)
+ {
+ if (i == u) // if end of buffer
+ goto L1; // give up
+ auto c = p[i];
+ i++;
+ if (c == terminator)
+ break;
+ }
+ app.putonly(p[0 .. i]);
+ }
+ fp._cnt -= i;
+ fp._ptr += i;
}
- if (ferror(fps))
- StdioException();
- }
- else if (fp._flag & _IONBF)
+ buf = app.data;
+ return buf.length;
+ }
+ else version (MICROSOFT_STDIO)
{
- /* Use this for unbuffered I/O, when running
- * across buffer boundaries, or for any but the common
- * cases.
+ FLOCK(fps);
+ scope(exit) FUNLOCK(fps);
+
+ /* Since fps is now locked, we can create an "unshared" version
+ * of fp.
*/
- L1:
+ auto fp = cast(_iobuf*) fps;
+
+ ReadlnAppender app;
+ app.initialize(buf);
+
int c;
while ((c = FGETC(fp)) != -1)
{
@@ -4785,295 +4888,208 @@ private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orie
if (ferror(fps))
StdioException();
+ buf = app.data;
+ return buf.length;
}
- else
+ else static if (__traits(compiles, core.sys.posix.stdio.getdelim))
{
- int u = fp._cnt;
- char* p = fp._ptr;
- int i;
- if (fp._flag & _IOTRAN)
- { /* Translated mode ignores \r and treats ^Z as end-of-file
+ import core.stdc.stdlib : free;
+ import core.stdc.wchar_ : fwide;
+
+ if (orientation == File.Orientation.wide)
+ {
+ /* Stream is in wide characters.
+ * Read them and convert to chars.
*/
- char c;
- while (1)
+ FLOCK(fps);
+ scope(exit) FUNLOCK(fps);
+ auto fp = cast(_iobuf*) fps;
+ version (Windows)
{
- if (i == u) // if end of buffer
- goto L1; // give up
- c = p[i];
- i++;
- if (c != '\r')
+ buf.length = 0;
+ for (int c = void; (c = FGETWC(fp)) != -1; )
{
- if (c == terminator)
- break;
- if (c != 0x1A)
- continue;
- goto L1;
+ if ((c & ~0x7F) == 0)
+ { buf ~= c;
+ if (c == terminator)
+ break;
+ }
+ else
+ {
+ if (c >= 0xD800 && c <= 0xDBFF)
+ {
+ int c2 = void;
+ if ((c2 = FGETWC(fp)) != -1 ||
+ c2 < 0xDC00 && c2 > 0xDFFF)
+ {
+ StdioException("unpaired UTF-16 surrogate");
+ }
+ c = ((c - 0xD7C0) << 10) + (c2 - 0xDC00);
+ }
+ import std.utf : encode;
+ encode(buf, c);
+ }
}
- else
- { if (i != u && p[i] == terminator)
+ if (ferror(fp))
+ StdioException();
+ return buf.length;
+ }
+ else version (Posix)
+ {
+ buf.length = 0;
+ for (int c; (c = FGETWC(fp)) != -1; )
+ {
+ import std.utf : encode;
+
+ if ((c & ~0x7F) == 0)
+ buf ~= cast(char) c;
+ else
+ encode(buf, cast(dchar) c);
+ if (c == terminator)
break;
- goto L1;
}
+ if (ferror(fps))
+ StdioException();
+ return buf.length;
+ }
+ else
+ {
+ static assert(0);
}
- app.putonly(p[0 .. i]);
- app.buf[i - 1] = cast(char) terminator;
- if (terminator == '\n' && c == '\r')
- i++;
}
- else
+
+ static char *lineptr = null;
+ static size_t n = 0;
+ scope(exit)
{
- while (1)
+ if (n > 128 * 1024)
{
- if (i == u) // if end of buffer
- goto L1; // give up
- auto c = p[i];
- i++;
- if (c == terminator)
- break;
+ // Bound memory used by readln
+ free(lineptr);
+ lineptr = null;
+ n = 0;
}
- app.putonly(p[0 .. i]);
}
- fp._cnt -= i;
- fp._ptr += i;
- }
-
- buf = app.data;
- return buf.length;
-}
-
-version (MICROSOFT_STDIO)
-private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orientation /*ignored*/)
-{
- FLOCK(fps);
- scope(exit) FUNLOCK(fps);
-
- /* Since fps is now locked, we can create an "unshared" version
- * of fp.
- */
- auto fp = cast(_iobuf*) fps;
-
- ReadlnAppender app;
- app.initialize(buf);
- int c;
- while ((c = FGETC(fp)) != -1)
- {
- app.putchar(cast(char) c);
- if (c == terminator)
+ auto s = core.sys.posix.stdio.getdelim(&lineptr, &n, terminator, fps);
+ if (s < 0)
{
- buf = app.data;
- return buf.length;
+ if (ferror(fps))
+ StdioException();
+ buf.length = 0; // end of file
+ return 0;
}
+ if (s <= buf.length)
+ {
+ buf = buf[0 .. s];
+ buf[] = lineptr[0 .. s];
+ }
+ else
+ {
+ buf = lineptr[0 .. s].dup;
+ }
+ return s;
}
-
- if (ferror(fps))
- StdioException();
- buf = app.data;
- return buf.length;
-}
-
-version (HAS_GETDELIM)
-private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orientation orientation)
-{
- import core.stdc.stdlib : free;
- import core.stdc.wchar_ : fwide;
-
- if (orientation == File.Orientation.wide)
+ else // version (NO_GETDELIM)
{
- /* Stream is in wide characters.
- * Read them and convert to chars.
- */
+ import core.stdc.wchar_ : fwide;
+
FLOCK(fps);
scope(exit) FUNLOCK(fps);
auto fp = cast(_iobuf*) fps;
- version (Windows)
+ if (orientation == File.Orientation.wide)
{
- buf.length = 0;
- for (int c = void; (c = FGETWC(fp)) != -1; )
+ /* Stream is in wide characters.
+ * Read them and convert to chars.
+ */
+ version (Windows)
{
- if ((c & ~0x7F) == 0)
- { buf ~= c;
- if (c == terminator)
- break;
- }
- else
+ buf.length = 0;
+ for (int c; (c = FGETWC(fp)) != -1; )
{
- if (c >= 0xD800 && c <= 0xDBFF)
+ if ((c & ~0x7F) == 0)
+ { buf ~= c;
+ if (c == terminator)
+ break;
+ }
+ else
{
- int c2 = void;
- if ((c2 = FGETWC(fp)) != -1 ||
- c2 < 0xDC00 && c2 > 0xDFFF)
+ if (c >= 0xD800 && c <= 0xDBFF)
{
- StdioException("unpaired UTF-16 surrogate");
+ int c2 = void;
+ if ((c2 = FGETWC(fp)) != -1 ||
+ c2 < 0xDC00 && c2 > 0xDFFF)
+ {
+ StdioException("unpaired UTF-16 surrogate");
+ }
+ c = ((c - 0xD7C0) << 10) + (c2 - 0xDC00);
}
- c = ((c - 0xD7C0) << 10) + (c2 - 0xDC00);
+ import std.utf : encode;
+ encode(buf, c);
}
- import std.utf : encode;
- encode(buf, c);
}
+ if (ferror(fp))
+ StdioException();
+ return buf.length;
}
- if (ferror(fp))
- StdioException();
- return buf.length;
- }
- else version (Posix)
- {
- buf.length = 0;
- for (int c; (c = FGETWC(fp)) != -1; )
+ else version (Posix)
{
import std.utf : encode;
-
- if ((c & ~0x7F) == 0)
- buf ~= cast(char) c;
- else
- encode(buf, cast(dchar) c);
- if (c == terminator)
- break;
- }
- if (ferror(fps))
- StdioException();
- return buf.length;
- }
- else
- {
- static assert(0);
- }
- }
-
- static char *lineptr = null;
- static size_t n = 0;
- scope(exit)
- {
- if (n > 128 * 1024)
- {
- // Bound memory used by readln
- free(lineptr);
- lineptr = null;
- n = 0;
- }
- }
-
- auto s = getdelim(&lineptr, &n, terminator, fps);
- if (s < 0)
- {
- if (ferror(fps))
- StdioException();
- buf.length = 0; // end of file
- return 0;
- }
-
- if (s <= buf.length)
- {
- buf = buf[0 .. s];
- buf[] = lineptr[0 .. s];
- }
- else
- {
- buf = lineptr[0 .. s].dup;
- }
- return s;
-}
-
-version (NO_GETDELIM)
-private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orientation orientation)
-{
- import core.stdc.wchar_ : fwide;
-
- FLOCK(fps);
- scope(exit) FUNLOCK(fps);
- auto fp = cast(_iobuf*) fps;
- if (orientation == File.Orientation.wide)
- {
- /* Stream is in wide characters.
- * Read them and convert to chars.
- */
- version (Windows)
- {
- buf.length = 0;
- for (int c; (c = FGETWC(fp)) != -1; )
- {
- if ((c & ~0x7F) == 0)
- { buf ~= c;
+ buf.length = 0;
+ for (int c; (c = FGETWC(fp)) != -1; )
+ {
+ if ((c & ~0x7F) == 0)
+ buf ~= cast(char) c;
+ else
+ encode(buf, cast(dchar) c);
if (c == terminator)
break;
}
- else
- {
- if (c >= 0xD800 && c <= 0xDBFF)
- {
- int c2 = void;
- if ((c2 = FGETWC(fp)) != -1 ||
- c2 < 0xDC00 && c2 > 0xDFFF)
- {
- StdioException("unpaired UTF-16 surrogate");
- }
- c = ((c - 0xD7C0) << 10) + (c2 - 0xDC00);
- }
- import std.utf : encode;
- encode(buf, c);
- }
+ if (ferror(fps))
+ StdioException();
+ return buf.length;
}
- if (ferror(fp))
- StdioException();
- return buf.length;
- }
- else version (Posix)
- {
- import std.utf : encode;
- buf.length = 0;
- for (int c; (c = FGETWC(fp)) != -1; )
+ else
{
- if ((c & ~0x7F) == 0)
- buf ~= cast(char) c;
- else
- encode(buf, cast(dchar) c);
- if (c == terminator)
- break;
+ static assert(0);
}
- if (ferror(fps))
- StdioException();
- return buf.length;
}
- else
- {
- static assert(0);
- }
- }
- // Narrow stream
- // First, fill the existing buffer
- for (size_t bufPos = 0; bufPos < buf.length; )
- {
- immutable c = FGETC(fp);
- if (c == -1)
- {
- buf.length = bufPos;
- goto endGame;
- }
- buf[bufPos++] = cast(char) c;
- if (c == terminator)
+ // Narrow stream
+ // First, fill the existing buffer
+ for (size_t bufPos = 0; bufPos < buf.length; )
{
- // No need to test for errors in file
- buf.length = bufPos;
- return bufPos;
+ immutable c = FGETC(fp);
+ if (c == -1)
+ {
+ buf.length = bufPos;
+ goto endGame;
+ }
+ buf[bufPos++] = cast(char) c;
+ if (c == terminator)
+ {
+ // No need to test for errors in file
+ buf.length = bufPos;
+ return bufPos;
+ }
}
- }
- // Then, append to it
- for (int c; (c = FGETC(fp)) != -1; )
- {
- buf ~= cast(char) c;
- if (c == terminator)
+ // Then, append to it
+ for (int c; (c = FGETC(fp)) != -1; )
{
- // No need to test for errors in file
- return buf.length;
+ buf ~= cast(char) c;
+ if (c == terminator)
+ {
+ // No need to test for errors in file
+ return buf.length;
+ }
}
- }
- endGame:
- if (ferror(fps))
- StdioException();
- return buf.length;
+ endGame:
+ if (ferror(fps))
+ StdioException();
+ return buf.length;
+ }
}
@system unittest
@@ -27,6 +27,12 @@ if { ![is-effective-target d_runtime_has_std_library] } {
# Gather a list of all tests.
set tests [lsort [filter_libphobos_unittests [find $srcdir/../src "*.d"]]]
+set version_flags ""
+
+if { [is-effective-target linux_pre_2639] } {
+ lappend version_flags "-fversion=Linux_Pre_2639"
+}
+
set libphobos_skip_tests {
# Skip curl tests if library is not available
{ libphobos.phobos/etc/c/curl.d { ! libcurl_available } }
@@ -39,7 +45,7 @@ dg-init
# Main loop.
foreach test $tests {
set libphobos_test_name "$subdir/[dg-trim-dirname $srcdir/../src $test]"
- dg-runtest $test "" "-fmain -fbuilding-libphobos-tests"
+ dg-runtest $test "" "-fmain -fbuilding-libphobos-tests $version_flags"
set libphobos_test_name ""
}
@@ -27,6 +27,12 @@ if { ![is-effective-target d_runtime_has_std_library] } {
# Gather a list of all tests.
set tests [lsort [filter_libphobos_unittests [find $srcdir/../src "*.d"]]]
+set version_flags ""
+
+if { [is-effective-target linux_pre_2639] } {
+ lappend version_flags "-fversion=Linux_Pre_2639"
+}
+
set libphobos_skip_tests {
# Skip curl tests if library is not available
{ libphobos.phobos_shared/etc/c/curl.d { ! libcurl_available } }
@@ -40,7 +46,7 @@ dg-init
foreach test $tests {
set libphobos_test_name "$subdir/[dg-trim-dirname $srcdir/../src $test]"
dg-runtest $test "-fversion=Shared -shared-libphobos" \
- "-fmain -fbuilding-libphobos-tests -fno-moduleinfo"
+ "-fmain -fbuilding-libphobos-tests -fno-moduleinfo $version_flags"
set libphobos_test_name ""
}