This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
The change to the internal representation introduced a bug whereby
[perl5.git] / perl.c
diff --git a/perl.c b/perl.c
index f387cf1..03187a3 100644 (file)
--- a/perl.c
+++ b/perl.c
  * "A ship then new they built for him/of mithril and of elven glass" --Bilbo
  */
 
+/* This file contains the top-level functions that are used to create, use
+ * and destroy a perl interpreter, plus the functions used by XS code to
+ * call back into perl. Note that it does not contain the actual main()
+ * function of the interpreter; that can be found in perlmain.c
+ */
+
 /* PSz 12 Nov 03
  * 
  * Be proud that perl(1) may proclaim:
@@ -190,8 +196,7 @@ perl_alloc(void)
     my_perl = (PerlInterpreter*)PerlMem_malloc(sizeof(PerlInterpreter));
 
     INIT_TLS_AND_INTERP;
-    Zero(my_perl, 1, PerlInterpreter);
-    return my_perl;
+    return ZeroD(my_perl, 1, PerlInterpreter);
 }
 #endif /* PERL_IMPLICIT_SYS */
 
@@ -232,11 +237,15 @@ perl_construct(pTHXx)
            SvREFCNT(&PL_sv_undef) = (~(U32)0)/2;
 
            sv_setpv(&PL_sv_no,PL_No);
+           /* value lookup in void context - happens to have the side effect
+              of caching the numeric forms.  */
+           SvIV(&PL_sv_no);
            SvNV(&PL_sv_no);
            SvREADONLY_on(&PL_sv_no);
            SvREFCNT(&PL_sv_no) = (~(U32)0)/2;
 
            sv_setpv(&PL_sv_yes,PL_Yes);
+           SvIV(&PL_sv_yes);
            SvNV(&PL_sv_yes);
            SvREADONLY_on(&PL_sv_yes);
            SvREFCNT(&PL_sv_yes) = (~(U32)0)/2;
@@ -262,28 +271,6 @@ perl_construct(pTHXx)
     init_i18nl10n(1);
     SET_NUMERIC_STANDARD();
 
-    {
-       U8 *s;
-       PL_patchlevel = NEWSV(0,4);
-       (void)SvUPGRADE(PL_patchlevel, SVt_PVNV);
-       if (PERL_REVISION > 127 || PERL_VERSION > 127 || PERL_SUBVERSION > 127)
-           SvGROW(PL_patchlevel, UTF8_MAXLEN*3+1);
-       s = (U8*)SvPVX(PL_patchlevel);
-       /* Build version strings using "native" characters */
-       s = uvchr_to_utf8(s, (UV)PERL_REVISION);
-       s = uvchr_to_utf8(s, (UV)PERL_VERSION);
-       s = uvchr_to_utf8(s, (UV)PERL_SUBVERSION);
-       *s = '\0';
-       SvCUR_set(PL_patchlevel, s - (U8*)SvPVX(PL_patchlevel));
-       SvPOK_on(PL_patchlevel);
-       SvNVX(PL_patchlevel) = (NV)PERL_REVISION +
-                             ((NV)PERL_VERSION / (NV)1000) +
-                             ((NV)PERL_SUBVERSION / (NV)1000000);
-       SvNOK_on(PL_patchlevel);        /* dual valued */
-       SvUTF8_on(PL_patchlevel);
-       SvREADONLY_on(PL_patchlevel);
-    }
-
 #if defined(LOCAL_PATCH_COUNT)
     PL_localpatches = local_patches;   /* For possible -v */
 #endif
@@ -338,6 +325,13 @@ perl_construct(pTHXx)
 
     PL_stashcache = newHV();
 
+    PL_patchlevel = newSVpv(
+           Perl_form(aTHX_ "%d.%d.%d",
+           (int)PERL_REVISION,
+           (int)PERL_VERSION,
+           (int)PERL_SUBVERSION ), 0
+    );
+
     ENTER;
 }
 
@@ -477,7 +471,7 @@ perl_destruct(pTHXx)
      */
 #ifndef PERL_MICRO
 #if defined(USE_ENVIRON_ARRAY) && !defined(PERL_USE_SAFE_PUTENV)
-    if (environ != PL_origenviron
+    if (environ != PL_origenviron && !PL_use_safe_putenv
 #ifdef USE_ITHREADS
        /* only main thread can free environ[0] contents */
        && PL_curinterp == aTHX
@@ -497,6 +491,9 @@ perl_destruct(pTHXx)
 #endif
 #endif /* !PERL_MICRO */
 
+    /* reset so print() ends up where we expect */
+    setdefout(Nullgv);
+
 #ifdef USE_ITHREADS
     /* the syntax tree is shared between clones
      * so op_free(PL_main_root) only ReREFCNT_dec's
@@ -638,9 +635,6 @@ perl_destruct(pTHXx)
     PL_dbargs = Nullav;
     PL_debstash = Nullhv;
 
-    /* reset so print() ends up where we expect */
-    setdefout(Nullgv);
-
     SvREFCNT_dec(PL_argvout_stack);
     PL_argvout_stack = Nullav;
 
@@ -847,9 +841,10 @@ perl_destruct(pTHXx)
            svend = &sva[SvREFCNT(sva)];
            for (sv = sva + 1; sv < svend; ++sv) {
                if (SvTYPE(sv) != SVTYPEMASK) {
-                   PerlIO_printf(Perl_debug_log, "leaked: 0x%p"
-                                  pTHX__FORMAT "\n",
-                                  sv pTHX__VALUE);
+                   PerlIO_printf(Perl_debug_log, "leaked: sv=0x%p"
+                       " flags=0x08%"UVxf
+                       " refcnt=%"UVuf pTHX__FORMAT "\n",
+                       sv, sv->sv_flags, sv->sv_refcnt pTHX__VALUE);
                }
            }
        }
@@ -921,7 +916,7 @@ perl_destruct(pTHXx)
            }
        }
        /* we know that type >= SVt_PV */
-       (void)SvOOK_off(PL_mess_sv);
+       SvOOK_off(PL_mess_sv);
        Safefree(SvPVX(PL_mess_sv));
        Safefree(SvANY(PL_mess_sv));
        Safefree(PL_mess_sv);
@@ -2052,7 +2047,6 @@ Perl_call_sv(pTHX_ SV *sv, I32 flags)
            ENTER;
            SAVETMPS;
        
-           push_return(Nullop);
            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. */
@@ -2119,7 +2113,6 @@ Perl_call_sv(pTHX_ SV *sv, I32 flags)
 
            POPBLOCK(cx,newpm);
            POPEVAL(cx);
-           pop_return();
            PL_curpm = newpm;
            LEAVE;
        }
@@ -2212,6 +2205,10 @@ Perl_eval_sv(pTHX_ SV *sv, I32 flags)
     CALLPROTECT(aTHX_ pcur_env, &ret, MEMBER_TO_FPTR(S_vcall_body),
                (OP*)&myop, TRUE);
 #else
+    /* fail now; otherwise we could fail after the JMPENV_PUSH but
+     * before a PUSHEVAL, which corrupts the stack after a croak */
+    TAINT_PROPER("eval_sv()");
+
     JMPENV_PUSH(ret);
 #endif
     switch (ret) {
@@ -2381,12 +2378,12 @@ NULL
 
 #ifdef DEBUGGING
 int
-Perl_get_debug_opts(pTHX_ char **s)
+Perl_get_debug_opts(pTHX_ char **s, bool givehelp)
 {
     static char *usage_msgd[] = {
       " Debugging flag values: (see also -d)",
       "  p  Tokenizing and parsing (with v, displays parse stack)",
-      "  s  Stack snapshots. with v, displays all stacks",
+      "  s  Stack snapshots (with v, displays all stacks)",
       "  l  Context (loop) stack processing",
       "  t  Trace execution",
       "  o  Method and overloading resolution",
@@ -2396,7 +2393,7 @@ Perl_get_debug_opts(pTHX_ char **s)
       "  f  Format processing",
       "  r  Regular expression parsing and execution",
       "  x  Syntax tree dump",
-      "  u  Tainting checks (Obsolete, previously used for LEAKTEST)",
+      "  u  Tainting checks",
       "  H  Hash dump -- usurps values()",
       "  X  Scratchpad allocation",
       "  D  Cleaning up",
@@ -2407,7 +2404,7 @@ Perl_get_debug_opts(pTHX_ char **s)
       "  v  Verbose: use in conjunction with other flags",
       "  C  Copy On Write",
       "  A  Consistency checks on internal structures",
-      "  q  quiet - currently only suppressed the 'EXECUTING' message",
+      "  q  quiet - currently only suppresses the 'EXECUTING' message",
       NULL
     };
     int i = 0;
@@ -2428,7 +2425,7 @@ Perl_get_debug_opts(pTHX_ char **s)
        i = atoi(*s);
        for (; isALNUM(**s); (*s)++) ;
     }
-    else {
+    else if (givehelp) {
       char **p = usage_msgd;
       while (*p) PerlIO_printf(PerlIO_stdout(), "%s\n", *p++);
     }
@@ -2512,6 +2509,13 @@ Perl_moreswitches(pTHX_ char *s)
     case 'd':
        forbid_setid("-d");
        s++;
+
+        /* -dt indicates to the debugger that threads will be used */
+       if (*s == 't' && !isALNUM(s[1])) {
+           ++s;
+           my_setenv("PERL5DB_THREADED", "1");
+       }
+
        /* The following permits -d:Mod to accepts arguments following an =
           in the fashion that -MSome::Mod does. */
        if (*s == ':' || *s == '=') {
@@ -2542,7 +2546,7 @@ Perl_moreswitches(pTHX_ char *s)
 #ifdef DEBUGGING
        forbid_setid("-D");
        s++;
-       PL_debug = get_debug_opts(&s) | DEBUG_TOP_FLAG;
+       PL_debug = get_debug_opts(&s, 1) | DEBUG_TOP_FLAG;
 #else /* !DEBUGGING */
        if (ckWARN_d(WARN_DEBUGGING))
            Perl_warner(aTHX_ packWARN(WARN_DEBUGGING),
@@ -2674,7 +2678,7 @@ Perl_moreswitches(pTHX_ char *s)
            av_push(PL_preambleav, sv);
        }
        else
-           Perl_croak(aTHX_ "No space allowed after -%c", *(s-1));
+           Perl_croak(aTHX_ "Missing argument to -%c", *(s-1));
        return s;
     case 'n':
        PL_minus_n = TRUE;
@@ -2711,14 +2715,18 @@ Perl_moreswitches(pTHX_ char *s)
        s++;
        return s;
     case 'v':
+       if (!sv_derived_from(PL_patchlevel, "version"))
+               (void *)upg_version(PL_patchlevel);
 #if !defined(DGUX)
        PerlIO_printf(PerlIO_stdout(),
-                     Perl_form(aTHX_ "\nThis is perl, v%"VDf" built for %s",
-                               PL_patchlevel, ARCHNAME));
+               Perl_form(aTHX_ "\nThis is perl, v%_ built for %s",
+                   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, version %vd\n", PL_patchlevel));
+               Perl_form(aTHX_ "\nThis is perl, v%_\n",
+                   vstringify(PL_patchlevel)));
        PerlIO_printf(PerlIO_stdout(),
                        Perl_form(aTHX_ "        built under %s at %s %s\n",
                                        OSNAME, __DATE__, __TIME__));
@@ -2807,7 +2815,7 @@ Perl may be copied only under the terms of either the Artistic License or the\n\
 GNU General Public License, which may be found in the Perl 5 source kit.\n\n\
 Complete documentation for Perl, including FAQ lists, should be found on\n\
 this system using `man perl' or `perldoc perl'.  If you have access to the\n\
-Internet, point your browser at http://www.perl.com/, the Perl Home Page.\n\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))
@@ -3127,9 +3135,8 @@ S_open_script(pTHX_ char *scriptname, bool dosearch, SV *sv)
 #endif /* IAMSUID */
     if (!PL_rsfp) {
        /* PSz 16 Sep 03  Keep neat error message */
-       Perl_croak(aTHX_ "Can't open perl script \"%s\": %s%s\n",
-               CopFILE(PL_curcop), Strerror(errno),
-               ".\nUse -S to search $PATH for it.");
+       Perl_croak(aTHX_ "Can't open perl script \"%s\": %s\n",
+               CopFILE(PL_curcop), Strerror(errno));
     }
 }
 
@@ -3893,10 +3900,6 @@ Perl_init_stacks(pTHX)
     New(54,PL_savestack,REASONABLE(128),ANY);
     PL_savestack_ix = 0;
     PL_savestack_max = REASONABLE(128);
-
-    New(54,PL_retstack,REASONABLE(16),OP*);
-    PL_retstack_ix = 0;
-    PL_retstack_max = REASONABLE(16);
 }
 
 #undef REASONABLE
@@ -3917,7 +3920,6 @@ S_nuke_stacks(pTHX)
     Safefree(PL_markstack);
     Safefree(PL_scopestack);
     Safefree(PL_savestack);
-    Safefree(PL_retstack);
 }
 
 STATIC void
@@ -4107,9 +4109,10 @@ S_init_postdump_symbols(pTHX_ register int argc, register char **argv, register
        {
            environ[0] = Nullch;
        }
-       if (env)
+       if (env) {
+          char** origenv = environ;
          for (; *env; env++) {
-           if (!(s = strchr(*env,'=')))
+           if (!(s = strchr(*env,'=')) || s == *env)
                continue;
 #if defined(MSDOS) && !defined(DJGPP)
            *s = '\0';
@@ -4120,7 +4123,13 @@ S_init_postdump_symbols(pTHX_ register int argc, register char **argv, register
            (void)hv_store(hv, *env, s - *env, sv, 0);
            if (env != environ)
                mg_set(sv);
+           if (origenv != environ) {
+             /* realloc has shifted us */
+             env = (env - origenv) + environ;
+             origenv = environ;
+           }
          }
+      }
 #endif /* USE_ENVIRON_ARRAY */
 #endif /* !PERL_MICRO */
     }