8
/* this should go into ppport */
9
#if PERL_BCDVERSION >= 0x5009005
10
#define PL_oldbufptr D_PPP_my_PL_parser_var(oldbufptr)
13
#if PERL_REVISION == 5 && PERL_VERSION >= 10
14
#define HAS_HINTS_HASH
17
#include "hook_op_check.h"
18
#include "hook_op_ppaddr.h"
19
#include "hook_parser.h"
21
typedef struct userdata_St {
24
hook_op_check_id eval_hook;
25
hook_op_check_id parser_id;
29
call_to_perl (SV *class, UV offset, char *proto) {
39
mPUSHp (proto, strlen (proto));
42
call_method ("callback", G_VOID|G_DISCARD);
49
qualify_func_name (const char *s) {
50
SV *ret = newSVpvs ("");
52
if (strstr (s, ":") == NULL) {
53
sv_catpv (ret, SvPVX (PL_curstname));
54
sv_catpvs (ret, "::");
66
HV *hints = GvHV (PL_hintgv);
67
SV **sv, *tmp = newSVsv (class);
69
sv_catpv (tmp, "::enabled");
70
key = SvPV (tmp, len);
76
sv = hv_fetch (hints, key, len, 0);
87
handle_proto (pTHX_ OP *op, void *user_data) {
91
char tmpbuf[sizeof (PL_tokenbuf)], proto[sizeof (PL_tokenbuf)];
93
userdata_t *ud = (userdata_t *)user_data;
95
if (strNE (ud->f_class, SvPVX (PL_curstname))) {
99
if (!enabled (ud->class)) {
111
op_sv = cSVOPx (op)->op_sv;
113
if (!SvPOK (op_sv)) {
119
s = hook_toke_skipspace (aTHX_ s);
121
if (strnNE (s, "sub", 3)) {
125
if (!isSPACE (s[3])) {
129
s = hook_toke_skipspace (aTHX_ s + 4);
131
if (strNE (SvPVX (PL_subname), "?")) {
132
(void)hook_toke_scan_word (aTHX_ (s - SvPVX (PL_linestr)), 1, tmpbuf, sizeof (tmpbuf), &retlen);
138
name = qualify_func_name (tmpbuf);
140
if (!sv_eq (PL_subname, name)) {
149
s = hook_toke_skipspace (aTHX_ s + retlen);
154
tmp = hook_toke_scan_str (aTHX_ s);
155
tmp2 = hook_parser_get_lex_stuff (aTHX);
156
hook_parser_clear_lex_stuff (aTHX);
158
if (s == tmp || !tmp2) {
162
strncpy (proto, s + 1, tmp - s - 2);
163
proto[tmp - s - 2] = '\0';
167
while (tmp > s + 1) {
168
if (isSPACE (s[0])) {
183
s = hook_toke_skipspace (aTHX_ s + 1);
186
while (s[0] != '{') {
188
s = hook_toke_skipspace (aTHX_ s);
190
(void)hook_toke_scan_word (aTHX_ (s - SvPVX (PL_linestr)), 0, tmpbuf, sizeof (tmpbuf), &retlen);
198
tmp = hook_toke_scan_str (aTHX_ s);
199
tmp2 = hook_parser_get_lex_stuff (aTHX);
200
hook_parser_clear_lex_stuff (aTHX);
208
if (strEQ (tmpbuf, "proto")) {
209
while (attr_start < tmp) {
215
sv_setpv (op_sv, tmp2);
218
else if (strEQ (tmpbuf, "proto")) {
219
croak ("proto attribute requires argument");
222
s = hook_toke_skipspace (aTHX_ s);
231
/* croak as we already messed with op when :proto is given? */
235
call_to_perl (ud->class, s - hook_parser_get_linestr (aTHX), proto);
245
before_eval (pTHX_ OP *op, void *user_data) {
248
SV *class = (SV *)user_data;
250
#ifdef HAS_HINTS_HASH
251
if (PL_op->op_private & OPpEVAL_HAS_HH) {
264
/* FIXME: this leaks the new scalar */
265
SV *new = newSVpvs ("use ");
266
sv_catsv (new, class);
267
sv_catpvs (new, ";");
276
handle_eval (pTHX_ OP *op, void *user_data) {
277
userdata_t *ud = (userdata_t *)user_data;
279
if (enabled (ud->class)) {
280
hook_op_ppaddr_around (op, before_eval, NULL, newSVsv (ud->class));
286
MODULE = signatures PACKAGE = signatures
291
setup (class, f_class)
297
Newx (ud, 1, userdata_t);
298
ud->class = newSVsv (class);
299
ud->f_class = f_class;
301
ud->parser_id = hook_parser_setup ();
302
ud->eval_hook = hook_op_check (OP_ENTEREVAL, handle_eval, ud);
303
RETVAL = (UV)hook_op_check (OP_CONST, handle_proto, ud);
313
ud = (userdata_t *)hook_op_check_remove (OP_CONST, id);
316
hook_op_check_remove (OP_ENTEREVAL, ud->eval_hook);
317
hook_parser_teardown (ud->parser_id);
318
SvREFCNT_dec (ud->class);