diff --git a/time.c b/time.c index 4af193d..842d8f2 100644 --- a/time.c +++ b/time.c @@ -1639,6 +1639,10 @@ localtime_with_gmtoff_zone(const time_t *t, struct tm *result, long *gmtoff, con else *zone = zone_str("(NO-TIMEZONE-ABBREVIATION)"); #elif defined(HAVE_TZNAME) && defined(HAVE_DAYLIGHT) +#ifdef _WIN32 +#define tzname _tzname +#define daylight _daylight +#endif /* this needs tzset or localtime, instead of localtime_r */ *zone = zone_str(tzname[daylight && tm.tm_isdst]); #else diff --git a/win32/Makefile.sub b/win32/Makefile.sub index 668f9e1..d30e7b9 100644 --- a/win32/Makefile.sub +++ b/win32/Makefile.sub @@ -113,7 +113,8 @@ DEBUGFLAGS = -Zi !if $(MSC_VER) < 1400 OPTFLAGS = -O2b2xg- !else -OPTFLAGS = -O2sy- +#OPTFLAGS = -O2sy- +OPTFLAGS = -Od !endif !endif !if !defined(PLATFORM) @@ -608,6 +609,9 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub #define HAVE_STRUCT_STAT_ST_RDEV 1 #define HAVE_ST_RDEV 1 #define HAVE_STRUCT_TIMEVAL 1 +!if $(MSC_VER) >= 1900 +#define HAVE_STRUCT_TIMESPEC +!endif !if $(MSC_VER) >= 1600 #define HAVE_STDINT_H 1 !else diff --git a/win32/mkexports.rb b/win32/mkexports.rb index ab29fc1..a210523 100755 --- a/win32/mkexports.rb +++ b/win32/mkexports.rb @@ -46,7 +46,7 @@ class Exports read_substitution(incdir+"/subst.h", syms, winapis) syms["rb_w32_vsnprintf"] ||= "ruby_vsnprintf" syms["rb_w32_snprintf"] ||= "ruby_snprintf" - @syms = syms + @syms = syms.reject {|k,v| k.index('_xmm') } end def read_substitution(header, syms, winapis) @@ -112,6 +112,7 @@ class Exports::Mswin < Exports when /OBJECT/, /LIBRARY/ next if /^[[:xdigit:]]+ 0+ UNDEF / =~ l next unless /External/ =~ l + next if /(?:_local_stdio_printf_options|v(f|sn?)printf_l)\Z/ =~ l next unless l.sub!(/.*?\s(\(\)\s+)?External\s+\|\s+/, '') is_data = !$1 if noprefix or /^[@_]/ =~ l diff --git a/win32/rtname.cmd b/win32/rtname.cmd index 1f410a0..f7a52b8 100644 --- a/win32/rtname.cmd +++ b/win32/rtname.cmd @@ -3,10 +3,14 @@ set rt= set rtver= set osver= for /f "usebackq" %%I in (`dumpbin -dependents %1 ^| findstr -r -i "\&2 - exit 1 -) +if "%rt%" NEQ "" goto :msvcr +for /f "usebackq" %%I in (`dumpbin -dependents %1 ^| findstr -r -i "\&2 +exit 1 + +:msvcr for %%i in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do @call set rt=%%rt:%%i=%%i%% if "%rt%" == "msvcrt" ( call set rtver=60 @@ -15,4 +19,13 @@ if "%rt%" == "msvcrt" ( call set rt=msvcr%%rtver%% call set osver=_%%rtver%% ) +goto :exit + +:vcruntime +for %%i in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do @call set rt=%%rt:%%i=%%i%% +call set rtver=%%rt:vcruntime=%% +call set rt=vcruntime%%rtver%% +call set osver=_%%rtver%% + +:exit for %%I in ("PLATFORM = $(TARGET_OS)%osver%" "RT = %rt%" "RT_VER = %rtver%") do @echo %%~I diff --git a/win32/win32.c b/win32/win32.c index eb1818a..7ed3071 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -2225,6 +2225,19 @@ rb_w32_closedir(DIR *dirp) /* License: Ruby's */ typedef struct { +#if RUBY_MSVCRT_VERSION >= 140 + CRITICAL_SECTION lock; + intptr_t osfhnd; // underlying OS file HANDLE + __int64 startpos; // File position that matches buffer start + unsigned char osfile; // Attributes of file (e.g., open in text mode?) + char textmode; // __crt_lowio_text_mode + char _pipe_lookahead[3]; + + uint8_t unicode : 1; // Was the file opened as unicode? + uint8_t utf8translations : 1; // Buffer contains translations other than CRLF + uint8_t dbcsBufferUsed : 1; // Is the dbcsBuffer in use? + char dbcsBuffer; // Buffer for the lead byte of DBCS when converting from DBCS to Unicode +#else intptr_t osfhnd; /* underlying OS file HANDLE */ char osfile; /* attributes of file (e.g., open in text mode?) */ char pipech; /* one char buffer for handles opened on pipes */ @@ -2236,6 +2249,7 @@ typedef struct { char textmode; char pipech2[2]; #endif +#endif } ioinfo; #if !defined _CRTIMP || defined __MINGW32__ @@ -2244,10 +2258,14 @@ typedef struct { #endif #if !defined(__BORLANDC__) +#if RUBY_MSVCRT_VERSION >= 140 +static ioinfo ** __pioinfo = NULL; +#else EXTERN_C _CRTIMP ioinfo * __pioinfo[]; +#endif static inline ioinfo* _pioinfo(int); -#define IOINFO_L2E 5 +#define IOINFO_L2E (RUBY_MSVCRT_VERSION >= 140 ? 6 : 5) #define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) #define _osfhnd(i) (_pioinfo(i)->osfhnd) #define _osfile(i) (_pioinfo(i)->osfile) @@ -2260,6 +2278,34 @@ static size_t pioinfo_extra = 0; /* workaround for VC++8 SP1 */ static void set_pioinfo_extra(void) { +#if RUBY_MSVCRT_VERSION >= 140 + // get __pioinfo addr with _isatty + HMODULE mod = GetModuleHandle("ucrtbase.dll"); + char *addr = (char*)GetProcAddress(mod, "_isatty"); + // _osfile(fh) & FDEV /*0x40*/ +#if _WIN64 + // lea rdx,[__pioinfo's addr in RIP-relative 32bit addr] + addr += 0x25; +# define OPSIZE 3 + if (memcmp(addr, "\x48\x8d\x15", OPSIZE)) { + fprintf(stderr, "unexpected ucrtbase.dll\n"); + abort(); + } + addr += OPSIZE; + int32_t rel = *(int32_t*)(addr); + char *rip = addr + 4; + __pioinfo = (ioinfo**)(rip + rel); +#else + // mov eax,dword ptr [eax*4+100EB430h] + addr += 0x32; +# define OPSIZE 3 + if (memcmp(addr, "\x8B\x04\x85", OPSIZE)) { + fprintf(stderr, "unexpected ucrtbase.dll\n"); + abort(); + } + __pioinfo = (ioinfo**)*(intptr_t*)(addr + OPSIZE); +#endif +#else int fd; fd = _open("NUL", O_RDONLY); @@ -2274,6 +2320,7 @@ set_pioinfo_extra(void) /* not found, maybe something wrong... */ pioinfo_extra = 0; } +#endif } #else #define pioinfo_extra 0 @@ -2363,16 +2410,16 @@ init_stdhandle(void) (fd)) if (fileno(stdin) < 0) { - stdin->_file = open_null(0); + freopen("NUL", "r+b", stdin); } else { setmode(fileno(stdin), O_BINARY); } if (fileno(stdout) < 0) { - stdout->_file = open_null(1); + freopen("NUL", "r+b", stdout); } if (fileno(stderr) < 0) { - stderr->_file = open_null(2); + freopen("NUL", "r+b", stderr); } if (nullfd >= 0 && !keep) close(nullfd); setvbuf(stderr, NULL, _IONBF, 0); @@ -5332,12 +5379,16 @@ read(int fd, void *buf, size_t size) #define FILE_COUNT _cnt #define FILE_READPTR _ptr -#undef fgetc +/*#undef fgetc*/ /* License: Ruby's */ int rb_w32_getc(FILE* stream) { int c; +#if RUBY_MSVCRT_VERSION >= 140 + c = _fgetc_nolock(stream); + catch_interrupt(); +#else if (enough_to_get(stream->FILE_COUNT)) { c = (unsigned char)*stream->FILE_READPTR++; } @@ -5350,14 +5401,19 @@ rb_w32_getc(FILE* stream) #endif catch_interrupt(); } +#endif return c; } -#undef fputc +/* #undef fputc */ /* License: Ruby's */ int rb_w32_putc(int c, FILE* stream) { +#if RUBY_MSVCRT_VERSION >= 140 + c = _fputc_nolock(c, stream); + catch_interrupt(); +#else if (enough_to_put(stream->FILE_COUNT)) { c = (unsigned char)(*stream->FILE_READPTR++ = (char)c); } @@ -5365,6 +5421,7 @@ rb_w32_putc(int c, FILE* stream) c = _flsbuf(c, stream); catch_interrupt(); } +#endif return c; }