First stab at 5.003 -> 5.004 integration.
Malcolm Beattie [Sun, 25 May 1997 10:31:21 +0000 (10:31 +0000)]
p4raw-id: //depot/perl@18

13 files changed:
1  2 
av.c
doop.c
ext/DB_File/DB_File.xs
global.sym
interp.sym
keywords.pl
op.c
perl.c
perl.h
pp.c
pp_hot.c
proto.h
toke.c

diff --cc av.c
Simple merge
diff --cc doop.c
--- 1/doop.c
--- 2/doop.c
+++ b/doop.c
@@@ -622,28 -448,45 +448,49 @@@ dARG
  {
      dSP;
      HV *hv = (HV*)POPs;
-     I32 i;
      register HE *entry;
-     char *tmps;
      SV *tmpstr;
+     I32 gimme = GIMME_V;
      I32 dokeys =   (op->op_type == OP_KEYS);
      I32 dovalues = (op->op_type == OP_VALUES);
 -
 +    I32 realhv = (SvTYPE(hv) == SVt_PVHV);
 +    
      if (op->op_type == OP_RV2HV || op->op_type == OP_PADHV) 
        dokeys = dovalues = TRUE;
  
-     if (!hv)
+     if (!hv) {
+       if (op->op_flags & OPf_MOD) {   /* lvalue */
+           dTARGET;            /* make sure to clear its target here */
+           if (SvTYPE(TARG) == SVt_PVLV)
+               LvTARG(TARG) = Nullsv;
+           PUSHs(TARG);
+       }
        RETURN;
+     }
  
 -    (void)hv_iterinit(hv);    /* always reset iterator regardless */
 +    if (realhv)
 +      (void)hv_iterinit(hv);  /* always reset iterator regardless */
 +    else
 +      (void)avhv_iterinit((AV*)hv);
-     
-     if (GIMME != G_ARRAY) {
+     if (gimme == G_VOID)
+       RETURN;
+     if (gimme == G_SCALAR) {
+       I32 i;
        dTARGET;
  
+       if (op->op_flags & OPf_MOD) {   /* lvalue */
+           if (SvTYPE(TARG) < SVt_PVLV) {
+               sv_upgrade(TARG, SVt_PVLV);
+               sv_magic(TARG, Nullsv, 'k', Nullch, 0);
+           }
+           LvTYPE(TARG) = 'k';
+           LvTARG(TARG) = (SV*)hv;
+           PUSHs(TARG);
+           RETURN;
+       }
        if (!SvRMAGICAL(hv) || !mg_find((SV*)hv,'P'))
            i = HvKEYS(hv);
        else {
      EXTEND(sp, HvMAX(hv) * (dokeys + dovalues));
  
      PUTBACK;  /* hv_iternext and hv_iterval might clobber stack_sp */
 -    while (entry = hv_iternext(hv)) {
 +    while (entry = realhv ? hv_iternext(hv) : avhv_iternext((AV*)hv)) {
        SPAGAIN;
-       if (dokeys) {
-           tmps = hv_iterkey(entry,&i);        /* won't clobber stack_sp */
-           if (!i)
-               tmps = "";
-           XPUSHs(sv_2mortal(newSVpv(tmps,i)));
-       }
+       if (dokeys)
+           XPUSHs(hv_iterkeysv(entry));        /* won't clobber stack_sp */
        if (dovalues) {
-           tmpstr = NEWSV(45,0);
+           tmpstr = sv_newmortal();
            PUTBACK;
 -          sv_setsv(tmpstr,hv_iterval(hv,entry));
 +          sv_setsv(tmpstr,realhv ?
 +                   hv_iterval(hv,entry) : avhv_iterval((AV*)hv,entry));
+           DEBUG_H(sv_setpvf(tmpstr, "%lu%%%d=%lu",
+                           (unsigned long)HeHASH(entry),
+                           HvMAX(hv)+1,
+                           (unsigned long)(HeHASH(entry) & HvMAX(hv))));
            SPAGAIN;
-           DEBUG_H( {
-               sprintf(buf,"%d%%%d=%d\n",entry->hent_hash,
-                   HvMAX(hv)+1,entry->hent_hash & HvMAX(hv));
-               sv_setpv(tmpstr,buf);
-           } )
-           XPUSHs(sv_2mortal(tmpstr));
+           XPUSHs(tmpstr);
        }
        PUTBACK;
      }
@@@ -717,9 -816,6 +816,16 @@@ db_DoTie_(isHASH, dbtype, name=undef, f
        OUTPUT: 
            RETVAL
  
++>>>> ORIGINAL VERSION
++BOOT:
++    newXS("DB_File::TIEARRAY", XS_DB_File_db_TIEHASH, file);
++
++==== THEIR VERSION
++==== YOUR VERSION
 +BOOT:
 +    newXS("DB_File::TIEARRAY", XS_DB_File_TIEHASH, file);
 +
++<<<<
  int
  db_DESTROY(db)
        DB_File         db
diff --cc global.sym
Simple merge
diff --cc interp.sym
Simple merge
diff --cc keywords.pl
Simple merge
diff --cc op.c
--- 1/op.c
--- 2/op.c
+++ b/op.c
@@@ -2872,60 -3348,71 +3357,76 @@@ OP *block
      CvSTART(cv) = LINKLIST(CvROOT(cv));
      CvROOT(cv)->op_next = 0;
      peep(CvSTART(cv));
-     if (s = strrchr(name,':'))
-       s++;
-     else
-       s = name;
-     if (strEQ(s, "BEGIN") && !error_count) {
-       line_t oldline = compiling.cop_line;
-       SV *oldrs = rs;
  
-       ENTER;
-       SAVESPTR(compiling.cop_filegv);
-       SAVEI32(perldb);
-       if (!beginav)
-           beginav = newAV();
-       av_push(beginav, (SV *)cv);
-       DEBUG_x( dump_sub(gv) );
-       rs = SvREFCNT_inc(nrs);
-       GvCV(gv) = 0;
-       calllist(beginav);
-       SvREFCNT_dec(rs);
-       rs = oldrs;
-       curcop = &compiling;
-       curcop->cop_line = oldline;     /* might have recursed to yylex */
-       LEAVE;
-     }
-     else if (strEQ(s, "END") && !error_count) {
-       if (!endav)
-           endav = newAV();
-       av_unshift(endav, 1);
-       av_store(endav, 0, SvREFCNT_inc(cv));
-     }
-     else if (strEQ(s, "RESTART") && !error_count) {
-       if (!restartav)
-           restartav = newAV();
-       av_push(restartav, SvREFCNT_inc(cv));
-     }
-     if (perldb && curstash != debstash) {
-       SV *sv;
-       SV *tmpstr = sv_newmortal();
+     if (name) {
+       char *s;
+       if (perldb && curstash != debstash) {
+           SV *sv = NEWSV(0,0);
+           SV *tmpstr = sv_newmortal();
+           static GV *db_postponed;
+           CV *cv;
+           HV *hv;
+           sv_setpvf(sv, "%_:%ld-%ld",
+                   GvSV(curcop->cop_filegv),
+                   (long)subline, (long)curcop->cop_line);
+           gv_efullname3(tmpstr, gv, Nullch);
+           hv_store(GvHV(DBsub), SvPVX(tmpstr), SvCUR(tmpstr), sv, 0);
+           if (!db_postponed) {
+               db_postponed = gv_fetchpv("DB::postponed", GV_ADDMULTI, SVt_PVHV);
+           }
+           hv = GvHVn(db_postponed);
+           if (HvFILL(hv) > 0 && hv_exists(hv, SvPVX(tmpstr), SvCUR(tmpstr))
+                 && (cv = GvCV(db_postponed))) {
+               dSP;
+               PUSHMARK(sp);
+               XPUSHs(tmpstr);
+               PUTBACK;
+               perl_call_sv((SV*)cv, G_DISCARD);
+           }
+       }
  
-       sprintf(buf,"%s:%ld",SvPVX(GvSV(curcop->cop_filegv)), (long)subline);
-       sv = newSVpv(buf,0);
-       sv_catpv(sv,"-");
-       sprintf(buf,"%ld",(long)curcop->cop_line);
-       sv_catpv(sv,buf);
-       gv_efullname(tmpstr,gv);
-       hv_store(GvHV(DBsub), SvPVX(tmpstr), SvCUR(tmpstr), sv, 0);
+       if ((s = strrchr(name,':')))
+           s++;
+       else
+           s = name;
+       if (strEQ(s, "BEGIN")) {
+           I32 oldscope = scopestack_ix;
+           ENTER;
+           SAVESPTR(compiling.cop_filegv);
+           SAVEI16(compiling.cop_line);
+           SAVEI32(perldb);
+           save_svref(&rs);
+           sv_setsv(rs, nrs);
+           if (!beginav)
+               beginav = newAV();
+           DEBUG_x( dump_sub(gv) );
+           av_push(beginav, (SV *)cv);
+           GvCV(gv) = 0;
+           call_list(oldscope, beginav);
+           curcop = &compiling;
+           LEAVE;
+       }
+       else if (strEQ(s, "END") && !error_count) {
+           if (!endav)
+               endav = newAV();
+           av_unshift(endav, 1);
+           av_store(endav, 0, (SV *)cv);
+           GvCV(gv) = 0;
+       }
++      else if (strEQ(s, "RESTART") && !error_count) {
++          if (!restartav)
++              restartav = newAV();
++          av_push(restartav, SvREFCNT_inc(cv));
++      }
      }
-     op_free(op);
+   done:
      copline = NOLINE;
      LEAVE_SCOPE(floor);
-     if (!op) {
-       GvCV(gv) = 0;   /* Will remember in SVOP instead. */
-       CvANON_on(cv);
-     }
      return cv;
  }
  
@@@ -2978,38 -3464,39 +3478,44 @@@ char *filename
      else {
        cv = (CV*)NEWSV(1105,0);
        sv_upgrade((SV *)cv, SVt_PVCV);
+       if (name) {
+           GvCV(gv) = cv;
+           GvCVGEN(gv) = 0;
+           sub_generation++;
+       }
      }
-     GvCV(gv) = cv;
-     CvGV(cv) = SvREFCNT_inc(gv);
-     GvCVGEN(gv) = 0;
+     CvGV(cv) = (GV*)SvREFCNT_inc(gv);
      CvFILEGV(cv) = gv_fetchfile(filename);
      CvXSUB(cv) = subaddr;
-     if (!name)
-       s = "__ANON__";
-     else if (s = strrchr(name,':'))
-       s++;
+     if (name) {
+       char *s = strrchr(name,':');
+       if (s)
+           s++;
+       else
+           s = name;
+       if (strEQ(s, "BEGIN")) {
+           if (!beginav)
+               beginav = newAV();
+           av_push(beginav, (SV *)cv);
+           GvCV(gv) = 0;
+       }
+       else if (strEQ(s, "END")) {
+           if (!endav)
+               endav = newAV();
+           av_unshift(endav, 1);
+           av_store(endav, 0, (SV *)cv);
+           GvCV(gv) = 0;
+       }
++      else if (strEQ(s, "RESTART")) {
++          if (!restartav)
++              restartav = newAV();
++          av_push(restartav, (SV *)cv);
++      }
+     }
      else
-       s = name;
-     if (strEQ(s, "BEGIN")) {
-       if (!beginav)
-           beginav = newAV();
-       av_push(beginav, SvREFCNT_inc(gv));
-     }
-     else if (strEQ(s, "END")) {
-       if (!endav)
-           endav = newAV();
-       av_unshift(endav, 1);
-       av_store(endav, 0, SvREFCNT_inc(gv));
-     }
-     else if (strEQ(s, "RESTART")) {
-       if (!restartav)
-           restartav = newAV();
-       av_push(restartav, SvREFCNT_inc(gv));
-     }
-     if (!name) {
-       GvCV(gv) = 0;   /* Will remember elsewhere instead. */
        CvANON_on(cv);
-     }
      return cv;
  }
  
diff --cc perl.c
Simple merge
diff --cc perl.h
--- 1/perl.h
--- 2/perl.h
+++ b/perl.h
@@@ -1314,9 -1799,7 +1800,8 @@@ IEXT HV *       Idebstash;      /* symbol table fo
  IEXT SV *     Icurstname;     /* name of current package */
  IEXT AV *     Ibeginav;       /* names of BEGIN subroutines */
  IEXT AV *     Iendav;         /* names of END subroutines */
 +IEXT AV *     Irestartav;     /* names of RESTART subroutines */
- IEXT AV *     Ipad;           /* storage for lexically scoped temporaries */
- IEXT AV *     Ipadname;       /* variable names for "my" variables */
+ IEXT HV *     Istrtab;        /* shared string table */
  
  /* memory management */
  IEXT SV **    Itmps_stack;
diff --cc pp.c
--- 1/pp.c
--- 2/pp.c
+++ b/pp.c
@@@ -1789,26 -2085,18 +2085,22 @@@ PP(pp_each
      dSP; dTARGET;
      HV *hash = (HV*)POPs;
      HE *entry;
-     I32 i;
-     char *tmps;
+     I32 gimme = GIMME_V;
 +    I32 realhv = (SvTYPE(hash) == SVt_PVHV);
      
      PUTBACK;
 -    entry = hv_iternext(hash);                /* might clobber stack_sp */
 +    /* might clobber stack_sp */
 +    entry = realhv ? hv_iternext(hash) : avhv_iternext((AV*)hash);
      SPAGAIN;
  
      EXTEND(SP, 2);
      if (entry) {
-       tmps = hv_iterkey(entry, &i);              /* won't clobber stack_sp */
-       if (!i)
-           tmps = "";
-       PUSHs(sv_2mortal(newSVpv(tmps, i)));
-       if (GIMME == G_ARRAY) {
+       PUSHs(hv_iterkeysv(entry));     /* won't clobber stack_sp */
+       if (gimme == G_ARRAY) {
            PUTBACK;
 -          sv_setsv(TARG, hv_iterval(hash, entry));  /* might hit stack_sp */
 +          /* might clobber stack_sp */
 +          sv_setsv(TARG, realhv ?
 +                   hv_iterval(hash, entry) : avhv_iterval((AV*)hash, entry));
            SPAGAIN;
            PUSHs(TARG);
        }
@@@ -1832,24 -2120,39 +2124,43 @@@ PP(pp_keys
  PP(pp_delete)
  {
      dSP;
+     I32 gimme = GIMME_V;
+     I32 discard = (gimme == G_VOID) ? G_DISCARD : 0;
      SV *sv;
-     SV *tmpsv = POPs;
-     HV *hv = (HV*)POPs;
-     char *tmps;
-     STRLEN len;
-     I32 flags = op->op_private & OPpLEAVE_VOID ? G_DISCARD : 0;
-     
-     tmps = SvPV(tmpsv, len);
-     if (SvTYPE(hv) == SVt_PVHV)
-       sv = hv_delete(hv, tmps, len, flags);
-     else if (SvTYPE(hv) == SVt_PVAV) {
-       sv = avhv_delete((AV*)hv, tmps, len, flags);
-     } else {
-       DIE("Not a HASH reference");
+     HV *hv;
+     if (op->op_private & OPpSLICE) {
+       dMARK; dORIGMARK;
+       hv = (HV*)POPs;
 -      if (SvTYPE(hv) != SVt_PVHV)
 -          DIE("Not a HASH reference");
++      U32 hvtype = SvTYPE(hv);
+       while (++MARK <= SP) {
 -          sv = hv_delete_ent(hv, *MARK, discard, 0);
++          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;
+       }
+       if (discard)
+           SP = ORIGMARK;
+       else if (gimme == G_SCALAR) {
+           MARK = ORIGMARK;
+           *++MARK = *SP;
+           SP = MARK;
+       }
+     }
+     else {
+       SV *keysv = POPs;
+       hv = (HV*)POPs;
+       if (SvTYPE(hv) != SVt_PVHV)
+           DIE("Not a HASH reference");
+       sv = hv_delete_ent(hv, keysv, discard, 0);
+       if (!sv)
+           sv = &sv_undef;
+       if (!discard)
+           PUSHs(sv);
      }
-     if (!sv)
-       RETPUSHUNDEF;
-     PUSHs(sv);
      RETURN;
  }
  
@@@ -1858,43 -2161,34 +2169,43 @@@ PP(pp_exists
      dSP;
      SV *tmpsv = POPs;
      HV *hv = (HV*)POPs;
-     char *tmps;
--    STRLEN len;
-     tmps = SvPV(tmpsv, len);
 -    if (SvTYPE(hv) != SVt_PVHV) {
 +    if (SvTYPE(hv) == SVt_PVHV) {
-       if (hv_exists(hv, tmps, len))
++      if (hv_exists_ent(hv, tmpsv, 0))
 +          RETPUSHYES;
 +    } else if (SvTYPE(hv) == SVt_PVAV) {
-       if (avhv_exists((AV*)hv, tmps, len))
++      if (avhv_exists_ent((AV*)hv, tmpsv, 0))
 +          RETPUSHYES;
 +    } else {
        DIE("Not a HASH reference");
      }
 -    if (hv_exists_ent(hv, tmpsv, 0))
 -      RETPUSHYES;
      RETPUSHNO;
  }
  
  PP(pp_hslice)
  {
      dSP; dMARK; dORIGMARK;
-     register SV **svp;
+     register HE *he;
      register HV *hv = (HV*)POPs;
      register I32 lval = op->op_flags & OPf_MOD;
 +    I32 realhv = (SvTYPE(hv) == SVt_PVHV);
  
 -    if (SvTYPE(hv) == SVt_PVHV) {
 +    if (realhv || SvTYPE(hv) == SVt_PVAV) {
        while (++MARK <= SP) {
-           STRLEN keylen;
-           char *key = SvPV(*MARK, keylen);
-           svp = realhv ? hv_fetch(hv, key, keylen, lval)
-               : avhv_fetch((AV*)hv, key, keylen, lval);
+           SV *keysv = *MARK;
 -
 -          he = hv_fetch_ent(hv, keysv, lval, 0);
++          SV **svp;
++          if (realhv) {
++              he = hv_fetch_ent(hv, keysv, lval, 0);
++              svp = he ? &HeVAL(he) : 0;
++          } else {
++              svp = avhv_fetch_ent((AV*)hv, keysv, lval);
++          }
            if (lval) {
-               if (!svp || *svp == &sv_undef)
-                   DIE(no_helem, key);
+               if (!he || HeVAL(he) == &sv_undef)
+                   DIE(no_helem, SvPV(keysv, na));
                if (op->op_private & OPpLVAL_INTRO)
-                   save_svref(svp);
+                   save_svref(&HeVAL(he));
            }
-           *MARK = svp ? *svp : &sv_undef;
+           *MARK = he ? HeVAL(he) : &sv_undef;
        }
      }
      if (GIMME != G_ARRAY) {
diff --cc pp_hot.c
+++ b/pp_hot.c
@@@ -526,14 -564,11 +564,13 @@@ PP(pp_rv2hv
      }
      else {
        dTARGET;
 +      /* This bit is OK even when hv is really an AV */
-       if (HvFILL(hv)) {
-           sprintf(buf, "%d/%d", HvFILL(hv), HvMAX(hv)+1);
-           sv_setpv(TARG, buf);
-       }
+       if (HvFILL(hv))
+           sv_setpvf(TARG, "%ld/%ld",
+                     (long)HvFILL(hv), (long)HvMAX(hv) + 1);
        else
            sv_setiv(TARG, 0);
 +      
        SETTARG;
        RETURN;
      }
@@@ -1193,29 -1260,41 +1262,50 @@@ PP(pp_enter
  PP(pp_helem)
  {
      dSP;
-     SV** svp;
+     HE* he;
++    SV **svp;
      SV *keysv = POPs;
-     STRLEN keylen;
-     char *key = SvPV(keysv, keylen);
      HV *hv = (HV*)POPs;
-     I32 lval = op->op_flags & OPf_MOD;
+     U32 lval = op->op_flags & OPf_MOD;
+     U32 defer = op->op_private & OPpLVAL_DEFER;
  
-     if (SvTYPE(hv) == SVt_PVHV)
-       svp = hv_fetch(hv, key, keylen, lval);
-     else if (SvTYPE(hv) == SVt_PVAV)
-       svp = avhv_fetch((AV*)hv, key, keylen, lval);
 -    if (SvTYPE(hv) != SVt_PVHV)
++    if (SvTYPE(hv) == SVt_PVHV) {
++      he = hv_fetch_ent(hv, keysv, lval && !defer, 0);
++      svp = he ? &Heval(he) : 0;
++    }
++    else if (SvTYPE(hv) == SVt_PVAV) {
++      svp = avhv_fetch_ent((AV*)hv, keysv, lval);
++    }
 +    else {
        RETPUSHUNDEF;
 -    he = hv_fetch_ent(hv, keysv, lval && !defer, 0);
 +    }
++<<<<
      if (lval) {
-       if (!svp || *svp == &sv_undef)
-           DIE(no_helem, key);
-       if (op->op_private & OPpLVAL_INTRO)
-           save_svref(svp);
-       else if (op->op_private & (OPpDEREF_HV|OPpDEREF_AV))
-           provide_ref(op, *svp);
 -      if (!he || HeVAL(he) == &sv_undef) {
++      if (svp || *svp == &sv_undef) {
+           SV* lv;
+           SV* key2;
+           if (!defer)
+               DIE(no_helem, SvPV(keysv, na));
+           lv = sv_newmortal();
+           sv_upgrade(lv, SVt_PVLV);
+           LvTYPE(lv) = 'y';
+           sv_magic(lv, key2 = newSVsv(keysv), 'y', Nullch, 0);
+           SvREFCNT_dec(key2); /* sv_magic() increments refcount */
+           LvTARG(lv) = SvREFCNT_inc(hv);
+           LvTARGLEN(lv) = 1;
+           PUSHs(lv);
+           RETURN;
+       }
+       if (op->op_private & OPpLVAL_INTRO) {
 -          if (HvNAME(hv) && isGV(HeVAL(he)))
 -              save_gp((GV*)HeVAL(he), !(op->op_flags & OPf_SPECIAL));
++          if (HvNAME(hv) && isGV(*svp))
++              save_gp((GV*)*svp, !(op->op_flags & OPf_SPECIAL));
+           else
 -              save_svref(&HeVAL(he));
++              save_svref(svp);
+       }
+       else if (op->op_private & OPpDEREF)
 -          vivify_ref(HeVAL(he), op->op_private & OPpDEREF);
++          vivify_ref(*svp, op->op_private & OPpDEREF);
      }
 -    PUSHs(he ? HeVAL(he) : &sv_undef);
 +    PUSHs(svp ? *svp : &sv_undef);
      RETURN;
  }
  
diff --cc proto.h
Simple merge
diff --cc toke.c
--- 1/toke.c
--- 2/toke.c
+++ b/toke.c
@@@ -2931,19 -3120,7 +3121,18 @@@ yylex(
  
        case KEY_my:
            in_my = TRUE;
-           yylval.ival = 1;
 +          s = skipspace(s);
 +          if (isIDFIRST(*s)) {
 +              s = scan_word(s, tokenbuf, TRUE, &len);
 +              in_my_stash = gv_stashpv(tokenbuf, FALSE);
 +              if (!in_my_stash) {
 +                  char tmpbuf[1024];
 +                  bufptr = s;
 +                  sprintf(tmpbuf, "No such class %.1000s", tokenbuf);
 +                  yyerror(tmpbuf);
 +              }
 +          }
-           OPERATOR(LOCAL);
+           OPERATOR(MY);
  
        case KEY_next:
            s = force_word(s,WORD,TRUE,FALSE,FALSE);
@@@ -5003,15 -5287,13 +5302,14 @@@ char *s
          multi_end = 0;
      }
      if (in_eval & 2)
-       warn("%s",buf);
+       warn("%_", msg);
      else if (in_eval)
-       sv_catpv(GvSV(errgv),buf);
+       sv_catsv(GvSV(errgv), msg);
      else
-       fputs(buf,stderr);
+       PerlIO_write(PerlIO_stderr(), SvPVX(msg), SvCUR(msg));
      if (++error_count >= 10)
-       croak("%s has too many errors.\n",
-       SvPVX(GvSV(curcop->cop_filegv)));
+       croak("%_ has too many errors.\n", GvSV(curcop->cop_filegv));
      in_my = 0;
 +    in_my_stash = Nullhv;
      return 0;
  }