I just got bitten by the problem foreach (and grep, map, and sub
calls) have changing elements in an array. (Namely that sv_undef
placeholders produce "Modification of a read-only value" error.) I've
fixed this by forcing the elements to become real in such situations.
Of course, this may cost if someone loops over a sparse array
*without* modifying elements, but I doubt this happens too often.
Getting it working right seems more important anyway.
(Example:
$unk = "unknown0000";
$row[2] = "xsize";
foreach $elt (@row) {
$elt = ++$unk unless defined $elt;
}
)
Mark
*** pp_hot.c.bak Wed Aug 30 13:05:09 1995
--- pp_hot.c Wed Aug 30 13:22:05 1995
***************
*** 378,387 ****
}
if (GIMME == G_ARRAY) {
! I32 maxarg = AvFILL(av) + 1;
! EXTEND(SP, maxarg);
! Copy(AvARRAY(av), SP+1, maxarg, SV*);
! SP += maxarg;
}
else {
dTARGET;
--- 378,407 ----
}
if (GIMME == G_ARRAY) {
! if (op->op_flags & OPf_MOD) {
! I32 maxarg = AvFILL(av) + 1;
! I32 key;
! SV** ary;
!
! EXTEND(SP, maxarg);
! ary = AvARRAY(av);
! for (key = 0; key < maxarg; ++key) {
! SV* it = ary[key];
!
! if (it == &sv_undef) {
! it = NEWSV(68,0);
! av_store(av,key,it);
! ary = AvARRAY(av);
! }
! *++SP = it;
! }
! }
! else {
! I32 maxarg = AvFILL(av) + 1;
! EXTEND(SP, maxarg);
! Copy(AvARRAY(av), SP+1, maxarg, SV*);
! SP += maxarg;
! }
}
else {
dTARGET;
*** pp.c.bak Wed Aug 30 13:40:09 1995
--- pp.c Wed Aug 30 13:42:51 1995
***************
*** 46,55 ****
RETURN;
}
if (GIMME == G_ARRAY) {
! I32 maxarg = AvFILL((AV*)TARG) + 1;
! EXTEND(SP, maxarg);
! Copy(AvARRAY((AV*)TARG), SP+1, maxarg, SV*);
! SP += maxarg;
}
else {
SV* sv = sv_newmortal();
--- 46,75 ----
RETURN;
}
if (GIMME == G_ARRAY) {
! if (op->op_flags & OPf_MOD) {
! I32 maxarg = AvFILL((AV*)TARG) + 1;
! I32 key;
! SV** ary;
!
! EXTEND(SP, maxarg);
! ary = AvARRAY((AV*)TARG);
! for (key = 0; key < maxarg; ++key) {
! SV* it = ary[key];
!
! if (it == &sv_undef) {
! it = NEWSV(68,0);
! av_store((AV*)TARG,key,it);
! ary = AvARRAY((AV*)TARG);
! }
! *++SP = it;
! }
! }
! else {
! I32 maxarg = AvFILL((AV*)TARG) + 1;
! EXTEND(SP, maxarg);
! Copy(AvARRAY((AV*)TARG), SP+1, maxarg, SV*);
! SP += maxarg;
! }
}
else {
SV* sv = sv_newmortal();
calls) have changing elements in an array. (Namely that sv_undef
placeholders produce "Modification of a read-only value" error.) I've
fixed this by forcing the elements to become real in such situations.
Of course, this may cost if someone loops over a sparse array
*without* modifying elements, but I doubt this happens too often.
Getting it working right seems more important anyway.
(Example:
$unk = "unknown0000";
$row[2] = "xsize";
foreach $elt (@row) {
$elt = ++$unk unless defined $elt;
}
)
Mark
*** pp_hot.c.bak Wed Aug 30 13:05:09 1995
--- pp_hot.c Wed Aug 30 13:22:05 1995
***************
*** 378,387 ****
}
if (GIMME == G_ARRAY) {
! I32 maxarg = AvFILL(av) + 1;
! EXTEND(SP, maxarg);
! Copy(AvARRAY(av), SP+1, maxarg, SV*);
! SP += maxarg;
}
else {
dTARGET;
--- 378,407 ----
}
if (GIMME == G_ARRAY) {
! if (op->op_flags & OPf_MOD) {
! I32 maxarg = AvFILL(av) + 1;
! I32 key;
! SV** ary;
!
! EXTEND(SP, maxarg);
! ary = AvARRAY(av);
! for (key = 0; key < maxarg; ++key) {
! SV* it = ary[key];
!
! if (it == &sv_undef) {
! it = NEWSV(68,0);
! av_store(av,key,it);
! ary = AvARRAY(av);
! }
! *++SP = it;
! }
! }
! else {
! I32 maxarg = AvFILL(av) + 1;
! EXTEND(SP, maxarg);
! Copy(AvARRAY(av), SP+1, maxarg, SV*);
! SP += maxarg;
! }
}
else {
dTARGET;
*** pp.c.bak Wed Aug 30 13:40:09 1995
--- pp.c Wed Aug 30 13:42:51 1995
***************
*** 46,55 ****
RETURN;
}
if (GIMME == G_ARRAY) {
! I32 maxarg = AvFILL((AV*)TARG) + 1;
! EXTEND(SP, maxarg);
! Copy(AvARRAY((AV*)TARG), SP+1, maxarg, SV*);
! SP += maxarg;
}
else {
SV* sv = sv_newmortal();
--- 46,75 ----
RETURN;
}
if (GIMME == G_ARRAY) {
! if (op->op_flags & OPf_MOD) {
! I32 maxarg = AvFILL((AV*)TARG) + 1;
! I32 key;
! SV** ary;
!
! EXTEND(SP, maxarg);
! ary = AvARRAY((AV*)TARG);
! for (key = 0; key < maxarg; ++key) {
! SV* it = ary[key];
!
! if (it == &sv_undef) {
! it = NEWSV(68,0);
! av_store((AV*)TARG,key,it);
! ary = AvARRAY((AV*)TARG);
! }
! *++SP = it;
! }
! }
! else {
! I32 maxarg = AvFILL((AV*)TARG) + 1;
! EXTEND(SP, maxarg);
! Copy(AvARRAY((AV*)TARG), SP+1, maxarg, SV*);
! SP += maxarg;
! }
}
else {
SV* sv = sv_newmortal();