tmpstr = POPs;
if (SvROK(tmpstr)) {
- SV *sv = SvRV(tmpstr);
+ SV * const sv = SvRV(tmpstr);
if(SvMAGICAL(sv))
mg = mg_find(sv, PERL_MAGIC_qr);
}
else {
STRLEN len;
const char *t = SvPV_const(tmpstr, len);
+ regexp * const re = PM_GETRE(pm);
/* Check against the last compiled regexp. */
- if (!PM_GETRE(pm) || !PM_GETRE(pm)->precomp ||
- PM_GETRE(pm)->prelen != (I32)len ||
- memNE(PM_GETRE(pm)->precomp, t, len))
+ if (!re || !re->precomp || re->prelen != (I32)len ||
+ memNE(re->precomp, t, len))
{
- if (PM_GETRE(pm)) {
- ReREFCNT_dec(PM_GETRE(pm));
+ if (re) {
+ ReREFCNT_dec(re);
PM_SETRE(pm, NULL); /* crucial if regcomp aborts */
}
if (PL_op->op_flags & OPf_SPECIAL)
if(old != rx) {
if(old)
ReREFCNT_dec(old);
- PM_SETRE(pm,rx);
+ PM_SETRE(pm,ReREFCNT_inc(rx));
}
rxres_restore(&cx->sb_rxres, rx);
if (DO_UTF8(dstr))
SvUTF8_on(targ);
SvPV_set(dstr, NULL);
- sv_free(dstr);
TAINT_IF(cx->sb_rxtainted & 1);
PUSHs(sv_2mortal(newSViv(saviters - 1)));
SvTAINT(targ);
LEAVE_SCOPE(cx->sb_oldsave);
- ReREFCNT_dec(rx);
POPSUBST(cx);
RETURNOP(pm->op_next);
}
case FF_0DECIMAL:
arg = *fpc++;
#if defined(USE_LONG_DOUBLE)
- fmt = (arg & 256) ? "%#0*.*" PERL_PRIfldbl : "%0*.*" PERL_PRIfldbl;
+ fmt = (const char *)
+ ((arg & 256) ?
+ "%#0*.*" PERL_PRIfldbl : "%0*.*" PERL_PRIfldbl);
#else
- fmt = (arg & 256) ? "%#0*.*f" : "%0*.*f";
+ fmt = (const char *)
+ ((arg & 256) ?
+ "%#0*.*f" : "%0*.*f");
#endif
goto ff_dec;
case FF_DECIMAL:
arg = *fpc++;
#if defined(USE_LONG_DOUBLE)
- fmt = (arg & 256) ? "%#*.*" PERL_PRIfldbl : "%*.*" PERL_PRIfldbl;
+ fmt = (const char *)
+ ((arg & 256) ? "%#*.*" PERL_PRIfldbl : "%*.*" PERL_PRIfldbl);
#else
- fmt = (arg & 256) ? "%#*.*f" : "%*.*f";
+ fmt = (const char *)
+ ((arg & 256) ? "%#*.*f" : "%*.*f");
#endif
ff_dec:
/* If the field is marked with ^ and the value is undefined,
/* Formats aren't yet marked for locales, so assume "yes". */
{
STORE_NUMERIC_STANDARD_SET_LOCAL();
- sprintf(t, fmt, (int) fieldsize, (int) arg & 255, value);
+ my_snprintf(t, SvLEN(PL_formtarget) - (t - SvPVX(PL_formtarget)), fmt, (int) fieldsize, (int) arg & 255, value);
RESTORE_NUMERIC_STANDARD();
}
t += fieldsize;
else if (PL_errors)
sv_catsv(PL_errors, err);
else
- Perl_warn(aTHX_ "%"SVf, err);
+ Perl_warn(aTHX_ "%"SVf, (void*)err);
++PL_error_count;
}
if (CxTYPE(cx) != CXt_EVAL) {
if (!message)
message = SvPVx_const(ERRSV, msglen);
- PerlIO_write(Perl_error_log, "panic: die ", 11);
+ PerlIO_write(Perl_error_log, (const char *)"panic: die ", 11);
PerlIO_write(Perl_error_log, message, msglen);
my_exit(1);
}
PUSHs(sv_2mortal(newSViv(CopHINTS_get(cx->blk_oldcop))));
{
SV * mask ;
- SV * const old_warnings = cx->blk_oldcop->cop_warnings ;
+ STRLEN * const old_warnings = cx->blk_oldcop->cop_warnings ;
if (old_warnings == pWARN_NONE ||
(old_warnings == pWARN_STD && (PL_dowarn & G_WARN_ON) == 0))
}
}
else
- mask = newSVsv(old_warnings);
+ mask = newSVpvn((char *) (old_warnings + 1), old_warnings[0]);
PUSHs(sv_2mortal(mask));
}
- PUSHs(cx->blk_oldcop->cop_hints ?
+ PUSHs(cx->blk_oldcop->cop_hints_hash ?
sv_2mortal(newRV_noinc(
- (SV*)Perl_refcounted_he_chain_2hv(aTHX_
- cx->blk_oldcop->cop_hints)))
+ (SV*)Perl_refcounted_he_chain_2hv(aTHX_
+ cx->blk_oldcop->cop_hints_hash)))
: &PL_sv_undef);
RETURN;
}
{
dVAR;
dSP;
- const char * const tmps = (MAXARG < 1) ? "" : POPpconstx;
+ const char * const tmps = (MAXARG < 1) ? (const char *)"" : POPpconstx;
sv_reset(tmps, CopSTASH(PL_curcop));
PUSHs(&PL_sv_yes);
RETURN;
TAINT_NOT;
if (gimme == G_VOID)
- /*EMPTY*/; /* do nothing */
+ NOOP;
else if (gimme == G_SCALAR) {
if (mark < SP)
*++newsp = sv_mortalcopy(*SP);
/* Unassume the success we assumed earlier. */
SV * const nsv = cx->blk_eval.old_namesv;
(void)hv_delete(GvHVn(PL_incgv), SvPVX_const(nsv), SvCUR(nsv), G_DISCARD);
- DIE(aTHX_ "%"SVf" did not return a true value", nsv);
+ DIE(aTHX_ "%"SVf" did not return a true value", (void*)nsv);
}
break;
case CXt_FORMAT:
goto retry;
tmpstr = sv_newmortal();
gv_efullname3(tmpstr, gv, NULL);
- DIE(aTHX_ "Goto undefined subroutine &%"SVf"",tmpstr);
+ DIE(aTHX_ "Goto undefined subroutine &%"SVf"",(void*)tmpstr);
}
DIE(aTHX_ "Goto undefined subroutine");
}
CvDEPTH(cv)++;
if (CvDEPTH(cv) < 2)
- SvREFCNT_inc_void_NN(cv);
+ SvREFCNT_inc_simple_void_NN(cv);
else {
if (CvDEPTH(cv) == 100 && ckWARN(WARN_RECURSION))
sub_crush_depth(cv);
len = SvCUR(sv);
}
else
- len = my_sprintf(tmpbuf, "_<(%.10s_eval %lu)", code,
- (unsigned long)++PL_evalseq);
+ len = my_snprintf(tmpbuf, sizeof(tbuf), "_<(%.10s_eval %lu)", code,
+ (unsigned long)++PL_evalseq);
SAVECOPFILE_FREE(&PL_compiling);
CopFILE_set(&PL_compiling, tmpbuf+2);
SAVECOPLINE(&PL_compiling);
/* set up a scratch pad */
CvPADLIST(PL_compcv) = pad_new(padnew_SAVE);
+ PL_op = NULL; /* avoid PL_op and PL_curpad referring to different CVs */
if (!PL_madskills)
DEBUG_x(dump_eval());
/* Register with debugger: */
- if (PERLDB_INTER && saveop->op_type == OP_REQUIRE) {
+ if (PERLDB_INTER && saveop && saveop->op_type == OP_REQUIRE) {
CV * const cv = get_cv("DB::postponed", FALSE);
if (cv) {
dSP;
{
Stat_t st;
const int st_rc = PerlLIO_stat(name, &st);
+
if (st_rc < 0 || S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode)) {
return NULL;
}
const I32 gimme = GIMME_V;
int filter_has_file = 0;
PerlIO *tryrsfp = NULL;
- GV *filter_child_proc = NULL;
+ SV *filter_cache = NULL;
SV *filter_state = NULL;
SV *filter_sub = NULL;
SV *hook_sv = NULL;
if (!sv_derived_from(PL_patchlevel, "version"))
upg_version(PL_patchlevel);
if (cUNOP->op_first->op_type == OP_CONST && cUNOP->op_first->op_private & OPpCONST_NOVER) {
- if ( vcmp(sv,PL_patchlevel) < 0 )
+ if ( vcmp(sv,PL_patchlevel) <= 0 )
DIE(aTHX_ "Perls since %"SVf" too modern--this is %"SVf", stopped",
- vnormal(sv), vnormal(PL_patchlevel));
+ (void*)vnormal(sv), (void*)vnormal(PL_patchlevel));
}
else {
if ( vcmp(sv,PL_patchlevel) > 0 )
DIE(aTHX_ "Perl %"SVf" required--this is only %"SVf", stopped",
- vnormal(sv), vnormal(PL_patchlevel));
+ (void*)vnormal(sv), (void*)vnormal(PL_patchlevel));
}
RETPUSHYES;
{
namesv = newSV(0);
for (i = 0; i <= AvFILL(ar); i++) {
- SV *dirsv = *av_fetch(ar, i, TRUE);
+ SV * const dirsv = *av_fetch(ar, i, TRUE);
if (SvROK(dirsv)) {
int count;
SP -= count - 1;
arg = SP[i++];
+ if (SvROK(arg) && (SvTYPE(SvRV(arg)) <= SVt_PVLV)
+ && !isGV_with_GP(SvRV(arg))) {
+ filter_cache = SvRV(arg);
+ SvREFCNT_inc_simple_void_NN(filter_cache);
+
+ if (i < count) {
+ arg = SP[i++];
+ }
+ }
+
if (SvROK(arg) && SvTYPE(SvRV(arg)) == SVt_PVGV) {
arg = SvRV(arg);
}
if (SvTYPE(arg) == SVt_PVGV) {
- IO *io = GvIO((GV *)arg);
+ IO * const io = GvIO((GV *)arg);
++filter_has_file;
if (io) {
tryrsfp = IoIFP(io);
- if (IoTYPE(io) == IoTYPE_PIPE) {
- /* reading from a child process doesn't
- nest -- when returning from reading
- the inner module, the outer one is
- unreadable (closed?) I've tried to
- save the gv to manage the lifespan of
- the pipe, but this didn't help. XXX */
- filter_child_proc = (GV *)arg;
- SvREFCNT_inc_simple_void(filter_child_proc);
- }
- else {
- if (IoOFP(io) && IoOFP(io) != IoIFP(io)) {
- PerlIO_close(IoOFP(io));
- }
- IoIFP(io) = NULL;
- IoOFP(io) = NULL;
+ if (IoOFP(io) && IoOFP(io) != IoIFP(io)) {
+ PerlIO_close(IoOFP(io));
}
+ IoIFP(io) = NULL;
+ IoOFP(io) = NULL;
}
if (i < count) {
if (SvROK(arg) && SvTYPE(SvRV(arg)) == SVt_PVCV) {
filter_sub = arg;
- SvREFCNT_inc_void_NN(filter_sub);
+ SvREFCNT_inc_simple_void_NN(filter_sub);
if (i < count) {
filter_state = SP[i];
SvREFCNT_inc_simple_void(filter_state);
}
+ }
- if (!tryrsfp) {
- tryrsfp = PerlIO_open("/dev/null", PERL_SCRIPT_MODE);
- }
+ if (!tryrsfp && (filter_cache || filter_sub)) {
+ tryrsfp = PerlIO_open(BIT_BUCKET,
+ PERL_SCRIPT_MODE);
}
SP--;
}
}
filter_has_file = 0;
- if (filter_child_proc) {
- SvREFCNT_dec(filter_child_proc);
- filter_child_proc = NULL;
+ if (filter_cache) {
+ SvREFCNT_dec(filter_cache);
+ filter_cache = NULL;
}
if (filter_state) {
SvREFCNT_dec(filter_state);
tryname += 2;
break;
}
+ else if (errno == EMFILE)
+ /* no point in trying other paths if out of handles */
+ break;
}
}
}
PL_rsfp = tryrsfp;
SAVEHINTS();
PL_hints = 0;
- SAVESPTR(PL_compiling.cop_warnings);
+ SAVECOMPILEWARNINGS();
if (PL_dowarn & G_WARN_ALL_ON)
PL_compiling.cop_warnings = pWARN_ALL ;
else if (PL_dowarn & G_WARN_ALL_OFF)
PL_compiling.cop_warnings = pWARN_NONE ;
- else if (PL_taint_warn)
- PL_compiling.cop_warnings = newSVpvn(WARN_TAINTstring, WARNsize);
+ else if (PL_taint_warn) {
+ PL_compiling.cop_warnings
+ = Perl_new_warnings_bitfield(aTHX_ NULL, WARN_TAINTstring, WARNsize);
+ }
else
PL_compiling.cop_warnings = pWARN_STD ;
- SAVESPTR(PL_compiling.cop_io);
- PL_compiling.cop_io = NULL;
- if (filter_sub || filter_child_proc) {
+ if (filter_sub || filter_cache) {
SV * const datasv = filter_add(S_run_user_filter, NULL);
IoLINES(datasv) = filter_has_file;
- IoFMT_GV(datasv) = (GV *)filter_child_proc;
IoTOP_GV(datasv) = (GV *)filter_state;
IoBOTTOM_GV(datasv) = (GV *)filter_sub;
+ IoFMT_GV(datasv) = (GV *)filter_cache;
}
/* switch to eval mode */
CV* runcv;
U32 seq;
HV *saved_hh = NULL;
+ const char * const fakestr = "_<(eval )";
+ const int fakelen = 9 + 1;
if (PL_op->op_private & OPpEVAL_HAS_HH) {
saved_hh = (HV*) SvREFCNT_inc(POPs);
len = SvCUR(temp_sv);
}
else
- len = my_sprintf(tmpbuf, "_<(eval %lu)", (unsigned long)++PL_evalseq);
+ len = my_snprintf(tmpbuf, sizeof(tbuf), "_<(eval %lu)", (unsigned long)++PL_evalseq);
SAVECOPFILE_FREE(&PL_compiling);
CopFILE_set(&PL_compiling, tmpbuf+2);
SAVECOPLINE(&PL_compiling);
PL_hints = PL_op->op_targ;
if (saved_hh)
GvHV(PL_hintgv) = saved_hh;
- SAVESPTR(PL_compiling.cop_warnings);
- if (specialWARN(PL_curcop->cop_warnings))
- PL_compiling.cop_warnings = PL_curcop->cop_warnings;
- else {
- PL_compiling.cop_warnings = newSVsv(PL_curcop->cop_warnings);
- SAVEFREESV(PL_compiling.cop_warnings);
- }
- SAVESPTR(PL_compiling.cop_io);
- if (specialCopIO(PL_curcop->cop_io))
- PL_compiling.cop_io = PL_curcop->cop_io;
- else {
- PL_compiling.cop_io = newSVsv(PL_curcop->cop_io);
- SAVEFREESV(PL_compiling.cop_io);
- }
- if (PL_compiling.cop_hints) {
- PL_compiling.cop_hints->refcounted_he_refcnt--;
+ SAVECOMPILEWARNINGS();
+ PL_compiling.cop_warnings = DUP_WARNINGS(PL_curcop->cop_warnings);
+ if (PL_compiling.cop_hints_hash) {
+ Perl_refcounted_he_free(aTHX_ PL_compiling.cop_hints_hash);
}
- PL_compiling.cop_hints = PL_curcop->cop_hints;
- if (PL_compiling.cop_hints) {
-#ifdef USE_ITHREADS
- /* PL_curcop could be pointing to an optree owned by another /.*parent/
- thread. We can't manipulate the reference count of the refcounted he
- there (race condition) so we have to do something less than
- pleasant to keep it read only. The simplest solution seems to be to
- copy their chain. We might want to cache this.
- Alternatively we could add a flag to the refcounted he *we* point to
- here saying "I don't own a reference count on the thing I point to",
- and arrange for Perl_refcounted_he_free() to spot that. If so, we'd
- still need to copy the topmost refcounted he so that we could change
- its flag. So still not trivial. (Flag bits could be hung from the
- shared HEK) */
- PL_compiling.cop_hints
- = Perl_refcounted_he_copy(aTHX_ PL_compiling.cop_hints);
-#else
- PL_compiling.cop_hints->refcounted_he_refcnt++;
-#endif
+ PL_compiling.cop_hints_hash = PL_curcop->cop_hints_hash;
+ if (PL_compiling.cop_hints_hash) {
+ HINTS_REFCNT_LOCK;
+ PL_compiling.cop_hints_hash->refcounted_he_refcnt++;
+ HINTS_REFCNT_UNLOCK;
}
/* special case: an eval '' executed within the DB package gets lexically
* placed in the first non-DB CV rather than the current CV - this
ret = doeval(gimme, NULL, runcv, seq);
if (PERLDB_INTER && was != (I32)PL_sub_generation /* Some subs defined here. */
&& ret != PL_op->op_next) { /* Successive compilation. */
- strcpy(safestr, "_<(eval )"); /* Anything fake and short. */
+ /* Copy in anything fake and short. */
+ my_strlcpy(safestr, fakestr, fakelen);
}
return DOCATCH(ret);
}
/* Unassume the success we assumed earlier. */
SV * const nsv = cx->blk_eval.old_namesv;
(void)hv_delete(GvHVn(PL_incgv), SvPVX_const(nsv), SvCUR(nsv), G_DISCARD);
- retop = Perl_die(aTHX_ "%"SVf" did not return a true value", nsv);
+ retop = Perl_die(aTHX_ "%"SVf" did not return a true value", (void*)nsv);
/* die_where() did LEAVE, or we won't be here */
}
else {
PP(pp_entertry)
{
dVAR;
- PERL_CONTEXT *cx = create_eval_scope(0);
+ PERL_CONTEXT * const cx = create_eval_scope(0);
cx->blk_eval.retop = cLOGOP->op_other->op_next;
return DOCATCH(PL_op->op_next);
}
return do_smartmatch(NULL, NULL);
}
-/* This version of do_smartmatch() implements the following
- table of smart matches:
-
- $a $b Type of Match Implied Matching Code
- ====== ===== ===================== =============
- (overloading trumps everything)
-
- Code[+] Code[+] referential equality match if refaddr($a) == refaddr($b)
- Any Code[+] scalar sub truth match if $b->($a)
-
- Hash Hash hash keys identical match if sort(keys(%$a)) ÈeqÇ sort(keys(%$b))
- Hash Array hash value slice truth match if $a->{any(@$b)}
- Hash Regex hash key grep match if any(keys(%$a)) =~ /$b/
- Hash Any hash entry existence match if exists $a->{$b}
-
- Array Array arrays are identical[*] match if $a È~~Ç $b
- Array Regex array grep match if any(@$a) =~ /$b/
- Array Num array contains number match if any($a) == $b
- Array Any array contains string match if any($a) eq $b
-
- Any undef undefined match if !defined $a
- Any Regex pattern match match if $a =~ /$b/
- Code() Code() results are equal match if $a->() eq $b->()
- Any Code() simple closure truth match if $b->() (ignoring $a)
- Num numish[!] numeric equality match if $a == $b
- Any Str string equality match if $a eq $b
- Any Num numeric equality match if $a == $b
-
- Any Any string equality match if $a eq $b
-
-
- + - this must be a code reference whose prototype (if present) is not ""
- (subs with a "" prototype are dealt with by the 'Code()' entry lower down)
- * - if a circular reference is found, we fall back to referential equality
- ! - either a real number, or a string that looks_like_number()
-
+/* This version of do_smartmatch() implements the
+ * table of smart matches that is found in perlsyn.
*/
STATIC
OP *
SV *e = TOPs; /* e is for 'expression' */
SV *d = TOPm1s; /* d is for 'default', as in PL_defgv */
- SV *this, *other;
+ SV *This, *Other; /* 'This' (and Other to match) to play with C++ */
MAGIC *mg;
regexp *this_regex, *other_regex;
# define NOT_EMPTY_PROTO(cv) (!SvPOK(cv) || SvCUR(cv) == 0)
# define SM_REF(type) ( \
- (SvROK(d) && (SvTYPE(this = SvRV(d)) == SVt_##type) && (other = e)) \
- || (SvROK(e) && (SvTYPE(this = SvRV(e)) == SVt_##type) && (other = d)))
+ (SvROK(d) && (SvTYPE(This = SvRV(d)) == SVt_##type) && (Other = e)) \
+ || (SvROK(e) && (SvTYPE(This = SvRV(e)) == SVt_##type) && (Other = d)))
# define SM_CV_NEP /* Find a code ref without an empty prototype */ \
- ((SvROK(d) && (SvTYPE(this = SvRV(d)) == SVt_PVCV) \
- && NOT_EMPTY_PROTO(this) && (other = e)) \
- || (SvROK(e) && (SvTYPE(this = SvRV(e)) == SVt_PVCV) \
- && NOT_EMPTY_PROTO(this) && (other = d)))
+ ((SvROK(d) && (SvTYPE(This = SvRV(d)) == SVt_PVCV) \
+ && NOT_EMPTY_PROTO(This) && (Other = e)) \
+ || (SvROK(e) && (SvTYPE(This = SvRV(e)) == SVt_PVCV) \
+ && NOT_EMPTY_PROTO(This) && (Other = d)))
# define SM_REGEX ( \
- (SvROK(d) && SvMAGICAL(this = SvRV(d)) \
- && (mg = mg_find(this, PERL_MAGIC_qr)) \
+ (SvROK(d) && SvMAGICAL(This = SvRV(d)) \
+ && (mg = mg_find(This, PERL_MAGIC_qr)) \
&& (this_regex = (regexp *)mg->mg_obj) \
- && (other = e)) \
+ && (Other = e)) \
|| \
- (SvROK(e) && SvMAGICAL(this = SvRV(e)) \
- && (mg = mg_find(this, PERL_MAGIC_qr)) \
+ (SvROK(e) && SvMAGICAL(This = SvRV(e)) \
+ && (mg = mg_find(This, PERL_MAGIC_qr)) \
&& (this_regex = (regexp *)mg->mg_obj) \
- && (other = d)) )
+ && (Other = d)) )
# define SM_OTHER_REF(type) \
- (SvROK(other) && SvTYPE(SvRV(other)) == SVt_##type)
+ (SvROK(Other) && SvTYPE(SvRV(Other)) == SVt_##type)
-# define SM_OTHER_REGEX (SvROK(other) && SvMAGICAL(SvRV(other)) \
- && (mg = mg_find(SvRV(other), PERL_MAGIC_qr)) \
+# define SM_OTHER_REGEX (SvROK(Other) && SvMAGICAL(SvRV(Other)) \
+ && (mg = mg_find(SvRV(Other), PERL_MAGIC_qr)) \
&& (other_regex = (regexp *)mg->mg_obj))
if (SM_CV_NEP) {
I32 c;
- if ( SM_OTHER_REF(PVCV) && NOT_EMPTY_PROTO(SvRV(other)) )
+ if ( SM_OTHER_REF(PVCV) && NOT_EMPTY_PROTO(SvRV(Other)) )
{
- if (this == SvRV(other))
+ if (This == SvRV(Other))
RETPUSHYES;
else
RETPUSHNO;
ENTER;
SAVETMPS;
PUSHMARK(SP);
- PUSHs(other);
+ PUSHs(Other);
PUTBACK;
- c = call_sv(this, G_SCALAR);
+ c = call_sv(This, G_SCALAR);
SPAGAIN;
if (c == 0)
PUSHs(&PL_sv_no);
else if (SvTEMP(TOPs))
- SvREFCNT_inc(TOPs);
+ SvREFCNT_inc_void(TOPs);
FREETMPS;
LEAVE;
RETURN;
if (SM_OTHER_REF(PVHV)) {
/* Check that the key-sets are identical */
HE *he;
- HV *other_hv = (HV *) SvRV(other);
+ HV *other_hv = (HV *) SvRV(Other);
bool tied = FALSE;
bool other_tied = FALSE;
U32 this_key_count = 0,
other_key_count = 0;
/* Tied hashes don't know how many keys they have. */
- if (SvTIED_mg(this, PERL_MAGIC_tied)) {
+ if (SvTIED_mg(This, PERL_MAGIC_tied)) {
tied = TRUE;
}
else if (SvTIED_mg((SV *) other_hv, PERL_MAGIC_tied)) {
HV * const temp = other_hv;
- other_hv = (HV *) this;
- this = (SV *) temp;
+ other_hv = (HV *) This;
+ This = (SV *) temp;
tied = TRUE;
}
if (SvTIED_mg((SV *) other_hv, PERL_MAGIC_tied))
other_tied = TRUE;
- if (!tied && HvUSEDKEYS((HV *) this) != HvUSEDKEYS(other_hv))
+ if (!tied && HvUSEDKEYS((HV *) This) != HvUSEDKEYS(other_hv))
RETPUSHNO;
/* The hashes have the same number of keys, so it suffices
to check that one is a subset of the other. */
- (void) hv_iterinit((HV *) this);
- while ( (he = hv_iternext((HV *) this)) ) {
+ (void) hv_iterinit((HV *) This);
+ while ( (he = hv_iternext((HV *) This)) ) {
I32 key_len;
char * const key = hv_iterkey(he, &key_len);
++ this_key_count;
if(!hv_exists(other_hv, key, key_len)) {
- (void) hv_iterinit((HV *) this); /* reset iterator */
+ (void) hv_iterinit((HV *) This); /* reset iterator */
RETPUSHNO;
}
}
RETPUSHYES;
}
else if (SM_OTHER_REF(PVAV)) {
- AV * const other_av = (AV *) SvRV(other);
+ AV * const other_av = (AV *) SvRV(Other);
const I32 other_len = av_len(other_av) + 1;
I32 i;
- if (HvUSEDKEYS((HV *) this) != other_len)
+ if (HvUSEDKEYS((HV *) This) != other_len)
RETPUSHNO;
for(i = 0; i < other_len; ++i) {
RETPUSHNO;
key = SvPV(*svp, key_len);
- if(!hv_exists((HV *) this, key, key_len))
+ if(!hv_exists((HV *) This, key, key_len))
RETPUSHNO;
}
RETPUSHYES;
PMOP * const matcher = make_matcher(other_regex);
HE *he;
- (void) hv_iterinit((HV *) this);
- while ( (he = hv_iternext((HV *) this)) ) {
+ (void) hv_iterinit((HV *) This);
+ while ( (he = hv_iternext((HV *) This)) ) {
if (matcher_matches_sv(matcher, hv_iterkeysv(he))) {
- (void) hv_iterinit((HV *) this);
+ (void) hv_iterinit((HV *) This);
destroy_matcher(matcher);
RETPUSHYES;
}
RETPUSHNO;
}
else {
- if (hv_exists_ent((HV *) this, other, 0))
+ if (hv_exists_ent((HV *) This, Other, 0))
RETPUSHYES;
else
RETPUSHNO;
}
else if (SM_REF(PVAV)) {
if (SM_OTHER_REF(PVAV)) {
- AV *other_av = (AV *) SvRV(other);
- if (av_len((AV *) this) != av_len(other_av))
+ AV *other_av = (AV *) SvRV(Other);
+ if (av_len((AV *) This) != av_len(other_av))
RETPUSHNO;
else {
I32 i;
(void) sv_2mortal((SV *) seen_other);
}
for(i = 0; i <= other_len; ++i) {
- SV * const * const this_elem = av_fetch((AV *)this, i, FALSE);
+ SV * const * const this_elem = av_fetch((AV *)This, i, FALSE);
SV * const * const other_elem = av_fetch(other_av, i, FALSE);
if (!this_elem || !other_elem) {
}
else if (SM_OTHER_REGEX) {
PMOP * const matcher = make_matcher(other_regex);
- const I32 this_len = av_len((AV *) this);
+ const I32 this_len = av_len((AV *) This);
I32 i;
for(i = 0; i <= this_len; ++i) {
- SV * const * const svp = av_fetch((AV *)this, i, FALSE);
+ SV * const * const svp = av_fetch((AV *)This, i, FALSE);
if (svp && matcher_matches_sv(matcher, *svp)) {
destroy_matcher(matcher);
RETPUSHYES;
destroy_matcher(matcher);
RETPUSHNO;
}
- else if (SvIOK(other) || SvNOK(other)) {
+ else if (SvIOK(Other) || SvNOK(Other)) {
I32 i;
- for(i = 0; i <= AvFILL((AV *) this); ++i) {
- SV * const * const svp = av_fetch((AV *)this, i, FALSE);
+ for(i = 0; i <= AvFILL((AV *) This); ++i) {
+ SV * const * const svp = av_fetch((AV *)This, i, FALSE);
if (!svp)
continue;
- PUSHs(other);
+ PUSHs(Other);
PUSHs(*svp);
PUTBACK;
- if ((PL_curcop->op_private & HINT_INTEGER) == HINT_INTEGER)
+ if (CopHINTS_get(PL_curcop) & HINT_INTEGER)
(void) pp_i_eq();
else
(void) pp_eq();
}
RETPUSHNO;
}
- else if (SvPOK(other)) {
- const I32 this_len = av_len((AV *) this);
+ else if (SvPOK(Other)) {
+ const I32 this_len = av_len((AV *) This);
I32 i;
for(i = 0; i <= this_len; ++i) {
- SV * const * const svp = av_fetch((AV *)this, i, FALSE);
+ SV * const * const svp = av_fetch((AV *)This, i, FALSE);
if (!svp)
continue;
- PUSHs(other);
+ PUSHs(Other);
PUSHs(*svp);
PUTBACK;
(void) pp_seq();
PMOP * const matcher = make_matcher(this_regex);
PUTBACK;
- PUSHs(matcher_matches_sv(matcher, other)
+ PUSHs(matcher_matches_sv(matcher, Other)
? &PL_sv_yes
: &PL_sv_no);
destroy_matcher(matcher);
SAVETMPS;
PUSHMARK(SP);
PUTBACK;
- c = call_sv(this, G_SCALAR);
+ c = call_sv(This, G_SCALAR);
SPAGAIN;
if (c == 0)
PUSHs(&PL_sv_undef);
else if (SvTEMP(TOPs))
- SvREFCNT_inc(TOPs);
+ SvREFCNT_inc_void(TOPs);
if (SM_OTHER_REF(PVCV)) {
/* This one has to be null-proto'd too.
Call both of 'em, and compare the results */
PUSHMARK(SP);
- c = call_sv(SvRV(other), G_SCALAR);
+ c = call_sv(SvRV(Other), G_SCALAR);
SPAGAIN;
if (c == 0)
PUSHs(&PL_sv_undef);
else if (SvTEMP(TOPs))
- SvREFCNT_inc(TOPs);
+ SvREFCNT_inc_void(TOPs);
FREETMPS;
LEAVE;
PUTBACK;
LEAVE;
RETURN;
}
- else if ( ((SvIOK(d) || SvNOK(d)) && (this = d) && (other = e))
- || ((SvIOK(e) || SvNOK(e)) && (this = e) && (other = d)) )
+ else if ( ((SvIOK(d) || SvNOK(d)) && (This = d) && (Other = e))
+ || ((SvIOK(e) || SvNOK(e)) && (This = e) && (Other = d)) )
{
- if (SvPOK(other) && !looks_like_number(other)) {
+ if (SvPOK(Other) && !looks_like_number(Other)) {
/* String comparison */
PUSHs(d); PUSHs(e);
PUTBACK;
/* Otherwise, numeric comparison */
PUSHs(d); PUSHs(e);
PUTBACK;
- if ((PL_curcop->op_private & HINT_INTEGER) == HINT_INTEGER)
+ if (CopHINTS_get(PL_curcop) & HINT_INTEGER)
(void) pp_i_eq();
else
(void) pp_eq();
dVAR;
SV * const datasv = FILTER_DATA(idx);
const int filter_has_file = IoLINES(datasv);
- GV * const filter_child_proc = (GV *)IoFMT_GV(datasv);
SV * const filter_state = (SV *)IoTOP_GV(datasv);
SV * const filter_sub = (SV *)IoBOTTOM_GV(datasv);
- int len = 0;
+ int status = 0;
+ SV *upstream;
+ STRLEN got_len;
+ const char *got_p = NULL;
+ const char *prune_from = NULL;
+ bool read_from_cache = FALSE;
+ STRLEN umaxlen;
+
+ assert(maxlen >= 0);
+ umaxlen = maxlen;
/* I was having segfault trouble under Linux 2.2.5 after a
parse error occured. (Had to hack around it with a test
for PL_error_count == 0.) Solaris doesn't segfault --
not sure where the trouble is yet. XXX */
+ if (IoFMT_GV(datasv)) {
+ SV *const cache = (SV *)IoFMT_GV(datasv);
+ if (SvOK(cache)) {
+ STRLEN cache_len;
+ const char *cache_p = SvPV(cache, cache_len);
+ STRLEN take = 0;
+
+ if (umaxlen) {
+ /* Running in block mode and we have some cached data already.
+ */
+ if (cache_len >= umaxlen) {
+ /* In fact, so much data we don't even need to call
+ filter_read. */
+ take = umaxlen;
+ }
+ } else {
+ const char *const first_nl =
+ (const char *)memchr(cache_p, '\n', cache_len);
+ if (first_nl) {
+ take = first_nl + 1 - cache_p;
+ }
+ }
+ if (take) {
+ sv_catpvn(buf_sv, cache_p, take);
+ sv_chop(cache, cache_p + take);
+ /* Definately not EOF */
+ return 1;
+ }
+
+ sv_catsv(buf_sv, cache);
+ if (umaxlen) {
+ umaxlen -= cache_len;
+ }
+ SvOK_off(cache);
+ read_from_cache = TRUE;
+ }
+ }
+
+ /* Filter API says that the filter appends to the contents of the buffer.
+ Usually the buffer is "", so the details don't matter. But if it's not,
+ then clearly what it contains is already filtered by this filter, so we
+ don't want to pass it in a second time.
+ I'm going to use a mortal in case the upstream filter croaks. */
+ upstream = ((SvOK(buf_sv) && sv_len(buf_sv)) || SvGMAGICAL(buf_sv))
+ ? sv_newmortal() : buf_sv;
+ SvUPGRADE(upstream, SVt_PV);
+
if (filter_has_file) {
- len = FILTER_READ(idx+1, buf_sv, maxlen);
+ status = FILTER_READ(idx+1, upstream, 0);
}
- if (filter_sub && len >= 0) {
+ if (filter_sub && status >= 0) {
dSP;
int count;
SAVETMPS;
EXTEND(SP, 2);
- DEFSV = buf_sv;
+ DEFSV = upstream;
PUSHMARK(SP);
- PUSHs(sv_2mortal(newSViv(maxlen)));
+ PUSHs(sv_2mortal(newSViv(0)));
if (filter_state) {
PUSHs(filter_state);
}
if (count > 0) {
SV *out = POPs;
if (SvOK(out)) {
- len = SvIV(out);
+ status = SvIV(out);
}
}
LEAVE;
}
- if (len <= 0) {
- IoLINES(datasv) = 0;
- if (filter_child_proc) {
- SvREFCNT_dec(filter_child_proc);
- IoFMT_GV(datasv) = NULL;
+ if(SvOK(upstream)) {
+ got_p = SvPV(upstream, got_len);
+ if (umaxlen) {
+ if (got_len > umaxlen) {
+ prune_from = got_p + umaxlen;
+ }
+ } else {
+ const char *const first_nl =
+ (const char *)memchr(got_p, '\n', got_len);
+ if (first_nl && first_nl + 1 < got_p + got_len) {
+ /* There's a second line here... */
+ prune_from = first_nl + 1;
+ }
+ }
+ }
+ if (prune_from) {
+ /* Oh. Too long. Stuff some in our cache. */
+ STRLEN cached_len = got_p + got_len - prune_from;
+ SV *cache = (SV *)IoFMT_GV(datasv);
+
+ if (!cache) {
+ IoFMT_GV(datasv) = (GV*) (cache = newSV(got_len - umaxlen));
+ } else if (SvOK(cache)) {
+ /* Cache should be empty. */
+ assert(!SvCUR(cache));
}
+
+ sv_setpvn(cache, prune_from, cached_len);
+ /* If you ask for block mode, you may well split UTF-8 characters.
+ "If it breaks, you get to keep both parts"
+ (Your code is broken if you don't put them back together again
+ before something notices.) */
+ if (SvUTF8(upstream)) {
+ SvUTF8_on(cache);
+ }
+ SvCUR_set(upstream, got_len - cached_len);
+ /* Can't yet be EOF */
+ if (status == 0)
+ status = 1;
+ }
+
+ /* If they are at EOF but buf_sv has something in it, then they may never
+ have touched the SV upstream, so it may be undefined. If we naively
+ concatenate it then we get a warning about use of uninitialised value.
+ */
+ if (upstream != buf_sv && (SvOK(upstream) || SvGMAGICAL(upstream))) {
+ sv_catsv(buf_sv, upstream);
+ }
+
+ if (status <= 0) {
+ IoLINES(datasv) = 0;
+ SvREFCNT_dec(IoFMT_GV(datasv));
if (filter_state) {
SvREFCNT_dec(filter_state);
IoTOP_GV(datasv) = NULL;
}
filter_del(S_run_user_filter);
}
-
- return len;
+ if (status == 0 && read_from_cache) {
+ /* If we read some data from the cache (and by getting here it implies
+ that we emptied the cache) then we aren't yet at EOF, and mustn't
+ report that to our caller. */
+ return 1;
+ }
+ return status;
}
/* perhaps someone can come up with a better name for