This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
avoid warnings in change#4839
[perl5.git] / av.c
diff --git a/av.c b/av.c
index 5242ffc..af8296a 100644 (file)
--- a/av.c
+++ b/av.c
@@ -1,6 +1,6 @@
 /*    av.c
  *
- *    Copyright (c) 1991-1997, Larry Wall
+ *    Copyright (c) 1991-1999, 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.
  */
 
 #include "EXTERN.h"
+#define PERL_IN_AV_C
 #include "perl.h"
 
 void
-av_reify(AV *av)
+Perl_av_reify(pTHX_ AV *av)
 {
     I32 key;
     SV* sv;
@@ -24,8 +25,8 @@ av_reify(AV *av)
     if (AvREAL(av))
        return;
 #ifdef DEBUGGING
-    if (SvRMAGICAL(av) && mg_find((SV*)av,'P'))
-       warn("av_reify called on tied array");
+    if (SvTIED_mg((SV*)av, 'P') && ckWARN_d(WARN_DEBUGGING))
+       Perl_warner(aTHX_ WARN_DEBUGGING, "av_reify called on tied array");
 #endif
     key = AvMAX(av) + 1;
     while (key > AvFILLp(av) + 1)
@@ -46,21 +47,21 @@ av_reify(AV *av)
 }
 
 void
-av_extend(AV *av, I32 key)
+Perl_av_extend(pTHX_ AV *av, I32 key)
 {
     dTHR;                      /* only necessary if we have to extend stack */
     MAGIC *mg;
-    if (SvRMAGICAL(av) && (mg = mg_find((SV*)av,'P'))) {
+    if (mg = SvTIED_mg((SV*)av, 'P')) {
        dSP;
        ENTER;
        SAVETMPS;
        PUSHSTACKi(PERLSI_MAGIC);
        PUSHMARK(SP);
        EXTEND(SP,2);
-       PUSHs(mg->mg_obj);
+       PUSHs(SvTIED_obj((SV*)av, mg));
        PUSHs(sv_2mortal(newSViv(key+1)));
         PUTBACK;
-       perl_call_method("EXTEND", G_SCALAR|G_DISCARD);
+       call_method("EXTEND", G_SCALAR|G_DISCARD);
        POPSTACK;
        FREETMPS;
        LEAVE;
@@ -90,7 +91,8 @@ av_extend(AV *av, I32 key)
        else {
            if (AvALLOC(av)) {
 #ifndef STRANGE_MALLOC
-               U32 bytes;
+               MEM_SIZE bytes;
+               IV itmp;
 #endif
 
 #if defined(MYMALLOC) && !defined(PURIFY) && !defined(LEAKTEST)
@@ -106,13 +108,14 @@ av_extend(AV *av, I32 key)
 #else
                bytes = (newmax + 1) * sizeof(SV*);
 #define MALLOC_OVERHEAD 16
-               tmp = MALLOC_OVERHEAD;
-               while (tmp - MALLOC_OVERHEAD < bytes)
-                   tmp += tmp;
-               tmp -= MALLOC_OVERHEAD;
-               tmp /= sizeof(SV*);
-               assert(tmp > newmax);
-               newmax = tmp - 1;
+               itmp = MALLOC_OVERHEAD;
+               while (itmp - MALLOC_OVERHEAD < bytes)
+                   itmp += itmp;
+               itmp -= MALLOC_OVERHEAD;
+               itmp /= sizeof(SV*);
+               assert(itmp > newmax);
+               newmax = itmp - 1;
+               assert(newmax >= AvMAX(av));
                New(2,ary, newmax+1, SV*);
                Copy(AvALLOC(av), ary, AvMAX(av)+1, SV*);
                if (AvMAX(av) > 64)
@@ -149,7 +152,7 @@ av_extend(AV *av, I32 key)
 }
 
 SV**
-av_fetch(register AV *av, I32 key, I32 lval)
+Perl_av_fetch(pTHX_ register AV *av, I32 key, I32 lval)
 {
     SV *sv;
 
@@ -175,10 +178,7 @@ av_fetch(register AV *av, I32 key, I32 lval)
     if (key > AvFILLp(av)) {
        if (!lval)
            return 0;
-       if (AvREALISH(av))
-           sv = NEWSV(5,0);
-       else
-           sv = sv_newmortal();
+       sv = NEWSV(5,0);
        return av_store(av,key,sv);
     }
     if (AvARRAY(av)[key] == &PL_sv_undef) {
@@ -199,7 +199,7 @@ av_fetch(register AV *av, I32 key, I32 lval)
 }
 
 SV**
-av_store(register AV *av, I32 key, SV *val)
+Perl_av_store(pTHX_ register AV *av, I32 key, SV *val)
 {
     SV** ary;
     U32  fill;
@@ -217,7 +217,7 @@ av_store(register AV *av, I32 key, SV *val)
     }
 
     if (SvREADONLY(av) && key >= AvFILL(av))
-       croak(no_modify);
+       Perl_croak(aTHX_ PL_no_modify);
 
     if (SvRMAGICAL(av)) {
        if (mg_find((SV*)av,'P')) {
@@ -258,7 +258,7 @@ av_store(register AV *av, I32 key, SV *val)
 }
 
 AV *
-newAV(void)
+Perl_newAV(pTHX)
 {
     register AV *av;
 
@@ -272,7 +272,7 @@ newAV(void)
 }
 
 AV *
-av_make(register I32 size, register SV **strp)
+Perl_av_make(pTHX_ register I32 size, register SV **strp)
 {
     register AV *av;
     register I32 i;
@@ -298,7 +298,7 @@ av_make(register I32 size, register SV **strp)
 }
 
 AV *
-av_fake(register I32 size, register SV **strp)
+Perl_av_fake(pTHX_ register I32 size, register SV **strp)
 {
     register AV *av;
     register SV** ary;
@@ -321,14 +321,14 @@ av_fake(register I32 size, register SV **strp)
 }
 
 void
-av_clear(register AV *av)
+Perl_av_clear(pTHX_ register AV *av)
 {
     register I32 key;
     SV** ary;
 
 #ifdef DEBUGGING
-    if (SvREFCNT(av) <= 0) {
-       warn("Attempt to clear deleted array");
+    if (SvREFCNT(av) <= 0 && ckWARN_d(WARN_DEBUGGING)) {
+       Perl_warner(aTHX_ WARN_DEBUGGING, "Attempt to clear deleted array");
     }
 #endif
     if (!av)
@@ -336,7 +336,7 @@ av_clear(register AV *av)
     /*SUPPRESS 560*/
 
     if (SvREADONLY(av))
-       croak(no_modify);
+       Perl_croak(aTHX_ PL_no_modify);
 
     /* Give any tie a chance to cleanup first */
     if (SvRMAGICAL(av))
@@ -362,7 +362,7 @@ av_clear(register AV *av)
 }
 
 void
-av_undef(register AV *av)
+Perl_av_undef(pTHX_ register AV *av)
 {
     register I32 key;
 
@@ -371,7 +371,7 @@ av_undef(register AV *av)
     /*SUPPRESS 560*/
 
     /* Give any tie a chance to cleanup first */
-    if (SvRMAGICAL(av) && mg_find((SV*)av,'P')) 
+    if (SvTIED_mg((SV*)av, 'P')) 
        av_fill(av, -1);   /* mg_clear() ? */
 
     if (AvREAL(av)) {
@@ -390,24 +390,24 @@ av_undef(register AV *av)
 }
 
 void
-av_push(register AV *av, SV *val)
+Perl_av_push(pTHX_ register AV *av, SV *val)
 {             
     MAGIC *mg;
     if (!av)
        return;
     if (SvREADONLY(av))
-       croak(no_modify);
+       Perl_croak(aTHX_ PL_no_modify);
 
-    if (SvRMAGICAL(av) && (mg = mg_find((SV*)av,'P'))) {
+    if (mg = SvTIED_mg((SV*)av, 'P')) {
        dSP;
        PUSHSTACKi(PERLSI_MAGIC);
        PUSHMARK(SP);
        EXTEND(SP,2);
-       PUSHs(mg->mg_obj);
+       PUSHs(SvTIED_obj((SV*)av, mg));
        PUSHs(val);
        PUTBACK;
        ENTER;
-       perl_call_method("PUSH", G_SCALAR|G_DISCARD);
+       call_method("PUSH", G_SCALAR|G_DISCARD);
        LEAVE;
        POPSTACK;
        return;
@@ -416,7 +416,7 @@ av_push(register AV *av, SV *val)
 }
 
 SV *
-av_pop(register AV *av)
+Perl_av_pop(pTHX_ register AV *av)
 {
     SV *retval;
     MAGIC* mg;
@@ -424,15 +424,15 @@ av_pop(register AV *av)
     if (!av || AvFILL(av) < 0)
        return &PL_sv_undef;
     if (SvREADONLY(av))
-       croak(no_modify);
-    if (SvRMAGICAL(av) && (mg = mg_find((SV*)av,'P'))) {
+       Perl_croak(aTHX_ PL_no_modify);
+    if (mg = SvTIED_mg((SV*)av, 'P')) {
        dSP;    
        PUSHSTACKi(PERLSI_MAGIC);
        PUSHMARK(SP);
-       XPUSHs(mg->mg_obj);
+       XPUSHs(SvTIED_obj((SV*)av, mg));
        PUTBACK;
        ENTER;
-       if (perl_call_method("POP", G_SCALAR)) {
+       if (call_method("POP", G_SCALAR)) {
            retval = newSVsv(*PL_stack_sp--);    
        } else {    
            retval = &PL_sv_undef;
@@ -449,7 +449,7 @@ av_pop(register AV *av)
 }
 
 void
-av_unshift(register AV *av, register I32 num)
+Perl_av_unshift(pTHX_ register AV *av, register I32 num)
 {
     register I32 i;
     register SV **ary;
@@ -458,20 +458,20 @@ av_unshift(register AV *av, register I32 num)
     if (!av || num <= 0)
        return;
     if (SvREADONLY(av))
-       croak(no_modify);
+       Perl_croak(aTHX_ PL_no_modify);
 
-    if (SvRMAGICAL(av) && (mg = mg_find((SV*)av,'P'))) {
+    if (mg = SvTIED_mg((SV*)av, 'P')) {
        dSP;
        PUSHSTACKi(PERLSI_MAGIC);
        PUSHMARK(SP);
        EXTEND(SP,1+num);
-       PUSHs(mg->mg_obj);
+       PUSHs(SvTIED_obj((SV*)av, mg));
        while (num-- > 0) {
            PUSHs(&PL_sv_undef);
        }
        PUTBACK;
        ENTER;
-       perl_call_method("UNSHIFT", G_SCALAR|G_DISCARD);
+       call_method("UNSHIFT", G_SCALAR|G_DISCARD);
        LEAVE;
        POPSTACK;
        return;
@@ -502,7 +502,7 @@ av_unshift(register AV *av, register I32 num)
 }
 
 SV *
-av_shift(register AV *av)
+Perl_av_shift(pTHX_ register AV *av)
 {
     SV *retval;
     MAGIC* mg;
@@ -510,15 +510,15 @@ av_shift(register AV *av)
     if (!av || AvFILL(av) < 0)
        return &PL_sv_undef;
     if (SvREADONLY(av))
-       croak(no_modify);
-    if (SvRMAGICAL(av) && (mg = mg_find((SV*)av,'P'))) {
+       Perl_croak(aTHX_ PL_no_modify);
+    if (mg = SvTIED_mg((SV*)av, 'P')) {
        dSP;
        PUSHSTACKi(PERLSI_MAGIC);
        PUSHMARK(SP);
-       XPUSHs(mg->mg_obj);
+       XPUSHs(SvTIED_obj((SV*)av, mg));
        PUTBACK;
        ENTER;
-       if (perl_call_method("SHIFT", G_SCALAR)) {
+       if (call_method("SHIFT", G_SCALAR)) {
            retval = newSVsv(*PL_stack_sp--);            
        } else {    
            retval = &PL_sv_undef;
@@ -539,30 +539,30 @@ av_shift(register AV *av)
 }
 
 I32
-av_len(register AV *av)
+Perl_av_len(pTHX_ register AV *av)
 {
     return AvFILL(av);
 }
 
 void
-av_fill(register AV *av, I32 fill)
+Perl_av_fill(pTHX_ register AV *av, I32 fill)
 {
     MAGIC *mg;
     if (!av)
-       croak("panic: null array");
+       Perl_croak(aTHX_ "panic: null array");
     if (fill < 0)
        fill = -1;
-    if (SvRMAGICAL(av) && (mg = mg_find((SV*)av,'P'))) {
+    if (mg = SvTIED_mg((SV*)av, 'P')) {
        dSP;            
        ENTER;
        SAVETMPS;
        PUSHSTACKi(PERLSI_MAGIC);
        PUSHMARK(SP);
        EXTEND(SP,2);
-       PUSHs(mg->mg_obj);
+       PUSHs(SvTIED_obj((SV*)av, mg));
        PUSHs(sv_2mortal(newSViv(fill+1)));
        PUTBACK;
-       perl_call_method("STORESIZE", G_SCALAR|G_DISCARD);
+       call_method("STORESIZE", G_SCALAR|G_DISCARD);
        POPSTACK;
        FREETMPS;
        LEAVE;
@@ -591,6 +591,86 @@ av_fill(register AV *av, I32 fill)
        (void)av_store(av,fill,&PL_sv_undef);
 }
 
+SV *
+Perl_av_delete(pTHX_ AV *av, I32 key, I32 flags)
+{
+    SV *sv;
+
+    if (!av)
+       return Nullsv;
+    if (SvREADONLY(av))
+       Perl_croak(aTHX_ PL_no_modify);
+    if (key < 0) {
+       key += AvFILL(av) + 1;
+       if (key < 0)
+           return Nullsv;
+    }
+    if (SvRMAGICAL(av)) {
+       SV **svp;
+       if ((mg_find((SV*)av,'P') || mg_find((SV*)av,'D'))
+           && (svp = av_fetch(av, key, TRUE)))
+       {
+           sv = *svp;
+           mg_clear(sv);
+           if (mg_find(sv, 'p')) {
+               sv_unmagic(sv, 'p');            /* No longer an element */
+               return sv;
+           }
+           return Nullsv;                      /* element cannot be deleted */
+       }
+    }
+    if (key > AvFILLp(av))
+       return Nullsv;
+    else {
+       sv = AvARRAY(av)[key];
+       if (key == AvFILLp(av)) {
+           do {
+               AvFILLp(av)--;
+           } while (--key >= 0 && AvARRAY(av)[key] == &PL_sv_undef);
+       }
+       else
+           AvARRAY(av)[key] = &PL_sv_undef;
+       if (SvSMAGICAL(av))
+           mg_set((SV*)av);
+    }
+    if (flags & G_DISCARD) {
+       SvREFCNT_dec(sv);
+       sv = Nullsv;
+    }
+    return sv;
+}
+
+/*
+ * This relies on the fact that uninitialized array elements
+ * are set to &PL_sv_undef.
+ */
+
+bool
+Perl_av_exists(pTHX_ AV *av, I32 key)
+{
+    if (!av)
+       return FALSE;
+    if (key < 0) {
+       key += AvFILL(av) + 1;
+       if (key < 0)
+           return FALSE;
+    }
+    if (SvRMAGICAL(av)) {
+       if (mg_find((SV*)av,'P') || mg_find((SV*)av,'D')) {
+           SV *sv = sv_newmortal();
+           mg_copy((SV*)av, sv, 0, key);
+           magic_existspack(sv, mg_find(sv, 'p'));
+           return SvTRUE(sv);
+       }
+    }
+    if (key <= AvFILLp(av) && AvARRAY(av)[key] != &PL_sv_undef
+       && AvARRAY(av)[key])
+    {
+       return TRUE;
+    }
+    else
+       return FALSE;
+}
 
 /* AVHV: Support for treating arrays as if they were hashes.  The
  * first element of the array should be a hash reference that maps
@@ -598,16 +678,16 @@ av_fill(register AV *av, I32 fill)
  */
 
 STATIC I32
-avhv_index_sv(SV* sv)
+S_avhv_index_sv(pTHX_ SV* sv)
 {
     I32 index = SvIV(sv);
     if (index < 1)
-       croak("Bad index while coercing array into hash");
+       Perl_croak(aTHX_ "Bad index while coercing array into hash");
     return index;    
 }
 
 HV*
-avhv_keys(AV *av)
+Perl_avhv_keys(pTHX_ AV *av)
 {
     SV **keysp = av_fetch(av, 0, FALSE);
     if (keysp) {
@@ -620,39 +700,62 @@ avhv_keys(AV *av)
                return (HV*)sv;
        }
     }
-    croak("Can't coerce array into hash");
+    Perl_croak(aTHX_ "Can't coerce array into hash");
     return Nullhv;
 }
 
 SV**
-avhv_fetch_ent(AV *av, SV *keysv, I32 lval, U32 hash)
+Perl_avhv_fetch_ent(pTHX_ AV *av, SV *keysv, I32 lval, U32 hash)
 {
     SV **indsvp;
     HV *keys = avhv_keys(av);
     HE *he;
-    
+    STRLEN n_a;
+   
     he = hv_fetch_ent(keys, keysv, FALSE, hash);
     if (!he)
-        croak("No such array field");
+        Perl_croak(aTHX_ "No such pseudo-hash field \"%s\"", SvPV(keysv,n_a));
     return av_fetch(av, avhv_index_sv(HeVAL(he)), lval);
 }
 
+SV *
+Perl_avhv_delete_ent(pTHX_ AV *av, SV *keysv, I32 flags, U32 hash)
+{
+    HV *keys = avhv_keys(av);
+    HE *he;
+       
+    he = hv_fetch_ent(keys, keysv, FALSE, hash);
+    if (!he || !SvOK(HeVAL(he)))
+       return Nullsv;
+
+    return av_delete(av, avhv_index_sv(HeVAL(he)), flags);
+}
+
+/* Check for the existence of an element named by a given key.
+ *
+ */
 bool
-avhv_exists_ent(AV *av, SV *keysv, U32 hash)
+Perl_avhv_exists_ent(pTHX_ AV *av, SV *keysv, U32 hash)
 {
     HV *keys = avhv_keys(av);
-    return hv_exists_ent(keys, keysv, hash);
+    HE *he;
+       
+    he = hv_fetch_ent(keys, keysv, FALSE, hash);
+    if (!he || !SvOK(HeVAL(he)))
+       return FALSE;
+
+    return av_exists(av, avhv_index_sv(HeVAL(he)));
 }
 
 HE *
-avhv_iternext(AV *av)
+Perl_avhv_iternext(pTHX_ AV *av)
 {
     HV *keys = avhv_keys(av);
     return hv_iternext(keys);
 }
 
 SV *
-avhv_iterval(AV *av, register HE *entry)
+Perl_avhv_iterval(pTHX_ AV *av, register HE *entry)
 {
     SV *sv = hv_iterval(avhv_keys(av), entry);
     return *av_fetch(av, avhv_index_sv(sv), TRUE);