From 2c1112ca80484ee5011c52b561900e47f22592bd Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Thu, 27 Aug 2015 00:33:21 +0200 Subject: [PATCH] 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 f7a1bc27c8..834c094ec4 100644 --- a/mak/SRCS +++ b/mak/SRCS @@ -75,7 +75,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 a34d423fec..30887bcd0e 100644 --- a/win64.mak +++ b/win64.mak @@ -27,12 +27,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) @@ -45,8 +43,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 ############################## @@ -657,6 +655,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 @@ -665,15 +667,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 #########################