This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Upgrade to version.pm 0.71, by John Peacock
[perl5.git] / perl.c
diff --git a/perl.c b/perl.c
index 7b715ae..982ec89 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -1,7 +1,7 @@
 /*    perl.c
  *
  *    Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- *    2000, 2001, 2002, 2003, 2004, 2005, 2006, by Larry Wall and others
+ *    2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 by Larry Wall and others
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
@@ -137,6 +137,22 @@ static I32 read_e_script(pTHX_ int idx, SV *buf_sv, int maxlen);
 #endif
 #endif
 
+#define CALL_BODY_EVAL(myop) \
+    if (PL_op == (myop)) \
+       PL_op = Perl_pp_entereval(aTHX); \
+    if (PL_op) \
+       CALLRUNOPS(aTHX);
+
+#define CALL_BODY_SUB(myop) \
+    if (PL_op == (myop)) \
+       PL_op = Perl_pp_entersub(aTHX); \
+    if (PL_op) \
+       CALLRUNOPS(aTHX);
+
+#define CALL_LIST_BODY(cv) \
+    PUSHMARK(PL_stack_sp); \
+    call_sv((SV*)(cv), G_EVAL|G_DISCARD);
+
 static void
 S_init_tls_and_interp(PerlInterpreter *my_perl)
 {
@@ -148,13 +164,19 @@ S_init_tls_and_interp(PerlInterpreter *my_perl)
        ALLOC_THREAD_KEY;
        PERL_SET_THX(my_perl);
        OP_REFCNT_INIT;
+       HINTS_REFCNT_INIT;
        MUTEX_INIT(&PL_dollarzero_mutex);
 #  endif
 #ifdef PERL_IMPLICIT_CONTEXT
        MUTEX_INIT(&PL_my_ctx_mutex);
 #  endif
     }
-    else {
+#if defined(USE_ITHREADS)
+    else
+#else
+    /* This always happens for non-ithreads  */
+#endif
+    {
        PERL_SET_THX(my_perl);
     }
 }
@@ -240,8 +262,8 @@ perl_construct(pTHXx)
     if (!PL_linestr) {
        PL_curcop = &PL_compiling;      /* needed by ckWARN, right away */
 
-       PL_linestr = newSV(79);
-       sv_upgrade(PL_linestr,SVt_PVIV);
+       PL_linestr = newSV_type(SVt_PVIV);
+       SvGROW(PL_linestr, 80);
 
        if (!SvREADONLY(&PL_sv_undef)) {
            /* set read-only and try to insure than we wont see REFCNT==0
@@ -304,8 +326,8 @@ perl_construct(pTHXx)
     sv_setpvn(PERL_DEBUG_PAD(1), "", 0);       /* ext/re needs these */
     sv_setpvn(PERL_DEBUG_PAD(2), "", 0);       /* even without DEBUGGING. */
 #ifdef USE_ITHREADS
-    PL_regex_padav = newAV();
-    av_push(PL_regex_padav,(SV*)newAV());    /* First entry is an array of empty elements */
+    /* First entry is an array of empty elements */
+    Perl_av_create_and_push(aTHX_ &PL_regex_padav,(SV*)newAV());
     PL_regex_pad = AvARRAY(PL_regex_padav);
 #endif
 #ifdef USE_REENTRANT_API
@@ -360,7 +382,7 @@ perl_construct(pTHXx)
        if ((long) PL_mmap_page_size < 0) {
          if (errno) {
            SV * const error = ERRSV;
-           (void) SvUPGRADE(error, SVt_PV);
+           SvUPGRADE(error, SVt_PV);
            Perl_croak(aTHX_ "panic: sysconf: %s", SvPV_nolen_const(error));
          }
          else
@@ -389,6 +411,10 @@ perl_construct(pTHXx)
     PL_timesbase.tms_cstime = 0;
 #endif
 
+#ifdef PERL_MAD
+    PL_curforce = -1;
+#endif
+
     ENTER;
 }
 
@@ -404,6 +430,7 @@ no threads.
 int
 Perl_nothreadhook(pTHX)
 {
+    PERL_UNUSED_CONTEXT;
     return 0;
 }
 
@@ -430,7 +457,7 @@ Perl_dump_sv_child(pTHX_ SV *sv)
        it to dump out to.  We can't let it hold open the file descriptor when it
        forks, as the file descriptor it will dump to can turn out to be one end
        of pipe that some other process will wait on for EOF. (So as it would
-       be open, the wait would be forever.  */
+       be open, the wait would be forever.)  */
 
     msg.msg_control = control.control;
     msg.msg_controllen = sizeof(control.control);
@@ -517,7 +544,7 @@ int
 perl_destruct(pTHXx)
 {
     dVAR;
-    volatile int destruct_level;  /* 0=none, 1=full, 2=full with checks */
+    VOL int destruct_level;  /* 0=none, 1=full, 2=full with checks */
     HV *hv;
 #ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
     pid_t child;
@@ -558,6 +585,7 @@ perl_destruct(pTHXx)
 
     if (CALL_FPTR(PL_threadhook)(aTHX)) {
         /* Threads hook has vetoed further cleanup */
+       PL_veto_cleanup = TRUE;
         return STATUS_EXIT;
     }
 
@@ -770,19 +798,6 @@ perl_destruct(pTHXx)
     PL_exitlist = NULL;
     PL_exitlistlen = 0;
 
-    if (destruct_level == 0){
-
-       DEBUG_P(debprofdump());
-
-#if defined(PERLIO_LAYERS)
-       /* No more IO - including error messages ! */
-       PerlIO_cleanup(aTHX);
-#endif
-
-       /* The exit() function will do everything that needs doing. */
-        return STATUS_EXIT;
-    }
-
     /* jettison our possibly duplicated environment */
     /* if PERL_USE_SAFE_PUTENV is defined environ will not have been copied
      * so we certainly shouldn't free it here
@@ -809,6 +824,22 @@ perl_destruct(pTHXx)
 #endif
 #endif /* !PERL_MICRO */
 
+    if (destruct_level == 0) {
+
+       DEBUG_P(debprofdump());
+
+#if defined(PERLIO_LAYERS)
+       /* No more IO - including error messages ! */
+       PerlIO_cleanup(aTHX);
+#endif
+
+       CopFILE_free(&PL_compiling);
+       CopSTASH_free(&PL_compiling);
+
+       /* The exit() function will do everything that needs doing. */
+        return STATUS_EXIT;
+    }
+
     /* reset so print() ends up where we expect */
     setdefout(NULL);
 
@@ -852,13 +883,18 @@ perl_destruct(pTHXx)
 
     if(PL_rsfp) {
        (void)PerlIO_close(PL_rsfp);
-       PL_rsfp = Nullfp;
+       PL_rsfp = NULL;
     }
 
     /* Filters for program text */
     SvREFCNT_dec(PL_rsfp_filters);
     PL_rsfp_filters = NULL;
 
+    if (PL_minus_F) {
+       Safefree(PL_splitstr);
+       PL_splitstr = NULL;
+    }
+
     /* switches */
     PL_preprocess   = FALSE;
     PL_minus_n      = FALSE;
@@ -894,7 +930,6 @@ perl_destruct(pTHXx)
     SvREFCNT_dec(PL_rs);       /* $/ */
     PL_rs = NULL;
 
-    PL_multiline = 0;          /* $* */
     Safefree(PL_osname);       /* $^O */
     PL_osname = NULL;
 
@@ -923,12 +958,16 @@ perl_destruct(pTHXx)
     SvREFCNT_dec(PL_endav);
     SvREFCNT_dec(PL_checkav);
     SvREFCNT_dec(PL_checkav_save);
+    SvREFCNT_dec(PL_unitcheckav);
+    SvREFCNT_dec(PL_unitcheckav_save);
     SvREFCNT_dec(PL_initav);
     PL_beginav = NULL;
     PL_beginav_save = NULL;
     PL_endav = NULL;
     PL_checkav = NULL;
     PL_checkav_save = NULL;
+    PL_unitcheckav = NULL;
+    PL_unitcheckav_save = NULL;
     PL_initav = NULL;
 
     /* shortcuts just get cleared */
@@ -1030,11 +1069,10 @@ perl_destruct(pTHXx)
     PL_utf8_idcont     = NULL;
 
     if (!specialWARN(PL_compiling.cop_warnings))
-       SvREFCNT_dec(PL_compiling.cop_warnings);
+       PerlMemShared_free(PL_compiling.cop_warnings);
     PL_compiling.cop_warnings = NULL;
-    if (!specialCopIO(PL_compiling.cop_io))
-       SvREFCNT_dec(PL_compiling.cop_io);
-    PL_compiling.cop_io = NULL;
+    Perl_refcounted_he_free(aTHX_ PL_compiling.cop_hints_hash);
+    PL_compiling.cop_hints_hash = NULL;
     CopFILE_free(&PL_compiling);
     CopSTASH_free(&PL_compiling);
 
@@ -1170,7 +1208,7 @@ perl_destruct(pTHXx)
                        " flags=0x%"UVxf
                        " refcnt=%"UVuf pTHX__FORMAT "\n"
                        "\tallocated at %s:%d %s %s%s\n",
-                       sv, sv->sv_flags, sv->sv_refcnt pTHX__VALUE,
+                       (void*)sv, sv->sv_flags, sv->sv_refcnt pTHX__VALUE,
                        sv->sv_debug_file ? sv->sv_debug_file : "(unknown)",
                        sv->sv_debug_line,
                        sv->sv_debug_inpad ? "for" : "by",
@@ -1251,6 +1289,12 @@ perl_destruct(pTHXx)
 
     sv_free_arenas();
 
+    while (PL_regmatch_slab) {
+       regmatch_slab  *s = PL_regmatch_slab;
+       PL_regmatch_slab = PL_regmatch_slab->next;
+       Safefree(s);
+    }
+
     /* As the absolutely last thing, free the non-arena SV for mess() */
 
     if (PL_mess_sv) {
@@ -1287,11 +1331,25 @@ Releases a Perl interpreter.  See L<perlembed>.
 void
 perl_free(pTHXx)
 {
+    dVAR;
+
+    if (PL_veto_cleanup)
+       return;
+
 #ifdef PERL_TRACK_MEMPOOL
-    /* Emulate the PerlHost behaviour of free()ing all memory allocated in this
-       thread at thread exit.  */
-    while(aTHXx->Imemory_debug_header.next != &(aTHXx->Imemory_debug_header))
-       safesysfree(sTHX + (char *)(aTHXx->Imemory_debug_header.next));
+    {
+       /*
+        * Don't free thread memory if PERL_DESTRUCT_LEVEL is set to a non-zero
+        * value as we're probably hunting memory leaks then
+        */
+       const char * const s = PerlEnv_getenv("PERL_DESTRUCT_LEVEL");
+       if (!s || atoi(s) == 0) {
+           /* Emulate the PerlHost behaviour of free()ing all memory allocated in this
+              thread at thread exit.  */
+           while(aTHXx->Imemory_debug_header.next != &(aTHXx->Imemory_debug_header))
+               safesysfree(sTHX + (char *)(aTHXx->Imemory_debug_header.next));
+       }
+    }
 #endif
 
 #if defined(WIN32) || defined(NETWARE)
@@ -1323,6 +1381,8 @@ perl_free(pTHXx)
 
 #if defined(__hpux) && !(defined(__ux_version) && __ux_version <= 1020) && !defined(__GNUC__)
 #pragma fini "perl_fini"
+#elif defined(__sun) && !defined(__GNUC__)
+#pragma fini (perl_fini)
 #endif
 
 static void
@@ -1332,7 +1392,7 @@ __attribute__((destructor))
 perl_fini(void)
 {
     dVAR;
-    if (PL_curinterp)
+    if (PL_curinterp  && !PL_veto_cleanup)
        FREE_THREAD_KEY;
 }
 
@@ -1417,7 +1477,7 @@ perl_parse(pTHXx_ XSINIT_t xsinit, int argc, char **argv, char **env)
     int ret;
     dJMPENV;
 
-    PERL_UNUSED_VAR(my_perl);
+    PERL_UNUSED_ARG(my_perl);
 
 #ifdef SETUID_SCRIPTS_ARE_SECURE_NOW
 #ifdef IAMSUID
@@ -1496,13 +1556,11 @@ setuid perl scripts securely.\n");
                        break;
              }
         }
+
+#ifndef PERL_USE_SAFE_PUTENV
         /* Can we grab env area too to be used as the area for $0? */
-        if (s && PL_origenviron) {
-             if ((PL_origenviron[0] == s + 1
-#ifdef OS2
-                  || (PL_origenviron[0] == s + 9 && (s += 8))
-#endif 
-                 )
+        if (s && PL_origenviron && !PL_use_safe_putenv) {
+             if ((PL_origenviron[0] == s + 1)
                  ||
                  (aligned &&
                   (PL_origenviron[0] >  s &&
@@ -1510,7 +1568,7 @@ setuid perl scripts securely.\n");
                    INT2PTR(char *, PTR2UV(s + PTRSIZE) & mask)))
                 )
              {
-#ifndef OS2
+#ifndef OS2            /* ENVIRON is read by the kernel too. */
                   s = PL_origenviron[0];
                   while (*s) s++;
 #endif
@@ -1533,6 +1591,8 @@ setuid perl scripts securely.\n");
                   }
              }
         }
+#endif /* !defined(PERL_USE_SAFE_PUTENV) */
+
         PL_origalen = s ? s - PL_origargv[0] + 1 : 0;
     }
 
@@ -1568,6 +1628,8 @@ setuid perl scripts securely.\n");
     switch (ret) {
     case 0:
        parse_body(env,xsinit);
+       if (PL_unitcheckav)
+           call_list(oldscope, PL_unitcheckav);
        if (PL_checkav)
            call_list(oldscope, PL_checkav);
        ret = 0;
@@ -1581,6 +1643,8 @@ setuid perl scripts securely.\n");
            LEAVE;
        FREETMPS;
        PL_curstash = PL_defstash;
+       if (PL_unitcheckav)
+           call_list(oldscope, PL_unitcheckav);
        if (PL_checkav)
            call_list(oldscope, PL_checkav);
        ret = STATUS_EXIT;
@@ -1604,7 +1668,7 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
     VOL bool dosearch = FALSE;
     const char *validarg = "";
     register SV *sv;
-    register char *s;
+    register char *s, c;
     const char *cddir = NULL;
 #ifdef USE_SITECUSTOMIZE
     bool minus_f = FALSE;
@@ -1632,7 +1696,7 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
 #endif
        s = argv[0]+1;
       reswitch:
-       switch (*s) {
+       switch ((c = *s)) {
        case 'C':
 #ifndef PERL_STRICT_CR
        case '\r':
@@ -1699,7 +1763,7 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
                argc--,argv++;
            }
            else
-               Perl_croak(aTHX_ "No code specified for -%c", *s);
+               Perl_croak(aTHX_ "No code specified for -%c", c);
            sv_catpvs(PL_e_script, "\n");
            break;
 
@@ -1741,10 +1805,7 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
            {
                SV *opts_prog;
 
-               if (!PL_preambleav)
-                   PL_preambleav = newAV();
-               av_push(PL_preambleav,
-                       newSVpvs("use Config;"));
+               Perl_av_create_and_push(aTHX_ &PL_preambleav, newSVpvs("use Config;"));
                if (*++s != ':')  {
                    STRLEN opts;
                
@@ -1790,6 +1851,9 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
 #  ifdef PERL_IMPLICIT_SYS
                             " PERL_IMPLICIT_SYS"
 #  endif
+#  ifdef PERL_MAD
+                            " PERL_MAD"
+#  endif
 #  ifdef PERL_MALLOC_WRAP
                             " PERL_MALLOC_WRAP"
 #  endif
@@ -2002,17 +2066,11 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
 
 #ifdef USE_SITECUSTOMIZE
     if (!minus_f) {
-       if (!PL_preambleav)
-           PL_preambleav = newAV();
-       av_unshift(PL_preambleav, 1);
-       (void)av_store(PL_preambleav, 0, Perl_newSVpvf(aTHX_ "BEGIN { do '%s/sitecustomize.pl' }", SITELIB_EXP));
+       (void)Perl_av_create_and_unshift_one(aTHX_ &PL_preambleav,
+                                            Perl_newSVpvf(aTHX_ "BEGIN { do '%s/sitecustomize.pl' }", SITELIB_EXP));
     }
 #endif
 
-    if (PL_taint_warn && PL_dowarn != G_WARN_ALL_OFF) {
-       PL_compiling.cop_warnings = newSVpvn(WARN_TAINTstring, WARNsize);
-    }
-
     if (!scriptname)
        scriptname = argv[0];
     if (PL_e_script) {
@@ -2075,8 +2133,7 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
        }
     }
 
-    PL_main_cv = PL_compcv = (CV*)newSV(0);
-    sv_upgrade((SV *)PL_compcv, SVt_PVCV);
+    PL_main_cv = PL_compcv = (CV*)newSV_type(SVt_PVCV);
     CvUNIQUE_on(PL_compcv);
 
     CvPADLIST(PL_compcv) = pad_new(0);
@@ -2163,6 +2220,25 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
              Perl_croak(aTHX_ "PERL_SIGNALS illegal: \"%s\"", s);
     }
 
+#ifdef PERL_MAD
+    if ((s = PerlEnv_getenv("PERL_XMLDUMP"))) {
+       PL_madskills = 1;
+       PL_minus_c = 1;
+       if (!s || !s[0])
+           PL_xmlfp = PerlIO_stdout();
+       else {
+           PL_xmlfp = PerlIO_open(s, "w");
+           if (!PL_xmlfp)
+               Perl_croak(aTHX_ "Can't open %s", s);
+       }
+       my_setenv("PERL_XMLDUMP", Nullch);      /* hide from subprocs */
+    }
+    if ((s = PerlEnv_getenv("PERL_MADSKILLS"))) {
+       PL_madskills = atoi(s);
+       my_setenv("PERL_MADSKILLS", Nullch);    /* hide from subprocs */
+    }
+#endif
+
     init_lexer();
 
     /* now parse the script */
@@ -2288,6 +2364,12 @@ S_run_body(pTHX_ I32 oldscope)
                     PL_sawampersand ? "Enabling" : "Omitting"));
 
     if (!PL_restartop) {
+#ifdef PERL_MAD
+       if (PL_xmlfp) {
+           xmldump_all();
+           exit(0);    /* less likely to core dump than my_exit(0) */
+       }
+#endif
        DEBUG_x(dump_all());
 #ifdef DEBUGGING
        if (!DEBUG_q_TEST)
@@ -2399,33 +2481,46 @@ Perl_get_hv(pTHX_ const char *name, I32 create)
 /*
 =head1 CV Manipulation Functions
 
+=for apidoc p||get_cvn_flags
+
+Returns the CV of the specified Perl subroutine.  C<flags> are passed to
+C<gv_fetchpvn_flags>. If C<GV_ADD> is set and the Perl subroutine does not
+exist then it will be declared (which has the same effect as saying
+C<sub name;>).  If C<GV_ADD> is not set and the subroutine does not exist
+then NULL is returned.
+
 =for apidoc p||get_cv
 
-Returns the CV of the specified Perl subroutine.  If C<create> is set and
-the Perl subroutine does not exist then it will be declared (which has the
-same effect as saying C<sub name;>).  If C<create> is not set and the
-subroutine does not exist then NULL is returned.
+Uses C<strlen> to get the length of C<name>, then calls C<get_cvn_flags>.
 
 =cut
 */
 
 CV*
-Perl_get_cv(pTHX_ const char *name, I32 create)
+Perl_get_cvn_flags(pTHX_ const char *name, STRLEN len, I32 flags)
 {
-    GV* const gv = gv_fetchpv(name, create, SVt_PVCV);
-    /* XXX unsafe for threads if eval_owner isn't held */
+    GV* const gv = gv_fetchpvn_flags(name, len, flags, SVt_PVCV);
     /* XXX this is probably not what they think they're getting.
      * It has the same effect as "sub name;", i.e. just a forward
      * declaration! */
-    if (create && !GvCVu(gv))
+    if ((flags & ~GV_NOADD_MASK) && !GvCVu(gv)) {
+       SV *const sv = newSVpvn(name,len);
+       SvFLAGS(sv) |= flags & SVf_UTF8;
        return newSUB(start_subparse(FALSE, 0),
-                     newSVOP(OP_CONST, 0, newSVpv(name,0)),
+                     newSVOP(OP_CONST, 0, sv),
                      NULL, NULL);
+    }
     if (gv)
        return GvCVu(gv);
     return NULL;
 }
 
+CV*
+Perl_get_cv(pTHX_ const char *name, I32 flags)
+{
+    return get_cvn_flags(name, strlen(name), flags);
+}
+
 /* Be sure to refetch the stack pointer after calling these routines. */
 
 /*
@@ -2510,7 +2605,7 @@ Perl_call_sv(pTHX_ SV *sv, I32 flags)
     LOGOP myop;                /* fake syntax tree node */
     UNOP method_op;
     I32 oldmark;
-    volatile I32 retval = 0;
+    VOL I32 retval = 0;
     I32 oldscope;
     bool oldcatch = CATCH_GET;
     int ret;
@@ -2556,38 +2651,22 @@ Perl_call_sv(pTHX_ SV *sv, I32 flags)
 
     if (!(flags & G_EVAL)) {
        CATCH_SET(TRUE);
-       call_body((OP*)&myop, FALSE);
+       CALL_BODY_SUB((OP*)&myop);
        retval = PL_stack_sp - (PL_stack_base + oldmark);
        CATCH_SET(oldcatch);
     }
     else {
        myop.op_other = (OP*)&myop;
        PL_markstack_ptr--;
-       /* we're trying to emulate pp_entertry() here */
-       {
-           register PERL_CONTEXT *cx;
-           const I32 gimme = GIMME_V;
-       
-           ENTER;
-           SAVETMPS;
-       
-           PUSHBLOCK(cx, (CXt_EVAL|CXp_TRYBLOCK), PL_stack_sp);
-           PUSHEVAL(cx, 0, 0);
-           PL_eval_root = PL_op;             /* Only needed so that goto works right. */
-       
-           PL_in_eval = EVAL_INEVAL;
-           if (flags & G_KEEPERR)
-               PL_in_eval |= EVAL_KEEPERR;
-           else
-               sv_setpvn(ERRSV,"",0);
-       }
+       create_eval_scope(flags|G_FAKINGEVAL);
        PL_markstack_ptr++;
 
        JMPENV_PUSH(ret);
+
        switch (ret) {
        case 0:
  redo_body:
-           call_body((OP*)&myop, FALSE);
+           CALL_BODY_SUB((OP*)&myop);
            retval = PL_stack_sp - (PL_stack_base + oldmark);
            if (!(flags & G_KEEPERR))
                sv_setpvn(ERRSV,"",0);
@@ -2620,21 +2699,8 @@ Perl_call_sv(pTHX_ SV *sv, I32 flags)
            break;
        }
 
-       if (PL_scopestack_ix > oldscope) {
-           SV **newsp;
-           PMOP *newpm;
-           I32 gimme;
-           register PERL_CONTEXT *cx;
-           I32 optype;
-
-           POPBLOCK(cx,newpm);
-           POPEVAL(cx);
-           PL_curpm = newpm;
-           LEAVE;
-           PERL_UNUSED_VAR(newsp);
-           PERL_UNUSED_VAR(gimme);
-           PERL_UNUSED_VAR(optype);
-       }
+       if (PL_scopestack_ix > oldscope)
+           delete_eval_scope();
        JMPENV_POP;
     }
 
@@ -2648,20 +2714,6 @@ Perl_call_sv(pTHX_ SV *sv, I32 flags)
     return retval;
 }
 
-STATIC void
-S_call_body(pTHX_ const OP *myop, bool is_eval)
-{
-    dVAR;
-    if (PL_op == myop) {
-       if (is_eval)
-           PL_op = Perl_pp_entereval(aTHX);    /* this doesn't do a POPMARK */
-       else
-           PL_op = Perl_pp_entersub(aTHX);     /* this does */
-    }
-    if (PL_op)
-       CALLRUNOPS(aTHX);
-}
-
 /* Eval a string. The G_EVAL flag is always assumed. */
 
 /*
@@ -2680,8 +2732,8 @@ Perl_eval_sv(pTHX_ SV *sv, I32 flags)
     dVAR;
     dSP;
     UNOP myop;         /* fake syntax tree node */
-    volatile I32 oldmark = SP - PL_stack_base;
-    volatile I32 retval = 0;
+    VOL I32 oldmark = SP - PL_stack_base;
+    VOL I32 retval = 0;
     int ret;
     OP* const oldop = PL_op;
     dJMPENV;
@@ -2715,7 +2767,7 @@ Perl_eval_sv(pTHX_ SV *sv, I32 flags)
     switch (ret) {
     case 0:
  redo_body:
-       call_body((OP*)&myop,TRUE);
+       CALL_BODY_EVAL((OP*)&myop);
        retval = PL_stack_sp - (PL_stack_base + oldmark);
        if (!(flags & G_KEEPERR))
            sv_setpvn(ERRSV,"",0);
@@ -2910,7 +2962,7 @@ Perl_get_debug_opts(pTHX_ const char **s, bool givehelp)
     int i = 0;
     if (isALPHA(**s)) {
        /* if adding extra options, remember to update DEBUG_MASK */
-       static const char debopts[] = "psltocPmfrxu HXDSTRJvCAq";
+       static const char debopts[] = "psltocPmfrxuUHXDSTRJvCAq";
 
        for (; isALNUM(**s); (*s)++) {
            const char * const d = strchr(debopts,**s);
@@ -2992,13 +3044,14 @@ Perl_moreswitches(pTHX_ char *s)
     case 'C':
         s++;
         PL_unicode = parse_unicode_opts( (const char **)&s );
+       if (PL_unicode & PERL_UNICODE_UTF8CACHEASSERT_FLAG)
+           PL_utf8cache = -1;
        return s;
     case 'F':
        PL_minus_F = TRUE;
        PL_splitstr = ++s;
        while (*s && !isSPACE(*s)) ++s;
-       *s = '\0';
-       PL_splitstr = savepv(PL_splitstr);
+       PL_splitstr = savepvn(PL_splitstr, s - PL_splitstr);
        return s;
     case 'a':
        PL_minus_a = TRUE;
@@ -3030,7 +3083,9 @@ Perl_moreswitches(pTHX_ char *s)
                sv_catpv(sv, start);
            else {
                sv_catpvn(sv, start, s-start);
-               Perl_sv_catpvf(aTHX_ sv, " split(/,/,q%c%s%c)", 0, ++s, 0);
+               /* Don't use NUL as q// delimiter here, this string goes in the
+                * environment. */
+               Perl_sv_catpvf(aTHX_ sv, " split(/,/,q{%s});", ++s);
            }
            s += strlen(s);
            my_setenv("PERL5DB", SvPV_nolen_const(sv));
@@ -3065,13 +3120,17 @@ Perl_moreswitches(pTHX_ char *s)
        return s+1;
        }
 #endif /* __CYGWIN__ */
-       PL_inplace = savepv(s+1);
-       for (s = PL_inplace; *s && !isSPACE(*s); s++)
-           ;
+       {
+           const char * const start = ++s;
+           while (*s && !isSPACE(*s))
+               ++s;
+
+           PL_inplace = savepvn(start, s - start);
+       }
        if (*s) {
-           *s++ = '\0';
+           ++s;
            if (*s == '-')      /* Additional switches on #! line. */
-               s++;
+               s++;
        }
        return s;
     case 'I':  /* -I handled both here and in parse_body() */
@@ -3125,8 +3184,6 @@ Perl_moreswitches(pTHX_ char *s)
        return s;
     case 'A':
        forbid_setid('A', -1);
-       if (!PL_preambleav)
-           PL_preambleav = newAV();
        s++;
        {
            char * const start = s;
@@ -3143,7 +3200,7 @@ Perl_moreswitches(pTHX_ char *s)
            else if (*s != '\0') {
                Perl_croak(aTHX_ "Can't use '%c' after -A%.*s", *s, (int)(s-start), start);
            }
-           av_push(PL_preambleav, sv);
+           Perl_av_create_and_push(aTHX_ &PL_preambleav, sv);
            return s;
        }
     case 'M':
@@ -3181,9 +3238,7 @@ Perl_moreswitches(pTHX_ char *s)
                sv_catpvs(sv,  "\0)");
            }
            s += strlen(s);
-           if (!PL_preambleav)
-               PL_preambleav = newAV();
-           av_push(PL_preambleav, sv);
+           Perl_av_create_and_push(aTHX_ &PL_preambleav, sv);
        }
        else
            Perl_croak(aTHX_ "Missing argument to -%c", *(s-1));
@@ -3224,7 +3279,7 @@ Perl_moreswitches(pTHX_ char *s)
        return s;
     case 'v':
        if (!sv_derived_from(PL_patchlevel, "version"))
-           upg_version(PL_patchlevel);
+           upg_version(PL_patchlevel, TRUE);
 #if !defined(DGUX)
        PerlIO_printf(PerlIO_stdout(),
                Perl_form(aTHX_ "\nThis is perl, %"SVf
@@ -3232,13 +3287,13 @@ Perl_moreswitches(pTHX_ char *s)
                          " DEVEL" STRINGIFY(PERL_PATCHNUM)
 #endif
                          " built for %s",
-                   vstringify(PL_patchlevel),
-                   ARCHNAME));
+                         SVfARG(vstringify(PL_patchlevel)),
+                         ARCHNAME));
 #else /* DGUX */
 /* Adjust verbose output as in the perl that ships with the DG/UX OS from EMC */
        PerlIO_printf(PerlIO_stdout(),
                Perl_form(aTHX_ "\nThis is perl, %"SVf"\n",
-                   vstringify(PL_patchlevel)));
+                   SVfARG(vstringify(PL_patchlevel))));
        PerlIO_printf(PerlIO_stdout(),
                        Perl_form(aTHX_ "        built under %s at %s %s\n",
                                        OSNAME, __DATE__, __TIME__));
@@ -3252,12 +3307,12 @@ Perl_moreswitches(pTHX_ char *s)
            PerlIO_printf(PerlIO_stdout(),
                          "\n(with %d registered patch%s, "
                          "see perl -V for more detail)",
-                         (int)LOCAL_PATCH_COUNT,
+                         LOCAL_PATCH_COUNT,
                          (LOCAL_PATCH_COUNT!=1) ? "es" : "");
 #endif
 
        PerlIO_printf(PerlIO_stdout(),
-                     "\n\nCopyright 1987-2006, Larry Wall\n");
+                     "\n\nCopyright 1987-2007, Larry Wall\n");
 #ifdef MACOS_TRADITIONAL
        PerlIO_printf(PerlIO_stdout(),
                      "\nMac OS port Copyright 1991-2002, Matthias Neeracher;\n"
@@ -3334,21 +3389,22 @@ this system using \"man perl\" or \"perldoc perl\".  If you have access to the\n
 Internet, point your browser at http://www.perl.org/, the Perl Home Page.\n\n");
        my_exit(0);
     case 'w':
-       if (! (PL_dowarn & G_WARN_ALL_MASK))
+       if (! (PL_dowarn & G_WARN_ALL_MASK)) {
            PL_dowarn |= G_WARN_ON;
+       }
        s++;
        return s;
     case 'W':
        PL_dowarn = G_WARN_ALL_ON|G_WARN_ON;
         if (!specialWARN(PL_compiling.cop_warnings))
-            SvREFCNT_dec(PL_compiling.cop_warnings);
+            PerlMemShared_free(PL_compiling.cop_warnings);
        PL_compiling.cop_warnings = pWARN_ALL ;
        s++;
        return s;
     case 'X':
        PL_dowarn = G_WARN_ALL_OFF;
         if (!specialWARN(PL_compiling.cop_warnings))
-            SvREFCNT_dec(PL_compiling.cop_warnings);
+            PerlMemShared_free(PL_compiling.cop_warnings);
        PL_compiling.cop_warnings = pWARN_NONE ;
        s++;
        return s;
@@ -3387,15 +3443,14 @@ Internet, point your browser at http://www.perl.org/, the Perl Home Page.\n\n");
 void
 Perl_my_unexec(pTHX)
 {
+    PERL_UNUSED_CONTEXT;
 #ifdef UNEXEC
-    SV*    prog;
-    SV*    file;
+    SV *    prog = newSVpv(BIN_EXP, 0);
+    SV *    file = newSVpv(PL_origfilename, 0);
     int    status = 1;
     extern int etext;
 
-    prog = newSVpv(BIN_EXP, 0);
     sv_catpvs(prog, "/perl");
-    file = newSVpv(PL_origfilename, 0);
     sv_catpvs(file, ".perldump");
 
     unexec(SvPVX(file), SvPVX(prog), &etext, sbrk(0), 0);
@@ -3447,6 +3502,10 @@ S_init_interp(pTHX)
 #  undef PERLVARIC
 #endif
 
+    /* As these are inside a structure, PERLVARI isn't capable of initialising
+       them  */
+    PL_reg_oldcurpm = PL_reg_curpm = NULL;
+    PL_reg_poscache = PL_reg_starttry = NULL;
 }
 
 STATIC void
@@ -3467,18 +3526,18 @@ S_init_main_stash(pTHX)
        of the SvREFCNT_dec, only to add it again with hv_name_set */
     SvREFCNT_dec(GvHV(gv));
     hv_name_set(PL_defstash, "main", 4, 0);
-    GvHV(gv) = (HV*)SvREFCNT_inc(PL_defstash);
+    GvHV(gv) = (HV*)SvREFCNT_inc_simple(PL_defstash);
     SvREADONLY_on(gv);
     PL_incgv = gv_HVadd(gv_AVadd(gv_fetchpvs("INC", GV_ADD|GV_NOTQUAL,
                                             SVt_PVAV)));
-    SvREFCNT_inc(PL_incgv); /* Don't allow it to be freed */
+    SvREFCNT_inc_simple(PL_incgv); /* Don't allow it to be freed */
     GvMULTI_on(PL_incgv);
     PL_hintgv = gv_fetchpvs("\010", GV_ADD|GV_NOTQUAL, SVt_PV); /* ^H */
     GvMULTI_on(PL_hintgv);
     PL_defgv = gv_fetchpvs("_", GV_ADD|GV_NOTQUAL, SVt_PVAV);
-    SvREFCNT_inc(PL_defgv);
+    SvREFCNT_inc_simple(PL_defgv);
     PL_errgv = gv_HVadd(gv_fetchpvs("@", GV_ADD|GV_NOTQUAL, SVt_PV));
-    SvREFCNT_inc(PL_errgv);
+    SvREFCNT_inc_simple(PL_errgv);
     GvMULTI_on(PL_errgv);
     PL_replgv = gv_fetchpvs("\022", GV_ADD|GV_NOTQUAL, SVt_PV); /* ^R */
     GvMULTI_on(PL_replgv);
@@ -3634,8 +3693,8 @@ S_open_script(pTHX_ const char *scriptname, bool dosearch, SV *sv,
 
         Perl_sv_setpvf(aTHX_ cmd, "\
 %s -ne%s%s%s %s | %"SVf" %s %"SVf" %s",
-                       perl, quote, code, quote, scriptname, cpp,
-                       cpp_discard_flag, sv, CPPMINUS);
+                       perl, quote, code, quote, scriptname, SVfARG(cpp),
+                       cpp_discard_flag, SVfARG(sv), CPPMINUS);
 
        PL_doextract = FALSE;
 
@@ -4491,7 +4550,7 @@ S_init_lexer(pTHX)
     dVAR;
     PerlIO *tmpfp;
     tmpfp = PL_rsfp;
-    PL_rsfp = Nullfp;
+    PL_rsfp = NULL;
     lex_start(PL_linestr);
     PL_rsfp = tmpfp;
     PL_subname = newSVpvs("main");
@@ -4512,7 +4571,7 @@ S_init_predump_symbols(pTHX)
     IoIFP(io) = PerlIO_stdin();
     tmpgv = gv_fetchpvs("stdin", GV_ADD|GV_NOTQUAL, SVt_PV);
     GvMULTI_on(tmpgv);
-    GvIOp(tmpgv) = (IO*)SvREFCNT_inc(io);
+    GvIOp(tmpgv) = (IO*)SvREFCNT_inc_simple(io);
 
     tmpgv = gv_fetchpvs("STDOUT", GV_ADD|GV_NOTQUAL, SVt_PVIO);
     GvMULTI_on(tmpgv);
@@ -4522,7 +4581,7 @@ S_init_predump_symbols(pTHX)
     setdefout(tmpgv);
     tmpgv = gv_fetchpvs("stdout", GV_ADD|GV_NOTQUAL, SVt_PV);
     GvMULTI_on(tmpgv);
-    GvIOp(tmpgv) = (IO*)SvREFCNT_inc(io);
+    GvIOp(tmpgv) = (IO*)SvREFCNT_inc_simple(io);
 
     PL_stderrgv = gv_fetchpvs("STDERR", GV_ADD|GV_NOTQUAL, SVt_PVIO);
     GvMULTI_on(PL_stderrgv);
@@ -4531,7 +4590,7 @@ S_init_predump_symbols(pTHX)
     IoOFP(io) = IoIFP(io) = PerlIO_stderr();
     tmpgv = gv_fetchpvs("stderr", GV_ADD|GV_NOTQUAL, SVt_PV);
     GvMULTI_on(tmpgv);
-    GvIOp(tmpgv) = (IO*)SvREFCNT_inc(io);
+    GvIOp(tmpgv) = (IO*)SvREFCNT_inc_simple(io);
 
     PL_statname = newSV(0);            /* last filename we did stat on */
 
@@ -4585,11 +4644,9 @@ S_init_postdump_symbols(pTHX_ register int argc, register char **argv, register
     dVAR;
     GV* tmpgv;
 
-    PL_toptarget = newSV(0);
-    sv_upgrade(PL_toptarget, SVt_PVFM);
+    PL_toptarget = newSV_type(SVt_PVFM);
     sv_setpvn(PL_toptarget, "", 0);
-    PL_bodytarget = newSV(0);
-    sv_upgrade(PL_bodytarget, SVt_PVFM);
+    PL_bodytarget = newSV_type(SVt_PVFM);
     sv_setpvn(PL_bodytarget, "", 0);
     PL_formtarget = PL_bodytarget;
 
@@ -4608,6 +4665,7 @@ S_init_postdump_symbols(pTHX_ register int argc, register char **argv, register
     }
     if ((PL_envgv = gv_fetchpvs("ENV", GV_ADD|GV_NOTQUAL, SVt_PVHV))) {
        HV *hv;
+       bool env_is_not_environ;
        GvMULTI_on(PL_envgv);
        hv = GvHVn(PL_envgv);
        hv_magic(hv, NULL, PERL_MAGIC_env);
@@ -4620,7 +4678,8 @@ S_init_postdump_symbols(pTHX_ register int argc, register char **argv, register
        */
        if (!env)
            env = environ;
-       if (env != environ
+       env_is_not_environ = env != environ;
+       if (env_is_not_environ
 #  ifdef USE_ITHREADS
            && PL_curinterp == aTHX
 #  endif
@@ -4629,7 +4688,6 @@ S_init_postdump_symbols(pTHX_ register int argc, register char **argv, register
            environ[0] = NULL;
        }
        if (env) {
-          char** origenv = environ;
          char *s;
          SV *sv;
          for (; *env; env++) {
@@ -4642,13 +4700,8 @@ S_init_postdump_symbols(pTHX_ register int argc, register char **argv, register
 #endif
            sv = newSVpv(s+1, 0);
            (void)hv_store(hv, *env, s - *env, sv, 0);
-           if (env != environ)
+           if (env_is_not_environ)
                mg_set(sv);
-           if (origenv != environ) {
-             /* realloc has shifted us */
-             env = (env - origenv) + environ;
-             origenv = environ;
-           }
          }
       }
 #endif /* USE_ENVIRON_ARRAY */
@@ -4668,9 +4721,6 @@ S_init_postdump_symbols(pTHX_ register int argc, register char **argv, register
     if (PL_minus_a) {
       (void) get_av("main::F", TRUE | GV_ADDMULTI);
     }
-    /* touch @- and @+ arrays to prevent spurious warnings 20020415 MJD */
-    (void) get_av("main::-", TRUE | GV_ADDMULTI);
-    (void) get_av("main::+", TRUE | GV_ADDMULTI);
 }
 
 STATIC void
@@ -4765,7 +4815,8 @@ S_init_perllib(pTHX)
 #  endif
 #endif
 
-#ifdef SITELIB_STEM /* Search for version-specific dirs below here */
+#if defined(SITELIB_STEM) && defined(PERL_INC_VERSION_LIST)
+    /* Search for version-specific dirs below here */
     incpush(SITELIB_STEM, FALSE, TRUE, TRUE, TRUE);
 #endif
 
@@ -5013,19 +5064,21 @@ S_incpush(pTHX_ const char *dir, bool addsubdirs, bool addoldvers, bool usesep,
 #endif
                /* .../version/archname if -d .../version/archname */
                Perl_sv_setpvf(aTHX_ subdir, "%"SVf PERL_ARCH_FMT_PATH PERL_ARCH_FMT,
-                               libdir,
+                              SVfARG(libdir),
                               (int)PERL_REVISION, (int)PERL_VERSION,
                               (int)PERL_SUBVERSION, ARCHNAME);
                subdir = S_incpush_if_exists(aTHX_ subdir);
 
                /* .../version if -d .../version */
-               Perl_sv_setpvf(aTHX_ subdir, "%"SVf PERL_ARCH_FMT_PATH, libdir,
+               Perl_sv_setpvf(aTHX_ subdir, "%"SVf PERL_ARCH_FMT_PATH,
+                              SVfARG(libdir),
                               (int)PERL_REVISION, (int)PERL_VERSION,
                               (int)PERL_SUBVERSION);
                subdir = S_incpush_if_exists(aTHX_ subdir);
 
                /* .../archname if -d .../archname */
-               Perl_sv_setpvf(aTHX_ subdir, "%"SVf PERL_ARCH_FMT, libdir, ARCHNAME);
+               Perl_sv_setpvf(aTHX_ subdir, "%"SVf PERL_ARCH_FMT,
+                              SVfARG(libdir), ARCHNAME);
                subdir = S_incpush_if_exists(aTHX_ subdir);
 
            }
@@ -5034,7 +5087,8 @@ S_incpush(pTHX_ const char *dir, bool addsubdirs, bool addoldvers, bool usesep,
            if (addoldvers) {
                for (incver = incverlist; *incver; incver++) {
                    /* .../xxx if -d .../xxx */
-                   Perl_sv_setpvf(aTHX_ subdir, "%"SVf PERL_ARCH_FMT, libdir, *incver);
+                   Perl_sv_setpvf(aTHX_ subdir, "%"SVf PERL_ARCH_FMT,
+                                  SVfARG(libdir), *incver);
                    subdir = S_incpush_if_exists(aTHX_ subdir);
                }
            }
@@ -5056,7 +5110,7 @@ Perl_call_list(pTHX_ I32 oldscope, AV *paramList)
 {
     dVAR;
     SV *atsv;
-    const line_t oldline = CopLINE(PL_curcop);
+    volatile const line_t oldline = PL_curcop ? CopLINE(PL_curcop) : 0;
     CV *cv;
     STRLEN len;
     int ret;
@@ -5067,25 +5121,36 @@ Perl_call_list(pTHX_ I32 oldscope, AV *paramList)
        if (PL_savebegin) {
            if (paramList == PL_beginav) {
                /* save PL_beginav for compiler */
-               if (! PL_beginav_save)
-                   PL_beginav_save = newAV();
-               av_push(PL_beginav_save, (SV*)cv);
+               Perl_av_create_and_push(aTHX_ &PL_beginav_save, (SV*)cv);
            }
            else if (paramList == PL_checkav) {
                /* save PL_checkav for compiler */
-               if (! PL_checkav_save)
-                   PL_checkav_save = newAV();
-               av_push(PL_checkav_save, (SV*)cv);
+               Perl_av_create_and_push(aTHX_ &PL_checkav_save, (SV*)cv);
+           }
+           else if (paramList == PL_unitcheckav) {
+               /* save PL_unitcheckav for compiler */
+               Perl_av_create_and_push(aTHX_ &PL_unitcheckav_save, (SV*)cv);
            }
        } else {
-           SAVEFREESV(cv);
+           if (!PL_madskills)
+               SAVEFREESV(cv);
        }
        JMPENV_PUSH(ret);
        switch (ret) {
        case 0:
-           call_list_body(cv);
+#ifdef PERL_MAD
+           if (PL_madskills)
+               PL_madskills |= 16384;
+#endif
+           CALL_LIST_BODY(cv);
+#ifdef PERL_MAD
+           if (PL_madskills)
+               PL_madskills &= ~16384;
+#endif
            atsv = ERRSV;
            (void)SvPV_const(atsv, len);
+           if (PL_madskills && PL_minus_c && paramList == PL_beginav)
+               break;  /* not really trying to run, so just wing it */
            if (len) {
                PL_curcop = &PL_compiling;
                CopLINE_set(PL_curcop, oldline);
@@ -5096,11 +5161,12 @@ Perl_call_list(pTHX_ I32 oldscope, AV *paramList)
                                   "%s failed--call queue aborted",
                                   paramList == PL_checkav ? "CHECK"
                                   : paramList == PL_initav ? "INIT"
+                                  : paramList == PL_unitcheckav ? "UNITCHECK"
                                   : "END");
                while (PL_scopestack_ix > oldscope)
                    LEAVE;
                JMPENV_POP;
-               Perl_croak(aTHX_ "%"SVf"", atsv);
+               Perl_croak(aTHX_ "%"SVf"", SVfARG(atsv));
            }
            break;
        case 1:
@@ -5115,6 +5181,8 @@ Perl_call_list(pTHX_ I32 oldscope, AV *paramList)
            PL_curcop = &PL_compiling;
            CopLINE_set(PL_curcop, oldline);
            JMPENV_POP;
+           if (PL_madskills && PL_minus_c && paramList == PL_beginav)
+               return; /* not really trying to run, so just wing it */
            if (PL_statusvalue && !(PL_exit_flags & PERL_EXIT_EXPECTED)) {
                if (paramList == PL_beginav)
                    Perl_croak(aTHX_ "BEGIN failed--compilation aborted");
@@ -5122,6 +5190,7 @@ Perl_call_list(pTHX_ I32 oldscope, AV *paramList)
                    Perl_croak(aTHX_ "%s failed--call queue aborted",
                               paramList == PL_checkav ? "CHECK"
                               : paramList == PL_initav ? "INIT"
+                              : paramList == PL_unitcheckav ? "UNITCHECK"
                               : "END");
            }
            my_exit_jump();
@@ -5140,21 +5209,12 @@ Perl_call_list(pTHX_ I32 oldscope, AV *paramList)
     }
 }
 
-STATIC void *
-S_call_list_body(pTHX_ CV *cv)
-{
-    dVAR;
-    PUSHMARK(PL_stack_sp);
-    call_sv((SV*)cv, G_EVAL|G_DISCARD);
-    return NULL;
-}
-
 void
 Perl_my_exit(pTHX_ U32 status)
 {
     dVAR;
     DEBUG_S(PerlIO_printf(Perl_debug_log, "my_exit: thread %p, status %lu\n",
-                         thr, (unsigned long) status));
+                         (void*)thr, (unsigned long) status));
     switch (status) {
     case 0:
        STATUS_ALL_SUCCESS;
@@ -5247,9 +5307,6 @@ STATIC void
 S_my_exit_jump(pTHX)
 {
     dVAR;
-    register PERL_CONTEXT *cx;
-    I32 gimme;
-    SV **newsp;
 
     if (PL_e_script) {
        SvREFCNT_dec(PL_e_script);
@@ -5257,16 +5314,10 @@ S_my_exit_jump(pTHX)
     }
 
     POPSTACK_TO(PL_mainstack);
-    if (cxstack_ix >= 0) {
-       if (cxstack_ix > 0)
-           dounwind(0);
-       POPBLOCK(cx,PL_curpm);
-       LEAVE;
-    }
+    dounwind(-1);
+    LEAVE_SCOPE(0);
 
     JMPENV_JUMP(2);
-    PERL_UNUSED_VAR(gimme);
-    PERL_UNUSED_VAR(newsp);
 }
 
 static I32