This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
fix for unpack('u') failures on OS/390
[perl5.git] / pp.c
diff --git a/pp.c b/pp.c
index 34e340d..1320486 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -46,7 +46,7 @@ typedef unsigned UBW;
  * have an integral type (except char) small enough to be represented
  * in a double without loss; that is, it has no 32-bit type.
  */
-#if BYTEORDER > 0xFFFF && defined(_CRAY) && !defined(_CRAYMPP)
+#if LONGSIZE > 4  && defined(_CRAY) && !defined(_CRAYMPP)
 #  define BW_BITS  32
 #  define BW_MASK  ((1 << BW_BITS) - 1)
 #  define BW_SIGN  (1 << (BW_BITS - 1))
@@ -69,7 +69,11 @@ typedef unsigned UBW;
  * If they're not right on your machine, then pack() and unpack()
  * wouldn't work right anyway; you'll need to apply the Cray hack.
  * (I'd like to check them with #if, but you can't use sizeof() in
- * the preprocessor.)
+ * the preprocessor.)  --???
+ */
+/*
+    The appropriate SHORTSIZE, INTSIZE, LONGSIZE, and LONGLONGSIZE
+    defines are now in config.h.  --Andy Dougherty  April 1998
  */
 #define SIZE16 2
 #define SIZE32 4
@@ -97,27 +101,33 @@ typedef unsigned UBW;
 #  define CAT32(sv,p)  sv_catpvn(sv, (char*)(p), SIZE32)
 #endif
 
+#ifndef PERL_OBJECT
 static void doencodes _((SV* sv, char* s, I32 len));
 static SV* refto _((SV* sv));
 static U32 seed _((void));
+#endif
 
 static bool srand_called = FALSE;
 
 /* variations on pp_null */
 
-#ifdef DONT_DECLARE_STD
 #ifdef I_UNISTD
 #include <unistd.h>
 #endif
-#else
-extern pid_t getpid (void);
+
+/* XXX I can't imagine anyone who doesn't have this actually _needs_
+   it, since pid_t is an integral type.
+   --AD  2/20/1998
+*/
+#ifdef NEED_GETPID_PROTO
+extern Pid_t getpid (void);
 #endif
 
 PP(pp_stub)
 {
     djSP;
     if (GIMME_V == G_SCALAR)
-       XPUSHs(&sv_undef);
+       XPUSHs(&PL_sv_undef);
     RETURN;
 }
 
@@ -131,10 +141,10 @@ PP(pp_scalar)
 PP(pp_padav)
 {
     djSP; dTARGET;
-    if (op->op_private & OPpLVAL_INTRO)
-       SAVECLEARSV(curpad[op->op_targ]);
+    if (PL_op->op_private & OPpLVAL_INTRO)
+       SAVECLEARSV(PL_curpad[PL_op->op_targ]);
     EXTEND(SP, 1);
-    if (op->op_flags & OPf_REF) {
+    if (PL_op->op_flags & OPf_REF) {
        PUSHs(TARG);
        RETURN;
     }
@@ -145,7 +155,7 @@ PP(pp_padav)
            U32 i;
            for (i=0; i < maxarg; i++) {
                SV **svp = av_fetch((AV*)TARG, i, FALSE);
-               SP[i+1] = (svp) ? *svp : &sv_undef;
+               SP[i+1] = (svp) ? *svp : &PL_sv_undef;
            }
        }
        else {
@@ -168,9 +178,9 @@ PP(pp_padhv)
     I32 gimme;
 
     XPUSHs(TARG);
-    if (op->op_private & OPpLVAL_INTRO)
-       SAVECLEARSV(curpad[op->op_targ]);
-    if (op->op_flags & OPf_REF)
+    if (PL_op->op_private & OPpLVAL_INTRO)
+       SAVECLEARSV(PL_curpad[PL_op->op_targ]);
+    if (PL_op->op_flags & OPf_REF)
        RETURN;
     gimme = GIMME_V;
     if (gimme == G_ARRAY) {
@@ -221,21 +231,21 @@ PP(pp_rv2gv)
                    goto wasref;
            }
            if (!SvOK(sv)) {
-               if (op->op_flags & OPf_REF ||
-                   op->op_private & HINT_STRICT_REFS)
+               if (PL_op->op_flags & OPf_REF ||
+                   PL_op->op_private & HINT_STRICT_REFS)
                    DIE(no_usym, "a symbol");
-               if (dowarn)
+               if (PL_dowarn)
                    warn(warn_uninit);
                RETSETUNDEF;
            }
-           sym = SvPV(sv, na);
-           if (op->op_private & HINT_STRICT_REFS)
+           sym = SvPV(sv, PL_na);
+           if (PL_op->op_private & HINT_STRICT_REFS)
                DIE(no_symref, sym, "a symbol");
            sv = (SV*)gv_fetchpv(sym, TRUE, SVt_PVGV);
        }
     }
-    if (op->op_private & OPpLVAL_INTRO)
-       save_gp((GV*)sv, !(op->op_flags & OPf_SPECIAL));
+    if (PL_op->op_private & OPpLVAL_INTRO)
+       save_gp((GV*)sv, !(PL_op->op_flags & OPf_SPECIAL));
     SETs(sv);
     RETURN;
 }
@@ -265,25 +275,25 @@ PP(pp_rv2sv)
                    goto wasref;
            }
            if (!SvOK(sv)) {
-               if (op->op_flags & OPf_REF ||
-                   op->op_private & HINT_STRICT_REFS)
+               if (PL_op->op_flags & OPf_REF ||
+                   PL_op->op_private & HINT_STRICT_REFS)
                    DIE(no_usym, "a SCALAR");
-               if (dowarn)
+               if (PL_dowarn)
                    warn(warn_uninit);
                RETSETUNDEF;
            }
-           sym = SvPV(sv, na);
-           if (op->op_private & HINT_STRICT_REFS)
+           sym = SvPV(sv, PL_na);
+           if (PL_op->op_private & HINT_STRICT_REFS)
                DIE(no_symref, sym, "a SCALAR");
            gv = (GV*)gv_fetchpv(sym, TRUE, SVt_PV);
        }
        sv = GvSV(gv);
     }
-    if (op->op_flags & OPf_MOD) {
-       if (op->op_private & OPpLVAL_INTRO)
+    if (PL_op->op_flags & OPf_MOD) {
+       if (PL_op->op_private & OPpLVAL_INTRO)
            sv = save_scalar((GV*)TOPs);
-       else if (op->op_private & OPpDEREF)
-           vivify_ref(sv, op->op_private & OPpDEREF);
+       else if (PL_op->op_private & OPpDEREF)
+           vivify_ref(sv, PL_op->op_private & OPpDEREF);
     }
     SETs(sv);
     RETURN;
@@ -307,14 +317,18 @@ PP(pp_pos)
 {
     djSP; dTARGET; dPOPss;
 
-    if (op->op_flags & OPf_MOD) {
+    if (PL_op->op_flags & OPf_MOD) {
        if (SvTYPE(TARG) < SVt_PVLV) {
            sv_upgrade(TARG, SVt_PVLV);
            sv_magic(TARG, Nullsv, '.', Nullch, 0);
        }
 
        LvTYPE(TARG) = '.';
-       LvTARG(TARG) = sv;
+       if (LvTARG(TARG) != sv) {
+           if (LvTARG(TARG))
+               SvREFCNT_dec(LvTARG(TARG));
+           LvTARG(TARG) = SvREFCNT_inc(sv);
+       }
        PUSHs(TARG);    /* no SvSETMAGIC */
        RETURN;
     }
@@ -324,7 +338,7 @@ PP(pp_pos)
        if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) {
            mg = mg_find(sv, 'g');
            if (mg && mg->mg_len >= 0) {
-               PUSHi(mg->mg_len + curcop->cop_arybase);
+               PUSHi(mg->mg_len + PL_curcop->cop_arybase);
                RETURN;
            }
        }
@@ -340,13 +354,13 @@ PP(pp_rv2cv)
 
     /* We usually try to add a non-existent subroutine in case of AUTOLOAD. */
     /* (But not in defined().) */
-    CV *cv = sv_2cv(TOPs, &stash, &gv, !(op->op_flags & OPf_SPECIAL));
+    CV *cv = sv_2cv(TOPs, &stash, &gv, !(PL_op->op_flags & OPf_SPECIAL));
     if (cv) {
        if (CvCLONE(cv))
            cv = (CV*)sv_2mortal((SV*)cv_clone(cv));
     }
     else
-       cv = (CV*)&sv_undef;
+       cv = (CV*)&PL_sv_undef;
     SETs((SV*)cv);
     RETURN;
 }
@@ -359,7 +373,7 @@ PP(pp_prototype)
     GV *gv;
     SV *ret;
 
-    ret = &sv_undef;
+    ret = &PL_sv_undef;
     if (SvPOK(TOPs) && SvCUR(TOPs) >= 7) {
        char *s = SvPVX(TOPs);
        if (strnEQ(s, "CORE::", 6)) {
@@ -415,7 +429,7 @@ PP(pp_prototype)
 PP(pp_anoncode)
 {
     djSP;
-    CV* cv = (CV*)curpad[op->op_targ];
+    CV* cv = (CV*)PL_curpad[PL_op->op_targ];
     if (CvCLONE(cv))
        cv = (CV*)sv_2mortal((SV*)cv_clone(cv));
     EXTEND(SP,1);
@@ -434,8 +448,13 @@ PP(pp_refgen)
 {
     djSP; dMARK;
     if (GIMME != G_ARRAY) {
-       MARK[1] = *SP;
-       SP = MARK + 1;
+       if (++MARK <= SP)
+           *MARK = *SP;
+       else
+           *MARK = &PL_sv_undef;
+       *MARK = refto(*MARK);
+       SP = MARK;
+       RETURN;
     }
     EXTEND_MORTAL(SP - MARK);
     while (++MARK <= SP)
@@ -443,7 +462,7 @@ PP(pp_refgen)
     RETURN;
 }
 
-static SV*
+STATIC SV*
 refto(SV *sv)
 {
     SV* rv;
@@ -452,7 +471,7 @@ refto(SV *sv)
        if (LvTARGLEN(sv))
            vivify_defelem(sv);
        if (!(sv = LvTARG(sv)))
-           sv = &sv_undef;
+           sv = &PL_sv_undef;
     }
     else if (SvPADTMP(sv))
        sv = newSVsv(sv);
@@ -493,9 +512,15 @@ PP(pp_bless)
     HV *stash;
 
     if (MAXARG == 1)
-       stash = curcop->cop_stash;
-    else
-       stash = gv_stashsv(POPs, TRUE);
+       stash = PL_curcop->cop_stash;
+    else {
+       SV *ssv = POPs;
+       STRLEN len;
+       char *ptr = SvPV(ssv,len);
+       if (PL_dowarn && len == 0)
+           warn("Explicit blessing to '' (assuming package main)");
+       stash = gv_stashpvn(ptr, len, TRUE);
+    }
 
     (void)sv_bless(TOPs, stash);
     RETURN;
@@ -505,40 +530,40 @@ PP(pp_gelem)
 {
     GV *gv;
     SV *sv;
-    SV *ref;
+    SV *tmpRef;
     char *elem;
     djSP;
 
     sv = POPs;
-    elem = SvPV(sv, na);
+    elem = SvPV(sv, PL_na);
     gv = (GV*)POPs;
-    ref = Nullsv;
+    tmpRef = Nullsv;
     sv = Nullsv;
     switch (elem ? *elem : '\0')
     {
     case 'A':
        if (strEQ(elem, "ARRAY"))
-           ref = (SV*)GvAV(gv);
+           tmpRef = (SV*)GvAV(gv);
        break;
     case 'C':
        if (strEQ(elem, "CODE"))
-           ref = (SV*)GvCVu(gv);
+           tmpRef = (SV*)GvCVu(gv);
        break;
     case 'F':
        if (strEQ(elem, "FILEHANDLE")) /* XXX deprecate in 5.005 */
-           ref = (SV*)GvIOp(gv);
+           tmpRef = (SV*)GvIOp(gv);
        break;
     case 'G':
        if (strEQ(elem, "GLOB"))
-           ref = (SV*)gv;
+           tmpRef = (SV*)gv;
        break;
     case 'H':
        if (strEQ(elem, "HASH"))
-           ref = (SV*)GvHV(gv);
+           tmpRef = (SV*)GvHV(gv);
        break;
     case 'I':
        if (strEQ(elem, "IO"))
-           ref = (SV*)GvIOp(gv);
+           tmpRef = (SV*)GvIOp(gv);
        break;
     case 'N':
        if (strEQ(elem, "NAME"))
@@ -550,15 +575,15 @@ PP(pp_gelem)
        break;
     case 'S':
        if (strEQ(elem, "SCALAR"))
-           ref = GvSV(gv);
+           tmpRef = GvSV(gv);
        break;
     }
-    if (ref)
-       sv = newRV(ref);
+    if (tmpRef)
+       sv = newRV(tmpRef);
     if (sv)
        sv_2mortal(sv);
     else
-       sv = &sv_undef;
+       sv = &PL_sv_undef;
     XPUSHs(sv);
     RETURN;
 }
@@ -576,44 +601,36 @@ PP(pp_study)
     register I32 *snext;
     STRLEN len;
 
-    if(unop->op_first && unop->op_first->op_type == OP_PUSHRE) {
-       PMOP *pm = (PMOP *)unop->op_first;
-       SV *rv = sv_newmortal();
-       sv = newSVrv(rv, "Regexp");
-       sv_magic(sv,(SV*)ReREFCNT_inc(pm->op_pmregexp),'r',0,0);
-       RETURNX(PUSHs(rv));
-    }
-
-    if (sv == lastscream) {
+    if (sv == PL_lastscream) {
        if (SvSCREAM(sv))
            RETPUSHYES;
     }
     else {
-       if (lastscream) {
-           SvSCREAM_off(lastscream);
-           SvREFCNT_dec(lastscream);
+       if (PL_lastscream) {
+           SvSCREAM_off(PL_lastscream);
+           SvREFCNT_dec(PL_lastscream);
        }
-       lastscream = SvREFCNT_inc(sv);
+       PL_lastscream = SvREFCNT_inc(sv);
     }
 
     s = (unsigned char*)(SvPV(sv, len));
     pos = len;
     if (pos <= 0)
        RETPUSHNO;
-    if (pos > maxscream) {
-       if (maxscream < 0) {
-           maxscream = pos + 80;
-           New(301, screamfirst, 256, I32);
-           New(302, screamnext, maxscream, I32);
+    if (pos > PL_maxscream) {
+       if (PL_maxscream < 0) {
+           PL_maxscream = pos + 80;
+           New(301, PL_screamfirst, 256, I32);
+           New(302, PL_screamnext, PL_maxscream, I32);
        }
        else {
-           maxscream = pos + pos / 4;
-           Renew(screamnext, maxscream, I32);
+           PL_maxscream = pos + pos / 4;
+           Renew(PL_screamnext, PL_maxscream, I32);
        }
     }
 
-    sfirst = screamfirst;
-    snext = screamnext;
+    sfirst = PL_screamfirst;
+    snext = PL_screamnext;
 
     if (!sfirst || !snext)
        DIE("do_study: out of memory");
@@ -641,14 +658,14 @@ PP(pp_trans)
     djSP; dTARG;
     SV *sv;
 
-    if (op->op_flags & OPf_STACKED)
+    if (PL_op->op_flags & OPf_STACKED)
        sv = POPs;
     else {
        sv = DEFSV;
        EXTEND(SP,1);
     }
     TARG = sv_newmortal();
-    PUSHi(do_trans(sv, op));
+    PUSHi(do_trans(sv, PL_op));
     RETURN;
 }
 
@@ -724,7 +741,7 @@ PP(pp_undef)
     djSP;
     SV *sv;
 
-    if (!op->op_private) {
+    if (!PL_op->op_private) {
        EXTEND(SP, 1);
        RETPUSHUNDEF;
     }
@@ -750,7 +767,7 @@ PP(pp_undef)
        hv_undef((HV*)sv);
        break;
     case SVt_PVCV:
-       if (cv_const_sv((CV*)sv))
+       if (PL_dowarn && cv_const_sv((CV*)sv))
            warn("Constant subroutine %s undefined",
                 CvANON((CV*)sv) ? "(anonymous)" : GvENAME(CvGV((CV*)sv)));
        /* FALL THROUGH */
@@ -761,7 +778,17 @@ PP(pp_undef)
        break;
     case SVt_PVGV:
        if (SvFAKE(sv))
-           sv_setsv(sv, &sv_undef);
+           SvSetMagicSV(sv, &PL_sv_undef);
+       else {
+           GP *gp;
+           gp_free((GV*)sv);
+           Newz(602, gp, 1, GP);
+           GvGP(sv) = gp_ref(gp);
+           GvSV(sv) = NEWSV(72,0);
+           GvLINE(sv) = PL_curcop->cop_line;
+           GvEGV(sv) = (GV*)sv;
+           GvMULTI_on(sv);
+       }
        break;
     default:
        if (SvTYPE(sv) >= SVt_PV && SvPVX(sv) && SvLEN(sv)) {
@@ -886,7 +913,7 @@ PP(pp_divide)
 
 PP(pp_modulo)
 {
-    djSP; dATARGET; tryAMAGICbin(mod,opASSIGN);
+    djSP; dATARGET; tryAMAGICbin(modulo,opASSIGN);
     {
       UV left;
       UV right;
@@ -938,7 +965,7 @@ PP(pp_repeat)
   djSP; dATARGET; tryAMAGICbin(repeat,opASSIGN);
   {
     register I32 count = POPi;
-    if (GIMME == G_ARRAY && op->op_private & OPpREPEAT_DOLIST) {
+    if (GIMME == G_ARRAY && PL_op->op_private & OPpREPEAT_DOLIST) {
        dMARK;
        I32 items = SP - MARK;
        I32 max;
@@ -965,7 +992,7 @@ PP(pp_repeat)
 
        tmpstr = POPs;
        if (TARG == tmpstr && SvTHINKFIRST(tmpstr)) {
-           if (SvREADONLY(tmpstr) && curcop != &compiling)
+           if (SvREADONLY(tmpstr) && PL_curcop != &PL_compiling)
                DIE("Can't x= to readonly value");
            if (SvROK(tmpstr))
                sv_unref(tmpstr);
@@ -1004,7 +1031,7 @@ PP(pp_left_shift)
     djSP; dATARGET; tryAMAGICbin(lshift,opASSIGN);
     {
       IBW shift = POPi;
-      if (op->op_private & HINT_INTEGER) {
+      if (PL_op->op_private & HINT_INTEGER) {
        IBW i = TOPi;
        i = BWi(i) << shift;
        SETi(BWi(i));
@@ -1023,7 +1050,7 @@ PP(pp_right_shift)
     djSP; dATARGET; tryAMAGICbin(rshift,opASSIGN);
     {
       IBW shift = POPi;
-      if (op->op_private & HINT_INTEGER) {
+      if (PL_op->op_private & HINT_INTEGER) {
        IBW i = TOPi;
        i = BWi(i) >> shift;
        SETi(BWi(i));
@@ -1101,7 +1128,7 @@ PP(pp_ncmp)
       else if (left > right)
        value = 1;
       else {
-       SETs(&sv_undef);
+       SETs(&PL_sv_undef);
        RETURN;
       }
       SETi(value);
@@ -1114,7 +1141,7 @@ PP(pp_slt)
     djSP; tryAMAGICbinSET(slt,0);
     {
       dPOPTOPssrl;
-      int cmp = ((op->op_private & OPpLOCALE)
+      int cmp = ((PL_op->op_private & OPpLOCALE)
                 ? sv_cmp_locale(left, right)
                 : sv_cmp(left, right));
       SETs(boolSV(cmp < 0));
@@ -1127,7 +1154,7 @@ PP(pp_sgt)
     djSP; tryAMAGICbinSET(sgt,0);
     {
       dPOPTOPssrl;
-      int cmp = ((op->op_private & OPpLOCALE)
+      int cmp = ((PL_op->op_private & OPpLOCALE)
                 ? sv_cmp_locale(left, right)
                 : sv_cmp(left, right));
       SETs(boolSV(cmp > 0));
@@ -1140,7 +1167,7 @@ PP(pp_sle)
     djSP; tryAMAGICbinSET(sle,0);
     {
       dPOPTOPssrl;
-      int cmp = ((op->op_private & OPpLOCALE)
+      int cmp = ((PL_op->op_private & OPpLOCALE)
                 ? sv_cmp_locale(left, right)
                 : sv_cmp(left, right));
       SETs(boolSV(cmp <= 0));
@@ -1153,7 +1180,7 @@ PP(pp_sge)
     djSP; tryAMAGICbinSET(sge,0);
     {
       dPOPTOPssrl;
-      int cmp = ((op->op_private & OPpLOCALE)
+      int cmp = ((PL_op->op_private & OPpLOCALE)
                 ? sv_cmp_locale(left, right)
                 : sv_cmp(left, right));
       SETs(boolSV(cmp >= 0));
@@ -1186,7 +1213,7 @@ PP(pp_scmp)
     djSP; dTARGET;  tryAMAGICbin(scmp,0);
     {
       dPOPTOPssrl;
-      int cmp = ((op->op_private & OPpLOCALE)
+      int cmp = ((PL_op->op_private & OPpLOCALE)
                 ? sv_cmp_locale(left, right)
                 : sv_cmp(left, right));
       SETi( cmp );
@@ -1200,7 +1227,7 @@ PP(pp_bit_and)
     {
       dPOPTOPssrl;
       if (SvNIOKp(left) || SvNIOKp(right)) {
-       if (op->op_private & HINT_INTEGER) {
+       if (PL_op->op_private & HINT_INTEGER) {
          IBW value = SvIV(left) & SvIV(right);
          SETi(BWi(value));
        }
@@ -1210,7 +1237,7 @@ PP(pp_bit_and)
        }
       }
       else {
-       do_vop(op->op_type, TARG, left, right);
+       do_vop(PL_op->op_type, TARG, left, right);
        SETTARG;
       }
       RETURN;
@@ -1223,7 +1250,7 @@ PP(pp_bit_xor)
     {
       dPOPTOPssrl;
       if (SvNIOKp(left) || SvNIOKp(right)) {
-       if (op->op_private & HINT_INTEGER) {
+       if (PL_op->op_private & HINT_INTEGER) {
          IBW value = (USE_LEFT(left) ? SvIV(left) : 0) ^ SvIV(right);
          SETi(BWi(value));
        }
@@ -1233,7 +1260,7 @@ PP(pp_bit_xor)
        }
       }
       else {
-       do_vop(op->op_type, TARG, left, right);
+       do_vop(PL_op->op_type, TARG, left, right);
        SETTARG;
       }
       RETURN;
@@ -1246,7 +1273,7 @@ PP(pp_bit_or)
     {
       dPOPTOPssrl;
       if (SvNIOKp(left) || SvNIOKp(right)) {
-       if (op->op_private & HINT_INTEGER) {
+       if (PL_op->op_private & HINT_INTEGER) {
          IBW value = (USE_LEFT(left) ? SvIV(left) : 0) | SvIV(right);
          SETi(BWi(value));
        }
@@ -1256,7 +1283,7 @@ PP(pp_bit_or)
        }
       }
       else {
-       do_vop(op->op_type, TARG, left, right);
+       do_vop(PL_op->op_type, TARG, left, right);
        SETTARG;
       }
       RETURN;
@@ -1300,7 +1327,7 @@ PP(pp_not)
 #ifdef OVERLOAD
     djSP; tryAMAGICunSET(not);
 #endif /* OVERLOAD */
-    *stack_sp = boolSV(!SvTRUE(*stack_sp));
+    *PL_stack_sp = boolSV(!SvTRUE(*PL_stack_sp));
     return NORMAL;
 }
 
@@ -1310,7 +1337,7 @@ PP(pp_complement)
     {
       dTOPss;
       if (SvNIOKp(sv)) {
-       if (op->op_private & HINT_INTEGER) {
+       if (PL_op->op_private & HINT_INTEGER) {
          IBW value = ~SvIV(sv);
          SETi(BWi(value));
        }
@@ -1372,7 +1399,7 @@ PP(pp_i_divide)
 
 PP(pp_i_modulo)
 {
-    djSP; dATARGET; tryAMAGICbin(mod,opASSIGN);
+    djSP; dATARGET; tryAMAGICbin(modulo,opASSIGN); 
     {
       dPOPTOPiirl;
       if (!right)
@@ -1523,6 +1550,19 @@ PP(pp_cos)
     }
 }
 
+/* Support Configure command-line overrides for rand() functions.
+   After 5.005, perhaps we should replace this by Configure support
+   for drand48(), random(), or rand().  For 5.005, though, maintain
+   compatibility by calling rand() but allow the user to override it.
+   See INSTALL for details.  --Andy Dougherty  15 July 1998
+*/
+#ifndef my_rand
+#  define my_rand      rand
+#endif
+#ifndef my_srand
+#  define my_srand     srand
+#endif
+
 PP(pp_rand)
 {
     djSP; dTARGET;
@@ -1534,19 +1574,19 @@ PP(pp_rand)
     if (value == 0.0)
        value = 1.0;
     if (!srand_called) {
-       (void)srand((unsigned)seed());
+       (void)my_srand((unsigned)seed());
        srand_called = TRUE;
     }
 #if RANDBITS == 31
-    value = rand() * value / 2147483648.0;
+    value = my_rand() * value / 2147483648.0;
 #else
 #if RANDBITS == 16
-    value = rand() * value / 65536.0;
+    value = my_rand() * value / 65536.0;
 #else
 #if RANDBITS == 15
-    value = rand() * value / 32768.0;
+    value = my_rand() * value / 32768.0;
 #else
-    value = rand() * value / (double)(((unsigned long)1) << RANDBITS);
+    value = my_rand() * value / (double)(((unsigned long)1) << RANDBITS);
 #endif
 #endif
 #endif
@@ -1562,13 +1602,13 @@ PP(pp_srand)
        anum = seed();
     else
        anum = POPu;
-    (void)srand((unsigned)anum);
+    (void)my_srand((unsigned)anum);
     srand_called = TRUE;
     EXTEND(SP, 1);
     RETPUSHYES;
 }
 
-static U32
+STATIC U32
 seed(void)
 {
     /*
@@ -1614,7 +1654,7 @@ seed(void)
 #  endif
 #endif
     u += SEED_C3 * (U32)getpid();
-    u += SEED_C4 * (U32)(UV)stack_sp;
+    u += SEED_C4 * (U32)(UV)PL_stack_sp;
 #ifndef PLAN9           /* XXX Plan9 assembler chokes on this; fix needed  */
     u += SEED_C5 * (U32)(UV)&when;
 #endif
@@ -1764,50 +1804,59 @@ PP(pp_substr)
     I32 pos;
     I32 rem;
     I32 fail;
-    I32 lvalue = op->op_flags & OPf_MOD;
+    I32 lvalue = PL_op->op_flags & OPf_MOD;
     char *tmps;
-    I32 arybase = curcop->cop_arybase;
-
-    if (MAXARG > 2)
+    I32 arybase = PL_curcop->cop_arybase;
+    char *repl = 0;
+    STRLEN repl_len;
+
+    SvTAINTED_off(TARG);                       /* decontaminate */
+    if (MAXARG > 2) {
+       if (MAXARG > 3) {
+           sv = POPs;
+           repl = SvPV(sv, repl_len);
+       }
        len = POPi;
+    }
     pos = POPi;
     sv = POPs;
+    PUTBACK;
     tmps = SvPV(sv, curlen);
     if (pos >= arybase) {
        pos -= arybase;
        rem = curlen-pos;
        fail = rem;
-        if (MAXARG > 2) {
-            if (len < 0) {
-               rem += len;
-                if (rem < 0)
-                    rem = 0;
-            }
-            else if (rem > len)
-                     rem = len;
-        }
+       if (MAXARG > 2) {
+           if (len < 0) {
+               rem += len;
+               if (rem < 0)
+                   rem = 0;
+           }
+           else if (rem > len)
+                    rem = len;
+       }
     }
     else {
-        pos += curlen;
-        if (MAXARG < 3)
-            rem = curlen;
-        else if (len >= 0) {
-            rem = pos+len;
-            if (rem > (I32)curlen)
-                rem = curlen;
-        }
-        else {
-            rem = curlen+len;
-            if (rem < pos)
-                rem = pos;
-        }
-        if (pos < 0)
-            pos = 0;
-        fail = rem;
-        rem -= pos;
+       pos += curlen;
+       if (MAXARG < 3)
+           rem = curlen;
+       else if (len >= 0) {
+           rem = pos+len;
+           if (rem > (I32)curlen)
+               rem = curlen;
+       }
+       else {
+           rem = curlen+len;
+           if (rem < pos)
+               rem = pos;
+       }
+       if (pos < 0)
+           pos = 0;
+       fail = rem;
+       rem -= pos;
     }
     if (fail < 0) {
-       if (dowarn || lvalue)
+       if (PL_dowarn || lvalue || repl)
            warn("substr outside of string");
        RETPUSHUNDEF;
     }
@@ -1817,8 +1866,8 @@ PP(pp_substr)
        if (lvalue) {                   /* it's an lvalue! */
            if (!SvGMAGICAL(sv)) {
                if (SvROK(sv)) {
-                   SvPV_force(sv,na);
-                   if (dowarn)
+                   SvPV_force(sv,PL_na);
+                   if (PL_dowarn)
                        warn("Attempt to use reference as lvalue in substr");
                }
                if (SvOK(sv))           /* is it defined ? */
@@ -1833,11 +1882,18 @@ PP(pp_substr)
            }
 
            LvTYPE(TARG) = 'x';
-           LvTARG(TARG) = sv;
+           if (LvTARG(TARG) != sv) {
+               if (LvTARG(TARG))
+                   SvREFCNT_dec(LvTARG(TARG));
+               LvTARG(TARG) = SvREFCNT_inc(sv);
+           }
            LvTARGOFF(TARG) = pos;
            LvTARGLEN(TARG) = rem;
        }
+       else if (repl)
+           sv_insert(sv, pos, rem, repl, repl_len);
     }
+    SPAGAIN;
     PUSHs(TARG);               /* avoid SvSETMAGIC here */
     RETURN;
 }
@@ -1848,12 +1904,13 @@ PP(pp_vec)
     register I32 size = POPi;
     register I32 offset = POPi;
     register SV *src = POPs;
-    I32 lvalue = op->op_flags & OPf_MOD;
+    I32 lvalue = PL_op->op_flags & OPf_MOD;
     STRLEN srclen;
     unsigned char *s = (unsigned char*)SvPV(src, srclen);
     unsigned long retnum;
     I32 len;
 
+    SvTAINTED_off(TARG);                       /* decontaminate */
     offset *= size;            /* turn into bit offset */
     len = (offset + size + 7) / 8;
     if (offset < 0 || size < 1)
@@ -1866,7 +1923,11 @@ PP(pp_vec)
            }
 
            LvTYPE(TARG) = 'v';
-           LvTARG(TARG) = src;
+           if (LvTARG(TARG) != src) {
+               if (LvTARG(TARG))
+                   SvREFCNT_dec(LvTARG(TARG));
+               LvTARG(TARG) = SvREFCNT_inc(src);
+           }
            LvTARGOFF(TARG) = offset;
            LvTARGLEN(TARG) = size;
        }
@@ -1926,7 +1987,7 @@ PP(pp_index)
     char *tmps;
     char *tmps2;
     STRLEN biglen;
-    I32 arybase = curcop->cop_arybase;
+    I32 arybase = PL_curcop->cop_arybase;
 
     if (MAXARG < 3)
        offset = 0;
@@ -1940,7 +2001,7 @@ PP(pp_index)
     else if (offset > biglen)
        offset = biglen;
     if (!(tmps2 = fbm_instr((unsigned char*)tmps + offset,
-      (unsigned char*)tmps + biglen, little)))
+      (unsigned char*)tmps + biglen, little, 0)))
        retval = -1 + arybase;
     else
        retval = tmps2 - tmps + arybase;
@@ -1960,7 +2021,7 @@ PP(pp_rindex)
     I32 retval;
     char *tmps;
     char *tmps2;
-    I32 arybase = curcop->cop_arybase;
+    I32 arybase = PL_curcop->cop_arybase;
 
     if (MAXARG >= 3)
        offstr = POPs;
@@ -1989,7 +2050,7 @@ PP(pp_sprintf)
 {
     djSP; dMARK; dORIGMARK; dTARGET;
 #ifdef USE_LOCALE_NUMERIC
-    if (op->op_private & OPpLOCALE)
+    if (PL_op->op_private & OPpLOCALE)
        SET_NUMERIC_LOCAL();
     else
        SET_NUMERIC_STANDARD();
@@ -2040,11 +2101,11 @@ PP(pp_crypt)
 {
     djSP; dTARGET; dPOPTOPssrl;
 #ifdef HAS_CRYPT
-    char *tmps = SvPV(left, na);
+    char *tmps = SvPV(left, PL_na);
 #ifdef FCRYPT
-    sv_setpv(TARG, fcrypt(tmps, SvPV(right, na)));
+    sv_setpv(TARG, fcrypt(tmps, SvPV(right, PL_na)));
 #else
-    sv_setpv(TARG, crypt(tmps, SvPV(right, na)));
+    sv_setpv(TARG, PerlProc_crypt(tmps, SvPV(right, PL_na)));
 #endif
 #else
     DIE(
@@ -2066,9 +2127,9 @@ PP(pp_ucfirst)
        sv = TARG;
        SETs(sv);
     }
-    s = SvPV_force(sv, na);
+    s = SvPV_force(sv, PL_na);
     if (*s) {
-       if (op->op_private & OPpLOCALE) {
+       if (PL_op->op_private & OPpLOCALE) {
            TAINT;
            SvTAINTED_on(sv);
            *s = toUPPER_LC(*s);
@@ -2092,9 +2153,9 @@ PP(pp_lcfirst)
        sv = TARG;
        SETs(sv);
     }
-    s = SvPV_force(sv, na);
+    s = SvPV_force(sv, PL_na);
     if (*s) {
-       if (op->op_private & OPpLOCALE) {
+       if (PL_op->op_private & OPpLOCALE) {
            TAINT;
            SvTAINTED_on(sv);
            *s = toLOWER_LC(*s);
@@ -2125,7 +2186,7 @@ PP(pp_uc)
     if (len) {
        register char *send = s + len;
 
-       if (op->op_private & OPpLOCALE) {
+       if (PL_op->op_private & OPpLOCALE) {
            TAINT;
            SvTAINTED_on(sv);
            for (; s < send; s++)
@@ -2157,7 +2218,7 @@ PP(pp_lc)
     if (len) {
        register char *send = s + len;
 
-       if (op->op_private & OPpLOCALE) {
+       if (PL_op->op_private & OPpLOCALE) {
            TAINT;
            SvTAINTED_on(sv);
            for (; s < send; s++)
@@ -2205,14 +2266,14 @@ PP(pp_aslice)
     djSP; dMARK; dORIGMARK;
     register SV** svp;
     register AV* av = (AV*)POPs;
-    register I32 lval = op->op_flags & OPf_MOD;
-    I32 arybase = curcop->cop_arybase;
+    register I32 lval = PL_op->op_flags & OPf_MOD;
+    I32 arybase = PL_curcop->cop_arybase;
     I32 elem;
 
     if (SvTYPE(av) == SVt_PVAV) {
-       if (lval && op->op_private & OPpLVAL_INTRO) {
+       if (lval && PL_op->op_private & OPpLVAL_INTRO) {
            I32 max = -1;
-           for (svp = mark + 1; svp <= sp; svp++) {
+           for (svp = MARK + 1; svp <= SP; svp++) {
                elem = SvIVx(*svp);
                if (elem > max)
                    max = elem;
@@ -2227,12 +2288,12 @@ PP(pp_aslice)
                elem -= arybase;
            svp = av_fetch(av, elem, lval);
            if (lval) {
-               if (!svp || *svp == &sv_undef)
+               if (!svp || *svp == &PL_sv_undef)
                    DIE(no_aelem, elem);
-               if (op->op_private & OPpLVAL_INTRO)
-                   save_svref(svp);
+               if (PL_op->op_private & OPpLVAL_INTRO)
+                   save_aelem(av, elem, svp);
            }
-           *MARK = svp ? *svp : &sv_undef;
+           *MARK = svp ? *svp : &PL_sv_undef;
        }
     }
     if (GIMME != G_ARRAY) {
@@ -2294,7 +2355,7 @@ PP(pp_delete)
     SV *sv;
     HV *hv;
 
-    if (op->op_private & OPpSLICE) {
+    if (PL_op->op_private & OPpSLICE) {
        dMARK; dORIGMARK;
        U32 hvtype;
        hv = (HV*)POPs;
@@ -2302,11 +2363,9 @@ PP(pp_delete)
        while (++MARK <= SP) {
            if (hvtype == SVt_PVHV)
                sv = hv_delete_ent(hv, *MARK, discard, 0);
-           else if (hvtype == SVt_PVAV)
-               sv = avhv_delete_ent((AV*)hv, *MARK, discard, 0);
            else
                DIE("Not a HASH reference");
-           *MARK = sv ? sv : &sv_undef;
+           *MARK = sv ? sv : &PL_sv_undef;
        }
        if (discard)
            SP = ORIGMARK;
@@ -2321,12 +2380,10 @@ PP(pp_delete)
        hv = (HV*)POPs;
        if (SvTYPE(hv) == SVt_PVHV)
            sv = hv_delete_ent(hv, keysv, discard, 0);
-       else if (SvTYPE(hv) == SVt_PVAV)
-           sv = avhv_delete_ent((AV*)hv, keysv, discard, 0);
        else
            DIE("Not a HASH reference");
        if (!sv)
-           sv = &sv_undef;
+           sv = &PL_sv_undef;
        if (!discard)
            PUSHs(sv);
     }
@@ -2353,28 +2410,30 @@ PP(pp_exists)
 PP(pp_hslice)
 {
     djSP; dMARK; dORIGMARK;
-    register HE *he;
     register HV *hv = (HV*)POPs;
-    register I32 lval = op->op_flags & OPf_MOD;
+    register I32 lval = PL_op->op_flags & OPf_MOD;
     I32 realhv = (SvTYPE(hv) == SVt_PVHV);
 
+    if (!realhv && PL_op->op_private & OPpLVAL_INTRO)
+       DIE("Can't localize pseudo-hash element");
+
     if (realhv || SvTYPE(hv) == SVt_PVAV) {
        while (++MARK <= SP) {
            SV *keysv = *MARK;
            SV **svp;
            if (realhv) {
-               he = hv_fetch_ent(hv, keysv, lval, 0);
+               HE *he = hv_fetch_ent(hv, keysv, lval, 0);
                svp = he ? &HeVAL(he) : 0;
            } else {
                svp = avhv_fetch_ent((AV*)hv, keysv, lval, 0);
            }
            if (lval) {
-               if (!he || HeVAL(he) == &sv_undef)
-                   DIE(no_helem, SvPV(keysv, na));
-               if (op->op_private & OPpLVAL_INTRO)
-                   save_svref(&HeVAL(he));
+               if (!svp || *svp == &PL_sv_undef)
+                   DIE(no_helem, SvPV(keysv, PL_na));
+               if (PL_op->op_private & OPpLVAL_INTRO)
+                   save_helem(hv, keysv, svp);
            }
-           *MARK = he ? HeVAL(he) : &sv_undef;
+           *MARK = svp ? *svp : &PL_sv_undef;
        }
     }
     if (GIMME != G_ARRAY) {
@@ -2394,7 +2453,7 @@ PP(pp_list)
        if (++MARK <= SP)
            *MARK = *SP;                /* unwanted list, return last item */
        else
-           *MARK = &sv_undef;
+           *MARK = &PL_sv_undef;
        SP = MARK;
     }
     RETURN;
@@ -2403,12 +2462,12 @@ PP(pp_list)
 PP(pp_lslice)
 {
     djSP;
-    SV **lastrelem = stack_sp;
-    SV **lastlelem = stack_base + POPMARK;
-    SV **firstlelem = stack_base + POPMARK + 1;
+    SV **lastrelem = PL_stack_sp;
+    SV **lastlelem = PL_stack_base + POPMARK;
+    SV **firstlelem = PL_stack_base + POPMARK + 1;
     register SV **firstrelem = lastlelem + 1;
-    I32 arybase = curcop->cop_arybase;
-    I32 lval = op->op_flags & OPf_MOD;
+    I32 arybase = PL_curcop->cop_arybase;
+    I32 lval = PL_op->op_flags & OPf_MOD;
     I32 is_something_there = lval;
 
     register I32 max = lastrelem - lastlelem;
@@ -2422,7 +2481,7 @@ PP(pp_lslice)
        else
            ix -= arybase;
        if (ix < 0 || ix >= max)
-           *firstlelem = &sv_undef;
+           *firstlelem = &PL_sv_undef;
        else
            *firstlelem = firstrelem[ix];
        SP = firstlelem;
@@ -2439,14 +2498,14 @@ PP(pp_lslice)
        if (ix < 0) {
            ix += max;
            if (ix < 0)
-               *lelem = &sv_undef;
+               *lelem = &PL_sv_undef;
            else if (!(*lelem = firstrelem[ix]))
-               *lelem = &sv_undef;
+               *lelem = &PL_sv_undef;
        }
        else {
            ix -= arybase;
            if (ix >= max || !(*lelem = firstrelem[ix]))
-               *lelem = &sv_undef;
+               *lelem = &PL_sv_undef;
        }
        if (!is_something_there && (SvOK(*lelem) || SvGMAGICAL(*lelem)))
            is_something_there = TRUE;
@@ -2478,8 +2537,8 @@ PP(pp_anonhash)
        SV *val = NEWSV(46, 0);
        if (MARK < SP)
            sv_setsv(val, *++MARK);
-       else if (dowarn)
-           warn("Odd number of elements in hash list");
+       else if (PL_dowarn)
+           warn("Odd number of elements in hash assignment");
        (void)hv_store_ent(hv,key,val,0);
     }
     SP = ORIGMARK;
@@ -2520,13 +2579,16 @@ PP(pp_splice)
        if (offset < 0)
            offset += AvFILLp(ary) + 1;
        else
-           offset -= curcop->cop_arybase;
+           offset -= PL_curcop->cop_arybase;
        if (offset < 0)
            DIE(no_aelem, i);
        if (++MARK < SP) {
            length = SvIVx(*MARK++);
-           if (length < 0)
-               length = 0;
+           if (length < 0) {
+               length += AvFILLp(ary) - offset + 1;
+               if (length < 0)
+                   length = 0;
+           }
        }
        else
            length = AvMAX(ary) + 1;            /* close enough to infinity */
@@ -2569,8 +2631,7 @@ PP(pp_splice)
            if (AvREAL(ary)) {
                EXTEND_MORTAL(length);
                for (i = length, dst = MARK; i; i--) {
-                   if (!SvIMMORTAL(*dst))
-                       sv_2mortal(*dst);       /* free them eventualy */
+                   sv_2mortal(*dst);   /* free them eventualy */
                    dst++;
                }
            }
@@ -2579,8 +2640,7 @@ PP(pp_splice)
        else {
            *MARK = AvARRAY(ary)[offset+length-1];
            if (AvREAL(ary)) {
-               if (!SvIMMORTAL(*MARK))
-                   sv_2mortal(*MARK);
+               sv_2mortal(*MARK);
                for (i = length - 1, dst = &AvARRAY(ary)[offset]; i > 0; i--)
                    SvREFCNT_dec(*dst++);       /* free them now */
            }
@@ -2611,7 +2671,7 @@ PP(pp_splice)
        }
        i = -diff;
        while (i)
-           dst[--i] = &sv_undef;
+           dst[--i] = &PL_sv_undef;
        
        if (newlen) {
            for (src = tmparyval, dst = AvARRAY(ary) + offset;
@@ -2668,8 +2728,7 @@ PP(pp_splice)
                if (AvREAL(ary)) {
                    EXTEND_MORTAL(length);
                    for (i = length, dst = MARK; i; i--) {
-                       if (!SvIMMORTAL(*dst))
-                           sv_2mortal(*dst);   /* free them eventualy */
+                       sv_2mortal(*dst);       /* free them eventualy */
                        dst++;
                    }
                }
@@ -2680,15 +2739,14 @@ PP(pp_splice)
        else if (length--) {
            *MARK = tmparyval[length];
            if (AvREAL(ary)) {
-               if (!SvIMMORTAL(*MARK))
-                   sv_2mortal(*MARK);
+               sv_2mortal(*MARK);
                while (length-- > 0)
                    SvREFCNT_dec(tmparyval[length]);
            }
            Safefree(tmparyval);
        }
        else
-           *MARK = &sv_undef;
+           *MARK = &PL_sv_undef;
     }
     SP = MARK;
     RETURN;
@@ -2698,7 +2756,7 @@ PP(pp_push)
 {
     djSP; dMARK; dORIGMARK; dTARGET;
     register AV *ary = (AV*)*++MARK;
-    register SV *sv = &sv_undef;
+    register SV *sv = &PL_sv_undef;
     MAGIC *mg;
 
     if (SvRMAGICAL(ary) && (mg = mg_find((SV*)ary,'P'))) {
@@ -2729,7 +2787,7 @@ PP(pp_pop)
     djSP;
     AV *av = (AV*)POPs;
     SV *sv = av_pop(av);
-    if (!SvIMMORTAL(sv) && AvREAL(av))
+    if (AvREAL(av))
        (void)sv_2mortal(sv);
     PUSHs(sv);
     RETURN;
@@ -2743,7 +2801,7 @@ PP(pp_shift)
     EXTEND(SP, 1);
     if (!sv)
        RETPUSHUNDEF;
-    if (!SvIMMORTAL(sv) && AvREAL(av))
+    if (AvREAL(av))
        (void)sv_2mortal(sv);
     PUSHs(sv);
     RETURN;
@@ -2758,9 +2816,8 @@ PP(pp_unshift)
     MAGIC *mg;
 
     if (SvRMAGICAL(ary) && (mg = mg_find((SV*)ary,'P'))) {
-
-
        *MARK-- = mg->mg_obj;
+       PUSHMARK(MARK);
        PUTBACK;
        ENTER;
        perl_call_method("UNSHIFT",G_SCALAR|G_DISCARD);
@@ -2803,7 +2860,7 @@ PP(pp_reverse)
        STRLEN len;
 
        if (SP - MARK > 1)
-           do_join(TARG, &sv_no, MARK, SP);
+           do_join(TARG, &PL_sv_no, MARK, SP);
        else
            sv_setsv(TARG, (SP > MARK) ? *SP : DEFSV);
        up = SvPV_force(TARG, len);
@@ -2822,7 +2879,7 @@ PP(pp_reverse)
     RETURN;
 }
 
-static SV      *
+STATIC SV      *
 mul128(SV *sv, U8 m)
 {
   STRLEN          len;
@@ -2831,11 +2888,11 @@ mul128(SV *sv, U8 m)
   U32             i = 0;
 
   if (!strnEQ(s, "0000", 4)) {  /* need to grow sv */
-    SV             *New = newSVpv("0000000000", 10);
+    SV             *tmpNew = newSVpv("0000000000", 10);
 
-    sv_catsv(New, sv);
+    sv_catsv(tmpNew, sv);
     SvREFCNT_dec(sv);          /* free old sv */
-    sv = New;
+    sv = tmpNew;
     s = SvPV(sv, len);
   }
   t = s + len - 1;
@@ -2851,11 +2908,25 @@ mul128(SV *sv, U8 m)
 
 /* Explosives and implosives. */
 
+static const char uuemap[] =
+    "`!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
+static char uudmap[256];        /* Initialised on first use */
+#if 'I' == 73 && 'J' == 74
+/* On an ASCII/ISO kind of system */
+#define ISUUCHAR(ch)    ((ch) >= ' ' && (ch) < 'a')
+#else
+/*
+  Some other sort of character set - use memchr() so we don't match
+  the null byte.
+ */
+#define ISUUCHAR(ch)    (memchr(uuemap, (ch), sizeof(uuemap)-1) || (ch) == ' ')
+#endif
+
 PP(pp_unpack)
 {
     djSP;
     dPOPPOPssrl;
-    SV **oldsp = sp;
+    SV **oldsp = SP;
     I32 gimme = GIMME_V;
     SV *sv;
     STRLEN llen;
@@ -2924,7 +2995,7 @@ PP(pp_unpack)
        default:
            croak("Invalid type in unpack: '%c'", (int)datumtype);
        case ',': /* grandfather in commas but with a warning */
-           if (commas++ == 0 && dowarn)
+           if (commas++ == 0 && PL_dowarn)
                warn("Invalid type in unpack: '%c'", (int)datumtype);
            break;
        case '%':
@@ -3055,7 +3126,7 @@ PP(pp_unpack)
                        bits >>= 4;
                    else
                        bits = *s++;
-                   *pat++ = hexdigit[bits & 15];
+                   *pat++ = PL_hexdigit[bits & 15];
                }
            }
            else {
@@ -3065,7 +3136,7 @@ PP(pp_unpack)
                        bits <<= 4;
                    else
                        bits = *s++;
-                   *pat++ = hexdigit[(bits >> 4) & 15];
+                   *pat++ = PL_hexdigit[(bits >> 4) & 15];
                }
            }
            *pat = '\0';
@@ -3202,6 +3273,13 @@ PP(pp_unpack)
                    Copy(s, &aint, 1, int);
                    s += sizeof(int);
                    sv = NEWSV(40, 0);
+#ifdef __osf__
+                    /* Without the dummy below unpack("i", pack("i",-1))
+                     * return 0xFFffFFff instead of -1 for Digital Unix V4.0
+                     * cc with optimization turned on */
+                    (aint) ?
+                       sv_setiv(sv, (IV)aint) :
+#endif
                    sv_setiv(sv, (IV)aint);
                    PUSHs(sv_2mortal(sv));
                }
@@ -3350,7 +3428,7 @@ PP(pp_unpack)
                                break;
                            }
                        }
-                       t = SvPV(sv, na);
+                       t = SvPV(sv, PL_na);
                        while (*t == '0')
                            t++;
                        sv_chop(sv, t);
@@ -3378,6 +3456,9 @@ PP(pp_unpack)
            break;
 #ifdef HAS_QUAD
        case 'q':
+           along = (strend - s) / sizeof(Quad_t);
+           if (len > along)
+               len = along;
            EXTEND(SP, len);
            EXTEND_MORTAL(len);
            while (len-- > 0) {
@@ -3396,6 +3477,9 @@ PP(pp_unpack)
            }
            break;
        case 'Q':
+           along = (strend - s) / sizeof(Quad_t);
+           if (len > along)
+               len = along;
            EXTEND(SP, len);
            EXTEND_MORTAL(len);
            while (len-- > 0) {
@@ -3406,7 +3490,7 @@ PP(pp_unpack)
                    s += sizeof(unsigned Quad_t);
                }
                sv = NEWSV(43, 0);
-               if (aquad <= UV_MAX)
+               if (auquad <= UV_MAX)
                    sv_setuv(sv, (UV)auquad);
                else
                    sv_setnv(sv, (double)auquad);
@@ -3464,31 +3548,48 @@ PP(pp_unpack)
            }
            break;
        case 'u':
+           /* MKS:
+            * Initialise the decode mapping.  By using a table driven
+             * algorithm, the code will be character-set independent
+             * (and just as fast as doing character arithmetic)
+             */
+            if (uudmap['M'] == 0) {
+                int i;
+                for (i = 0; i < sizeof(uuemap); i += 1)
+                    uudmap[uuemap[i]] = i;
+                /*
+                 * Because ' ' and '`' map to the same value,
+                 * we need to decode them both the same.
+                 */
+                uudmap[' '] = 0;
+            }
+
            along = (strend - s) * 3 / 4;
            sv = NEWSV(42, along);
            if (along)
                SvPOK_on(sv);
-           while (s < strend && *s > ' ' && *s < 'a') {
+           while (s < strend && *s > ' ' && ISUUCHAR(*s)) {
                I32 a, b, c, d;
                char hunk[4];
 
                hunk[3] = '\0';
-               len = (*s++ - ' ') & 077;
+               len = uudmap[*s++] & 077;
                while (len > 0) {
-                   if (s < strend && *s >= ' ')
-                       a = (*s++ - ' ') & 077;
-                   else
-                       a = 0;
-                   if (s < strend && *s >= ' ')
-                       b = (*s++ - ' ') & 077;
-                   else
-                       b = 0;
-                   if (s < strend && *s >= ' ')
-                       c = (*s++ - ' ') & 077;
-                   else
-                       c = 0;
-                   if (s < strend && *s >= ' ')
-                       d = (*s++ - ' ') & 077;
+                   if (s < strend && ISUUCHAR(*s))
+                       a = uudmap[*s++] & 077;
+                   else
+                       a = 0;
+                   if (s < strend && ISUUCHAR(*s))
+                       b = uudmap[*s++] & 077;
+                   else
+                       b = 0;
+                   if (s < strend && ISUUCHAR(*s))
+                       c = uudmap[*s++] & 077;
+                   else
+                       c = 0;
+                   if (s < strend && ISUUCHAR(*s))
+                       d = uudmap[*s++] & 077;
                    else
                        d = 0;
                    hunk[0] = (a << 2) | (b >> 4);
@@ -3539,40 +3640,44 @@ PP(pp_unpack)
            checksum = 0;
        }
     }
-    if (sp == oldsp && gimme == G_SCALAR)
-       PUSHs(&sv_undef);
+    if (SP == oldsp && gimme == G_SCALAR)
+       PUSHs(&PL_sv_undef);
     RETURN;
 }
 
-static void
+STATIC void
 doencodes(register SV *sv, register char *s, register I32 len)
 {
     char hunk[5];
 
-    *hunk = len + ' ';
+    *hunk = uuemap[len];
     sv_catpvn(sv, hunk, 1);
     hunk[4] = '\0';
-    while (len > 0) {
-       hunk[0] = ' ' + (077 & (*s >> 2));
-       hunk[1] = ' ' + (077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017)));
-       hunk[2] = ' ' + (077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03)));
-       hunk[3] = ' ' + (077 & (s[2] & 077));
+    while (len > 2) {
+       hunk[0] = uuemap[(077 & (*s >> 2))];
+       hunk[1] = uuemap[(077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017)))];
+       hunk[2] = uuemap[(077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03)))];
+       hunk[3] = uuemap[(077 & (s[2] & 077))];
        sv_catpvn(sv, hunk, 4);
        s += 3;
        len -= 3;
     }
-    for (s = SvPVX(sv); *s; s++) {
-       if (*s == ' ')
-           *s = '`';
+    if (len > 0) {
+       char r = (len > 1 ? s[1] : '\0');
+       hunk[0] = uuemap[(077 & (*s >> 2))];
+       hunk[1] = uuemap[(077 & (((*s << 4) & 060) | ((r >> 4) & 017)))];
+       hunk[2] = uuemap[(077 & ((r << 2) & 074))];
+       hunk[3] = uuemap[0];
+       sv_catpvn(sv, hunk, 4);
     }
     sv_catpvn(sv, "\n", 1);
 }
 
-static SV      *
+STATIC SV      *
 is_an_int(char *s, STRLEN l)
 {
   SV             *result = newSVpv("", l);
-  char           *result_c = SvPV(result, na); /* convenience */
+  char           *result_c = SvPV(result, PL_na);      /* convenience */
   char           *out = result_c;
   bool            skip = 1;
   bool            ignore = 0;
@@ -3616,7 +3721,7 @@ is_an_int(char *s, STRLEN l)
   return (result);
 }
 
-static int
+STATIC int
 div128(SV *pnum, bool *done)
                                            /* must be '\0' terminated */
 
@@ -3680,7 +3785,7 @@ PP(pp_pack)
     MARK++;
     sv_setpvn(cat, "", 0);
     while (pat < patend) {
-#define NEXTFROM (items-- > 0 ? *MARK++ : &sv_no)
+#define NEXTFROM (items-- > 0 ? *MARK++ : &PL_sv_no)
        datumtype = *pat++ & 0xFF;
        if (isSPACE(datumtype))
            continue;
@@ -3699,7 +3804,7 @@ PP(pp_pack)
        default:
            croak("Invalid type in pack: '%c'", (int)datumtype);
        case ',': /* grandfather in commas but with a warning */
-           if (commas++ == 0 && dowarn)
+           if (commas++ == 0 && PL_dowarn)
                warn("Invalid type in pack: '%c'", (int)datumtype);
            break;
        case '%':
@@ -4064,7 +4169,7 @@ PP(pp_pack)
        case 'p':
            while (len-- > 0) {
                fromstr = NEXTFROM;
-               if (fromstr == &sv_undef)
+               if (fromstr == &PL_sv_undef)
                    aptr = NULL;
                else {
                    /* XXX better yet, could spirit away the string to
@@ -4072,12 +4177,12 @@ PP(pp_pack)
                     * of pack() (and all copies of the result) are
                     * gone.
                     */
-                   if (dowarn && (SvTEMP(fromstr) || SvPADTMP(fromstr)))
+                   if (PL_dowarn && (SvTEMP(fromstr) || SvPADTMP(fromstr)))
                        warn("Attempt to pack pointer to temporary value");
                    if (SvPOK(fromstr) || SvNIOK(fromstr))
-                       aptr = SvPV(fromstr,na);
+                       aptr = SvPV(fromstr,PL_na);
                    else
-                       aptr = SvPV_force(fromstr,na);
+                       aptr = SvPV_force(fromstr,PL_na);
                }
                sv_catpvn(cat, (char*)&aptr, sizeof(char*));
            }
@@ -4132,9 +4237,9 @@ PP(pp_split)
     I32 origlimit = limit;
     I32 realarray = 0;
     I32 base;
-    AV *oldstack = curstack;
+    AV *oldstack = PL_curstack;
     I32 gimme = GIMME_V;
-    I32 oldsave = savestack_ix;
+    I32 oldsave = PL_savestack_ix;
     I32 make_mortal = 1;
     MAGIC *mg = (MAGIC *) NULL;
 
@@ -4154,9 +4259,9 @@ PP(pp_split)
        ary = GvAVn((GV*)pm->op_pmreplroot);
     else if (gimme != G_ARRAY)
 #ifdef USE_THREADS
-       ary = (AV*)curpad[0];
+       ary = (AV*)PL_curpad[0];
 #else
-       ary = GvAVn(defgv);
+       ary = GvAVn(PL_defgv);
 #endif /* USE_THREADS */
     else
        ary = Nullav;
@@ -4174,14 +4279,14 @@ PP(pp_split)
            if (!AvREAL(ary)) {
                AvREAL_on(ary);
                for (i = AvFILLp(ary); i >= 0; i--)
-                   AvARRAY(ary)[i] = &sv_undef;        /* don't free mere refs */
+                   AvARRAY(ary)[i] = &PL_sv_undef;     /* don't free mere refs */
            }
            /* temporarily switch stacks */
-           SWITCHSTACK(curstack, ary);
+           SWITCHSTACK(PL_curstack, ary);
            make_mortal = 0;
        }
     }
-    base = SP - stack_base;
+    base = SP - PL_stack_base;
     orig = s;
     if (pm->op_pmflags & PMf_SKIPWHITE) {
        if (pm->op_pmflags & PMf_LOCALE) {
@@ -4194,8 +4299,8 @@ PP(pp_split)
        }
     }
     if (pm->op_pmflags & (PMf_MULTILINE|PMf_SINGLELINE)) {
-       SAVEINT(multiline);
-       multiline = pm->op_pmflags & PMf_MULTILINE;
+       SAVEINT(PL_multiline);
+       PL_multiline = pm->op_pmflags & PMf_MULTILINE;
     }
 
     if (!limit)
@@ -4261,7 +4366,7 @@ PP(pp_split)
 #ifndef lint
            while (s < strend && --limit &&
              (m=fbm_instr((unsigned char*)s, (unsigned char*)strend,
-                   rx->check_substr)) )
+                   rx->check_substr, 0)) )
 #endif
            {
                dstr = NEWSV(31, m-s);
@@ -4276,7 +4381,7 @@ PP(pp_split)
     else {
        maxiters += (strend - s) * rx->nparens;
        while (s < strend && --limit &&
-              regexec_flags(rx, s, strend, orig, 1, Nullsv, NULL, 0))
+              CALLREGEXEC(rx, s, strend, orig, 1, Nullsv, NULL, 0))
        {
            TAINT_IF(RX_MATCH_TAINTED(rx));
            if (rx->subbase
@@ -4313,7 +4418,7 @@ PP(pp_split)
     }
 
     LEAVE_SCOPE(oldsave);
-    iters = (SP - stack_base) - base;
+    iters = (SP - PL_stack_base) - base;
     if (iters > maxiters)
        DIE("Split loop");
 
@@ -4357,7 +4462,7 @@ PP(pp_split)
                EXTEND(SP, iters);
                for (i=0; i < iters; i++) {
                    SV **svp = av_fetch(ary, i, FALSE);
-                   PUSHs((svp) ? *svp : &sv_undef);
+                   PUSHs((svp) ? *svp : &PL_sv_undef);
                }
                RETURN;
            }
@@ -4389,7 +4494,7 @@ unlock_condpair(void *svv)
        croak("panic: unlock_condpair unlocking mutex that we don't own");
     MgOWNER(mg) = 0;
     COND_SIGNAL(MgOWNERCONDP(mg));
-    DEBUG_L(PerlIO_printf(PerlIO_stderr(), "0x%lx: unlock 0x%lx\n",
+    DEBUG_S(PerlIO_printf(PerlIO_stderr(), "0x%lx: unlock 0x%lx\n",
                          (unsigned long)thr, (unsigned long)svv);)
     MUTEX_UNLOCK(MgMUTEXP(mg));
 }
@@ -4414,7 +4519,7 @@ PP(pp_lock)
        while (MgOWNER(mg))
            COND_WAIT(MgOWNERCONDP(mg), MgMUTEXP(mg));
        MgOWNER(mg) = thr;
-       DEBUG_L(PerlIO_printf(PerlIO_stderr(), "0x%lx: pp_lock lock 0x%lx\n",
+       DEBUG_S(PerlIO_printf(PerlIO_stderr(), "0x%lx: pp_lock lock 0x%lx\n",
                              (unsigned long)thr, (unsigned long)sv);)
        MUTEX_UNLOCK(MgMUTEXP(mg));
        SvREFCNT_inc(sv);       /* keep alive until magic_mutexfree */
@@ -4433,11 +4538,11 @@ PP(pp_threadsv)
 {
     djSP;
 #ifdef USE_THREADS
-    EXTEND(sp, 1);
-    if (op->op_private & OPpLVAL_INTRO)
-       PUSHs(*save_threadsv(op->op_targ));
+    EXTEND(SP, 1);
+    if (PL_op->op_private & OPpLVAL_INTRO)
+       PUSHs(*save_threadsv(PL_op->op_targ));
     else
-       PUSHs(THREADSV(op->op_targ));
+       PUSHs(THREADSV(PL_op->op_targ));
     RETURN;
 #else
     DIE("tried to access per-thread data in non-threaded perl");