This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
In taint.t, replace calls to all_tainted() with a loop over is_tainted().
[perl5.git] / perl.c
diff --git a/perl.c b/perl.c
index cf42087..6bb9f46 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -2,8 +2,8 @@
 /*    perl.c
  *
  *    Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
- *    2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by Larry Wall
- *    and others
+ *    2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+ *     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.
  * function of the interpreter; that can be found in perlmain.c
  */
 
+#ifdef PERL_IS_MINIPERL
+#  define USE_SITECUSTOMIZE
+#endif
+
 #include "EXTERN.h"
 #define PERL_IN_PERL_C
 #include "perl.h"
@@ -80,12 +84,6 @@ static I32 read_e_script(pTHX_ int idx, SV *buf_sv, int maxlen);
 #  define validate_suid(validarg, scriptname, fdscript, suidscript, linestr_sv, rsfp) S_validate_suid(aTHX_ rsfp)
 #endif
 
-#define CALL_BODY_EVAL(myop) \
-    if (PL_op == (myop)) \
-       PL_op = PL_ppaddr[OP_ENTEREVAL](aTHX); \
-    if (PL_op) \
-       CALLRUNOPS(aTHX);
-
 #define CALL_BODY_SUB(myop) \
     if (PL_op == (myop)) \
        PL_op = PL_ppaddr[OP_ENTERSUB](aTHX); \
@@ -563,8 +561,10 @@ perl_destruct(pTHXx)
 
         JMPENV_PUSH(x);
        PERL_UNUSED_VAR(x);
-        if (PL_endav && !PL_minus_c)
+        if (PL_endav && !PL_minus_c) {
+           PL_phase = PERL_PHASE_END;
             call_list(PL_scopestack_ix, PL_endav);
+       }
         JMPENV_POP;
     }
     LEAVE;
@@ -757,7 +757,7 @@ perl_destruct(pTHXx)
      * destruct_level > 0 */
     SvREFCNT_dec(PL_main_cv);
     PL_main_cv = NULL;
-    PL_dirty = TRUE;
+    PL_phase = PERL_PHASE_DESTRUCT;
 
     /* Tell PerlIO we are about to tear things apart in case
        we have layers which are using resources that should
@@ -870,7 +870,6 @@ perl_destruct(pTHXx)
     PL_minus_F      = FALSE;
     PL_doswitches   = FALSE;
     PL_dowarn       = G_WARN_OFF;
-    PL_doextract    = FALSE;
     PL_sawampersand = FALSE;   /* must save all match strings */
     PL_unsafe       = FALSE;
 
@@ -1010,6 +1009,7 @@ perl_destruct(pTHXx)
     SvREFCNT_dec(PL_utf8_tofold);
     SvREFCNT_dec(PL_utf8_idstart);
     SvREFCNT_dec(PL_utf8_idcont);
+    SvREFCNT_dec(PL_utf8_foldclosures);
     PL_utf8_alnum      = NULL;
     PL_utf8_ascii      = NULL;
     PL_utf8_alpha      = NULL;
@@ -1029,12 +1029,13 @@ perl_destruct(pTHXx)
     PL_utf8_tofold     = NULL;
     PL_utf8_idstart    = NULL;
     PL_utf8_idcont     = NULL;
+    PL_utf8_foldclosures = NULL;
 
     if (!specialWARN(PL_compiling.cop_warnings))
        PerlMemShared_free(PL_compiling.cop_warnings);
     PL_compiling.cop_warnings = NULL;
-    Perl_refcounted_he_free(aTHX_ PL_compiling.cop_hints_hash);
-    PL_compiling.cop_hints_hash = NULL;
+    cophh_free(CopHINTHASH_get(&PL_compiling));
+    CopHINTHASH_set(&PL_compiling, cophh_new_empty());
     CopFILE_free(&PL_compiling);
     CopSTASH_free(&PL_compiling);
 
@@ -1472,7 +1473,7 @@ perl_parse(pTHXx_ XSINIT_t xsinit, int argc, char **argv, char **env)
 #if defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT)
     /* [perl #22371] Algorimic Complexity Attack on Perl 5.6.1, 5.8.0
      * This MUST be done before any hash stores or fetches take place.
-     * If you set PL_rehash_seed (and assumedly also PL_rehash_seed_set)
+     * If you set PL_rehash_seed (and presumably also PL_rehash_seed_set)
      * yourself, it is your responsibility to provide a good random seed!
      * You can also define PERL_HASH_SEED in compile time, see hv.h. */
     if (!PL_rehash_seed_set)
@@ -1610,10 +1611,13 @@ perl_parse(pTHXx_ XSINIT_t xsinit, int argc, char **argv, char **env)
     switch (ret) {
     case 0:
        parse_body(env,xsinit);
-       if (PL_unitcheckav)
+       if (PL_unitcheckav) {
            call_list(oldscope, PL_unitcheckav);
-       if (PL_checkav)
+       }
+       if (PL_checkav) {
+           PL_phase = PERL_PHASE_CHECK;
            call_list(oldscope, PL_checkav);
+       }
        ret = 0;
        break;
     case 1:
@@ -1625,10 +1629,13 @@ perl_parse(pTHXx_ XSINIT_t xsinit, int argc, char **argv, char **env)
            LEAVE;
        FREETMPS;
        PL_curstash = PL_defstash;
-       if (PL_unitcheckav)
+       if (PL_unitcheckav) {
            call_list(oldscope, PL_unitcheckav);
-       if (PL_checkav)
+       }
+       if (PL_checkav) {
+           PL_phase = PERL_PHASE_CHECK;
            call_list(oldscope, PL_checkav);
+       }
        ret = STATUS_EXIT;
        break;
     case 3:
@@ -1752,6 +1759,7 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
     const char *scriptname = NULL;
     VOL bool dosearch = FALSE;
     register char c;
+    bool doextract = FALSE;
     const char *cddir = NULL;
 #ifdef USE_SITECUSTOMIZE
     bool minus_f = FALSE;
@@ -1759,6 +1767,8 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
     SV *linestr_sv = newSV_type(SVt_PVIV);
     bool add_read_e_script = FALSE;
 
+    PL_phase = PERL_PHASE_START;
+
     SvGROW(linestr_sv, 80);
     sv_setpvs(linestr_sv,"");
 
@@ -1880,7 +1890,7 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
                goto reswitch;
            }
        case 'x':
-           PL_doextract = TRUE;
+           doextract = TRUE;
            s++;
            if (*s)
                cddir = s;
@@ -1967,15 +1977,26 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
     }
     }
 
-#if defined(USE_SITECUSTOMIZE) && !defined(PERL_IS_MINIPERL)
+#if defined(USE_SITECUSTOMIZE)
     if (!minus_f) {
-       /* SITELIB_EXP is a function call on Win32.
-          The games with local $! are to avoid setting errno if there is no
+       /* The games with local $! are to avoid setting errno if there is no
           sitecustomize script.  */
+#  ifdef PERL_IS_MINIPERL
+       AV *const inc = GvAV(PL_incgv);
+       SV **const inc0 = inc ? av_fetch(inc, 0, FALSE) : NULL;
+
+       if (inc0) {
+           (void)Perl_av_create_and_unshift_one(aTHX_ &PL_preambleav,
+                                                Perl_newSVpvf(aTHX_
+                                                              "BEGIN { do {local $!; -f '%"SVf"/buildcustomize.pl'} && do '%"SVf"/buildcustomize.pl' }", *inc0, *inc0));
+       }
+#  else
+       /* SITELIB_EXP is a function call on Win32.  */
        const char *const sitelib = SITELIB_EXP;
        (void)Perl_av_create_and_unshift_one(aTHX_ &PL_preambleav,
                                             Perl_newSVpvf(aTHX_
                                                           "BEGIN { do {local $!; -f '%s/sitecustomize.pl'} && do '%s/sitecustomize.pl' }", sitelib, sitelib));
+#  endif
     }
 #endif
 
@@ -2024,7 +2045,7 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
 #  endif
 #endif
 
-       if (PL_doextract) {
+       if (doextract) {
 
            /* This will croak if suidscript is true, as -x cannot be used with
               setuid scripts.  */
@@ -2158,7 +2179,7 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
     }
 #endif
 
-    lex_start(linestr_sv, rsfp, TRUE);
+    lex_start(linestr_sv, rsfp, 0);
     PL_subname = newSVpvs("main");
 
     if (add_read_e_script)
@@ -2249,8 +2270,10 @@ perl_run(pTHXx)
        FREETMPS;
        PL_curstash = PL_defstash;
        if (!(PL_exit_flags & PERL_EXIT_DESTRUCT_END) &&
-           PL_endav && !PL_minus_c)
+           PL_endav && !PL_minus_c) {
+           PL_phase = PERL_PHASE_END;
            call_list(oldscope, PL_endav);
+       }
 #ifdef MYMALLOC
        if (PerlEnv_getenv("PERL_DEBUG_MSTATS"))
            dump_mstats("after execution:  ");
@@ -2299,8 +2322,10 @@ S_run_body(pTHX_ I32 oldscope)
        }
        if (PERLDB_SINGLE && PL_DBsingle)
            sv_setiv(PL_DBsingle, 1);
-       if (PL_initav)
+       if (PL_initav) {
+           PL_phase = PERL_PHASE_INIT;
            call_list(oldscope, PL_initav);
+       }
 #ifdef PERL_DEBUG_READONLY_OPS
        Perl_pending_Slabs_to_ro(aTHX);
 #endif
@@ -2308,6 +2333,8 @@ S_run_body(pTHX_ I32 oldscope)
 
     /* do it */
 
+    PL_phase = PERL_PHASE_RUN;
+
     if (PL_restartop) {
        PL_restartjmpenv = NULL;
        PL_op = PL_restartop;
@@ -2667,7 +2694,8 @@ Perl_call_sv(pTHX_ SV *sv, VOL I32 flags)
 /*
 =for apidoc p||eval_sv
 
-Tells Perl to C<eval> the string in the SV.
+Tells Perl to C<eval> the string in the SV. It supports the same flags
+as C<call_sv>, with the obvious exception of G_EVAL. See L<perlcall>.
 
 =cut
 */
@@ -2715,7 +2743,12 @@ Perl_eval_sv(pTHX_ SV *sv, I32 flags)
     switch (ret) {
     case 0:
  redo_body:
-       CALL_BODY_EVAL((OP*)&myop);
+       if (PL_op == (OP*)(&myop)) {
+           PL_op = PL_ppaddr[OP_ENTEREVAL](aTHX);
+           if (!PL_op)
+               goto fail; /* failed in compilation */
+       }
+       CALLRUNOPS(aTHX);
        retval = PL_stack_sp - (PL_stack_base + oldmark);
        if (!(flags & G_KEEPERR)) {
            CLEAR_ERRSV();
@@ -2738,6 +2771,7 @@ Perl_eval_sv(pTHX_ SV *sv, I32 flags)
            PL_restartop = 0;
            goto redo_body;
        }
+      fail:
        PL_stack_sp = PL_stack_base + oldmark;
        if ((flags & G_WANT) == G_ARRAY)
            retval = 0;
@@ -3029,11 +3063,21 @@ Perl_moreswitches(pTHX_ const char *s)
        /* The following permits -d:Mod to accepts arguments following an =
           in the fashion that -MSome::Mod does. */
        if (*s == ':' || *s == '=') {
-           const char *start = ++s;
-           const char *const end = s + strlen(s);
-           SV * const sv = newSVpvs("use Devel::");
+           const char *start;
+           const char *end;
+           SV *sv;
+
+           if (*++s == '-') {
+               ++s;
+               sv = newSVpvs("no Devel::");
+           } else {
+               sv = newSVpvs("use Devel::");
+           }
 
-           /* We now allow -d:Module=Foo,Bar */
+           start = s;
+           end = s + strlen(s);
+
+           /* We now allow -d:Module=Foo,Bar and -d:-Module */
            while(isALNUM(*s) || *s==':') ++s;
            if (*s != '=')
                sv_catpvn(sv, start, end - start);
@@ -3275,7 +3319,7 @@ Perl_moreswitches(pTHX_ const char *s)
 #endif
 
        PerlIO_printf(PerlIO_stdout(),
-                     "\n\nCopyright 1987-2010, Larry Wall\n");
+                     "\n\nCopyright 1987-2011, Larry Wall\n");
 #ifdef MSDOS
        PerlIO_printf(PerlIO_stdout(),
                      "\nMS-DOS port Copyright (c) 1989, 1990, Diomidis Spinellis\n");
@@ -3673,24 +3717,21 @@ S_find_beginning(pTHX_ SV* linestr_sv, PerlIO *rsfp)
 
     /* skip forward in input to the real script? */
 
-    while (PL_doextract) {
+    do {
        if ((s = sv_gets(linestr_sv, rsfp, 0)) == NULL)
            Perl_croak(aTHX_ "No Perl script found in input\n");
        s2 = s;
-       if (*s == '#' && s[1] == '!' && ((s = instr(s,"perl")) || (s = instr(s2,"PERL")))) {
-           PerlIO_ungetc(rsfp, '\n');          /* to keep line count right */
-           PL_doextract = FALSE;
-           while (*s && !(isSPACE (*s) || *s == '#')) s++;
-           s2 = s;
-           while (*s == ' ' || *s == '\t') s++;
-           if (*s++ == '-') {
-               while (isDIGIT(s2[-1]) || s2[-1] == '-' || s2[-1] == '.'
-                      || s2[-1] == '_') s2--;
-               if (strnEQ(s2-4,"perl",4))
-                   while ((s = moreswitches(s)))
-                       ;
-           }
-       }
+    } while (!(*s == '#' && s[1] == '!' && ((s = instr(s,"perl")) || (s = instr(s2,"PERL")))));
+    PerlIO_ungetc(rsfp, '\n');         /* to keep line count right */
+    while (*s && !(isSPACE (*s) || *s == '#')) s++;
+    s2 = s;
+    while (*s == ' ' || *s == '\t') s++;
+    if (*s++ == '-') {
+       while (isDIGIT(s2[-1]) || s2[-1] == '-' || s2[-1] == '.'
+              || s2[-1] == '_') s2--;
+       if (strnEQ(s2-4,"perl",4))
+           while ((s = moreswitches(s)))
+               ;
     }
 }
 
@@ -3892,6 +3933,39 @@ S_nuke_stacks(pTHX)
     Safefree(PL_savestack);
 }
 
+void
+Perl_populate_isa(pTHX_ const char *name, STRLEN len, ...)
+{
+    GV *const gv = gv_fetchpvn(name, len, GV_ADD | GV_ADDMULTI, SVt_PVAV);
+    AV *const isa = GvAVn(gv);
+    va_list args;
+
+    PERL_ARGS_ASSERT_POPULATE_ISA;
+
+    if(AvFILLp(isa) != -1)
+       return;
+
+    /* NOTE: No support for tied ISA */
+
+    va_start(args, len);
+    do {
+       const char *const parent = va_arg(args, const char*);
+       size_t parent_len;
+
+       if (!parent)
+           break;
+       parent_len = va_arg(args, size_t);
+
+       /* Arguments are supplied with a trailing ::  */
+       assert(parent_len > 2);
+       assert(parent[parent_len - 1] == ':');
+       assert(parent[parent_len - 2] == ':');
+       av_push(isa, newSVpvn(parent, parent_len - 2));
+       (void) gv_fetchpvn(parent, parent_len, GV_ADD, SVt_PVGV);
+    } while (1);
+    va_end(args);
+}
+
 
 STATIC void
 S_init_predump_symbols(pTHX)
@@ -3899,7 +3973,6 @@ S_init_predump_symbols(pTHX)
     dVAR;
     GV *tmpgv;
     IO *io;
-    AV *isa;
 
     sv_setpvs(get_sv("\"", GV_ADD), " ");
     PL_ofsgv = (GV*)SvREFCNT_inc(gv_fetchpvs(",", GV_ADD|GV_NOTQUAL, SVt_PV));
@@ -3918,14 +3991,11 @@ S_init_predump_symbols(pTHX)
        so that code that does C<use IO::Handle>; will still work.
     */
                   
-    isa = get_av("IO::File::ISA", GV_ADD | GV_ADDMULTI);
-    av_push(isa, newSVpvs("IO::Handle"));
-    av_push(isa, newSVpvs("IO::Seekable"));
-    av_push(isa, newSVpvs("Exporter"));
-    (void) gv_fetchpvs("IO::Handle::", GV_ADD, SVt_PVGV);
-    (void) gv_fetchpvs("IO::Seekable::", GV_ADD, SVt_PVGV);
-    (void) gv_fetchpvs("Exporter::", GV_ADD, SVt_PVGV);
-
+    Perl_populate_isa(aTHX_ STR_WITH_LEN("IO::File::ISA"),
+                     STR_WITH_LEN("IO::Handle::"),
+                     STR_WITH_LEN("IO::Seekable::"),
+                     STR_WITH_LEN("Exporter::"),
+                     NULL);
 
     PL_stdingv = gv_fetchpvs("STDIN", GV_ADD|GV_NOTQUAL, SVt_PVIO);
     GvMULTI_on(PL_stdingv);
@@ -4446,7 +4516,7 @@ S_incpush(pTHX_ const char *const dir, STRLEN len, U32 flags)
                    libdir = tempsv;
                    if (PL_tainting &&
                        (PL_uid != PL_euid || PL_gid != PL_egid)) {
-                       /* Need to taint reloccated paths if running set ID  */
+                       /* Need to taint relocated paths if running set ID  */
                        SvTAINTED_on(libdir);
                    }
                }