This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Update B-Debug to CPAN version 1.17
[perl5.git] / perl.c
diff --git a/perl.c b/perl.c
index 39c555c..27e80ac 100644 (file)
--- a/perl.c
+++ b/perl.c
 #include "nwutil.h"    
 #endif
 
-/* XXX If this causes problems, set i_unistd=undef in the hint file.  */
-#ifdef I_UNISTD
-#include <unistd.h>
+#ifdef USE_KERN_PROC_PATHNAME
+#  include <sys/sysctl.h>
+#endif
+
+#ifdef USE_NSGETEXECUTABLEPATH
+#  include <mach-o/dyld.h>
 #endif
 
 #ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
-#  ifdef I_SYS_WAIT
-#   include <sys/wait.h>
-#  endif
 #  ifdef I_SYSUIO
 #    include <sys/uio.h>
 #  endif
@@ -983,10 +983,8 @@ perl_destruct(pTHXx)
 
     /* clear utf8 character classes */
     SvREFCNT_dec(PL_utf8_alnum);
-    SvREFCNT_dec(PL_utf8_ascii);
     SvREFCNT_dec(PL_utf8_alpha);
     SvREFCNT_dec(PL_utf8_space);
-    SvREFCNT_dec(PL_utf8_cntrl);
     SvREFCNT_dec(PL_utf8_graph);
     SvREFCNT_dec(PL_utf8_digit);
     SvREFCNT_dec(PL_utf8_upper);
@@ -1003,10 +1001,8 @@ perl_destruct(pTHXx)
     SvREFCNT_dec(PL_utf8_idcont);
     SvREFCNT_dec(PL_utf8_foldclosures);
     PL_utf8_alnum      = NULL;
-    PL_utf8_ascii      = NULL;
     PL_utf8_alpha      = NULL;
     PL_utf8_space      = NULL;
-    PL_utf8_cntrl      = NULL;
     PL_utf8_graph      = NULL;
     PL_utf8_digit      = NULL;
     PL_utf8_upper      = NULL;
@@ -1389,56 +1385,82 @@ Perl_call_atexit(pTHX_ ATEXIT_t fn, void *ptr)
     ++PL_exitlistlen;
 }
 
-#ifdef HAS_PROCSELFEXE
-/* This is a function so that we don't hold on to MAXPATHLEN
-   bytes of stack longer than necessary
- */
-STATIC void
-S_procself_val(pTHX_ SV *sv, const char *arg0)
-{
-    char buf[MAXPATHLEN];
-    int len = readlink(PROCSELFEXE_PATH, buf, sizeof(buf) - 1);
-
-    /* On Playstation2 Linux V1.0 (kernel 2.2.1) readlink(/proc/self/exe)
-       includes a spurious NUL which will cause $^X to fail in system
-       or backticks (this will prevent extensions from being built and
-       many tests from working). readlink is not meant to add a NUL.
-       Normal readlink works fine.
-     */
-    if (len > 0 && buf[len-1] == '\0') {
-      len--;
-    }
-
-    /* FreeBSD's implementation is acknowledged to be imperfect, sometimes
-       returning the text "unknown" from the readlink rather than the path
-       to the executable (or returning an error from the readlink).  Any valid
-       path has a '/' in it somewhere, so use that to validate the result.
-       See http://www.freebsd.org/cgi/query-pr.cgi?pr=35703
-    */
-    if (len > 0 && memchr(buf, '/', len)) {
-       sv_setpvn(sv,buf,len);
-    }
-    else {
-       sv_setpv(sv,arg0);
-    }
-}
-#endif /* HAS_PROCSELFEXE */
-
 STATIC void
 S_set_caret_X(pTHX) {
     dVAR;
     GV* tmpgv = gv_fetchpvs("\030", GV_ADD|GV_NOTQUAL, SVt_PV); /* $^X */
     if (tmpgv) {
        SV *const caret_x = GvSV(tmpgv);
-#ifdef HAS_PROCSELFEXE
-       S_procself_val(aTHX_ caret_x, PL_origargv[0]);
-#else
-#ifdef OS2
+#if defined(OS2)
        sv_setpv(caret_x, os2_execname(aTHX));
 #else
+#  ifdef USE_KERN_PROC_PATHNAME
+       size_t size = 0;
+       int mib[4];
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_PROC;
+       mib[2] = KERN_PROC_PATHNAME;
+       mib[3] = -1;
+
+       if (sysctl(mib, 4, NULL, &size, NULL, 0) == 0
+           && size > 0 && size < MAXPATHLEN * MAXPATHLEN) {
+           sv_grow(caret_x, size);
+
+           if (sysctl(mib, 4, SvPVX(caret_x), &size, NULL, 0) == 0
+               && size > 2) {
+               SvPOK_only(caret_x);
+               SvCUR_set(caret_x, size - 1);
+               SvTAINT(caret_x);
+               return;
+           }
+       }
+#  elif defined(USE_NSGETEXECUTABLEPATH)
+       char buf[1];
+       uint32_t size = sizeof(buf);
+
+       _NSGetExecutablePath(buf, &size);
+       if (size < MAXPATHLEN * MAXPATHLEN) {
+           sv_grow(caret_x, size);
+           if (_NSGetExecutablePath(SvPVX(caret_x), &size) == 0) {
+               char *const tidied = realpath(SvPVX(caret_x), NULL);
+               if (tidied) {
+                   sv_setpv(caret_x, tidied);
+                   free(tidied);
+               } else {
+                   SvPOK_only(caret_x);
+                   SvCUR_set(caret_x, size);
+               }
+               return;
+           }
+       }
+#  elif defined(HAS_PROCSELFEXE)
+       char buf[MAXPATHLEN];
+       int len = readlink(PROCSELFEXE_PATH, buf, sizeof(buf) - 1);
+
+       /* On Playstation2 Linux V1.0 (kernel 2.2.1) readlink(/proc/self/exe)
+          includes a spurious NUL which will cause $^X to fail in system
+          or backticks (this will prevent extensions from being built and
+          many tests from working). readlink is not meant to add a NUL.
+          Normal readlink works fine.
+       */
+       if (len > 0 && buf[len-1] == '\0') {
+           len--;
+       }
+
+       /* FreeBSD's implementation is acknowledged to be imperfect, sometimes
+          returning the text "unknown" from the readlink rather than the path
+          to the executable (or returning an error from the readlink). Any
+          valid path has a '/' in it somewhere, so use that to validate the
+          result. See http://www.freebsd.org/cgi/query-pr.cgi?pr=35703
+       */
+       if (len > 0 && memchr(buf, '/', len)) {
+           sv_setpvn(caret_x, buf, len);
+           return;
+       }
+#  endif
+       /* Fallback to this:  */
        sv_setpv(caret_x, PL_origargv[0]);
 #endif
-#endif
     }
 }
 
@@ -1450,6 +1472,12 @@ Tells a Perl interpreter to parse a Perl script.  See L<perlembed>.
 =cut
 */
 
+#define SET_CURSTASH(newstash)                       \
+       if (PL_curstash != newstash) {                \
+           SvREFCNT_dec(PL_curstash);                 \
+           PL_curstash = (HV *)SvREFCNT_inc(newstash); \
+       }
+
 int
 perl_parse(pTHXx_ XSINIT_t xsinit, int argc, char **argv, char **env)
 {
@@ -1621,7 +1649,7 @@ perl_parse(pTHXx_ XSINIT_t xsinit, int argc, char **argv, char **env)
        while (PL_scopestack_ix > oldscope)
            LEAVE;
        FREETMPS;
-       PL_curstash = PL_defstash;
+       SET_CURSTASH(PL_defstash);
        if (PL_unitcheckav) {
            call_list(oldscope, PL_unitcheckav);
        }
@@ -2205,7 +2233,7 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
        }
     }
     CopLINE_set(PL_curcop, 0);
-    PL_curstash = PL_defstash;
+    SET_CURSTASH(PL_defstash);
     if (PL_e_script) {
        SvREFCNT_dec(PL_e_script);
        PL_e_script = NULL;
@@ -2276,7 +2304,7 @@ perl_run(pTHXx)
        while (PL_scopestack_ix > oldscope)
            LEAVE;
        FREETMPS;
-       PL_curstash = PL_defstash;
+       SET_CURSTASH(PL_defstash);
        if (!(PL_exit_flags & PERL_EXIT_DESTRUCT_END) &&
            PL_endav && !PL_minus_c) {
            PERL_SET_PHASE(PERL_PHASE_END);
@@ -2666,7 +2694,7 @@ Perl_call_sv(pTHX_ SV *sv, VOL I32 flags)
            /* FALL THROUGH */
        case 2:
            /* my_exit() was called */
-           PL_curstash = PL_defstash;
+           SET_CURSTASH(PL_defstash);
            FREETMPS;
            JMPENV_POP;
            my_exit_jump();
@@ -2773,7 +2801,7 @@ Perl_eval_sv(pTHX_ SV *sv, I32 flags)
        /* FALL THROUGH */
     case 2:
        /* my_exit() was called */
-       PL_curstash = PL_defstash;
+       SET_CURSTASH(PL_defstash);
        FREETMPS;
        JMPENV_POP;
        my_exit_jump();
@@ -3265,14 +3293,10 @@ Perl_moreswitches(pTHX_ const char *s)
        s++;
        return s;
     case 't':
+    case 'T':
         if (!PL_tainting)
-           TOO_LATE_FOR('t');
+           TOO_LATE_FOR(*s);
         s++;
-        return s;
-    case 'T':
-       if (!PL_tainting)
-           TOO_LATE_FOR('T');
-       s++;
        return s;
     case 'u':
        PL_do_undump = TRUE;
@@ -3522,7 +3546,7 @@ S_init_main_stash(pTHX)
     dVAR;
     GV *gv;
 
-    PL_curstash = PL_defstash = newHV();
+    PL_curstash = PL_defstash = (HV *)SvREFCNT_inc_simple_NN(newHV());
     /* We know that the string "main" will be in the global shared string
        table, so it's a small saving to use it rather than allocate another
        8 bytes.  */
@@ -3555,7 +3579,7 @@ S_init_main_stash(pTHX)
 #endif
     sv_grow(ERRSV, 240);       /* Preallocate - for immediate signals. */
     CLEAR_ERRSV();
-    PL_curstash = PL_defstash;
+    SET_CURSTASH(PL_defstash);
     CopSTASH_set(&PL_compiling, PL_defstash);
     PL_debstash = GvHV(gv_fetchpvs("DB::", GV_ADDMULTI, SVt_PVHV));
     PL_globalstash = GvHV(gv_fetchpvs("CORE::GLOBAL::", GV_ADDMULTI,
@@ -3861,7 +3885,7 @@ Perl_init_debugger(pTHX)
     dVAR;
     HV * const ostash = PL_curstash;
 
-    PL_curstash = PL_debstash;
+    PL_curstash = (HV *)SvREFCNT_inc_simple(PL_debstash);
 
     Perl_init_dbargs(aTHX);
     PL_DBgv = gv_fetchpvs("DB::DB", GV_ADDMULTI, SVt_PVGV);
@@ -3876,6 +3900,7 @@ Perl_init_debugger(pTHX)
     PL_DBsignal = GvSV((gv_fetchpvs("DB::signal", GV_ADDMULTI, SVt_PV)));
     if (!SvIOK(PL_DBsignal))
        sv_setiv(PL_DBsignal, 0);
+    SvREFCNT_dec(PL_curstash);
     PL_curstash = ostash;
 }
 
@@ -4750,7 +4775,7 @@ Perl_call_list(pTHX_ I32 oldscope, AV *paramList)
            while (PL_scopestack_ix > oldscope)
                LEAVE;
            FREETMPS;
-           PL_curstash = PL_defstash;
+           SET_CURSTASH(PL_defstash);
            PL_curcop = &PL_compiling;
            CopLINE_set(PL_curcop, oldline);
            JMPENV_POP;