summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGurusamy Sarathy <gsar@cpan.org>1998-01-19 04:40:04 +0000
committerGurusamy Sarathy <gsar@cpan.org>1998-01-19 04:40:04 +0000
commit165f6120bc62123046b2281a8f26dd679e405685 (patch)
treee667ab058f991655451405d895a2f080aeb25fc2
parent189b2af51bf236b53a02db0b105a3de423d3fff4 (diff)
parent982fa0b99bd3e50eaadd172e08c0a8e5cc2bdfc6 (diff)
downloadperl-165f6120bc62123046b2281a8f26dd679e405685.tar.gz
[win32] integrate changes in winansi
p4raw-id: //depot/win32/perl@431
-rw-r--r--MANIFEST6
-rw-r--r--av.c204
-rw-r--r--av.h11
-rw-r--r--deb.c2
-rw-r--r--doio.c4
-rw-r--r--embed.h2
-rw-r--r--ext/DB_File/DB_File.pm6
-rw-r--r--global.sym2
-rw-r--r--gv.c6
-rw-r--r--lib/Tie/Array.pm262
-rw-r--r--mg.c127
-rw-r--r--op.c38
-rw-r--r--perl.c2
-rw-r--r--perl.h4
-rw-r--r--pod/perlfunc.pod1
-rw-r--r--pod/perltie.pod23
-rw-r--r--pp.c290
-rw-r--r--pp.h4
-rw-r--r--pp_ctl.c26
-rw-r--r--pp_hot.c57
-rw-r--r--pp_sys.c142
-rw-r--r--proto.h2
-rw-r--r--scope.c8
-rw-r--r--sv.c8
-rwxr-xr-xt/lib/tie-push.t24
-rwxr-xr-xt/lib/tie-stdarray.t12
-rwxr-xr-xt/lib/tie-stdpush.t10
-rwxr-xr-xt/op/avhv.t29
-rwxr-xr-xt/op/push.t3
-rwxr-xr-xt/op/tiearray.t210
-rw-r--r--toke.c10
-rw-r--r--universal.c3
-rw-r--r--util.c4
33 files changed, 1162 insertions, 380 deletions
diff --git a/MANIFEST b/MANIFEST
index 7d6b83aae4..d25520a836 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -426,6 +426,7 @@ lib/Text/ParseWords.pm Perl module to split words on arbitrary delimiter
lib/Text/Soundex.pm Perl module to implement Soundex
lib/Text/Tabs.pm Do expand and unexpand
lib/Text/Wrap.pm Paragraph formatter
+lib/Tie/Array.pm Base class for tied arrays
lib/Tie/Hash.pm Base class for tied hashes
lib/Tie/RefHash.pm Base class for tied hashes with references as keys
lib/Tie/Scalar.pm Base class for tied scalars
@@ -735,7 +736,9 @@ t/lib/soundex.t See if Soundex works
t/lib/symbol.t See if Symbol works
t/lib/texttabs.t See if Text::Tabs works
t/lib/textwrap.t See if Text::Wrap works
-t/lib/timelocal.t See if Time::Local works
+t/lib/tie-push.t Test for Tie::Array
+t/lib/tie-stdarray.t Test for Tie::StdArray
+t/lib/tie-stdpush.t Test for Tie::StdArray
t/lib/thread.t Basic test of threading (skipped if no threads)
t/lib/trig.t See if Math::Trig works
t/op/append.t See if . works
@@ -800,6 +803,7 @@ t/op/substr.t See if substr works
t/op/sysio.t See if sysread and syswrite work
t/op/taint.t See if tainting works
t/op/tie.t See if tie/untie functions work
+t/op/tiearray.t See if tied arrays work
t/op/time.t See if time functions work
t/op/undef.t See if undef works
t/op/universal.t See if UNIVERSAL class works
diff --git a/av.c b/av.c
index 176844294e..5925a17869 100644
--- a/av.c
+++ b/av.c
@@ -21,10 +21,14 @@ av_reify(AV *av)
I32 key;
SV* sv;
- if (AvREAL(av))
- return;
+ if (AvREAL(av))
+ return;
+#ifdef DEBUGGING
+ if (SvRMAGICAL(av) && mg_find((SV*)av,'P'))
+ warn("av_reify called on tied array");
+#endif
key = AvMAX(av) + 1;
- while (key > AvFILL(av) + 1)
+ while (key > AvFILLp(av) + 1)
AvARRAY(av)[--key] = &sv_undef;
while (key) {
sv = AvARRAY(av)[--key];
@@ -44,15 +48,30 @@ void
av_extend(AV *av, I32 key)
{
dTHR; /* only necessary if we have to extend stack */
+ MAGIC *mg;
+ if (SvRMAGICAL(av) && (mg = mg_find((SV*)av,'P'))) {
+ dSP;
+ ENTER;
+ SAVETMPS;
+ PUSHMARK(sp);
+ EXTEND(sp,2);
+ PUSHs(mg->mg_obj);
+ PUSHs(sv_2mortal(newSViv(key+1)));
+ PUTBACK;
+ perl_call_method("EXTEND", G_SCALAR|G_DISCARD);
+ FREETMPS;
+ LEAVE;
+ return;
+ }
if (key > AvMAX(av)) {
SV** ary;
I32 tmp;
I32 newmax;
if (AvALLOC(av) != AvARRAY(av)) {
- ary = AvALLOC(av) + AvFILL(av) + 1;
+ ary = AvALLOC(av) + AvFILLp(av) + 1;
tmp = AvARRAY(av) - AvALLOC(av);
- Move(AvARRAY(av), AvALLOC(av), AvFILL(av)+1, SV*);
+ Move(AvARRAY(av), AvALLOC(av), AvFILLp(av)+1, SV*);
AvMAX(av) += tmp;
SvPVX(av) = (char*)AvALLOC(av);
if (AvREAL(av)) {
@@ -127,6 +146,12 @@ av_fetch(register AV *av, I32 key, I32 lval)
if (!av)
return 0;
+ if (key < 0) {
+ key += AvFILL(av) + 1;
+ if (key < 0)
+ return 0;
+ }
+
if (SvRMAGICAL(av)) {
if (mg_find((SV*)av,'P')) {
dTHR;
@@ -137,12 +162,7 @@ av_fetch(register AV *av, I32 key, I32 lval)
}
}
- if (key < 0) {
- key += AvFILL(av) + 1;
- if (key < 0)
- return 0;
- }
- else if (key > AvFILL(av)) {
+ if (key > AvFILLp(av)) {
if (!lval)
return 0;
if (AvREALISH(av))
@@ -172,42 +192,47 @@ SV**
av_store(register AV *av, I32 key, SV *val)
{
SV** ary;
+ U32 fill;
+
if (!av)
return 0;
if (!val)
val = &sv_undef;
- if (SvRMAGICAL(av)) {
- if (mg_find((SV*)av,'P')) {
- if (val != &sv_undef)
- mg_copy((SV*)av, val, 0, key);
- return 0;
- }
- }
-
if (key < 0) {
key += AvFILL(av) + 1;
if (key < 0)
return 0;
}
+
if (SvREADONLY(av) && key >= AvFILL(av))
croak(no_modify);
+
+ if (SvRMAGICAL(av)) {
+ if (mg_find((SV*)av,'P')) {
+ if (val != &sv_undef) {
+ mg_copy((SV*)av, val, 0, key);
+ }
+ return 0;
+ }
+ }
+
if (!AvREAL(av) && AvREIFY(av))
av_reify(av);
if (key > AvMAX(av))
av_extend(av,key);
ary = AvARRAY(av);
- if (AvFILL(av) < key) {
+ if (AvFILLp(av) < key) {
if (!AvREAL(av)) {
dTHR;
if (av == curstack && key > stack_sp - stack_base)
stack_sp = stack_base + key; /* XPUSH in disguise */
do
- ary[++AvFILL(av)] = &sv_undef;
- while (AvFILL(av) < key);
+ ary[++AvFILLp(av)] = &sv_undef;
+ while (AvFILLp(av) < key);
}
- AvFILL(av) = key;
+ AvFILLp(av) = key;
}
else if (AvREAL(av))
SvREFCNT_dec(ary[key]);
@@ -232,7 +257,7 @@ newAV(void)
AvREAL_on(av);
AvALLOC(av) = 0;
SvPVX(av) = 0;
- AvMAX(av) = AvFILL(av) = -1;
+ AvMAX(av) = AvFILLp(av) = -1;
return av;
}
@@ -250,7 +275,7 @@ av_make(register I32 size, register SV **strp)
New(4,ary,size,SV*);
AvALLOC(av) = ary;
SvPVX(av) = (char*)ary;
- AvFILL(av) = size - 1;
+ AvFILLp(av) = size - 1;
AvMAX(av) = size - 1;
for (i = 0; i < size; i++) {
assert (*strp);
@@ -275,7 +300,7 @@ av_fake(register I32 size, register SV **strp)
Copy(strp,ary,size,SV*);
AvFLAGS(av) = AVf_REIFY;
SvPVX(av) = (char*)ary;
- AvFILL(av) = size - 1;
+ AvFILLp(av) = size - 1;
AvMAX(av) = size - 1;
while (size--) {
assert (*strp);
@@ -296,13 +321,20 @@ av_clear(register AV *av)
warn("Attempt to clear deleted array");
}
#endif
- if (!av || AvMAX(av) < 0)
+ if (!av)
return;
/*SUPPRESS 560*/
+ /* Give any tie a chance to cleanup first */
+ if (SvRMAGICAL(av))
+ mg_clear((SV*)av);
+
+ if (AvMAX(av) < 0)
+ return;
+
if (AvREAL(av)) {
ary = AvARRAY(av);
- key = AvFILL(av) + 1;
+ key = AvFILLp(av) + 1;
while (key) {
SvREFCNT_dec(ary[--key]);
ary[key] = &sv_undef;
@@ -312,10 +344,8 @@ av_clear(register AV *av)
AvMAX(av) += key;
SvPVX(av) = (char*)AvALLOC(av);
}
- AvFILL(av) = -1;
+ AvFILLp(av) = -1;
- if (SvRMAGICAL(av))
- mg_clear((SV*)av);
}
void
@@ -326,15 +356,21 @@ av_undef(register AV *av)
if (!av)
return;
/*SUPPRESS 560*/
+
+ /* Give any tie a chance to cleanup first */
+ if (SvRMAGICAL(av) && mg_find((SV*)av,'P'))
+ av_fill(av, -1); /* mg_clear() ? */
+
if (AvREAL(av)) {
- key = AvFILL(av) + 1;
+ key = AvFILLp(av) + 1;
while (key)
SvREFCNT_dec(AvARRAY(av)[--key]);
}
Safefree(AvALLOC(av));
+ AvARRAY(av) = 0;
AvALLOC(av) = 0;
SvPVX(av) = 0;
- AvMAX(av) = AvFILL(av) = -1;
+ AvMAX(av) = AvFILLp(av) = -1;
if (AvARYLEN(av)) {
SvREFCNT_dec(AvARYLEN(av));
AvARYLEN(av) = 0;
@@ -343,23 +379,54 @@ av_undef(register AV *av)
void
av_push(register AV *av, SV *val)
-{
+{
+ MAGIC *mg;
if (!av)
return;
- av_store(av,AvFILL(av)+1,val);
+ if (SvREADONLY(av))
+ croak(no_modify);
+
+ if (SvRMAGICAL(av) && (mg = mg_find((SV*)av,'P'))) {
+ dSP;
+ PUSHMARK(sp);
+ EXTEND(sp,2);
+ PUSHs(mg->mg_obj);
+ PUSHs(val);
+ PUTBACK;
+ ENTER;
+ perl_call_method("PUSH", G_SCALAR|G_DISCARD);
+ LEAVE;
+ return;
+ }
+ av_store(av,AvFILLp(av)+1,val);
}
SV *
av_pop(register AV *av)
{
SV *retval;
+ MAGIC* mg;
if (!av || AvFILL(av) < 0)
return &sv_undef;
if (SvREADONLY(av))
croak(no_modify);
- retval = AvARRAY(av)[AvFILL(av)];
- AvARRAY(av)[AvFILL(av)--] = &sv_undef;
+ if (SvRMAGICAL(av) && (mg = mg_find((SV*)av,'P'))) {
+ dSP;
+ PUSHMARK(sp);
+ XPUSHs(mg->mg_obj);
+ PUTBACK;
+ ENTER;
+ if (perl_call_method("POP", G_SCALAR)) {
+ retval = newSVsv(*stack_sp--);
+ } else {
+ retval = &sv_undef;
+ }
+ LEAVE;
+ return retval;
+ }
+ retval = AvARRAY(av)[AvFILLp(av)];
+ AvARRAY(av)[AvFILLp(av)--] = &sv_undef;
if (SvSMAGICAL(av))
mg_set((SV*)av);
return retval;
@@ -370,11 +437,28 @@ av_unshift(register AV *av, register I32 num)
{
register I32 i;
register SV **sstr,**dstr;
+ MAGIC* mg;
if (!av || num <= 0)
return;
if (SvREADONLY(av))
croak(no_modify);
+
+ if (SvRMAGICAL(av) && (mg = mg_find((SV*)av,'P'))) {
+ dSP;
+ PUSHMARK(sp);
+ EXTEND(sp,1+num);
+ PUSHs(mg->mg_obj);
+ while (num-- > 0) {
+ PUSHs(&sv_undef);
+ }
+ PUTBACK;
+ ENTER;
+ perl_call_method("UNSHIFT", G_SCALAR|G_DISCARD);
+ LEAVE;
+ return;
+ }
+
if (!AvREAL(av) && AvREIFY(av))
av_reify(av);
i = AvARRAY(av) - AvALLOC(av);
@@ -384,18 +468,18 @@ av_unshift(register AV *av, register I32 num)
num -= i;
AvMAX(av) += i;
- AvFILL(av) += i;
+ AvFILLp(av) += i;
SvPVX(av) = (char*)(AvARRAY(av) - i);
}
if (num) {
- av_extend(av,AvFILL(av)+num);
- AvFILL(av) += num;
- dstr = AvARRAY(av) + AvFILL(av);
+ av_extend(av,AvFILLp(av)+num);
+ AvFILLp(av) += num;
+ dstr = AvARRAY(av) + AvFILLp(av);
sstr = dstr - num;
#ifdef BUGGY_MSC5
# pragma loop_opt(off) /* don't loop-optimize the following code */
#endif /* BUGGY_MSC5 */
- for (i = AvFILL(av) - num; i >= 0; --i) {
+ for (i = AvFILLp(av) - num; i >= 0; --i) {
*dstr-- = *sstr--;
#ifdef BUGGY_MSC5
# pragma loop_opt() /* loop-optimization back to command-line setting */
@@ -410,17 +494,32 @@ SV *
av_shift(register AV *av)
{
SV *retval;
+ MAGIC* mg;
if (!av || AvFILL(av) < 0)
return &sv_undef;
if (SvREADONLY(av))
croak(no_modify);
+ if (SvRMAGICAL(av) && (mg = mg_find((SV*)av,'P'))) {
+ dSP;
+ PUSHMARK(sp);
+ XPUSHs(mg->mg_obj);
+ PUTBACK;
+ ENTER;
+ if (perl_call_method("SHIFT", G_SCALAR)) {
+ retval = newSVsv(*stack_sp--);
+ } else {
+ retval = &sv_undef;
+ }
+ LEAVE;
+ return retval;
+ }
retval = *AvARRAY(av);
if (AvREAL(av))
*AvARRAY(av) = &sv_undef;
SvPVX(av) = (char*)(AvARRAY(av) + 1);
AvMAX(av)--;
- AvFILL(av)--;
+ AvFILLp(av)--;
if (SvSMAGICAL(av))
mg_set((SV*)av);
return retval;
@@ -435,12 +534,27 @@ av_len(register AV *av)
void
av_fill(register AV *av, I32 fill)
{
+ MAGIC *mg;
if (!av)
croak("panic: null array");
if (fill < 0)
fill = -1;
+ if (SvRMAGICAL(av) && (mg = mg_find((SV*)av,'P'))) {
+ dSP;
+ ENTER;
+ SAVETMPS;
+ PUSHMARK(sp);
+ EXTEND(sp,2);
+ PUSHs(mg->mg_obj);
+ PUSHs(sv_2mortal(newSViv(fill+1)));
+ PUTBACK;
+ perl_call_method("STORESIZE", G_SCALAR|G_DISCARD);
+ FREETMPS;
+ LEAVE;
+ return;
+ }
if (fill <= AvMAX(av)) {
- I32 key = AvFILL(av);
+ I32 key = AvFILLp(av);
SV** ary = AvARRAY(av);
if (AvREAL(av)) {
@@ -454,7 +568,7 @@ av_fill(register AV *av, I32 fill)
ary[++key] = &sv_undef;
}
- AvFILL(av) = fill;
+ AvFILLp(av) = fill;
if (SvSMAGICAL(av))
mg_set((SV*)av);
}
diff --git a/av.h b/av.h
index a8dc60b4cd..8de81f42e4 100644
--- a/av.h
+++ b/av.h
@@ -1,6 +1,6 @@
/* av.h
*
- * Copyright (c) 1991-1997, Larry Wall
+ * Copyright (c) 1991-1998, 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.
@@ -9,8 +9,8 @@
struct xpvav {
char* xav_array; /* pointer to first array element */
- SSize_t xav_fill;
- SSize_t xav_max;
+ SSize_t xav_fill; /* Index of last element present */
+ SSize_t xav_max; /* Number of elements for which array has space */
IV xof_off; /* ptr is incremented by offset */
double xnv_nv; /* numeric value, if any */
MAGIC* xmg_magic; /* magic for scalar array */
@@ -30,7 +30,7 @@ struct xpvav {
#define AvARRAY(av) ((SV**)((XPVAV*) SvANY(av))->xav_array)
#define AvALLOC(av) ((XPVAV*) SvANY(av))->xav_alloc
#define AvMAX(av) ((XPVAV*) SvANY(av))->xav_max
-#define AvFILL(av) ((XPVAV*) SvANY(av))->xav_fill
+#define AvFILLp(av) ((XPVAV*) SvANY(av))->xav_fill
#define AvARYLEN(av) ((XPVAV*) SvANY(av))->xav_arylen
#define AvFLAGS(av) ((XPVAV*) SvANY(av))->xav_flags
@@ -45,4 +45,7 @@ struct xpvav {
#define AvREUSED_off(av) (AvFLAGS(av) &= ~AVf_REUSED)
#define AvREALISH(av) (AvFLAGS(av) & (AVf_REAL|AVf_REIFY))
+
+#define AvFILL(av) ((SvRMAGICAL((SV *) (av))) \
+ ? mg_size((SV *) av) : AvFILLp(av))
diff --git a/deb.c b/deb.c
index 95ea3f4087..ea40c00b9a 100644
--- a/deb.c
+++ b/deb.c
@@ -105,7 +105,7 @@ debstackptrs(void)
(long)(stack_max-stack_base));
PerlIO_printf(Perl_debug_log, "%8lx %8lx %8ld %8ld %8ld\n",
(unsigned long)mainstack, (unsigned long)AvARRAY(curstack),
- (long)mainstack, (long)AvFILL(curstack), (long)AvMAX(curstack));
+ (long)mainstack, (long)AvFILLp(curstack), (long)AvMAX(curstack));
return 0;
}
diff --git a/doio.c b/doio.c
index dce271d4af..502f8341ea 100644
--- a/doio.c
+++ b/doio.c
@@ -76,7 +76,7 @@
#endif
bool
-do_open(GV *gv, register char *name, I32 len, int as_raw, int rawmode, int rawperm, FILE *supplied_fp)
+do_open(GV *gv, register char *name, I32 len, int as_raw, int rawmode, int rawperm, PerlIO *supplied_fp)
{
register IO *io = GvIOn(gv);
PerlIO *saveifp = Nullfp;
@@ -760,7 +760,7 @@ Off_t length; /* length to set file to */
#endif /* F_FREESP */
bool
-do_print(register SV *sv, FILE *fp)
+do_print(register SV *sv, PerlIO *fp)
{
register char *tmps;
STRLEN len;
diff --git a/embed.h b/embed.h
index 60000eff71..41a6af9e99 100644
--- a/embed.h
+++ b/embed.h
@@ -314,6 +314,7 @@
#define magic_settaint Perl_magic_settaint
#define magic_setuvar Perl_magic_setuvar
#define magic_setvec Perl_magic_setvec
+#define magic_sizepack Perl_magic_sizepack
#define magic_wipepack Perl_magic_wipepack
#define magicname Perl_magicname
#define markstack_grow Perl_markstack_grow
@@ -327,6 +328,7 @@
#define mg_len Perl_mg_len
#define mg_magical Perl_mg_magical
#define mg_set Perl_mg_set
+#define mg_size Perl_mg_size
#define mod Perl_mod
#define mod_amg Perl_mod_amg
#define mod_ass_amg Perl_mod_ass_amg
diff --git a/ext/DB_File/DB_File.pm b/ext/DB_File/DB_File.pm
index d08b21ceab..812464361a 100644
--- a/ext/DB_File/DB_File.pm
+++ b/ext/DB_File/DB_File.pm
@@ -106,7 +106,7 @@ package DB_File::RECNOINFO ;
use strict ;
-@DB_File::RECNOINFO::ISA = qw(DB_File::HASHINFO) ;
+@DB_File::RECNOINFO::ISA = qw(DB_File::HASHINFO) ;
sub TIEHASH
{
@@ -189,7 +189,9 @@ require DynaLoader;
R_SNAPSHOT
__R_UNUSED
-);
+);
+
+*FETCHSIZE = \&length;
sub AUTOLOAD {
my($constname);
diff --git a/global.sym b/global.sym
index 969f752ab6..979f8d1818 100644
--- a/global.sym
+++ b/global.sym
@@ -416,6 +416,7 @@ magic_settaint
magic_setuvar
magic_setvec
magic_set_all_env
+magic_sizepack
magic_wipepack
magicname
markstack_grow
@@ -429,6 +430,7 @@ mg_get
mg_len
mg_magical
mg_set
+mg_size
mod
modkids
moreswitches
diff --git a/gv.c b/gv.c
index 7d8df6cd17..251e453733 100644
--- a/gv.c
+++ b/gv.c
@@ -183,7 +183,8 @@ gv_fetchmeth(HV *stash, char *name, STRLEN len, I32 level)
if (av) {
SV** svp = AvARRAY(av);
- I32 items = AvFILL(av) + 1;
+ /* NOTE: No support for tied ISA */
+ I32 items = AvFILLp(av) + 1;
while (items--) {
SV* sv = *svp++;
HV* basestash = gv_stashsv(sv, FALSE);
@@ -582,7 +583,8 @@ gv_fetchpv(char *nambeg, I32 add, I32 sv_type)
AV* av = GvAVn(gv);
GvMULTI_on(gv);
sv_magic((SV*)av, (SV*)gv, 'I', Nullch, 0);
- if (add & 2 && strEQ(nambeg,"AnyDBM_File::ISA") && AvFILL(av) == -1)
+ /* NOTE: No support for tied ISA */
+ if (add & 2 && strEQ(nambeg,"AnyDBM_File::ISA") && AvFILLp(av) == -1)
{
char *pname;
av_push(av, newSVpv(pname = "NDBM_File",0));
diff --git a/lib/Tie/Array.pm b/lib/Tie/Array.pm
new file mode 100644
index 0000000000..336e003b25
--- /dev/null
+++ b/lib/Tie/Array.pm
@@ -0,0 +1,262 @@
+package Tie::Array;
+use vars qw($VERSION);
+use strict;
+$VERSION = '1.00';
+
+# Pod documentation after __END__ below.
+
+sub DESTROY { }
+sub EXTEND { }
+sub UNSHIFT { shift->SPLICE(0,0,@_) }
+sub SHIFT { shift->SPLICE(0,1) }
+sub CLEAR { shift->STORESIZE(0) }
+
+sub PUSH
+{
+ my $obj = shift;
+ my $i = $obj->FETCHSIZE;
+ $obj->STORE($i++, shift) while (@_);
+}
+
+sub POP
+{
+ my $obj = shift;
+ my $newsize = $obj->FETCHSIZE - 1;
+ my $val;
+ if ($newsize >= 0)
+ {
+ $val = $obj->FETCH($newsize);
+ $obj->SETSIZE($newsize);
+ }
+ $val;
+}
+
+sub SPLICE
+{
+ my $obj = shift;
+ my $sz = $obj->FETCHSIZE;
+ my $off = (@_) ? shift : 0;
+ $off += $sz if ($off < 0);
+ my $len = (@_) ? shift : $sz - $off;
+ my @result;
+ for (my $i = 0; $i < $len; $i++)
+ {
+ push(@result,$obj->FETCH($off+$i));
+ }
+ if (@_ > $len)
+ {
+ # Move items up to make room
+ my $d = @_ - $len;
+ my $e = $off+$len;
+ $obj->EXTEND($sz+$d);
+ for (my $i=$sz-1; $i >= $e; $i--)
+ {
+ my $val = $obj->FETCH($i);
+ $obj->STORE($i+$d,$val);
+ }
+ }
+ elsif (@_ < $len)
+ {
+ # Move items down to close the gap
+ my $d = $len - @_;
+ my $e = $off+$len;
+ for (my $i=$off+$len; $i < $sz; $i++)
+ {
+ my $val = $obj->FETCH($i);
+ $obj->STORE($i-$d,$val);
+ }
+ $obj->STORESIZE($sz-$d);
+ }
+ for (my $i=0; $i < @_; $i++)
+ {
+ $obj->STORE($off+$i,$_[$i]);
+ }
+ return @result;
+}
+
+package Tie::StdArray;
+use vars qw(@ISA);
+@ISA = 'Tie::Array';
+
+sub TIEARRAY { bless [], $_[0] }
+sub FETCHSIZE { scalar @{$_[0]} }
+sub STORESIZE { $#{$_[0]} = $_[1]-1 }
+sub STORE { $_[0]->[$_[1]] = $_[2] }
+sub FETCH { $_[0]->[$_[1]] }
+sub CLEAR { @{$_[0]} = () }
+sub POP { pop(@{$_[0]}) }
+sub PUSH { my $o = shift; push(@$o,@_) }
+sub SHIFT { shift(@{$_[0]}) }
+sub UNSHIFT { my $o = shift; unshift(@$o,@_) }
+
+sub SPLICE
+{
+ my $ob = shift;
+ my $sz = $ob->FETCHSIZE;
+ my $off = @_ ? shift : 0;
+ $off += $sz if $off < 0;
+ my $len = @_ ? shift : $sz-$off;
+ return splice(@$ob,$off,$len,@_);
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Tie::Array - base class for tied arrays
+
+=head1 SYNOPSIS
+
+ package NewArray;
+ use Tie::Array;
+ @ISA = ('Tie::Array');
+
+ # mandatory methods
+ sub TIEARRAY { ... }
+ sub FETCH { ... }
+ sub FETCHSIZE { ... }
+
+ sub STORE { ... } # mandatory if elements writeable
+ sub STORESIZE { ... } # mandatory if elements can be added/deleted
+
+ # optional methods - for efficiency
+ sub CLEAR { ... }
+ sub PUSH { ... }
+ sub POP { ... }
+ sub SHIFT { ... }
+ sub UNSHIFT { ... }
+ sub SPLICE { ... }
+ sub EXTEND { ... }
+ sub DESTROY { ... }
+
+ package NewStdArray;
+ use Tie::Array;
+
+ @ISA = ('Tie::StdArray');
+
+ # all methods provided by default
+
+ package main;
+
+ $object = tie @somearray,Tie::NewArray;
+ $object = tie @somearray,Tie::StdArray;
+ $object = tie @somearray,Tie::NewStdArray;
+
+
+
+=head1 DESCRIPTION
+
+This module provides methods for array-tying classes. See
+L<perltie> for a list of the functions required in order to tie an array
+to a package. The basic B<Tie::Array> package provides stub C<DELETE>
+and C<EXTEND> methods, and implementations of C<PUSH>, C<POP>, C<SHIFT>,
+C<UNSHIFT>, C<SPLICE> and C<CLEAR> in terms of basic C<FETCH>, C<STORE>,
+C<FETCHSIZE>, C<STORESIZE>.
+
+The B<Tie::StdHash> package provides efficient methods required for tied arrays
+which are implemented as blessed references to an "inner" perl array.
+It inherits from B<Tie::Array>, and should cause tied arrays to behave exactly
+like standard hashes, allowing for selective overloading of methods.
+
+For developers wishing to write their own tied arrays, the required methods
+are briefly defined below. See the L<perltie> section for more detailed
+descriptive, as well as example code:
+
+=over
+
+=item TIEARRAY classname, LIST
+
+The class method is invoked by the command C<tie @array, classname>. Associates
+an array instance with the specified class. C<LIST> would represent
+additional arguments (along the lines of L<AnyDBM_File> and compatriots) needed
+to complete the association. The method should return an object of a class which
+provides the methods below.
+
+=item STORE this, index, value
+
+Store datum I<value> into I<index> for the tied array assoicated with
+object I<this>. If this makes the array larger then
+class's mapping of C<undef> should be returned for new positions.
+
+=item FETCH this, index
+
+Retrieve the datum in I<index> for the tied array assoicated with
+object I<this>.
+
+=item FETCHSIZE this
+
+Returns the total number of items in the tied array assoicated with
+object I<this>. (Equivalent to C<scalar(@array)>).
+
+=item STORESIZE this, count
+
+Sets the total number of items in the tied array assoicated with
+object I<this> to be I<count>. If this makes the array larger then
+class's mapping of C<undef> should be returned for new positions.
+If the array becomes smaller then entries beyond count should be
+deleted.
+
+=item EXTEND this, count
+
+Informative call that array is likely to grow to have I<count> entries.
+Can be used to optimize allocation. This method need do nothing.
+
+=item CLEAR this
+
+Clear (remove, delete, ...) all values from the tied array assoicated with
+object I<this>.
+
+=item DESTROY this
+
+Normal object destructor method.
+
+=item PUSH this, LIST
+
+Append elements of LIST to the array.
+
+=item POP this
+
+Remove last element of the array and return it.
+
+=item SHIFT this
+
+Remove the first element of the array (shifting other elements down)
+and return it.
+
+=item UNSHIFT this, LIST
+
+Insert LIST elements at the begining of the array, moving existing elements
+up to make room.
+
+=item SPLICE this, offset, length, LIST
+
+Perform the equivalent of C<splice> on the array.
+
+I<offset> is optional and defaults to zero, negative values count back
+from the end of the array.
+
+I<length> is optional and defaults to rest of the array.
+
+I<LIST> may be empty.
+
+Returns a list of the original I<length> elements at I<offset>.
+
+=back
+
+=head1 CAVEATS
+
+There is no support at present for tied @ISA. There is a potential conflict
+between magic entries needed to notice setting of @ISA, and those needed to
+implement 'tie'.
+
+Very little consideration has been given to the behaviour of tied arrays
+when C<$[> is not default value of zero.
+
+=head1 AUTHOR
+
+Nick Ing-Simmons E<lt>nik@tiuk.ti.comE<gt>
+
+=cut
+
diff --git a/mg.c b/mg.c
index 1d0014315d..af2dddc87e 100644
--- a/mg.c
+++ b/mg.c
@@ -170,6 +170,37 @@ mg_len(SV *sv)
return len;
}
+I32
+mg_size(SV *sv)
+{
+ MAGIC* mg;
+ I32 len;
+
+ for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
+ MGVTBL* vtbl = mg->mg_virtual;
+ if (vtbl && vtbl->svt_len) {
+ MGS mgs;
+ ENTER;
+ /* omit MGf_GSKIP -- not changed here */
+ len = (*vtbl->svt_len)(sv, mg);
+ LEAVE;
+ return len;
+ }
+ }
+
+ switch(SvTYPE(sv)) {
+ case SVt_PVAV:
+ len = AvFILLp((AV *) sv); /* Fallback to non-tied array */
+ return len;
+ case SVt_PVHV:
+ /* FIXME */
+ default:
+ croak("Size magic not implemented");
+ break;
+ }
+ return 0;
+}
+
int
mg_clear(SV *sv)
{
@@ -865,8 +896,9 @@ magic_setisa(SV *sv, MAGIC *mg)
stash = GvSTASH(mg->mg_obj);
svp = AvARRAY((AV*)sv);
-
- for (fill = AvFILL((AV*)sv); fill >= 0; fill--, svp++) {
+
+ /* NOTE: No support for tied ISA */
+ for (fill = AvFILLp((AV*)sv); fill >= 0; fill--, svp++) {
HV *basestash = gv_stashsv(*svp, FALSE);
if (!basestash) {
@@ -920,30 +952,46 @@ magic_setnkeys(SV *sv, MAGIC *mg)
LvTARG(sv) = Nullsv; /* Don't allow a ref to reassign this. */
}
return 0;
-}
+}
static int
-magic_methpack(SV *sv, MAGIC *mg, char *meth)
+magic_methcall(MAGIC *mg, char *meth, I32 flags, int n, SV *val)
{
dSP;
- ENTER;
- SAVETMPS;
PUSHMARK(sp);
- EXTEND(sp, 2);
+ EXTEND(sp, n);
PUSHs(mg->mg_obj);
- if (mg->mg_ptr) {
- if (mg->mg_len >= 0)
- PUSHs(sv_2mortal(newSVpv(mg->mg_ptr, mg->mg_len)));
- else if (mg->mg_len == HEf_SVKEY)
- PUSHs((SV*)mg->mg_ptr);
+ if (n > 1) {
+ if (mg->mg_ptr) {
+ if (mg->mg_len >= 0)
+ PUSHs(sv_2mortal(newSVpv(mg->mg_ptr, mg->mg_len)));
+ else if (mg->mg_len == HEf_SVKEY)
+ PUSHs((SV*)mg->mg_ptr);
+ }
+ else if (mg->mg_type == 'p') {
+ PUSHs(sv_2mortal(newSViv(mg->mg_len)));
+ }
+ }
+ if (n > 2) {
+ PUSHs(val);
}
- else if (mg->mg_type == 'p')
- PUSHs(sv_2mortal(newSViv(mg->mg_len)));
PUTBACK;
- if (perl_call_method(meth, G_SCALAR))
+ return perl_call_method(meth, flags);
+}
+
+static int
+magic_methpack(SV *sv, MAGIC *mg, char *meth)
+{
+ dSP;
+
+ ENTER;
+ SAVETMPS;
+
+ if (magic_methcall(mg, meth, G_SCALAR, 2, NULL)) {
sv_setsv(sv, *stack_sp--);
+ }
FREETMPS;
LEAVE;
@@ -961,25 +1009,10 @@ magic_getpack(SV *sv, MAGIC *mg)
int
magic_setpack(SV *sv, MAGIC *mg)
-{
- dSP;
-
- PUSHMARK(sp);
- EXTEND(sp, 3);
- PUSHs(mg->mg_obj);
- if (mg->mg_ptr) {
- if (mg->mg_len >= 0)
- PUSHs(sv_2mortal(newSVpv(mg->mg_ptr, mg->mg_len)));
- else if (mg->mg_len == HEf_SVKEY)
- PUSHs((SV*)mg->mg_ptr);
- }
- else if (mg->mg_type == 'p')
- PUSHs(sv_2mortal(newSViv(mg->mg_len)));
- PUSHs(sv);
- PUTBACK;
-
- perl_call_method("STORE", G_SCALAR|G_DISCARD);
-
+{
+ ENTER;
+ magic_methcall(mg, "STORE", G_SCALAR|G_DISCARD, 3, sv);
+ LEAVE;
return 0;
}
@@ -989,6 +1022,24 @@ magic_clearpack(SV *sv, MAGIC *mg)
return magic_methpack(sv,mg,"DELETE");
}
+
+U32
+magic_sizepack(SV *sv, MAGIC *mg)
+{
+ dTHR;
+ U32 retval = 0;
+
+ ENTER;
+ SAVETMPS;
+ if (magic_methcall(mg, "FETCHSIZE", G_SCALAR, 2, NULL)) {
+ sv = *stack_sp--;
+ retval = (U32) SvIV(sv)-1;
+ }
+ FREETMPS;
+ LEAVE;
+ return retval;
+}
+
int magic_wipepack(SV *sv, MAGIC *mg)
{
dSP;
@@ -996,9 +1047,9 @@ int magic_wipepack(SV *sv, MAGIC *mg)
PUSHMARK(sp);
XPUSHs(mg->mg_obj);
PUTBACK;
-
+ ENTER;
perl_call_method("CLEAR", G_SCALAR|G_DISCARD);
-
+ LEAVE;
return 0;
}
@@ -1208,7 +1259,7 @@ magic_getdefelem(SV *sv, MAGIC *mg)
targ = HeVAL(he);
}
else {
- AV* av = (AV*)LvTARG(sv);
+ AV* av = (AV*)LvTARG(sv);
if ((I32)LvTARGOFF(sv) <= AvFILL(av))
targ = AvARRAY(av)[LvTARGOFF(sv)];
}
@@ -1812,7 +1863,7 @@ sighandler(int sig)
oldstack = curstack;
if (curstack != signalstack)
- AvFILL(signalstack) = 0;
+ AvFILLp(signalstack) = 0;
SWITCHSTACK(curstack, signalstack);
if(psig_name[sig]) {
diff --git a/op.c b/op.c
index 47f2f57f3e..073569c1e4 100644
--- a/op.c
+++ b/op.c
@@ -108,9 +108,9 @@ pad_allocmy(char *name)
}
croak("Can't use global %s in \"my\"",name);
}
- if (dowarn && AvFILL(comppad_name) >= 0) {
+ if (dowarn && AvFILLp(comppad_name) >= 0) {
SV **svp = AvARRAY(comppad_name);
- for (off = AvFILL(comppad_name); off > comppad_name_floor; off--) {
+ for (off = AvFILLp(comppad_name); off > comppad_name_floor; off--) {
if ((sv = svp[off])
&& sv != &sv_undef
&& SvIVX(sv) == 999999999 /* var is in open scope */
@@ -176,7 +176,7 @@ pad_findlex(char *name, PADOFFSET newoff, U32 seq, CV* startcv, I32 cx_ix)
continue;
curname = (AV*)*svp;
svp = AvARRAY(curname);
- for (off = AvFILL(curname); off > 0; off--) {
+ for (off = AvFILLp(curname); off > 0; off--) {
if ((sv = svp[off]) &&
sv != &sv_undef &&
seq <= SvIVX(sv) &&
@@ -307,7 +307,7 @@ pad_findmy(char *name)
#endif /* USE_THREADS */
/* The one we're looking for is probably just before comppad_name_fill. */
- for (off = AvFILL(comppad_name); off > 0; off--) {
+ for (off = AvFILLp(comppad_name); off > 0; off--) {
if ((sv = svp[off]) &&
sv != &sv_undef &&
(!SvIVX(sv) ||
@@ -345,7 +345,7 @@ pad_leavemy(I32 fill)
}
}
/* "Deintroduce" my variables that are leaving with this scope. */
- for (off = AvFILL(comppad_name); off > fill; off--) {
+ for (off = AvFILLp(comppad_name); off > fill; off--) {
if ((sv = svp[off]) && sv != &sv_undef && SvIVX(sv) == 999999999)
SvIVX(sv) = cop_seqmax;
}
@@ -364,13 +364,13 @@ pad_alloc(I32 optype, U32 tmptype)
pad_reset();
if (tmptype & SVs_PADMY) {
do {
- sv = *av_fetch(comppad, AvFILL(comppad) + 1, TRUE);
+ sv = *av_fetch(comppad, AvFILLp(comppad) + 1, TRUE);
} while (SvPADBUSY(sv)); /* need a fresh one */
- retval = AvFILL(comppad);
+ retval = AvFILLp(comppad);
}
else {
SV **names = AvARRAY(comppad_name);
- SSize_t names_fill = AvFILL(comppad_name);
+ SSize_t names_fill = AvFILLp(comppad_name);
for (;;) {
/*
* "foreach" index vars temporarily become aliases to non-"my"
@@ -1502,7 +1502,7 @@ block_start(int full)
int retval = savestack_ix;
SAVEI32(comppad_name_floor);
if (full) {
- if ((comppad_name_fill = AvFILL(comppad_name)) > 0)
+ if ((comppad_name_fill = AvFILLp(comppad_name)) > 0)
comppad_name_floor = comppad_name_fill;
else
comppad_name_floor = 0;
@@ -3026,7 +3026,7 @@ cv_undef(CV *cv)
if (CvPADLIST(cv)) {
/* may be during global destruction */
if (SvREFCNT(CvPADLIST(cv))) {
- I32 i = AvFILL(CvPADLIST(cv));
+ I32 i = AvFILLp(CvPADLIST(cv));
while (i >= 0) {
SV** svp = av_fetch(CvPADLIST(cv), i--, FALSE);
SV* sv = svp ? *svp : Nullsv;
@@ -3080,7 +3080,7 @@ CV* cv;
pname = AvARRAY(pad_name);
ppad = AvARRAY(pad);
- for (ix = 1; ix <= AvFILL(pad_name); ix++) {
+ for (ix = 1; ix <= AvFILLp(pad_name); ix++) {
if (SvPOK(pname[ix]))
PerlIO_printf(Perl_debug_log, "\t%4d. 0x%lx (%s\"%s\" %ld-%ld)\n",
ix, ppad[ix],
@@ -3103,8 +3103,8 @@ cv_clone2(CV *proto, CV *outside)
AV* protopad = (AV*)*av_fetch(protopadlist, 1, FALSE);
SV** pname = AvARRAY(protopad_name);
SV** ppad = AvARRAY(protopad);
- I32 fname = AvFILL(protopad_name);
- I32 fpad = AvFILL(protopad);
+ I32 fname = AvFILLp(protopad_name);
+ I32 fpad = AvFILLp(protopad);
AV* comppadlist;
CV* cv;
@@ -3149,7 +3149,7 @@ cv_clone2(CV *proto, CV *outside)
av_store(comppadlist, 0, (SV*)comppad_name);
av_store(comppadlist, 1, (SV*)comppad);
CvPADLIST(cv) = comppadlist;
- av_fill(comppad, AvFILL(protopad));
+ av_fill(comppad, AvFILLp(protopad));
curpad = AvARRAY(comppad);
av = newAV(); /* will be @_ */
@@ -3386,12 +3386,12 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block)
return cv;
}
- if (AvFILL(comppad_name) < AvFILL(comppad))
- av_store(comppad_name, AvFILL(comppad), Nullsv);
+ if (AvFILLp(comppad_name) < AvFILLp(comppad))
+ av_store(comppad_name, AvFILLp(comppad), Nullsv);
if (CvCLONE(cv)) {
SV **namep = AvARRAY(comppad_name);
- for (ix = AvFILL(comppad); ix > 0; ix--) {
+ for (ix = AvFILLp(comppad); ix > 0; ix--) {
SV *namesv;
if (SvIMMORTAL(curpad[ix]))
@@ -3417,7 +3417,7 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block)
av_store(comppad, 0, (SV*)av);
AvFLAGS(av) = AVf_REIFY;
- for (ix = AvFILL(comppad); ix > 0; ix--) {
+ for (ix = AvFILLp(comppad); ix > 0; ix--) {
if (SvIMMORTAL(curpad[ix]))
continue;
if (!SvPADMY(curpad[ix]))
@@ -3606,7 +3606,7 @@ newFORM(I32 floor, OP *o, OP *block)
CvGV(cv) = (GV*)SvREFCNT_inc(gv);
CvFILEGV(cv) = curcop->cop_filegv;
- for (ix = AvFILL(comppad); ix > 0; ix--) {
+ for (ix = AvFILLp(comppad); ix > 0; ix--) {
if (!SvPADMY(curpad[ix]) && !SvIMMORTAL(curpad[ix]))
SvPADTMP_on(curpad[ix]);
}
diff --git a/perl.c b/perl.c
index c0fa69f021..a693f231b1 100644
--- a/perl.c
+++ b/perl.c
@@ -2860,7 +2860,7 @@ call_list(I32 oldscope, AV *list)
dJMPENV;
int ret;
- while (AvFILL(list) >= 0) {
+ while (AvFILL(list) >= 0) {
CV *cv = (CV*)av_shift(list);
SAVEFREESV(cv);
diff --git a/perl.h b/perl.h
index bec110cf74..5c963cabb4 100644
--- a/perl.h
+++ b/perl.h
@@ -945,7 +945,7 @@ typedef union any ANY;
typedef I32 (*filter_t) _((int, SV *, int));
#define FILTER_READ(idx, sv, len) filter_read(idx, sv, len)
#define FILTER_DATA(idx) (AvARRAY(rsfp_filters)[idx])
-#define FILTER_ISREADER(idx) (idx >= AvFILL(rsfp_filters))
+#define FILTER_ISREADER(idx) (idx >= AvFILLp(rsfp_filters))
#ifdef DOSISH
# if defined(OS2)
@@ -1750,7 +1750,7 @@ EXT MGVTBL vtbl_sigelem = {magic_getsig,
magic_setsig,
0, magic_clearsig,
0};
-EXT MGVTBL vtbl_pack = {0, 0, 0, magic_wipepack,
+EXT MGVTBL vtbl_pack = {0, 0, magic_sizepack, magic_wipepack,
0};
EXT MGVTBL vtbl_packelem = {magic_getpack,
magic_setpack,
diff --git a/pod/perlfunc.pod b/pod/perlfunc.pod
index a89ee99e06..a1184c8a08 100644
--- a/pod/perlfunc.pod
+++ b/pod/perlfunc.pod
@@ -1580,6 +1580,7 @@ elements. That is, modifying an element of a list returned by grep
actually modifies the element in the original list.
See also L</map> for an array composed of the results of the BLOCK or EXPR.
+
=item hex EXPR
=item hex
diff --git a/pod/perltie.pod b/pod/perltie.pod
index c6eb7156ce..79a749e68a 100644
--- a/pod/perltie.pod
+++ b/pod/perltie.pod
@@ -180,17 +180,26 @@ TIESCALAR classes are certainly possible.
=head2 Tying Arrays
A class implementing a tied ordinary array should define the following
-methods: TIEARRAY, FETCH, STORE, and perhaps DESTROY.
+methods: TIEARRAY, FETCH, STORE, FETCHSIZE, STORESIZE and perhaps DESTROY.
-B<WARNING>: Tied arrays are I<incomplete>. They are also distinctly lacking
-something for the C<$#ARRAY> access (which is hard, as it's an lvalue), as
-well as the other obvious array functions, like push(), pop(), shift(),
-unshift(), and splice().
+FETCHSIZE and STORESIZE are used to provide C<$#array> and
+equivalent C<scalar(@array)> access.
+
+The methods POP, PUSH, SHIFT, UNSHIFT, SPLICE are required if the perl
+operator with the corresponding (but lowercase) name is to operate on the
+tied array. The B<Tie::Array> class can be used as a base class to implement
+these in terms of the basic five methods above.
+
+In addition EXTEND will be called when perl would have pre-extended
+allocation in a real array.
+
+This means that tied arrays are now I<complete>. The example below needs
+upgrading to illustrate this. (The documentation in B<Tie::Array> is more
+complete.)
For this discussion, we'll implement an array whose indices are fixed at
its creation. If you try to access anything beyond those bounds, you'll
-take an exception. (Well, if you access an individual element; an
-aggregate assignment would be missed.) For example:
+take an exception. For example:
require Bounded_Array;
tie @ary, 'Bounded_Array', 2;
diff --git a/pp.c b/pp.c
index 7864089313..3afd65b04d 100644
--- a/pp.c
+++ b/pp.c
@@ -24,7 +24,7 @@
*/
#ifdef CXUX_BROKEN_CONSTANT_CONVERT
static double UV_MAX_cxux = ((double)UV_MAX);
-#endif
+#endif
/*
* Types used in bitwise operations.
@@ -141,7 +141,16 @@ PP(pp_padav)
if (GIMME == G_ARRAY) {
I32 maxarg = AvFILL((AV*)TARG) + 1;
EXTEND(SP, maxarg);
- Copy(AvARRAY((AV*)TARG), SP+1, maxarg, SV*);
+ if (SvMAGICAL(TARG)) {
+ U32 i;
+ for (i=0; i < maxarg; i++) {
+ SV **svp = av_fetch((AV*)TARG, i, FALSE);
+ SP[i+1] = (svp) ? *svp : &sv_undef;
+ }
+ }
+ else {
+ Copy(AvARRAY((AV*)TARG), SP+1, maxarg, SV*);
+ }
SP += maxarg;
}
else {
@@ -189,7 +198,7 @@ PP(pp_padany)
PP(pp_rv2gv)
{
djSP; dTOPss;
-
+
if (SvROK(sv)) {
wasref:
sv = SvRV(sv);
@@ -297,7 +306,7 @@ PP(pp_av2arylen)
PP(pp_pos)
{
djSP; dTARGET; dPOPss;
-
+
if (op->op_flags & OPf_MOD) {
if (SvTYPE(TARG) < SVt_PVLV) {
sv_upgrade(TARG, SVt_PVLV);
@@ -310,7 +319,7 @@ PP(pp_pos)
RETURN;
}
else {
- MAGIC* mg;
+ MAGIC* mg;
if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) {
mg = mg_find(sv, 'g');
@@ -374,7 +383,7 @@ PP(pp_srefgen)
djSP;
*SP = refto(*SP);
RETURN;
-}
+}
PP(pp_refgen)
{
@@ -422,7 +431,7 @@ PP(pp_ref)
sv = POPs;
if (sv && SvGMAGICAL(sv))
- mg_get(sv);
+ mg_get(sv);
if (!sv || !SvROK(sv))
RETPUSHNO;
@@ -628,7 +637,7 @@ PP(pp_chomp)
{
djSP; dMARK; dTARGET;
register I32 count = 0;
-
+
while (SP > MARK)
count += do_chomp(POPs);
PUSHi(count);
@@ -784,7 +793,7 @@ PP(pp_postdec)
PP(pp_pow)
{
- djSP; dATARGET; tryAMAGICbin(pow,opASSIGN);
+ djSP; dATARGET; tryAMAGICbin(pow,opASSIGN);
{
dPOPTOPnnrl;
SETn( pow( left, right) );
@@ -794,7 +803,7 @@ PP(pp_pow)
PP(pp_multiply)
{
- djSP; dATARGET; tryAMAGICbin(mult,opASSIGN);
+ djSP; dATARGET; tryAMAGICbin(mult,opASSIGN);
{
dPOPTOPnnrl;
SETn( left * right );
@@ -804,7 +813,7 @@ PP(pp_multiply)
PP(pp_divide)
{
- djSP; dATARGET; tryAMAGICbin(div,opASSIGN);
+ djSP; dATARGET; tryAMAGICbin(div,opASSIGN);
{
dPOPPOPnnrl;
double value;
@@ -937,7 +946,7 @@ PP(pp_repeat)
PP(pp_subtract)
{
- djSP; dATARGET; tryAMAGICbin(subtr,opASSIGN);
+ djSP; dATARGET; tryAMAGICbin(subtr,opASSIGN);
{
dPOPTOPnnrl_ul;
SETn( left - right );
@@ -947,7 +956,7 @@ PP(pp_subtract)
PP(pp_left_shift)
{
- djSP; dATARGET; tryAMAGICbin(lshift,opASSIGN);
+ djSP; dATARGET; tryAMAGICbin(lshift,opASSIGN);
{
IBW shift = POPi;
if (op->op_private & HINT_INTEGER) {
@@ -966,7 +975,7 @@ PP(pp_left_shift)
PP(pp_right_shift)
{
- djSP; dATARGET; tryAMAGICbin(rshift,opASSIGN);
+ djSP; dATARGET; tryAMAGICbin(rshift,opASSIGN);
{
IBW shift = POPi;
if (op->op_private & HINT_INTEGER) {
@@ -985,7 +994,7 @@ PP(pp_right_shift)
PP(pp_lt)
{
- djSP; tryAMAGICbinSET(lt,0);
+ djSP; tryAMAGICbinSET(lt,0);
{
dPOPnv;
SETs(boolSV(TOPn < value));
@@ -995,7 +1004,7 @@ PP(pp_lt)
PP(pp_gt)
{
- djSP; tryAMAGICbinSET(gt,0);
+ djSP; tryAMAGICbinSET(gt,0);
{
dPOPnv;
SETs(boolSV(TOPn > value));
@@ -1005,7 +1014,7 @@ PP(pp_gt)
PP(pp_le)
{
- djSP; tryAMAGICbinSET(le,0);
+ djSP; tryAMAGICbinSET(le,0);
{
dPOPnv;
SETs(boolSV(TOPn <= value));
@@ -1015,7 +1024,7 @@ PP(pp_le)
PP(pp_ge)
{
- djSP; tryAMAGICbinSET(ge,0);
+ djSP; tryAMAGICbinSET(ge,0);
{
dPOPnv;
SETs(boolSV(TOPn >= value));
@@ -1025,7 +1034,7 @@ PP(pp_ge)
PP(pp_ne)
{
- djSP; tryAMAGICbinSET(ne,0);
+ djSP; tryAMAGICbinSET(ne,0);
{
dPOPnv;
SETs(boolSV(TOPn != value));
@@ -1035,7 +1044,7 @@ PP(pp_ne)
PP(pp_ncmp)
{
- djSP; dTARGET; tryAMAGICbin(ncmp,0);
+ djSP; dTARGET; tryAMAGICbin(ncmp,0);
{
dPOPTOPnnrl;
I32 value;
@@ -1057,7 +1066,7 @@ PP(pp_ncmp)
PP(pp_slt)
{
- djSP; tryAMAGICbinSET(slt,0);
+ djSP; tryAMAGICbinSET(slt,0);
{
dPOPTOPssrl;
int cmp = ((op->op_private & OPpLOCALE)
@@ -1070,7 +1079,7 @@ PP(pp_slt)
PP(pp_sgt)
{
- djSP; tryAMAGICbinSET(sgt,0);
+ djSP; tryAMAGICbinSET(sgt,0);
{
dPOPTOPssrl;
int cmp = ((op->op_private & OPpLOCALE)
@@ -1083,7 +1092,7 @@ PP(pp_sgt)
PP(pp_sle)
{
- djSP; tryAMAGICbinSET(sle,0);
+ djSP; tryAMAGICbinSET(sle,0);
{
dPOPTOPssrl;
int cmp = ((op->op_private & OPpLOCALE)
@@ -1096,7 +1105,7 @@ PP(pp_sle)
PP(pp_sge)
{
- djSP; tryAMAGICbinSET(sge,0);
+ djSP; tryAMAGICbinSET(sge,0);
{
dPOPTOPssrl;
int cmp = ((op->op_private & OPpLOCALE)
@@ -1109,7 +1118,7 @@ PP(pp_sge)
PP(pp_seq)
{
- djSP; tryAMAGICbinSET(seq,0);
+ djSP; tryAMAGICbinSET(seq,0);
{
dPOPTOPssrl;
SETs(boolSV(sv_eq(left, right)));
@@ -1119,7 +1128,7 @@ PP(pp_seq)
PP(pp_sne)
{
- djSP; tryAMAGICbinSET(sne,0);
+ djSP; tryAMAGICbinSET(sne,0);
{
dPOPTOPssrl;
SETs(boolSV(!sv_eq(left, right)));
@@ -1142,16 +1151,16 @@ PP(pp_scmp)
PP(pp_bit_and)
{
- djSP; dATARGET; tryAMAGICbin(band,opASSIGN);
+ djSP; dATARGET; tryAMAGICbin(band,opASSIGN);
{
dPOPTOPssrl;
if (SvNIOKp(left) || SvNIOKp(right)) {
if (op->op_private & HINT_INTEGER) {
- IBW value = SvIV(left) & SvIV(right);
+ IBW value = SvIV(left) & SvIV(right);
SETi(BWi(value));
}
else {
- UBW value = SvUV(left) & SvUV(right);
+ UBW value = SvUV(left) & SvUV(right);
SETu(BWu(value));
}
}
@@ -1165,16 +1174,16 @@ PP(pp_bit_and)
PP(pp_bit_xor)
{
- djSP; dATARGET; tryAMAGICbin(bxor,opASSIGN);
+ djSP; dATARGET; tryAMAGICbin(bxor,opASSIGN);
{
dPOPTOPssrl;
if (SvNIOKp(left) || SvNIOKp(right)) {
if (op->op_private & HINT_INTEGER) {
- IBW value = (USE_LEFT(left) ? SvIV(left) : 0) ^ SvIV(right);
+ IBW value = (USE_LEFT(left) ? SvIV(left) : 0) ^ SvIV(right);
SETi(BWi(value));
}
else {
- UBW value = (USE_LEFT(left) ? SvUV(left) : 0) ^ SvUV(right);
+ UBW value = (USE_LEFT(left) ? SvUV(left) : 0) ^ SvUV(right);
SETu(BWu(value));
}
}
@@ -1188,16 +1197,16 @@ PP(pp_bit_xor)
PP(pp_bit_or)
{
- djSP; dATARGET; tryAMAGICbin(bor,opASSIGN);
+ djSP; dATARGET; tryAMAGICbin(bor,opASSIGN);
{
dPOPTOPssrl;
if (SvNIOKp(left) || SvNIOKp(right)) {
if (op->op_private & HINT_INTEGER) {
- IBW value = (USE_LEFT(left) ? SvIV(left) : 0) | SvIV(right);
+ IBW value = (USE_LEFT(left) ? SvIV(left) : 0) | SvIV(right);
SETi(BWi(value));
}
else {
- UBW value = (USE_LEFT(left) ? SvUV(left) : 0) | SvUV(right);
+ UBW value = (USE_LEFT(left) ? SvUV(left) : 0) | SvUV(right);
SETu(BWu(value));
}
}
@@ -1252,7 +1261,7 @@ PP(pp_not)
PP(pp_complement)
{
- djSP; dTARGET; tryAMAGICun(compl);
+ djSP; dTARGET; tryAMAGICun(compl);
{
dTOPss;
if (SvNIOKp(sv)) {
@@ -1295,7 +1304,7 @@ PP(pp_complement)
PP(pp_i_multiply)
{
- djSP; dATARGET; tryAMAGICbin(mult,opASSIGN);
+ djSP; dATARGET; tryAMAGICbin(mult,opASSIGN);
{
dPOPTOPiirl;
SETi( left * right );
@@ -1305,7 +1314,7 @@ PP(pp_i_multiply)
PP(pp_i_divide)
{
- djSP; dATARGET; tryAMAGICbin(div,opASSIGN);
+ djSP; dATARGET; tryAMAGICbin(div,opASSIGN);
{
dPOPiv;
if (value == 0)
@@ -1318,7 +1327,7 @@ PP(pp_i_divide)
PP(pp_i_modulo)
{
- djSP; dATARGET; tryAMAGICbin(mod,opASSIGN);
+ djSP; dATARGET; tryAMAGICbin(mod,opASSIGN);
{
dPOPTOPiirl;
if (!right)
@@ -1330,7 +1339,7 @@ PP(pp_i_modulo)
PP(pp_i_add)
{
- djSP; dATARGET; tryAMAGICbin(add,opASSIGN);
+ djSP; dATARGET; tryAMAGICbin(add,opASSIGN);
{
dPOPTOPiirl;
SETi( left + right );
@@ -1340,7 +1349,7 @@ PP(pp_i_add)
PP(pp_i_subtract)
{
- djSP; dATARGET; tryAMAGICbin(subtr,opASSIGN);
+ djSP; dATARGET; tryAMAGICbin(subtr,opASSIGN);
{
dPOPTOPiirl;
SETi( left - right );
@@ -1350,7 +1359,7 @@ PP(pp_i_subtract)
PP(pp_i_lt)
{
- djSP; tryAMAGICbinSET(lt,0);
+ djSP; tryAMAGICbinSET(lt,0);
{
dPOPTOPiirl;
SETs(boolSV(left < right));
@@ -1360,7 +1369,7 @@ PP(pp_i_lt)
PP(pp_i_gt)
{
- djSP; tryAMAGICbinSET(gt,0);
+ djSP; tryAMAGICbinSET(gt,0);
{
dPOPTOPiirl;
SETs(boolSV(left > right));
@@ -1370,7 +1379,7 @@ PP(pp_i_gt)
PP(pp_i_le)
{
- djSP; tryAMAGICbinSET(le,0);
+ djSP; tryAMAGICbinSET(le,0);
{
dPOPTOPiirl;
SETs(boolSV(left <= right));
@@ -1380,7 +1389,7 @@ PP(pp_i_le)
PP(pp_i_ge)
{
- djSP; tryAMAGICbinSET(ge,0);
+ djSP; tryAMAGICbinSET(ge,0);
{
dPOPTOPiirl;
SETs(boolSV(left >= right));
@@ -1390,7 +1399,7 @@ PP(pp_i_ge)
PP(pp_i_eq)
{
- djSP; tryAMAGICbinSET(eq,0);
+ djSP; tryAMAGICbinSET(eq,0);
{
dPOPTOPiirl;
SETs(boolSV(left == right));
@@ -1400,7 +1409,7 @@ PP(pp_i_eq)
PP(pp_i_ne)
{
- djSP; tryAMAGICbinSET(ne,0);
+ djSP; tryAMAGICbinSET(ne,0);
{
dPOPTOPiirl;
SETs(boolSV(left != right));
@@ -1410,7 +1419,7 @@ PP(pp_i_ne)
PP(pp_i_ncmp)
{
- djSP; dTARGET; tryAMAGICbin(ncmp,0);
+ djSP; dTARGET; tryAMAGICbin(ncmp,0);
{
dPOPTOPiirl;
I32 value;
@@ -1437,7 +1446,7 @@ PP(pp_i_negate)
PP(pp_atan2)
{
- djSP; dTARGET; tryAMAGICbin(atan2,0);
+ djSP; dTARGET; tryAMAGICbin(atan2,0);
{
dPOPTOPnnrl;
SETn(atan2(left, right));
@@ -1753,7 +1762,7 @@ PP(pp_substr)
rem -= pos;
}
if (fail < 0) {
- if (dowarn || lvalue)
+ if (dowarn || lvalue)
warn("substr outside of string");
RETPUSHUNDEF;
}
@@ -1781,7 +1790,7 @@ PP(pp_substr)
LvTYPE(TARG) = 'x';
LvTARG(TARG) = sv;
LvTARGOFF(TARG) = pos;
- LvTARGLEN(TARG) = rem;
+ LvTARGLEN(TARG) = rem;
}
}
PUSHs(TARG); /* avoid SvSETMAGIC here */
@@ -1813,8 +1822,8 @@ PP(pp_vec)
LvTYPE(TARG) = 'v';
LvTARG(TARG) = src;
- LvTARGOFF(TARG) = offset;
- LvTARGLEN(TARG) = size;
+ LvTARGOFF(TARG) = offset;
+ LvTARGLEN(TARG) = size;
}
if (len > srclen) {
if (size <= 8)
@@ -2198,7 +2207,7 @@ PP(pp_each)
HE *entry;
I32 gimme = GIMME_V;
I32 realhv = (SvTYPE(hash) == SVt_PVHV);
-
+
PUTBACK;
/* might clobber stack_sp */
entry = realhv ? hv_iternext(hash) : avhv_iternext((AV*)hash);
@@ -2446,13 +2455,25 @@ PP(pp_splice)
I32 after;
I32 diff;
SV **tmparyval = 0;
+ MAGIC *mg;
+
+ if (SvRMAGICAL(ary) && (mg = mg_find((SV*)ary,'P'))) {
+ *MARK-- = mg->mg_obj;
+ PUSHMARK(MARK);
+ PUTBACK;
+ ENTER;
+ perl_call_method("SPLICE",GIMME_V);
+ LEAVE;
+ SPAGAIN;
+ RETURN;
+ }
SP++;
if (++MARK < SP) {
offset = i = SvIVx(*MARK);
if (offset < 0)
- offset += AvFILL(ary) + 1;
+ offset += AvFILLp(ary) + 1;
else
offset -= curcop->cop_arybase;
if (offset < 0)
@@ -2469,9 +2490,9 @@ PP(pp_splice)
offset = 0;
length = AvMAX(ary) + 1;
}
- if (offset > AvFILL(ary) + 1)
- offset = AvFILL(ary) + 1;
- after = AvFILL(ary) + 1 - (offset + length);
+ if (offset > AvFILLp(ary) + 1)
+ offset = AvFILLp(ary) + 1;
+ after = AvFILLp(ary) + 1 - (offset + length);
if (after < 0) { /* not that much array */
length += after; /* offset+length now in array */
after = 0;
@@ -2519,7 +2540,7 @@ PP(pp_splice)
SvREFCNT_dec(*dst++); /* free them now */
}
}
- AvFILL(ary) += diff;
+ AvFILLp(ary) += diff;
/* pull up or down? */
@@ -2540,7 +2561,7 @@ PP(pp_splice)
dst = src + diff; /* diff is negative */
Move(src, dst, after, SV*);
}
- dst = &AvARRAY(ary)[AvFILL(ary)+1];
+ dst = &AvARRAY(ary)[AvFILLp(ary)+1];
/* avoid later double free */
}
i = -diff;
@@ -2574,15 +2595,15 @@ PP(pp_splice)
}
SvPVX(ary) = (char*)(AvARRAY(ary) - diff);/* diff is positive */
AvMAX(ary) += diff;
- AvFILL(ary) += diff;
+ AvFILLp(ary) += diff;
}
else {
- if (AvFILL(ary) + diff >= AvMAX(ary)) /* oh, well */
- av_extend(ary, AvFILL(ary) + diff);
- AvFILL(ary) += diff;
+ if (AvFILLp(ary) + diff >= AvMAX(ary)) /* oh, well */
+ av_extend(ary, AvFILLp(ary) + diff);
+ AvFILLp(ary) += diff;
if (after) {
- dst = AvARRAY(ary) + AvFILL(ary);
+ dst = AvARRAY(ary) + AvFILLp(ary);
src = dst - diff;
for (i = after; i; i--) {
*dst-- = *src--;
@@ -2633,12 +2654,25 @@ PP(pp_push)
djSP; dMARK; dORIGMARK; dTARGET;
register AV *ary = (AV*)*++MARK;
register SV *sv = &sv_undef;
+ MAGIC *mg;
- for (++MARK; MARK <= SP; MARK++) {
- sv = NEWSV(51, 0);
- if (*MARK)
- sv_setsv(sv, *MARK);
- av_push(ary, sv);
+ if (SvRMAGICAL(ary) && (mg = mg_find((SV*)ary,'P'))) {
+ *MARK-- = mg->mg_obj;
+ PUSHMARK(MARK);
+ PUTBACK;
+ ENTER;
+ perl_call_method("PUSH",G_SCALAR|G_DISCARD);
+ LEAVE;
+ SPAGAIN;
+ }
+ else {
+ /* Why no pre-extend of ary here ? */
+ for (++MARK; MARK <= SP; MARK++) {
+ sv = NEWSV(51, 0);
+ if (*MARK)
+ sv_setsv(sv, *MARK);
+ av_push(ary, sv);
+ }
}
SP = ORIGMARK;
PUSHi( AvFILL(ary) + 1 );
@@ -2676,14 +2710,26 @@ PP(pp_unshift)
register AV *ary = (AV*)*++MARK;
register SV *sv;
register I32 i = 0;
+ MAGIC *mg;
+
+ if (SvRMAGICAL(ary) && (mg = mg_find((SV*)ary,'P'))) {
- av_unshift(ary, SP - MARK);
- while (MARK < SP) {
- sv = NEWSV(27, 0);
- sv_setsv(sv, *++MARK);
- (void)av_store(ary, i++, sv);
- }
+ *MARK-- = mg->mg_obj;
+ PUTBACK;
+ ENTER;
+ perl_call_method("UNSHIFT",G_SCALAR|G_DISCARD);
+ LEAVE;
+ SPAGAIN;
+ }
+ else {
+ av_unshift(ary, SP - MARK);
+ while (MARK < SP) {
+ sv = NEWSV(27, 0);
+ sv_setsv(sv, *++MARK);
+ (void)av_store(ary, i++, sv);
+ }
+ }
SP = ORIGMARK;
PUSHi( AvFILL(ary) + 1 );
RETURN;
@@ -3234,7 +3280,7 @@ PP(pp_unpack)
case 'w':
EXTEND(SP, len);
EXTEND_MORTAL(len);
- {
+ {
UV auv = 0;
U32 bytes = 0;
@@ -3528,7 +3574,7 @@ is_an_int(char *s, STRLEN l)
static int
div128(SV *pnum, bool *done)
/* must be '\0' terminated */
-
+
{
STRLEN len;
char *s = SvPV(pnum, len);
@@ -3876,7 +3922,7 @@ PP(pp_pack)
SV *norm;
STRLEN len;
bool done;
-
+
/* Copy string and check for compliance */
from = SvPV(fromstr, len);
if ((norm = is_an_int(from, len)) == NULL)
@@ -4020,6 +4066,7 @@ PP(pp_pack)
}
#undef NEXTFROM
+
PP(pp_split)
{
djSP; dTARG;
@@ -4043,6 +4090,8 @@ PP(pp_split)
AV *oldstack = curstack;
I32 gimme = GIMME_V;
I32 oldsave = savestack_ix;
+ I32 make_mortal = 1;
+ MAGIC *mg = (MAGIC *) NULL;
#ifdef DEBUGGING
Copy(&LvTARGOFF(POPs), &pm, 1, PMOP*);
@@ -4068,15 +4117,24 @@ PP(pp_split)
ary = Nullav;
if (ary && (gimme != G_ARRAY || (pm->op_pmflags & PMf_ONCE))) {
realarray = 1;
- if (!AvREAL(ary)) {
- AvREAL_on(ary);
- for (i = AvFILL(ary); i >= 0; i--)
- AvARRAY(ary)[i] = &sv_undef; /* don't free mere refs */
- }
+ PUTBACK;
av_extend(ary,0);
av_clear(ary);
- /* temporarily switch stacks */
- SWITCHSTACK(curstack, ary);
+ SPAGAIN;
+ if (SvRMAGICAL(ary) && (mg = mg_find((SV *) ary, 'P'))) {
+ PUSHMARK(SP);
+ XPUSHs(mg->mg_obj);
+ }
+ else {
+ if (!AvREAL(ary)) {
+ AvREAL_on(ary);
+ for (i = AvFILLp(ary); i >= 0; i--)
+ AvARRAY(ary)[i] = &sv_undef; /* don't free mere refs */
+ }
+ /* temporarily switch stacks */
+ SWITCHSTACK(curstack, ary);
+ make_mortal = 0;
+ }
}
base = SP - stack_base;
orig = s;
@@ -4109,7 +4167,7 @@ PP(pp_split)
dstr = NEWSV(30, m-s);
sv_setpvn(dstr, s, m-s);
- if (!realarray)
+ if (make_mortal)
sv_2mortal(dstr);
XPUSHs(dstr);
@@ -4129,13 +4187,13 @@ PP(pp_split)
break;
dstr = NEWSV(30, m-s);
sv_setpvn(dstr, s, m-s);
- if (!realarray)
+ if (make_mortal)
sv_2mortal(dstr);
XPUSHs(dstr);
s = m;
}
}
- else if (rx->check_substr && !rx->nparens
+ else if (rx->check_substr && !rx->nparens
&& (rx->reganch & ROPT_CHECK_ALL)
&& !(rx->reganch & ROPT_ANCH)) {
i = SvCUR(rx->check_substr);
@@ -4148,7 +4206,7 @@ PP(pp_split)
break;
dstr = NEWSV(30, m-s);
sv_setpvn(dstr, s, m-s);
- if (!realarray)
+ if (make_mortal)
sv_2mortal(dstr);
XPUSHs(dstr);
s = m + 1;
@@ -4163,7 +4221,7 @@ PP(pp_split)
{
dstr = NEWSV(31, m-s);
sv_setpvn(dstr, s, m-s);
- if (!realarray)
+ if (make_mortal)
sv_2mortal(dstr);
XPUSHs(dstr);
s = m + i;
@@ -4187,7 +4245,7 @@ PP(pp_split)
m = rx->startp[0];
dstr = NEWSV(32, m-s);
sv_setpvn(dstr, s, m-s);
- if (!realarray)
+ if (make_mortal)
sv_2mortal(dstr);
XPUSHs(dstr);
if (rx->nparens) {
@@ -4200,7 +4258,7 @@ PP(pp_split)
}
else
dstr = NEWSV(33, 0);
- if (!realarray)
+ if (make_mortal)
sv_2mortal(dstr);
XPUSHs(dstr);
}
@@ -4208,16 +4266,17 @@ PP(pp_split)
s = rx->endp[0];
}
}
+
LEAVE_SCOPE(oldsave);
iters = (SP - stack_base) - base;
if (iters > maxiters)
DIE("Split loop");
-
+
/* keep field after final delim? */
if (s < strend || (iters && origlimit)) {
dstr = NEWSV(34, strend-s);
sv_setpvn(dstr, s, strend-s);
- if (!realarray)
+ if (make_mortal)
sv_2mortal(dstr);
XPUSHs(dstr);
iters++;
@@ -4226,18 +4285,37 @@ PP(pp_split)
while (iters > 0 && (!TOPs || !SvANY(TOPs) || SvCUR(TOPs) == 0))
iters--, SP--;
}
+
if (realarray) {
- SWITCHSTACK(ary, oldstack);
- if (SvSMAGICAL(ary)) {
+ if (!mg) {
+ SWITCHSTACK(ary, oldstack);
+ if (SvSMAGICAL(ary)) {
+ PUTBACK;
+ mg_set((SV*)ary);
+ SPAGAIN;
+ }
+ if (gimme == G_ARRAY) {
+ EXTEND(SP, iters);
+ Copy(AvARRAY(ary), SP + 1, iters, SV*);
+ SP += iters;
+ RETURN;
+ }
+ }
+ else {
PUTBACK;
- mg_set((SV*)ary);
+ ENTER;
+ perl_call_method("PUSH",G_SCALAR|G_DISCARD);
+ LEAVE;
SPAGAIN;
- }
- if (gimme == G_ARRAY) {
- EXTEND(SP, iters);
- Copy(AvARRAY(ary), SP + 1, iters, SV*);
- SP += iters;
- RETURN;
+ if (gimme == G_ARRAY) {
+ /* EXTEND should not be needed - we just popped them */
+ EXTEND(SP, iters);
+ for (i=0; i < iters; i++) {
+ SV **svp = av_fetch(ary, i, FALSE);
+ PUSHs((svp) ? *svp : &sv_undef);
+ }
+ RETURN;
+ }
}
}
else {
@@ -4258,7 +4336,7 @@ unlock_condpair(void *svv)
{
dTHR;
MAGIC *mg = mg_find((SV*)svv, 'm');
-
+
if (!mg)
croak("panic: unlock_condpair unlocking non-mutex");
MUTEX_LOCK(MgMUTEXP(mg));
@@ -4279,7 +4357,7 @@ PP(pp_lock)
SV *retsv = sv;
#ifdef USE_THREADS
MAGIC *mg;
-
+
if (SvROK(sv))
sv = SvRV(sv);
diff --git a/pp.h b/pp.h
index 1914fcc5b5..ab4140c415 100644
--- a/pp.h
+++ b/pp.h
@@ -154,10 +154,10 @@
#define ARGTARG op->op_targ
#define MAXARG op->op_private
-#define SWITCHSTACK(f,t) AvFILL(f) = sp - stack_base; \
+#define SWITCHSTACK(f,t) AvFILLp(f) = sp - stack_base; \
stack_base = AvARRAY(t); \
stack_max = stack_base + AvMAX(t); \
- sp = stack_sp = stack_base + AvFILL(t); \
+ sp = stack_sp = stack_base + AvFILLp(t); \
curstack = t;
#define EXTEND_MORTAL(n) \
diff --git a/pp_ctl.c b/pp_ctl.c
index 822627414d..9590271e87 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1214,10 +1214,10 @@ PP(pp_caller)
AvREAL_off(dbargs); /* XXX Should be REIFY */
}
- if (AvMAX(dbargs) < AvFILL(ary) + off)
- av_extend(dbargs, AvFILL(ary) + off);
- Copy(AvALLOC(ary), AvARRAY(dbargs), AvFILL(ary) + 1 + off, SV*);
- AvFILL(dbargs) = AvFILL(ary) + off;
+ if (AvMAX(dbargs) < AvFILLp(ary) + off)
+ av_extend(dbargs, AvFILLp(ary) + off);
+ Copy(AvALLOC(ary), AvARRAY(dbargs), AvFILLp(ary) + 1 + off, SV*);
+ AvFILLp(dbargs) = AvFILLp(ary) + off;
}
RETURN;
}
@@ -1348,7 +1348,7 @@ PP(pp_enteriter)
cx->blk_loop.iterary = (AV*)SvREFCNT_inc(POPs);
else {
cx->blk_loop.iterary = curstack;
- AvFILL(curstack) = sp - stack_base;
+ AvFILLp(curstack) = sp - stack_base;
cx->blk_loop.iterix = MARK - stack_base;
}
@@ -1714,7 +1714,7 @@ PP(pp_goto)
if (cx->blk_sub.hasargs) { /* put @_ back onto stack */
AV* av = cx->blk_sub.argarray;
- items = AvFILL(av) + 1;
+ items = AvFILLp(av) + 1;
stack_sp++;
EXTEND(stack_sp, items); /* @_ could have been extended. */
Copy(AvARRAY(av), stack_sp, items, SV*);
@@ -1764,10 +1764,10 @@ PP(pp_goto)
else { /* save temporaries on recursion? */
if (CvDEPTH(cv) == 100 && dowarn)
sub_crush_depth(cv);
- if (CvDEPTH(cv) > AvFILL(padlist)) {
+ if (CvDEPTH(cv) > AvFILLp(padlist)) {
AV *newpad = newAV();
SV **oldpad = AvARRAY(svp[CvDEPTH(cv)-1]);
- I32 ix = AvFILL((AV*)svp[1]);
+ I32 ix = AvFILLp((AV*)svp[1]);
svp = AvARRAY(svp[0]);
for ( ;ix > 0; ix--) {
if (svp[ix] != &sv_undef) {
@@ -1801,7 +1801,7 @@ PP(pp_goto)
AvFLAGS(av) = AVf_REIFY;
}
av_store(padlist, CvDEPTH(cv), (SV*)newpad);
- AvFILL(padlist) = CvDEPTH(cv);
+ AvFILLp(padlist) = CvDEPTH(cv);
svp = AvARRAY(padlist);
}
}
@@ -1809,7 +1809,7 @@ PP(pp_goto)
if (!cx->blk_sub.hasargs) {
AV* av = (AV*)curpad[0];
- items = AvFILL(av) + 1;
+ items = AvFILLp(av) + 1;
if (items) {
/* Mark is at the end of the stack. */
EXTEND(sp, items);
@@ -1849,7 +1849,7 @@ PP(pp_goto)
}
}
Copy(mark,AvARRAY(av),items,SV*);
- AvFILL(av) = items - 1;
+ AvFILLp(av) = items - 1;
while (items--) {
if (*mark)
@@ -2578,10 +2578,10 @@ PP(pp_leaveeval)
* (Note that the fact that compcv and friends are still set here
* is, AFAIK, an accident.) --Chip
*/
- if (AvFILL(comppad_name) >= 0) {
+ if (AvFILLp(comppad_name) >= 0) {
SV **svp = AvARRAY(comppad_name);
I32 ix;
- for (ix = AvFILL(comppad_name); ix >= 0; ix--) {
+ for (ix = AvFILLp(comppad_name); ix >= 0; ix--) {
SV *sv = svp[ix];
if (sv && sv != &sv_undef && *SvPVX(sv) == '&') {
SvREFCNT_dec(sv);
diff --git a/pp_hot.c b/pp_hot.c
index 7c320b37c4..633a7b09fe 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -183,8 +183,11 @@ PP(pp_padsv)
if (op->op_flags & OPf_MOD) {
if (op->op_private & OPpLVAL_INTRO)
SAVECLEARSV(curpad[op->op_targ]);
- else if (op->op_private & OPpDEREF)
+ else if (op->op_private & OPpDEREF) {
+ PUTBACK;
vivify_ref(curpad[op->op_targ], op->op_private & OPpDEREF);
+ SPAGAIN;
+ }
}
RETURN;
}
@@ -297,6 +300,9 @@ PP(pp_print)
gv = defoutgv;
if (SvRMAGICAL(gv) && (mg = mg_find((SV*)gv, 'q'))) {
if (MARK == ORIGMARK) {
+ /* If using default handle then we need to make space to
+ * pass object as 1st arg, so move other args up ...
+ */
MEXTEND(SP, 1);
++MARK;
Move(MARK, MARK + 1, (SP - MARK) + 1, SV*);
@@ -443,8 +449,17 @@ PP(pp_rv2av)
if (GIMME == G_ARRAY) {
I32 maxarg = AvFILL(av) + 1;
- EXTEND(SP, maxarg);
- Copy(AvARRAY(av), SP+1, maxarg, SV*);
+ EXTEND(SP, maxarg);
+ if (SvRMAGICAL(av)) {
+ U32 i;
+ for (i=0; i < maxarg; i++) {
+ SV **svp = av_fetch(av, i, FALSE);
+ SP[i+1] = (svp) ? *svp : &sv_undef;
+ }
+ }
+ else {
+ Copy(AvARRAY(av), SP+1, maxarg, SV*);
+ }
SP += maxarg;
}
else {
@@ -1378,7 +1393,9 @@ PP(pp_iter)
SvREFCNT_dec(*cx->blk_loop.itervar);
- if (sv = AvARRAY(av)[++cx->blk_loop.iterix])
+ if (sv = (SvMAGICAL(av))
+ ? *av_fetch(av, ++cx->blk_loop.iterix, FALSE)
+ : AvARRAY(av)[++cx->blk_loop.iterix])
SvTEMP_off(sv);
else
sv = &sv_undef;
@@ -1439,11 +1456,13 @@ PP(pp_subst)
else {
TARG = DEFSV;
EXTEND(SP,1);
- }
+ }
if (SvREADONLY(TARG)
|| (SvTYPE(TARG) > SVt_PVLV
&& !(SvTYPE(TARG) == SVt_PVGV && SvFAKE(TARG))))
croak(no_modify);
+ PUTBACK;
+
s = SvPV(TARG, len);
if (!SvPOKp(TARG) || SvTYPE(TARG) == SVt_PVGV)
force_on_match = 1;
@@ -1519,6 +1538,7 @@ PP(pp_subst)
if (c && clen <= rx->minlen && (once || !(safebase & REXEC_COPY_STR))
&& !(rx->reganch & ROPT_LOOKBEHIND_SEEN)) {
if (!regexec_flags(rx, s, strend, orig, 0, screamer, NULL, safebase)) {
+ SPAGAIN;
PUSHs(&sv_no);
LEAVE_SCOPE(oldsave);
RETURN;
@@ -1574,6 +1594,7 @@ PP(pp_subst)
sv_chop(TARG, d);
}
TAINT_IF(rxtainted);
+ SPAGAIN;
PUSHs(&sv_yes);
}
else {
@@ -1602,10 +1623,15 @@ PP(pp_subst)
Move(s, d, i+1, char); /* include the NUL */
}
TAINT_IF(rxtainted);
+ SPAGAIN;
PUSHs(sv_2mortal(newSViv((I32)iters)));
}
(void)SvPOK_only(TARG);
- SvSETMAGIC(TARG);
+ if (SvSMAGICAL(TARG)) {
+ PUTBACK;
+ mg_set(TARG);
+ SPAGAIN;
+ }
SvTAINT(TARG);
LEAVE_SCOPE(oldsave);
RETURN;
@@ -1618,11 +1644,12 @@ PP(pp_subst)
goto force_it;
}
rxtainted = RX_MATCH_TAINTED(rx);
- dstr = NEWSV(25, sv_len(TARG));
+ dstr = NEWSV(25, len);
sv_setpvn(dstr, m, s-m);
curpm = pm;
if (!c) {
register PERL_CONTEXT *cx;
+ SPAGAIN;
PUSHSUBST(cx);
RETURNOP(cPMOP->op_pmreplroot);
}
@@ -1660,6 +1687,7 @@ PP(pp_subst)
(void)SvPOK_only(TARG);
SvSETMAGIC(TARG);
SvTAINT(TARG);
+ SPAGAIN;
PUSHs(sv_2mortal(newSViv((I32)iters)));
LEAVE_SCOPE(oldsave);
RETURN;
@@ -1669,7 +1697,8 @@ PP(pp_subst)
nope:
++BmUSEFUL(rx->check_substr);
-ret_no:
+ret_no:
+ SPAGAIN;
PUSHs(&sv_no);
LEAVE_SCOPE(oldsave);
RETURN;
@@ -2038,7 +2067,7 @@ PP(pp_entersub)
#else
av = GvAV(defgv);
#endif /* USE_THREADS */
- items = AvFILL(av) + 1;
+ items = AvFILLp(av) + 1; /* @_ is not tieable */
if (items) {
/* Mark is at the end of the stack. */
@@ -2085,11 +2114,11 @@ PP(pp_entersub)
if (CvDEPTH(cv) == 100 && dowarn
&& !(PERLDB_SUB && cv == GvCV(DBsub)))
sub_crush_depth(cv);
- if (CvDEPTH(cv) > AvFILL(padlist)) {
+ if (CvDEPTH(cv) > AvFILLp(padlist)) {
AV *av;
AV *newpad = newAV();
SV **oldpad = AvARRAY(svp[CvDEPTH(cv)-1]);
- I32 ix = AvFILL((AV*)svp[1]);
+ I32 ix = AvFILLp((AV*)svp[1]);
svp = AvARRAY(svp[0]);
for ( ;ix > 0; ix--) {
if (svp[ix] != &sv_undef) {
@@ -2119,7 +2148,7 @@ PP(pp_entersub)
av_store(newpad, 0, (SV*)av);
AvFLAGS(av) = AVf_REIFY;
av_store(padlist, CvDEPTH(cv), (SV*)newpad);
- AvFILL(padlist) = CvDEPTH(cv);
+ AvFILLp(padlist) = CvDEPTH(cv);
svp = AvARRAY(padlist);
}
}
@@ -2127,7 +2156,7 @@ PP(pp_entersub)
if (!hasargs) {
AV* av = (AV*)curpad[0];
- items = AvFILL(av) + 1;
+ items = AvFILLp(av) + 1;
if (items) {
/* Mark is at the end of the stack. */
EXTEND(sp, items);
@@ -2176,7 +2205,7 @@ PP(pp_entersub)
}
}
Copy(MARK,AvARRAY(av),items,SV*);
- AvFILL(av) = items - 1;
+ AvFILLp(av) = items - 1;
while (items--) {
if (*MARK)
diff --git a/pp_sys.c b/pp_sys.c
index 26886d1af1..4893913d99 100644
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -516,62 +516,48 @@ PP(pp_tie)
SV **mark = stack_base + ++*markstack_ptr; /* reuse in entersub */
I32 markoff = mark - stack_base - 1;
char *methname;
-#ifdef ORIGINAL_TIE
- BINOP myop;
- bool oldcatch = CATCH_GET;
-#endif
-
- varsv = mark[0];
- if (SvTYPE(varsv) == SVt_PVHV)
- methname = "TIEHASH";
- else if (SvTYPE(varsv) == SVt_PVAV)
- methname = "TIEARRAY";
- else if (SvTYPE(varsv) == SVt_PVGV)
- methname = "TIEHANDLE";
- else
- methname = "TIESCALAR";
-
- stash = gv_stashsv(mark[1], FALSE);
- if (!stash || !(gv = gv_fetchmethod(stash, methname)))
- DIE("Can't locate object method \"%s\" via package \"%s\"",
- methname, SvPV(mark[1],na));
-
-#ifdef ORIGINAL_TIE
- Zero(&myop, 1, BINOP);
- myop.op_last = (OP *) &myop;
- myop.op_next = Nullop;
- myop.op_flags = OPf_WANT_SCALAR | OPf_STACKED;
- CATCH_SET(TRUE);
+ int how = 'P';
- ENTER;
- SAVEOP();
- op = (OP *) &myop;
- if (PERLDB_SUB && curstash != debstash)
- op->op_private |= OPpENTERSUB_DB;
-
- XPUSHs((SV*)GvCV(gv));
- PUTBACK;
+ varsv = mark[0];
+ switch(SvTYPE(varsv)) {
+ case SVt_PVHV:
+ methname = "TIEHASH";
+ break;
+ case SVt_PVAV:
+ methname = "TIEARRAY";
+ break;
+ case SVt_PVGV:
+ methname = "TIEHANDLE";
+ how = 'q';
+ break;
+ default:
+ methname = "TIESCALAR";
+ how = 'q';
+ break;
+ }
- if (op = pp_entersub(ARGS))
- runops();
+ if (sv_isobject(mark[1])) {
+ ENTER;
+ perl_call_method(methname, G_SCALAR);
+ }
+ else {
+ /* Not clear why we don't call perl_call_method here too.
+ * perhaps to get different error message ?
+ */
+ stash = gv_stashsv(mark[1], FALSE);
+ if (!stash || !(gv = gv_fetchmethod(stash, methname))) {
+ DIE("Can't locate object method \"%s\" via package \"%s\"",
+ methname, SvPV(mark[1],na));
+ }
+ ENTER;
+ perl_call_sv((SV*)GvCV(gv), G_SCALAR);
+ }
SPAGAIN;
- CATCH_SET(oldcatch);
-#else
- ENTER;
- perl_call_sv((SV*)GvCV(gv), G_SCALAR);
- SPAGAIN;
-#endif
sv = TOPs;
if (sv_isobject(sv)) {
- if (SvTYPE(varsv) == SVt_PVHV || SvTYPE(varsv) == SVt_PVAV) {
- sv_unmagic(varsv, 'P');
- sv_magic(varsv, sv, 'P', Nullch, 0);
- }
- else {
- sv_unmagic(varsv, 'q');
- sv_magic(varsv, sv, 'q', Nullch, 0);
- }
+ sv_unmagic(varsv, how);
+ sv_magic(varsv, sv, how, Nullch, 0);
}
LEAVE;
SP = stack_base + markoff;
@@ -583,8 +569,7 @@ PP(pp_untie)
{
djSP;
SV * sv ;
-
- sv = POPs;
+ sv = POPs;
if (dowarn) {
MAGIC * mg ;
@@ -625,7 +610,6 @@ PP(pp_tied)
RETURN ;
}
}
-
RETPUSHUNDEF;
}
@@ -637,10 +621,6 @@ PP(pp_dbmopen)
HV* stash;
GV *gv;
SV *sv;
-#ifdef ORIGINAL_TIE
- BINOP myop;
- bool oldcatch = CATCH_GET;
-#endif
hv = (HV*)POPs;
@@ -655,24 +635,9 @@ PP(pp_dbmopen)
DIE("No dbm on this machine");
}
-#ifdef ORIGINAL_TIE
- Zero(&myop, 1, BINOP);
- myop.op_last = (OP *) &myop;
- myop.op_next = Nullop;
- myop.op_flags = OPf_WANT_SCALAR | OPf_STACKED;
- CATCH_SET(TRUE);
-
- ENTER;
- SAVEOP();
- op = (OP *) &myop;
- if (PERLDB_SUB && curstash != debstash)
- op->op_private |= OPpENTERSUB_DB;
- PUTBACK;
- pp_pushmark(ARGS);
-#else
ENTER;
PUSHMARK(sp);
-#endif
+
EXTEND(sp, 5);
PUSHs(sv);
PUSHs(left);
@@ -681,51 +646,26 @@ PP(pp_dbmopen)
else
PUSHs(sv_2mortal(newSViv(O_RDWR)));
PUSHs(right);
-#ifdef ORIGINAL_TIE
- PUSHs((SV*)GvCV(gv));
- PUTBACK;
-
- if (op = pp_entersub(ARGS))
- runops();
-#else
PUTBACK;
perl_call_sv((SV*)GvCV(gv), G_SCALAR);
-#endif
SPAGAIN;
if (!sv_isobject(TOPs)) {
sp--;
-#ifdef ORIGINAL_TIE
- op = (OP *) &myop;
- PUTBACK;
- pp_pushmark(ARGS);
-#else
PUSHMARK(sp);
-#endif
-
PUSHs(sv);
PUSHs(left);
PUSHs(sv_2mortal(newSViv(O_RDONLY)));
PUSHs(right);
-#ifdef ORIGINAL_TIE
- PUSHs((SV*)GvCV(gv));
-#endif
PUTBACK;
-
-#ifdef ORIGINAL_TIE
- if (op = pp_entersub(ARGS))
- runops();
-#else
perl_call_sv((SV*)GvCV(gv), G_SCALAR);
-#endif
SPAGAIN;
}
-#ifdef ORIGINAL_TIE
- CATCH_SET(oldcatch);
-#endif
- if (sv_isobject(TOPs))
+ if (sv_isobject(TOPs)) {
+ sv_unmagic((SV *) hv, 'P');
sv_magic((SV*)hv, TOPs, 'P', Nullch, 0);
+ }
LEAVE;
RETURN;
}
diff --git a/proto.h b/proto.h
index 67cebd143d..19159c5fd9 100644
--- a/proto.h
+++ b/proto.h
@@ -251,6 +251,7 @@ int magic_settaint _((SV* sv, MAGIC* mg));
int magic_setuvar _((SV* sv, MAGIC* mg));
int magic_setvec _((SV* sv, MAGIC* mg));
int magic_set_all_env _((SV* sv, MAGIC* mg));
+U32 magic_sizepack _((SV* sv, MAGIC* mg));
int magic_wipepack _((SV* sv, MAGIC* mg));
void magicname _((char* sym, char* name, I32 namlen));
int main _((int argc, char** argv, char** env));
@@ -267,6 +268,7 @@ int mg_get _((SV* sv));
U32 mg_len _((SV* sv));
void mg_magical _((SV* sv));
int mg_set _((SV* sv));
+I32 mg_size _((SV* sv));
OP* mod _((OP* o, I32 type));
char* moreswitches _((char* s));
OP* my _((OP* o));
diff --git a/scope.c b/scope.c
index 3b4428f945..bca1c2b455 100644
--- a/scope.c
+++ b/scope.c
@@ -19,8 +19,16 @@ SV**
stack_grow(SV **sp, SV **p, int n)
{
dTHR;
+#if defined(DEBUGGING) && !defined(USE_THREADS)
+ static int growing = 0;
+ if (growing++)
+ abort();
+#endif
stack_sp = sp;
av_extend(curstack, (p - stack_base) + (n) + 128);
+#if defined(DEBUGGING) && !defined(USE_THREADS)
+ growing--;
+#endif
return stack_sp;
}
diff --git a/sv.c b/sv.c
index b0d7f973b1..65d10c65a8 100644
--- a/sv.c
+++ b/sv.c
@@ -785,7 +785,7 @@ sv_upgrade(register SV *sv, U32 mt)
Safefree(pv);
SvPVX(sv) = 0;
AvMAX(sv) = -1;
- AvFILL(sv) = -1;
+ AvFILLp(sv) = -1;
SvIVX(sv) = 0;
SvNVX(sv) = 0.0;
SvMAGIC(sv) = magic;
@@ -2983,7 +2983,7 @@ sv_collxfrm(SV *sv, STRLEN *nxp)
#endif /* USE_LOCALE_COLLATE */
char *
-sv_gets(register SV *sv, register FILE *fp, I32 append)
+sv_gets(register SV *sv, register PerlIO *fp, I32 append)
{
dTHR;
char *rsptr;
@@ -3703,8 +3703,6 @@ sv_true(register SV *sv)
dTHR;
if (!sv)
return 0;
- if (SvGMAGICAL(sv))
- mg_get(sv);
if (SvPOK(sv)) {
register XPV* tXpv;
if ((tXpv = (XPV*)SvANY(sv)) &&
@@ -4774,7 +4772,7 @@ sv_dump(SV *sv)
case SVt_PVAV:
PerlIO_printf(Perl_debug_log, " ARRAY = 0x%lx\n", (long)AvARRAY(sv));
PerlIO_printf(Perl_debug_log, " ALLOC = 0x%lx\n", (long)AvALLOC(sv));
- PerlIO_printf(Perl_debug_log, " FILL = %ld\n", (long)AvFILL(sv));
+ PerlIO_printf(Perl_debug_log, " FILL = %ld\n", (long)AvFILLp(sv));
PerlIO_printf(Perl_debug_log, " MAX = %ld\n", (long)AvMAX(sv));
PerlIO_printf(Perl_debug_log, " ARYLEN = 0x%lx\n", (long)AvARYLEN(sv));
flags = AvFLAGS(sv);
diff --git a/t/lib/tie-push.t b/t/lib/tie-push.t
new file mode 100755
index 0000000000..dd718deb14
--- /dev/null
+++ b/t/lib/tie-push.t
@@ -0,0 +1,24 @@
+#!./perl
+
+BEGIN {
+ chdir 't' if -d 't';
+ @INC = '../lib';
+}
+
+{
+ package Basic;
+ use Tie::Array;
+ @ISA = qw(Tie::Array);
+
+ sub TIEARRAY { return bless [], shift }
+ sub FETCH { $_[0]->[$_[1]] }
+ sub STORE { $_[0]->[$_[1]] = $_[2] }
+ sub FETCHSIZE { scalar(@{$_[0]}) }
+ sub STORESIZE { $#{$_[0]} = $_[1]-1 }
+}
+
+tie @x,Basic;
+tie @get,Basic;
+tie @got,Basic;
+tie @tests,Basic;
+require "../t/op/push.t"
diff --git a/t/lib/tie-stdarray.t b/t/lib/tie-stdarray.t
new file mode 100755
index 0000000000..7ca4d76f11
--- /dev/null
+++ b/t/lib/tie-stdarray.t
@@ -0,0 +1,12 @@
+#!./perl
+
+BEGIN {
+ chdir 't' if -d 't';
+ @INC = '../lib';
+}
+
+use Tie::Array;
+tie @foo,Tie::StdArray;
+tie @ary,Tie::StdArray;
+tie @bar,Tie::StdArray;
+require "../t/op/array.t"
diff --git a/t/lib/tie-stdpush.t b/t/lib/tie-stdpush.t
new file mode 100755
index 0000000000..34a69472f4
--- /dev/null
+++ b/t/lib/tie-stdpush.t
@@ -0,0 +1,10 @@
+#!./perl
+
+BEGIN {
+ chdir 't' if -d 't';
+ @INC = '../lib';
+}
+
+use Tie::Array;
+tie @x,Tie::StdArray;
+require "../t/op/push.t"
diff --git a/t/op/avhv.t b/t/op/avhv.t
index 0390429d2b..a7ce58ab87 100755
--- a/t/op/avhv.t
+++ b/t/op/avhv.t
@@ -1,13 +1,23 @@
#!./perl
+
+BEGIN {
+ chdir 't' if -d 't';
+ @INC = '../lib';
+}
+
+require Tie::Array;
-package Tie::StdArray;
+package Tie::BasicArray;
+@ISA = 'Tie::Array';
sub TIEARRAY { bless [], $_[0] }
-sub STORE { $_[0]->[$_[1]] = $_[2] }
-sub FETCH { $_[0]->[$_[1]] }
+sub STORE { $_[0]->[$_[1]] = $_[2] }
+sub FETCH { $_[0]->[$_[1]] }
+sub FETCHSIZE { scalar(@{$_[0]})}
+sub STORESIZE { $#{$_[0]} = $_[1]+1 }
package main;
-print "1..4\n";
+print "1..5\n";
$sch = {
'abc' => 1,
@@ -48,12 +58,19 @@ $a->[0] = $sch;
$a->{'abc'} = 'ABC';
if ($a->{'abc'} eq 'ABC') {print "ok 3\n";} else {print "not ok 3\n";}
+# quick check with tied array
+tie @fake, 'Tie::BasicArray';
+$a = \@fake;
+$a->[0] = $sch;
+
+$a->{'abc'} = 'ABC';
+if ($a->{'abc'} eq 'ABC') {print "ok 4\n";} else {print "not ok 4\n";}
+
# quick check with tied array & tied hash
-@INC = ("./lib", "../lib");
require Tie::Hash;
tie %fake, Tie::StdHash;
%fake = %$sch;
$a->[0] = \%fake;
$a->{'abc'} = 'ABC';
-if ($a->{'abc'} eq 'ABC') {print "ok 4\n";} else {print "not ok 4\n";}
+if ($a->{'abc'} eq 'ABC') {print "ok 5\n";} else {print "not ok 5\n";}
diff --git a/t/op/push.t b/t/op/push.t
index 68fab66af7..f62a4e9d8e 100755
--- a/t/op/push.t
+++ b/t/op/push.t
@@ -22,7 +22,7 @@ die "blech" unless @tests;
@x = (1,2,3);
push(@x,@x);
if (join(':',@x) eq '1:2:3:1:2:3') {print "ok 1\n";} else {print "not ok 1\n";}
-push(x,4);
+push(@x,4);
if (join(':',@x) eq '1:2:3:1:2:3:4') {print "ok 2\n";} else {print "not ok 2\n";}
$test = 3;
@@ -47,3 +47,4 @@ foreach $line (@tests) {
}
}
+1; # this file is require'd by lib/tie-stdpush.t
diff --git a/t/op/tiearray.t b/t/op/tiearray.t
new file mode 100755
index 0000000000..8e78b2f76b
--- /dev/null
+++ b/t/op/tiearray.t
@@ -0,0 +1,210 @@
+#!./perl
+
+
+BEGIN {
+ chdir 't' if -d 't';
+ @INC = '../lib';
+}
+
+my %seen;
+
+package Implement;
+
+sub TIEARRAY
+{
+ $seen{'TIEARRAY'}++;
+ my ($class,@val) = @_;
+ return bless \@val,$class;
+}
+
+sub STORESIZE
+{
+ $seen{'STORESIZE'}++;
+ my ($ob,$sz) = @_;
+ return $#{$ob} = $sz-1;
+}
+
+sub EXTEND
+{
+ $seen{'EXTEND'}++;
+ my ($ob,$sz) = @_;
+ return @$ob = $sz;
+}
+
+sub FETCHSIZE
+{
+ $seen{'FETCHSIZE'}++;
+ return scalar(@{$_[0]});
+}
+
+sub FETCH
+{
+ $seen{'FETCH'}++;
+ my ($ob,$id) = @_;
+ return $ob->[$id];
+}
+
+sub STORE
+{
+ $seen{'STORE'}++;
+ my ($ob,$id,$val) = @_;
+ $ob->[$id] = $val;
+}
+
+sub UNSHIFT
+{
+ $seen{'UNSHIFT'}++;
+ my $ob = shift;
+ unshift(@$ob,@_);
+}
+
+sub PUSH
+{
+ $seen{'PUSH'}++;
+ my $ob = shift;;
+ push(@$ob,@_);
+}
+
+sub CLEAR
+{
+ $seen{'CLEAR'}++;
+ @{$_[0]} = ();
+}
+
+sub DESTROY
+{
+ $seen{'DESTROY'}++;
+}
+
+sub POP
+{
+ $seen{'POP'}++;
+ my ($ob) = @_;
+ return pop(@$ob);
+}
+
+sub SHIFT
+{
+ $seen{'SHIFT'}++;
+ my ($ob) = @_;
+ return shift(@$ob);
+}
+
+sub SPLICE
+{
+ $seen{'SPLICE'}++;
+ my $ob = shift;
+ my $off = @_ ? shift : 0;
+ my $len = @_ ? shift : @$ob-1;
+ return splice(@$ob,$off,$len,@_);
+}
+
+package main;
+
+print "1..31\n";
+my $test = 1;
+
+{my @ary;
+
+{ my $ob = tie @ary,'Implement',3,2,1;
+ print "not " unless $ob;
+ print "ok ", $test++,"\n";
+ print "not " unless tied(@ary) == $ob;
+ print "ok ", $test++,"\n";
+}
+
+
+print "not " unless @ary == 3;
+print "ok ", $test++,"\n";
+
+print "not " unless $#ary == 2;
+print "ok ", $test++,"\n";
+
+print "not " unless join(':',@ary) eq '3:2:1';
+print "ok ", $test++,"\n";
+
+print "not " unless $seen{'FETCH'} >= 3;
+print "ok ", $test++,"\n";
+
+@ary = (1,2,3);
+
+print "not " unless $seen{'STORE'} >= 3;
+print "ok ", $test++,"\n";
+print "not " unless join(':',@ary) eq '1:2:3';
+print "ok ", $test++,"\n";
+
+{my @thing = @ary;
+print "not " unless join(':',@thing) eq '1:2:3';
+print "ok ", $test++,"\n";
+
+tie @thing,'Implement';
+@thing = @ary;
+print "not " unless join(':',@thing) eq '1:2:3';
+print "ok ", $test++,"\n";
+}
+
+print "not " unless pop(@ary) == 3;
+print "ok ", $test++,"\n";
+print "not " unless $seen{'POP'} == 1;
+print "ok ", $test++,"\n";
+print "not " unless join(':',@ary) eq '1:2';
+print "ok ", $test++,"\n";
+
+push(@ary,4);
+print "not " unless $seen{'PUSH'} == 1;
+print "ok ", $test++,"\n";
+print "not " unless join(':',@ary) eq '1:2:4';
+print "ok ", $test++,"\n";
+
+my @x = splice(@ary,1,1,7);
+
+
+print "not " unless $seen{'SPLICE'} == 1;
+print "ok ", $test++,"\n";
+
+print "not " unless @x == 1;
+print "ok ", $test++,"\n";
+print "not " unless $x[0] == 2;
+print "ok ", $test++,"\n";
+print "not " unless join(':',@ary) eq '1:7:4';
+print "ok ", $test++,"\n";
+
+print "not " unless shift(@ary) == 1;
+print "ok ", $test++,"\n";
+print "not " unless $seen{'SHIFT'} == 1;
+print "ok ", $test++,"\n";
+print "not " unless join(':',@ary) eq '7:4';
+print "ok ", $test++,"\n";
+
+my $n = unshift(@ary,5,6);
+print "not " unless $seen{'UNSHIFT'} == 1;
+print "ok ", $test++,"\n";
+print "not " unless $n == 4;
+print "ok ", $test++,"\n";
+print "not " unless join(':',@ary) eq '5:6:7:4';
+print "ok ", $test++,"\n";
+
+@ary = split(/:/,'1:2:3');
+print "not " unless join(':',@ary) eq '1:2:3';
+print "ok ", $test++,"\n";
+
+my $t = 0;
+foreach $n (@ary)
+ {
+ print "not " unless $n == ++$t;
+ print "ok ", $test++,"\n";
+ }
+
+@ary = qw(3 2 1);
+print "not " unless join(':',@ary) eq '3:2:1';
+print "ok ", $test++,"\n";
+
+untie @ary;
+
+}
+
+print "not " unless $seen{'DESTROY'} == 2;
+print "ok ", $test++,"\n";
+
+
+
diff --git a/toke.c b/toke.c
index 6773f3f13c..3c4ed6e153 100644
--- a/toke.c
+++ b/toke.c
@@ -1120,10 +1120,10 @@ filter_del(filter_t funcp)
{
if (filter_debug)
warn("filter_del func %p", funcp);
- if (!rsfp_filters || AvFILL(rsfp_filters)<0)
+ if (!rsfp_filters || AvFILLp(rsfp_filters)<0)
return;
/* if filter is on top of stack (usual case) just pop it off */
- if (IoDIRP(FILTER_DATA(AvFILL(rsfp_filters))) == (void*)funcp){
+ if (IoDIRP(FILTER_DATA(AvFILLp(rsfp_filters))) == (void*)funcp){
sv_free(av_pop(rsfp_filters));
return;
@@ -1145,7 +1145,7 @@ filter_read(int idx, SV *buf_sv, int maxlen)
if (!rsfp_filters)
return -1;
- if (idx > AvFILL(rsfp_filters)){ /* Any more filters? */
+ if (idx > AvFILLp(rsfp_filters)){ /* Any more filters? */
/* Provide a default input filter to make life easy. */
/* Note that we append to the line. This is handy. */
if (filter_debug)
@@ -1195,7 +1195,7 @@ filter_read(int idx, SV *buf_sv, int maxlen)
static char *
-filter_gets(register SV *sv, register FILE *fp, STRLEN append)
+filter_gets(register SV *sv, register PerlIO *fp, STRLEN append)
{
#ifdef WIN32FILTER
if (!rsfp_filters) {
@@ -1503,7 +1503,7 @@ yylex(void)
if (SvCUR(linestr))
sv_catpv(linestr,";");
if (preambleav){
- while(AvFILL(preambleav) >= 0) {
+ while(AvFILLp(preambleav) >= 0) {
SV *tmpsv = av_shift(preambleav);
sv_catsv(linestr, tmpsv);
sv_catpv(linestr, ";");
diff --git a/universal.c b/universal.c
index 9a867631d0..67f96c381b 100644
--- a/universal.c
+++ b/universal.c
@@ -48,7 +48,8 @@ isa_lookup(HV *stash, char *name, int len, int level)
}
if(hv) {
SV** svp = AvARRAY(av);
- I32 items = AvFILL(av) + 1;
+ /* NOTE: No support for tied ISA */
+ I32 items = AvFILLp(av) + 1;
while (items--) {
SV* sv = *svp++;
HV* basestash = gv_stashsv(sv, FALSE);
diff --git a/util.c b/util.c
index 1c4b79af7f..0380085995 100644
--- a/util.c
+++ b/util.c
@@ -2013,7 +2013,7 @@ rsignal_restore(int signo, Sigsave_t *save)
/* VMS' my_pclose() is in VMS.c; same with OS/2 */
#if (!defined(DOSISH) || defined(HAS_FORK) || defined(AMIGAOS)) && !defined(VMS)
I32
-my_pclose(FILE *ptr)
+my_pclose(PerlIO *ptr)
{
Sigsave_t hstat, istat, qstat;
int status;
@@ -2543,7 +2543,7 @@ new_struct_thread(struct perl_thread *t)
/* Initialise all per-thread SVs that the template thread used */
svp = AvARRAY(t->threadsv);
- for (i = 0; i <= AvFILL(t->threadsv); i++, svp++) {
+ for (i = 0; i <= AvFILLp(t->threadsv); i++, svp++) {
if (*svp && *svp != &sv_undef) {
SV *sv = newSVsv(*svp);
av_store(thr->threadsv, i, sv);