/usr/local/CPAN/wildproto/wildproto.pm
package wildproto;
$VERSION = '1.0.1';
use base pragmatic;
bootstrap xsub;
use xsub q{
static bool active = FALSE;
OP *(*old_ck_entersub)(pTHX_ OP *);
static OP *new_ck_entersub(pTHX_ OP *o) {
OP *op;
char *real_proto = NULL;
char *copy_proto = NULL;
if (active) {
UNOP *uno = (UNOP *)o;
OP *prev;
OP *argop;
OP *cvop;
char *proto = 0;
CV *cv = 0;
SVOP *tmpop;
if (o->op_private & OPpENTERSUB_AMPER)
goto real_op;
prev = uno->op_first->op_sibling ? o : uno->op_first;
prev = ((UNOP *)prev)->op_first;
argop = prev->op_sibling;
for (cvop = argop; cvop->op_sibling; cvop = cvop->op_sibling);
if (cvop->op_type != OP_RV2CV)
goto real_op;
if (cvop->op_private & OPpENTERSUB_AMPER)
goto real_op;
tmpop = (SVOP*)((UNOP*)cvop)->op_first;
if (tmpop->op_type != OP_GV)
goto real_op;
cv = GvCVu(cGVOPx_gv(tmpop));
if (!cv || !SvPOK(cv))
goto real_op;
proto = SvPV_nolen((SV*)cv);
while (argop != cvop) {
#ifdef WACKYPROTO
int type = 0;
#endif
while (*proto == ' ' || *proto == ';')
proto++;
if (!*proto || *proto == '@' || *proto == '%')
break;
if (*proto == '\\\\' && *(proto+1) == '?')
#ifdef WACKYPROTO
type = 1;
else if (*(proto+0) == '(' && *(proto+1) == ')')
type = 2;
else if (*(proto+0) == '[' && *(proto+1) == ']') type = 3;
else if (*(proto+0) == '{' && *(proto+1) == '}') type = 4;
else type = 0;
if (type)
#endif
{
OP *next = argop->op_sibling;
argop->op_sibling = 0;
#ifdef WACKYPROTO
switch (type) {
case 1:
#endif
argop = newUNOP(OP_REFGEN, 0, mod(argop, OP_REFGEN));
#ifdef WACKYPROTO
break;
case 2:
argop = newUNOP(OP_REFGEN, 0, mod(argop, OP_REFGEN));
argop = newANONLIST(argop);
break;
case 3:
argop = newANONLIST(argop);
break;
case 4:
argop = newANONHASH(argop);
break;
}
#endif
argop->op_sibling = next;
prev->op_sibling = argop;
if (!real_proto) {
real_proto = proto;
copy_proto = savepv(proto);
}
*proto++ = ' ';
*proto = '$';
}
if (*proto == '\\\\')
if (!*++proto)
break;
proto++;
prev = argop;
argop = argop->op_sibling;
}
}
real_op:
op = old_ck_entersub(aTHX_ o);
if (real_proto)
strcpy(real_proto, copy_proto);
return op;
}
};
use xsub enable => q($), q{
if (active)
return &PL_sv_yes;
old_ck_entersub = PL_check[OP_ENTERSUB];
PL_check[OP_ENTERSUB] = new_ck_entersub;
active = TRUE;
return &PL_sv_yes;
};
use xsub disable => q($), q{
if (!active)
return &PL_sv_yes;
active = FALSE;
if (PL_check[OP_ENTERSUB] == new_ck_entersub) {
PL_check[OP_ENTERSUB] = old_ck_entersub;
} else {
Perl_warn(aTHX_ "PL_check[OP_ENTERSUB] apparently hijacked at %s line %d\n",
__FILE__, __LINE__);
}
return &PL_sv_no;
};
1