#ifdef NOTDEF if (go_to) { if (op->cop_label && strEQ(go_to,op->cop_label)) goto_targ = go_to = Nullch; /* here at last */ else { switch (op->cop_type) { case COP_IF: oldspat = curspat; oldsave = savestack->av_fill; #ifdef DEBUGGING olddlevel = dlevel; #endif retstr = &sv_yes; newsp = -2; if (op->uop.ccop_true) { #ifdef DEBUGGING if (debug) { debname[dlevel] = 't'; debdelim[dlevel] = '_'; if (++dlevel >= dlmax) deb_growlevel(); } #endif newsp = cop_exec(op->uop.ccop_true,gimme && (opflags & COPf_TERM),sp); st = stack->av_array; /* possibly reallocated */ retstr = st[newsp]; } if (!goto_targ) go_to = Nullch; curspat = oldspat; if (savestack->av_fill > oldsave) leave_scope(oldsave); #ifdef DEBUGGING dlevel = olddlevel; #endif op = op->uop.ccop_alt; goto tail_recursion_entry; case COP_ELSE: oldspat = curspat; oldsave = savestack->av_fill; #ifdef DEBUGGING olddlevel = dlevel; #endif retstr = &sv_undef; newsp = -2; if (op->uop.ccop_true) { #ifdef DEBUGGING if (debug) { debname[dlevel] = 'e'; debdelim[dlevel] = '_'; if (++dlevel >= dlmax) deb_growlevel(); } #endif newsp = cop_exec(op->uop.ccop_true,gimme && (opflags & COPf_TERM),sp); st = stack->av_array; /* possibly reallocated */ retstr = st[newsp]; } if (!goto_targ) go_to = Nullch; curspat = oldspat; if (savestack->av_fill > oldsave) leave_scope(oldsave); #ifdef DEBUGGING dlevel = olddlevel; #endif break; case COP_BLOCK: case COP_WHILE: if (!(opflags & COPf_ONCE)) { opflags |= COPf_ONCE; if (++loop_ptr >= loop_max) { loop_max += 128; Renew(loop_stack, loop_max, struct loop); } loop_stack[loop_ptr].loop_label = op->cop_label; loop_stack[loop_ptr].loop_sp = sp; #ifdef DEBUGGING if (debug & 4) { deb("(Pushing label #%d %s)\n", loop_ptr, op->cop_label ? op->cop_label : ""); } #endif } #ifdef JMPCLOBBER opparm = op; #endif match = setjmp(loop_stack[loop_ptr].loop_env); if (match) { st = stack->av_array; /* possibly reallocated */ #ifdef JMPCLOBBER op = opparm; opflags = op->cop_flags|COPf_ONCE; #endif if (savestack->av_fill > oldsave) leave_scope(oldsave); switch (match) { default: fatal("longjmp returned bad value (%d)",match); case OP_LAST: /* not done unless go_to found */ go_to = Nullch; if (lastretstr) { retstr = lastretstr; newsp = -2; } else { newsp = sp + lastsize; retstr = st[newsp]; } #ifdef DEBUGGING olddlevel = dlevel; #endif curspat = oldspat; goto next_op; case OP_NEXT: /* not done unless go_to found */ go_to = Nullch; #ifdef JMPCLOBBER newsp = -2; retstr = &sv_undef; #endif goto next_iter; case OP_REDO: /* not done unless go_to found */ go_to = Nullch; #ifdef JMPCLOBBER newsp = -2; retstr = &sv_undef; #endif goto doit; } } oldspat = curspat; oldsave = savestack->av_fill; #ifdef DEBUGGING olddlevel = dlevel; #endif if (op->uop.ccop_true) { #ifdef DEBUGGING if (debug) { debname[dlevel] = 't'; debdelim[dlevel] = '_'; if (++dlevel >= dlmax) deb_growlevel(); } #endif newsp = cop_exec(op->uop.ccop_true,gimme && (opflags & COPf_TERM),sp); st = stack->av_array; /* possibly reallocated */ if (newsp >= 0) retstr = st[newsp]; } if (!goto_targ) { go_to = Nullch; goto next_iter; } #ifdef DEBUGGING dlevel = olddlevel; #endif if (op->uop.ccop_alt) { #ifdef DEBUGGING if (debug) { debname[dlevel] = 'a'; debdelim[dlevel] = '_'; if (++dlevel >= dlmax) deb_growlevel(); } #endif newsp = cop_exec(op->uop.ccop_alt,gimme && (opflags & COPf_TERM),sp); st = stack->av_array; /* possibly reallocated */ if (newsp >= 0) retstr = st[newsp]; } if (goto_targ) break; go_to = Nullch; goto finish_while; } op = op->cop_next; if (op && op->cop_head == op) /* reached end of while loop */ return sp; /* targ isn't in this block */ if (opflags & COPf_ONCE) { #ifdef DEBUGGING if (debug & 4) { tmps = loop_stack[loop_ptr].loop_label; deb("(Popping label #%d %s)\n",loop_ptr, tmps ? tmps : "" ); } #endif loop_ptr--; } goto tail_recursion_entry; } } #endif #ifdef DEBUGGING if (debug) { if (debug & 2) { deb("%s (%lx) r%lx t%lx a%lx n%lx cs%lx\n", cop_name[op->cop_type],op,op->cop_expr, op->uop.ccop_true,op->uop.ccop_alt,op->cop_next, curspat); } debname[dlevel] = cop_name[op->cop_type][0]; debdelim[dlevel] = '!'; if (++dlevel >= dlmax) deb_growlevel(); } #endif /* Here is some common optimization */ if (opflags & COPf_COND) { switch (opflags & COPf_OPTIMIZE) { case COPo_FALSE: retstr = op->cop_short; newsp = -2; match = FALSE; if (opflags & COPf_NESURE) goto maybe; break; case COPo_TRUE: retstr = op->cop_short; newsp = -2; match = TRUE; if (opflags & COPf_EQSURE) goto flipmaybe; break; case COPo_REG: retstr = GV_STR(op->cop_stab); newsp = -2; match = SvTRUE(retstr); /* => retstr = retstr, c2 should fix */ if (opflags & (match ? COPf_EQSURE : COPf_NESURE)) goto flipmaybe; break; case COPo_ANCHOR: /* /^pat/ optimization */ if (multiline) { if (*op->cop_short->sv_ptr && !(opflags & COPf_EQSURE)) goto scanner; /* just unanchor it */ else break; /* must evaluate */ } match = 0; goto strop; case COPo_STROP: /* string op optimization */ match = 1; strop: retstr = GV_STR(op->cop_stab); newsp = -2; #ifndef I286 if (*op->cop_short->sv_ptr == *SvPV(retstr) && (match ? retstr->sv_cur == op->cop_slen - 1 : retstr->sv_cur >= op->cop_slen) && bcmp(op->cop_short->sv_ptr, SvPV(retstr), op->cop_slen) == 0 ) { if (opflags & COPf_EQSURE) { if (sawampersand && (opflags & COPf_OPTIMIZE) != COPo_STROP) { curspat = Nullpm; if (leftstab) sv_setpvn(GvSV(leftstab),"",0); if (amperstab) sv_setsv(GvSV(amperstab),op->cop_short); if (rightstab) sv_setpvn(GvSV(rightstab), retstr->sv_ptr + op->cop_slen, retstr->sv_cur - op->cop_slen); } if (op->cop_spat) lastspat = op->cop_spat; match = !(opflags & COPf_FIRSTNEG); retstr = match ? &sv_yes : &sv_no; goto flipmaybe; } } else if (opflags & COPf_NESURE) { match = opflags & COPf_FIRSTNEG; retstr = match ? &sv_yes : &sv_no; goto flipmaybe; } #else { char *zap1, *zap2, zap1c, zap2c; int zaplen; int lenok; zap1 = op->cop_short->sv_ptr; zap2 = SvPV(retstr); zap1c = *zap1; zap2c = *zap2; zaplen = op->cop_slen; if (match) lenok = (retstr->sv_cur == op->cop_slen - 1); else lenok = (retstr->sv_cur >= op->cop_slen); if ((zap1c == zap2c) && lenok && (bcmp(zap1, zap2, zaplen) == 0)) { if (opflags & COPf_EQSURE) { if (sawampersand && (opflags & COPf_OPTIMIZE) != COPo_STROP) { curspat = Nullpm; if (leftstab) sv_setpvn(GvSV(leftstab),"",0); if (amperstab) sv_setsv(GvSV(amperstab),op->cop_short); if (rightstab) sv_setpvn(GvSV(rightstab), retstr->sv_ptr + op->cop_slen, retstr->sv_cur - op->cop_slen); } if (op->cop_spat) lastspat = op->cop_spat; match = !(opflags & COPf_FIRSTNEG); retstr = match ? &sv_yes : &sv_no; goto flipmaybe; } } else if (opflags & COPf_NESURE) { match = opflags & COPf_FIRSTNEG; retstr = match ? &sv_yes : &sv_no; goto flipmaybe; } } #endif break; /* must evaluate */ case COPo_SCAN: /* non-anchored search */ scanner: retstr = GV_STR(op->cop_stab); newsp = -2; if (retstr->sv_pok & SVp_STUDIED) if (screamfirst[op->cop_short->sv_rare] >= 0) tmps = screaminstr(retstr, op->cop_short); else tmps = Nullch; else { tmps = SvPV(retstr); /* make sure it's pok */ #ifndef lint tmps = fbm_instr((unsigned char*)tmps, (unsigned char*)tmps + retstr->sv_cur, op->cop_short); #endif } if (tmps) { if (opflags & COPf_EQSURE) { ++op->cop_short->sv_u.sv_useful; if (sawampersand) { curspat = Nullpm; if (leftstab) sv_setpvn(GvSV(leftstab),retstr->sv_ptr, tmps - retstr->sv_ptr); if (amperstab) sv_setpvn(GvSV(amperstab), tmps, op->cop_short->sv_cur); if (rightstab) sv_setpvn(GvSV(rightstab), tmps + op->cop_short->sv_cur, retstr->sv_cur - (tmps - retstr->sv_ptr) - op->cop_short->sv_cur); } lastspat = op->cop_spat; match = !(opflags & COPf_FIRSTNEG); retstr = match ? &sv_yes : &sv_no; goto flipmaybe; } else hint = tmps; } else { if (opflags & COPf_NESURE) { ++op->cop_short->sv_u.sv_useful; match = opflags & COPf_FIRSTNEG; retstr = match ? &sv_yes : &sv_no; goto flipmaybe; } } if (--op->cop_short->sv_u.sv_useful < 0) { opflags &= ~COPf_OPTIMIZE; opflags |= COPo_EVAL; /* never try this optimization again */ op->cop_flags = (opflags & ~COPf_ONCE); } break; /* must evaluate */ case COPo_NUMOP: /* numeric op optimization */ retstr = GV_STR(op->cop_stab); newsp = -2; switch (op->cop_slen) { case OP_EQ: if (dowarn) { if ((!retstr->sv_nok && !looks_like_number(retstr))) warn("Possible use of == on string value"); } match = (SvNV(retstr) == op->cop_short->sv_u.sv_nv); break; case OP_NE: match = (SvNV(retstr) != op->cop_short->sv_u.sv_nv); break; case OP_LT: match = (SvNV(retstr) < op->cop_short->sv_u.sv_nv); break; case OP_LE: match = (SvNV(retstr) <= op->cop_short->sv_u.sv_nv); break; case OP_GT: match = (SvNV(retstr) > op->cop_short->sv_u.sv_nv); break; case OP_GE: match = (SvNV(retstr) >= op->cop_short->sv_u.sv_nv); break; } if (match) { if (opflags & COPf_EQSURE) { retstr = &sv_yes; goto flipmaybe; } } else if (opflags & COPf_NESURE) { retstr = &sv_no; goto flipmaybe; } break; /* must evaluate */ case COPo_INDGETS: /* while (<$foo>) */ last_in_stab = newGV(SvPV(GV_STR(op->cop_stab)),TRUE); if (!GvIO(last_in_stab)) GvIO(last_in_stab) = newIO(); goto dogets; case COPo_GETS: /* really a while () */ last_in_stab = op->cop_stab; dogets: fp = GvIO(last_in_stab)->ifp; retstr = GvSV(defstab); newsp = -2; keepgoing: if (fp && sv_gets(retstr, fp, 0)) { if (*retstr->sv_ptr == '0' && retstr->sv_cur == 1) match = FALSE; else match = TRUE; GvIO(last_in_stab)->lines++; } else if (GvIO(last_in_stab)->flags & IOf_ARGV) { if (!fp) goto doeval; /* first time through */ fp = nextargv(last_in_stab); if (fp) goto keepgoing; (void)do_close(last_in_stab,FALSE); GvIO(last_in_stab)->flags |= IOf_START; retstr = &sv_undef; match = FALSE; } else { retstr = &sv_undef; match = FALSE; } goto flipmaybe; case COPo_EVAL: break; case COPo_UNFLIP: while (tmps_max > tmps_base) { /* clean up after last oldeval */ sv_free(tmps_list[tmps_max]); tmps_list[tmps_max--] = Nullsv; } newsp = oldeval(Nullsv,op->cop_expr,gimme && (opflags & COPf_TERM),sp); st = stack->av_array; /* possibly reallocated */ retstr = st[newsp]; match = SvTRUE(retstr); if (op->cop_expr->arg_type == OP_FLIP) /* undid itself? */ opflags = copyopt(op,op->cop_expr[3].arg_ptr.arg_op); goto maybe; case COPo_CHOP: retstr = GvSV(op->cop_stab); newsp = -2; match = (retstr->sv_cur != 0); tmps = SvPV(retstr); tmps += retstr->sv_cur - match; sv_setpvn(&strchop,tmps,match); *tmps = '\0'; retstr->sv_nok = 0; retstr->sv_cur = tmps - retstr->sv_ptr; SvSETMAGIC(retstr); retstr = &strchop; goto flipmaybe; case COPo_ARRAY: match = op->cop_short->sv_u.sv_useful; /* just to get register */ if (match < 0) { /* first time through here? */ ar = GvAVn(op->cop_expr[1].arg_ptr.arg_stab); aryoptsave = savestack->av_fill; save_sptr(&GvSV(op->cop_stab)); save_long(&op->cop_short->sv_u.sv_useful); } else { ar = GvAV(op->cop_expr[1].arg_ptr.arg_stab); if (op->cop_type != COP_WHILE && savestack->av_fill > firstsave) leave_scope(firstsave); } if (match >= ar->av_fill) { /* we're in LAST, probably */ if (match < 0 && /* er, probably not... */ savestack->av_fill > aryoptsave) leave_scope(aryoptsave); retstr = &sv_undef; op->cop_short->sv_u.sv_useful = -1; /* actually redundant */ match = FALSE; } else { match++; if (!(retstr = ar->av_array[match])) retstr = av_fetch(ar,match,TRUE); GvSV(op->cop_stab) = retstr; op->cop_short->sv_u.sv_useful = match; match = TRUE; } newsp = -2; goto maybe; case COPo_D1: break; case COPo_D0: if (DBsingle->sv_u.sv_nv != 0) break; if (DBsignal->sv_u.sv_nv != 0) break; if (DBtrace->sv_u.sv_nv != 0) break; goto next_op; } /* we have tried to make this normal case as abnormal as possible */ doeval: if (gimme == G_ARRAY) { lastretstr = Nullsv; lastspbase = sp; lastsize = newsp - sp; if (lastsize < 0) lastsize = 0; } else lastretstr = retstr; while (tmps_max > tmps_base) { /* clean up after last oldeval */ sv_free(tmps_list[tmps_max]); tmps_list[tmps_max--] = Nullsv; } newsp = oldeval(Nullsv,op->cop_expr, gimme && (opflags & COPf_TERM) && op->cop_type == COP_EXPR && !op->uop.acop_expr, sp); st = stack->av_array; /* possibly reallocated */ retstr = st[newsp]; if (newsp > sp && retstr) match = SvTRUE(retstr); else match = FALSE; goto maybe; /* if flipflop was true, flop it */ flipmaybe: if (match && opflags & COPf_FLIP) { while (tmps_max > tmps_base) { /* clean up after last oldeval */ sv_free(tmps_list[tmps_max]); tmps_list[tmps_max--] = Nullsv; } if (op->cop_expr->arg_type == OP_FLOP) { /* currently toggled? */ newsp = oldeval(Nullsv,op->cop_expr,G_SCALAR,sp);/*let oldeval undo it*/ opflags = copyopt(op,op->cop_expr[3].arg_ptr.arg_op); } else { newsp = oldeval(Nullsv,op->cop_expr,G_SCALAR,sp);/* let oldeval do it */ if (op->cop_expr->arg_type == OP_FLOP) /* still toggled? */ opflags = copyopt(op,op->cop_expr[4].arg_ptr.arg_op); } } else if (opflags & COPf_FLIP) { if (op->cop_expr->arg_type == OP_FLOP) { /* currently toggled? */ match = TRUE; /* force on */ } } /* at this point, match says whether our expression was true */ maybe: if (opflags & COPf_INVERT) match = !match; if (!match) goto next_op; } #ifdef TAINT tainted = 0; /* modifier doesn't affect regular expression */ #endif