From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1698) id 2F276386F030; Mon, 21 Dec 2020 20:36:17 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2F276386F030 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Iain D Sandoe To: gcc-cvs@gcc.gnu.org Subject: [gcc(refs/users/iains/heads/d-for-darwin)] libphobos: Move getdelim declaration to druntime, fix stdio logic, add ucontext_t X-Act-Checkin: gcc X-Git-Author: Iain Buclaw X-Git-Refname: refs/users/iains/heads/d-for-darwin X-Git-Oldrev: 603c217f8af85c40a60f12221ce52609b16c7e63 X-Git-Newrev: cb227eb0d06ef529489f45656022badce54ae52c Message-Id: <20201221203617.2F276386F030@sourceware.org> Date: Mon, 21 Dec 2020 20:36:17 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 21 Dec 2020 20:36:17 -0000 https://gcc.gnu.org/g:cb227eb0d06ef529489f45656022badce54ae52c commit cb227eb0d06ef529489f45656022badce54ae52c Author: Iain Buclaw Date: Thu Dec 3 23:51:01 2020 +0100 libphobos: Move getdelim declaration to druntime, fix stdio logic, add ucontext_t Diff: --- libphobos/libdruntime/core/sys/posix/stdio.d | 194 +++++--- libphobos/libdruntime/core/sys/posix/ucontext.d | 25 + libphobos/src/std/stdio.d | 582 ++++++++++++------------ 3 files changed, 458 insertions(+), 343 deletions(-) diff --git a/libphobos/libdruntime/core/sys/posix/stdio.d b/libphobos/libdruntime/core/sys/posix/stdio.d index bc2329e6bf8..a47aec525e8 100644 --- a/libphobos/libdruntime/core/sys/posix/stdio.d +++ b/libphobos/libdruntime/core/sys/posix/stdio.d @@ -249,64 +249,72 @@ else version (Solaris) /* L_ctermid -char* ctermid(char*); -FILE* fdopen(int, in char*); -int fileno(FILE*); -int fseeko(FILE*, off_t, int); -off_t ftello(FILE*); -char* gets(char*); -int pclose(FILE*); -FILE* popen(in char*, in char*); +char* ctermid(char*); +FILE* fdopen(int, const scope char*); +int fileno(FILE*); +int fseeko(FILE*, off_t, int); +off_t ftello(FILE*); +ssize_t getdelim(char**, size_t*, int, FILE*); +ssize_t getline(char**, size_t*, FILE*); +char* gets(char*); +int pclose(FILE*); +FILE* popen(const scope char*, const scope char*); */ version (CRuntime_Glibc) { enum L_ctermid = 9; - static if ( __USE_FILE_OFFSET64 ) - { - int fseeko64(FILE*, off_t, int); - alias fseeko64 fseeko; - } - else - { - int fseeko(FILE*, off_t, int); - } - - static if ( __USE_FILE_OFFSET64 ) - { - off_t ftello64(FILE*); - alias ftello64 ftello; - } - else - { - off_t ftello(FILE*); - } + static if ( __USE_FILE_OFFSET64 ) + { + int fseeko64(FILE*, off_t, int); + alias fseeko64 fseeko; + } + else + { + int fseeko(FILE*, off_t, int); + } + + static if ( __USE_FILE_OFFSET64 ) + { + off_t ftello64(FILE*); + alias ftello64 ftello; + } + else + { + off_t ftello(FILE*); + } + + ssize_t getdelim(char**, size_t*, int, FILE*); + ssize_t getline(char**, size_t*, FILE*); } else version (CRuntime_UClibc) { enum L_ctermid = 9; enum L_cuserid = 9; - static if ( __USE_FILE_OFFSET64 ) - { - int fseeko64(FILE*, off_t, int); - alias fseeko64 fseeko; - } - else - { - int fseeko(FILE*, off_t, int); - } - - static if ( __USE_FILE_OFFSET64 ) - { - off_t ftello64(FILE*); - alias ftello64 ftello; - } - else - { - off_t ftello(FILE*); - } + static if ( __USE_FILE_OFFSET64 ) + { + int fseeko64(FILE*, off_t, int); + alias fseeko64 fseeko; + } + else + { + int fseeko(FILE*, off_t, int); + } + + static if ( __USE_FILE_OFFSET64 ) + { + off_t ftello64(FILE*); + alias ftello64 ftello; + } + else + { + off_t ftello(FILE*); + } + + ssize_t getdelim(char**, size_t*, int, FILE*); + ssize_t getline(char**, size_t*, FILE*); } else version (CRuntime_Musl) { @@ -331,6 +339,91 @@ else version (CRuntime_Musl) { off_t ftello(FILE*); } + + ssize_t getdelim(char**, size_t*, int, FILE*); + ssize_t getline(char**, size_t*, FILE*); +} +else version (CRuntime_Bionic) +{ + enum L_ctermid = 1024; + + static if ( __USE_FILE_OFFSET64 ) + { + int fseeko64(FILE*, off_t, int); + alias fseeko64 fseeko; + } + else + { + int fseeko(FILE*, off_t, int); + } + + static if ( __USE_FILE_OFFSET64 ) + { + off_t ftello64(FILE*); + alias ftello64 ftello; + } + else + { + off_t ftello(FILE*); + } + + ssize_t getdelim(char**, size_t*, int, FILE*); + ssize_t getline(char**, size_t*, FILE*); +} +else version (Darwin) +{ + enum L_ctermid = 1024; + + int fseeko(FILE*, off_t, int); + off_t ftello(FILE*); + + ssize_t getdelim(char**, size_t*, int, FILE*); + ssize_t getline(char**, size_t*, FILE*); +} +else version (FreeBSD) +{ + import core.sys.freebsd.config; + + enum L_ctermid = 1024; + + int fseeko(FILE*, off_t, int); + off_t ftello(FILE*); + + static if (__FreeBSD_version >= 800000) + { + ssize_t getdelim(char**, size_t*, int, FILE*); + ssize_t getline(char**, size_t*, FILE*); + } +} +else version (NetBSD) +{ + enum L_ctermid = 1024; + + int fseeko(FILE*, off_t, int); + off_t ftello(FILE*); + + ssize_t getdelim(char**, size_t*, int, FILE*); + ssize_t getline(char**, size_t*, FILE*); +} +else version (OpenBSD) +{ + enum L_ctermid = 1024; + + int fseeko(FILE*, off_t, int); + off_t ftello(FILE*); + + ssize_t getdelim(char**, size_t*, int, FILE*); + ssize_t getline(char**, size_t*, FILE*); +} +else version (DragonFlyBSD) +{ + enum L_ctermid = 1024; + + int fseeko(FILE*, off_t, int); + off_t ftello(FILE*); + + ssize_t getdelim(char**, size_t*, int, FILE*); + ssize_t getline(char**, size_t*, FILE*); } else version (Solaris) { @@ -356,6 +449,9 @@ else version (Solaris) { off_t ftello(FILE*); } + + ssize_t getdelim(char**, size_t*, int, FILE*); + ssize_t getline(char**, size_t*, FILE*); } else version (Posix) { @@ -366,8 +462,6 @@ else version (Posix) char* ctermid(char*); FILE* fdopen(int, in char*); int fileno(FILE*); -//int fseeko(FILE*, off_t, int); -//off_t ftello(FILE*); char* gets(char*); int pclose(FILE*); FILE* popen(in char*, in char*); @@ -546,7 +640,3 @@ unittest assert(memcmp(ptr, testdata.ptr, testdata.length*wchar_t.sizeof) == 0); assert(fclose(f) == 0); } - - -ssize_t getdelim (char** lineptr, size_t* n, int delimiter, FILE* stream); -ssize_t getline (char** lineptr, size_t* n, FILE* stream); diff --git a/libphobos/libdruntime/core/sys/posix/ucontext.d b/libphobos/libdruntime/core/sys/posix/ucontext.d index 2e518aefa84..ef74771a50d 100644 --- a/libphobos/libdruntime/core/sys/posix/ucontext.d +++ b/libphobos/libdruntime/core/sys/posix/ucontext.d @@ -23,6 +23,15 @@ extern (C): nothrow: @nogc: +version (OSX) + version = Darwin; +else version (iOS) + version = Darwin; +else version (TVOS) + version = Darwin; +else version (WatchOS) + version = Darwin; + version (MIPS32) version = MIPS_Any; version (MIPS64) version = MIPS_Any; version (PPC) version = PPC_Any; @@ -909,6 +918,22 @@ else version (CRuntime_Musl) else static assert(0, "unimplemented"); } +else version (Darwin) +{ + alias mcontext_t = void; + + struct ucontext + { + int uc_onstack; + sigset_t uc_sigmask; + stack_t uc_stack; + ucontext* uc_link; + size_t uc_mcsize; + mcontext_t* uc_mcontext; + } + + alias ucontext_t = ucontext; +} else version (FreeBSD) { // diff --git a/libphobos/src/std/stdio.d b/libphobos/src/std/stdio.d index 4c1ad0baa15..9265cc05170 100644 --- a/libphobos/src/std/stdio.d +++ b/libphobos/src/std/stdio.d @@ -42,43 +42,34 @@ 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 (OSX) { 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 +96,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 +240,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 +4722,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 +4872,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) + // Narrow stream + // First, fill the existing buffer + for (size_t bufPos = 0; bufPos < buf.length; ) { - 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; + 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