From: Gurusamy Sarathy Date: Tue, 25 Jan 2000 22:16:19 +0000 (+0000) Subject: eliminate need for perl95.exe on Windows 9x by working around CRT X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=9e5f57defb0d4fe4a23e6e24c3d57478465aea87;p=p5sagit%2Fp5-mst-13.2.git eliminate need for perl95.exe on Windows 9x by working around CRT bug internally (from Benjamin Stuhl ); modified to call the fixed version of open_osfhandle() only on Windows 9x; updated the makefiles and README.win32 to suit p4raw-id: //depot/perl@4892 --- diff --git a/README.win32 b/README.win32 index 1623acf..d5adfd7 100644 --- a/README.win32 +++ b/README.win32 @@ -215,21 +215,6 @@ The build process may produce "harmless" compiler warnings (more or less copiously, depending on how picky your compiler gets). The maintainers are aware of these warnings, thankyouverymuch. :) -When building using Visual C++, a perl95.exe will also get built. This -executable is only needed on Windows95, and should be used instead of -perl.exe, and then only if you want sockets to work properly on Windows95. -This is necessitated by a bug in the Microsoft C Runtime that cannot be -worked around in the "normal" perl.exe. perl95.exe gets built with its -own private copy of the C Runtime that is not accessible to extensions -(which see the DLL version of the CRT). Be aware, therefore, that this -perl95.exe will have esoteric problems with extensions like perl/Tk that -themselves use the C Runtime heavily, or want to free() pointers -malloc()-ed by perl. - -You can avoid the perl95.exe problems completely if you either enable -USE_PERLCRT with Visual C++, or use Borland C++ for building perl. In -those cases, perl95.exe is not needed and will not be built. - =back =head2 Testing diff --git a/win32/Makefile b/win32/Makefile index 2a00255..e4f3d86 100644 --- a/win32/Makefile +++ b/win32/Makefile @@ -107,7 +107,6 @@ INST_ARCH = \$(ARCHNAME) # Not recommended if you have VC 6.x and you're not running Windows 9x. # #USE_PERLCRT = define -#BUILD_FOR_WIN95 = define # # uncomment to enable linking with setargv.obj under the Visual C @@ -482,10 +481,6 @@ MAKE = nmake -nologo CFGSH_TMPL = config.vc CFGH_TMPL = config_H.vc -!IF "$(BUILD_FOR_WIN95)" == "define" -PERL95EXE = ..\perl95.exe -!ENDIF - XCOPY = xcopy /f /r /i /d RCOPY = xcopy /f /r /i /e /d NOOP = @echo @@ -549,15 +544,6 @@ WIN32_SRC = $(WIN32_SRC) .\win32thread.c WIN32_SRC = $(WIN32_SRC) .\$(CRYPT_SRC) !ENDIF -PERL95_SRC = \ - perl95.c \ - win32mt.c \ - win32sckmt.c - -!IF "$(CRYPT_SRC)" != "" -PERL95_SRC = $(PERL95_SRC) .\$(CRYPT_SRC) -!ENDIF - DLL_SRC = $(DYNALOADER).c X2P_SRC = \ @@ -620,7 +606,6 @@ MINICORE_OBJ = $(MICROCORE_OBJ:..\=.\mini\) \ $(MINIDIR)\perlio$(o) MINIWIN32_OBJ = $(WIN32_OBJ:.\=.\mini\) MINI_OBJ = $(MINICORE_OBJ) $(MINIWIN32_OBJ) -PERL95_OBJ = $(PERL95_SRC:.c=.obj) DLL_OBJ = $(DLL_SRC:.c=.obj) X2P_OBJ = $(X2P_SRC:.c=.obj) @@ -629,7 +614,6 @@ PERLEXE_OBJ = perlmain$(o) PERLDLL_OBJ = $(PERLDLL_OBJ) $(WIN32_OBJ) $(DLL_OBJ) #PERLEXE_OBJ = $(PERLEXE_OBJ) $(WIN32_OBJ) $(DLL_OBJ) -#PERL95_OBJ = $(PERL95_OBJ) DynaLoadmt$(o) !IF "$(USE_SETARGV)" != "" SETARGV_OBJ = setargv$(o) @@ -749,7 +733,7 @@ CFG_VARS = \ # Top targets # -all : .\config.h $(GLOBEXE) $(MINIMOD) $(CONFIGPM) $(PERLEXE) $(PERL95EXE) \ +all : .\config.h $(GLOBEXE) $(MINIMOD) $(CONFIGPM) $(PERLEXE) \ $(X2P) $(EXTENSION_DLL) $(EXTENSION_PM) $(DYNALOADER)$(o) : $(DYNALOADER).c $(CORE_H) $(EXTDIR)\DynaLoader\dlutils.c @@ -823,7 +807,6 @@ $(MINI_OBJ) : $(CORE_NOCFG_H) $(WIN32_OBJ) : $(CORE_H) $(CORE_OBJ) : $(CORE_H) $(DLL_OBJ) : $(CORE_H) -$(PERL95_OBJ) : $(CORE_H) $(X2P_OBJ) : $(CORE_H) perldll.def : $(MINIPERL) $(CONFIGPM) ..\global.sym ..\pp.sym ..\makedef.pl @@ -875,33 +858,6 @@ $(PERLEXE): $(PERLDLL) $(CONFIGPM) $(PERLEXE_OBJ) $(PERLEXE_RES) copy splittree.pl .. $(MINIPERL) -I..\lib ..\splittree.pl "../LIB" $(AUTODIR) -!IF "$(BUILD_FOR_WIN95)" == "define" - -perl95.c : runperl.c - copy runperl.c perl95.c - -perl95$(o) : perl95.c - $(CC) $(CFLAGS_O) -MT -UPERLDLL -DWIN95FIX -c perl95.c - -win32sckmt$(o) : win32sck.c - $(CC) $(CFLAGS_O) -MT -UPERLDLL -DWIN95FIX -c \ - $(OBJOUT_FLAG)win32sckmt$(o) win32sck.c - -win32mt$(o) : win32.c - $(CC) $(CFLAGS_O) -MT -UPERLDLL -DWIN95FIX -c \ - $(OBJOUT_FLAG)win32mt$(o) win32.c - -DynaLoadmt$(o) : $(DYNALOADER).c - $(CC) $(CFLAGS_O) -MT -UPERLDLL -DWIN95FIX -c \ - $(OBJOUT_FLAG)DynaLoadmt$(o) $(DYNALOADER).c - -$(PERL95EXE): $(PERLDLL) $(CONFIGPM) $(PERL95_OBJ) - $(LINK32) -subsystem:console -nodefaultlib -out:$@ $(LINK_FLAGS) \ - $(LIBBASEFILES) $(PERL95_OBJ) $(SETARGV_OBJ) $(PERLIMPLIB) \ - libcmt.lib - -!ENDIF - $(DYNALOADER).c: $(MINIPERL) $(EXTDIR)\DynaLoader\dl_win32.xs $(CONFIGPM) if not exist $(AUTODIR) mkdir $(AUTODIR) cd $(EXTDIR)\$(*B) @@ -1028,7 +984,7 @@ utils: $(PERLEXE) $(X2P) $(PERLEXE) $(PL2BAT) $(UTILS) distclean: clean - -del /f $(MINIPERL) $(PERLEXE) $(PERL95EXE) $(PERLDLL) $(GLOBEXE) \ + -del /f $(MINIPERL) $(PERLEXE) $(PERLDLL) $(GLOBEXE) \ $(PERLIMPLIB) ..\miniperl.lib $(MINIMOD) -del /f *.def *.map -del /f $(EXTENSION_DLL) $(EXTENSION_PM) @@ -1059,7 +1015,6 @@ distclean: clean cd ..\win32 -del /f ..\config.sh ..\splittree.pl perlmain.c dlutils.c config.h.new -del /f $(CONFIGPM) - -del /f perl95.c -del /f bin\*.bat cd $(EXTDIR) -del /s *.lib *.def *.map *.pdb *.bs Makefile *$(o) pm_to_blib @@ -1071,9 +1026,6 @@ install : all installbare installhtml installbare : utils $(PERLEXE) ..\installperl -!IF "$(BUILD_FOR_WIN95)" == "define" - $(XCOPY) $(PERL95EXE) $(INST_BIN)\*.* -!ENDIF if exist $(WPERLEXE) $(XCOPY) $(WPERLEXE) $(INST_BIN)\*.* $(XCOPY) $(GLOBEXE) $(INST_BIN)\*.* $(XCOPY) bin\*.bat $(INST_SCRIPT)\*.* diff --git a/win32/makefile.mk b/win32/makefile.mk index 5736366..6d13e10 100644 --- a/win32/makefile.mk +++ b/win32/makefile.mk @@ -600,9 +600,6 @@ PERLIMPLIB = ..\libperl$(a) CFGSH_TMPL = config.vc CFGH_TMPL = config_H.vc -.IF "$(USE_PERLCRT)" != "define" -PERL95EXE = ..\perl95.exe -.ENDIF .ENDIF @@ -671,15 +668,6 @@ WIN32_SRC += .\win32thread.c WIN32_SRC += .\$(CRYPT_SRC) .ENDIF -PERL95_SRC = \ - perl95.c \ - win32mt.c \ - win32sckmt.c - -.IF "$(CRYPT_SRC)" != "" -PERL95_SRC += .\$(CRYPT_SRC) -.ENDIF - DLL_SRC = $(DYNALOADER).c X2P_SRC = \ @@ -740,7 +728,6 @@ WIN32_OBJ = $(WIN32_SRC:db:+$(o)) MINICORE_OBJ = $(MINIDIR)\{$(MICROCORE_OBJ:f) miniperlmain$(o) perlio$(o)} MINIWIN32_OBJ = $(MINIDIR)\{$(WIN32_OBJ:f)} MINI_OBJ = $(MINICORE_OBJ) $(MINIWIN32_OBJ) -PERL95_OBJ = $(PERL95_SRC:db:+$(o)) DLL_OBJ = $(DLL_SRC:db:+$(o)) X2P_OBJ = $(X2P_SRC:db:+$(o)) @@ -887,7 +874,7 @@ RIGHTMAKE = __not_needed # all : .\config.h $(GLOBEXE) $(MINIPERL) $(MK2) \ - $(RIGHTMAKE) $(MINIMOD) $(CONFIGPM) $(PERLEXE) $(PERL95EXE) \ + $(RIGHTMAKE) $(MINIMOD) $(CONFIGPM) $(PERLEXE) \ $(X2P) $(EXTENSION_DLL) $(EXTENSION_PM) $(DYNALOADER)$(o) : $(DYNALOADER).c $(CORE_H) $(EXTDIR)\DynaLoader\dlutils.c @@ -1026,7 +1013,6 @@ $(MINI_OBJ) : $(CORE_NOCFG_H) $(WIN32_OBJ) : $(CORE_H) $(CORE_OBJ) : $(CORE_H) $(DLL_OBJ) : $(CORE_H) -$(PERL95_OBJ) : $(CORE_H) $(X2P_OBJ) : $(CORE_H) perldll.def : $(MINIPERL) $(CONFIGPM) ..\global.sym ..\pp.sym ..\makedef.pl @@ -1114,37 +1100,6 @@ $(PERLEXE): $(PERLDLL) $(CONFIGPM) $(PERLEXE_OBJ) $(PERLEXE_RES) copy splittree.pl .. $(MINIPERL) -I..\lib ..\splittree.pl "../LIB" $(AUTODIR) -.IF "$(CCTYPE)" != "BORLAND" -.IF "$(CCTYPE)" != "GCC" -.IF "$(USE_PERLCRT)" != "define" - -perl95.c : runperl.c - copy runperl.c perl95.c - -perl95$(o) : perl95.c - $(CC) $(CFLAGS_O) -MT -UPERLDLL -DWIN95FIX -c perl95.c - -win32sckmt$(o) : win32sck.c - $(CC) $(CFLAGS_O) -MT -UPERLDLL -DWIN95FIX -c \ - $(OBJOUT_FLAG)win32sckmt$(o) win32sck.c - -win32mt$(o) : win32.c - $(CC) $(CFLAGS_O) -MT -UPERLDLL -DWIN95FIX -c \ - $(OBJOUT_FLAG)win32mt$(o) win32.c - -DynaLoadmt$(o) : $(DYNALOADER).c - $(CC) $(CFLAGS_O) -MT -UPERLDLL -DWIN95FIX -c \ - $(OBJOUT_FLAG)DynaLoadmt$(o) $(DYNALOADER).c - -$(PERL95EXE): $(PERLDLL) $(CONFIGPM) $(PERL95_OBJ) - $(LINK32) -subsystem:console -nodefaultlib -out:$@ $(BLINK_FLAGS) \ - $(LIBBASEFILES) $(PERL95_OBJ) $(SETARGV_OBJ) $(PERLIMPLIB) \ - libcmt.lib - -.ENDIF -.ENDIF -.ENDIF - $(DYNALOADER).c: $(MINIPERL) $(EXTDIR)\DynaLoader\dl_win32.xs $(CONFIGPM) if not exist $(AUTODIR) mkdir $(AUTODIR) cd $(EXTDIR)\$(*B) && ..\$(MINIPERL) -I..\..\lib $(*B)_pm.PL @@ -1249,7 +1204,7 @@ utils: $(PERLEXE) $(X2P) $(PERLEXE) $(PL2BAT) $(UTILS) distclean: clean - -del /f $(MINIPERL) $(PERLEXE) $(PERL95EXE) $(PERLDLL) $(GLOBEXE) \ + -del /f $(MINIPERL) $(PERLEXE) $(PERLDLL) $(GLOBEXE) \ $(PERLIMPLIB) ..\miniperl$(a) $(MINIMOD) -del /f *.def *.map -del /f $(EXTENSION_DLL) $(EXTENSION_PM) @@ -1275,9 +1230,6 @@ distclean: clean -cd ..\x2p && del /f find2perl s2p *.bat -del /f ..\config.sh ..\splittree.pl perlmain.c dlutils.c config.h.new -del /f $(CONFIGPM) -.IF "$(PERL95EXE)" != "" - -del /f perl95.c -.ENDIF -del /f bin\*.bat -cd $(EXTDIR) && del /s *$(a) *.def *.map *.pdb *.bs Makefile *$(o) \ pm_to_blib @@ -1288,9 +1240,6 @@ install : all installbare installhtml installbare : $(RIGHTMAKE) utils $(PERLEXE) ..\installperl -.IF "$(PERL95EXE)" != "" - $(XCOPY) $(PERL95EXE) $(INST_BIN)\*.* -.ENDIF if exist $(WPERLEXE) $(XCOPY) $(WPERLEXE) $(INST_BIN)\*.* $(XCOPY) $(GLOBEXE) $(INST_BIN)\*.* $(XCOPY) bin\*.bat $(INST_SCRIPT)\*.* diff --git a/win32/win32.c b/win32/win32.c index 22842ea..49a8dee 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -1747,53 +1747,70 @@ win32_crypt(const char *txt, const char *salt) #endif } -#ifdef USE_FIXED_OSFHANDLE +/* C doesn't like repeat struct definitions */ + +#if defined(USE_FIXED_OSFHANDLE) || defined(PERL_MSVCRT_READFIX) -EXTERN_C int __cdecl _alloc_osfhnd(void); -EXTERN_C int __cdecl _set_osfhnd(int fh, long value); -EXTERN_C void __cdecl _lock_fhandle(int); -EXTERN_C void __cdecl _unlock_fhandle(int); -EXTERN_C void __cdecl _unlock(int); +#ifndef _CRTIMP +#define _CRTIMP __declspec(dllimport) +#endif -#if (_MSC_VER >= 1000) -typedef struct { +/* + * Control structure for lowio file handles + */ +typedef struct { long 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 */ -#if defined (_MT) && !defined (DLL_FOR_WIN32S) int lockinitflag; CRITICAL_SECTION lock; -#endif /* defined (_MT) && !defined (DLL_FOR_WIN32S) */ -} ioinfo; +} ioinfo; + + +/* + * Array of arrays of control structures for lowio files. + */ +EXTERN_C _CRTIMP ioinfo* __pioinfo[]; + +/* + * Definition of IOINFO_L2E, the log base 2 of the number of elements in each + * array of ioinfo structs. + */ +#define IOINFO_L2E 5 + +/* + * Definition of IOINFO_ARRAY_ELTS, the number of elements in ioinfo array + */ +#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) -EXTERN_C ioinfo * __pioinfo[]; +/* + * Access macros for getting at an ioinfo struct and its fields from a + * file handle + */ +#define _pioinfo(i) (__pioinfo[(i) >> IOINFO_L2E] + ((i) & (IOINFO_ARRAY_ELTS - 1))) +#define _osfhnd(i) (_pioinfo(i)->osfhnd) +#define _osfile(i) (_pioinfo(i)->osfile) +#define _pipech(i) (_pioinfo(i)->pipech) -#define IOINFO_L2E 5 -#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) -#define _pioinfo(i) (__pioinfo[i >> IOINFO_L2E] + (i & (IOINFO_ARRAY_ELTS - 1))) -#define _osfile(i) (_pioinfo(i)->osfile) +#endif -#else /* (_MSC_VER >= 1000) */ -extern char _osfile[]; -#endif /* (_MSC_VER >= 1000) */ +#ifdef USE_FIXED_OSFHANDLE #define FOPEN 0x01 /* file handle open */ #define FAPPEND 0x20 /* file handle opened O_APPEND */ #define FDEV 0x40 /* file handle refers to device */ #define FTEXT 0x80 /* file handle is in text mode */ -#define _STREAM_LOCKS 26 /* Table of stream locks */ -#define _LAST_STREAM_LOCK (_STREAM_LOCKS+_NSTREAM_-1) /* Last stream lock */ -#define _FH_LOCKS (_LAST_STREAM_LOCK+1) /* Table of fh locks */ - /*** *int my_open_osfhandle(long osfhandle, int flags) - open C Runtime file handle * *Purpose: * This function allocates a free C Runtime file handle and associates * it with the Win32 HANDLE specified by the first parameter. This is a -* temperary fix for WIN95's brain damage GetFileType() error on socket -* we just bypass that call for socket +* temperary fix for WIN95's brain damage GetFileType() error on socket +* we just bypass that call for socket +* +* This works with MSVC++ 4.0+ or GCC/Mingw32 * *Entry: * long osfhandle - Win32 HANDLE to associate with C Runtime file handle. @@ -1807,6 +1824,30 @@ extern char _osfile[]; * *******************************************************************************/ +/* + * we fake up some parts of the CRT that aren't exported by MSVCRT.dll + * this lets sockets work on Win9X with GCC and should fix the problems + * with perl95.exe + * -- BKS, 1-23-2000 +*/ + +/* since we are not doing a dup2(), this works fine */ + +#define _set_osfhnd(fh, osfh) (void)(_osfhnd(fh) = osfh) + +/* create an ioinfo entry, kill its handle, and steal the entry */ + +static int _alloc_osfhnd() +{ + HANDLE hF = CreateFile("NUL", 0, 0, NULL, OPEN_ALWAYS, 0, NULL); + int fh = _open_osfhandle(hF, 0); + CloseHandle(hF); + if (fh == -1) + return fh; + EnterCriticalSection(&(_pioinfo(fh)->lock)); + return fh; +} + static int my_open_osfhandle(long osfhandle, int flags) { @@ -1834,18 +1875,12 @@ my_open_osfhandle(long osfhandle, int flags) fileflags |= FOPEN; /* mark as open */ -#if (_MSC_VER >= 1000) _osfile(fh) = fileflags; /* set osfile entry */ - _unlock_fhandle(fh); -#else - _osfile[fh] = fileflags; /* set osfile entry */ - _unlock(fh+_FH_LOCKS); /* unlock handle */ -#endif + LeaveCritiicalSection(&_pioinfo(fh)->lock); return fh; /* return handle */ } -#define _open_osfhandle my_open_osfhandle #endif /* USE_FIXED_OSFHANDLE */ /* simulate flock by locking a range on the file */ @@ -2636,43 +2671,6 @@ win32_dup2(int fd1,int fd2) #define FTEXT 0x80 /* file handle is in text mode */ #define MAX_DESCRIPTOR_COUNT (64*32) /* this is the maximun that MSVCRT can handle */ -/* - * Control structure for lowio file handles - */ -typedef struct { - long 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 */ - int lockinitflag; - CRITICAL_SECTION lock; -} ioinfo; - - -/* - * Array of arrays of control structures for lowio files. - */ -EXTERN_C _CRTIMP ioinfo* __pioinfo[]; - -/* - * Definition of IOINFO_L2E, the log base 2 of the number of elements in each - * array of ioinfo structs. - */ -#define IOINFO_L2E 5 - -/* - * Definition of IOINFO_ARRAY_ELTS, the number of elements in ioinfo array - */ -#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) - -/* - * Access macros for getting at an ioinfo struct and its fields from a - * file handle - */ -#define _pioinfo(i) (__pioinfo[(i) >> IOINFO_L2E] + ((i) & (IOINFO_ARRAY_ELTS - 1))) -#define _osfhnd(i) (_pioinfo(i)->osfhnd) -#define _osfile(i) (_pioinfo(i)->osfile) -#define _pipech(i) (_pioinfo(i)->pipech) - int __cdecl _fixed_read(int fh, void *buf, unsigned cnt) { int bytes_read; /* number of bytes read */ @@ -3405,6 +3403,10 @@ win32_free(void *block) int win32_open_osfhandle(long handle, int flags) { +#ifdef USE_FIXED_OSFHANDLE + if (IsWin95()) + return my_open_osfhandle(handle, flags); +#endif return _open_osfhandle(handle, flags); } diff --git a/win32/win32.h b/win32/win32.h index d447f2b..066ed72 100644 --- a/win32/win32.h +++ b/win32/win32.h @@ -130,9 +130,11 @@ struct utsname { * facilities for accessing the same. See note in util.c/my_setenv(). */ /*#define USE_WIN32_RTL_ENV */ -/* Define USE_FIXED_OSFHANDLE to fix VC's _open_osfhandle() on W95. - * Can only enable it if not using the DLL CRT (it doesn't expose internals) */ -#if defined(_MSC_VER) && !defined(_DLL) && defined(_M_IX86) +/* Define USE_FIXED_OSFHANDLE to fix MSVCRT's _open_osfhandle() on W95. + It now uses some black magic to work seamlessly with the DLL CRT and + works with MSVC++ 4.0+ or GCC/Mingw32 + -- BKS 1-24-2000 */ +#if (defined(_M_IX86) && _MSC_VER >= 1000) || defined(__MINGW32__) #define USE_FIXED_OSFHANDLE #endif