This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
bisect-runner.pl needs to work around an OpenBSD/sparc compiler bug.
[perl5.git] / win32 / perlhost.h
index 371a3a5..e8f5fb4 100644 (file)
@@ -7,20 +7,29 @@
  *    License or the Artistic License, as specified in the README file.
  */
 
+#ifndef UNDER_CE
 #define CHECK_HOST_INTERP
+#endif
 
 #ifndef ___PerlHost_H___
 #define ___PerlHost_H___
 
+#ifndef UNDER_CE
 #include <signal.h>
+#endif
 #include "iperlsys.h"
 #include "vmem.h"
 #include "vdir.h"
 
+#ifndef WC_NO_BEST_FIT_CHARS
+#  define WC_NO_BEST_FIT_CHARS 0x00000400
+#endif
+
 START_EXTERN_C
-extern char *          g_win32_get_privlib(const char *pl);
-extern char *          g_win32_get_sitelib(const char *pl);
-extern char *          g_win32_get_vendorlib(const char *pl);
+extern char *          g_win32_get_privlib(const char *pl, STRLEN *const len);
+extern char *          g_win32_get_sitelib(const char *pl, STRLEN *const len);
+extern char *          g_win32_get_vendorlib(const char *pl,
+                                             STRLEN *const len);
 extern char *          g_getlogin(void);
 END_EXTERN_C
 
@@ -509,21 +518,22 @@ PerlEnvOsId(struct IPerlEnv* piPerl)
 }
 
 char*
-PerlEnvLibPath(struct IPerlEnv* piPerl, const char *pl)
+PerlEnvLibPath(struct IPerlEnv* piPerl, const char *pl, STRLEN *const len)
 {
-    return g_win32_get_privlib(pl);
+    return g_win32_get_privlib(pl, len);
 }
 
 char*
-PerlEnvSiteLibPath(struct IPerlEnv* piPerl, const char *pl)
+PerlEnvSiteLibPath(struct IPerlEnv* piPerl, const char *pl, STRLEN *const len)
 {
-    return g_win32_get_sitelib(pl);
+    return g_win32_get_sitelib(pl, len);
 }
 
 char*
-PerlEnvVendorLibPath(struct IPerlEnv* piPerl, const char *pl)
+PerlEnvVendorLibPath(struct IPerlEnv* piPerl, const char *pl,
+                    STRLEN *const len)
 {
-    return g_win32_get_vendorlib(pl);
+    return g_win32_get_vendorlib(pl, len);
 }
 
 void
@@ -608,14 +618,14 @@ PerlStdIOGetc(struct IPerlStdIO* piPerl, FILE* pf)
     return win32_getc(pf);
 }
 
-char*
+STDCHAR*
 PerlStdIOGetBase(struct IPerlStdIO* piPerl, FILE* pf)
 {
 #ifdef FILE_base
     FILE *f = pf;
     return FILE_base(f);
 #else
-    return Nullch;
+    return NULL;
 #endif
 }
 
@@ -641,31 +651,31 @@ PerlStdIOGetCnt(struct IPerlStdIO* piPerl, FILE* pf)
 #endif
 }
 
-char*
+STDCHAR*
 PerlStdIOGetPtr(struct IPerlStdIO* piPerl, FILE* pf)
 {
 #ifdef USE_STDIO_PTR
     FILE *f = pf;
     return FILE_ptr(f);
 #else
-    return Nullch;
+    return NULL;
 #endif
 }
 
 char*
-PerlStdIOGets(struct IPerlStdIO* piPerl, FILE* pf, char* s, int n)
+PerlStdIOGets(struct IPerlStdIO* piPerl, char* s, int n, FILE* pf)
 {
     return win32_fgets(s, n, pf);
 }
 
 int
-PerlStdIOPutc(struct IPerlStdIO* piPerl, FILE* pf, int c)
+PerlStdIOPutc(struct IPerlStdIO* piPerl, int c, FILE* pf)
 {
     return win32_fputc(c, pf);
 }
 
 int
-PerlStdIOPuts(struct IPerlStdIO* piPerl, FILE* pf, const char *s)
+PerlStdIOPuts(struct IPerlStdIO* piPerl, const char *s, FILE* pf)
 {
     return win32_fputs(s, pf);
 }
@@ -734,7 +744,7 @@ PerlStdIOSetCnt(struct IPerlStdIO* piPerl, FILE* pf, int n)
 }
 
 void
-PerlStdIOSetPtr(struct IPerlStdIO* piPerl, FILE* pf, char * ptr)
+PerlStdIOSetPtr(struct IPerlStdIO* piPerl, FILE* pf, STDCHAR * ptr)
 {
 #ifdef STDIO_PTR_LVALUE
     FILE *f = pf;
@@ -823,27 +833,13 @@ PerlStdIOGetOSfhandle(struct IPerlStdIO* piPerl, int filenum)
 FILE*
 PerlStdIOFdupopen(struct IPerlStdIO* piPerl, FILE* pf)
 {
+#ifndef UNDER_CE
     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;
@@ -857,7 +853,6 @@ PerlStdIOFdupopen(struct IPerlStdIO* piPerl, FILE* pf)
        mode[1] = '+';
        mode[2] = 0;
     }
-#endif
 
     /* it appears that the binmode is attached to the
      * file descriptor so binmode files will be handled
@@ -870,6 +865,9 @@ PerlStdIOFdupopen(struct IPerlStdIO* piPerl, FILE* pf)
        fsetpos(pfdup, &pos);
     }
     return pfdup;
+#else
+    return 0;
+#endif
 }
 
 struct IPerlStdIO perlStdIO =
@@ -977,13 +975,20 @@ PerlLIOFileStat(struct IPerlLIO* piPerl, int handle, Stat_t *buffer)
 int
 PerlLIOIOCtl(struct IPerlLIO* piPerl, int i, unsigned int u, char *data)
 {
-    return win32_ioctlsocket((SOCKET)i, (long)u, (u_long*)data);
+    u_long u_long_arg;
+    int retval;
+
+    /* mauke says using memcpy avoids alignment issues */
+    memcpy(&u_long_arg, data, sizeof u_long_arg); 
+    retval = win32_ioctlsocket((SOCKET)i, (long)u, &u_long_arg);
+    memcpy(data, &u_long_arg, sizeof u_long_arg);
+    return retval;
 }
 
 int
 PerlLIOIsatty(struct IPerlLIO* piPerl, int fd)
 {
-    return isatty(fd);
+    return win32_isatty(fd);
 }
 
 int
@@ -1065,7 +1070,7 @@ PerlLIOUnlink(struct IPerlLIO* piPerl, const char *filename)
 }
 
 int
-PerlLIOUtime(struct IPerlLIO* piPerl, char *filename, struct utimbuf *times)
+PerlLIOUtime(struct IPerlLIO* piPerl, const char *filename, struct utimbuf *times)
 {
     return win32_utime(filename, times);
 }
@@ -1136,7 +1141,7 @@ PerlDirClose(struct IPerlDir* piPerl, DIR *dirp)
 }
 
 DIR*
-PerlDirOpen(struct IPerlDir* piPerl, char *filename)
+PerlDirOpen(struct IPerlDir* piPerl, const char *filename)
 {
     return win32_opendir(filename);
 }
@@ -1599,9 +1604,7 @@ PerlProcKill(struct IPerlProc* piPerl, int pid, int sig)
 int
 PerlProcKillpg(struct IPerlProc* piPerl, int pid, int sig)
 {
-    dTHX;
-    Perl_croak(aTHX_ "killpg not implemented!\n");
-    return 0;
+    return win32_kill(pid, -sig);
 }
 
 int
@@ -1691,8 +1694,8 @@ static THREAD_RET_TYPE
 win32_start_child(LPVOID arg)
 {
     PerlInterpreter *my_perl = (PerlInterpreter*)arg;
-    GV *tmpgv;
     int status;
+    HWND parent_message_hwnd;
 #ifdef PERL_SYNC_FORK
     static long sync_fork_id = 0;
     long id = ++sync_fork_id;
@@ -1702,24 +1705,20 @@ win32_start_child(LPVOID arg)
     PERL_SET_THX(my_perl);
     win32_checkTLS(my_perl);
 
-    /* set $$ to pseudo id */
 #ifdef PERL_SYNC_FORK
     w32_pseudo_id = id;
 #else
     w32_pseudo_id = GetCurrentThreadId();
-    if (IsWin95()) {
-       int pid = (int)w32_pseudo_id;
-       if (pid < 0)
-           w32_pseudo_id = -pid;
-    }
 #endif
-    if (tmpgv = gv_fetchpv("$", TRUE, SVt_PV)) {
-       SV *sv = GvSV(tmpgv);
-       SvREADONLY_off(sv);
-       sv_setiv(sv, -(IV)w32_pseudo_id);
-       SvREADONLY_on(sv);
-    }
+#ifdef PERL_USES_PL_PIDSTATUS    
     hv_clear(PL_pidstatus);
+#endif    
+
+    /* create message window and tell parent about it */
+    parent_message_hwnd = w32_message_hwnd;
+    w32_message_hwnd = win32_create_message_window();
+    if (parent_message_hwnd != NULL)
+        PostMessage(parent_message_hwnd, WM_USER_MESSAGE, w32_pseudo_id, (LPARAM)w32_message_hwnd);
 
     /* push a zero on the stack (we are the child) */
     {
@@ -1734,13 +1733,23 @@ win32_start_child(LPVOID arg)
 
     {
        dJMPENV;
-       volatile int oldscope = PL_scopestack_ix;
+       volatile int oldscope = 1; /* We are responsible for all scopes */
 
 restart:
        JMPENV_PUSH(status);
        switch (status) {
        case 0:
            CALLRUNOPS(aTHX);
+            /* We may have additional unclosed scopes if fork() was called
+             * from within a BEGIN block.  See perlfork.pod for more details.
+             * We cannot clean up these other scopes because they belong to a
+             * different interpreter, but we also cannot leave PL_scopestack_ix
+             * dangling because that can trigger an assertion in perl_destruct().
+             */
+            if (PL_scopestack_ix > oldscope) {
+                PL_scopestack[oldscope-1] = PL_scopestack[PL_scopestack_ix-1];
+                PL_scopestack_ix = oldscope;
+            }
            status = 0;
            break;
        case 2:
@@ -1748,15 +1757,19 @@ restart:
                LEAVE;
            FREETMPS;
            PL_curstash = PL_defstash;
+           if (PL_curstash != PL_defstash) {
+               SvREFCNT_dec(PL_curstash);
+               PL_curstash = (HV *)SvREFCNT_inc(PL_defstash);
+           }
            if (PL_endav && !PL_minus_c)
                call_list(oldscope, PL_endav);
-           status = STATUS_NATIVE_EXPORT;
+           status = STATUS_EXIT;
            break;
        case 3:
            if (PL_restartop) {
                POPSTACK_TO(PL_mainstack);
                PL_op = PL_restartop;
-               PL_restartop = Nullop;
+               PL_restartop = (OP*)NULL;
                goto restart;
            }
            PerlIO_printf(Perl_error_log, "panic: restartop\n");
@@ -1768,7 +1781,7 @@ restart:
 
        /* XXX hack to avoid perl_destruct() freeing optree */
         win32_checkTLS(my_perl);
-       PL_main_root = Nullop;
+       PL_main_root = (OP*)NULL;
     }
 
     win32_checkTLS(my_perl);
@@ -1807,7 +1820,8 @@ PerlProcFork(struct IPerlProc* piPerl)
        return -1;
     }
     h = new CPerlHost(*(CPerlHost*)w32_internal_host);
-    PerlInterpreter *new_perl = perl_clone_using((PerlInterpreter*)aTHX, 1,
+    PerlInterpreter *new_perl = perl_clone_using((PerlInterpreter*)aTHX,
+                                                CLONEf_COPY_STACKS,
                                                 h->m_pHostperlMem,
                                                 h->m_pHostperlMemShared,
                                                 h->m_pHostperlMemParse,
@@ -1824,6 +1838,11 @@ PerlProcFork(struct IPerlProc* piPerl)
     id = win32_start_child((LPVOID)new_perl);
     PERL_SET_THX(aTHX);
 #  else
+    if (w32_message_hwnd == INVALID_HANDLE_VALUE)
+        w32_message_hwnd = win32_create_message_window();
+    new_perl->Isys_intern.message_hwnd = w32_message_hwnd;
+    w32_pseudo_child_message_hwnds[w32_num_pseudo_children] =
+        (w32_message_hwnd == NULL) ? (HWND)NULL : (HWND)INVALID_HANDLE_VALUE;
 #    ifdef USE_RTL_THREAD_API
     handle = (HANDLE)_beginthreadex((void*)NULL, 0, win32_start_child,
                                    (void*)new_perl, 0, (unsigned*)&id);
@@ -1836,13 +1855,9 @@ PerlProcFork(struct IPerlProc* piPerl)
        errno = EAGAIN;
        return -1;
     }
-    if (IsWin95()) {
-       int pid = (int)id;
-       if (pid < 0)
-           id = -pid;
-    }
     w32_pseudo_child_handles[w32_num_pseudo_children] = handle;
     w32_pseudo_child_pids[w32_num_pseudo_children] = id;
+    w32_pseudo_child_sigterm[w32_num_pseudo_children] = 0;
     ++w32_num_pseudo_children;
 #  endif
     return -(int)id;
@@ -2057,7 +2072,7 @@ CPerlHost::CPerlHost(CPerlHost& host)
 
 CPerlHost::~CPerlHost(void)
 {
-//  Reset();
+    Reset();
     InterlockedDecrement(&num_hosts);
     delete m_pvDir;
     m_pVMemParse->Release();
@@ -2118,6 +2133,12 @@ lookup(const void *arg1, const void *arg2)
 LPSTR*
 CPerlHost::Lookup(LPCSTR lpStr)
 {
+#ifdef UNDER_CE
+    if (!m_lppEnvList || !m_dwEnvCount)
+       return NULL;
+#endif
+    if (!lpStr)
+       return NULL;
     return (LPSTR*)bsearch(&lpStr, m_lppEnvList, m_dwEnvCount, sizeof(LPSTR), lookup);
 }
 
@@ -2169,20 +2190,24 @@ CPerlHost::Add(LPCSTR lpStr)
 
     // replacing ?
     lpPtr = Lookup(szBuffer);
-    if(lpPtr != NULL) {
-       Renew(*lpPtr, length, char);
+    if (lpPtr != NULL) {
+       // must allocate things via host memory allocation functions 
+       // rather than perl's Renew() et al, as the perl interpreter
+       // may either not be initialized enough when we allocate these,
+       // or may already be dead when we go to free these
+       *lpPtr = (char*)Realloc(*lpPtr, length * sizeof(char));
        strcpy(*lpPtr, lpStr);
     }
     else {
-       ++m_dwEnvCount;
-       Renew(m_lppEnvList, m_dwEnvCount, LPSTR);
-       New(1, m_lppEnvList[m_dwEnvCount-1], length, char);
-       if(m_lppEnvList[m_dwEnvCount-1] != NULL) {
-           strcpy(m_lppEnvList[m_dwEnvCount-1], lpStr);
-           qsort(m_lppEnvList, m_dwEnvCount, sizeof(LPSTR), compare);
+       m_lppEnvList = (LPSTR*)Realloc(m_lppEnvList, (m_dwEnvCount+1) * sizeof(LPSTR));
+       if (m_lppEnvList) {
+           m_lppEnvList[m_dwEnvCount] = (char*)Malloc(length * sizeof(char));
+           if (m_lppEnvList[m_dwEnvCount] != NULL) {
+               strcpy(m_lppEnvList[m_dwEnvCount], lpStr);
+               ++m_dwEnvCount;
+               qsort(m_lppEnvList, m_dwEnvCount, sizeof(LPSTR), compare);
+           }
        }
-       else
-           --m_dwEnvCount;
     }
 }
 
@@ -2208,16 +2233,15 @@ char*
 CPerlHost::GetChildDir(void)
 {
     dTHX;
-    int length;
     char* ptr;
-    New(0, ptr, MAX_PATH+1, char);
-    if(ptr) {
-       m_pvDir->GetCurrentDirectoryA(MAX_PATH+1, ptr);
-       length = strlen(ptr);
-       if (length > 3) {
-           if ((ptr[length-1] == '\\') || (ptr[length-1] == '/'))
-               ptr[length-1] = 0;
-       }
+    size_t length;
+
+    Newx(ptr, MAX_PATH+1, char);
+    m_pvDir->GetCurrentDirectoryA(MAX_PATH+1, ptr);
+    length = strlen(ptr);
+    if (length > 3) {
+        if ((ptr[length-1] == '\\') || (ptr[length-1] == '/'))
+            ptr[length-1] = 0;
     }
     return ptr;
 }
@@ -2257,7 +2281,7 @@ CPerlHost::CreateLocalEnvironmentStrings(VDir &vDir)
     // add the additional space used by changes made to the environment
     dwSize += CalculateEnvironmentSpace();
 
-    New(1, lpStr, dwSize, char);
+    Newx(lpStr, dwSize, char);
     lpPtr = lpStr;
     if(lpStr != NULL) {
        // build the local environment
@@ -2325,11 +2349,13 @@ CPerlHost::Reset(void)
     dTHX;
     if(m_lppEnvList != NULL) {
        for(DWORD index = 0; index < m_dwEnvCount; ++index) {
-           Safefree(m_lppEnvList[index]);
+           Free(m_lppEnvList[index]);
            m_lppEnvList[index] = NULL;
        }
     }
     m_dwEnvCount = 0;
+    Free(m_lppEnvList);
+    m_lppEnvList = NULL;
 }
 
 void
@@ -2404,13 +2430,7 @@ CPerlHost::Chdir(const char *dirname)
        errno = ENOENT;
        return -1;
     }
-    if (USING_WIDE()) {
-       WCHAR wBuffer[MAX_PATH];
-       A2WHELPER(dirname, wBuffer, sizeof(wBuffer));
-       ret = m_pvDir->SetCurrentDirectoryW(wBuffer);
-    }
-    else
-       ret = m_pvDir->SetCurrentDirectoryA((char*)dirname);
+    ret = m_pvDir->SetCurrentDirectoryA((char*)dirname);
     if(ret < 0) {
        errno = ENOENT;
     }