From 999fae2ef017bcd956d97a77eb5d35c61b993350 Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 27 Feb 2015 21:49:45 +0100 Subject: [PATCH 1/2] core.stdc.stdarg: mark LDC vararg intrinsics @nogc nothrow. --- src/core/stdc/stdarg.d | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/stdc/stdarg.d b/src/core/stdc/stdarg.d index 1752f45942..9c81bfdefc 100644 --- a/src/core/stdc/stdarg.d +++ b/src/core/stdc/stdarg.d @@ -314,10 +314,10 @@ version( LDC ) alias char* va_list; pragma(LDC_va_start) - void va_start(T)(va_list ap, ref T); + void va_start(T)(va_list ap, ref T) @nogc nothrow; private pragma(LDC_va_arg) - T va_arg_intrinsic(T)(va_list ap); + T va_arg_intrinsic(T)(va_list ap) @nogc nothrow; T va_arg(T)(ref va_list ap) { @@ -442,10 +442,10 @@ version( LDC ) } pragma(LDC_va_end) - void va_end(va_list ap); + void va_end(va_list ap) @nogc nothrow; pragma(LDC_va_copy) - void va_copy(out va_list dest, va_list src); + void va_copy(out va_list dest, va_list src) @nogc nothrow; } else version( X86 ) { From 83e9c91882cb8de7c22a44eb6da6cc2006a973e1 Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 27 Feb 2015 22:17:03 +0100 Subject: [PATCH 2/2] core.stdc.stdio: add experimental support for MSVCRT 14 (VS 2015). --- src/core/stdc/stdio.d | 222 +++++++++++++++++++++++++++++++++++++----- src/rt/dmain2.d | 24 +++-- 2 files changed, 215 insertions(+), 31 deletions(-) diff --git a/src/core/stdc/stdio.d b/src/core/stdc/stdio.d index cc4f3140da..eb23cd977d 100644 --- a/src/core/stdc/stdio.d +++ b/src/core/stdc/stdio.d @@ -30,6 +30,9 @@ private } } +// uncomment for MSVCRT >= 14 (VS 2015) +//version(LDC) { version(Win64) version = LDC_MSVCRT14; } + extern (C): @system: nothrow: @@ -60,14 +63,23 @@ else version( Win64 ) EOF = -1, FOPEN_MAX = 20, FILENAME_MAX = 260, - TMP_MAX = 32767, _SYS_OPEN = 20, // non-standard } - enum int _NFILE = 512; // non-standard + enum int _NFILE = 512; // non-standard + + version( LDC_MSVCRT14 ) // requires MSVCRT >= 14 (VS 2015) + { + enum int TMP_MAX = int.max; + enum int L_tmpnam = 260; + } + else + { + enum int TMP_MAX = short.max; enum string _P_tmpdir = "\\"; // non-standard enum wstring _wP_tmpdir = "\\"; // non-standard enum int L_tmpnam = _P_tmpdir.length + 12; + } } else version( linux ) { @@ -198,8 +210,17 @@ version( Win32 ) } else version( Win64 ) { - alias int fpos_t; //check this + alias long fpos_t; + version( LDC_MSVCRT14 ) // requires MSVCRT >= 14 (VS 2015) + { + struct _iobuf + { + void* _Placeholder; + } + } + else + { struct _iobuf { char* _ptr; @@ -211,6 +232,7 @@ else version( Win64 ) int _bufsiz; char* _tmpfname; } + } alias shared(_iobuf) FILE; } @@ -436,26 +458,37 @@ else version( Win64 ) _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 } extern shared void function() _fcloseallp; - private extern shared FILE[_NFILE] _iob; - - shared(FILE)* __iob_func(); + version( LDC_MSVCRT14 ) // requires MSVCRT >= 14 (VS 2015) + { + shared(FILE)* __acrt_iob_func(uint); + shared FILE* stdin; // = __acrt_iob_func(0); + shared FILE* stdout; // = __acrt_iob_func(1); + shared FILE* stderr; // = __acrt_iob_func(2); + } + else + { + enum + { + _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 + } - shared FILE* stdin; // = &__iob_func()[0]; - shared FILE* stdout; // = &__iob_func()[1]; - shared FILE* stderr; // = &__iob_func()[2]; + shared(FILE)* __iob_func(); + shared FILE* stdin; // = &__iob_func()[0]; + shared FILE* stdout; // = &__iob_func()[1]; + shared FILE* stderr; // = &__iob_func()[2]; + } } else version( linux ) { @@ -605,6 +638,110 @@ version (MinGW) int __mingw_scanf(in char* format, ...); alias __mingw_scanf scanf; } +else version (LDC_MSVCRT14) // requires MSVCRT >= 14 (VS 2015) +{ + // MS define the *printf and *scanf function families inline, forwarding to 4 + // basic functions. + // We implement corresponding wrappers around these basic functions and use + // special mangled names (__ldc_ prefix) to avoid duplicate symbols when + // linking against other C/C++ objects with their own versions. + + private + { + enum _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR = 2; + + int __stdio_common_vfprintf(ulong _Options, FILE* _Stream, + in char* _Format, void* _Locale, va_list _ArgList); + int __stdio_common_vsprintf(ulong _Options, char* _Buffer, size_t _BufferCount, + in char* _Format, void* _Locale, va_list _ArgList); + + int __stdio_common_vfscanf(ulong _Options, FILE* _Stream, + in char* _Format, void* _Locale, va_list _Arglist); + int __stdio_common_vsscanf(ulong _Options, in char* _Buffer, size_t _BufferCount, + in char* _Format, void* _Locale, va_list _ArgList); + } + + // *printf: + pragma(mangle, "__ldc_vfprintf") + int vfprintf(FILE* stream, in char* format, va_list args) + { + return __stdio_common_vfprintf(0, stream, format, null, args); + } + pragma(mangle, "__ldc_fprintf") + int fprintf(FILE* stream, in char* format, ...) + { + va_list args; + va_start(args, format); + return vfprintf(stream, format, args); + } + + pragma(mangle, "__ldc_vprintf") + int vprintf(in char* format, va_list args) + { + return vfprintf(stdout, format, args); + } + pragma(mangle, "__ldc_printf") + int printf(in char* format, ...) + { + va_list args; + va_start(args, format); + return vprintf(format, args); + } + + pragma(mangle, "__ldc_vsprintf") + int vsprintf(char* s, in char* format, va_list args) + { + return vsnprintf(s, size_t.max, format, args); + } + pragma(mangle, "__ldc_sprintf") + int sprintf(char* s, in char* format, ...) + { + va_list args; + va_start(args, format); + return vsprintf(s, format, args); + } + + // *scanf: + + pragma(mangle, "__ldc_vfscanf") + int vfscanf(FILE* stream, in char* format, va_list args) + { + return __stdio_common_vfscanf(0, stream, format, null, args); + } + pragma(mangle, "__ldc_fscanf") + int fscanf(FILE* stream, in char* format, ...) + { + va_list args; + va_start(args, format); + return vfscanf(stream, format, args); + } + + pragma(mangle, "__ldc_vscanf") + int vscanf(in char* format, va_list args) + { + return vfscanf(stdin, format, args); + } + pragma(mangle, "__ldc_scanf") + int scanf(in char* format, ...) + { + va_list args; + va_start(args, format); + return vscanf(format, args); + } + + pragma(mangle, "__ldc_vsscanf") + int vsscanf(in char* s, in char* format, va_list args) + { + return __stdio_common_vsscanf(0, s, size_t.max, format, null, args); + } + pragma(mangle, "__ldc_sscanf") + int sscanf(in char* s, in char* format, ...) + { + va_list args; + va_start(args, format); + return vsscanf(s, format, args); + } +} else { int fprintf(FILE* stream, in char* format, ...); @@ -699,15 +836,49 @@ else version( Win32 ) } else version( Win64 ) { - // No unsafe pointer manipulation. - extern (D) @trusted + version( LDC_MSVCRT14 ) // requires MSVCRT >= 14 (VS 2015) { - void rewind(FILE* stream) { fseek(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; } + // No unsafe pointer manipulation. + @trusted + { + void rewind(FILE* stream); + pure void clearerr(FILE* stream); + pure int feof(FILE* stream); + pure int ferror(FILE* stream); + pure int fileno(FILE* stream); + } + + /// + pragma(mangle, "__ldc_vsnprintf") + int vsnprintf(char* s, size_t n, in char* format, va_list args) + { + int result = __stdio_common_vsprintf( + _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, + s, n, format, null, args); + return result < 0 ? -1 : result; + } + + /// + pragma(mangle, "__ldc_snprintf") + int snprintf(char* s, size_t n, in char* format, ...) + { + va_list args; + va_start(args, format); + return vsnprintf(s, n, format, args); + } } + else + { + // No unsafe pointer manipulation. + extern (D) @trusted + { + void rewind(FILE* stream) { fseek(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; } + } + int _snprintf(char* s, size_t n, in char* fmt, ...); alias _snprintf snprintf; @@ -745,6 +916,7 @@ else version( Win64 ) else return _filbuf(fp); } + } int _lock_file(FILE *fp); int _unlock_file(FILE *fp); diff --git a/src/rt/dmain2.d b/src/rt/dmain2.d index 0f5c6f748a..4bcc7baddc 100644 --- a/src/rt/dmain2.d +++ b/src/rt/dmain2.d @@ -37,6 +37,9 @@ version (FreeBSD) import core.stdc.fenv; } +// uncomment for MSVCRT >= 14 (VS 2015) +//version(LDC) { version(Win64) version = LDC_MSVCRT14; } + extern (C) void _STI_monitor_staticctor(); extern (C) void _STD_monitor_staticdtor(); extern (C) void _STI_critical_init(); @@ -266,13 +269,22 @@ extern (C) int _d_run_main(int argc, char **argv, MainFunc mainFunc) version (Win64) { - auto fp = __iob_func(); - stdin = &fp[0]; - stdout = &fp[1]; - stderr = &fp[2]; + version (LDC_MSVCRT14) // requires MSVCRT >= 14 (VS 2015) + { + stdin = __acrt_iob_func(0); + stdout = __acrt_iob_func(1); + stderr = __acrt_iob_func(2); + } + else + { + 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); + // ensure that *printf generates only 2 digit exponent when writing floating point values + _set_output_format(_TWO_DIGIT_EXPONENT); + } // enable full precision for reals asm