Alt-Devel-CallParser-ButWorking

 view release on metacpan or  search on metacpan

lib/Devel/CallParser.xs  view on Meta::CPAN

		if(SvMAGICAL((SV*)cv))
			sv_unmagicext((SV*)cv, PERL_MAGIC_ext,
				&mgvtbl_parsecall);
	} else {
		MAGIC *callmg =
			mg_findext((SV*)cv, PERL_MAGIC_ext, &mgvtbl_parsecall);
		if(!callmg)
			callmg = sv_magicext((SV*)cv, &PL_sv_undef,
				PERL_MAGIC_ext, &mgvtbl_parsecall, NULL, 0);
		if(callmg->mg_flags & MGf_REFCOUNTED) {
			SvREFCNT_dec(callmg->mg_obj);
			callmg->mg_flags &= ~MGf_REFCOUNTED;
		}
		callmg->mg_ptr = FPTR2DPTR(char *, psfun);
		callmg->mg_obj = psobj;
		if(psobj != (SV*)cv) {
			SvREFCNT_inc(psobj);
			callmg->mg_flags |= MGf_REFCOUNTED;
		}
	}
}

#if Q_PARSER_AVAILABLE

MY_EXPORT_CALLCONV void QPFXD(gcp1)(pTHX_ CV *cv,
	Perl_call_parser *psfun_p, SV **psobj_p)
{
	QPFXD(gcp0)(aTHX_ cv, psfun_p, psobj_p);
	if(!*psfun_p && !*psobj_p) {
		*psfun_p = Perl_parse_args_proto_or_list;
		*psobj_p = (SV*)cv;
	}
}

MY_EXPORT_CALLCONV void QPFXD(scp1)(pTHX_ CV *cv,
	Perl_call_parser psfun, SV *psobj)
{
	if(!psobj) croak("null object for cv_set_call_parser");
	QPFXD(scp0)(aTHX_ cv, psfun, psobj);
}

#endif /* Q_PARSER_AVAILABLE */

static int (*next_keyword_plugin)(pTHX_ char *, STRLEN, OP **);
static int my_keyword_plugin(pTHX_
	char *keyword_ptr, STRLEN keyword_len, OP **op_ptr)
{
	OP *nmop, *cvop, *argsop;
	CV *cv;
	GV *namegv;
	Perl_call_parser psfun;
	SV *psobj;
	U32 parser_flags;
	/*
	 * Creation of the rv2cv op below (or more precisely its gv op
	 * child created during checking) uses a pad slot under threads.
	 * Normally this is fine, but early versions of the padrange
	 * mechanism make assumptions about pad slots being contiguous
	 * that this breaks.  On the affected perl versions, therefore,
	 * we watch for the pad slot being consumed, and restore the
	 * pad's fill pointer if we throw the op away (upon declining
	 * to handle the keyword).
	 *
	 * The core bug was supposedly fixed in Perl 5.19.4, but actually
	 * that version exhibits a different bug also apparently related
	 * to padrange.  Restoring the pad's fill pointer works around
	 * this bug too.
	 *
	 * The other padrange bug was fixed in Perl 5.19.5 (commit aa033da),
	 * so the workaround is no longer needed after that, but it remains
	 * harmless until v5.21.4 (commit c9859fb)  where it starts breaking
	 * (see t/pad2.t.)	 */
#define MUST_RESTORE_PAD_FILL USE_THREADS && PERL_VERSION_GE(5,17,6) && ! PERL_VERSION_GE(5,19,5)
#if MUST_RESTORE_PAD_FILL
	I32 padfill = av_len(PL_comppad);
#endif /* MUST_RESTORE_PAD_FILL */
	/*
	 * If Devel::Declare happens to be loaded, it triggers magic
	 * upon building of an rv2cv op, assuming that it's being built
	 * by the lexer.  Since we're about to build such an op here,
	 * replicating what the lexer will normally do shortly after,
	 * there's a risk that Devel::Declare could fire here, ultimately
	 * firing twice for a single appearance of a name it's interested
	 * in.	To suppress Devel::Declare, therefore, we temporarily
	 * set PL_parser to null.  The same goes for Data::Alias and
	 * some other modules that use similar techniques.
	 *
	 * Unfortunately Devel::Declare prior to 0.006004 still does some
	 * work at the wrong time if PL_parser is null, and Data::Alias
	 * prior to 1.13 crashes if PL_parser is null.	So this module
	 * is not compatible with earlier versions of those modules,
	 * and can't be made compatible.
	 */
	ENTER;
	SAVEVPTR(PL_parser);
	PL_parser = NULL;
	nmop = newSVOP(OP_CONST, 0, newSVpvn(keyword_ptr, keyword_len));
	nmop->op_private = OPpCONST_BARE;
	cvop = newCVREF(0, nmop);
	LEAVE;
	if(!(cv = rv2cv_op_cv(cvop, 0))) {
		decline:
		op_free(cvop);
#if MUST_RESTORE_PAD_FILL
		av_fill(PL_comppad, padfill);
#endif /* MUST_RESTORE_PAD_FILL */
		return next_keyword_plugin(aTHX_
			keyword_ptr, keyword_len, op_ptr);
	}
	QPFXD(gcp0)(aTHX_ cv, &psfun, &psobj);
	if(!psfun && !psobj) goto decline;
	namegv = (GV*)rv2cv_op_cv(cvop,
			RV2CVOPCV_MARK_EARLY|RV2CVOPCV_RETURN_NAME_GV);
	parser_flags = 0;
	argsop = psfun(aTHX_ namegv, psobj, &parser_flags);
	if(!(parser_flags & CALLPARSER_PARENS))
		cvop->op_private |= OPpENTERSUB_NOPAREN;
	*op_ptr = newUNOP(OP_ENTERSUB, OPf_STACKED,
			op_append_elem(OP_LIST, argsop, cvop));
	return (parser_flags & CALLPARSER_STATEMENT) ?
		KEYWORD_PLUGIN_STMT : KEYWORD_PLUGIN_EXPR;



( run in 0.921 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )