Re: The Inaba patch for tr/// vs. use encoding
[p5sagit/p5-mst-13.2.git] / win32 / win32.c
index ba8c637..633dbbd 100644 (file)
@@ -15,7 +15,8 @@
 #define Win32_Winsock
 #endif
 #include <windows.h>
-#ifndef __MINGW32__    /* GCC/Mingw32-2.95.2 forgot the WINAPI on CommandLineToArgvW() */
+/* GCC-2.95.2/Mingw32-1.1 forgot the WINAPI on CommandLineToArgvW() */
+#if defined(__MINGW32__) && (__MINGW32_MAJOR_VERSION==1)       
 #  include <shellapi.h>
 #else
    LPWSTR* WINAPI CommandLineToArgvW(LPCWSTR lpCommandLine, int * pNumArgs);
@@ -60,8 +61,8 @@
 int _CRT_glob = 0;
 #endif
 
-#if defined(__MINGW32__)
-/* Mingw32 is missing some prototypes */
+#if defined(__MINGW32__) && (__MINGW32_MAJOR_VERSION==1)       
+/* Mingw32-1.1 is missing some prototypes */
 FILE * _wfopen(LPCWSTR wszFileName, LPCWSTR wszMode);
 FILE * _wfdopen(int nFd, LPCWSTR wszMode);
 FILE * _freopen(LPCWSTR wszFileName, LPCWSTR wszMode, FILE * pOldStream);
@@ -85,15 +86,13 @@ int _fcloseall();
 #  define win32_get_sitelib g_win32_get_sitelib
 #  undef win32_get_vendorlib
 #  define win32_get_vendorlib g_win32_get_vendorlib
-#  undef do_spawn
-#  define do_spawn g_do_spawn
 #  undef getlogin
 #  define getlogin g_getlogin
 #endif
 
 static void            get_shell(void);
 static long            tokenize(const char *str, char **dest, char ***destv);
-       int             do_spawn2(char *cmd, int exectype);
+static int             do_spawn2(pTHX_ char *cmd, int exectype);
 static BOOL            has_shell_metachars(char *ptr);
 static long            filetime_to_clock(PFILETIME ft);
 static BOOL            filetime_from_time(PFILETIME ft, time_t t);
@@ -516,12 +515,8 @@ get_shell(void)
 }
 
 int
-do_aspawn(void *vreally, void **vmark, void **vsp)
+Perl_do_aspawn(pTHX_ SV *really, SV **mark, SV **sp)
 {
-    dTHX;
-    SV *really = (SV*)vreally;
-    SV **mark = (SV**)vmark;
-    SV **sp = (SV**)vsp;
     char **argv;
     char *str;
     int status;
@@ -607,10 +602,9 @@ find_next_space(const char *s)
     return (char*)s;
 }
 
-int
-do_spawn2(char *cmd, int exectype)
+static int
+do_spawn2(pTHX_ char *cmd, int exectype)
 {
-    dTHX;
     char **a;
     char *s;
     char **argv;
@@ -700,21 +694,21 @@ do_spawn2(char *cmd, int exectype)
 }
 
 int
-do_spawn(char *cmd)
+Perl_do_spawn(pTHX_ char *cmd)
 {
-    return do_spawn2(cmd, EXECF_SPAWN);
+    return do_spawn2(aTHX_ cmd, EXECF_SPAWN);
 }
 
 int
-do_spawn_nowait(char *cmd)
+Perl_do_spawn_nowait(pTHX_ char *cmd)
 {
-    return do_spawn2(cmd, EXECF_SPAWN_NOWAIT);
+    return do_spawn2(aTHX_ cmd, EXECF_SPAWN_NOWAIT);
 }
 
 bool
 Perl_do_exec(pTHX_ char *cmd)
 {
-    do_spawn2(cmd, EXECF_EXEC);
+    do_spawn2(aTHX_ cmd, EXECF_EXEC);
     return FALSE;
 }
 
@@ -1651,6 +1645,38 @@ win32_utime(const char *filename, struct utimbuf *times)
     return rc;
 }
 
+typedef union {
+    unsigned __int64   ft_i64;
+    FILETIME           ft_val;
+} FT_t;
+
+#ifdef __GNUC__
+#define Const64(x) x##LL
+#else
+#define Const64(x) x##i64
+#endif
+/* Number of 100 nanosecond units from 1/1/1601 to 1/1/1970 */
+#define EPOCH_BIAS  Const64(116444736000000000)
+
+/* NOTE: This does not compute the timezone info (doing so can be expensive,
+ * and appears to be unsupported even by glibc) */
+DllExport int
+win32_gettimeofday(struct timeval *tp, void *not_used)
+{
+    FT_t ft;
+
+    /* this returns time in 100-nanosecond units  (i.e. tens of usecs) */
+    GetSystemTimeAsFileTime(&ft.ft_val);
+
+    /* seconds since epoch */
+    tp->tv_sec = (long)((ft.ft_i64 - EPOCH_BIAS) / Const64(10000000));
+
+    /* microseconds remaining */
+    tp->tv_usec = (long)((ft.ft_i64 / Const64(10)) % Const64(1000000));
+
+    return 0;
+}
+
 DllExport int
 win32_uname(struct utsname *name)
 {
@@ -1717,15 +1743,17 @@ win32_uname(struct utsname *name)
     /* machine (architecture) */
     {
        SYSTEM_INFO info;
+       DWORD procarch;
        char *arch;
        GetSystemInfo(&info);
 
 #if (defined(__BORLANDC__)&&(__BORLANDC__<=0x520)) \
  || (defined(__MINGW32__) && !defined(_ANONYMOUS_UNION))
-       switch (info.u.s.wProcessorArchitecture) {
+       procarch = info.u.s.wProcessorArchitecture;
 #else
-       switch (info.wProcessorArchitecture) {
+       procarch = info.wProcessorArchitecture;
 #endif
+       switch (procarch) {
        case PROCESSOR_ARCHITECTURE_INTEL:
            arch = "x86"; break;
        case PROCESSOR_ARCHITECTURE_MIPS:
@@ -1734,10 +1762,45 @@ win32_uname(struct utsname *name)
            arch = "alpha"; break;
        case PROCESSOR_ARCHITECTURE_PPC:
            arch = "ppc"; break;
-       default:
+#ifdef PROCESSOR_ARCHITECTURE_SHX
+       case PROCESSOR_ARCHITECTURE_SHX:
+           arch = "shx"; break;
+#endif
+#ifdef PROCESSOR_ARCHITECTURE_ARM
+       case PROCESSOR_ARCHITECTURE_ARM:
+           arch = "arm"; break;
+#endif
+#ifdef PROCESSOR_ARCHITECTURE_IA64
+       case PROCESSOR_ARCHITECTURE_IA64:
+           arch = "ia64"; break;
+#endif
+#ifdef PROCESSOR_ARCHITECTURE_ALPHA64
+       case PROCESSOR_ARCHITECTURE_ALPHA64:
+           arch = "alpha64"; break;
+#endif
+#ifdef PROCESSOR_ARCHITECTURE_MSIL
+       case PROCESSOR_ARCHITECTURE_MSIL:
+           arch = "msil"; break;
+#endif
+#ifdef PROCESSOR_ARCHITECTURE_AMD64
+       case PROCESSOR_ARCHITECTURE_AMD64:
+           arch = "amd64"; break;
+#endif
+#ifdef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
+       case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
+           arch = "ia32-64"; break;
+#endif
+#ifdef PROCESSOR_ARCHITECTURE_UNKNOWN
+       case PROCESSOR_ARCHITECTURE_UNKNOWN:
            arch = "unknown"; break;
+#endif
+       default:
+           sprintf(name->machine, "unknown(0x%x)", procarch);
+           arch = name->machine;
+           break;
        }
-       strcpy(name->machine, arch);
+       if (name->machine != arch)
+           strcpy(name->machine, arch);
     }
     return 0;
 }
@@ -2643,22 +2706,28 @@ win32_popen(const char *command, const char *mode)
 #ifdef USE_RTL_POPEN
     return _popen(command, mode);
 #else
+    dTHX;
     int p[2];
     int parent, child;
     int stdfd, oldfd;
     int ourmode;
     int childpid;
+    DWORD nhandle;
+    HANDLE old_h;
+    int lock_held = 0;
 
     /* establish which ends read and write */
     if (strchr(mode,'w')) {
         stdfd = 0;             /* stdin */
         parent = 1;
         child = 0;
+       nhandle = STD_INPUT_HANDLE;
     }
     else if (strchr(mode,'r')) {
         stdfd = 1;             /* stdout */
         parent = 0;
         child = 1;
+       nhandle = STD_OUTPUT_HANDLE;
     }
     else
         return NULL;
@@ -2674,7 +2743,7 @@ win32_popen(const char *command, const char *mode)
     /* the child doesn't inherit handles */
     ourmode |= O_NOINHERIT;
 
-    if (win32_pipe( p, 512, ourmode) == -1)
+    if (win32_pipe(p, 512, ourmode) == -1)
         return NULL;
 
     /* save current stdfd */
@@ -2689,12 +2758,25 @@ win32_popen(const char *command, const char *mode)
     /* close the child end in parent */
     win32_close(p[child]);
 
+    /* save the old std handle, and set the std handle */
+    OP_REFCNT_LOCK;
+    lock_held = 1;
+    old_h = GetStdHandle(nhandle);
+    SetStdHandle(nhandle, (HANDLE)_get_osfhandle(stdfd));
+
     /* start the child */
     {
        dTHX;
        if ((childpid = do_spawn_nowait((char*)command)) == -1)
            goto cleanup;
 
+       /* restore the old std handle */
+       if (lock_held) {
+           SetStdHandle(nhandle, old_h);
+           OP_REFCNT_UNLOCK;
+           lock_held = 0;
+       }
+
        /* revert stdfd to whatever it was before */
        if (win32_dup2(oldfd, stdfd) == -1)
            goto cleanup;
@@ -2717,6 +2799,11 @@ cleanup:
     /* we don't need to check for errors here */
     win32_close(p[0]);
     win32_close(p[1]);
+    if (lock_held) {
+       SetStdHandle(nhandle, old_h);
+       OP_REFCNT_UNLOCK;
+       lock_held = 0;
+    }
     if (oldfd != -1) {
         win32_dup2(oldfd, stdfd);
         win32_close(oldfd);
@@ -4020,7 +4107,7 @@ win32_free(void *block)
 }
 
 
-int
+DllExport int
 win32_open_osfhandle(intptr_t handle, int flags)
 {
 #ifdef USE_FIXED_OSFHANDLE
@@ -4030,12 +4117,64 @@ win32_open_osfhandle(intptr_t handle, int flags)
     return _open_osfhandle(handle, flags);
 }
 
-intptr_t
+DllExport intptr_t
 win32_get_osfhandle(int fd)
 {
     return (intptr_t)_get_osfhandle(fd);
 }
 
+DllExport FILE *
+win32_fdupopen(FILE *pf)
+{
+    FILE* pfdup;
+    fpos_t pos;
+    char mode[3];
+    int fileno = win32_dup(win32_fileno(pf));
+
+    /* open the file in the same mode */
+#ifdef __BORLANDC__
+    if((pf)->flags & _F_READ) {
+       mode[0] = 'r';
+       mode[1] = 0;
+    }
+    else if((pf)->flags & _F_WRIT) {
+       mode[0] = 'a';
+       mode[1] = 0;
+    }
+    else if((pf)->flags & _F_RDWR) {
+       mode[0] = 'r';
+       mode[1] = '+';
+       mode[2] = 0;
+    }
+#else
+    if((pf)->_flag & _IOREAD) {
+       mode[0] = 'r';
+       mode[1] = 0;
+    }
+    else if((pf)->_flag & _IOWRT) {
+       mode[0] = 'a';
+       mode[1] = 0;
+    }
+    else if((pf)->_flag & _IORW) {
+       mode[0] = 'r';
+       mode[1] = '+';
+       mode[2] = 0;
+    }
+#endif
+
+    /* it appears that the binmode is attached to the
+     * file descriptor so binmode files will be handled
+     * correctly
+     */
+    pfdup = win32_fdopen(fileno, mode);
+
+    /* move the file pointer to the same position */
+    if (!fgetpos(pf, &pos)) {
+       fsetpos(pfdup, &pos);
+    }
+    return pfdup;
+}
+
 DllExport void*
 win32_dynaload(const char* filename)
 {
@@ -4601,20 +4740,21 @@ Perl_init_os_extras(void)
      */
 }
 
-#ifdef MULTIPLICITY
-
-PerlInterpreter *
+void *
 win32_signal_context(void)
 {
     dTHX;
+#ifdef MULTIPLICITY
     if (!my_perl) {
        my_perl = PL_curinterp;
        PERL_SET_THX(my_perl);
     }
     return my_perl;
+#else
+    return PL_curinterp;
+#endif
 }
 
-#endif
 
 BOOL WINAPI
 win32_ctrlhandler(DWORD dwCtrlType)