Skip to content
This repository was archived by the owner on Feb 8, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions mak/MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
97 changes: 27 additions & 70 deletions src/core/stdc/stdio.d
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,19 @@ 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
}

///
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 )
Expand Down Expand Up @@ -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;
}

///
Expand Down Expand Up @@ -549,32 +542,28 @@ 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
}

extern shared void function() _fcloseallp;

private extern shared FILE[_NFILE] _iob;

shared(FILE)* __iob_func();

///
shared FILE* stdin; // = &__iob_func()[0];
///
Expand Down Expand Up @@ -942,66 +931,34 @@ 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, ...);
///
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);
///
alias _vsnprintf vsnprintf;

///
uint _set_output_format(uint format);
///
enum _TWO_DIGIT_EXPONENT = 1;
int snprintf(char* s, size_t n, in char* format, ...);

///
int _filbuf(FILE *fp);
int _vsnprintf(char* s, size_t n, in char* format, va_list arg);
///
int _flsbuf(int c, FILE *fp);
int vsnprintf(char* s, size_t n, in char* format, va_list arg);

///
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);
Expand Down
13 changes: 6 additions & 7 deletions src/rt/dmain2.d
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down
147 changes: 147 additions & 0 deletions src/rt/stdio_msvc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/**
* 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 + 2;
}
if (&_set_output_format != (void*) &_nullfunc)
{
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")
#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
{
SEEK_SET = 0,
_IOEOF = 0x10,
_IOERR = 0x20
};

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;
}
9 changes: 7 additions & 2 deletions win64.mak
Original file line number Diff line number Diff line change
Expand Up @@ -41,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 ##############################

Expand Down Expand Up @@ -640,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

Expand All @@ -648,6 +652,7 @@ src\rt\minit.obj : src\rt\minit.asm
$(GCSTUB) : src\gcstub\gc.d win64.mak
$(DMD) -c -of$(GCSTUB) src\gcstub\gc.d $(DFLAGS)


################### Library generation #########################

$(DRUNTIME): $(OBJS) $(SRCS) win64.mak
Expand Down