Example #1
0
bool
_runops_debug(int flag)
{
    dTHX;
    bool d = PL_runops == MEMBER_TO_FPTR(Perl_runops_debug);

    if (flag >= 0)
	PL_runops 
	    = MEMBER_TO_FPTR(flag ? Perl_runops_debug : Perl_runops_standard);
    return d;
}
Example #2
0
OP *
Perl_mod(pTHX_ OP *o, I32 type)
{
    dVAR;
    OP **tokid;
    /* -1 = error on localize, 0 = ignore localize, 1 = ok to localize */
    int localize = -1;

    if (!o || (PL_parser && PL_parser->error_count))
	return o;

    if ((o->op_flags & OPf_TARGET_MY)
	&& (PL_opargs[o->op_type] & OA_TARGLEX))/* OPp share the meaning */
    {
	return o;
    }

    switch (o->op_type) {
    case OP_UNDEF:
	localize = 0;
	return o;
    case OP_STUB:
	if ((o->op_flags & OPf_PARENS) || PL_madskills)
	    break;
	goto nomod;
    default:
      nomod:
	/* grep, foreach, subcalls, refgen */
	if (type == OP_GREPSTART || type == OP_ENTERSUB || type == OP_SREFGEN)
	    break;
	Perl_croak_at(aTHX_ o->op_location, 
		      "Can't modify %s in %s",
		      (o->op_type == OP_NULL && (o->op_flags & OPf_SPECIAL)
		       ? "do block"
		       : OP_DESC(o)),
		      type ? PL_op_desc[type] : "local");
	return o;

    case OP_PREINC:
    case OP_PREDEC:
    case OP_POW:
    case OP_MULTIPLY:
    case OP_DIVIDE:
    case OP_MODULO:
    case OP_REPEAT:
    case OP_ADD:
    case OP_SUBTRACT:
    case OP_CONCAT:
    case OP_LEFT_SHIFT:
    case OP_RIGHT_SHIFT:
    case OP_BIT_AND:
    case OP_BIT_XOR:
    case OP_BIT_OR:
    case OP_I_MULTIPLY:
    case OP_I_DIVIDE:
    case OP_I_MODULO:
    case OP_I_ADD:
    case OP_I_SUBTRACT:
	if (!(o->op_flags & OPf_STACKED))
	    goto nomod;
	break;

    case OP_COND_EXPR:
	localize = 1;
	for (tokid = &(cUNOPo->op_first->op_sibling); *tokid; tokid = &((*tokid)->op_sibling))
	    *tokid = mod(*tokid, type);
	break;

    case OP_RV2GV:
/* 	if (scalar_mod_type(o, type)) */
/* 	    goto nomod; */
	doref(cUNOPo->op_first, o->op_type, TRUE);
	localize = 1;
	break;
    case OP_ASLICE:
    case OP_HSLICE:
	localize = 1;
	/* FALL THROUGH */
    case OP_NEXTSTATE:
    case OP_DBSTATE:
	break;
    case OP_RV2CV:
    case OP_RV2AV:
    case OP_RV2HV:
    case OP_RV2SV:
	doref(cUNOPo->op_first, o->op_type, TRUE);
	localize = 1;
	/* FALL THROUGH */
    case OP_GV:
	PL_hints |= HINT_BLOCK_SCOPE;
        break;
    case OP_SASSIGN:
    case OP_ANDASSIGN:
    case OP_ORASSIGN:
    case OP_DORASSIGN:
        break;

    case OP_AELEMFAST:
	localize = -1;
	break;

    case OP_EXPAND:
	cUNOPo->op_first = mod(cUNOPo->op_first, type);
	break;

    case OP_DOTDOTDOT:
    case OP_PLACEHOLDER:
	localize = 0;
	break;

    case OP_PADSV:
	if (!type) /* local() */
	    Perl_croak(aTHX_ "Can't localize lexical variable %s",
		 PAD_COMPNAME_PV(o->op_targ));
	break;

    case OP_MAGICSV:
	localize = 1;
	if ( type && type != OP_SASSIGN && type != OP_SUBST )
	    goto nomod;
	break;

    case OP_PUSHMARK:
	localize = 0;
	break;

    case OP_KEYS:
        goto nomod;
	break;

    case OP_AELEM:
    case OP_HELEM:
        o = op_mod_assign(
            o,
            &(cBINOPo->op_first),
            type == OP_NULL ? o->op_type : type
            );
	localize = 1;
	break;

    case OP_ENTERSUB_SAVE:
        o = op_mod_assign(
            o,
            &(cUNOPo->op_first),
            type == OP_NULL ? o->op_type : type
            );

	localize = 1;
        break;
    case OP_ENTERSUB:
        if ( ! type ) {
            /* add localize opcode */
            const PADOFFSET po = pad_alloc(OP_SASSIGN, SVs_PADTMP);
            o->op_targ = po;
            o->op_private |= OPpENTERSUB_SAVEARGS;
            o = newUNOP(OP_ENTERSUB_SAVE, 0, scalar(o), o->op_location);
            o->op_targ = po;
        }
	localize = 1;
        break;

    case OP_SCOPE:
    case OP_LEAVE:
    case OP_ENTER:
    case OP_LINESEQ:
	localize = 0;
	if (o->op_flags & OPf_KIDS)
	    cLISTOPo->op_last = mod(cLISTOPo->op_last, type);
	break;

    case OP_NULL:
	localize = 0;
	if (o->op_flags & OPf_SPECIAL)		/* do BLOCK */
	    goto nomod;
	else if (!(o->op_flags & OPf_KIDS))
	    break;
	if (o->op_targ != OP_LIST) {
	    cBINOPo->op_first = mod(cBINOPo->op_first, type);
	    break;
	}
	/* FALL THROUGH */
    case OP_HASHEXPAND:
    case OP_ARRAYEXPAND:
    case OP_LIST:
	localize = 0;
	for (tokid = &(cLISTOPo->op_first); *tokid; tokid = &((*tokid)->op_sibling))
	    *tokid = mod(*tokid, type);
	break;

    case OP_ANONARRAY:
    case OP_ANONHASH:
    case OP_ANONSCALAR:
        if ( ! type ) {
            /* propagate localize */
            for (tokid = &(cLISTOPo->op_first); *tokid; tokid = &((*tokid)->op_sibling))
                *tokid = mod(*tokid, type);
        }
        localize = 0;
        break;
        
    case OP_LISTLAST:
	localize = 0;
	if (o->op_flags & OPf_KIDS)
	    cLISTOPo->op_last = mod(cLISTOPo->op_last, type);
	break;

    case OP_LISTFIRST:
	localize = 0;
	if (o->op_flags & OPf_KIDS)
	    cLISTOPo->op_first->op_sibling = mod(cLISTOPo->op_first->op_sibling, type);
	break;

    case OP_RETURN:
	goto nomod;
	break; /* mod()ing was handled by ck_return() */
    }

    /* [20011101.069] File test operators interpret OPf_REF to mean that
       their argument is a filehandle; thus \stat(".") should not set
       it. AMS 20011102 */
    if (type == OP_SREFGEN &&
        PL_check[o->op_type] == MEMBER_TO_FPTR(Perl_ck_ftst))
        return o;

    o->op_flags |= OPf_MOD;

    if (type == OP_SASSIGN)
	o->op_flags |= OPf_SPECIAL|OPf_REF;
    else if (!type) { /* local() */
	switch (localize) {
	case 1:
	    o->op_private |= OPpLVAL_INTRO;
	    o->op_flags &= ~OPf_SPECIAL;
	    PL_hints |= HINT_BLOCK_SCOPE;
	    break;
	case 0:
	    break;
	case -1:
	    Perl_croak(aTHX_ "Can't localize %s", OP_DESC(o));
	}
    }
    else if (type != OP_GREPSTART && type != OP_ENTERSUB)
	o->op_flags |= OPf_REF;
    return o;
}