This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Re: [PATCH] "Constant subroutine redefined" mandatory warning
[perl5.git] / perl.c
diff --git a/perl.c b/perl.c
index a235122..cbe966c 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -1,6 +1,6 @@
 /*    perl.c
  *
- *    Copyright (c) 1987-1999 Larry Wall
+ *    Copyright (c) 1987-2000 Larry Wall
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
@@ -27,13 +27,6 @@ char *getenv (char *); /* Usually in <stdlib.h> */
 
 static I32 read_e_script(pTHXo_ int idx, SV *buf_sv, int maxlen);
 
-#ifdef I_FCNTL
-#include <fcntl.h>
-#endif
-#ifdef I_SYS_FILE
-#include <sys/file.h>
-#endif
-
 #ifdef IAMSUID
 #ifndef DOSUID
 #define DOSUID
@@ -54,6 +47,41 @@ static I32 read_e_script(pTHXo_ int idx, SV *buf_sv, int maxlen);
 #define perl_free      Perl_free
 #endif
 
+#if defined(USE_THREADS)
+#  define INIT_TLS_AND_INTERP \
+    STMT_START {                               \
+       if (!PL_curinterp) {                    \
+           PERL_SET_INTERP(my_perl);           \
+           INIT_THREADS;                       \
+           ALLOC_THREAD_KEY;                   \
+       }                                       \
+    } STMT_END
+#else
+#  if defined(USE_ITHREADS)
+#  define INIT_TLS_AND_INTERP \
+    STMT_START {                               \
+       if (!PL_curinterp) {                    \
+           PERL_SET_INTERP(my_perl);           \
+           INIT_THREADS;                       \
+           ALLOC_THREAD_KEY;                   \
+           PERL_SET_THX(my_perl);              \
+           OP_REFCNT_INIT;                     \
+       }                                       \
+       else {                                  \
+           PERL_SET_THX(my_perl);              \
+       }                                       \
+    } STMT_END
+#  else
+#  define INIT_TLS_AND_INTERP \
+    STMT_START {                               \
+       if (!PL_curinterp) {                    \
+           PERL_SET_INTERP(my_perl);           \
+       }                                       \
+       PERL_SET_THX(my_perl);                  \
+    } STMT_END
+#  endif
+#endif
+
 #ifdef PERL_IMPLICIT_SYS
 PerlInterpreter *
 perl_alloc_using(struct IPerlMem* ipM, struct IPerlMem* ipMS,
@@ -66,11 +94,11 @@ perl_alloc_using(struct IPerlMem* ipM, struct IPerlMem* ipMS,
 #ifdef PERL_OBJECT
     my_perl = (PerlInterpreter*)new(ipM) CPerlObj(ipM, ipMS, ipMP, ipE, ipStd,
                                                  ipLIO, ipD, ipS, ipP);
-    PERL_SET_INTERP(my_perl);
+    INIT_TLS_AND_INTERP;
 #else
     /* New() needs interpreter, so call malloc() instead */
     my_perl = (PerlInterpreter*)(*ipM->pMalloc)(ipM, sizeof(PerlInterpreter));
-    PERL_SET_INTERP(my_perl);
+    INIT_TLS_AND_INTERP;
     Zero(my_perl, 1, PerlInterpreter);
     PL_Mem = ipM;
     PL_MemShared = ipMS;
@@ -86,6 +114,15 @@ perl_alloc_using(struct IPerlMem* ipM, struct IPerlMem* ipMS,
     return my_perl;
 }
 #else
+
+/*
+=for apidoc perl_alloc
+
+Allocates a new Perl interpreter.  See L<perlembed>.
+
+=cut
+*/
+
 PerlInterpreter *
 perl_alloc(void)
 {
@@ -93,12 +130,21 @@ perl_alloc(void)
 
     /* New() needs interpreter, so call malloc() instead */
     my_perl = (PerlInterpreter*)PerlMem_malloc(sizeof(PerlInterpreter));
-    PERL_SET_INTERP(my_perl);
+
+    INIT_TLS_AND_INTERP;
     Zero(my_perl, 1, PerlInterpreter);
     return my_perl;
 }
 #endif /* PERL_IMPLICIT_SYS */
 
+/*
+=for apidoc perl_construct
+
+Initializes a new Perl interpreter.  See L<perlembed>.
+
+=cut
+*/
+
 void
 perl_construct(pTHXx)
 {
@@ -108,7 +154,7 @@ perl_construct(pTHXx)
     struct perl_thread *thr = NULL;
 #endif /* FAKE_THREADS */
 #endif /* USE_THREADS */
-    
+
 #ifdef MULTIPLICITY
     init_interp();
     PL_perl_destruct_level = 1; 
@@ -120,14 +166,6 @@ perl_construct(pTHXx)
    /* Init the real globals (and main thread)? */
     if (!PL_linestr) {
 #ifdef USE_THREADS
-
-       INIT_THREADS;
-#ifdef ALLOC_THREAD_KEY
-        ALLOC_THREAD_KEY;
-#else
-       if (pthread_key_create(&PL_thr_key, 0))
-           Perl_croak(aTHX_ "panic: pthread_key_create");
-#endif
        MUTEX_INIT(&PL_sv_mutex);
        /*
         * Safe to use basic SV functions from now on (though
@@ -137,16 +175,20 @@ perl_construct(pTHXx)
        COND_INIT(&PL_eval_cond);
        MUTEX_INIT(&PL_threads_mutex);
        COND_INIT(&PL_nthreads_cond);
-#ifdef EMULATE_ATOMIC_REFCOUNTS
+#  ifdef EMULATE_ATOMIC_REFCOUNTS
        MUTEX_INIT(&PL_svref_mutex);
-#endif /* EMULATE_ATOMIC_REFCOUNTS */
+#  endif /* EMULATE_ATOMIC_REFCOUNTS */
        
        MUTEX_INIT(&PL_cred_mutex);
+       MUTEX_INIT(&PL_sv_lock_mutex);
+       MUTEX_INIT(&PL_fdpid_mutex);
 
        thr = init_main_thread();
 #endif /* USE_THREADS */
 
+#ifdef PERL_FLEXIBLE_EXCEPTIONS
        PL_protect = MEMBER_TO_FPTR(Perl_default_protect); /* for exceptions */
+#endif
 
        PL_curcop = &PL_compiling;      /* needed by ckWARN, right away */
 
@@ -204,27 +246,55 @@ 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);
+       s = uv_to_utf8(s, (UV)PERL_REVISION);
+       s = uv_to_utf8(s, (UV)PERL_VERSION);
+       s = uv_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)
 #if defined(PERL_SUBVERSION) && PERL_SUBVERSION > 0
-    sprintf(PL_patchlevel, "%7.5f",   (double) PERL_REVISION
-                               + ((double) PERL_VERSION / (double) 1000)
-                               + ((double) PERL_SUBVERSION / (double) 100000));
-#else
-    sprintf(PL_patchlevel, "%5.3f", (double) PERL_REVISION +
-                               ((double) PERL_VERSION / (double) 1000));
+                               + ((NV)PERL_SUBVERSION / (NV)1000000)
 #endif
+                               ;
+       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
 
+#ifdef HAVE_INTERP_INTERN
+    sys_intern_init();
+#endif
+
     PerlIO_init();                     /* Hook to IO system */
 
     PL_fdpid = newAV();                        /* for remembering popen pids by fd */
     PL_modglobal = newHV();            /* pointers to per-interpreter module globals */
+    PL_errors = newSVpvn("",0);
 
     ENTER;
 }
 
+/*
+=for apidoc perl_destruct
+
+Shuts down a Perl interpreter.  See L<perlembed>.
+
+=cut
+*/
+
 void
 perl_destruct(pTHXx)
 {
@@ -314,7 +384,7 @@ perl_destruct(pTHXx)
 #ifdef DEBUGGING
     {
        char *s;
-       if (s = PerlEnv_getenv("PERL_DESTRUCT_LEVEL")) {
+       if ((s = PerlEnv_getenv("PERL_DESTRUCT_LEVEL"))) {
            int i = atoi(s);
            if (destruct_level < i)
                destruct_level = i;
@@ -394,6 +464,7 @@ perl_destruct(pTHXx)
 
     Safefree(PL_inplace);
     PL_inplace = Nullch;
+    SvREFCNT_dec(PL_patchlevel);
 
     if (PL_e_script) {
        SvREFCNT_dec(PL_e_script);
@@ -402,10 +473,10 @@ perl_destruct(pTHXx)
 
     /* magical thingies */
 
-    Safefree(PL_ofs);  /* $, */
+    Safefree(PL_ofs);          /* $, */
     PL_ofs = Nullch;
 
-    Safefree(PL_ors);  /* $\ */
+    Safefree(PL_ors);          /* $\ */
     PL_ors = Nullch;
 
     SvREFCNT_dec(PL_rs);       /* $/ */
@@ -414,7 +485,9 @@ perl_destruct(pTHXx)
     SvREFCNT_dec(PL_nrs);      /* $/ helper */
     PL_nrs = Nullsv;
 
-    PL_multiline = 0;  /* $* */
+    PL_multiline = 0;          /* $* */
+    Safefree(PL_osname);       /* $^O */
+    PL_osname = Nullch;
 
     SvREFCNT_dec(PL_statname);
     PL_statname = Nullsv;
@@ -438,11 +511,11 @@ perl_destruct(pTHXx)
     /* startup and shutdown function lists */
     SvREFCNT_dec(PL_beginav);
     SvREFCNT_dec(PL_endav);
-    SvREFCNT_dec(PL_stopav);
+    SvREFCNT_dec(PL_checkav);
     SvREFCNT_dec(PL_initav);
     PL_beginav = Nullav;
     PL_endav = Nullav;
-    PL_stopav = Nullav;
+    PL_checkav = Nullav;
     PL_initav = Nullav;
 
     /* shortcuts just get cleared */
@@ -464,8 +537,6 @@ perl_destruct(pTHXx)
     SvREFCNT_dec(PL_argvout_stack);
     PL_argvout_stack = Nullav;
 
-    SvREFCNT_dec(PL_fdpid);
-    PL_fdpid = Nullav;
     SvREFCNT_dec(PL_modglobal);
     PL_modglobal = Nullhv;
     SvREFCNT_dec(PL_preambleav);
@@ -482,6 +553,17 @@ perl_destruct(pTHXx)
     PL_bodytarget = Nullsv;
     PL_formtarget = Nullsv;
 
+    /* free locale stuff */
+#ifdef USE_LOCALE_COLLATE
+    Safefree(PL_collation_name);
+    PL_collation_name = Nullch;
+#endif
+
+#ifdef USE_LOCALE_NUMERIC
+    Safefree(PL_numeric_name);
+    PL_numeric_name = Nullch;
+#endif
+
     /* clear utf8 character classes */
     SvREFCNT_dec(PL_utf8_alnum);
     SvREFCNT_dec(PL_utf8_alnumc);
@@ -520,6 +602,15 @@ perl_destruct(pTHXx)
     if (!specialWARN(PL_compiling.cop_warnings))
        SvREFCNT_dec(PL_compiling.cop_warnings);
     PL_compiling.cop_warnings = Nullsv;
+#ifdef USE_ITHREADS
+    Safefree(CopFILE(&PL_compiling));
+    CopFILE(&PL_compiling) = Nullch;
+    Safefree(CopSTASHPV(&PL_compiling));
+#else
+    SvREFCNT_dec(CopFILEGV(&PL_compiling));
+    CopFILEGV(&PL_compiling) = Nullgv;
+    /* cop_stash is not refcounted */
+#endif
 
     /* Prepare to destruct main symbol table.  */
 
@@ -553,14 +644,21 @@ perl_destruct(pTHXx)
 
     /* Now absolutely destruct everything, somehow or other, loops or no. */
     last_sv_count = 0;
+    SvFLAGS(PL_fdpid) |= SVTYPEMASK;           /* don't clean out pid table now */
     SvFLAGS(PL_strtab) |= SVTYPEMASK;          /* don't clean out strtab now */
     while (PL_sv_count != 0 && PL_sv_count != last_sv_count) {
        last_sv_count = PL_sv_count;
        sv_clean_all();
     }
+    SvFLAGS(PL_fdpid) &= ~SVTYPEMASK;
+    SvFLAGS(PL_fdpid) |= SVt_PVAV;
     SvFLAGS(PL_strtab) &= ~SVTYPEMASK;
     SvFLAGS(PL_strtab) |= SVt_PVHV;
-    
+
+    AvREAL_off(PL_fdpid);              /* no surviving entries */
+    SvREFCNT_dec(PL_fdpid);            /* needed in io_close() */
+    PL_fdpid = Nullav;
+
     /* Destruct the global string table. */
     {
        /* Yell and reset the HeVAL() slots that are still holding refcounts,
@@ -592,6 +690,21 @@ perl_destruct(pTHXx)
     }
     SvREFCNT_dec(PL_strtab);
 
+    /* free special SVs */
+
+    SvREFCNT(&PL_sv_yes) = 0;
+    sv_clear(&PL_sv_yes);
+    SvANY(&PL_sv_yes) = NULL;
+    SvFLAGS(&PL_sv_yes) = 0;
+
+    SvREFCNT(&PL_sv_no) = 0;
+    sv_clear(&PL_sv_no);
+    SvANY(&PL_sv_no) = NULL;
+    SvFLAGS(&PL_sv_no) = 0;
+
+    SvREFCNT(&PL_sv_undef) = 0;
+    SvREADONLY_off(&PL_sv_undef);
+
     if (PL_sv_count != 0 && ckWARN_d(WARN_INTERNAL))
        Perl_warner(aTHX_ WARN_INTERNAL,"Scalars leaked: %ld\n", (long)PL_sv_count);
 
@@ -599,7 +712,6 @@ perl_destruct(pTHXx)
 
     /* No SVs have survived, need to clean out */
     Safefree(PL_origfilename);
-    Safefree(PL_archpat_auto);
     Safefree(PL_reg_start_tmp);
     if (PL_reg_curpm)
        Safefree(PL_reg_curpm);
@@ -615,6 +727,7 @@ perl_destruct(pTHXx)
     MUTEX_DESTROY(&PL_sv_mutex);
     MUTEX_DESTROY(&PL_eval_mutex);
     MUTEX_DESTROY(&PL_cred_mutex);
+    MUTEX_DESTROY(&PL_fdpid_mutex);
     COND_DESTROY(&PL_eval_cond);
 #ifdef EMULATE_ATOMIC_REFCOUNTS
     MUTEX_DESTROY(&PL_svref_mutex);
@@ -626,7 +739,7 @@ perl_destruct(pTHXx)
     Safefree(PL_thrsv);
     PL_thrsv = Nullsv;
 #endif /* USE_THREADS */
-    
+
     /* As the absolutely last thing, free the non-arena SV for mess() */
 
     if (PL_mess_sv) {
@@ -642,7 +755,7 @@ perl_destruct(pTHXx)
            }
        }
        /* we know that type >= SVt_PV */
-       SvOOK_off(PL_mess_sv);
+       (void)SvOOK_off(PL_mess_sv);
        Safefree(SvPVX(PL_mess_sv));
        Safefree(SvANY(PL_mess_sv));
        Safefree(PL_mess_sv);
@@ -650,13 +763,27 @@ perl_destruct(pTHXx)
     }
 }
 
+/*
+=for apidoc perl_free
+
+Releases a Perl interpreter.  See L<perlembed>.
+
+=cut
+*/
+
 void
 perl_free(pTHXx)
 {
 #if defined(PERL_OBJECT)
     PerlMem_free(this);
 #else
+#  if defined(PERL_IMPLICIT_SYS) && defined(WIN32)
+    void *host = w32_internal_host;
+    PerlMem_free(aTHXx);
+    win32_delete_internal_host(host);
+#  else
     PerlMem_free(aTHXx);
+#  endif
 #endif
 }
 
@@ -669,6 +796,14 @@ Perl_call_atexit(pTHX_ ATEXIT_t fn, void *ptr)
     ++PL_exitlistlen;
 }
 
+/*
+=for apidoc perl_parse
+
+Tells a Perl interpreter to parse a Perl script.  See L<perlembed>.
+
+=cut
+*/
+
 int
 perl_parse(pTHXx_ XSINIT_t xsinit, int argc, char **argv, char **env)
 {
@@ -724,13 +859,20 @@ setuid perl scripts securely.\n");
     oldscope = PL_scopestack_ix;
     PL_dowarn = G_WARN_OFF;
 
-    CALLPROTECT(aTHX_ pcur_env, &ret, MEMBER_TO_FPTR(S_parse_body),
-               env, xsinit);
+#ifdef PERL_FLEXIBLE_EXCEPTIONS
+    CALLPROTECT(aTHX_ pcur_env, &ret, MEMBER_TO_FPTR(S_vparse_body), env, xsinit);
+#else
+    JMPENV_PUSH(ret);
+#endif
     switch (ret) {
     case 0:
-       if (PL_stopav)
-           call_list(oldscope, PL_stopav);
-       return 0;
+#ifndef PERL_FLEXIBLE_EXCEPTIONS
+       parse_body(env,xsinit);
+#endif
+       if (PL_checkav)
+           call_list(oldscope, PL_checkav);
+       ret = 0;
+       break;
     case 1:
        STATUS_ALL_FAILURE;
        /* FALL THROUGH */
@@ -740,23 +882,36 @@ setuid perl scripts securely.\n");
            LEAVE;
        FREETMPS;
        PL_curstash = PL_defstash;
-       if (PL_stopav)
-           call_list(oldscope, PL_stopav);
-       return STATUS_NATIVE_EXPORT;
+       if (PL_checkav)
+           call_list(oldscope, PL_checkav);
+       ret = STATUS_NATIVE_EXPORT;
+       break;
     case 3:
        PerlIO_printf(Perl_error_log, "panic: top_env\n");
-       return 1;
+       ret = 1;
+       break;
     }
-    return 0;
+    JMPENV_POP;
+    return ret;
+}
+
+#ifdef PERL_FLEXIBLE_EXCEPTIONS
+STATIC void *
+S_vparse_body(pTHX_ va_list args)
+{
+    char **env = va_arg(args, char**);
+    XSINIT_t xsinit = va_arg(args, XSINIT_t);
+
+    return parse_body(env, xsinit);
 }
+#endif
 
 STATIC void *
-S_parse_body(pTHX_ va_list args)
+S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
 {
     dTHR;
     int argc = PL_origargc;
     char **argv = PL_origargv;
-    char **env = va_arg(args, char**);
     char *scriptname = NULL;
     int fdscript = -1;
     VOL bool dosearch = FALSE;
@@ -766,8 +921,6 @@ S_parse_body(pTHX_ va_list args)
     register char *s;
     char *cddir = Nullch;
 
-    XSINIT_t xsinit = va_arg(args, XSINIT_t);
-
     sv_setpvn(PL_linestr,"",0);
     sv = newSVpvn("",0);               /* first used for -I flags */
     SAVEFREESV(sv);
@@ -785,6 +938,11 @@ S_parse_body(pTHX_ va_list args)
        s = argv[0]+1;
       reswitch:
        switch (*s) {
+       case 'C':
+#ifdef WIN32
+           win32_argv2utf8(argc-1, argv+1);
+           /* FALL THROUGH */
+#endif
 #ifndef PERL_STRICT_CR
        case '\r':
 #endif
@@ -809,7 +967,7 @@ S_parse_body(pTHX_ va_list args)
        case 'W':
        case 'X':
        case 'w':
-           if (s = moreswitches(s))
+           if ((s = moreswitches(s)))
                goto reswitch;
            break;
 
@@ -819,6 +977,11 @@ S_parse_body(pTHX_ va_list args)
            goto reswitch;
 
        case 'e':
+#ifdef MACOS_TRADITIONAL
+           /* ignore -e for Dev:Pseudo argument */
+           if (argv[1] && !strcmp(argv[1], "Dev:Pseudo"))
+               break; 
+#endif
            if (PL_euid != PL_uid || PL_egid != PL_gid)
                Perl_croak(aTHX_ "No -e allowed in setuid scripts");
            if (!PL_e_script) {
@@ -841,18 +1004,18 @@ S_parse_body(pTHX_ va_list args)
            if (!*++s && (s=argv[1]) != Nullch) {
                argc--,argv++;
            }
-           while (s && isSPACE(*s))
-               ++s;
            if (s && *s) {
-               char *e, *p;
-               for (e = s; *e && !isSPACE(*e); e++) ;
-               p = savepvn(s, e-s);
-               incpush(p, TRUE);
-               sv_catpv(sv,"-I");
-               sv_catpv(sv,p);
-               sv_catpv(sv," ");
+               char *p;
+               STRLEN len = strlen(s);
+               p = savepvn(s, len);
+               incpush(p, TRUE, TRUE);
+               sv_catpvn(sv, "-I", 2);
+               sv_catpvn(sv, p, len);
+               sv_catpvn(sv, " ", 1);
                Safefree(p);
-           }   /* XXX else croak? */
+           }
+           else
+               Perl_croak(aTHX_ "No directory specified for -I");
            break;
        case 'P':
            forbid_setid("-P");
@@ -885,6 +1048,24 @@ S_parse_body(pTHX_ va_list args)
 #  ifdef USE_THREADS
                sv_catpv(PL_Sv," USE_THREADS");
 #  endif
+#  ifdef USE_ITHREADS
+               sv_catpv(PL_Sv," USE_ITHREADS");
+#  endif
+#  ifdef USE_64_BIT_INT
+               sv_catpv(PL_Sv," USE_64_BIT_INT");
+#  endif
+#  ifdef USE_64_BIT_ALL
+               sv_catpv(PL_Sv," USE_64_BIT_ALL");
+#  endif
+#  ifdef USE_LONG_DOUBLE
+               sv_catpv(PL_Sv," USE_LONG_DOUBLE");
+#  endif
+#  ifdef USE_LARGE_FILES
+               sv_catpv(PL_Sv," USE_LARGE_FILES");
+#  endif
+#  ifdef USE_SOCKS
+               sv_catpv(PL_Sv," USE_SOCKS");
+#  endif
 #  ifdef PERL_OBJECT
                sv_catpv(PL_Sv," PERL_OBJECT");
 #  endif
@@ -963,7 +1144,8 @@ print \"  \\@INC:\\n    @INC\\n\";");
 #ifndef SECURE_INTERNAL_GETENV
         !PL_tainting &&
 #endif
-                        (s = PerlEnv_getenv("PERL5OPT"))) {
+       (s = PerlEnv_getenv("PERL5OPT")))
+    {
        while (isSPACE(*s))
            s++;
        if (*s == '-' && *(s+1) == 'T')
@@ -1006,6 +1188,7 @@ print \"  \\@INC:\\n    @INC\\n\";");
 
     validate_suid(validarg, scriptname,fdscript);
 
+#ifndef PERL_MICRO
 #if defined(SIGCHLD) || defined(SIGCLD)
     {
 #ifndef SIGCHLD
@@ -1020,8 +1203,13 @@ print \"  \\@INC:\\n    @INC\\n\";");
        }
     }
 #endif
+#endif
 
+#ifdef MACOS_TRADITIONAL
+    if (PL_doextract || gMacPerl_AlwaysExtract) {
+#else
     if (PL_doextract) {
+#endif
        find_beginning();
        if (cddir && PerlDir_chdir(cddir) < 0)
            Perl_croak(aTHX_ "Can't chdir to %s",cddir);
@@ -1055,13 +1243,17 @@ print \"  \\@INC:\\n    @INC\\n\";");
     CvPADLIST(PL_compcv) = comppadlist;
 
     boot_core_UNIVERSAL();
+#ifndef PERL_MICRO
     boot_core_xsutils();
+#endif
 
     if (xsinit)
        (*xsinit)(aTHXo);       /* in case linked C routines want magical variables */
-#if defined(VMS) || defined(WIN32) || defined(DJGPP)
+#ifndef PERL_MICRO
+#if defined(VMS) || defined(WIN32) || defined(DJGPP) || defined(__CYGWIN__)
     init_os_extras();
 #endif
+#endif
 
 #ifdef USE_SOCKS
     SOCKSinit(argv[0]);
@@ -1080,6 +1272,16 @@ print \"  \\@INC:\\n    @INC\\n\";");
 
     SETERRNO(0,SS$_NORMAL);
     PL_error_count = 0;
+#ifdef MACOS_TRADITIONAL
+    if (gMacPerl_SyntaxError = (yyparse() || PL_error_count)) {
+       if (PL_minus_c)
+           Perl_croak(aTHX_ "%s had compilation errors.\n", MacPerl_MPWFileName(PL_origfilename));
+       else {
+           Perl_croak(aTHX_ "Execution of %s aborted due to compilation errors.\n",
+                      MacPerl_MPWFileName(PL_origfilename));
+       }
+    }
+#else
     if (yyparse() || PL_error_count) {
        if (PL_minus_c)
            Perl_croak(aTHX_ "%s had compilation errors.\n", PL_origfilename);
@@ -1088,6 +1290,7 @@ print \"  \\@INC:\\n    @INC\\n\";");
                       PL_origfilename);
        }
     }
+#endif
     CopLINE_set(PL_curcop, 0);
     PL_curstash = PL_defstash;
     PL_preprocess = FALSE;
@@ -1122,12 +1325,20 @@ print \"  \\@INC:\\n    @INC\\n\";");
     return NULL;
 }
 
+/*
+=for apidoc perl_run
+
+Tells a Perl interpreter to run.  See L<perlembed>.
+
+=cut
+*/
+
 int
 perl_run(pTHXx)
 {
     dTHR;
     I32 oldscope;
-    int ret;
+    int ret = 0;
     dJMPENV;
 #ifdef USE_THREADS
     dTHX;
@@ -1135,14 +1346,23 @@ perl_run(pTHXx)
 
     oldscope = PL_scopestack_ix;
 
+#ifdef PERL_FLEXIBLE_EXCEPTIONS
  redo_body:
-    CALLPROTECT(aTHX_ pcur_env, &ret, MEMBER_TO_FPTR(S_run_body), oldscope);
+    CALLPROTECT(aTHX_ pcur_env, &ret, MEMBER_TO_FPTR(S_vrun_body), oldscope);
+#else
+    JMPENV_PUSH(ret);
+#endif
     switch (ret) {
     case 1:
        cxstack_ix = -1;                /* start context stack again */
        goto redo_body;
-    case 0:  /* normal completion */
-    case 2:  /* my_exit() */
+    case 0:                            /* normal completion */
+#ifndef PERL_FLEXIBLE_EXCEPTIONS
+ redo_body:
+       run_body(oldscope);
+#endif
+       /* FALL THROUGH */
+    case 2:                            /* my_exit() */
        while (PL_scopestack_ix > oldscope)
            LEAVE;
        FREETMPS;
@@ -1153,7 +1373,8 @@ perl_run(pTHXx)
        if (PerlEnv_getenv("PERL_DEBUG_MSTATS"))
            dump_mstats("after execution:  ");
 #endif
-       return STATUS_NATIVE_EXPORT;
+       ret = STATUS_NATIVE_EXPORT;
+       break;
     case 3:
        if (PL_restartop) {
            POPSTACK_TO(PL_mainstack);
@@ -1161,19 +1382,30 @@ perl_run(pTHXx)
        }
        PerlIO_printf(Perl_error_log, "panic: restartop\n");
        FREETMPS;
-       return 1;
+       ret = 1;
+       break;
     }
 
-    /* NOTREACHED */
-    return 0;
+    JMPENV_POP;
+    return ret;
 }
 
+#ifdef PERL_FLEXIBLE_EXCEPTIONS
 STATIC void *
-S_run_body(pTHX_ va_list args)
+S_vrun_body(pTHX_ va_list args)
 {
-    dTHR;
     I32 oldscope = va_arg(args, I32);
 
+    return run_body(oldscope);
+}
+#endif
+
+
+STATIC void *
+S_run_body(pTHX_ I32 oldscope)
+{
+    dTHR;
+
     DEBUG_r(PerlIO_printf(Perl_debug_log, "%s $` $& $' support.\n",
                     PL_sawampersand ? "Enabling" : "Omitting"));
 
@@ -1184,7 +1416,11 @@ S_run_body(pTHX_ va_list args)
                              PTR2UV(thr)));
 
        if (PL_minus_c) {
+#ifdef MACOS_TRADITIONAL
+           PerlIO_printf(Perl_error_log, "%s syntax OK\n", MacPerl_MPWFileName(PL_origfilename));
+#else
            PerlIO_printf(Perl_error_log, "%s syntax OK\n", PL_origfilename);
+#endif
            my_exit(0);
        }
        if (PERLDB_SINGLE && PL_DBsingle)
@@ -1211,6 +1447,16 @@ S_run_body(pTHX_ va_list args)
     return NULL;
 }
 
+/*
+=for apidoc p||get_sv
+
+Returns the SV of the specified Perl scalar.  If C<create> is set and the
+Perl variable does not exist then it will be created.  If C<create> is not
+set and the variable does not exist then NULL is returned.
+
+=cut
+*/
+
 SV*
 Perl_get_sv(pTHX_ const char *name, I32 create)
 {
@@ -1230,6 +1476,16 @@ Perl_get_sv(pTHX_ const char *name, I32 create)
     return Nullsv;
 }
 
+/*
+=for apidoc p||get_av
+
+Returns the AV of the specified Perl array.  If C<create> is set and the
+Perl variable does not exist then it will be created.  If C<create> is not
+set and the variable does not exist then NULL is returned.
+
+=cut
+*/
+
 AV*
 Perl_get_av(pTHX_ const char *name, I32 create)
 {
@@ -1241,6 +1497,16 @@ Perl_get_av(pTHX_ const char *name, I32 create)
     return Nullav;
 }
 
+/*
+=for apidoc p||get_hv
+
+Returns the HV of the specified Perl hash.  If C<create> is set and the
+Perl variable does not exist then it will be created.  If C<create> is not
+set and the variable does not exist then NULL is returned.
+
+=cut
+*/
+
 HV*
 Perl_get_hv(pTHX_ const char *name, I32 create)
 {
@@ -1252,6 +1518,17 @@ Perl_get_hv(pTHX_ const char *name, I32 create)
     return Nullhv;
 }
 
+/*
+=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.
+
+=cut
+*/
+
 CV*
 Perl_get_cv(pTHX_ const char *name, I32 create)
 {
@@ -1272,6 +1549,14 @@ Perl_get_cv(pTHX_ const char *name, I32 create)
 
 /* Be sure to refetch the stack pointer after calling these routines. */
 
+/*
+=for apidoc p||call_argv
+
+Performs a callback to the specified Perl sub.  See L<perlcall>.
+
+=cut
+*/
+
 I32
 Perl_call_argv(pTHX_ const char *sub_name, I32 flags, register char **argv)
               
@@ -1291,6 +1576,14 @@ Perl_call_argv(pTHX_ const char *sub_name, I32 flags, register char **argv)
     return call_pv(sub_name, flags);
 }
 
+/*
+=for apidoc p||call_pv
+
+Performs a callback to the specified Perl sub.  See L<perlcall>.
+
+=cut
+*/
+
 I32
 Perl_call_pv(pTHX_ const char *sub_name, I32 flags)
                        /* name of the subroutine */
@@ -1299,31 +1592,40 @@ Perl_call_pv(pTHX_ const char *sub_name, I32 flags)
     return call_sv((SV*)get_cv(sub_name, TRUE), flags);
 }
 
+/*
+=for apidoc p||call_method
+
+Performs a callback to the specified Perl method.  The blessed object must
+be on the stack.  See L<perlcall>.
+
+=cut
+*/
+
 I32
 Perl_call_method(pTHX_ const char *methname, I32 flags)
                                /* name of the subroutine */
                        /* See G_* flags in cop.h */
 {
-    dSP;
-    OP myop;
-    if (!PL_op)
-       PL_op = &myop;
-    XPUSHs(sv_2mortal(newSVpv(methname,0)));
-    PUTBACK;
-    pp_method();
-       if(PL_op == &myop)
-               PL_op = Nullop;
-    return call_sv(*PL_stack_sp--, flags);
+    return call_sv(sv_2mortal(newSVpv(methname,0)), flags | G_METHOD);
 }
 
 /* May be called with any of a CV, a GV, or an SV containing the name. */
+/*
+=for apidoc p||call_sv
+
+Performs a callback to the Perl sub whose name is in the SV.  See
+L<perlcall>.
+
+=cut
+*/
+
 I32
 Perl_call_sv(pTHX_ SV *sv, I32 flags)
-       
                        /* See G_* flags in cop.h */
 {
     dSP;
     LOGOP myop;                /* fake syntax tree node */
+    UNOP method_op;
     I32 oldmark;
     I32 retval;
     I32 oldscope;
@@ -1361,14 +1663,22 @@ Perl_call_sv(pTHX_ SV *sv, I32 flags)
          && !(flags & G_NODEBUG))
        PL_op->op_private |= OPpENTERSUB_DB;
 
+    if (flags & G_METHOD) {
+       Zero(&method_op, 1, UNOP);
+       method_op.op_next = PL_op;
+       method_op.op_ppaddr = PL_ppaddr[OP_METHOD];
+       myop.op_ppaddr = PL_ppaddr[OP_ENTERSUB];
+       PL_op = (OP*)&method_op;
+    }
+
     if (!(flags & G_EVAL)) {
        CATCH_SET(TRUE);
-       call_xbody((OP*)&myop, FALSE);
+       call_body((OP*)&myop, FALSE);
        retval = PL_stack_sp - (PL_stack_base + oldmark);
        CATCH_SET(oldcatch);
     }
     else {
-       cLOGOP->op_other = PL_op;
+       myop.op_other = (OP*)&myop;
        PL_markstack_ptr--;
        /* we're trying to emulate pp_entertry() here */
        {
@@ -1378,8 +1688,8 @@ Perl_call_sv(pTHX_ SV *sv, I32 flags)
            ENTER;
            SAVETMPS;
            
-           push_return(PL_op->op_next);
-           PUSHBLOCK(cx, CXt_EVAL, PL_stack_sp);
+           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. */
            
@@ -1391,11 +1701,19 @@ Perl_call_sv(pTHX_ SV *sv, I32 flags)
        }
        PL_markstack_ptr++;
 
-  redo_body:
-       CALLPROTECT(aTHX_ pcur_env, &ret, MEMBER_TO_FPTR(S_call_body),
+#ifdef PERL_FLEXIBLE_EXCEPTIONS
+ redo_body:
+       CALLPROTECT(aTHX_ pcur_env, &ret, MEMBER_TO_FPTR(S_vcall_body),
                    (OP*)&myop, FALSE);
+#else
+       JMPENV_PUSH(ret);
+#endif
        switch (ret) {
        case 0:
+#ifndef PERL_FLEXIBLE_EXCEPTIONS
+ redo_body:
+           call_body((OP*)&myop, FALSE);
+#endif
            retval = PL_stack_sp - (PL_stack_base + oldmark);
            if (!(flags & G_KEEPERR))
                sv_setpv(ERRSV,"");
@@ -1407,6 +1725,7 @@ Perl_call_sv(pTHX_ SV *sv, I32 flags)
            /* my_exit() was called */
            PL_curstash = PL_defstash;
            FREETMPS;
+           JMPENV_POP;
            if (PL_statusvalue && !(PL_exit_flags & PERL_EXIT_EXPECTED))
                Perl_croak(aTHX_ "Callback called exit");
            my_exit_jump();
@@ -1440,6 +1759,7 @@ Perl_call_sv(pTHX_ SV *sv, I32 flags)
            PL_curpm = newpm;
            LEAVE;
        }
+       JMPENV_POP;
     }
 
     if (flags & G_DISCARD) {
@@ -1452,26 +1772,28 @@ Perl_call_sv(pTHX_ SV *sv, I32 flags)
     return retval;
 }
 
+#ifdef PERL_FLEXIBLE_EXCEPTIONS
 STATIC void *
-S_call_body(pTHX_ va_list args)
+S_vcall_body(pTHX_ va_list args)
 {
     OP *myop = va_arg(args, OP*);
     int is_eval = va_arg(args, int);
 
-    call_xbody(myop, is_eval);
+    call_body(myop, is_eval);
     return NULL;
 }
+#endif
 
 STATIC void
-S_call_xbody(pTHX_ OP *myop, int is_eval)
+S_call_body(pTHX_ OP *myop, int is_eval)
 {
     dTHR;
 
     if (PL_op == myop) {
        if (is_eval)
-           PL_op = Perl_pp_entereval(aTHX);
+           PL_op = Perl_pp_entereval(aTHX);    /* this doesn't do a POPMARK */
        else
-           PL_op = Perl_pp_entersub(aTHX);
+           PL_op = Perl_pp_entersub(aTHX);     /* this does */
     }
     if (PL_op)
        CALLRUNOPS(aTHX);
@@ -1479,6 +1801,14 @@ S_call_xbody(pTHX_ OP *myop, int is_eval)
 
 /* Eval a string. The G_EVAL flag is always assumed. */
 
+/*
+=for apidoc p||eval_sv
+
+Tells Perl to C<eval> the string in the SV.
+
+=cut
+*/
+
 I32
 Perl_eval_sv(pTHX_ SV *sv, I32 flags)
        
@@ -1515,11 +1845,19 @@ Perl_eval_sv(pTHX_ SV *sv, I32 flags)
     if (flags & G_KEEPERR)
        myop.op_flags |= OPf_SPECIAL;
 
+#ifdef PERL_FLEXIBLE_EXCEPTIONS
  redo_body:
-    CALLPROTECT(aTHX_ pcur_env, &ret, MEMBER_TO_FPTR(S_call_body),
+    CALLPROTECT(aTHX_ pcur_env, &ret, MEMBER_TO_FPTR(S_vcall_body),
                (OP*)&myop, TRUE);
+#else
+    JMPENV_PUSH(ret);
+#endif
     switch (ret) {
     case 0:
+#ifndef PERL_FLEXIBLE_EXCEPTIONS
+ redo_body:
+       call_body((OP*)&myop,TRUE);
+#endif
        retval = PL_stack_sp - (PL_stack_base + oldmark);
        if (!(flags & G_KEEPERR))
            sv_setpv(ERRSV,"");
@@ -1531,6 +1869,7 @@ Perl_eval_sv(pTHX_ SV *sv, I32 flags)
        /* my_exit() was called */
        PL_curstash = PL_defstash;
        FREETMPS;
+       JMPENV_POP;
        if (PL_statusvalue && !(PL_exit_flags & PERL_EXIT_EXPECTED))
            Perl_croak(aTHX_ "Callback called exit");
        my_exit_jump();
@@ -1551,6 +1890,7 @@ Perl_eval_sv(pTHX_ SV *sv, I32 flags)
        break;
     }
 
+    JMPENV_POP;
     if (flags & G_DISCARD) {
        PL_stack_sp = PL_stack_base + oldmark;
        retval = 0;
@@ -1561,13 +1901,20 @@ Perl_eval_sv(pTHX_ SV *sv, I32 flags)
     return retval;
 }
 
+/*
+=for apidoc p||eval_pv
+
+Tells Perl to C<eval> the given string and return an SV* result.
+
+=cut
+*/
+
 SV*
 Perl_eval_pv(pTHX_ const char *p, I32 croak_on_error)
 {
     dSP;
     SV* sv = newSVpv(p, 0);
 
-    PUSHMARK(SP);
     eval_sv(sv, G_SCALAR);
     SvREFCNT_dec(sv);
 
@@ -1585,6 +1932,14 @@ Perl_eval_pv(pTHX_ const char *p, I32 croak_on_error)
 
 /* Require a module. */
 
+/*
+=for apidoc p||require_pv
+
+Tells Perl to C<require> a module.
+
+=cut
+*/
+
 void
 Perl_require_pv(pTHX_ const char *pv)
 {
@@ -1606,7 +1961,7 @@ Perl_magicname(pTHX_ char *sym, char *name, I32 namlen)
 {
     register GV *gv;
 
-    if (gv = gv_fetchpv(sym,TRUE, SVt_PV))
+    if ((gv = gv_fetchpv(sym,TRUE, SVt_PV)))
        sv_magic(GvSV(gv), (SV*)gv, 0, name, namlen);
 }
 
@@ -1619,7 +1974,8 @@ S_usage(pTHX_ char *name)         /* XXX move this out into a module ? */
     static char *usage_msg[] = {
 "-0[octal]       specify record separator (\\0, if no argument)",
 "-a              autosplit mode with -n or -p (splits $_ into @F)",
-"-c              check syntax only (runs BEGIN and END blocks)",
+"-C              enable native wide character system interfaces",
+"-c              check syntax only (runs BEGIN and CHECK blocks)",
 "-d[:debugger]   run program under debugger",
 "-D[number/list] set debugging flags (argument is a bit mask or alphabets)",
 "-e 'command'    one line of program (several -e's allowed, omit programfile)",
@@ -1639,15 +1995,19 @@ S_usage(pTHX_ char *name)               /* XXX move this out into a module ? */
 "-v              print version, subversion (includes VERY IMPORTANT perl info)",
 "-V[:variable]   print configuration summary (or a single Config.pm variable)",
 "-w              enable many useful warnings (RECOMMENDED)",
+"-W              enable all warnings",
+"-X              disable all warnings",
 "-x[directory]   strip off text before #!perl line and perhaps cd to directory",
 "\n",
 NULL
 };
     char **p = usage_msg;
 
-    printf("\nUsage: %s [switches] [--] [programfile] [arguments]", name);
+    PerlIO_printf(PerlIO_stdout(),
+                 "\nUsage: %s [switches] [--] [programfile] [arguments]",
+                 name);
     while (*p)
-       printf("\n  %s", *p++);
+       PerlIO_printf(PerlIO_stdout(), "\n  %s", *p++);
 }
 
 /* This routine handles any switches that can be given during run */
@@ -1662,6 +2022,7 @@ Perl_moreswitches(pTHX_ char *s)
     case '0':
     {
        dTHR;
+       numlen = 0;                     /* disallow underscores */
        rschar = (U32)scan_oct(s, 4, &numlen);
        SvREFCNT_dec(PL_nrs);
        if (rschar & ~((U8)~0))
@@ -1674,6 +2035,10 @@ Perl_moreswitches(pTHX_ char *s)
        }
        return s + numlen;
     }
+    case 'C':
+       PL_widesyscalls = TRUE;
+       s++;
+       return s;
     case 'F':
        PL_minus_F = TRUE;
        PL_splitstr = savepv(s + 1);
@@ -1747,14 +2112,23 @@ Perl_moreswitches(pTHX_ char *s)
            ++s;
        if (*s) {
            char *e, *p;
-           for (e = s; *e && !isSPACE(*e); e++) ;
-           p = savepvn(s, e-s);
-           incpush(p, TRUE);
-           Safefree(p);
-           s = e;
+           p = s;
+           /* ignore trailing spaces (possibly followed by other switches) */
+           do {
+               for (e = p; *e && !isSPACE(*e); e++) ;
+               p = e;
+               while (isSPACE(*p))
+                   p++;
+           } while (*p && *p != '-');
+           e = savepvn(s, e-s);
+           incpush(e, TRUE, TRUE);
+           Safefree(e);
+           s = p;
+           if (*s == '-')
+               s++;
        }
        else
-           Perl_croak(aTHX_ "No space allowed after -I");
+           Perl_croak(aTHX_ "No directory specified for -I");
        return s;
     case 'l':
        PL_minus_l = TRUE;
@@ -1764,6 +2138,7 @@ Perl_moreswitches(pTHX_ char *s)
        if (isDIGIT(*s)) {
            PL_ors = savepv("\n");
            PL_orslen = 1;
+           numlen = 0;                 /* disallow underscores */
            *PL_ors = (char)scan_oct(s, 3 + (*s == '0'), &numlen);
            s += numlen;
        }
@@ -1801,6 +2176,9 @@ Perl_moreswitches(pTHX_ char *s)
                    sv_catpv( sv, " ()");
                }
            } else {
+                if (s == start)
+                    Perl_croak(aTHX_ "Module name required with -%c option",
+                              s[-1]);
                sv_catpvn(sv, start, s-start);
                sv_catpv(sv, " split(/,/,q{");
                sv_catpv(sv, ++s);
@@ -1833,6 +2211,9 @@ Perl_moreswitches(pTHX_ char *s)
        s++;
        return s;
     case 'u':
+#ifdef MACOS_TRADITIONAL
+       Perl_croak(aTHX_ "Believe me, you don't want to use \"-u\" on a Macintosh");
+#endif
        PL_do_undump = TRUE;
        s++;
        return s;
@@ -1841,59 +2222,75 @@ Perl_moreswitches(pTHX_ char *s)
        s++;
        return s;
     case 'v':
-#if defined(PERL_SUBVERSION) && PERL_SUBVERSION > 0
-       printf("\nThis is perl, version %d.%03d_%02d built for %s",
-           PERL_REVISION, PERL_VERSION, PERL_SUBVERSION, ARCHNAME);
-#else
-       printf("\nThis is perl, version %s built for %s",
-               PL_patchlevel, ARCHNAME);
-#endif
+       PerlIO_printf(PerlIO_stdout(),
+                     Perl_form(aTHX_ "\nThis is perl, v%vd built for %s",
+                               PL_patchlevel, ARCHNAME));
 #if defined(LOCAL_PATCH_COUNT)
        if (LOCAL_PATCH_COUNT > 0)
-           printf("\n(with %d registered patch%s, see perl -V for more detail)",
-               (int)LOCAL_PATCH_COUNT, (LOCAL_PATCH_COUNT!=1) ? "es" : "");
+           PerlIO_printf(PerlIO_stdout(),
+                         "\n(with %d registered patch%s, "
+                         "see perl -V for more detail)",
+                         (int)LOCAL_PATCH_COUNT,
+                         (LOCAL_PATCH_COUNT!=1) ? "es" : "");
 #endif
 
-       printf("\n\nCopyright 1987-1999, Larry Wall\n");
+       PerlIO_printf(PerlIO_stdout(),
+                     "\n\nCopyright 1987-2000, Larry Wall\n");
 #ifdef MSDOS
-       printf("\nMS-DOS port Copyright (c) 1989, 1990, Diomidis Spinellis\n");
+       PerlIO_printf(PerlIO_stdout(),
+                     "\nMS-DOS port Copyright (c) 1989, 1990, Diomidis Spinellis\n");
 #endif
 #ifdef DJGPP
-       printf("djgpp v2 port (jpl5003c) by Hirofumi Watanabe, 1996\n");
-       printf("djgpp v2 port (perl5004+) by Laszlo Molnar, 1997-1999\n");
+       PerlIO_printf(PerlIO_stdout(),
+                     "djgpp v2 port (jpl5003c) by Hirofumi Watanabe, 1996\n"
+                     "djgpp v2 port (perl5004+) by Laszlo Molnar, 1997-1999\n");
 #endif
 #ifdef OS2
-       printf("\n\nOS/2 port Copyright (c) 1990, 1991, Raymond Chen, Kai Uwe Rommel\n"
-           "Version 5 port Copyright (c) 1994-1999, Andreas Kaiser, Ilya Zakharevich\n");
+       PerlIO_printf(PerlIO_stdout(),
+                     "\n\nOS/2 port Copyright (c) 1990, 1991, Raymond Chen, Kai Uwe Rommel\n"
+                     "Version 5 port Copyright (c) 1994-1999, Andreas Kaiser, Ilya Zakharevich\n");
 #endif
 #ifdef atarist
-       printf("atariST series port, ++jrb  bammi@cadence.com\n");
+       PerlIO_printf(PerlIO_stdout(),
+                     "atariST series port, ++jrb  bammi@cadence.com\n");
 #endif
 #ifdef __BEOS__
-       printf("BeOS port Copyright Tom Spindler, 1997-1999\n");
+       PerlIO_printf(PerlIO_stdout(),
+                     "BeOS port Copyright Tom Spindler, 1997-1999\n");
 #endif
 #ifdef MPE
-       printf("MPE/iX port Copyright by Mark Klein and Mark Bixby, 1996-1999\n");
+       PerlIO_printf(PerlIO_stdout(),
+                     "MPE/iX port Copyright by Mark Klein and Mark Bixby, 1996-1999\n");
 #endif
 #ifdef OEMVS
-       printf("MVS (OS390) port by Mortice Kern Systems, 1997-1999\n");
+       PerlIO_printf(PerlIO_stdout(),
+                     "MVS (OS390) port by Mortice Kern Systems, 1997-1999\n");
 #endif
 #ifdef __VOS__
-       printf("Stratus VOS port by Paul_Green@stratus.com, 1997-1999\n");
+       PerlIO_printf(PerlIO_stdout(),
+                     "Stratus VOS port by Paul_Green@stratus.com, 1997-1999\n");
 #endif
 #ifdef __OPEN_VM
-       printf("VM/ESA port by Neale Ferguson, 1998-1999\n");
+       PerlIO_printf(PerlIO_stdout(),
+                     "VM/ESA port by Neale Ferguson, 1998-1999\n");
 #endif
 #ifdef POSIX_BC
-       printf("BS2000 (POSIX) port by Start Amadeus GmbH, 1998-1999\n");
+       PerlIO_printf(PerlIO_stdout(),
+                     "BS2000 (POSIX) port by Start Amadeus GmbH, 1998-1999\n");
 #endif
 #ifdef __MINT__
-       printf("MiNT port by Guido Flohr, 1997-1999\n");
+       PerlIO_printf(PerlIO_stdout(),
+                     "MiNT port by Guido Flohr, 1997-1999\n");
+#endif
+#ifdef EPOC
+       PerlIO_printf(PerlIO_stdout(),
+                     "EPOC port by Olaf Flebbe, 1999-2000\n");
 #endif
 #ifdef BINARY_BUILD_NOTICE
        BINARY_BUILD_NOTICE;
 #endif
-       printf("\n\
+       PerlIO_printf(PerlIO_stdout(),
+                     "\n\
 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.0 source kit.\n\n\
 Complete documentation for Perl, including FAQ lists, should be found on\n\
@@ -1907,12 +2304,12 @@ Internet, point your browser at http://www.perl.com/, the Perl Home Page.\n\n");
        return s;
     case 'W':
        PL_dowarn = G_WARN_ALL_ON|G_WARN_ON; 
-       PL_compiling.cop_warnings = WARN_ALL ;
+       PL_compiling.cop_warnings = pWARN_ALL ;
        s++;
        return s;
     case 'X':
        PL_dowarn = G_WARN_ALL_OFF; 
-       PL_compiling.cop_warnings = WARN_NONE ;
+       PL_compiling.cop_warnings = pWARN_NONE ;
        s++;
        return s;
     case '*':
@@ -2093,6 +2490,7 @@ S_init_main_stash(pTHX)
     CopSTASH_set(&PL_compiling, PL_defstash);
     PL_debstash = GvHV(gv_fetchpv("DB::", GV_ADDMULTI, SVt_PVHV));
     PL_globalstash = GvHV(gv_fetchpv("CORE::GLOBAL::", GV_ADDMULTI, SVt_PVHV));
+    PL_nullstash = GvHV(gv_fetchpv("<none>::", GV_ADDMULTI, SVt_PVHV));
     /* We must init $/ before switches are processed. */
     sv_setpvn(get_sv("/", TRUE), "\n", 1);
 }
@@ -2101,7 +2499,6 @@ STATIC void
 S_open_script(pTHX_ char *scriptname, bool dosearch, SV *sv, int *fdscript)
 {
     dTHR;
-    register char *s;
 
     *fdscript = -1;
 
@@ -2125,6 +2522,11 @@ S_open_script(pTHX_ char *scriptname, bool dosearch, SV *sv, int *fdscript)
        }
     }
 
+#ifdef USE_ITHREADS
+    Safefree(CopFILE(PL_curcop));
+#else
+    SvREFCNT_dec(CopFILEGV(PL_curcop));
+#endif
     CopFILE_set(PL_curcop, PL_origfilename);
     if (strEQ(PL_origfilename,"-"))
        scriptname = "";
@@ -2144,10 +2546,10 @@ S_open_script(pTHX_ char *scriptname, bool dosearch, SV *sv, int *fdscript)
            Perl_sv_catpvf(aTHX_ cpp, "%s/", BIN_EXP);
        sv_catpv(cpp, cpp_cfg);
 
-       sv_catpv(sv,"-I");
+       sv_catpvn(sv, "-I", 2);
        sv_catpv(sv,PRIVLIB_EXP);
 
-#ifdef MSDOS
+#if defined(MSDOS) || defined(WIN32)
        Perl_sv_setpvf(aTHX_ cmd, "\
 sed %s -e \"/^[^#]/b\" \
  -e \"/^#[     ]*include[      ]/b\" \
@@ -2160,7 +2562,7 @@ sed %s -e \"/^[^#]/b\" \
  -e \"/^#[     ]*undef[        ]/b\" \
  -e \"/^#[     ]*endif/b\" \
  -e \"s/^#.*//\" \
- %s | %_ -C %_ %s",
+ %s | %"SVf" -C %"SVf" %s",
          (PL_doextract ? "-e \"1,/^#/d\n\"" : ""),
 #else
 #  ifdef __OPEN_VM
@@ -2176,7 +2578,7 @@ sed %s -e \"/^[^#]/b\" \
  -e '/^#[      ]*undef[        ]/b' \
  -e '/^#[      ]*endif/b' \
  -e 's/^[      ]*#.*//' \
- %s | %_ %_ %s",
+ %s | %"SVf" %"SVf" %s",
 #  else
        Perl_sv_setpvf(aTHX_ cmd, "\
 %s %s -e '/^[^#]/b' \
@@ -2190,7 +2592,7 @@ sed %s -e \"/^[^#]/b\" \
  -e '/^#[      ]*undef[        ]/b' \
  -e '/^#[      ]*endif/b' \
  -e 's/^[      ]*#.*//' \
- %s | %_ -C %_ %s",
+ %s | %"SVf" -C %"SVf" %s",
 #  endif
 #ifdef LOC_SED
          LOC_SED,
@@ -2243,7 +2645,9 @@ sed %s -e \"/^[^#]/b\" \
            PL_statbuf.st_mode & (S_ISUID|S_ISGID))
        {
            /* try again */
-           PerlProc_execv(Perl_form(aTHX_ "%s/sperl%s", BIN_EXP, PL_patchlevel), PL_origargv);
+           PerlProc_execv(Perl_form(aTHX_ "%s/sperl"PERL_FS_VER_FMT, BIN_EXP,
+                                    (int)PERL_REVISION, (int)PERL_VERSION,
+                                    (int)PERL_SUBVERSION), PL_origargv);
            Perl_croak(aTHX_ "Can't do setuid\n");
        }
 #endif
@@ -2256,7 +2660,7 @@ sed %s -e \"/^[^#]/b\" \
 /* Mention
  * I_SYSSTATVFS        HAS_FSTATVFS
  * I_SYSMOUNT
- * I_STATFS    HAS_FSTATFS
+ * I_STATFS    HAS_FSTATFS     HAS_GETFSSTAT
  * I_MNTENT    HAS_GETMNTENT   HAS_HASMNTOPT
  * here so that metaconfig picks them up. */
 
@@ -2275,72 +2679,85 @@ S_fd_on_nosuid_fs(pTHX_ int fd)
  * an irrelevant filesystem while trying to reach the right one.
  */
 
-#   ifdef HAS_FSTATVFS
+#undef FD_ON_NOSUID_CHECK_OKAY  /* found the syscalls to do the check? */
+
+#   if !defined(FD_ON_NOSUID_CHECK_OKAY) && \
+        defined(HAS_FSTATVFS)
+#   define FD_ON_NOSUID_CHECK_OKAY
     struct statvfs stfs;
+
     check_okay = fstatvfs(fd, &stfs) == 0;
     on_nosuid  = check_okay && (stfs.f_flag  & ST_NOSUID);
-#   else
-#       ifdef PERL_MOUNT_NOSUID
-#           if defined(HAS_FSTATFS) && \
-              defined(HAS_STRUCT_STATFS) && \
-              defined(HAS_STRUCT_STATFS_F_FLAGS)
+#   endif /* fstatvfs */
+#   if !defined(FD_ON_NOSUID_CHECK_OKAY) && \
+        defined(PERL_MOUNT_NOSUID)     && \
+        defined(HAS_FSTATFS)           && \
+        defined(HAS_STRUCT_STATFS)     && \
+        defined(HAS_STRUCT_STATFS_F_FLAGS)
+#   define FD_ON_NOSUID_CHECK_OKAY
     struct statfs  stfs;
+
     check_okay = fstatfs(fd, &stfs)  == 0;
     on_nosuid  = check_okay && (stfs.f_flags & PERL_MOUNT_NOSUID);
-#           else
-#               if defined(HAS_FSTAT) && \
-                  defined(HAS_USTAT) && \
-                  defined(HAS_GETMNT) && \
-                  defined(HAS_STRUCT_FS_DATA) && \
-                  defined(NOSTAT_ONE)
+#   endif /* fstatfs */
+
+#   if !defined(FD_ON_NOSUID_CHECK_OKAY) && \
+        defined(PERL_MOUNT_NOSUID)     && \
+        defined(HAS_FSTAT)             && \
+        defined(HAS_USTAT)             && \
+        defined(HAS_GETMNT)            && \
+        defined(HAS_STRUCT_FS_DATA)    && \
+        defined(NOSTAT_ONE)
+#   define FD_ON_NOSUID_CHECK_OKAY
     struct stat fdst;
+
     if (fstat(fd, &fdst) == 0) {
-       struct ustat us;
-       if (ustat(fdst.st_dev, &us) == 0) {
-           struct fs_data fsd;
-           /* NOSTAT_ONE here because we're not examining fields which
-            * vary between that case and STAT_ONE. */
+        struct ustat us;
+        if (ustat(fdst.st_dev, &us) == 0) {
+            struct fs_data fsd;
+            /* NOSTAT_ONE here because we're not examining fields which
+             * vary between that case and STAT_ONE. */
             if (getmnt((int*)0, &fsd, (int)0, NOSTAT_ONE, us.f_fname) == 0) {
-               size_t cmplen = sizeof(us.f_fname);
-               if (sizeof(fsd.fd_req.path) < cmplen)
-                   cmplen = sizeof(fsd.fd_req.path);
-               if (strnEQ(fsd.fd_req.path, us.f_fname, cmplen) &&
-                   fdst.st_dev == fsd.fd_req.dev) {
-                       check_okay = 1;
-                       on_nosuid = fsd.fd_req.flags & PERL_MOUNT_NOSUID;
-                   }
-               }
-           }
-       }
-    }
-#               endif /* fstat+ustat+getmnt */
-#           endif /* fstatfs */
-#       else
-#           if defined(HAS_GETMNTENT) && \
-              defined(HAS_HASMNTOPT) && \
-              defined(MNTOPT_NOSUID)
-    FILE               *mtab = fopen("/etc/mtab", "r");
-    struct mntent      *entry;
-    struct stat                stb, fsb;
+                size_t cmplen = sizeof(us.f_fname);
+                if (sizeof(fsd.fd_req.path) < cmplen)
+                    cmplen = sizeof(fsd.fd_req.path);
+                if (strnEQ(fsd.fd_req.path, us.f_fname, cmplen) &&
+                    fdst.st_dev == fsd.fd_req.dev) {
+                        check_okay = 1;
+                        on_nosuid = fsd.fd_req.flags & PERL_MOUNT_NOSUID;
+                    }
+                }
+            }
+        }
+    }
+#   endif /* fstat+ustat+getmnt */
+
+#   if !defined(FD_ON_NOSUID_CHECK_OKAY) && \
+        defined(HAS_GETMNTENT)         && \
+        defined(HAS_HASMNTOPT)         && \
+        defined(MNTOPT_NOSUID)
+#   define FD_ON_NOSUID_CHECK_OKAY
+    FILE                *mtab = fopen("/etc/mtab", "r");
+    struct mntent       *entry;
+    struct stat         stb, fsb;
 
     if (mtab && (fstat(fd, &stb) == 0)) {
-       while (entry = getmntent(mtab)) {
-           if (stat(entry->mnt_dir, &fsb) == 0
-               && fsb.st_dev == stb.st_dev)
-           {
-               /* found the filesystem */
-               check_okay = 1;
-               if (hasmntopt(entry, MNTOPT_NOSUID))
-                   on_nosuid = 1;
-               break;
-           } /* A single fs may well fail its stat(). */
-       }
+        while (entry = getmntent(mtab)) {
+            if (stat(entry->mnt_dir, &fsb) == 0
+                && fsb.st_dev == stb.st_dev)
+            {
+                /* found the filesystem */
+                check_okay = 1;
+                if (hasmntopt(entry, MNTOPT_NOSUID))
+                    on_nosuid = 1;
+                break;
+            } /* A single fs may well fail its stat(). */
+        }
     }
     if (mtab)
-       fclose(mtab);
-#           endif /* getmntent+hasmntopt */
-#       endif /* PERL_MOUNT_NOSUID: fstatfs or fstat+ustat+statfs */
-#   endif /* statvfs */
+        fclose(mtab);
+#   endif /* getmntent+hasmntopt */
 
     if (!check_okay) 
        Perl_croak(aTHX_ "Can't check filesystem of script \"%s\" for nosuid", PL_origfilename);
@@ -2351,7 +2768,9 @@ S_fd_on_nosuid_fs(pTHX_ int fd)
 STATIC void
 S_validate_suid(pTHX_ char *validarg, char *scriptname, int fdscript)
 {
+#ifdef IAMSUID
     int which;
+#endif
 
     /* do we need to emulate setuid on scripts? */
 
@@ -2490,7 +2909,9 @@ FIX YOUR KERNEL, PUT A C WRAPPER AROUND THIS SCRIPT, OR USE -u AND UNDUMP!\n");
            (void)PerlIO_close(PL_rsfp);
 #ifndef IAMSUID
            /* try again */
-           PerlProc_execv(Perl_form(aTHX_ "%s/sperl%s", BIN_EXP, PL_patchlevel), PL_origargv);
+           PerlProc_execv(Perl_form(aTHX_ "%s/sperl"PERL_FS_VER_FMT, BIN_EXP,
+                                    (int)PERL_REVISION, (int)PERL_VERSION,
+                                    (int)PERL_SUBVERSION), PL_origargv);
 #endif
            Perl_croak(aTHX_ "Can't do setuid\n");
        }
@@ -2572,7 +2993,9 @@ FIX YOUR KERNEL, PUT A C WRAPPER AROUND THIS SCRIPT, OR USE -u AND UNDUMP!\n");
 #if defined(HAS_FCNTL) && defined(F_SETFD)
     fcntl(PerlIO_fileno(PL_rsfp),F_SETFD,0);   /* ensure no close-on-exec */
 #endif
-    PerlProc_execv(Perl_form(aTHX_ "%s/perl%s", BIN_EXP, PL_patchlevel), PL_origargv);/* try again */
+    PerlProc_execv(Perl_form(aTHX_ "%s/perl"PERL_FS_VER_FMT, BIN_EXP,
+                            (int)PERL_REVISION, (int)PERL_VERSION,
+                            (int)PERL_SUBVERSION), PL_origargv);/* try again */
     Perl_croak(aTHX_ "Can't do setuid\n");
 #endif /* IAMSUID */
 #else /* !DOSUID */
@@ -2601,9 +3024,30 @@ S_find_beginning(pTHX)
     /* skip forward in input to the real script? */
 
     forbid_setid("-x");
+#ifdef MACOS_TRADITIONAL
+    /* Since the Mac OS does not honor !# arguments for us, we do it ourselves */
+    
+    while (PL_doextract || gMacPerl_AlwaysExtract) {
+       if ((s = sv_gets(PL_linestr, PL_rsfp, 0)) == Nullch) {
+           if (!gMacPerl_AlwaysExtract)
+               Perl_croak(aTHX_ "No Perl script found in input\n");
+               
+           if (PL_doextract)                   /* require explicit override ? */
+               if (!OverrideExtract(PL_origfilename))
+                   Perl_croak(aTHX_ "User aborted script\n");
+               else
+                   PL_doextract = FALSE;
+               
+           /* Pater peccavi, file does not have #! */
+           PerlIO_rewind(PL_rsfp);
+           
+           break;
+       }
+#else
     while (PL_doextract) {
        if ((s = sv_gets(PL_linestr, PL_rsfp, 0)) == Nullch)
            Perl_croak(aTHX_ "No Perl script found in input\n");
+#endif
        if (*s == '#' && s[1] == '!' && (s = instr(s,"perl"))) {
            PerlIO_ungetc(PL_rsfp, '\n');               /* to keep line count right */
            PL_doextract = FALSE;
@@ -2614,7 +3058,8 @@ S_find_beginning(pTHX)
                while (isDIGIT(s2[-1]) || strchr("-._", s2[-1])) s2--;
                if (strnEQ(s2-4,"perl",4))
                    /*SUPPRESS 530*/
-                   while (s = moreswitches(s)) ;
+                   while ((s = moreswitches(s)))
+                       ;
            }
        }
     }
@@ -2754,7 +3199,6 @@ S_init_predump_symbols(pTHX)
 {
     dTHR;
     GV *tmpgv;
-    GV *othergv;
     IO *io;
 
     sv_setpvn(get_sv("\"", TRUE), " ", 1);
@@ -2785,8 +3229,9 @@ S_init_predump_symbols(pTHX)
 
     PL_statname = NEWSV(66,0);         /* last filename we did stat on */
 
-    if (!PL_osname)
-       PL_osname = savepv(OSNAME);
+    if (PL_osname)
+       Safefree(PL_osname);
+    PL_osname = savepv(OSNAME);
 }
 
 STATIC void
@@ -2802,11 +3247,11 @@ S_init_postdump_symbols(pTHX_ register int argc, register char **argv, register
        for (; argc > 0 && **argv == '-'; argc--,argv++) {
            if (!argv[0][1])
                break;
-           if (argv[0][1] == '-') {
+           if (argv[0][1] == '-' && !argv[0][2]) {
                argc--,argv++;
                break;
            }
-           if (s = strchr(argv[0], '=')) {
+           if ((s = strchr(argv[0], '='))) {
                *s++ = '\0';
                sv_setpv(GvSV(gv_fetchpv(argv[0]+1,TRUE, SVt_PV)),s);
            }
@@ -2823,30 +3268,38 @@ S_init_postdump_symbols(pTHX_ register int argc, register char **argv, register
     PL_formtarget = PL_bodytarget;
 
     TAINT;
-    if (tmpgv = gv_fetchpv("0",TRUE, SVt_PV)) {
+    if ((tmpgv = gv_fetchpv("0",TRUE, SVt_PV))) {
+#ifdef MACOS_TRADITIONAL
+       /* $0 is not majick on a Mac */
+       sv_setpv(GvSV(tmpgv),MacPerl_MPWFileName(PL_origfilename));
+#else
        sv_setpv(GvSV(tmpgv),PL_origfilename);
        magicname("0", "0", 1);
+#endif
     }
-    if (tmpgv = gv_fetchpv("\030",TRUE, SVt_PV))
+    if ((tmpgv = gv_fetchpv("\030",TRUE, SVt_PV)))
 #ifdef OS2
-       sv_setpv(GvSV(tmpgv), os2_execname());
+       sv_setpv(GvSV(tmpgv), os2_execname(aTHX));
 #else
        sv_setpv(GvSV(tmpgv),PL_origargv[0]);
 #endif
-    if (PL_argvgv = gv_fetchpv("ARGV",TRUE, SVt_PVAV)) {
+    if ((PL_argvgv = gv_fetchpv("ARGV",TRUE, SVt_PVAV))) {
        GvMULTI_on(PL_argvgv);
        (void)gv_AVadd(PL_argvgv);
        av_clear(GvAVn(PL_argvgv));
        for (; argc > 0; argc--,argv++) {
-           av_push(GvAVn(PL_argvgv),newSVpv(argv[0],0));
+           SV *sv = newSVpv(argv[0],0);
+           av_push(GvAVn(PL_argvgv),sv);
+           if (PL_widesyscalls)
+               (void)sv_utf8_decode(sv);
        }
     }
-    if (PL_envgv = gv_fetchpv("ENV",TRUE, SVt_PVHV)) {
+    if ((PL_envgv = gv_fetchpv("ENV",TRUE, SVt_PVHV))) {
        HV *hv;
        GvMULTI_on(PL_envgv);
        hv = GvHVn(PL_envgv);
        hv_magic(hv, PL_envgv, 'E');
-#if !defined( VMS) && !defined(EPOC)  /* VMS doesn't have environ array */
+#if !defined( VMS) && !defined(EPOC) && !defined(MACOS_TRADITIONAL) /* VMS doesn't have environ array */
        /* Note that if the supplied env parameter is actually a copy
           of the global environ then it may now point to free'd memory
           if the environment has been modified since. To avoid this
@@ -2877,7 +3330,7 @@ S_init_postdump_symbols(pTHX_ register int argc, register char **argv, register
 #endif
     }
     TAINT_NOT;
-    if (tmpgv = gv_fetchpv("$",TRUE, SVt_PV))
+    if ((tmpgv = gv_fetchpv("$",TRUE, SVt_PV)))
        sv_setiv(GvSV(tmpgv), (IV)PerlProc_getpid());
 }
 
@@ -2889,9 +3342,9 @@ S_init_perllib(pTHX)
 #ifndef VMS
        s = PerlEnv_getenv("PERL5LIB");
        if (s)
-           incpush(s, TRUE);
+           incpush(s, TRUE, TRUE);
        else
-           incpush(PerlEnv_getenv("PERLLIB"), FALSE);
+           incpush(PerlEnv_getenv("PERLLIB"), FALSE, FALSE);
 #else /* VMS */
        /* Treat PERL5?LIB as a possible search list logical name -- the
         * "natural" VMS idiom for a Unix path string.  We allow each
@@ -2900,50 +3353,99 @@ S_init_perllib(pTHX)
        char buf[256];
        int idx = 0;
        if (my_trnlnm("PERL5LIB",buf,0))
-           do { incpush(buf,TRUE); } while (my_trnlnm("PERL5LIB",buf,++idx));
+           do { incpush(buf,TRUE,TRUE); } while (my_trnlnm("PERL5LIB",buf,++idx));
        else
-           while (my_trnlnm("PERLLIB",buf,idx++)) incpush(buf,FALSE);
+           while (my_trnlnm("PERLLIB",buf,idx++)) incpush(buf,FALSE,FALSE);
 #endif /* VMS */
     }
 
 /* Use the ~-expanded versions of APPLLIB (undocumented),
-    ARCHLIB PRIVLIB SITEARCH and SITELIB 
+    ARCHLIB PRIVLIB SITEARCH SITELIB VENDORARCH and VENDORLIB
 */
 #ifdef APPLLIB_EXP
-    incpush(APPLLIB_EXP, TRUE);
+    incpush(APPLLIB_EXP, TRUE, TRUE);
 #endif
 
 #ifdef ARCHLIB_EXP
-    incpush(ARCHLIB_EXP, FALSE);
+    incpush(ARCHLIB_EXP, FALSE, FALSE);
 #endif
+#ifdef MACOS_TRADITIONAL
+    {
+       struct stat tmpstatbuf;
+       SV * privdir = NEWSV(55, 0);
+       char * macperl = PerlEnv_getenv("MACPERL");
+       
+       if (!macperl)
+           macperl = "";
+       
+       Perl_sv_setpvf(aTHX_ privdir, "%slib:", macperl);
+       if (PerlLIO_stat(SvPVX(privdir), &tmpstatbuf) >= 0 && S_ISDIR(tmpstatbuf.st_mode))
+           incpush(SvPVX(privdir), TRUE, FALSE);
+       Perl_sv_setpvf(aTHX_ privdir, "%ssite_perl:", macperl);
+       if (PerlLIO_stat(SvPVX(privdir), &tmpstatbuf) >= 0 && S_ISDIR(tmpstatbuf.st_mode))
+           incpush(SvPVX(privdir), TRUE, FALSE);
+           
+       SvREFCNT_dec(privdir);
+    }
+    if (!PL_tainting)
+       incpush(":", FALSE, FALSE);
+#else
 #ifndef PRIVLIB_EXP
-#define PRIVLIB_EXP "/usr/local/lib/perl5:/usr/local/lib/perl"
+#  define PRIVLIB_EXP "/usr/local/lib/perl5:/usr/local/lib/perl"
 #endif
 #if defined(WIN32) 
-    incpush(PRIVLIB_EXP, TRUE);
+    incpush(PRIVLIB_EXP, TRUE, FALSE);
 #else
-    incpush(PRIVLIB_EXP, FALSE);
+    incpush(PRIVLIB_EXP, FALSE, FALSE);
 #endif
 
 #ifdef SITEARCH_EXP
-    incpush(SITEARCH_EXP, FALSE);
+    /* sitearch is always relative to sitelib on Windows for
+     * DLL-based path intuition to work correctly */
+#  if !defined(WIN32)
+    incpush(SITEARCH_EXP, FALSE, FALSE);
+#  endif
 #endif
+
 #ifdef SITELIB_EXP
-#if defined(WIN32) 
-    incpush(SITELIB_EXP, TRUE);
-#else
-    incpush(SITELIB_EXP, FALSE);
+#  if defined(WIN32)
+    incpush(SITELIB_EXP, TRUE, FALSE); /* this picks up sitearch as well */
+#  else
+    incpush(SITELIB_EXP, FALSE, FALSE);
+#  endif
 #endif
+
+#ifdef SITELIB_STEM /* Search for version-specific dirs below here */
+    incpush(SITELIB_STEM, FALSE, TRUE);
 #endif
-#if defined(PERL_VENDORLIB_EXP)
-#if defined(WIN32) 
-    incpush(PERL_VENDORLIB_EXP, TRUE);
-#else
-    incpush(PERL_VENDORLIB_EXP, FALSE);
+
+#ifdef PERL_VENDORARCH_EXP
+    /* vendorarch is always relative to vendorlib on Windows for
+     * DLL-based path intuition to work correctly */
+#  if !defined(WIN32)
+    incpush(PERL_VENDORARCH_EXP, FALSE, FALSE);
+#  endif
+#endif
+
+#ifdef PERL_VENDORLIB_EXP
+#  if defined(WIN32)
+    incpush(PERL_VENDORLIB_EXP, TRUE, FALSE);  /* this picks up vendorarch as well */
+#  else
+    incpush(PERL_VENDORLIB_EXP, FALSE, FALSE);
+#  endif
 #endif
+
+#ifdef PERL_VENDORLIB_STEM /* Search for version-specific dirs below here */
+    incpush(PERL_VENDORLIB_STEM, FALSE, TRUE);
 #endif
+
+#ifdef PERL_OTHERLIBDIRS
+    incpush(PERL_OTHERLIBDIRS, TRUE, TRUE);
+#endif
+
     if (!PL_tainting)
-       incpush(".", FALSE);
+       incpush(".", FALSE, FALSE);
+#endif /* MACOS_TRADITIONAL */
 }
 
 #if defined(DOSISH)
@@ -2952,7 +3454,11 @@ S_init_perllib(pTHX)
 #  if defined(VMS)
 #    define PERLLIB_SEP '|'
 #  else
-#    define PERLLIB_SEP ':'
+#    if defined(MACOS_TRADITIONAL)
+#      define PERLLIB_SEP ','
+#    else
+#      define PERLLIB_SEP ':'
+#    endif
 #  endif
 #endif
 #ifndef PERLLIB_MANGLE
@@ -2960,26 +3466,15 @@ S_init_perllib(pTHX)
 #endif 
 
 STATIC void
-S_incpush(pTHX_ char *p, int addsubdirs)
+S_incpush(pTHX_ char *p, int addsubdirs, int addoldvers)
 {
     SV *subdir = Nullsv;
 
-    if (!p)
+    if (!p || !*p)
        return;
 
-    if (addsubdirs) {
+    if (addsubdirs || addoldvers) {
        subdir = sv_newmortal();
-       if (!PL_archpat_auto) {
-           STRLEN len = (sizeof(ARCHNAME) + strlen(PL_patchlevel)
-                         + sizeof("//auto"));
-           New(55, PL_archpat_auto, len, char);
-           sprintf(PL_archpat_auto, "/%s/%s/auto", ARCHNAME, PL_patchlevel);
-#ifdef VMS
-       for (len = sizeof(ARCHNAME) + 2;
-            PL_archpat_auto[len] != '\0' && PL_archpat_auto[len] != '/'; len++)
-               if (PL_archpat_auto[len] == '.') PL_archpat_auto[len] = '_';
-#endif
-       }
     }
 
     /* Break at all separators */
@@ -3003,12 +3498,23 @@ S_incpush(pTHX_ char *p, int addsubdirs)
            sv_setpv(libdir, PERLLIB_MANGLE(p, 0));
            p = Nullch; /* break out */
        }
+#ifdef MACOS_TRADITIONAL
+       if (!strchr(SvPVX(libdir), ':'))
+           sv_insert(libdir, 0, 0, ":", 1);
+       if (SvPVX(libdir)[SvCUR(libdir)-1] != ':')
+           sv_catpv(libdir, ":");
+#endif
 
        /*
         * BEFORE pushing libdir onto @INC we may first push version- and
         * archname-specific sub-directories.
         */
-       if (addsubdirs) {
+       if (addsubdirs || addoldvers) {
+#ifdef PERL_INC_VERSION_LIST
+           /* Configure terminates PERL_INC_VERSION_LIST with a NULL */
+           const char *incverlist[] = { PERL_INC_VERSION_LIST };
+           const char **incver;
+#endif
            struct stat tmpstatbuf;
 #ifdef VMS
            char *unix;
@@ -3024,21 +3530,49 @@ S_incpush(pTHX_ char *p, int addsubdirs)
                              "Failed to unixify @INC element \"%s\"\n",
                              SvPV(libdir,len));
 #endif
-           /* .../archname/version if -d .../archname/version/auto */
-           sv_setsv(subdir, libdir);
-           sv_catpv(subdir, PL_archpat_auto);
-           if (PerlLIO_stat(SvPVX(subdir), &tmpstatbuf) >= 0 &&
-                 S_ISDIR(tmpstatbuf.st_mode))
-               av_push(GvAVn(PL_incgv),
-                       newSVpvn(SvPVX(subdir), SvCUR(subdir) - sizeof "auto"));
-
-           /* .../archname if -d .../archname/auto */
-           sv_insert(subdir, SvCUR(libdir) + sizeof(ARCHNAME),
-                     strlen(PL_patchlevel) + 1, "", 0);
-           if (PerlLIO_stat(SvPVX(subdir), &tmpstatbuf) >= 0 &&
-                 S_ISDIR(tmpstatbuf.st_mode))
-               av_push(GvAVn(PL_incgv),
-                       newSVpvn(SvPVX(subdir), SvCUR(subdir) - sizeof "auto"));
+           if (addsubdirs) {
+#ifdef MACOS_TRADITIONAL
+#define PERL_AV_SUFFIX_FMT     ""
+#define PERL_ARCH_FMT          ":%s"
+#else
+#define PERL_AV_SUFFIX_FMT     "/"
+#define PERL_ARCH_FMT          "/%s"
+#endif
+               /* .../version/archname if -d .../version/archname */
+               Perl_sv_setpvf(aTHX_ subdir, "%"SVf PERL_AV_SUFFIX_FMT PERL_FS_VER_FMT PERL_ARCH_FMT, 
+                               libdir,
+                              (int)PERL_REVISION, (int)PERL_VERSION,
+                              (int)PERL_SUBVERSION, ARCHNAME);
+               if (PerlLIO_stat(SvPVX(subdir), &tmpstatbuf) >= 0 &&
+                     S_ISDIR(tmpstatbuf.st_mode))
+                   av_push(GvAVn(PL_incgv), newSVsv(subdir));
+
+               /* .../version if -d .../version */
+               Perl_sv_setpvf(aTHX_ subdir, "%"SVf PERL_AV_SUFFIX_FMT PERL_FS_VER_FMT, libdir,
+                              (int)PERL_REVISION, (int)PERL_VERSION,
+                              (int)PERL_SUBVERSION);
+               if (PerlLIO_stat(SvPVX(subdir), &tmpstatbuf) >= 0 &&
+                     S_ISDIR(tmpstatbuf.st_mode))
+                   av_push(GvAVn(PL_incgv), newSVsv(subdir));
+
+               /* .../archname if -d .../archname */
+               Perl_sv_setpvf(aTHX_ subdir, "%"SVf PERL_ARCH_FMT, libdir, ARCHNAME);
+               if (PerlLIO_stat(SvPVX(subdir), &tmpstatbuf) >= 0 &&
+                     S_ISDIR(tmpstatbuf.st_mode))
+                   av_push(GvAVn(PL_incgv), newSVsv(subdir));
+           }
+
+#ifdef PERL_INC_VERSION_LIST
+           if (addoldvers) {
+               for (incver = incverlist; *incver; incver++) {
+                   /* .../xxx if -d .../xxx */
+                   Perl_sv_setpvf(aTHX_ subdir, "%"SVf PERL_ARCH_FMT, libdir, *incver);
+                   if (PerlLIO_stat(SvPVX(subdir), &tmpstatbuf) >= 0 &&
+                         S_ISDIR(tmpstatbuf.st_mode))
+                       av_push(GvAVn(PL_incgv), newSVsv(subdir));
+               }
+           }
+#endif
        }
 
        /* finally push this lib directory on the end of @INC */
@@ -3094,7 +3628,7 @@ S_init_main_thread(pTHX)
 #else
     thr->self = pthread_self();
 #endif /* SET_THREAD_SELF */
-    SET_THR(thr);
+    PERL_SET_THX(thr);
 
     /*
      * These must come after the SET_THR because sv_setpvn does
@@ -3136,10 +3670,24 @@ Perl_call_list(pTHX_ I32 oldscope, AV *paramList)
 
     while (AvFILL(paramList) >= 0) {
        cv = (CV*)av_shift(paramList);
-       SAVEFREESV(cv);
-       CALLPROTECT(aTHX_ pcur_env, &ret, MEMBER_TO_FPTR(S_call_list_body), cv);
+       if ((PL_minus_c & 0x10) && (paramList == PL_beginav)) {
+               /* save PL_beginav for compiler */
+           if (! PL_beginav_save)
+               PL_beginav_save = newAV();
+           av_push(PL_beginav_save, (SV*)cv);
+       } else {
+           SAVEFREESV(cv);
+       }
+#ifdef PERL_FLEXIBLE_EXCEPTIONS
+       CALLPROTECT(aTHX_ pcur_env, &ret, MEMBER_TO_FPTR(S_vcall_list_body), cv);
+#else
+       JMPENV_PUSH(ret);
+#endif
        switch (ret) {
        case 0:
+#ifndef PERL_FLEXIBLE_EXCEPTIONS
+           call_list_body(cv);
+#endif
            atsv = ERRSV;
            (void)SvPV(atsv, len);
            if (len) {
@@ -3151,11 +3699,12 @@ Perl_call_list(pTHX_ I32 oldscope, AV *paramList)
                else
                    Perl_sv_catpvf(aTHX_ atsv,
                                   "%s failed--call queue aborted",
-                                  paramList == PL_stopav ? "STOP"
+                                  paramList == PL_checkav ? "CHECK"
                                   : paramList == PL_initav ? "INIT"
                                   : "END");
                while (PL_scopestack_ix > oldscope)
                    LEAVE;
+               JMPENV_POP;
                Perl_croak(aTHX_ "%s", SvPVx(atsv, n_a));
            }
            break;
@@ -3170,12 +3719,13 @@ Perl_call_list(pTHX_ I32 oldscope, AV *paramList)
            PL_curstash = PL_defstash;
            PL_curcop = &PL_compiling;
            CopLINE_set(PL_curcop, oldline);
+           JMPENV_POP;
            if (PL_statusvalue && !(PL_exit_flags & PERL_EXIT_EXPECTED)) {
                if (paramList == PL_beginav)
                    Perl_croak(aTHX_ "BEGIN failed--compilation aborted");
                else
                    Perl_croak(aTHX_ "%s failed--call queue aborted",
-                              paramList == PL_stopav ? "STOP"
+                              paramList == PL_checkav ? "CHECK"
                               : paramList == PL_initav ? "INIT"
                               : "END");
            }
@@ -3191,15 +3741,22 @@ Perl_call_list(pTHX_ I32 oldscope, AV *paramList)
            FREETMPS;
            break;
        }
+       JMPENV_POP;
     }
 }
 
+#ifdef PERL_FLEXIBLE_EXCEPTIONS
 STATIC void *
-S_call_list_body(pTHX_ va_list args)
+S_vcall_list_body(pTHX_ va_list args)
 {
-    dTHR;
     CV *cv = va_arg(args, CV*);
+    return call_list_body(cv);
+}
+#endif
 
+STATIC void *
+S_call_list_body(pTHX_ CV *cv)
+{
     PUSHMARK(PL_stack_sp);
     call_sv((SV*)cv, G_EVAL|G_DISCARD);
     return NULL;