static PADOFFSET pad_findlex _((char* name, PADOFFSET newoff, U32 seq,
CV* startcv, I32 cx_ix));
static OP *newDEFSVOP _((void));
+static OP *new_logop _((I32 type, I32 flags, OP **firstp, OP **otherp));
static char*
gv_ename(GV *gv)
int type = o->op_type;
if (type != OP_AELEM && type != OP_HELEM) {
yyerror(form("Can't use subscript on %s", op_desc[type]));
- if (type == OP_ENTERSUB || type == OP_RV2HV || type == OP_PADHV)
- warn("(Did you mean $ or @ instead of %c?)\n",
- type == OP_ENTERSUB ? '&' : '%');
+ if (type == OP_ENTERSUB || type == OP_RV2HV || type == OP_PADHV) {
+ dTHR;
+ SV *msg = sv_2mortal(
+ newSVpvf("(Did you mean $ or @ instead of %c?)\n",
+ type == OP_ENTERSUB ? '&' : '%'));
+ if (in_eval & 2)
+ warn("%_", msg);
+ else if (in_eval)
+ sv_catsv(GvSV(errgv), msg);
+ else
+ PerlIO_write(PerlIO_stderr(), SvPVX(msg), SvCUR(msg));
+ }
}
}
}
static PADOFFSET
-#ifndef CAN_PROTOTYPE
-pad_findlex(name, newoff, seq, startcv, cx_ix)
-char *name;
-PADOFFSET newoff;
-U32 seq;
-CV* startcv;
-I32 cx_ix;
-#else
pad_findlex(char *name, PADOFFSET newoff, U32 seq, CV* startcv, I32 cx_ix)
-#endif
{
dTHR;
CV *cv;
(unsigned long) thr, (unsigned long) curpad,
(long) retval, op_name[optype]));
#else
- DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad alloc %ld for %s\n",
+ DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad 0x%lx alloc %ld for %s\n",
+ (unsigned long) curpad,
(long) retval, op_name[optype]));
#endif /* USE_THREADS */
return (PADOFFSET)retval;
}
SV *
-#ifndef CAN_PROTOTYPE
-pad_sv(po)
-PADOFFSET po;
-#else
pad_sv(PADOFFSET po)
-#endif /* CAN_PROTOTYPE */
{
dTHR;
#ifdef USE_THREADS
#else
if (!po)
croak("panic: pad_sv po");
- DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad sv %d\n", po));
+ DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad 0x%lx sv %d\n",
+ (unsigned long) curpad, po));
#endif /* USE_THREADS */
return curpad[po]; /* eventually we'll turn this into a macro */
}
void
-#ifndef CAN_PROTOTYPE
-pad_free(po)
-PADOFFSET po;
-#else
pad_free(PADOFFSET po)
-#endif /* CAN_PROTOTYPE */
{
dTHR;
if (!curpad)
DEBUG_X(PerlIO_printf(Perl_debug_log, "0x%lx Pad 0x%lx free %d\n",
(unsigned long) thr, (unsigned long) curpad, po));
#else
- DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad free %d\n", po));
+ DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad 0x%lx free %d\n",
+ (unsigned long) curpad, po));
#endif /* USE_THREADS */
if (curpad[po] && curpad[po] != &sv_undef)
SvPADTMP_off(curpad[po]);
}
void
-#ifndef CAN_PROTOTYPE
-pad_swipe(po)
-PADOFFSET po;
-#else
pad_swipe(PADOFFSET po)
-#endif /* CAN_PROTOTYPE */
{
dTHR;
if (AvARRAY(comppad) != curpad)
DEBUG_X(PerlIO_printf(Perl_debug_log, "0x%lx Pad 0x%lx swipe %d\n",
(unsigned long) thr, (unsigned long) curpad, po));
#else
- DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad swipe %d\n", po));
+ DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad 0x%lx swipe %d\n",
+ (unsigned long) curpad, po));
#endif /* USE_THREADS */
SvPADTMP_off(curpad[po]);
curpad[po] = NEWSV(1107,0);
padix = po - 1;
}
+/* XXX pad_reset() is currently disabled because it results in serious bugs.
+ * It causes pad temp TARGs to be shared between OPs. Since TARGs are pushed
+ * on the stack by OPs that use them, there are several ways to get an alias
+ * to a shared TARG. Such an alias will change randomly and unpredictably.
+ * We avoid doing this until we can think of a Better Way.
+ * GSAR 97-10-29 */
void
pad_reset(void)
{
+#ifdef USE_BROKEN_PAD_RESET
dTHR;
register I32 po;
DEBUG_X(PerlIO_printf(Perl_debug_log, "0x%lx Pad 0x%lx reset\n",
(unsigned long) thr, (unsigned long) curpad));
#else
- DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad reset\n"));
+ DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad 0x%lx reset\n",
+ (unsigned long) curpad));
#endif /* USE_THREADS */
if (!tainting) { /* Can't mix tainted and non-tainted temporaries. */
for (po = AvMAX(comppad); po > padix_floor; po--) {
}
padix = padix_floor;
}
+#endif
pad_reset_pending = FALSE;
}
else if (!type) {
o->op_private |= OPpLVAL_INTRO;
o->op_flags &= ~OPf_SPECIAL;
+ hints |= HINT_BLOCK_SCOPE;
}
else if (type != OP_GREPSTART && type != OP_ENTERSUB)
o->op_flags |= OPf_REF;
if (type == OP_LIST) {
for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling)
my(kid);
- }
- else if (type != OP_PADSV &&
+ } else if (type == OP_UNDEF) {
+ return o;
+ } else if (type != OP_PADSV &&
type != OP_PADAV &&
type != OP_PADHV &&
type != OP_PUSHMARK)
CV *cv = perl_get_cv("DB::postponed", FALSE);
if (cv) {
dSP;
- PUSHMARK(sp);
+ PUSHMARK(SP);
XPUSHs((SV*)compiling.cop_filegv);
PUTBACK;
perl_call_sv((SV*)cv, G_DISCARD);
OP *
newLOGOP(I32 type, I32 flags, OP *first, OP *other)
{
+ return new_logop(type, flags, &first, &other);
+}
+
+static OP *
+new_logop(I32 type, I32 flags, OP** firstp, OP** otherp)
+{
dTHR;
LOGOP *logop;
OP *o;
+ OP *first = *firstp;
+ OP *other = *otherp;
if (type == OP_XOR) /* Not short circuit, but here by precedence. */
return newBINOP(type, flags, scalar(first), scalar(other));
else
type = OP_AND;
o = first;
- first = cUNOPo->op_first;
+ first = *firstp = cUNOPo->op_first;
if (o->op_next)
first->op_next = o->op_next;
cUNOPo->op_first = Nullop;
warn("Probable precedence problem on %s", op_desc[type]);
if ((type == OP_AND) == (SvTRUE(((SVOP*)first)->op_sv))) {
op_free(first);
+ *firstp = Nullop;
return other;
}
else {
op_free(other);
+ *otherp = Nullop;
return first;
}
}
}
listop = append_elem(OP_LINESEQ, block, newOP(OP_UNSTACK, 0));
- o = newLOGOP(OP_AND, 0, expr, listop);
+ o = new_logop(OP_AND, 0, &expr, &listop);
- ((LISTOP*)listop)->op_last->op_next = LINKLIST(o);
+ if (listop)
+ ((LISTOP*)listop)->op_last->op_next = LINKLIST(o);
if (once && o != listop)
o->op_next = ((LOGOP*)cUNOPo->op_first)->op_other;
redo = LINKLIST(listop);
if (expr) {
- o = newLOGOP(OP_AND, 0, expr, scalar(listop));
+ copline = whileline;
+ scalar(listop);
+ o = new_logop(OP_AND, 0, &expr, &listop);
if (o == expr && o->op_type == OP_CONST && !SvTRUE(cSVOPo->op_sv)) {
op_free(expr); /* oops, it's a while (0) */
op_free((OP*)loop);
- return Nullop; /* (listop already freed by newLOGOP) */
+ return Nullop; /* listop already freed by new_logop */
}
- ((LISTOP*)listop)->op_last->op_next = condop =
- (o == listop ? redo : LINKLIST(o));
+ if (listop)
+ ((LISTOP*)listop)->op_last->op_next = condop =
+ (o == listop ? redo : LINKLIST(o));
if (!next)
next = condop;
}
}
OP *
-#ifndef CAN_PROTOTYPE
-newFOROP(flags,label,forline,sv,expr,block,cont)
-I32 flags;
-char *label;
-line_t forline;
-OP* sv;
-OP* expr;
-OP*block;
-OP*cont;
-#else
newFOROP(I32 flags,char *label,line_t forline,OP *sv,OP *expr,OP *block,OP *cont)
-#endif /* CAN_PROTOTYPE */
{
LOOP *loop;
OP *wop;
goto done;
}
/* ahem, death to those who redefine active sort subs */
- if (curstack == sortstack && sortcop == CvSTART(cv))
+ if (curstackinfo->si_type == SI_SORT && sortcop == CvSTART(cv))
croak("Can't redefine active sort subroutine %s", name);
const_sv = cv_const_sv(cv);
- if (const_sv || dowarn) {
+ if (const_sv || dowarn && !(CvGV(cv) && GvSTASH(CvGV(cv))
+ && HvNAME(GvSTASH(CvGV(cv)))
+ && strEQ(HvNAME(GvSTASH(CvGV(cv))),
+ "autouse"))) {
line_t oldline = curcop->cop_line;
curcop->cop_line = copline;
warn(const_sv ? "Constant subroutine %s redefined"
if (HvFILL(hv) > 0 && hv_exists(hv, SvPVX(tmpstr), SvCUR(tmpstr))
&& (cv = GvCV(db_postponed))) {
dSP;
- PUSHMARK(sp);
+ PUSHMARK(SP);
XPUSHs(tmpstr);
PUTBACK;
perl_call_sv((SV*)cv, G_DISCARD);
return cv;
}
+void
+newCONSTSUB(HV *stash, char *name, SV *sv)
+{
+ dTHR;
+ U32 oldhints = hints;
+ HV *old_cop_stash = curcop->cop_stash;
+ HV *old_curstash = curstash;
+ line_t oldline = curcop->cop_line;
+ curcop->cop_line = copline;
+
+ hints &= ~HINT_BLOCK_SCOPE;
+ if(stash)
+ curstash = curcop->cop_stash = stash;
+
+ newSUB(
+ start_subparse(FALSE, 0),
+ newSVOP(OP_CONST, 0, newSVpv(name,0)),
+ newSVOP(OP_CONST, 0, &sv_no), /* SvPV(&sv_no) == "" -- GMB */
+ newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv))
+ );
+
+ hints = oldhints;
+ curcop->cop_stash = old_cop_stash;
+ curstash = old_curstash;
+ curcop->cop_line = oldline;
+}
+
CV *
newXS(char *name, void (*subaddr) (CV *), char *filename)
{
}
else if (CvROOT(cv) || CvXSUB(cv) || GvASSUMECV(gv)) {
/* already defined (or promised) */
- if (dowarn) {
+ if (dowarn && !(CvGV(cv) && GvSTASH(CvGV(cv))
+ && HvNAME(GvSTASH(CvGV(cv)))
+ && strEQ(HvNAME(GvSTASH(CvGV(cv))), "autouse"))) {
line_t oldline = curcop->cop_line;
curcop->cop_line = copline;
warn("Subroutine %s redefined",name);
"Can't use bareword (\"%s\") as %s ref while \"strict refs\" in use",
name, badthing);
}
- kid->op_type = OP_GV;
+ /*
+ * This is a little tricky. We only want to add the symbol if we
+ * didn't add it in the lexer. Otherwise we get duplicate strict
+ * warnings. But if we didn't add it in the lexer, we must at
+ * least pretend like we wanted to add it even if it existed before,
+ * or we get possible typo warnings. OPpCONST_ENTERED says
+ * whether the lexer already added THIS instance of this symbol.
+ */
iscv = (o->op_type == OP_RV2CV) * 2;
- for (gv = 0; !gv; iscv++) {
- /*
- * This is a little tricky. We only want to add the symbol if we
- * didn't add it in the lexer. Otherwise we get duplicate strict
- * warnings. But if we didn't add it in the lexer, we must at
- * least pretend like we wanted to add it even if it existed before,
- * or we get possible typo warnings. OPpCONST_ENTERED says
- * whether the lexer already added THIS instance of this symbol.
- */
+ do {
gv = gv_fetchpv(name,
iscv | !(kid->op_private & OPpCONST_ENTERED),
iscv
: o->op_type == OP_RV2HV
? SVt_PVHV
: SVt_PVGV);
+ } while (!gv && !(kid->op_private & OPpCONST_ENTERED) && !iscv++);
+ if (gv) {
+ kid->op_type = OP_GV;
+ SvREFCNT_dec(kid->op_sv);
+ kid->op_sv = SvREFCNT_inc(gv);
}
- SvREFCNT_dec(kid->op_sv);
- kid->op_sv = SvREFCNT_inc(gv);
}
return o;
}
if (o->op_flags & OPf_KIDS) {
OP *kid = cLISTOPo->op_first->op_sibling; /* get past pushmark */
if (kid && kid->op_type == OP_CONST)
- fbm_compile(((SVOP*)kid)->op_sv);
+ fbm_compile(((SVOP*)kid)->op_sv, 0);
}
return ck_fun(o);
}
kid->op_sibling = 0;
o2 = newUNOP(OP_RV2GV, 0, kid);
o2->op_sibling = sib;
- prev->op_sibling = o;
+ prev->op_sibling = o2;
}
goto wrapref;
case '\\':
wrapref:
{
OP* kid = o2;
- o2 = newUNOP(OP_REFGEN, 0, kid);
- o2->op_sibling = kid->op_sibling;
+ OP* sib = kid->op_sibling;
kid->op_sibling = 0;
+ o2 = newUNOP(OP_REFGEN, 0, kid);
+ o2->op_sibling = sib;
prev->op_sibling = o2;
}
break;
goto nothin;
case OP_NULL:
if (o->op_targ == OP_NEXTSTATE || o->op_targ == OP_DBSTATE)
- curcop = ((COP*)op);
+ curcop = ((COP*)o);
goto nothin;
case OP_SCALAR:
case OP_LINESEQ:
case OP_AND:
case OP_OR:
o->op_seq = op_seqmax++;
+ while (cLOGOP->op_other->op_type == OP_NULL)
+ cLOGOP->op_other = cLOGOP->op_other->op_next;
peep(cLOGOP->op_other);
break;