rallhook 0.7.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.
Files changed (50) hide show
  1. data/AUTHORS +3 -0
  2. data/CHANGELOG +82 -0
  3. data/README +207 -0
  4. data/Rakefile +49 -0
  5. data/TODO +8 -0
  6. data/examples/hook/example1.rb +19 -0
  7. data/examples/hook/example2.rb +30 -0
  8. data/examples/hook/example3.rb +24 -0
  9. data/examples/hook/example4.rb +18 -0
  10. data/examples/hook/intercept.rb +41 -0
  11. data/examples/hook/intercept2.rb +49 -0
  12. data/examples/hook/redirect.rb +55 -0
  13. data/examples/hook/redirect_inherited.rb +28 -0
  14. data/examples/hook/shadow.rb +44 -0
  15. data/examples/instrospection/main.rb +13 -0
  16. data/examples/instrospection/source1.rb +4 -0
  17. data/examples/instrospection/source2.rb +4 -0
  18. data/ext/rallhook_base/distorm.h +401 -0
  19. data/ext/rallhook_base/extconf.rb +21 -0
  20. data/ext/rallhook_base/hook.c +165 -0
  21. data/ext/rallhook_base/hook.h +30 -0
  22. data/ext/rallhook_base/hook_rb_call.c +88 -0
  23. data/ext/rallhook_base/hook_rb_call.h +33 -0
  24. data/ext/rallhook_base/method_node.c +212 -0
  25. data/ext/rallhook_base/method_node.h +27 -0
  26. data/ext/rallhook_base/node_defs.h +294 -0
  27. data/ext/rallhook_base/rallhook.c +396 -0
  28. data/ext/rallhook_base/rb_call_fake.c +398 -0
  29. data/ext/rallhook_base/rb_call_fake.h +138 -0
  30. data/ext/rallhook_base/restrict_def.c +176 -0
  31. data/ext/rallhook_base/restrict_def.h +37 -0
  32. data/ext/rallhook_base/ruby_redirect.c +122 -0
  33. data/ext/rallhook_base/ruby_redirect.h +33 -0
  34. data/ext/rallhook_base/ruby_symbols.c +43 -0
  35. data/ext/rallhook_base/ruby_symbols.h +28 -0
  36. data/ext/rallhook_base/ruby_version.h +21 -0
  37. data/lib/rallhook/thread_hook.rb +37 -0
  38. data/lib/rallhook.rb +384 -0
  39. data/test/basic_proc.rb +45 -0
  40. data/test/integrity/test_array.rb +42 -0
  41. data/test/integrity/test_binding.rb +26 -0
  42. data/test/integrity/test_block.rb +37 -0
  43. data/test/integrity/test_call.rb +1 -0
  44. data/test/integrity/test_class_methods.rb +1 -0
  45. data/test/integrity/test_exception.rb +1 -0
  46. data/test/integrity/test_super.rb +34 -0
  47. data/test/introspection/test_call.rb +29 -0
  48. data/test/introspection/test_class_method.rb +41 -0
  49. data/test/introspection/test_file.rb +15 -0
  50. metadata +113 -0
@@ -0,0 +1,33 @@
1
+ /*
2
+
3
+ This file is part of the rallhook project, http://github.com/tario/rallhook
4
+
5
+ Copyright (c) 2009-2010 Roberto Dario Seminara <robertodarioseminara@gmail.com>
6
+
7
+ rallhook 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
+ rallhook 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 rallhook. if not, see <http://www.gnu.org/licenses/>.
19
+
20
+ */
21
+
22
+ #ifndef __HOOK_RB_CALL
23
+ #define __HOOK_RB_CALL
24
+
25
+ void* hook_rb_call(void* fake_function);
26
+
27
+ #ifdef RUBY1_9
28
+ void* hook_vm_call_method(void *fake_function);
29
+ #endif
30
+
31
+ void init_hook_rb_call();
32
+
33
+ #endif
@@ -0,0 +1,212 @@
1
+ /*
2
+
3
+ This file is part of the rallhook project, http://github.com/tario/rallhook
4
+
5
+ Copyright (c) 2009-2010 Roberto Dario Seminara <robertodarioseminara@gmail.com>
6
+
7
+ rallhook 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
+ rallhook 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 rallhook. if not, see <http://www.gnu.org/licenses/>.
19
+
20
+ */
21
+
22
+ #include <ruby.h>
23
+ #include <ruby_version.h>
24
+
25
+ #ifdef RUBY1_8
26
+ #include <node.h>
27
+ #endif
28
+
29
+ #ifdef RUBY1_9
30
+ #include <node_defs.h>
31
+ #endif
32
+
33
+ #include "ruby_symbols.h"
34
+ #include "distorm.h"
35
+
36
+ #ifndef __USE_GNU
37
+ #define __USE_GNU
38
+ #endif
39
+ #include <dlfcn.h>
40
+
41
+
42
+ VALUE rb_cNode;
43
+ ID intern_owner;
44
+ ID intern_name;
45
+ ID intern_sym;
46
+
47
+ /// from eval.c
48
+ #ifdef RUBY1_8
49
+ struct METHOD {
50
+ VALUE klass, rklass;
51
+
52
+ VALUE recv;
53
+ ID id, oid;
54
+ int safe_level;
55
+ NODE *body;
56
+ };
57
+ unsigned char* base__;
58
+
59
+ #define nd_file(n) n->nd_file
60
+
61
+ #endif
62
+
63
+ #ifdef RUBY1_9
64
+
65
+ // from proc.c
66
+ struct METHOD {
67
+ VALUE oclass; /* class that holds the method */
68
+ VALUE rclass; /* class of the receiver */
69
+ VALUE recv;
70
+ ID id, oid;
71
+ NODE *body;
72
+ };
73
+
74
+ typedef struct rb_iseq_struct__ {
75
+ VALUE type; // instruction sequence type
76
+ VALUE name; // String: iseq name
77
+ VALUE filename; // file information where this sequence from
78
+ } rb_iseq_t__;
79
+
80
+
81
+ typedef VALUE (*MNEW)(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope);
82
+ MNEW mnew_;
83
+ unsigned char* base__;
84
+
85
+ #endif
86
+
87
+ /*
88
+ The node that acts as body of the method
89
+ */
90
+ VALUE rb_method_body(VALUE self) {
91
+
92
+ // VALUE name = rb_funcall(self, intern_name, 0);
93
+ // VALUE sym = rb_funcall(name, intern_sym, 0);
94
+ // VALUE owner = rb_funcall(self, intern_owner, 0);
95
+ // NODE* body = rb_method_node(owner, SYM2ID(sym) );
96
+
97
+ struct METHOD* method;
98
+ Data_Get_Struct(self,struct METHOD,method);
99
+
100
+ if (method->body == 0) return Qnil;
101
+ if (method->body->nd_defn == 0) {
102
+ return Data_Wrap_Struct(rb_cNode, 0, 0, method->body);
103
+ } else {
104
+ return Data_Wrap_Struct(rb_cNode, 0, 0, method->body->nd_defn);
105
+ }
106
+ }
107
+
108
+ /*
109
+ The number of the line where the code associated with note are defined in the ruby source file
110
+ */
111
+ VALUE rb_node_line(VALUE self) {
112
+ NODE* _node;
113
+ Data_Get_Struct(self,NODE,_node);
114
+
115
+ #ifdef RUBY1_8
116
+ return INT2FIX(nd_line(_node));
117
+ #endif
118
+
119
+ #ifdef RUBY1_9
120
+ return INT2FIX(0);
121
+ #endif
122
+ }
123
+
124
+ /*
125
+ The name of the ruby source file where the code associated with the node are defined
126
+ */
127
+ VALUE rb_node_file(VALUE self) {
128
+ NODE* _node;
129
+ Data_Get_Struct(self,NODE,_node);
130
+
131
+ #ifdef RUBY1_8
132
+ if (nd_file(_node) == NULL ) {
133
+ return rb_str_new2("");
134
+ }
135
+ return rb_str_new2(nd_file(_node) );
136
+ #endif
137
+
138
+ #ifdef RUBY1_9
139
+
140
+ if (nd_type(_node) == RUBY_VM_METHOD_NODE) {
141
+ VALUE iseqval = (VALUE)(_node->nd_body);
142
+ rb_iseq_t__* ptr;
143
+ Data_Get_Struct(iseqval, rb_iseq_t__, ptr);
144
+
145
+ return ptr->filename;
146
+ }
147
+
148
+ return rb_str_new2("");
149
+
150
+ #endif
151
+
152
+ }
153
+
154
+
155
+ static void
156
+ bm_mark(struct METHOD *data)
157
+ {
158
+ #ifdef RUBY1_8
159
+ rb_gc_mark(data->klass);
160
+ rb_gc_mark(data->rklass);
161
+ rb_gc_mark(data->recv);
162
+ rb_gc_mark((VALUE)data->body);
163
+ #endif
164
+ #ifdef RUBY1_9
165
+ rb_gc_mark(data->rclass);
166
+ rb_gc_mark(data->oclass);
167
+ rb_gc_mark(data->recv);
168
+ rb_gc_mark((VALUE)data->body);
169
+ #endif
170
+
171
+ }
172
+
173
+ static VALUE
174
+ umethod_unchecked_bind(VALUE method, VALUE recv)
175
+ {
176
+ struct METHOD *data, *bound;
177
+
178
+ Data_Get_Struct(method, struct METHOD, data);
179
+
180
+ method = Data_Make_Struct(rb_cMethod, struct METHOD, bm_mark, -1, bound);
181
+ *bound = *data;
182
+ bound->recv = recv;
183
+ #ifdef RUBY1_8
184
+ bound->rklass = CLASS_OF(recv);
185
+ #endif
186
+ #ifdef RUBY1_9
187
+ bound->rclass = CLASS_OF(recv);
188
+ #endif
189
+
190
+ return method;
191
+ }
192
+
193
+
194
+ void init_node() {
195
+ rb_define_method(rb_cMethod, "body", rb_method_body,0);
196
+ rb_define_method(rb_cUnboundMethod, "body", rb_method_body,0);
197
+ rb_define_method(rb_cUnboundMethod, "unchecked_bind", umethod_unchecked_bind,1);
198
+
199
+ /*
200
+ The class Node represents the internal ruby node, a node is a piece of ruby code used
201
+ for represent ruby methods in memory and other executable entities, many nodes come from
202
+ the ruby source code and may be associated with a file and line where thats node are defined
203
+ */
204
+ rb_cNode = rb_define_class("Node", rb_cObject);
205
+
206
+ rb_define_method(rb_cNode, "line", rb_node_line, 0);
207
+ rb_define_method(rb_cNode, "file", rb_node_file, 0);
208
+
209
+ intern_owner = rb_intern("owner");
210
+ intern_name = rb_intern("name");
211
+ intern_sym = rb_intern("to_sym");
212
+ }
@@ -0,0 +1,27 @@
1
+ /*
2
+
3
+ This file is part of the rallhook project, http://github.com/tario/rallhook
4
+
5
+ Copyright (c) 2009-2010 Roberto Dario Seminara <robertodarioseminara@gmail.com>
6
+
7
+ rallhook 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
+ rallhook 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 rallhook. if not, see <http://www.gnu.org/licenses/>.
19
+
20
+ */
21
+
22
+ #ifndef __NODE_H
23
+ #define __NODE_H
24
+
25
+ void init_node();
26
+
27
+ #endif
@@ -0,0 +1,294 @@
1
+ /*
2
+
3
+ This file is part of the rallhook project, http://github.com/tario/rallhook
4
+
5
+ Copyright (c) 2009-2010 Roberto Dario Seminara <robertodarioseminara@gmail.com>
6
+
7
+ rallhook 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
+ rallhook 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 rallhook. if not, see <http://www.gnu.org/licenses/>.
19
+
20
+ */
21
+
22
+ #ifndef __NODE_DEFS_H
23
+ #define __NODE_DEFS_H
24
+
25
+
26
+ #ifdef RUBY1_9
27
+
28
+
29
+ enum node_type {
30
+ NODE_METHOD,
31
+ #define NODE_METHOD NODE_METHOD
32
+ NODE_FBODY,
33
+ #define NODE_FBODY NODE_FBODY
34
+ NODE_CFUNC,
35
+ #define NODE_CFUNC NODE_CFUNC
36
+ NODE_SCOPE,
37
+ #define NODE_SCOPE NODE_SCOPE
38
+ NODE_BLOCK,
39
+ #define NODE_BLOCK NODE_BLOCK
40
+ NODE_IF,
41
+ #define NODE_IF NODE_IF
42
+ NODE_CASE,
43
+ #define NODE_CASE NODE_CASE
44
+ NODE_WHEN,
45
+ #define NODE_WHEN NODE_WHEN
46
+ NODE_OPT_N,
47
+ #define NODE_OPT_N NODE_OPT_N
48
+ NODE_WHILE,
49
+ #define NODE_WHILE NODE_WHILE
50
+ NODE_UNTIL,
51
+ #define NODE_UNTIL NODE_UNTIL
52
+ NODE_ITER,
53
+ #define NODE_ITER NODE_ITER
54
+ NODE_FOR,
55
+ #define NODE_FOR NODE_FOR
56
+ NODE_BREAK,
57
+ #define NODE_BREAK NODE_BREAK
58
+ NODE_NEXT,
59
+ #define NODE_NEXT NODE_NEXT
60
+ NODE_REDO,
61
+ #define NODE_REDO NODE_REDO
62
+ NODE_RETRY,
63
+ #define NODE_RETRY NODE_RETRY
64
+ NODE_BEGIN,
65
+ #define NODE_BEGIN NODE_BEGIN
66
+ NODE_RESCUE,
67
+ #define NODE_RESCUE NODE_RESCUE
68
+ NODE_RESBODY,
69
+ #define NODE_RESBODY NODE_RESBODY
70
+ NODE_ENSURE,
71
+ #define NODE_ENSURE NODE_ENSURE
72
+ NODE_AND,
73
+ #define NODE_AND NODE_AND
74
+ NODE_OR,
75
+ #define NODE_OR NODE_OR
76
+ NODE_MASGN,
77
+ #define NODE_MASGN NODE_MASGN
78
+ NODE_LASGN,
79
+ #define NODE_LASGN NODE_LASGN
80
+ NODE_DASGN,
81
+ #define NODE_DASGN NODE_DASGN
82
+ NODE_DASGN_CURR,
83
+ #define NODE_DASGN_CURR NODE_DASGN_CURR
84
+ NODE_GASGN,
85
+ #define NODE_GASGN NODE_GASGN
86
+ NODE_IASGN,
87
+ #define NODE_IASGN NODE_IASGN
88
+ NODE_IASGN2,
89
+ #define NODE_IASGN2 NODE_IASGN2
90
+ NODE_CDECL,
91
+ #define NODE_CDECL NODE_CDECL
92
+ NODE_CVASGN,
93
+ #define NODE_CVASGN NODE_CVASGN
94
+ NODE_CVDECL,
95
+ #define NODE_CVDECL NODE_CVDECL
96
+ NODE_OP_ASGN1,
97
+ #define NODE_OP_ASGN1 NODE_OP_ASGN1
98
+ NODE_OP_ASGN2,
99
+ #define NODE_OP_ASGN2 NODE_OP_ASGN2
100
+ NODE_OP_ASGN_AND,
101
+ #define NODE_OP_ASGN_AND NODE_OP_ASGN_AND
102
+ NODE_OP_ASGN_OR,
103
+ #define NODE_OP_ASGN_OR NODE_OP_ASGN_OR
104
+ NODE_CALL,
105
+ #define NODE_CALL NODE_CALL
106
+ NODE_FCALL,
107
+ #define NODE_FCALL NODE_FCALL
108
+ NODE_VCALL,
109
+ #define NODE_VCALL NODE_VCALL
110
+ NODE_SUPER,
111
+ #define NODE_SUPER NODE_SUPER
112
+ NODE_ZSUPER,
113
+ #define NODE_ZSUPER NODE_ZSUPER
114
+ NODE_ARRAY,
115
+ #define NODE_ARRAY NODE_ARRAY
116
+ NODE_ZARRAY,
117
+ #define NODE_ZARRAY NODE_ZARRAY
118
+ NODE_VALUES,
119
+ #define NODE_VALUES NODE_VALUES
120
+ NODE_HASH,
121
+ #define NODE_HASH NODE_HASH
122
+ NODE_RETURN,
123
+ #define NODE_RETURN NODE_RETURN
124
+ NODE_YIELD,
125
+ #define NODE_YIELD NODE_YIELD
126
+ NODE_LVAR,
127
+ #define NODE_LVAR NODE_LVAR
128
+ NODE_DVAR,
129
+ #define NODE_DVAR NODE_DVAR
130
+ NODE_GVAR,
131
+ #define NODE_GVAR NODE_GVAR
132
+ NODE_IVAR,
133
+ #define NODE_IVAR NODE_IVAR
134
+ NODE_CONST,
135
+ #define NODE_CONST NODE_CONST
136
+ NODE_CVAR,
137
+ #define NODE_CVAR NODE_CVAR
138
+ NODE_NTH_REF,
139
+ #define NODE_NTH_REF NODE_NTH_REF
140
+ NODE_BACK_REF,
141
+ #define NODE_BACK_REF NODE_BACK_REF
142
+ NODE_MATCH,
143
+ #define NODE_MATCH NODE_MATCH
144
+ NODE_MATCH2,
145
+ #define NODE_MATCH2 NODE_MATCH2
146
+ NODE_MATCH3,
147
+ #define NODE_MATCH3 NODE_MATCH3
148
+ NODE_LIT,
149
+ #define NODE_LIT NODE_LIT
150
+ NODE_STR,
151
+ #define NODE_STR NODE_STR
152
+ NODE_DSTR,
153
+ #define NODE_DSTR NODE_DSTR
154
+ NODE_XSTR,
155
+ #define NODE_XSTR NODE_XSTR
156
+ NODE_DXSTR,
157
+ #define NODE_DXSTR NODE_DXSTR
158
+ NODE_EVSTR,
159
+ #define NODE_EVSTR NODE_EVSTR
160
+ NODE_DREGX,
161
+ #define NODE_DREGX NODE_DREGX
162
+ NODE_DREGX_ONCE,
163
+ #define NODE_DREGX_ONCE NODE_DREGX_ONCE
164
+ NODE_ARGS,
165
+ #define NODE_ARGS NODE_ARGS
166
+ NODE_ARGS_AUX,
167
+ #define NODE_ARGS_AUX NODE_ARGS_AUX
168
+ NODE_OPT_ARG,
169
+ #define NODE_OPT_ARG NODE_OPT_ARG
170
+ NODE_POSTARG,
171
+ #define NODE_POSTARG NODE_POSTARG
172
+ NODE_ARGSCAT,
173
+ #define NODE_ARGSCAT NODE_ARGSCAT
174
+ NODE_ARGSPUSH,
175
+ #define NODE_ARGSPUSH NODE_ARGSPUSH
176
+ NODE_SPLAT,
177
+ #define NODE_SPLAT NODE_SPLAT
178
+ NODE_TO_ARY,
179
+ #define NODE_TO_ARY NODE_TO_ARY
180
+ NODE_BLOCK_ARG,
181
+ #define NODE_BLOCK_ARG NODE_BLOCK_ARG
182
+ NODE_BLOCK_PASS,
183
+ #define NODE_BLOCK_PASS NODE_BLOCK_PASS
184
+ NODE_DEFN,
185
+ #define NODE_DEFN NODE_DEFN
186
+ NODE_DEFS,
187
+ #define NODE_DEFS NODE_DEFS
188
+ NODE_ALIAS,
189
+ #define NODE_ALIAS NODE_ALIAS
190
+ NODE_VALIAS,
191
+ #define NODE_VALIAS NODE_VALIAS
192
+ NODE_UNDEF,
193
+ #define NODE_UNDEF NODE_UNDEF
194
+ NODE_CLASS,
195
+ #define NODE_CLASS NODE_CLASS
196
+ NODE_MODULE,
197
+ #define NODE_MODULE NODE_MODULE
198
+ NODE_SCLASS,
199
+ #define NODE_SCLASS NODE_SCLASS
200
+ NODE_COLON2,
201
+ #define NODE_COLON2 NODE_COLON2
202
+ NODE_COLON3,
203
+ #define NODE_COLON3 NODE_COLON3
204
+ NODE_DOT2,
205
+ #define NODE_DOT2 NODE_DOT2
206
+ NODE_DOT3,
207
+ #define NODE_DOT3 NODE_DOT3
208
+ NODE_FLIP2,
209
+ #define NODE_FLIP2 NODE_FLIP2
210
+ NODE_FLIP3,
211
+ #define NODE_FLIP3 NODE_FLIP3
212
+ NODE_ATTRSET,
213
+ #define NODE_ATTRSET NODE_ATTRSET
214
+ NODE_SELF,
215
+ #define NODE_SELF NODE_SELF
216
+ NODE_NIL,
217
+ #define NODE_NIL NODE_NIL
218
+ NODE_TRUE,
219
+ #define NODE_TRUE NODE_TRUE
220
+ NODE_FALSE,
221
+ #define NODE_FALSE NODE_FALSE
222
+ NODE_ERRINFO,
223
+ #define NODE_ERRINFO NODE_ERRINFO
224
+ NODE_DEFINED,
225
+ #define NODE_DEFINED NODE_DEFINED
226
+ NODE_POSTEXE,
227
+ #define NODE_POSTEXE NODE_POSTEXE
228
+ NODE_ALLOCA,
229
+ #define NODE_ALLOCA NODE_ALLOCA
230
+ NODE_BMETHOD,
231
+ #define NODE_BMETHOD NODE_BMETHOD
232
+ NODE_MEMO,
233
+ #define NODE_MEMO NODE_MEMO
234
+ NODE_IFUNC,
235
+ #define NODE_IFUNC NODE_IFUNC
236
+ NODE_DSYM,
237
+ #define NODE_DSYM NODE_DSYM
238
+ NODE_ATTRASGN,
239
+ #define NODE_ATTRASGN NODE_ATTRASGN
240
+ NODE_PRELUDE,
241
+ #define NODE_PRELUDE NODE_PRELUDE
242
+ NODE_LAMBDA,
243
+ #define NODE_LAMBDA NODE_LAMBDA
244
+ NODE_OPTBLOCK,
245
+ #define NODE_OPTBLOCK NODE_OPTBLOCK
246
+ NODE_LAST
247
+ #define NODE_LAST NODE_LAST
248
+ };
249
+
250
+ #define RUBY_VM_METHOD_NODE NODE_METHOD
251
+
252
+ #else
253
+ #define RUBY_VM_METHOD_NODE 0
254
+ #define NODE_METHOD 0
255
+
256
+ #endif
257
+
258
+
259
+ typedef struct RNode {
260
+ unsigned long flags;
261
+ char *nd_file;
262
+ union {
263
+ struct RNode *node;
264
+ ID id;
265
+ VALUE value;
266
+ VALUE (*cfunc)(ANYARGS);
267
+ ID *tbl;
268
+ } u1;
269
+ union {
270
+ struct RNode *node;
271
+ ID id;
272
+ long argc;
273
+ VALUE value;
274
+ } u2;
275
+ union {
276
+ struct RNode *node;
277
+ ID id;
278
+ long state;
279
+ struct global_entry *entry;
280
+ long cnt;
281
+ VALUE value;
282
+ } u3;
283
+ } NODE;
284
+
285
+ #define RNODE(obj) (R_CAST(RNode)(obj))
286
+
287
+ #define NODE_TYPESHIFT 8
288
+ #define NODE_TYPEMASK (((VALUE)0x7f)<<NODE_TYPESHIFT)
289
+
290
+ #define nd_body u2.node
291
+ #define nd_type(n) ((int) (((RNODE(n))->flags & NODE_TYPEMASK)>>NODE_TYPESHIFT))
292
+ #define nd_clss u1.value
293
+
294
+ #endif