From b2dfd013b63358d5ca1e59c4384ab7374c58f0fc Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Wed, 5 Aug 2015 21:50:24 +0200 Subject: [PATCH 1/5] first support for VS2015 --- mak/SRCS | 1 + src/core/stdc/stdio.d | 61 +++------------- src/core/sys/windows/stdio_msvc12.d | 108 ++++++++++++++++++++++++++++ src/core/sys/windows/stdio_msvc14.d | 38 ++++++++++ src/rt/dmain2.d | 13 ++-- 5 files changed, 162 insertions(+), 59 deletions(-) create mode 100644 src/core/sys/windows/stdio_msvc12.d create mode 100644 src/core/sys/windows/stdio_msvc14.d diff --git a/mak/SRCS b/mak/SRCS index 703b86d961..7d8fe4e0be 100644 --- a/mak/SRCS +++ b/mak/SRCS @@ -73,6 +73,7 @@ SRCS=\ src\core\sys\windows\threadaux.d \ src\core\sys\windows\windows.d \ src\core\sys\windows\winsock2.d \ + src\core\sys\windows\stdio_msvc12.d \ \ src\gc\bits.d \ src\gc\config.d \ diff --git a/src/core/stdc/stdio.d b/src/core/stdc/stdio.d index e78034fda6..f099ab11ed 100644 --- a/src/core/stdc/stdio.d +++ b/src/core/stdc/stdio.d @@ -264,14 +264,7 @@ else version( CRuntime_Microsoft ) /// struct _iobuf { - char* _ptr; - int _cnt; - char* _base; - int _flag; - int _file; - int _charbuf; - int _bufsiz; - char* _tmpfname; + void* undefined; } /// @@ -571,10 +564,6 @@ else version( CRuntime_Microsoft ) extern shared void function() _fcloseallp; - private extern shared FILE[_NFILE] _iob; - - shared(FILE)* __iob_func(); - /// shared FILE* stdin; // = &__iob_func()[0]; /// @@ -942,18 +931,18 @@ else version( CRuntime_DigitalMars ) else version( CRuntime_Microsoft ) { // No unsafe pointer manipulation. - extern (D) @trusted + @trusted { /// - void rewind(FILE* stream) { fseek(stream,0L,SEEK_SET); stream._flag = stream._flag & ~_IOERR; } + void rewind(FILE* stream); /// - pure void clearerr(FILE* stream) { stream._flag = stream._flag & ~(_IOERR|_IOEOF); } + pure void clearerr(FILE* stream); /// - pure int feof(FILE* stream) { return stream._flag&_IOEOF; } + pure int feof(FILE* stream); /// - pure int ferror(FILE* stream) { return stream._flag&_IOERR; } + pure int ferror(FILE* stream); /// - pure int fileno(FILE* stream) { return stream._file; } + pure int fileno(FILE* stream); } /// int _snprintf(char* s, size_t n, in char* fmt, ...); @@ -966,42 +955,10 @@ else version( CRuntime_Microsoft ) alias _vsnprintf vsnprintf; /// - uint _set_output_format(uint format); - /// - enum _TWO_DIGIT_EXPONENT = 1; - - /// - int _filbuf(FILE *fp); - /// - int _flsbuf(int c, FILE *fp); - - /// - int _fputc_nolock(int c, FILE *fp) - { - fp._cnt = fp._cnt - 1; - if (fp._cnt >= 0) - { - *fp._ptr = cast(char)c; - fp._ptr = fp._ptr + 1; - return cast(char)c; - } - else - return _flsbuf(c, fp); - } + int _fputc_nolock(int c, FILE *fp); /// - int _fgetc_nolock(FILE *fp) - { - fp._cnt = fp._cnt - 1; - if (fp._cnt >= 0) - { - char c = *fp._ptr; - fp._ptr = fp._ptr + 1; - return c; - } - else - return _filbuf(fp); - } + int _fgetc_nolock(FILE *fp); /// int _lock_file(FILE *fp); diff --git a/src/core/sys/windows/stdio_msvc12.d b/src/core/sys/windows/stdio_msvc12.d new file mode 100644 index 0000000000..44e944fc2b --- /dev/null +++ b/src/core/sys/windows/stdio_msvc12.d @@ -0,0 +1,108 @@ +/** +* This module provides MS VC runtime helper function to be used +* with VS versions before VS 2015 +* +* Copyright: Copyright Digital Mars 2015. +* License: Distributed under the +* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). +* (See accompanying file LICENSE) +* Source: $(DRUNTIMESRC core/sys/windows/_stdio_msvc12.d) +* Authors: Rainer Schuetze +*/ + +module core.sys.windows.stdio_msvc12; + +version( CRuntime_Microsoft ): + +import core.stdc.stdio; + +extern (C): +@system: +nothrow: +@nogc: + +alias stdio_FILE = core.stdc.stdio.FILE; + +FILE* __iob_func(); + +uint _set_output_format(uint format); + +enum _TWO_DIGIT_EXPONENT = 1; + +void init_msvc() +{ + // stdin,stdout and stderr internally in a static array __iob[3] + auto fp = __iob_func(); + stdin = cast(stdio_FILE*) &fp[0]; + stdout = cast(stdio_FILE*) &fp[1]; + stderr = cast(stdio_FILE*) &fp[2]; + + // ensure that sprintf generates only 2 digit exponent when writing floating point values + _set_output_format(_TWO_DIGIT_EXPONENT); +} + +struct _iobuf +{ + char* _ptr; + int _cnt; // _cnt and _base exchanged for VS2015 + char* _base; + int _flag; + int _file; + int _charbuf; + int _bufsiz; + char* _tmpfname; +} + +alias shared(_iobuf) FILE; + +int _filbuf(FILE *fp); +int _flsbuf(int c, FILE *fp); + +int _fputc_nolock(int c, FILE *fp) +{ + fp._cnt = fp._cnt - 1; + if (fp._cnt >= 0) + { + *fp._ptr = cast(char)c; + fp._ptr = fp._ptr + 1; + return cast(char)c; + } + else + return _flsbuf(c, fp); +} + +int _fgetc_nolock(FILE *fp) +{ + fp._cnt = fp._cnt - 1; + if (fp._cnt >= 0) + { + char c = *fp._ptr; + fp._ptr = fp._ptr + 1; + return c; + } + else + return _filbuf(fp); +} + +shared(FILE)* __acrt_iob_func(uint id) +{ + return __iob_func() + id; +} + +@trusted +{ + /// + void rewind(FILE* stream) + { + fseek(cast(stdio_FILE*)stream,0L,SEEK_SET); + stream._flag = stream._flag & ~_IOERR; + } + /// + pure void clearerr(FILE* stream) { stream._flag = stream._flag & ~(_IOERR|_IOEOF); } + /// + pure int feof(FILE* stream) { return stream._flag&_IOEOF; } + /// + pure int ferror(FILE* stream) { return stream._flag&_IOERR; } + /// + pure int fileno(FILE* stream) { return stream._file; } +} diff --git a/src/core/sys/windows/stdio_msvc14.d b/src/core/sys/windows/stdio_msvc14.d new file mode 100644 index 0000000000..f434543b99 --- /dev/null +++ b/src/core/sys/windows/stdio_msvc14.d @@ -0,0 +1,38 @@ +/** +* This module provides MS VC runtime helper function to be used +* with VS versions VS 2015 or later +* +* Copyright: Copyright Digital Mars 2015. +* License: Distributed under the +* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). +* (See accompanying file LICENSE) +* Source: $(DRUNTIMESRC core/sys/windows/_stdio_msvc14.d) +* Authors: Rainer Schuetze +*/ + +module core.sys.windows.stdio_msvc14; + +version (CRuntime_Microsoft): + +import core.stdc.stdio; + +extern (C): +@system: +nothrow: +@nogc: + +shared(FILE)* __acrt_iob_func(uint); // VS2015+ + +void init_msvc() +{ + stdin = __acrt_iob_func(0); + stdout = __acrt_iob_func(1); + stderr = __acrt_iob_func(2); +} + +pragma(lib, "legacy_stdio_definitions.lib"); + +shared static this() +{ + // force linkage of ModuleInfo that includes the pragma(lib) above in its object file +} diff --git a/src/rt/dmain2.d b/src/rt/dmain2.d index 77edcd592b..8392d3633e 100644 --- a/src/rt/dmain2.d +++ b/src/rt/dmain2.d @@ -57,6 +57,11 @@ version (OSX) extern (C) __gshared void* __osx_stack_end = cast(void*)0xC0000000; } +version(CRuntime_Microsoft) +{ + extern(C) void init_msvc(); +} + /*********************************** * These are a temporary means of providing a GC hook for DLL use. They may be * replaced with some other similar functionality later. @@ -270,13 +275,7 @@ extern (C) int _d_run_main(int argc, char **argv, MainFunc mainFunc) } version (CRuntime_Microsoft) { - auto fp = __iob_func(); - stdin = &fp[0]; - stdout = &fp[1]; - stderr = &fp[2]; - - // ensure that sprintf generates only 2 digit exponent when writing floating point values - _set_output_format(_TWO_DIGIT_EXPONENT); + init_msvc(); // enable full precision for reals version(Win64) From 1f1a936a59486698077c082b86942df235d21c9e Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Tue, 11 Aug 2015 18:01:14 +0200 Subject: [PATCH 2/5] don't build stdio_msvc12.d into lib, create object files stdio_msvc12.obj and stdio_msvc14.obj instead --- mak/MANIFEST | 2 ++ mak/SRCS | 1 - src/core/sys/windows/stdio_msvc12.d | 5 ----- win64.mak | 14 +++++++++++++- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/mak/MANIFEST b/mak/MANIFEST index af2dfa21c8..abe9f591b3 100644 --- a/mak/MANIFEST +++ b/mak/MANIFEST @@ -183,6 +183,8 @@ MANIFEST=\ src\core\sys\windows\threadaux.d \ src\core\sys\windows\windows.d \ src\core\sys\windows\winsock2.d \ + src\core\sys\windows\stdio_msvc12.d \ + src\core\sys\windows\stdio_msvc14.d \ \ src\gc\bits.d \ src\gc\config.d \ diff --git a/mak/SRCS b/mak/SRCS index 7d8fe4e0be..703b86d961 100644 --- a/mak/SRCS +++ b/mak/SRCS @@ -73,7 +73,6 @@ SRCS=\ src\core\sys\windows\threadaux.d \ src\core\sys\windows\windows.d \ src\core\sys\windows\winsock2.d \ - src\core\sys\windows\stdio_msvc12.d \ \ src\gc\bits.d \ src\gc\config.d \ diff --git a/src/core/sys/windows/stdio_msvc12.d b/src/core/sys/windows/stdio_msvc12.d index 44e944fc2b..e028a4048e 100644 --- a/src/core/sys/windows/stdio_msvc12.d +++ b/src/core/sys/windows/stdio_msvc12.d @@ -84,11 +84,6 @@ int _fgetc_nolock(FILE *fp) return _filbuf(fp); } -shared(FILE)* __acrt_iob_func(uint id) -{ - return __iob_func() + id; -} - @trusted { /// diff --git a/win64.mak b/win64.mak index b55d433d18..4f65691429 100644 --- a/win64.mak +++ b/win64.mak @@ -25,10 +25,12 @@ CFLAGS=/Z7 /I"$(VCDIR)"\INCLUDE /I"$(SDKDIR)"\Include DRUNTIME_BASE=druntime$(MODEL) DRUNTIME=lib\$(DRUNTIME_BASE).lib GCSTUB=lib\gcstub$(MODEL).obj +STDIO_VS12=lib\stdio_msvc12_$(MODEL).obj +STDIO_VS14=lib\stdio_msvc14_$(MODEL).obj DOCFMT= -target : import copydir copy $(DRUNTIME) $(GCSTUB) +target : import copydir copy $(DRUNTIME) $(GCSTUB) stdio_vs $(mak\COPY) $(mak\DOCS) @@ -648,6 +650,16 @@ src\rt\minit.obj : src\rt\minit.asm $(GCSTUB) : src\gcstub\gc.d win64.mak $(DMD) -c -of$(GCSTUB) src\gcstub\gc.d $(DFLAGS) +################### VS 2015 init code ######################### + +stdio_vs: $(STDIO_VS14) $(STDIO_VS12) + +$(STDIO_VS12) : src\core\sys\windows\stdio_msvc12.d win64.mak + $(DMD) -c -of$(STDIO_VS12) src\core\sys\windows\stdio_msvc12.d $(DFLAGS) + +$(STDIO_VS14) : src\core\sys\windows\stdio_msvc14.d win64.mak + $(DMD) -c -of$(STDIO_VS14) src\core\sys\windows\stdio_msvc14.d $(DFLAGS) + ################### Library generation ######################### $(DRUNTIME): $(OBJS) $(SRCS) win64.mak From e719d34dcf19bcc90b0bbbfb78aefb01a7f5271b Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Mon, 24 Aug 2015 20:23:58 +0200 Subject: [PATCH 3/5] temporarily add stdio_msvc12.d to the lib to allow successful build before updating dmd --- mak/SRCS | 1 + 1 file changed, 1 insertion(+) diff --git a/mak/SRCS b/mak/SRCS index 703b86d961..7d8fe4e0be 100644 --- a/mak/SRCS +++ b/mak/SRCS @@ -73,6 +73,7 @@ SRCS=\ src\core\sys\windows\threadaux.d \ src\core\sys\windows\windows.d \ src\core\sys\windows\winsock2.d \ + src\core\sys\windows\stdio_msvc12.d \ \ src\gc\bits.d \ src\gc\config.d \ From 26e07e2f37f172688325f558450a10808d7fc7e4 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Thu, 27 Aug 2015 00:33:21 +0200 Subject: [PATCH 4/5] Use "weak" linkage to select code path depending on MS C runtime version --- mak/SRCS | 1 - src/core/sys/windows/stdio_msvc12.d | 103 ------------------- src/core/sys/windows/stdio_msvc14.d | 38 ------- src/rt/stdio_msvc.c | 154 ++++++++++++++++++++++++++++ win64.mak | 21 ++-- 5 files changed, 161 insertions(+), 156 deletions(-) delete mode 100644 src/core/sys/windows/stdio_msvc12.d delete mode 100644 src/core/sys/windows/stdio_msvc14.d create mode 100644 src/rt/stdio_msvc.c diff --git a/mak/SRCS b/mak/SRCS index 7d8fe4e0be..703b86d961 100644 --- a/mak/SRCS +++ b/mak/SRCS @@ -73,7 +73,6 @@ SRCS=\ src\core\sys\windows\threadaux.d \ src\core\sys\windows\windows.d \ src\core\sys\windows\winsock2.d \ - src\core\sys\windows\stdio_msvc12.d \ \ src\gc\bits.d \ src\gc\config.d \ diff --git a/src/core/sys/windows/stdio_msvc12.d b/src/core/sys/windows/stdio_msvc12.d deleted file mode 100644 index e028a4048e..0000000000 --- a/src/core/sys/windows/stdio_msvc12.d +++ /dev/null @@ -1,103 +0,0 @@ -/** -* This module provides MS VC runtime helper function to be used -* with VS versions before VS 2015 -* -* Copyright: Copyright Digital Mars 2015. -* License: Distributed under the -* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). -* (See accompanying file LICENSE) -* Source: $(DRUNTIMESRC core/sys/windows/_stdio_msvc12.d) -* Authors: Rainer Schuetze -*/ - -module core.sys.windows.stdio_msvc12; - -version( CRuntime_Microsoft ): - -import core.stdc.stdio; - -extern (C): -@system: -nothrow: -@nogc: - -alias stdio_FILE = core.stdc.stdio.FILE; - -FILE* __iob_func(); - -uint _set_output_format(uint format); - -enum _TWO_DIGIT_EXPONENT = 1; - -void init_msvc() -{ - // stdin,stdout and stderr internally in a static array __iob[3] - auto fp = __iob_func(); - stdin = cast(stdio_FILE*) &fp[0]; - stdout = cast(stdio_FILE*) &fp[1]; - stderr = cast(stdio_FILE*) &fp[2]; - - // ensure that sprintf generates only 2 digit exponent when writing floating point values - _set_output_format(_TWO_DIGIT_EXPONENT); -} - -struct _iobuf -{ - char* _ptr; - int _cnt; // _cnt and _base exchanged for VS2015 - char* _base; - int _flag; - int _file; - int _charbuf; - int _bufsiz; - char* _tmpfname; -} - -alias shared(_iobuf) FILE; - -int _filbuf(FILE *fp); -int _flsbuf(int c, FILE *fp); - -int _fputc_nolock(int c, FILE *fp) -{ - fp._cnt = fp._cnt - 1; - if (fp._cnt >= 0) - { - *fp._ptr = cast(char)c; - fp._ptr = fp._ptr + 1; - return cast(char)c; - } - else - return _flsbuf(c, fp); -} - -int _fgetc_nolock(FILE *fp) -{ - fp._cnt = fp._cnt - 1; - if (fp._cnt >= 0) - { - char c = *fp._ptr; - fp._ptr = fp._ptr + 1; - return c; - } - else - return _filbuf(fp); -} - -@trusted -{ - /// - void rewind(FILE* stream) - { - fseek(cast(stdio_FILE*)stream,0L,SEEK_SET); - stream._flag = stream._flag & ~_IOERR; - } - /// - pure void clearerr(FILE* stream) { stream._flag = stream._flag & ~(_IOERR|_IOEOF); } - /// - pure int feof(FILE* stream) { return stream._flag&_IOEOF; } - /// - pure int ferror(FILE* stream) { return stream._flag&_IOERR; } - /// - pure int fileno(FILE* stream) { return stream._file; } -} diff --git a/src/core/sys/windows/stdio_msvc14.d b/src/core/sys/windows/stdio_msvc14.d deleted file mode 100644 index f434543b99..0000000000 --- a/src/core/sys/windows/stdio_msvc14.d +++ /dev/null @@ -1,38 +0,0 @@ -/** -* This module provides MS VC runtime helper function to be used -* with VS versions VS 2015 or later -* -* Copyright: Copyright Digital Mars 2015. -* License: Distributed under the -* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). -* (See accompanying file LICENSE) -* Source: $(DRUNTIMESRC core/sys/windows/_stdio_msvc14.d) -* Authors: Rainer Schuetze -*/ - -module core.sys.windows.stdio_msvc14; - -version (CRuntime_Microsoft): - -import core.stdc.stdio; - -extern (C): -@system: -nothrow: -@nogc: - -shared(FILE)* __acrt_iob_func(uint); // VS2015+ - -void init_msvc() -{ - stdin = __acrt_iob_func(0); - stdout = __acrt_iob_func(1); - stderr = __acrt_iob_func(2); -} - -pragma(lib, "legacy_stdio_definitions.lib"); - -shared static this() -{ - // force linkage of ModuleInfo that includes the pragma(lib) above in its object file -} diff --git a/src/rt/stdio_msvc.c b/src/rt/stdio_msvc.c new file mode 100644 index 0000000000..92f0f9b7c6 --- /dev/null +++ b/src/rt/stdio_msvc.c @@ -0,0 +1,154 @@ +/** +* This module provides MS VC runtime helper function that +* wrap differences between different versions of the MS C runtime +* +* Copyright: Copyright Digital Mars 2015. +* License: Distributed under the +* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). +* (See accompanying file LICENSE) +* Source: $(DRUNTIMESRC rt/_stdio_msvc.d) +* Authors: Rainer Schuetze +*/ + +struct _iobuf +{ + char* _ptr; + int _cnt; // _cnt and _base exchanged for VS2015 + char* _base; + int _flag; + int _file; + int _charbuf; + int _bufsiz; + char* _tmpfname; + // additional members in VS2015 +}; + +typedef struct _iobuf FILE; +extern FILE* stdin; +extern FILE* stdout; +extern FILE* stderr; + +FILE* __acrt_iob_func(int hnd); // VS2015+ +FILE* __iob_func(); // VS2013- + +int _set_output_format(int format); // VS2013- + +//extern const char* __acrt_iob_func; +extern const char* _nullfunc = 0; + +#pragma comment(linker, "/alternatename:__acrt_iob_func=_nullfunc") +#pragma comment(linker, "/alternatename:__iob_func=_nullfunc") +#pragma comment(linker, "/alternatename:_set_output_format=_nullfunc") + +void init_msvc() +{ + if (&__acrt_iob_func != (void*) &_nullfunc) + { + stdin = __acrt_iob_func(0); + stdout = __acrt_iob_func(1); + stderr = __acrt_iob_func(2); + } + else if (&__iob_func != (void*) &_nullfunc) + { + FILE* fp = __iob_func(); + stdin = fp; + stdout = fp + 1; + stderr = fp + 1; + } + if (&_set_output_format != (void*) &_nullfunc) + _set_output_format(1); +} + +// VS2013- implements these functions as macros, VS2015+ provides symbols + +#pragma comment(linker, "/alternatename:_fputc_nolock=_msvc_fputc_nolock") +#pragma comment(linker, "/alternatename:_fgetc_nolock=_msvc_fgetc_nolock") +#pragma comment(linker, "/alternatename:rewind=_msvc_rewind") +#pragma comment(linker, "/alternatename:clearerr=_msvc_clearerr") +#pragma comment(linker, "/alternatename:feof=_msvc_feof") +#pragma comment(linker, "/alternatename:ferror=_msvc_ferror") +#pragma comment(linker, "/alternatename:fileno=_msvc_fileno") + +// VS2013- helper functions +int _filbuf(FILE *fp); +int _flsbuf(int c, FILE *fp); + +#pragma comment(linker, "/alternatename:_filbuf=_nullfunc") +#pragma comment(linker, "/alternatename:_flsbuf=_nullfunc") + +int _msvc_fputc_nolock(int c, FILE *fp) +{ + fp->_cnt = fp->_cnt - 1; + if (fp->_cnt >= 0) + { + *(fp->_ptr) = (char)c; + fp->_ptr = fp->_ptr + 1; + return (char)c; + } + else + return _flsbuf(c, fp); +} + +int _msvc_fgetc_nolock(FILE *fp) +{ + fp->_cnt = fp->_cnt - 1; + if (fp->_cnt >= 0) + { + char c = *(fp->_ptr); + fp->_ptr = fp->_ptr + 1; + return c; + } + else + return _filbuf(fp); +} + +enum +{ + _IOFBF = 0, + _IOLBF = 0x40, + _IONBF = 4, + _IOREAD = 1, // non-standard + _IOWRT = 2, // non-standard + _IOMYBUF = 8, // non-standard + _IOEOF = 0x10, // non-standard + _IOERR = 0x20, // non-standard + _IOSTRG = 0x40, // non-standard + _IORW = 0x80, // non-standard + _IOAPP = 0x200, // non-standard + _IOAPPEND = 0x200, // non-standard +}; + +enum +{ + SEEK_SET, + SEEK_CUR, + SEEK_END +}; + +int fseek(FILE *fp, long off, int whence); + +void _msvc_rewind(FILE* stream) +{ + fseek(stream, 0L, SEEK_SET); + stream->_flag = stream->_flag & ~_IOERR; +} +/// +void _msvc_clearerr(FILE* stream) +{ + stream->_flag = stream->_flag & ~(_IOERR|_IOEOF); +} + +int _msvc_feof(FILE* stream) +{ + return stream->_flag & _IOEOF; +} + +int _msvc_ferror(FILE* stream) +{ + return stream->_flag & _IOERR; +} + +int _msvc_fileno(FILE* stream) +{ + return stream->_file; +} diff --git a/win64.mak b/win64.mak index 4f65691429..86871c2c8e 100644 --- a/win64.mak +++ b/win64.mak @@ -25,12 +25,10 @@ CFLAGS=/Z7 /I"$(VCDIR)"\INCLUDE /I"$(SDKDIR)"\Include DRUNTIME_BASE=druntime$(MODEL) DRUNTIME=lib\$(DRUNTIME_BASE).lib GCSTUB=lib\gcstub$(MODEL).obj -STDIO_VS12=lib\stdio_msvc12_$(MODEL).obj -STDIO_VS14=lib\stdio_msvc14_$(MODEL).obj DOCFMT= -target : import copydir copy $(DRUNTIME) $(GCSTUB) stdio_vs +target : import copydir copy $(DRUNTIME) $(GCSTUB) $(mak\COPY) $(mak\DOCS) @@ -43,8 +41,8 @@ $(mak\SRCS) # NOTE: a pre-compiled minit.obj has been provided in dmd for Win32 and # minit.asm is not used by dmd for Linux -OBJS= errno_c.obj -OBJS_TO_DELETE= errno_c.obj +OBJS= errno_c.obj stdio_msvc_$(MODEL).obj +OBJS_TO_DELETE= errno_c.obj stdio_msvc_$(MODEL).obj ######################## Doc .html file generation ############################## @@ -642,6 +640,10 @@ $(IMPDIR)\etc\linux\memoryerror.d : src\etc\linux\memoryerror.d errno_c.obj : src\core\stdc\errno.c $(CC) -c $(CFLAGS) src\core\stdc\errno.c -Foerrno_c.obj +stdio_msvc_$(MODEL).obj : src\rt\stdio_msvc.c win64.mak + $(CC) -c -Fo$@ $(CFLAGS) src\rt\stdio_msvc.c + + src\rt\minit.obj : src\rt\minit.asm $(CC) -c $(CFLAGS) src\rt\minit.asm @@ -650,15 +652,6 @@ src\rt\minit.obj : src\rt\minit.asm $(GCSTUB) : src\gcstub\gc.d win64.mak $(DMD) -c -of$(GCSTUB) src\gcstub\gc.d $(DFLAGS) -################### VS 2015 init code ######################### - -stdio_vs: $(STDIO_VS14) $(STDIO_VS12) - -$(STDIO_VS12) : src\core\sys\windows\stdio_msvc12.d win64.mak - $(DMD) -c -of$(STDIO_VS12) src\core\sys\windows\stdio_msvc12.d $(DFLAGS) - -$(STDIO_VS14) : src\core\sys\windows\stdio_msvc14.d win64.mak - $(DMD) -c -of$(STDIO_VS14) src\core\sys\windows\stdio_msvc14.d $(DFLAGS) ################### Library generation ######################### From 44ee88865e71bea42a6c6e6028a0376614da61fa Mon Sep 17 00:00:00 2001 From: Martin Date: Thu, 27 Aug 2015 21:51:30 +0200 Subject: [PATCH 5/5] Visual Studio 2015: exploit C99-conformant (v)snprintf in core.stdc.stdio --- src/core/stdc/stdio.d | 36 +++++++++++++++---------------- src/rt/stdio_msvc.c | 49 +++++++++++++++++++------------------------ 2 files changed, 39 insertions(+), 46 deletions(-) diff --git a/src/core/stdc/stdio.d b/src/core/stdc/stdio.d index f099ab11ed..bb284f3cb3 100644 --- a/src/core/stdc/stdio.d +++ b/src/core/stdc/stdio.d @@ -76,7 +76,7 @@ else version( CRuntime_Microsoft ) FOPEN_MAX = 20, /// FILENAME_MAX = 260, - /// + /// Actually int.max since Visual Studio 2015. TMP_MAX = 32767, /// _SYS_OPEN = 20, // non-standard @@ -84,11 +84,11 @@ else version( CRuntime_Microsoft ) /// enum int _NFILE = 512; // non-standard - /// + /// Removed since Visual Studio 2015. enum string _P_tmpdir = "\\"; // non-standard - /// + /// Removed since Visual Studio 2015. enum wstring _wP_tmpdir = "\\"; // non-standard - /// + /// Actually 260 since Visual Studio 2015. enum int L_tmpnam = _P_tmpdir.length + 12; } else version( linux ) @@ -542,23 +542,23 @@ else version( CRuntime_Microsoft ) _IOLBF = 0x40, /// _IONBF = 4, - /// + /// Removed since Visual Studio 2015. _IOREAD = 1, // non-standard - /// + /// Removed since Visual Studio 2015. _IOWRT = 2, // non-standard - /// + /// Removed since Visual Studio 2015. _IOMYBUF = 8, // non-standard - /// + /// Removed since Visual Studio 2015. _IOEOF = 0x10, // non-standard - /// + /// Removed since Visual Studio 2015. _IOERR = 0x20, // non-standard - /// + /// Removed since Visual Studio 2015. _IOSTRG = 0x40, // non-standard - /// + /// Removed since Visual Studio 2015. _IORW = 0x80, // non-standard - /// + /// Removed since Visual Studio 2015. _IOAPP = 0x200, // non-standard - /// + /// Removed since Visual Studio 2015. _IOAPPEND = 0x200, // non-standard } @@ -944,19 +944,19 @@ else version( CRuntime_Microsoft ) /// pure int fileno(FILE* stream); } + /// - int _snprintf(char* s, size_t n, in char* fmt, ...); + int _snprintf(char* s, size_t n, in char* format, ...); /// - alias _snprintf snprintf; + int snprintf(char* s, size_t n, in char* format, ...); /// - int _vsnprintf(char* s, size_t n, in char* format, va_list arg); + int _vsnprintf(char* s, size_t n, in char* format, va_list arg); /// - alias _vsnprintf vsnprintf; + int vsnprintf(char* s, size_t n, in char* format, va_list arg); /// int _fputc_nolock(int c, FILE *fp); - /// int _fgetc_nolock(FILE *fp); diff --git a/src/rt/stdio_msvc.c b/src/rt/stdio_msvc.c index 92f0f9b7c6..a81042643f 100644 --- a/src/rt/stdio_msvc.c +++ b/src/rt/stdio_msvc.c @@ -53,12 +53,21 @@ void init_msvc() FILE* fp = __iob_func(); stdin = fp; stdout = fp + 1; - stderr = fp + 1; + stderr = fp + 2; } if (&_set_output_format != (void*) &_nullfunc) - _set_output_format(1); + { + const int _TWO_DIGIT_EXPONENT = 1; + _set_output_format(_TWO_DIGIT_EXPONENT); + } } +// VS2015+ provides C99-conformant (v)snprintf functions, so weakly +// link to legacy _(v)snprintf (not C99-conformant!) for VS2013- only + +#pragma comment(linker, "/alternatename:snprintf=_snprintf") +#pragma comment(linker, "/alternatename:vsnprintf=_vsnprintf") + // VS2013- implements these functions as macros, VS2015+ provides symbols #pragma comment(linker, "/alternatename:_fputc_nolock=_msvc_fputc_nolock") @@ -70,13 +79,13 @@ void init_msvc() #pragma comment(linker, "/alternatename:fileno=_msvc_fileno") // VS2013- helper functions -int _filbuf(FILE *fp); -int _flsbuf(int c, FILE *fp); +int _filbuf(FILE* fp); +int _flsbuf(int c, FILE* fp); #pragma comment(linker, "/alternatename:_filbuf=_nullfunc") #pragma comment(linker, "/alternatename:_flsbuf=_nullfunc") -int _msvc_fputc_nolock(int c, FILE *fp) +int _msvc_fputc_nolock(int c, FILE* fp) { fp->_cnt = fp->_cnt - 1; if (fp->_cnt >= 0) @@ -89,7 +98,7 @@ int _msvc_fputc_nolock(int c, FILE *fp) return _flsbuf(c, fp); } -int _msvc_fgetc_nolock(FILE *fp) +int _msvc_fgetc_nolock(FILE* fp) { fp->_cnt = fp->_cnt - 1; if (fp->_cnt >= 0) @@ -104,38 +113,22 @@ int _msvc_fgetc_nolock(FILE *fp) enum { - _IOFBF = 0, - _IOLBF = 0x40, - _IONBF = 4, - _IOREAD = 1, // non-standard - _IOWRT = 2, // non-standard - _IOMYBUF = 8, // non-standard - _IOEOF = 0x10, // non-standard - _IOERR = 0x20, // non-standard - _IOSTRG = 0x40, // non-standard - _IORW = 0x80, // non-standard - _IOAPP = 0x200, // non-standard - _IOAPPEND = 0x200, // non-standard + SEEK_SET = 0, + _IOEOF = 0x10, + _IOERR = 0x20 }; -enum -{ - SEEK_SET, - SEEK_CUR, - SEEK_END -}; - -int fseek(FILE *fp, long off, int whence); +int fseek(FILE* fp, long off, int whence); void _msvc_rewind(FILE* stream) { fseek(stream, 0L, SEEK_SET); stream->_flag = stream->_flag & ~_IOERR; } -/// + void _msvc_clearerr(FILE* stream) { - stream->_flag = stream->_flag & ~(_IOERR|_IOEOF); + stream->_flag = stream->_flag & ~(_IOERR | _IOEOF); } int _msvc_feof(FILE* stream)