rallhook 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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