evalhook 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +2 -0
- data/Rakefile +4 -4
- data/lib/evalhook/hook_context.rb +144 -0
- data/lib/evalhook/hook_handler.rb +35 -0
- data/lib/evalhook/multi_hook_handler.rb +1 -1
- data/lib/evalhook.rb +44 -30
- data/spec/hook_handler/hook_handler_arguments_spec.rb +15 -0
- data/spec/hook_handler/hook_handler_defaults_spec.rb +230 -0
- data/spec/hook_handler/hook_handler_hook_spec.rb +46 -0
- data/spec/hook_handler/hook_handler_multiple_redirect_spec.rb +67 -0
- data/spec/hook_handler/hook_handler_multiple_spec.rb +99 -0
- data/spec/hook_handler/hook_handler_ruby_spec.rb +47 -0
- data/spec/hook_handler/hook_handler_visitor_spec.rb +103 -0
- data/spec/validation/hook_handler_spec.rb +19 -0
- metadata +33 -9
- data/ext/evalhook_base/evalhook_base.c +0 -795
- data/ext/evalhook_base/extconf.rb +0 -7
@@ -1,795 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
|
3
|
-
This file is part of the evalhook project, http://github.com/tario/evalhook
|
4
|
-
|
5
|
-
Copyright (c) 2010 Roberto Dario Seminara <robertodarioseminara@gmail.com>
|
6
|
-
|
7
|
-
evalhook is free software: you can redistribute it and/or modify
|
8
|
-
it under the terms of the gnu general public license as published by
|
9
|
-
the free software foundation, either version 3 of the license, or
|
10
|
-
(at your option) any later version.
|
11
|
-
|
12
|
-
evalhook is distributed in the hope that it will be useful,
|
13
|
-
but without any warranty; without even the implied warranty of
|
14
|
-
merchantability or fitness for a particular purpose. see the
|
15
|
-
gnu general public license for more details.
|
16
|
-
|
17
|
-
you should have received a copy of the gnu general public license
|
18
|
-
along with evalhook. if not, see <http://www.gnu.org/licenses/>.
|
19
|
-
|
20
|
-
*/
|
21
|
-
|
22
|
-
#include <ruby.h>
|
23
|
-
#include <env.h>
|
24
|
-
#include <node.h>
|
25
|
-
|
26
|
-
VALUE m_EvalHook ;
|
27
|
-
VALUE c_HookHandler;
|
28
|
-
|
29
|
-
#define nd_3rd u3.node
|
30
|
-
|
31
|
-
ID method_call;
|
32
|
-
ID method_hooked_method;
|
33
|
-
ID method_local_hooked_method;
|
34
|
-
ID method_private_hooked_method;
|
35
|
-
ID method_public_hooked_method;
|
36
|
-
ID method_protected_hooked_method;
|
37
|
-
ID method_public, method_private, method_protected;
|
38
|
-
|
39
|
-
ID method_set_hook_handler;
|
40
|
-
|
41
|
-
struct BLOCK {
|
42
|
-
NODE *var;
|
43
|
-
NODE *body;
|
44
|
-
VALUE self;
|
45
|
-
struct FRAME frame;
|
46
|
-
struct SCOPE *scope;
|
47
|
-
VALUE klass;
|
48
|
-
NODE *cref;
|
49
|
-
int iter;
|
50
|
-
int vmode;
|
51
|
-
int flags;
|
52
|
-
int uniq;
|
53
|
-
struct RVarmap *dyna_vars;
|
54
|
-
VALUE orig_thread;
|
55
|
-
VALUE wrapper;
|
56
|
-
VALUE block_obj;
|
57
|
-
struct BLOCK *outer;
|
58
|
-
struct BLOCK *prev;
|
59
|
-
};
|
60
|
-
|
61
|
-
struct METHOD {
|
62
|
-
VALUE klass, rklass;
|
63
|
-
VALUE recv;
|
64
|
-
ID id, oid;
|
65
|
-
int safe_level;
|
66
|
-
NODE *body;
|
67
|
-
};
|
68
|
-
|
69
|
-
|
70
|
-
void process_node(NODE* node, VALUE handler);
|
71
|
-
|
72
|
-
void patch_local_call_node(NODE* node, VALUE handler) {
|
73
|
-
NODE* args1 = NEW_LIST(NEW_LIT(ID2SYM(node->nd_mid)));
|
74
|
-
NODE* args2 = NEW_LIST(NEW_LIT(handler));
|
75
|
-
|
76
|
-
node->nd_recv = NEW_CALL(NEW_SELF(), method_local_hooked_method, args1);
|
77
|
-
node->nd_recv = NEW_CALL(node->nd_recv, method_set_hook_handler, args2);
|
78
|
-
node->nd_mid = method_call;
|
79
|
-
|
80
|
-
nd_set_type(node, NODE_CALL);
|
81
|
-
}
|
82
|
-
|
83
|
-
void patch_call_node(NODE* node, VALUE handler) {
|
84
|
-
NODE* args1 = NEW_LIST(NEW_LIT(ID2SYM(node->nd_mid)));
|
85
|
-
NODE* args2 = NEW_LIST(NEW_LIT(handler));
|
86
|
-
|
87
|
-
node->nd_recv = NEW_CALL(node->nd_recv, method_hooked_method, args1);
|
88
|
-
node->nd_recv = NEW_CALL(node->nd_recv, method_set_hook_handler, args2);
|
89
|
-
|
90
|
-
node->nd_mid = method_call;
|
91
|
-
}
|
92
|
-
|
93
|
-
struct global_entry {
|
94
|
-
struct global_variable *var;
|
95
|
-
ID id;
|
96
|
-
};
|
97
|
-
|
98
|
-
void process_individual_node(NODE* node, VALUE handler) {
|
99
|
-
ID id = node->nd_mid;
|
100
|
-
|
101
|
-
switch (nd_type(node)) {
|
102
|
-
case NODE_XSTR:{
|
103
|
-
|
104
|
-
NODE* args1 = NEW_LIST(NEW_LIT(node->nd_lit));
|
105
|
-
node->nd_recv = NEW_LIT(handler);
|
106
|
-
node->nd_mid = rb_intern("hooked_xstr");
|
107
|
-
node->nd_args = args1;
|
108
|
-
|
109
|
-
nd_set_type(node, NODE_CALL);
|
110
|
-
break;
|
111
|
-
}
|
112
|
-
case NODE_DXSTR:{
|
113
|
-
|
114
|
-
NODE* newnode = malloc(sizeof(NODE));
|
115
|
-
|
116
|
-
memcpy(newnode, node, sizeof(NODE));
|
117
|
-
nd_set_type(newnode, NODE_DSTR);
|
118
|
-
|
119
|
-
NODE* args1 = NEW_LIST(newnode);
|
120
|
-
|
121
|
-
node->nd_recv = NEW_LIT(handler);
|
122
|
-
node->nd_mid = rb_intern("hooked_xstr");
|
123
|
-
node->nd_args = args1;
|
124
|
-
|
125
|
-
nd_set_type(node, NODE_CALL);
|
126
|
-
|
127
|
-
break;
|
128
|
-
}
|
129
|
-
case NODE_COLON3: {
|
130
|
-
|
131
|
-
ID const_id = node->u2.id;
|
132
|
-
|
133
|
-
VALUE two_points = rb_str_new2("::");
|
134
|
-
VALUE base_namespace_sym = rb_funcall(handler, rb_intern("base_namespace"),0);
|
135
|
-
VALUE base_namespace_str = rb_funcall(base_namespace_sym, rb_intern("to_s"), 0);
|
136
|
-
VALUE base_namespace_array = rb_funcall(base_namespace_str, rb_intern("split"), 1, two_points);
|
137
|
-
|
138
|
-
if (RARRAY(base_namespace_array)->len == 1) {
|
139
|
-
node->nd_mid = const_id;
|
140
|
-
node->nd_head = NEW_CONST(SYM2ID(base_namespace_sym));
|
141
|
-
} else {
|
142
|
-
node->nd_mid = const_id;
|
143
|
-
|
144
|
-
NODE* prevnode;
|
145
|
-
|
146
|
-
int i;
|
147
|
-
for (i=0; i<RARRAY(base_namespace_array)->len; ++i) {
|
148
|
-
|
149
|
-
|
150
|
-
VALUE curr = rb_ary_entry(base_namespace_array, i);
|
151
|
-
|
152
|
-
ID curr_id =
|
153
|
-
SYM2ID(rb_funcall(curr, rb_intern("to_sym"), 0) );
|
154
|
-
|
155
|
-
if (i==0) {
|
156
|
-
prevnode = NEW_CONST(curr_id);
|
157
|
-
} else {
|
158
|
-
prevnode = NEW_COLON2(prevnode, curr_id);
|
159
|
-
}
|
160
|
-
}
|
161
|
-
|
162
|
-
node->nd_head = prevnode;
|
163
|
-
}
|
164
|
-
|
165
|
-
nd_set_type(node, NODE_COLON2);
|
166
|
-
break;
|
167
|
-
}
|
168
|
-
/* case NODE_LASGN:
|
169
|
-
case NODE_IASGN:
|
170
|
-
case NODE_DASGN:
|
171
|
-
case NODE_CVASGN:
|
172
|
-
case NODE_CVDECL:*/
|
173
|
-
case NODE_GASGN: {
|
174
|
-
|
175
|
-
NODE* args1;
|
176
|
-
NODE* args2 = NEW_LIST(node->nd_value);
|
177
|
-
|
178
|
-
if (node->nd_entry != 0) {
|
179
|
-
args1 = NEW_LIST(NEW_LIT(ID2SYM(node->nd_entry->id)));
|
180
|
-
} else {
|
181
|
-
args1 = NEW_LIST(NEW_LIT(ID2SYM(rb_intern("unknown_global"))));
|
182
|
-
}
|
183
|
-
|
184
|
-
node->nd_recv = NEW_CALL(NEW_LIT(handler), rb_intern("hooked_gasgn"), args1);
|
185
|
-
node->nd_mid = rb_intern("set_value");
|
186
|
-
node->nd_args = args2;
|
187
|
-
|
188
|
-
nd_set_type(node, NODE_CALL);
|
189
|
-
break;
|
190
|
-
}
|
191
|
-
case NODE_CDECL: {
|
192
|
-
|
193
|
-
NODE* else_node = node->nd_else;
|
194
|
-
NODE* head_node = node->nd_head;
|
195
|
-
NODE* base_class;
|
196
|
-
|
197
|
-
ID vid;
|
198
|
-
|
199
|
-
if (node->nd_vid == 0) {
|
200
|
-
base_class = else_node;
|
201
|
-
vid = node->nd_else->nd_mid;
|
202
|
-
} else {
|
203
|
-
base_class = NEW_LIT( (ruby_cref->nd_clss));
|
204
|
-
vid = node->nd_vid;
|
205
|
-
}
|
206
|
-
|
207
|
-
|
208
|
-
NODE* args1 = NEW_LIST(base_class);
|
209
|
-
NODE* args2 = NEW_LIST(NEW_LIT(ID2SYM(vid)));
|
210
|
-
NODE* args3 = NEW_LIST(node->nd_value);
|
211
|
-
|
212
|
-
node->nd_recv = NEW_CALL(NEW_LIT(handler), rb_intern("hooked_cdecl"), args1);
|
213
|
-
node->nd_recv = NEW_CALL(node->nd_recv, rb_intern("set_id"), args2);
|
214
|
-
node->nd_mid = rb_intern("set_value");
|
215
|
-
node->nd_args = args3;
|
216
|
-
|
217
|
-
nd_set_type(node, NODE_CALL);
|
218
|
-
break;
|
219
|
-
}
|
220
|
-
|
221
|
-
|
222
|
-
case NODE_SUPER:
|
223
|
-
case NODE_ZSUPER: {
|
224
|
-
node->nd_mid = rb_intern("hooked_super");
|
225
|
-
node->nd_recv = NEW_LIT(handler);
|
226
|
-
nd_set_type(node, NODE_CALL);
|
227
|
-
break;
|
228
|
-
}
|
229
|
-
case NODE_FCALL: {
|
230
|
-
if (id == method_public) break;
|
231
|
-
if (id == method_private) break;
|
232
|
-
if (id == method_protected) break;
|
233
|
-
|
234
|
-
patch_local_call_node(node, handler);
|
235
|
-
break;
|
236
|
-
}
|
237
|
-
|
238
|
-
case NODE_CALL: {
|
239
|
-
patch_call_node(node, handler);
|
240
|
-
break;
|
241
|
-
|
242
|
-
}
|
243
|
-
case NODE_VCALL: {
|
244
|
-
if (id == method_public) break;
|
245
|
-
if (id == method_private) break;
|
246
|
-
if (id == method_protected) break;
|
247
|
-
|
248
|
-
patch_local_call_node(node, handler);
|
249
|
-
|
250
|
-
break;
|
251
|
-
}
|
252
|
-
}
|
253
|
-
}
|
254
|
-
|
255
|
-
void process_recursive_node(NODE* node, VALUE handler ) {
|
256
|
-
|
257
|
-
switch (nd_type(node)) {
|
258
|
-
|
259
|
-
case NODE_BLOCK:
|
260
|
-
{
|
261
|
-
while (node) {
|
262
|
-
process_node(node->nd_head, handler);
|
263
|
-
node = node->nd_next;
|
264
|
-
}
|
265
|
-
}
|
266
|
-
break;
|
267
|
-
|
268
|
-
case NODE_FBODY:
|
269
|
-
case NODE_DEFINED:
|
270
|
-
case NODE_COLON2:
|
271
|
-
process_node(node->nd_head, handler);
|
272
|
-
break;
|
273
|
-
|
274
|
-
case NODE_MATCH2:
|
275
|
-
case NODE_MATCH3:
|
276
|
-
process_node(node->nd_recv, handler);
|
277
|
-
process_node(node->nd_value, handler);
|
278
|
-
break;
|
279
|
-
|
280
|
-
case NODE_BEGIN:
|
281
|
-
case NODE_OPT_N:
|
282
|
-
case NODE_NOT:
|
283
|
-
process_node(node->nd_body, handler);
|
284
|
-
break;
|
285
|
-
|
286
|
-
case NODE_IF:
|
287
|
-
process_node(node->nd_cond, handler);
|
288
|
-
if (node->nd_body) {
|
289
|
-
process_node(node->nd_body, handler);
|
290
|
-
}
|
291
|
-
if (node->nd_else) {
|
292
|
-
process_node(node->nd_else, handler);
|
293
|
-
}
|
294
|
-
break;
|
295
|
-
|
296
|
-
case NODE_CASE:
|
297
|
-
if (node->nd_head != NULL) {
|
298
|
-
process_node(node->nd_head, handler);
|
299
|
-
}
|
300
|
-
node = node->nd_body;
|
301
|
-
while (node) {
|
302
|
-
process_node(node, handler);
|
303
|
-
if (nd_type(node) == NODE_WHEN) { /* when */
|
304
|
-
node = node->nd_next;
|
305
|
-
} else {
|
306
|
-
break; /* else */
|
307
|
-
}
|
308
|
-
}
|
309
|
-
break;
|
310
|
-
|
311
|
-
case NODE_WHEN:
|
312
|
-
process_node(node->nd_head, handler);
|
313
|
-
if (node->nd_body) {
|
314
|
-
process_node(node->nd_body, handler);
|
315
|
-
}
|
316
|
-
break;
|
317
|
-
|
318
|
-
case NODE_WHILE:
|
319
|
-
case NODE_UNTIL:
|
320
|
-
process_node(node->nd_cond, handler);
|
321
|
-
if (node->nd_body) {
|
322
|
-
process_node(node->nd_body, handler);
|
323
|
-
}
|
324
|
-
break;
|
325
|
-
|
326
|
-
case NODE_BLOCK_PASS:
|
327
|
-
process_node(node->nd_body, handler);
|
328
|
-
process_node(node->nd_iter, handler);
|
329
|
-
break;
|
330
|
-
|
331
|
-
case NODE_ITER:
|
332
|
-
case NODE_FOR:
|
333
|
-
process_node(node->nd_iter, handler);
|
334
|
-
if (node->nd_var != (NODE *)1
|
335
|
-
&& node->nd_var != (NODE *)2
|
336
|
-
&& node->nd_var != NULL) {
|
337
|
-
process_node(node->nd_var, handler);
|
338
|
-
}
|
339
|
-
process_node(node->nd_body, handler);
|
340
|
-
break;
|
341
|
-
|
342
|
-
case NODE_BREAK:
|
343
|
-
case NODE_NEXT:
|
344
|
-
if (node->nd_stts)
|
345
|
-
process_node(node->nd_stts, handler);
|
346
|
-
|
347
|
-
break;
|
348
|
-
|
349
|
-
case NODE_YIELD:
|
350
|
-
if (node->nd_stts)
|
351
|
-
process_node(node->nd_stts, handler);
|
352
|
-
|
353
|
-
break;
|
354
|
-
|
355
|
-
case NODE_RESCUE:
|
356
|
-
process_node(node->nd_1st, handler);
|
357
|
-
process_node(node->nd_2nd, handler);
|
358
|
-
process_node(node->nd_3rd, handler);
|
359
|
-
break;
|
360
|
-
|
361
|
-
/*
|
362
|
-
// rescue body:
|
363
|
-
// begin stmt rescue exception => var; stmt; [rescue e2 => v2; s2;]* end
|
364
|
-
// stmt rescue stmt
|
365
|
-
// a = b rescue c
|
366
|
-
*/
|
367
|
-
|
368
|
-
case NODE_RESBODY:
|
369
|
-
if (node->nd_3rd) {
|
370
|
-
process_node(node->nd_3rd, handler);
|
371
|
-
}
|
372
|
-
process_node(node->nd_2nd, handler);
|
373
|
-
process_node(node->nd_1st, handler);
|
374
|
-
break;
|
375
|
-
|
376
|
-
case NODE_ENSURE:
|
377
|
-
process_node(node->nd_head, handler);
|
378
|
-
if (node->nd_ensr) {
|
379
|
-
process_node(node->nd_ensr, handler);
|
380
|
-
}
|
381
|
-
break;
|
382
|
-
|
383
|
-
case NODE_AND:
|
384
|
-
case NODE_OR:
|
385
|
-
process_node(node->nd_1st, handler);
|
386
|
-
process_node(node->nd_2nd, handler);
|
387
|
-
break;
|
388
|
-
|
389
|
-
case NODE_FLIP2:
|
390
|
-
case NODE_FLIP3:
|
391
|
-
process_node(node->nd_beg, handler);
|
392
|
-
process_node(node->nd_end, handler);
|
393
|
-
break;
|
394
|
-
|
395
|
-
case NODE_DOT2:
|
396
|
-
case NODE_DOT3:
|
397
|
-
process_node(node->nd_beg, handler);
|
398
|
-
process_node(node->nd_end, handler);
|
399
|
-
break;
|
400
|
-
|
401
|
-
case NODE_RETURN:
|
402
|
-
if (node->nd_stts)
|
403
|
-
process_node(node->nd_stts, handler);
|
404
|
-
break;
|
405
|
-
|
406
|
-
case NODE_ARGSCAT:
|
407
|
-
case NODE_ARGSPUSH:
|
408
|
-
process_node(node->nd_head, handler);
|
409
|
-
process_node(node->nd_body, handler);
|
410
|
-
break;
|
411
|
-
|
412
|
-
case NODE_CALL:
|
413
|
-
case NODE_FCALL:
|
414
|
-
case NODE_VCALL:
|
415
|
-
if (nd_type(node) != NODE_FCALL) {
|
416
|
-
if (node->nd_recv) process_node(node->nd_recv, handler);
|
417
|
-
}
|
418
|
-
if (node->nd_args || nd_type(node) != NODE_FCALL) {
|
419
|
-
if (node->nd_args) process_node(node->nd_args, handler);
|
420
|
-
}
|
421
|
-
break;
|
422
|
-
|
423
|
-
case NODE_SUPER:
|
424
|
-
process_node(node->nd_args, handler);
|
425
|
-
break;
|
426
|
-
|
427
|
-
case NODE_BMETHOD:
|
428
|
-
{
|
429
|
-
struct BLOCK *data;
|
430
|
-
Data_Get_Struct(node->nd_cval, struct BLOCK, data);
|
431
|
-
|
432
|
-
if (data->var == 0 || data->var == (NODE *)1 || data->var == (NODE *)2) {
|
433
|
-
} else {
|
434
|
-
process_node(data->var, handler);
|
435
|
-
}
|
436
|
-
process_node(data->body, handler);
|
437
|
-
}
|
438
|
-
break;
|
439
|
-
|
440
|
-
#if RUBY_VERSION_CODE < 190
|
441
|
-
case NODE_DMETHOD:
|
442
|
-
{
|
443
|
-
struct METHOD *data;
|
444
|
-
Data_Get_Struct(node->nd_cval, struct METHOD, data);
|
445
|
-
process_node(data->body, handler);
|
446
|
-
|
447
|
-
break;
|
448
|
-
}
|
449
|
-
#endif
|
450
|
-
|
451
|
-
case NODE_METHOD:
|
452
|
-
// You should not ever get here. parse_tree_for_meth passes nd_body
|
453
|
-
process_node(node->nd_body, handler);
|
454
|
-
break;
|
455
|
-
|
456
|
-
case NODE_SCOPE:
|
457
|
-
process_node(node->nd_next, handler);
|
458
|
-
break;
|
459
|
-
|
460
|
-
case NODE_OP_ASGN1:
|
461
|
-
process_node(node->nd_recv, handler);
|
462
|
-
#if RUBY_VERSION_CODE < 185
|
463
|
-
process_node(node->nd_args->nd_next, handler);
|
464
|
-
#else
|
465
|
-
process_node(node->nd_args->nd_2nd, handler);
|
466
|
-
#endif
|
467
|
-
process_node(node->nd_args->nd_head, handler);
|
468
|
-
break;
|
469
|
-
|
470
|
-
case NODE_OP_ASGN2:
|
471
|
-
process_node(node->nd_recv, handler);
|
472
|
-
process_node(node->nd_value, handler);
|
473
|
-
break;
|
474
|
-
|
475
|
-
case NODE_OP_ASGN_AND:
|
476
|
-
case NODE_OP_ASGN_OR:
|
477
|
-
process_node(node->nd_head, handler);
|
478
|
-
process_node(node->nd_value, handler);
|
479
|
-
break;
|
480
|
-
|
481
|
-
case NODE_MASGN:
|
482
|
-
if (node->nd_head) {
|
483
|
-
process_node(node->nd_head, handler);
|
484
|
-
}
|
485
|
-
if (node->nd_args) {
|
486
|
-
if (node->nd_args != (NODE *)-1) {
|
487
|
-
process_node(node->nd_args, handler);
|
488
|
-
}
|
489
|
-
}
|
490
|
-
if (node->nd_value) {
|
491
|
-
process_node(node->nd_value, handler);
|
492
|
-
}
|
493
|
-
break;
|
494
|
-
|
495
|
-
case NODE_LASGN:
|
496
|
-
case NODE_IASGN:
|
497
|
-
case NODE_DASGN:
|
498
|
-
case NODE_CVASGN:
|
499
|
-
case NODE_CVDECL:
|
500
|
-
case NODE_GASGN:
|
501
|
-
process_node(node->nd_value, handler);
|
502
|
-
break;
|
503
|
-
|
504
|
-
case NODE_CDECL:
|
505
|
-
if (node->nd_vid) {
|
506
|
-
} else {
|
507
|
-
process_node(node->nd_else, handler);
|
508
|
-
}
|
509
|
-
process_node(node->nd_value, handler);
|
510
|
-
break;
|
511
|
-
|
512
|
-
case NODE_DASGN_CURR:
|
513
|
-
if (node->nd_value) {
|
514
|
-
process_node(node->nd_value, handler);
|
515
|
-
}
|
516
|
-
break;
|
517
|
-
|
518
|
-
case NODE_ALIAS: /* u1 u2 (alias :blah :blah2) */
|
519
|
-
#if RUBY_VERSION_CODE < 185
|
520
|
-
#else
|
521
|
-
process_node(node->nd_1st, handler);
|
522
|
-
process_node(node->nd_2nd, handler);
|
523
|
-
#endif
|
524
|
-
break;
|
525
|
-
|
526
|
-
case NODE_UNDEF: /* u2 (undef name, ...) */
|
527
|
-
#if RUBY_VERSION_CODE < 185
|
528
|
-
#else
|
529
|
-
process_node(node->nd_value, handler);
|
530
|
-
#endif
|
531
|
-
break;
|
532
|
-
|
533
|
-
case NODE_HASH:
|
534
|
-
{
|
535
|
-
NODE *list;
|
536
|
-
|
537
|
-
list = node->nd_head;
|
538
|
-
while (list) {
|
539
|
-
process_node(list->nd_head, handler);
|
540
|
-
list = list->nd_next;
|
541
|
-
}
|
542
|
-
}
|
543
|
-
break;
|
544
|
-
|
545
|
-
case NODE_ARRAY:
|
546
|
-
while (node) {
|
547
|
-
process_node(node->nd_head, handler);
|
548
|
-
node = node->nd_next;
|
549
|
-
}
|
550
|
-
break;
|
551
|
-
|
552
|
-
case NODE_DSTR:
|
553
|
-
case NODE_DSYM:
|
554
|
-
case NODE_DXSTR:
|
555
|
-
case NODE_DREGX:
|
556
|
-
case NODE_DREGX_ONCE:
|
557
|
-
{
|
558
|
-
NODE *list = node->nd_next;
|
559
|
-
while (list) {
|
560
|
-
if (list->nd_head) {
|
561
|
-
process_node(list->nd_head, handler);
|
562
|
-
}
|
563
|
-
list = list->nd_next;
|
564
|
-
}
|
565
|
-
}
|
566
|
-
break;
|
567
|
-
|
568
|
-
case NODE_DEFN:
|
569
|
-
case NODE_DEFS:
|
570
|
-
if (node->nd_defn) {
|
571
|
-
if (nd_type(node) == NODE_DEFS)
|
572
|
-
process_node(node->nd_recv, handler);
|
573
|
-
|
574
|
-
process_node(node->nd_defn, handler);
|
575
|
-
}
|
576
|
-
break;
|
577
|
-
|
578
|
-
case NODE_CLASS:
|
579
|
-
case NODE_MODULE:
|
580
|
-
if (nd_type(node->nd_cpath) == NODE_COLON2 && ! node->nd_cpath->nd_vid) {
|
581
|
-
} else {
|
582
|
-
process_node(node->nd_cpath, handler);
|
583
|
-
}
|
584
|
-
|
585
|
-
if (nd_type(node) == NODE_CLASS) {
|
586
|
-
if (node->nd_super) {
|
587
|
-
process_node(node->nd_super, handler);
|
588
|
-
}
|
589
|
-
}
|
590
|
-
process_node(node->nd_body, handler);
|
591
|
-
break;
|
592
|
-
|
593
|
-
case NODE_SCLASS:
|
594
|
-
process_node(node->nd_recv, handler);
|
595
|
-
process_node(node->nd_body, handler);
|
596
|
-
break;
|
597
|
-
|
598
|
-
case NODE_ARGS: {
|
599
|
-
NODE *optnode;
|
600
|
-
optnode = node->nd_opt;
|
601
|
-
if (optnode) {
|
602
|
-
process_node(node->nd_opt, handler);
|
603
|
-
}
|
604
|
-
} break;
|
605
|
-
|
606
|
-
case NODE_NEWLINE:
|
607
|
-
process_node(node->nd_next, handler);
|
608
|
-
break;
|
609
|
-
|
610
|
-
case NODE_SPLAT:
|
611
|
-
case NODE_TO_ARY:
|
612
|
-
case NODE_SVALUE: /* a = b, c */
|
613
|
-
process_node(node->nd_head, handler);
|
614
|
-
break;
|
615
|
-
|
616
|
-
case NODE_ATTRASGN: /* literal.meth = y u1 u2 u3 */
|
617
|
-
/* node id node */
|
618
|
-
if (node->nd_1st == RNODE(1)) {
|
619
|
-
// add_to_parse_tree(self, current, NEW_SELF(), locals);
|
620
|
-
} else {
|
621
|
-
process_node(node->nd_1st, handler);
|
622
|
-
}
|
623
|
-
process_node(node->nd_3rd, handler);
|
624
|
-
break;
|
625
|
-
|
626
|
-
case NODE_EVSTR:
|
627
|
-
process_node(node->nd_2nd, handler);
|
628
|
-
break;
|
629
|
-
|
630
|
-
|
631
|
-
#if RUBY_VERSION_CODE >= 190
|
632
|
-
case NODE_ERRINFO:
|
633
|
-
case NODE_VALUES:
|
634
|
-
case NODE_PRELUDE:
|
635
|
-
case NODE_LAMBDA:
|
636
|
-
puts("no worky in 1.9 yet");
|
637
|
-
break;
|
638
|
-
#endif
|
639
|
-
|
640
|
-
/* Nodes we found but have yet to decypher */
|
641
|
-
/* I think these are all runtime only... not positive but... */
|
642
|
-
case NODE_MEMO: /* enum.c zip */
|
643
|
-
case NODE_CREF:
|
644
|
-
/* #defines: */
|
645
|
-
/* case NODE_LMASK: */
|
646
|
-
/* case NODE_LSHIFT: */
|
647
|
-
default:
|
648
|
-
break;
|
649
|
-
}
|
650
|
-
}
|
651
|
-
|
652
|
-
void process_node(NODE* node, VALUE handler) {
|
653
|
-
if (node) {
|
654
|
-
process_recursive_node(node, handler);
|
655
|
-
process_individual_node(node, handler);
|
656
|
-
}
|
657
|
-
}
|
658
|
-
|
659
|
-
VALUE hook_method_tree(VALUE self, VALUE rb_method) {
|
660
|
-
|
661
|
-
struct METHOD* method;
|
662
|
-
Data_Get_Struct(rb_method,struct METHOD,method);
|
663
|
-
|
664
|
-
NODE* node = method->body->nd_defn;
|
665
|
-
process_node(node, self);
|
666
|
-
|
667
|
-
return Qnil;
|
668
|
-
}
|
669
|
-
|
670
|
-
|
671
|
-
VALUE hook_block(VALUE self, VALUE handler) {
|
672
|
-
process_node(ruby_frame->node->nd_recv, handler);
|
673
|
-
}
|
674
|
-
|
675
|
-
VALUE caller_method(VALUE self, VALUE rblevel) {
|
676
|
-
int level = FIX2INT(rblevel);
|
677
|
-
|
678
|
-
struct FRAME* frame = ruby_frame;
|
679
|
-
while(level--) frame = frame->prev;
|
680
|
-
|
681
|
-
return ID2SYM(frame->orig_func);
|
682
|
-
}
|
683
|
-
|
684
|
-
VALUE caller_class(VALUE self, VALUE rblevel) {
|
685
|
-
int level = FIX2INT(rblevel);
|
686
|
-
|
687
|
-
struct FRAME* frame = ruby_frame;
|
688
|
-
while(level--) frame = frame->prev;
|
689
|
-
|
690
|
-
return frame->last_class;
|
691
|
-
}
|
692
|
-
|
693
|
-
VALUE caller_obj(VALUE self, VALUE rblevel) {
|
694
|
-
int level = FIX2INT(rblevel);
|
695
|
-
|
696
|
-
struct FRAME* frame = ruby_frame;
|
697
|
-
while(level--) frame = frame->prev;
|
698
|
-
|
699
|
-
return frame->self;
|
700
|
-
}
|
701
|
-
|
702
|
-
|
703
|
-
static void
|
704
|
-
blk_mark(data)
|
705
|
-
struct BLOCK *data;
|
706
|
-
{
|
707
|
-
while (data) {
|
708
|
-
rb_gc_mark_frame(&data->frame);
|
709
|
-
rb_gc_mark((VALUE)data->scope);
|
710
|
-
rb_gc_mark((VALUE)data->var);
|
711
|
-
rb_gc_mark((VALUE)data->body);
|
712
|
-
rb_gc_mark((VALUE)data->self);
|
713
|
-
rb_gc_mark((VALUE)data->dyna_vars);
|
714
|
-
rb_gc_mark((VALUE)data->cref);
|
715
|
-
rb_gc_mark(data->wrapper);
|
716
|
-
rb_gc_mark(data->block_obj);
|
717
|
-
data = data->prev;
|
718
|
-
}
|
719
|
-
}
|
720
|
-
|
721
|
-
static void
|
722
|
-
blk_free(data)
|
723
|
-
struct BLOCK *data;
|
724
|
-
{
|
725
|
-
void *tmp;
|
726
|
-
|
727
|
-
while (data) {
|
728
|
-
frame_free(&data->frame);
|
729
|
-
tmp = data;
|
730
|
-
data = data->prev;
|
731
|
-
free(tmp);
|
732
|
-
}
|
733
|
-
}
|
734
|
-
|
735
|
-
|
736
|
-
VALUE validate_syntax(VALUE self, VALUE code) {
|
737
|
-
|
738
|
-
NODE* node = rb_compile_string("(eval)", code, 1);
|
739
|
-
|
740
|
-
if (node == 0) {
|
741
|
-
rb_raise(rb_eSyntaxError,"");
|
742
|
-
}
|
743
|
-
|
744
|
-
return Qnil;
|
745
|
-
}
|
746
|
-
|
747
|
-
|
748
|
-
extern void Init_evalhook_base() {
|
749
|
-
m_EvalHook = rb_define_module("EvalHook");
|
750
|
-
|
751
|
-
/*
|
752
|
-
Class to create hook instances for specific handling of method calls and/or const and global assignment
|
753
|
-
|
754
|
-
=== Example:
|
755
|
-
|
756
|
-
Hook of method calls
|
757
|
-
|
758
|
-
require "rubygems"
|
759
|
-
require "evalhook"
|
760
|
-
|
761
|
-
class Hook < EvalHook::HookHandler
|
762
|
-
def handle_method(klass, recv, method_name)
|
763
|
-
print "called #{klass}##{method_name} over #{recv}\n"
|
764
|
-
nil
|
765
|
-
end
|
766
|
-
end
|
767
|
-
|
768
|
-
h = Hook.new
|
769
|
-
h.evalhook('print "hello world\n"')
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
See README for more examples
|
775
|
-
|
776
|
-
*/
|
777
|
-
c_HookHandler = rb_define_class_under(m_EvalHook, "HookHandler", rb_cObject);
|
778
|
-
|
779
|
-
rb_define_singleton_method(m_EvalHook, "hook_block", hook_block, 1);
|
780
|
-
rb_define_singleton_method(m_EvalHook, "validate_syntax", validate_syntax, 1);
|
781
|
-
|
782
|
-
rb_define_method(c_HookHandler, "hook_method_tree", hook_method_tree, 1);
|
783
|
-
|
784
|
-
rb_define_method(c_HookHandler, "caller_method", caller_method, 1);
|
785
|
-
rb_define_method(c_HookHandler, "caller_class", caller_class, 1);
|
786
|
-
rb_define_method(c_HookHandler, "caller_obj", caller_obj, 1);
|
787
|
-
|
788
|
-
method_local_hooked_method = rb_intern("local_hooked_method");
|
789
|
-
method_hooked_method = rb_intern("hooked_method");
|
790
|
-
method_call = rb_intern("call");
|
791
|
-
method_private = rb_intern("private");
|
792
|
-
method_public = rb_intern("public");
|
793
|
-
method_protected = rb_intern("protected");
|
794
|
-
method_set_hook_handler = rb_intern("set_hook_handler");
|
795
|
-
}
|