diff options
Diffstat (limited to 'win32')
-rw-r--r-- | win32/Makefile.sub | 73 | ||||
-rwxr-xr-x | win32/configure.bat | 11 | ||||
-rw-r--r-- | win32/file.c | 33 | ||||
-rw-r--r-- | win32/file.h | 3 | ||||
-rwxr-xr-x | win32/mkexports.rb | 2 | ||||
-rw-r--r-- | win32/setup.mak | 17 | ||||
-rw-r--r-- | win32/win32.c | 157 |
7 files changed, 215 insertions, 81 deletions
diff --git a/win32/Makefile.sub b/win32/Makefile.sub index 7b56e43511..c73a8a4ba5 100644 --- a/win32/Makefile.sub +++ b/win32/Makefile.sub @@ -11,13 +11,15 @@ PATH_SEPARATOR = ; TZ = # skip timezone tests PWD = $(MAKEDIR) empty = +tooldir = $(srcdir)/tool !ifndef MFLAGS MFLAGS=-l !endif !if "$(BASERUBY)" == "" -! if [for %I in (ruby.exe) do @echo BASERUBY = %~s$$PATH:I > baseruby.mk] +! if [ruby $(tooldir)/missing-baseruby.bat 2> nul] +! else if [for %I in (ruby.exe) do @echo BASERUBY = %~s$$PATH:I > baseruby.mk] ! else ! include baseruby.mk ! endif @@ -27,7 +29,7 @@ MFLAGS=-l BASERUBY = !endif !if "$(BASERUBY)" == "" -BASERUBY = echo executable host ruby is required. use --with-baseruby option.^& exit 1 +BASERUBY = $(tooldir:/=\)\missing-baseruby.bat HAVE_BASERUBY = no !else HAVE_BASERUBY = yes @@ -158,6 +160,9 @@ OPTFLAGS = -O2b2xg- OPTFLAGS = -O2sy- !endif !endif +!if !defined(incflags) +incflags = +!endif !if !defined(PLATFORM) PLATFORM = mswin32 !endif @@ -292,9 +297,7 @@ CXXFLAGS = $(CFLAGS) !if !defined(LDFLAGS) LDFLAGS = -incremental:no -debug -opt:ref -opt:icf !endif -!if !defined(XLDFLAGS) -XLDFLAGS = -stack:$(STACK) -!endif +XLDFLAGS = -stack:$(STACK) $(XLDFLAGS) !if !defined(RFLAGS) RFLAGS = -r !endif @@ -330,8 +333,7 @@ COROUTINE_SRC = $(COROUTINE_OBJ:.obj=.asm) COROUTINE_OBJ = coroutine/win32/Context.obj COROUTINE_SRC = $(COROUTINE_OBJ:.obj=.asm) !else -COROUTINE_OBJ = coroutine/copy/Context.obj -COROUTINE_SRC = $(COROUTINE_OBJ:.obj=.c) +!error copy coroutine has been replaced with pthread implementation at 42130a64f02294dc8025af3a51bda518c67ab33d !endif COROUTINE_H = $(COROUTINE_OBJ:.obj=.h) @@ -339,7 +341,9 @@ ARFLAGS = -machine:$(MACHINE) -out: LD = $(CC) LDSHARED = $(LD) -LD XCFLAGS = -DRUBY_EXPORT $(INCFLAGS) $(XCFLAGS) -!if $(MSC_VER) >= 1400 +!if $(MSC_VER) >= 1800 +LDFLAGS = $(LDFLAGS) -manifest:embed,ID=2 +!elseif $(MSC_VER) >= 1400 # Prevents VC++ 2005 (cl ver 14) warnings MANIFESTTOOL = mt -nologo LDSHARED_0 = @if exist $(@).manifest $(MINIRUBY) -run -e wait_writable -- -n 10 $@ @@ -433,8 +437,10 @@ THREAD_IMPL_SRC = thread_$(THREAD_MODEL).c !if "$(CROSS_COMPILING)" == "yes" PREP = $(arch)-fake.rb +BUILTIN_BINARY = no !else PREP = miniruby$(EXEEXT) +BUILTIN_BINARY = yes !endif !if !defined(EXTSTATIC) @@ -482,7 +488,6 @@ EXTOBJS = dmyext.$(OBJEXT) arch_hdrdir = $(EXTOUT)/include/$(arch) top_srcdir = $(srcdir) hdrdir = $(srcdir)/include -tooldir = $(srcdir)/tool VPATH = $(arch_hdrdir)/ruby;$(hdrdir)/ruby;$(srcdir);$(srcdir)/missing;$(win_srcdir) !ifndef GIT @@ -545,8 +550,9 @@ GOLF_PRELUDE_C = golf_prelude.c RBCONFIG = ./.rbconfig.time !if "$(GITHUB_ACTIONS)" == "true" -ACTIONS_GROUP = @echo ^#^#[group]$(@:yes-=) -ACTIONS_ENDGROUP = @echo ^#^#[endgroup] +# 93(bright yellow) is copied from .github/workflows/mingw.yml +ACTIONS_GROUP = @echo ::group::[93m$(@:yes-=)[m +ACTIONS_ENDGROUP = @echo ::endgroup:: !else ACTIONS_GROUP = @:: $(empty) ACTIONS_ENDGROUP = @:: @@ -678,7 +684,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub #define _INTEGRAL_MAX_BITS 64 #endif #define SIZEOF_OFF_T 8 -!if "$(ARCH)" == "x64" +!if "$(TARGET_OS)" == "mswin64" #define SIZEOF_VOIDP 8 !else #define SIZEOF_VOIDP 4 @@ -700,7 +706,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub #define NUM2CLOCKID(v) NUM2INT(v) #define SIZEOF_CLOCK_T 4 #define SIZEOF_RLIM_T 0 -!if "$(ARCH)" == "x64" +!if "$(TARGET_OS)" == "mswin64" #define SIZEOF_SIZE_T 8 #define SIZEOF_PTRDIFF_T 8 #define SIZEOF_INTPTR_T 8 @@ -740,6 +746,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub #define RBIMPL_ATTR_PACKED_STRUCT_END() __pragma(pack(pop)) !endif #define RUBY_EXTERN extern __declspec(dllimport) +#define RUBY_FUNC_EXPORTED extern __declspec(dllexport) #define RUBY_ALIGNAS(n) __declspec(align(n)) #define RUBY_ALIGNOF __alignof #define HAVE_DECL_SYS_NERR 1 @@ -757,6 +764,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub #define HAVE_STRUCT_TIMESPEC !endif !if $(MSC_VER) >= 1600 +#define HAVE_INTTYPES_H 1 #define HAVE_STDINT_H 1 !else #define int8_t signed char @@ -799,7 +807,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub #define HAVE_INTPTR_T 1 #define HAVE_UINTPTR_T 1 #define HAVE_SSIZE_T 1 -!if "$(ARCH)" == "x64" +!if "$(TARGET_OS)" == "mswin64" #define ssize_t __int64 #define PRI_PTR_PREFIX "I64" !else @@ -964,6 +972,7 @@ s,@WERRORFLAG@,$(WERRORFLAG),;t t s,@DEFS@,$(DEFS),;t t s,@CPPFLAGS@,$(CPPFLAGS),;t t s,@CXXFLAGS@,$(CXXFLAGS),;t t +s,@incflags@,$(incflags),;t t s,@FFLAGS@,$(FFLAGS),;t t s,@LDFLAGS@,$(LDFLAGS),;t t s,@LIBS@,user32.lib,;t t @@ -1071,7 +1080,7 @@ s,@LIBPATHFLAG@, -libpath:%s,;t t s,@RPATHFLAG@,,;t t s,@LIBARG@,%s.lib,;t t s,@LINK_SO@,$$(LDSHARED) -Fe$$(@) $$(OBJS) $$(LIBS) $$(LOCAL_LIBS) -link $$(DLDFLAGS) -implib:$$(*F:.so=)-$$(arch).lib -pdb:$$(*F:.so=)-$$(arch).pdb -def:$$(DEFFILE),;t t -!if $(MSC_VER) >= 1400 +!if $(MSC_VER) >= 1400 && $(MSC_VER) < 1800 s,@LINK_SO@,@if exist $$(@).manifest $$(RUBY) -run -e wait_writable -- -n 10 $$(@),;t t s,@LINK_SO@,@if exist $$(@).manifest $(MANIFESTTOOL) -manifest $$(@).manifest -outputresource:$$(@);2,;t t s,@LINK_SO@,@if exist $$(@).manifest $$(RM) $$(@:/=\).manifest,;t t @@ -1137,7 +1146,8 @@ miniruby: miniruby$(EXEEXT) miniruby$(EXEEXT): @echo $(LIBS) $(ECHO) linking $(@:\=/) - $(Q) $(PURIFY) $(CC) $(MAINOBJ) $(MINIOBJS) $(COMMONOBJS) $(LIBS) -Fe$@ -link $(LDFLAGS) + $(Q) $(PURIFY) $(CC) $(MAINOBJ) $(MINIOBJS) $(COMMONOBJS) $(LIBS) \ + $(OUTFLAG)$@ -link $(LDFLAGS) $(XLDFLAGS) @$(RM) miniruby.lib miniruby.exp $(Q) miniruby.exe -v $(Q) $(LDSHARED_1) @@ -1151,9 +1161,11 @@ $(PROGRAM): $(MAINOBJ) $(LIBRUBY_SO) $(RUBY_INSTALL_NAME).res $(ECHO) linking $(@:\=/) $(Q) $(PURIFY) $(CC) $(MAINOBJ) $(EXTOBJS) $(RUBY_INSTALL_NAME).res \ $(OUTFLAG)$@ $(LIBRUBYARG) -link $(LDFLAGS) $(XLDFLAGS) +! if defined(LDSHARED_0) $(Q) $(LDSHARED_0) $(Q) $(LDSHARED_1) $(Q) $(LDSHARED_2) +! endif !endif !if "$(WPROGRAM)" != "" @@ -1162,9 +1174,11 @@ $(WPROGRAM): $(MAINOBJ) $(WINMAINOBJ) $(LIBRUBY_SO) $(RUBYW_INSTALL_NAME).res $(Q) $(PURIFY) $(CC) $(MAINOBJ) $(WINMAINOBJ) \ $(RUBYW_INSTALL_NAME).res $(OUTFLAG)$@ $(LIBRUBYARG) \ -link $(LDFLAGS) $(XLDFLAGS) -subsystem:Windows +! if defined(LDSHARED_0) $(Q) $(LDSHARED_0) $(Q) $(LDSHARED_1) $(Q) $(LDSHARED_2) +! endif !endif !if "$(STUBPROGRAM)" != "" @@ -1172,9 +1186,11 @@ $(STUBPROGRAM): rubystub.$(OBJEXT) $(LIBRUBY) $(LIBRUBY_SO) $(RUBY_INSTALL_NAME) $(ECHO) linking $(@:\=/) $(Q) $(PURIFY) $(CC) rubystub.$(OBJEXT) $(RUBY_INSTALL_NAME).res \ $(OUTFLAG)$@ $(LIBRUBYARG) -link $(LDFLAGS) $(XLDFLAGS) +! if defined(LDSHARED_0) $(Q) $(LDSHARED_0) $(Q) $(LDSHARED_1) $(Q) $(LDSHARED_2) +! endif !endif !if "$(LIBRUBY_SO_UPDATE)" == "" @@ -1201,13 +1217,16 @@ $(LIBRUBY_SO): $(LIBRUBY_A) $(DLDOBJS) $(RUBYDEF) $(RUBY_SO_NAME).res !endif $(ECHO) linking shared-library $(@:\=/) $(Q) $(LDSHARED) $(DLDOBJS) $(LIBRUBY_A) \ - $(RUBY_SO_NAME).res $(SOLIBS) $(EXTSOLIBS) $(LIBS) -Fe$@ -link $(LDFLAGS) \ + $(RUBY_SO_NAME).res $(SOLIBS) $(EXTSOLIBS) $(LIBS) \ + $(OUTFLAG)$@ -link $(LDFLAGS) $(XLDFLAGS) \ $(LIBRUBY_DLDFLAGS) @$(RM) dummy.lib dummy.exp +!if defined(LDSHARED_0) $(Q) $(LDSHARED_0) $(Q) $(LDSHARED_1) $(Q) $(LDSHARED_2) # | findstr -v -c:LNK4049 -c:LNK4217 +!endif $(RUBYDEF): $(LIBRUBY_A) $(RBCONFIG) $(ECHO) generating $(@:\=/) @@ -1278,6 +1297,15 @@ $(ruby_pc): $(RBCONFIG) $(ECHO) assembling $(<:\=/) $(Q) $(AS) $(ASFLAGS) $(XCFLAGS) $(CPPFLAGS) $(COUTFLAG)$@ -c $(<:\=/) +{$(srcdir)/prism}.c.obj: + $(ECHO) compiling $(<:\=/) + $(Q) $(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$(<:\=/) +{$(srcdir)/prism/enc}.c.obj: + $(ECHO) compiling $(<:\=/) + $(Q) $(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$(<:\=/) +{$(srcdir)/prism/util}.c.obj: + $(ECHO) compiling $(<:\=/) + $(Q) $(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$(<:\=/) {$(srcdir)/enc/trans}.c.obj: $(ECHO) compiling $(<:\=/) $(Q) $(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$(<:\=/) @@ -1354,7 +1382,7 @@ probes.h: {$(VPATH)}probes.dmyh #include "$(*F).dmyh" <<KEEP -INSNS = opt_sc.inc optinsn.inc optunifs.inc insns.inc insns_info.inc \ +INSNS = optinsn.inc optunifs.inc insns.inc insns_info.inc \ vmtc.inc vm.inc !if [exit > insns_rules.mk] @@ -1403,9 +1431,16 @@ rubyspec-capiext: $(RUBYSPEC_CAPIEXT_EXTS) $(Q)$(MAKEDIRS) $(@D) $(Q)echo> $*.def EXPORTS $(Q)echo>> $*.def Init_$(*F) - $(Q)$(LDSHARED) -Fe$(@) $(INCFLAGS) $(CFLAGS) $(CPPFLAGS) $< $(LIBRUBYARG) -link $(DLDFLAGS) $(LIBS) $(LOCAL_LIBS) -implib:$*.lib -pdb:$*.pdb -def:$*.def + $(Q)$(LDSHARED) -Fe$(@) $(INCFLAGS) $(CFLAGS) $(CPPFLAGS) $< $(LIBRUBYARG) -link $(DLDFLAGS) $(XLDFLAGS) $(LIBS) $(LOCAL_LIBS) -implib:$*.lib -pdb:$*.pdb -def:$*.def +!if defined(LDSHARED_0) $(Q)$(LDSHARED_0) $(Q)$(LDSHARED_1) $(Q)$(LDSHARED_2) +!endif exts: rubyspec-capiext + +yesterday: + for /f "usebackq" %H in \ + (`$(GIT) -C $(srcdir) log -1 "--before=00:00+0900" "--format=%H"`) do \ + $(GIT) -C $(srcdir) reset --hard %%H diff --git a/win32/configure.bat b/win32/configure.bat index 7253ade28b..dd1a917adc 100755 --- a/win32/configure.bat +++ b/win32/configure.bat @@ -7,6 +7,9 @@ for %%I in (%0) do if /%%~dpI/ == /%CD%\/ ( exit /b 999
)
+set XINCFLAGS=
+set XLDFLAGS=
+
echo> ~tmp~.mak ####
echo>> ~tmp~.mak conf = %0
echo>> ~tmp~.mak $(conf): nul
@@ -48,7 +51,9 @@ if "%1" == "--with-git" goto :git if "%1" == "--without-git" goto :nogit
if "%1" == "--without-ext" goto :witharg
if "%1" == "--without-extensions" goto :witharg
+if "%1" == "--with-opt-dir" goto :opt-dir
if "%1" == "--with-gmp" goto :gmp
+if "%1" == "--with-gmp-dir" goto :gmp-dir
if "%opt:~0,10%" == "--without-" goto :withoutarg
if "%opt:~0,7%" == "--with-" goto :witharg
if "%1" == "-h" goto :help
@@ -217,6 +222,10 @@ goto :loop ; shift
shift
goto :loop ;
+:gmp-dir
+:opt-dir
+ set XINCFLAGS=%XINCFLAGS% -I%2/include
+ set XLDFLAGS=%XLDFLAGS% -libpath:%2/lib
:witharg
echo>>confargs.tmp %1=%2\
set witharg=1
@@ -263,6 +272,8 @@ cl -EP confargs.c > ~setup~.mak 2>nul if exist pathlist.tmp echo>>~setup~.mak PATH = $(pathlist:;=/bin;)$(PATH)
if exist pathlist.tmp echo>>~setup~.mak INCLUDE = $(pathlist:;=/include;)
if exist pathlist.tmp echo>>~setup~.mak LIB = $(pathlist:;=/lib;)
+echo>>~setup~.mak XINCFLAGS = %XINCFLAGS%
+echo>>~setup~.mak XLDFLAGS = %XLDFLAGS%
type>>~setup~.mak ~tmp~.mak
del *.tmp > nul
del ~tmp~.mak > nul
diff --git a/win32/file.c b/win32/file.c index 31cc1aff6e..5f5590d3c8 100644 --- a/win32/file.c +++ b/win32/file.c @@ -263,7 +263,7 @@ rb_default_home_dir(VALUE result) { WCHAR *dir = rb_w32_home_dir(); if (!dir) { - rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding `~'"); + rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding '~'"); } append_wstr(result, dir, -1, CP_UTF8, rb_utf8_encoding()); @@ -326,7 +326,7 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na whome = rb_w32_home_dir(); if (whome == NULL) { free(wpath); - rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding `~'"); + rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding '~'"); } whome_len = wcslen(whome); @@ -372,8 +372,7 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na result = append_wstr(result, wpath_pos + 1, user_length_in_path(wpath_pos + 1, wpath_len - 1), path_cp, path_encoding); - if (wpath) - free(wpath); + free(wpath); rb_exc_raise(rb_exc_new_str(rb_eArgError, result)); } @@ -390,7 +389,7 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na const long dir_len = RSTRING_LEN(dir); #if SIZEOF_INT < SIZEOF_LONG if ((long)(int)dir_len != dir_len) { - if (wpath) free(wpath); + free(wpath); rb_raise(rb_eRangeError, "base directory (%ld bytes) is too long", dir_len); } @@ -405,7 +404,7 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na if (whome == NULL) { free(wpath); free(wdir); - rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding `~'"); + rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding '~'"); } whome_len = wcslen(whome); @@ -452,11 +451,8 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na result = rb_str_new_cstr("can't find user "); result = append_wstr(result, wdir_pos + 1, user_length_in_path(wdir_pos + 1, wdir_len - 1), path_cp, path_encoding); - if (wpath) - free(wpath); - - if (wdir) - free(wdir); + free(wpath); + free(wdir); rb_exc_raise(rb_exc_new_str(rb_eArgError, result)); } @@ -573,17 +569,10 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na result = append_wstr(result, wfullpath, size, path_cp, path_encoding); /* TODO: better cleanup */ - if (buffer) - xfree(buffer); - - if (wpath) - free(wpath); - - if (wdir) - free(wdir); - - if (whome) - xfree(whome); + xfree(buffer); + free(wpath); + free(wdir); + xfree(whome); if (wfullpath != wfullpath_buffer) xfree(wfullpath); diff --git a/win32/file.h b/win32/file.h index 4f1f36a75c..7bf9868e7d 100644 --- a/win32/file.h +++ b/win32/file.h @@ -47,4 +47,7 @@ int fchmod(int fd, int mode); UINT rb_w32_filecp(void); WCHAR *rb_w32_home_dir(void); +rb_pid_t rb_w32_uspawn_process(int mode, const char *prog, char *const *argv, + int in_fd, int out_fd, int err_fd, DWORD flags); + #endif /* RUBY_WIN32_FILE_H */ diff --git a/win32/mkexports.rb b/win32/mkexports.rb index 2889908942..dd0fbf6313 100755 --- a/win32/mkexports.rb +++ b/win32/mkexports.rb @@ -151,7 +151,7 @@ class Exports::Cygwin < Exports end def each_line(objs, &block) - IO.foreach("|#{self.class.nm} --extern --defined #{objs.join(' ')}", &block) + IO.foreach("|#{self.class.nm} --extern-only --defined-only #{objs.join(' ')}", &block) end def each_export(objs) diff --git a/win32/setup.mak b/win32/setup.mak index c0074bf963..3b822a33c0 100644 --- a/win32/setup.mak +++ b/win32/setup.mak @@ -62,10 +62,17 @@ ENABLE_DEBUG_ENV = $(ENABLE_DEBUG_ENV) !if defined(RJIT_SUPPORT) RJIT_SUPPORT = $(RJIT_SUPPORT) !endif +!if defined(XINCFLAGS) +CPPFLAGS = $(XINCFLAGS) +!endif +!if defined(XLDFLAGS) +XLDFLAGS = $(XLDFLAGS) +!endif # TOOLS << !if defined(BASERUBY) + $(BASERUBY:/=\) "$(srcdir)/tool/missing-baseruby.bat" @echo BASERUBY = $(BASERUBY:/=\)>> $(MAKEFILE) !endif !if "$(RUBY_DEVEL)" == "yes" @@ -78,8 +85,13 @@ RJIT_SUPPORT = $(RJIT_SUPPORT) @echo HAVE_GIT = $(HAVE_GIT)>> $(MAKEFILE) !endif -!if "$(WITH_GMP)" == "yes" - @echo>>$(MAKEFILE) USE_GMP = 1 +!if "$(WITH_GMP)" != "no" + @($(CC) $(XINCFLAGS) <<conftest.c -link $(XLDFLAGS) gmp.lib > nul && (echo USE_GMP = yes) || exit /b 0) >>$(MAKEFILE) +#include <gmp.h> +mpz_t x; +int main(void) {mpz_init(x); return 0;} +<< + @$(WIN32DIR:/=\)\rm.bat conftest.* !endif -osname-section-: @@ -129,6 +141,7 @@ vs2022-fp-bug: /* compile with -O2 */ #include <math.h> #include <float.h> +#include <stdio.h> #define value_finite(d) 'f' #define value_infinity() 'i' diff --git a/win32/win32.c b/win32/win32.c index c2d12a79f4..0d9cc087dc 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -622,21 +622,24 @@ init_env(void) if (!GetEnvironmentVariableW(L"HOME", env, numberof(env))) { f = FALSE; - if (GetEnvironmentVariableW(L"HOMEDRIVE", env, numberof(env))) - len = lstrlenW(env); - else - len = 0; - if (GetEnvironmentVariableW(L"HOMEPATH", env + len, numberof(env) - len) || len) { - f = TRUE; - } - else if (GetEnvironmentVariableW(L"USERPROFILE", env, numberof(env))) { - f = TRUE; - } - else if (get_special_folder(CSIDL_PROFILE, env, numberof(env))) { + if (GetEnvironmentVariableW(L"USERPROFILE", env, numberof(env))) { f = TRUE; } - else if (get_special_folder(CSIDL_PERSONAL, env, numberof(env))) { - f = TRUE; + else { + if (GetEnvironmentVariableW(L"HOMEDRIVE", env, numberof(env))) + len = lstrlenW(env); + else + len = 0; + + if (GetEnvironmentVariableW(L"HOMEPATH", env + len, numberof(env) - len) || len) { + f = TRUE; + } + else if (get_special_folder(CSIDL_PROFILE, env, numberof(env))) { + f = TRUE; + } + else if (get_special_folder(CSIDL_PERSONAL, env, numberof(env))) { + f = TRUE; + } } if (f) { regulate_path(env); @@ -1537,7 +1540,8 @@ rb_w32_uspawn(int mode, const char *cmd, const char *prog) /* License: Artistic or GPL */ static rb_pid_t -w32_aspawn_flags(int mode, const char *prog, char *const *argv, DWORD flags, UINT cp) +w32_spawn_process(int mode, const char *prog, char *const *argv, + int in_fd, int out_fd, int err_fd, DWORD flags, UINT cp) { int c_switch = 0; size_t len; @@ -1548,9 +1552,20 @@ w32_aspawn_flags(int mode, const char *prog, char *const *argv, DWORD flags, UIN int e = 0; rb_pid_t ret = -1; VALUE v = 0; + HANDLE in_handle = NULL, out_handle = NULL, err_handle = NULL; if (check_spawn_mode(mode)) return -1; + if (in_fd >= 0) { + in_handle = (HANDLE)rb_w32_get_osfhandle(in_fd); + } + if (out_fd >= 0) { + out_handle = (HANDLE)rb_w32_get_osfhandle(out_fd); + } + if (err_fd >= 0) { + err_handle = (HANDLE)rb_w32_get_osfhandle(err_fd); + } + if (!prog) prog = argv[0]; if ((shell = w32_getenv("COMSPEC", cp)) && internal_cmd_match(prog, tmpnt = !is_command_com(shell))) { @@ -1598,7 +1613,7 @@ w32_aspawn_flags(int mode, const char *prog, char *const *argv, DWORD flags, UIN if (!e) { struct ChildRecord *child = FindFreeChildSlot(); - if (CreateChild(child, wcmd, wprog, NULL, NULL, NULL, flags)) { + if (CreateChild(child, wcmd, wprog, in_handle, out_handle, err_handle, flags)) { ret = child_result(child, mode); } } @@ -1613,21 +1628,21 @@ rb_pid_t rb_w32_aspawn_flags(int mode, const char *prog, char *const *argv, DWORD flags) { /* assume ACP */ - return w32_aspawn_flags(mode, prog, argv, flags, filecp()); + return w32_spawn_process(mode, prog, argv, -1, -1, -1, flags, filecp()); } /* License: Ruby's */ rb_pid_t rb_w32_uaspawn_flags(int mode, const char *prog, char *const *argv, DWORD flags) { - return w32_aspawn_flags(mode, prog, argv, flags, CP_UTF8); + return w32_spawn_process(mode, prog, argv, -1, -1, -1, flags, CP_UTF8); } /* License: Ruby's */ rb_pid_t rb_w32_aspawn(int mode, const char *prog, char *const *argv) { - return w32_aspawn_flags(mode, prog, argv, 0, filecp()); + return w32_spawn_process(mode, prog, argv, -1, -1, -1, 0, filecp()); } /* License: Ruby's */ @@ -1637,6 +1652,15 @@ rb_w32_uaspawn(int mode, const char *prog, char *const *argv) return rb_w32_uaspawn_flags(mode, prog, argv, 0); } +/* License: Ruby's */ +rb_pid_t +rb_w32_uspawn_process(int mode, const char *prog, char *const *argv, + int in_fd, int out_fd, int err_fd, DWORD flags) +{ + return w32_spawn_process(mode, prog, argv, in_fd, out_fd, err_fd, + flags, CP_UTF8); +} + /* License: Artistic or GPL */ typedef struct _NtCmdLineElement { struct _NtCmdLineElement *next; @@ -1926,7 +1950,7 @@ w32_cmdvector(const WCHAR *cmd, char ***vec, UINT cp, rb_encoding *enc) } } - curr = (NtCmdLineElement *)calloc(sizeof(NtCmdLineElement), 1); + curr = (NtCmdLineElement *)calloc(1, sizeof(NtCmdLineElement)); if (!curr) goto do_nothing; curr->str = rb_w32_wstr_to_mbstr(cp, base, len, &curr->len); curr->flags |= NTMALLOC; @@ -2132,7 +2156,7 @@ w32_wopendir(const WCHAR *wpath) // // Get us a DIR structure // - p = calloc(sizeof(DIR), 1); + p = calloc(1, sizeof(DIR)); if (p == NULL) return NULL; @@ -2369,10 +2393,8 @@ readdir_internal(DIR *dirp, BOOL (*conv)(const WCHAR *, const WCHAR *, struct di // // first set up the structure to return // - if (dirp->dirstr.d_name) - free(dirp->dirstr.d_name); - if (dirp->dirstr.d_altname) - free(dirp->dirstr.d_altname); + free(dirp->dirstr.d_name); + free(dirp->dirstr.d_altname); dirp->dirstr.d_altname = 0; dirp->dirstr.d_altlen = 0; conv(dirp->curr, dirp->curr + lstrlenW(dirp->curr) + 1, &dirp->dirstr, enc); @@ -2478,14 +2500,10 @@ void rb_w32_closedir(DIR *dirp) { if (dirp) { - if (dirp->dirstr.d_name) - free(dirp->dirstr.d_name); - if (dirp->dirstr.d_altname) - free(dirp->dirstr.d_altname); - if (dirp->start) - free(dirp->start); - if (dirp->bits) - free(dirp->bits); + free(dirp->dirstr.d_name); + free(dirp->dirstr.d_altname); + free(dirp->start); + free(dirp->bits); free(dirp); } } @@ -2597,9 +2615,73 @@ set_pioinfo_extra(void) * * https://bugs.ruby-lang.org/issues/18605 */ char *p = (char*)get_proc_address(UCRTBASE, "_isatty", NULL); - char *pend = p; /* _osfile(fh) & FDEV */ +#ifdef _M_ARM64 +#define IS_INSN(pc, name) ((*(pc) & name##_mask) == name##_id) + const int max_num_inst = 500; + uint32_t *start = (uint32_t*)p; + uint32_t *end_limit = (start + max_num_inst); + uint32_t *pc = start; + + if (!p) { + fprintf(stderr, "_isatty proc not found in " UCRTBASE "\n"); + _exit(1); + } + + /* end of function */ + const uint32_t ret_id = 0xd65f0000; + const uint32_t ret_mask = 0xfffffc1f; + for(; pc < end_limit; pc++) { + if (IS_INSN(pc, ret)) { + break; + } + } + if (pc == end_limit) { + fprintf(stderr, "end of _isatty not found in " UCRTBASE "\n"); + _exit(1); + } + + /* pioinfo instruction mark */ + const uint32_t adrp_id = 0x90000000; + const uint32_t adrp_mask = 0x9f000000; + const uint32_t add_id = 0x11000000; + const uint32_t add_mask = 0x3fc00000; + for(; pc > start; pc--) { + if (IS_INSN(pc, adrp) && IS_INSN(pc + 1, add)) { + break; + } + } + if(pc == start) { + fprintf(stderr, "pioinfo mark not found in " UCRTBASE "\n"); + _exit(1); + } + + /* We now point to instructions that load address of __pioinfo: + * adrp x8, 0x1801d8000 + * add x8, x8, #0xdb0 + * https://devblogs.microsoft.com/oldnewthing/20220809-00/?p=106955 + * The last adrp/add sequence before ret is what we are looking for. + */ + const uint32_t adrp_insn = *pc; + const uint32_t adrp_immhi = (adrp_insn & 0x00ffffe0) >> 5; + const uint32_t adrp_immlo = (adrp_insn & 0x60000000) >> (5 + 19 + 5); + /* imm = immhi:immlo:Zeros(12), 64 */ + const uint64_t adrp_imm = ((adrp_immhi << 2) | adrp_immlo) << 12; + /* base = PC64<63:12>:Zeros(12) */ + const uint64_t adrp_base = (uint64_t)pc & 0xfffffffffffff000; + + const uint32_t add_insn = *(pc + 1); + const uint32_t add_sh = (add_insn & 0x400000) >> (12 + 5 + 5); + /* case sh of + when '0' imm = ZeroExtend(imm12, datasize); + when '1' imm = ZeroExtend(imm12:Zeros(12), datasize); */ + const uint64_t add_imm = ((add_insn & 0x3ffc00) >> (5 + 5)) << (add_sh ? 12 : 0); + + __pioinfo = (ioinfo**)(adrp_base + adrp_imm + add_imm); +#else /* _M_ARM64 */ + char *pend = p; + # ifdef _WIN64 int32_t rel; char *rip; @@ -2649,7 +2731,8 @@ set_pioinfo_extra(void) #else __pioinfo = *(ioinfo***)(p); #endif -#endif +#endif /* _M_ARM64 */ +#endif /* RUBY_MSVCRT_VERSION */ int fd; fd = _open("NUL", O_RDONLY); @@ -4378,8 +4461,8 @@ freeifaddrs(struct ifaddrs *ifp) { while (ifp) { struct ifaddrs *next = ifp->ifa_next; - if (ifp->ifa_addr) ruby_xfree(ifp->ifa_addr); - if (ifp->ifa_name) ruby_xfree(ifp->ifa_name); + ruby_xfree(ifp->ifa_addr); + ruby_xfree(ifp->ifa_name); ruby_xfree(ifp); ifp = next; } @@ -7593,7 +7676,7 @@ rb_w32_write_console(uintptr_t strarg, int fd) } } RB_GC_GUARD(str); - if (wbuffer) free(wbuffer); + free(wbuffer); return (long)reslen; } |