nodewrap 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (236) hide show
  1. data/COPYING +59 -0
  2. data/LEGAL +6 -0
  3. data/LGPL +515 -0
  4. data/LICENSE +6 -0
  5. data/README +31 -0
  6. data/TODO +9 -0
  7. data/example/README +5 -0
  8. data/example/simple_client.rb +12 -0
  9. data/example/simple_server.rb +11 -0
  10. data/example/triangle_client.rb +7 -0
  11. data/example/triangle_server.rb +24 -0
  12. data/ext/MANIFEST +11 -0
  13. data/ext/builtins.h +25 -0
  14. data/ext/cached/ruby-1.6.3/COPYING +340 -0
  15. data/ext/cached/ruby-1.6.3/README +3 -0
  16. data/ext/cached/ruby-1.6.3/classpath.c +3 -0
  17. data/ext/cached/ruby-1.6.3/classpath.h +8 -0
  18. data/ext/cached/ruby-1.6.3/evalinfo.h +62 -0
  19. data/ext/cached/ruby-1.6.3/global_entry.h +15 -0
  20. data/ext/cached/ruby-1.6.3/insns_info.c +40 -0
  21. data/ext/cached/ruby-1.6.3/insns_info.h +19 -0
  22. data/ext/cached/ruby-1.6.3/node_type_descrip.c +150 -0
  23. data/ext/cached/ruby-1.6.3/nodeinfo.c +3182 -0
  24. data/ext/cached/ruby-1.6.3/nodeinfo.h +66 -0
  25. data/ext/cached/ruby-1.6.4/COPYING +340 -0
  26. data/ext/cached/ruby-1.6.4/README +3 -0
  27. data/ext/cached/ruby-1.6.4/classpath.c +3 -0
  28. data/ext/cached/ruby-1.6.4/classpath.h +8 -0
  29. data/ext/cached/ruby-1.6.4/evalinfo.h +62 -0
  30. data/ext/cached/ruby-1.6.4/global_entry.h +15 -0
  31. data/ext/cached/ruby-1.6.4/insns_info.c +40 -0
  32. data/ext/cached/ruby-1.6.4/insns_info.h +19 -0
  33. data/ext/cached/ruby-1.6.4/node_type_descrip.c +150 -0
  34. data/ext/cached/ruby-1.6.4/nodeinfo.c +3182 -0
  35. data/ext/cached/ruby-1.6.4/nodeinfo.h +66 -0
  36. data/ext/cached/ruby-1.6.5/COPYING +56 -0
  37. data/ext/cached/ruby-1.6.5/GPL +340 -0
  38. data/ext/cached/ruby-1.6.5/LEGAL +325 -0
  39. data/ext/cached/ruby-1.6.5/LGPL +504 -0
  40. data/ext/cached/ruby-1.6.5/README +3 -0
  41. data/ext/cached/ruby-1.6.5/classpath.c +3 -0
  42. data/ext/cached/ruby-1.6.5/classpath.h +8 -0
  43. data/ext/cached/ruby-1.6.5/evalinfo.h +63 -0
  44. data/ext/cached/ruby-1.6.5/global_entry.h +15 -0
  45. data/ext/cached/ruby-1.6.5/insns_info.c +40 -0
  46. data/ext/cached/ruby-1.6.5/insns_info.h +19 -0
  47. data/ext/cached/ruby-1.6.5/node_type_descrip.c +150 -0
  48. data/ext/cached/ruby-1.6.5/nodeinfo.c +3182 -0
  49. data/ext/cached/ruby-1.6.5/nodeinfo.h +66 -0
  50. data/ext/cached/ruby-1.6.7/COPYING +56 -0
  51. data/ext/cached/ruby-1.6.7/GPL +340 -0
  52. data/ext/cached/ruby-1.6.7/LEGAL +308 -0
  53. data/ext/cached/ruby-1.6.7/LGPL +504 -0
  54. data/ext/cached/ruby-1.6.7/README +3 -0
  55. data/ext/cached/ruby-1.6.7/classpath.c +3 -0
  56. data/ext/cached/ruby-1.6.7/classpath.h +8 -0
  57. data/ext/cached/ruby-1.6.7/evalinfo.h +63 -0
  58. data/ext/cached/ruby-1.6.7/global_entry.h +15 -0
  59. data/ext/cached/ruby-1.6.7/insns_info.c +40 -0
  60. data/ext/cached/ruby-1.6.7/insns_info.h +19 -0
  61. data/ext/cached/ruby-1.6.7/node_type_descrip.c +150 -0
  62. data/ext/cached/ruby-1.6.7/nodeinfo.c +3182 -0
  63. data/ext/cached/ruby-1.6.7/nodeinfo.h +66 -0
  64. data/ext/cached/ruby-1.6.8/COPYING +56 -0
  65. data/ext/cached/ruby-1.6.8/GPL +340 -0
  66. data/ext/cached/ruby-1.6.8/LEGAL +308 -0
  67. data/ext/cached/ruby-1.6.8/LGPL +504 -0
  68. data/ext/cached/ruby-1.6.8/README +3 -0
  69. data/ext/cached/ruby-1.6.8/classpath.c +3 -0
  70. data/ext/cached/ruby-1.6.8/classpath.h +8 -0
  71. data/ext/cached/ruby-1.6.8/evalinfo.h +63 -0
  72. data/ext/cached/ruby-1.6.8/global_entry.h +15 -0
  73. data/ext/cached/ruby-1.6.8/insns_info.c +40 -0
  74. data/ext/cached/ruby-1.6.8/insns_info.h +19 -0
  75. data/ext/cached/ruby-1.6.8/node_type_descrip.c +150 -0
  76. data/ext/cached/ruby-1.6.8/nodeinfo.c +3182 -0
  77. data/ext/cached/ruby-1.6.8/nodeinfo.h +66 -0
  78. data/ext/cached/ruby-1.8.0/COPYING +56 -0
  79. data/ext/cached/ruby-1.8.0/GPL +340 -0
  80. data/ext/cached/ruby-1.8.0/LEGAL +371 -0
  81. data/ext/cached/ruby-1.8.0/LGPL +504 -0
  82. data/ext/cached/ruby-1.8.0/README +3 -0
  83. data/ext/cached/ruby-1.8.0/classpath.c +27 -0
  84. data/ext/cached/ruby-1.8.0/classpath.h +14 -0
  85. data/ext/cached/ruby-1.8.0/evalinfo.h +65 -0
  86. data/ext/cached/ruby-1.8.0/global_entry.h +10 -0
  87. data/ext/cached/ruby-1.8.0/insns_info.c +40 -0
  88. data/ext/cached/ruby-1.8.0/insns_info.h +19 -0
  89. data/ext/cached/ruby-1.8.0/node_type_descrip.c +150 -0
  90. data/ext/cached/ruby-1.8.0/nodeinfo.c +3199 -0
  91. data/ext/cached/ruby-1.8.0/nodeinfo.h +66 -0
  92. data/ext/cached/ruby-1.8.1/COPYING +56 -0
  93. data/ext/cached/ruby-1.8.1/GPL +340 -0
  94. data/ext/cached/ruby-1.8.1/LEGAL +371 -0
  95. data/ext/cached/ruby-1.8.1/LGPL +504 -0
  96. data/ext/cached/ruby-1.8.1/README +3 -0
  97. data/ext/cached/ruby-1.8.1/classpath.c +27 -0
  98. data/ext/cached/ruby-1.8.1/classpath.h +14 -0
  99. data/ext/cached/ruby-1.8.1/evalinfo.h +59 -0
  100. data/ext/cached/ruby-1.8.1/global_entry.h +10 -0
  101. data/ext/cached/ruby-1.8.1/insns_info.c +40 -0
  102. data/ext/cached/ruby-1.8.1/insns_info.h +19 -0
  103. data/ext/cached/ruby-1.8.1/node_type_descrip.c +150 -0
  104. data/ext/cached/ruby-1.8.1/nodeinfo.c +3199 -0
  105. data/ext/cached/ruby-1.8.1/nodeinfo.h +66 -0
  106. data/ext/cached/ruby-1.8.2/COPYING +56 -0
  107. data/ext/cached/ruby-1.8.2/GPL +340 -0
  108. data/ext/cached/ruby-1.8.2/LEGAL +371 -0
  109. data/ext/cached/ruby-1.8.2/LGPL +504 -0
  110. data/ext/cached/ruby-1.8.2/README +3 -0
  111. data/ext/cached/ruby-1.8.2/classpath.c +45 -0
  112. data/ext/cached/ruby-1.8.2/classpath.h +17 -0
  113. data/ext/cached/ruby-1.8.2/evalinfo.h +60 -0
  114. data/ext/cached/ruby-1.8.2/global_entry.h +10 -0
  115. data/ext/cached/ruby-1.8.2/insns_info.c +40 -0
  116. data/ext/cached/ruby-1.8.2/insns_info.h +19 -0
  117. data/ext/cached/ruby-1.8.2/node_type_descrip.c +150 -0
  118. data/ext/cached/ruby-1.8.2/nodeinfo.c +3199 -0
  119. data/ext/cached/ruby-1.8.2/nodeinfo.h +66 -0
  120. data/ext/cached/ruby-1.8.3/COPYING +56 -0
  121. data/ext/cached/ruby-1.8.3/GPL +340 -0
  122. data/ext/cached/ruby-1.8.3/LEGAL +370 -0
  123. data/ext/cached/ruby-1.8.3/LGPL +504 -0
  124. data/ext/cached/ruby-1.8.3/README +3 -0
  125. data/ext/cached/ruby-1.8.3/classpath.c +45 -0
  126. data/ext/cached/ruby-1.8.3/classpath.h +17 -0
  127. data/ext/cached/ruby-1.8.3/evalinfo.h +61 -0
  128. data/ext/cached/ruby-1.8.3/global_entry.h +10 -0
  129. data/ext/cached/ruby-1.8.3/insns_info.c +40 -0
  130. data/ext/cached/ruby-1.8.3/insns_info.h +19 -0
  131. data/ext/cached/ruby-1.8.3/node_type_descrip.c +150 -0
  132. data/ext/cached/ruby-1.8.3/nodeinfo.c +3199 -0
  133. data/ext/cached/ruby-1.8.3/nodeinfo.h +66 -0
  134. data/ext/cached/ruby-1.8.4/COPYING +56 -0
  135. data/ext/cached/ruby-1.8.4/GPL +340 -0
  136. data/ext/cached/ruby-1.8.4/LEGAL +370 -0
  137. data/ext/cached/ruby-1.8.4/LGPL +504 -0
  138. data/ext/cached/ruby-1.8.4/README +3 -0
  139. data/ext/cached/ruby-1.8.4/classpath.c +45 -0
  140. data/ext/cached/ruby-1.8.4/classpath.h +17 -0
  141. data/ext/cached/ruby-1.8.4/evalinfo.h +61 -0
  142. data/ext/cached/ruby-1.8.4/global_entry.h +10 -0
  143. data/ext/cached/ruby-1.8.4/insns_info.c +40 -0
  144. data/ext/cached/ruby-1.8.4/insns_info.h +19 -0
  145. data/ext/cached/ruby-1.8.4/node_type_descrip.c +150 -0
  146. data/ext/cached/ruby-1.8.4/nodeinfo.c +3199 -0
  147. data/ext/cached/ruby-1.8.4/nodeinfo.h +66 -0
  148. data/ext/cached/ruby-1.8.5/COPYING +56 -0
  149. data/ext/cached/ruby-1.8.5/GPL +340 -0
  150. data/ext/cached/ruby-1.8.5/LEGAL +370 -0
  151. data/ext/cached/ruby-1.8.5/LGPL +504 -0
  152. data/ext/cached/ruby-1.8.5/README +3 -0
  153. data/ext/cached/ruby-1.8.5/classpath.c +45 -0
  154. data/ext/cached/ruby-1.8.5/classpath.h +17 -0
  155. data/ext/cached/ruby-1.8.5/evalinfo.h +61 -0
  156. data/ext/cached/ruby-1.8.5/global_entry.h +10 -0
  157. data/ext/cached/ruby-1.8.5/insns_info.c +40 -0
  158. data/ext/cached/ruby-1.8.5/insns_info.h +19 -0
  159. data/ext/cached/ruby-1.8.5/node_type_descrip.c +150 -0
  160. data/ext/cached/ruby-1.8.5/nodeinfo.c +3187 -0
  161. data/ext/cached/ruby-1.8.5/nodeinfo.h +64 -0
  162. data/ext/cached/ruby-1.8.6/COPYING +56 -0
  163. data/ext/cached/ruby-1.8.6/GPL +340 -0
  164. data/ext/cached/ruby-1.8.6/LEGAL +370 -0
  165. data/ext/cached/ruby-1.8.6/LGPL +504 -0
  166. data/ext/cached/ruby-1.8.6/README +3 -0
  167. data/ext/cached/ruby-1.8.6/classpath.c +45 -0
  168. data/ext/cached/ruby-1.8.6/classpath.h +17 -0
  169. data/ext/cached/ruby-1.8.6/evalinfo.h +61 -0
  170. data/ext/cached/ruby-1.8.6/global_entry.h +10 -0
  171. data/ext/cached/ruby-1.8.6/insns_info.c +40 -0
  172. data/ext/cached/ruby-1.8.6/insns_info.h +19 -0
  173. data/ext/cached/ruby-1.8.6/node_type_descrip.c +150 -0
  174. data/ext/cached/ruby-1.8.6/nodeinfo.c +3187 -0
  175. data/ext/cached/ruby-1.8.6/nodeinfo.h +64 -0
  176. data/ext/classpath.c +42 -0
  177. data/ext/classpath.c.rpp +28 -0
  178. data/ext/classpath.h +17 -0
  179. data/ext/classpath.h.rpp +35 -0
  180. data/ext/evalinfo.h +21 -0
  181. data/ext/evalinfo.h.rpp +49 -0
  182. data/ext/extconf.rb +68 -0
  183. data/ext/generate.rb +201 -0
  184. data/ext/generate_cached.rb +49 -0
  185. data/ext/global_entry.h +10 -0
  186. data/ext/global_entry.h.rpp +25 -0
  187. data/ext/insns_info.c +6079 -0
  188. data/ext/insns_info.c.rpp +210 -0
  189. data/ext/insns_info.h +819 -0
  190. data/ext/insns_info.h.rpp +50 -0
  191. data/ext/node_type_descrip.c +148 -0
  192. data/ext/node_type_descrip.c.rpp +72 -0
  193. data/ext/node_type_descrip.h +17 -0
  194. data/ext/node_type_descrip.rb +169 -0
  195. data/ext/nodeinfo.c +3164 -0
  196. data/ext/nodeinfo.c.rpp +519 -0
  197. data/ext/nodeinfo.h +67 -0
  198. data/ext/nodeinfo.h.rpp +27 -0
  199. data/ext/nodewrap.c +2576 -0
  200. data/ext/nodewrap.h +20 -0
  201. data/ext/read_node_h.rb +19 -0
  202. data/ext/ruby_source_dir.rb +15 -0
  203. data/ext/ruby_version.h +12 -0
  204. data/ext/ruby_version_code.rb +16 -0
  205. data/ext/rubypp.rb +97 -0
  206. data/ext/test.rb +15 -0
  207. data/generate_rdoc.rb +33 -0
  208. data/install.rb +1022 -0
  209. data/lib/as_code.rb +347 -0
  210. data/lib/as_expression.rb +657 -0
  211. data/lib/bytedecoder.rb +848 -0
  212. data/lib/classtree.rb +54 -0
  213. data/lib/methodsig.rb +266 -0
  214. data/lib/node_to_a.rb +34 -0
  215. data/lib/nodepp.rb +71 -0
  216. data/lib/nwdebug.rb +18 -0
  217. data/lib/nwdump.rb +53 -0
  218. data/lib/nwobfusc.rb +57 -0
  219. data/lib/procsig.rb +182 -0
  220. data/lib/test.rb +8 -0
  221. data/metaconfig +10 -0
  222. data/post-config.rb +53 -0
  223. data/post-setup.rb +9 -0
  224. data/pre-config.rb +1 -0
  225. data/run_tests.rb +48 -0
  226. data/test/expression_samples.rb +158 -0
  227. data/test/node_samples.rb +122 -0
  228. data/test/test.rb +39 -0
  229. data/test/test2.rb +7 -0
  230. data/test/test3.rb +5 -0
  231. data/test/test4.rb +5 -0
  232. data/test/test_as_code.rb +249 -0
  233. data/test/test_as_expression.rb +222 -0
  234. data/test/test_methodsig.rb +189 -0
  235. data/test/test_nodewrap.rb +369 -0
  236. metadata +286 -0
@@ -0,0 +1,67 @@
1
+ #ifndef nodeinfo_h
2
+ #define nodeinfo_h
3
+
4
+ #include "ruby.h"
5
+ #include "node.h"
6
+ #include "nodewrap.h"
7
+
8
+ enum Node_Elem_Name
9
+ {
10
+ NEN_NONE,
11
+ NEN_1ST,
12
+ NEN_2ND,
13
+ NEN_AID,
14
+ NEN_ALEN,
15
+ NEN_ARGC,
16
+ NEN_ARGS,
17
+ NEN_BEG,
18
+ NEN_BODY,
19
+ NEN_CFLAG,
20
+ NEN_CFNC,
21
+ NEN_CLSS,
22
+ NEN_CNT,
23
+ NEN_COND,
24
+ NEN_CPATH,
25
+ NEN_CVAL,
26
+ NEN_DEFN,
27
+ NEN_ELSE,
28
+ NEN_END,
29
+ NEN_ENSR,
30
+ NEN_ENTRY,
31
+ NEN_FRML,
32
+ NEN_HEAD,
33
+ NEN_ITER,
34
+ NEN_LIT,
35
+ NEN_MID,
36
+ NEN_MODL,
37
+ NEN_NEXT,
38
+ NEN_NOEX,
39
+ NEN_NTH,
40
+ NEN_OID,
41
+ NEN_OPT,
42
+ NEN_ORIG,
43
+ NEN_PID,
44
+ NEN_PLEN,
45
+ NEN_RECV,
46
+ NEN_RESQ,
47
+ NEN_REST,
48
+ NEN_RVAL,
49
+ NEN_STATE,
50
+ NEN_STTS,
51
+ NEN_SUPER,
52
+ NEN_TAG,
53
+ NEN_TBL,
54
+ NEN_TVAL,
55
+ NEN_VALUE,
56
+ NEN_VAR,
57
+ NEN_VID,
58
+ NEN_VISI,
59
+ };
60
+
61
+ VALUE dump_node_elem(enum Node_Elem_Name nen, NODE * n, VALUE node_hash);
62
+ void load_node_elem(enum Node_Elem_Name nen, VALUE v, NODE * n, VALUE node_hash, VALUE id_hash);
63
+ VALUE node_s_members(VALUE klass);
64
+ void define_node_subclass_methods();
65
+
66
+ #endif
67
+
@@ -0,0 +1,27 @@
1
+ #ifndef nodeinfo_h
2
+ #define nodeinfo_h
3
+
4
+ #include "ruby.h"
5
+ #include "node.h"
6
+ #include "nodewrap.h"
7
+
8
+ enum Node_Elem_Name
9
+ {
10
+ NEN_NONE,
11
+ #ruby <<END
12
+ require 'read_node_h.rb'
13
+
14
+ NODEINFO.sort.each do |node_elem_name, node_elem_ref|
15
+ puts " NEN_#{node_elem_name.upcase},"
16
+ end
17
+ nil
18
+ END
19
+ };
20
+
21
+ VALUE dump_node_elem(enum Node_Elem_Name nen, NODE * n, VALUE node_hash);
22
+ void load_node_elem(enum Node_Elem_Name nen, VALUE v, NODE * n, VALUE node_hash, VALUE id_hash);
23
+ VALUE node_s_members(VALUE klass);
24
+ void define_node_subclass_methods();
25
+
26
+ #endif
27
+
@@ -0,0 +1,2576 @@
1
+ #include "nodeinfo.h"
2
+ #include "evalinfo.h"
3
+ #include "nodewrap.h"
4
+ #include "node_type_descrip.h"
5
+ #include "builtins.h"
6
+ #include "insns_info.h"
7
+
8
+ #include "ruby.h"
9
+ #include "version.h"
10
+ #include "rubysig.h"
11
+ #include "node.h"
12
+ #include "st.h"
13
+
14
+ #include <ctype.h>
15
+
16
+ static VALUE rb_mNodewrap = Qnil;
17
+
18
+ #ifdef RUBY_HAS_YARV
19
+ #include "eval_intern.h"
20
+ #define ruby_safe_level rb_safe_level()
21
+ VALUE iseq_data_to_ary(rb_iseq_t * iseq);
22
+ VALUE iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt);
23
+ static VALUE rb_cInstruction = Qnil;
24
+ static VALUE rb_cModulePlaceholder = Qnil;
25
+ static VALUE rb_cInlineCache = Qnil;
26
+ #endif
27
+
28
+ static VALUE rb_cNode = Qnil;
29
+ static VALUE rb_cNodeType = Qnil;
30
+ VALUE rb_cNodeSubclass[NODE_LAST];
31
+ static VALUE rb_cUnboundProc = Qnil;
32
+ static VALUE rb_mMarshal = Qnil;
33
+
34
+ #if RUBY_VERSION_CODE < 185
35
+ static VALUE rb_cMethod = Qnil;
36
+ static VALUE rb_cUnboundMethod = Qnil;
37
+ #endif
38
+
39
+ #if RUBY_VERSION_CODE >= 180
40
+ struct Class_Restorer
41
+ {
42
+ VALUE klass;
43
+ struct st_table m_tbl;
44
+ struct st_table iv_tbl;
45
+ #ifndef RUBY_HAS_YARV
46
+ int thread_critical;
47
+ #endif
48
+ };
49
+
50
+ static VALUE rb_cClass_Restorer = Qnil;
51
+
52
+ static void mark_class_restorer(struct Class_Restorer * class_restorer);
53
+ #endif
54
+
55
+ #if RUBY_VERSION_CODE < 170
56
+ typedef void st_data_t;
57
+ #endif
58
+
59
+ static VALUE wrapped_nodes = Qnil;
60
+
61
+ /* ---------------------------------------------------------------------
62
+ * Node helper functions
63
+ * ---------------------------------------------------------------------
64
+ */
65
+
66
+ static void wrapped_nodes_end_proc(VALUE data)
67
+ {
68
+ wrapped_nodes = Qnil;
69
+ }
70
+
71
+ static void mark_node(
72
+ void * data)
73
+ {
74
+ rb_gc_mark((VALUE)data);
75
+ }
76
+
77
+ static void free_node(
78
+ void * data)
79
+ {
80
+ VALUE key, node_id;
81
+
82
+ if(wrapped_nodes == Qnil)
83
+ {
84
+ /* We're finalizing at exit, so don't clean up */
85
+ return;
86
+ }
87
+
88
+ key = LONG2FIX((long)data / 4);
89
+ node_id = rb_hash_aref(wrapped_nodes, key);
90
+
91
+ if(NIL_P(node_id))
92
+ {
93
+ rb_bug("tried to free a node that wasn't wrapped!");
94
+ return;
95
+ }
96
+ rb_funcall(wrapped_nodes, rb_intern("delete"), 1, LONG2NUM((long)data / 4));
97
+ }
98
+
99
+ VALUE wrap_node_as(NODE * n, VALUE klass)
100
+ {
101
+ VALUE node_id;
102
+
103
+ if(!n)
104
+ {
105
+ return Qnil;
106
+ }
107
+
108
+ if(wrapped_nodes == Qnil)
109
+ {
110
+ /* We're finalizing at exit so we can't function properly */
111
+ rb_raise(rb_eRuntimeError, "Unable to wrap node during cleanup");
112
+ }
113
+
114
+ node_id = rb_hash_aref(wrapped_nodes, LONG2FIX((long)n / 4));
115
+
116
+ if(!NIL_P(node_id))
117
+ {
118
+ return (VALUE)(node_id ^ FIXNUM_FLAG);
119
+ }
120
+ else
121
+ {
122
+ VALUE node = Data_Wrap_Struct(klass, mark_node, free_node, n);
123
+ VALUE node_id = rb_obj_id(node);
124
+ rb_hash_aset(wrapped_nodes, LONG2FIX((long)n / 4), node_id);
125
+ return node;
126
+ }
127
+ }
128
+
129
+ VALUE wrap_node(NODE * n)
130
+ {
131
+ if(!n)
132
+ {
133
+ return Qnil;
134
+ }
135
+
136
+ return wrap_node_as(n, rb_cNodeSubclass[nd_type(n)]);
137
+ }
138
+
139
+ NODE * unwrap_node(VALUE r)
140
+ {
141
+ if(!RTEST(r))
142
+ {
143
+ return 0;
144
+ }
145
+ else
146
+ {
147
+ NODE * n;
148
+ if(TYPE(r) == 0)
149
+ {
150
+ rb_bug("Tried to unwrap recycled node");
151
+ }
152
+ if(!rb_obj_is_kind_of(r, rb_cNode))
153
+ {
154
+ rb_raise(rb_eTypeError, "Expected Node");
155
+ }
156
+ Data_Get_Struct(r, NODE, n);
157
+ return n;
158
+ }
159
+ }
160
+
161
+ /* ---------------------------------------------------------------------
162
+ * Instruction sequence helper functions
163
+ * ---------------------------------------------------------------------
164
+ */
165
+
166
+ #ifdef RUBY_HAS_YARV
167
+ /* From iseq.c */
168
+ static rb_iseq_t *
169
+ iseq_check(VALUE val)
170
+ {
171
+ rb_iseq_t *iseq;
172
+ if(!rb_obj_is_kind_of(val, rb_cISeq))
173
+ {
174
+ rb_raise(
175
+ rb_eTypeError,
176
+ "Expected VM::InstructionSequence, but got %s",
177
+ rb_class2name(CLASS_OF(val)));
178
+ }
179
+ GetISeqPtr(val, iseq);
180
+ if (!iseq->name) {
181
+ rb_raise(rb_eTypeError, "uninitialized InstructionSequence");
182
+ }
183
+ return iseq;
184
+ }
185
+ #endif
186
+
187
+ /* ---------------------------------------------------------------------
188
+ * Marshalling
189
+ * ---------------------------------------------------------------------
190
+ */
191
+
192
+ VALUE marshal_dump(VALUE obj, VALUE limit)
193
+ {
194
+ return rb_funcall(rb_mMarshal, rb_intern("dump"), 2, obj, limit);
195
+ }
196
+
197
+ VALUE marshal_load(VALUE obj)
198
+ {
199
+ return rb_funcall(rb_mMarshal, rb_intern("load"), 1, obj);
200
+ }
201
+
202
+ /* ---------------------------------------------------------------------
203
+ * Constant lookup
204
+ * ---------------------------------------------------------------------
205
+ */
206
+
207
+ /* This differs from rb_class2path in that it handles the case of
208
+ * <Singleton>.
209
+ */
210
+
211
+ static char const * lookup_module_str =
212
+ "proc { |name|\n"
213
+ " o = Object\n"
214
+ " name.to_s.split('::').each do |subname|\n"
215
+ " if subname == '<Singleton>' then\n"
216
+ " o = o.singleton_class\n"
217
+ " else\n"
218
+ " o = o.const_get(subname)\n"
219
+ " end\n"
220
+ " end\n"
221
+ " o\n"
222
+ "}\n";
223
+ static VALUE lookup_module_proc = Qnil;
224
+
225
+ static char const * outer_module_str =
226
+ "proc { |name|\n"
227
+ " o = Object\n"
228
+ " names = name.to_s.split('::')\n"
229
+ " names.pop\n"
230
+ " names.each do |subname|\n"
231
+ " if subname == '<Singleton>' then\n"
232
+ " o = o.singleton_class\n"
233
+ " else\n"
234
+ " o = o.const_get(subname)\n"
235
+ " end\n"
236
+ " end\n"
237
+ " o\n"
238
+ "}\n";
239
+
240
+ static VALUE outer_module_proc = Qnil;
241
+
242
+ static char const * module_name_str =
243
+ "proc { |name|\n"
244
+ " names = name.to_s.split('::')\n"
245
+ " names[-1].intern\n"
246
+ "}\n";
247
+
248
+ static VALUE module_name_proc = Qnil;
249
+
250
+ /* ---------------------------------------------------------------------
251
+ * Node methods
252
+ * ---------------------------------------------------------------------
253
+ */
254
+
255
+ /*
256
+ * Document-class: Node
257
+ *
258
+ * Node is a wrapper for Ruby's Nodes, which are not objects. Nodes
259
+ * can be obtained from many of the other methods in the nodewrap
260
+ * library (see Method#body and Proc#body, for example).
261
+ */
262
+
263
+ #if RUBY_VERSION_CODE >= 180
264
+ /*
265
+ * call-seq:
266
+ * Node.allocate() => Node
267
+ *
268
+ * Allocate a new node.
269
+ */
270
+ static VALUE node_allocate(VALUE klass)
271
+ {
272
+ NODE * n = NEW_NIL();
273
+ return wrap_node(n);
274
+ }
275
+ #endif
276
+
277
+ /*
278
+ * call-seq:
279
+ * node.address() => Numeric
280
+ *
281
+ * Returns a node's address.
282
+ */
283
+ static VALUE node_address(VALUE self)
284
+ {
285
+ NODE * n;
286
+ Data_Get_Struct(self, NODE, n);
287
+ return ULONG2NUM((unsigned long)(n));
288
+ }
289
+
290
+ /*
291
+ * call-seq:
292
+ * node.flags() => Numeric
293
+ *
294
+ * Returns a node's flags.
295
+ */
296
+ static VALUE node_flags(VALUE self)
297
+ {
298
+ NODE * n;
299
+ Data_Get_Struct(self, NODE, n);
300
+ return INT2NUM(n->flags);
301
+ }
302
+
303
+ /*
304
+ * call-seq:
305
+ * node.nd_file => String or nil
306
+ *
307
+ * Returns the file the node is associated with
308
+ */
309
+ static VALUE node_nd_file(VALUE self)
310
+ {
311
+ NODE * n;
312
+ Data_Get_Struct(self, NODE, n);
313
+ if(n->nd_file)
314
+ {
315
+ return rb_str_new2(n->nd_file);
316
+ }
317
+ else
318
+ {
319
+ return Qnil;
320
+ }
321
+ }
322
+
323
+ /*
324
+ * call-seq:
325
+ * node.nd_line => Numeric
326
+ *
327
+ * Returns the line number the node is associated with.
328
+ */
329
+ static VALUE node_nd_line(VALUE self)
330
+ {
331
+ NODE * n;
332
+ Data_Get_Struct(self, NODE, n);
333
+ return LONG2NUM(nd_line(n));
334
+ }
335
+
336
+ /*
337
+ * call-seq:
338
+ * node.nd_type => NodeType
339
+ *
340
+ * Returns a NodeType structure representing the type of the node.
341
+ */
342
+ static VALUE node_nd_type(VALUE self)
343
+ {
344
+ NODE * n;
345
+ const Node_Type_Descrip * descrip;
346
+ Data_Get_Struct(self, NODE, n);
347
+ rb_check_type((VALUE)(self), T_DATA);
348
+ descrip = node_type_descrip(nd_type(n));
349
+ return rb_struct_new(
350
+ rb_cNodeType,
351
+ rb_str_new2(descrip->name),
352
+ INT2NUM(descrip->nt));
353
+ }
354
+
355
+ VALUE node_id(NODE * n)
356
+ {
357
+ return rb_obj_id((VALUE)n);
358
+ }
359
+
360
+ NODE * id_to_node(VALUE id)
361
+ {
362
+ unsigned long n = NUM2INT(id);
363
+ return (NODE *)n;
364
+ }
365
+
366
+ /*
367
+ * call-seq:
368
+ * node.members => Array of String
369
+ *
370
+ * Return an array of strings containing the names of a node's
371
+ * members.
372
+ */
373
+ static VALUE node_members(VALUE node)
374
+ {
375
+ return node_s_members(rb_class_of(node));
376
+ }
377
+
378
+ /*
379
+ * call-seq:
380
+ * node[member] => Object
381
+ *
382
+ * Return the given member of a node.
383
+ */
384
+ static VALUE node_bracket(VALUE node, VALUE member)
385
+ {
386
+ ID id = SYMBOL_P(member)
387
+ ? SYM2ID(member)
388
+ : rb_intern(STR2CSTR(member));
389
+ return rb_funcall(node, id, 0);
390
+ }
391
+
392
+ #if RUBY_VERSION_CODE < 190
393
+ static VALUE node_inspect_protect(VALUE node)
394
+ #else
395
+ static VALUE node_inspect_protect(VALUE node, VALUE dummy, int recur)
396
+ #endif
397
+ {
398
+ VALUE str = rb_str_new2("#<");
399
+ rb_str_cat2(str, rb_class2name(CLASS_OF(node)));
400
+ rb_str_cat2(str, " ");
401
+ VALUE members = node_members(node);
402
+ int j;
403
+
404
+
405
+ for(j = 0; j < RARRAY(members)->len; ++j)
406
+ {
407
+ VALUE name = RARRAY(members)->ptr[j];
408
+ VALUE value = node_bracket(node, name);
409
+ rb_str_append(str, name);
410
+ rb_str_cat2(str, "=");
411
+ if(TYPE(value) == T_NODE)
412
+ {
413
+ rb_str_append(str, rb_funcall(value, rb_intern("to_s"), 0));
414
+ }
415
+ else
416
+ {
417
+ rb_str_append(str, rb_funcall(value, rb_intern("inspect"), 0));
418
+ }
419
+ if(j != RARRAY(members)->len - 1)
420
+ {
421
+ rb_str_cat2(str, ", ");
422
+ }
423
+ }
424
+
425
+ rb_str_cat2(str, ">");
426
+
427
+ return str;
428
+ }
429
+
430
+ /*
431
+ * call-seq:
432
+ * node.inspect => String
433
+ *
434
+ * Returns a string representation of the node's data.
435
+ */
436
+ static VALUE node_inspect(VALUE node)
437
+ {
438
+ #if RUBY_VERSION_CODE < 190
439
+ if(rb_inspecting_p(node))
440
+ {
441
+ VALUE str = rb_str_new2("#<");
442
+ rb_str_cat2(str, rb_class2name(CLASS_OF(node)));
443
+ rb_str_cat2(str, ":...>");
444
+ return str;
445
+ }
446
+ else
447
+ {
448
+ return rb_protect_inspect(node_inspect_protect, node, 0);
449
+ }
450
+ #else
451
+ return rb_exec_recursive(node_inspect_protect, node, 0);
452
+ #endif
453
+ }
454
+
455
+ /* ---------------------------------------------------------------------
456
+ * NodeType methods
457
+ * ---------------------------------------------------------------------
458
+ */
459
+
460
+ /*
461
+ * Document-class: NodeType
462
+ *
463
+ * NodeType is an abstraction for the C type of a node. It is a Struct
464
+ * which has two members, +name+ and +value+.
465
+ */
466
+
467
+ /*
468
+ * call-seq:
469
+ * node_type.name => String
470
+ *
471
+ * Returns the name of the node.
472
+ */
473
+ static VALUE node_type_to_s(VALUE node_type)
474
+ {
475
+ return rb_struct_getmember(node_type, rb_intern("name"));
476
+ }
477
+
478
+ /*
479
+ * call-seq:
480
+ * node_type.to_i => Numeric
481
+ *
482
+ * Returns an integer representing integer type of a node. This is the
483
+ * value you would see for the type of the node if you were examining it
484
+ * in gdb.
485
+ */
486
+ static VALUE node_type_to_i(VALUE node_type)
487
+ {
488
+ return rb_struct_getmember(node_type, rb_intern("value"));
489
+ }
490
+
491
+ /* ---------------------------------------------------------------------
492
+ * Module methods
493
+ * ---------------------------------------------------------------------
494
+ */
495
+
496
+ #ifdef RUBY_HAS_YARV
497
+
498
+ static void set_cref_stack(rb_iseq_t * iseqdat, VALUE klass, VALUE noex)
499
+ {
500
+ rb_thread_t * th = GET_THREAD();
501
+ rb_control_frame_t * cfp = th_get_ruby_level_cfp(th, th->cfp);
502
+ iseqdat->cref_stack = NEW_BLOCK(klass);
503
+ iseqdat->cref_stack->nd_visi = noex;
504
+ iseqdat->cref_stack->nd_next = cfp->iseq->cref_stack; /* TODO: use lfp? */
505
+ }
506
+
507
+ #endif
508
+
509
+ /*
510
+ * call-seq:
511
+ * class.add_method(id, node or iseq, noex) #=> nil
512
+ *
513
+ * Adds the method as an instance method to the given class.
514
+ *
515
+ * To add a singleton method to a class, add the method to its singleton
516
+ * class.
517
+ */
518
+ static VALUE module_add_method(VALUE klass, VALUE id, VALUE node, VALUE noex)
519
+ {
520
+ NODE * n = 0;
521
+
522
+ if(ruby_safe_level >= 2)
523
+ {
524
+ /* adding a method with the wrong node type can cause a crash */
525
+ rb_raise(rb_eSecurityError, "Insecure: can't add method");
526
+ }
527
+
528
+ #ifdef RUBY_HAS_YARV
529
+ if(rb_obj_is_kind_of(node, rb_cISeq))
530
+ {
531
+ rb_iseq_t *iseqdat = iseq_check(node);
532
+ /* TODO: any restrictions on what kinds of iseqs we can add here?
533
+ */
534
+ set_cref_stack(iseqdat, klass, noex);
535
+ iseqdat->klass = klass;
536
+ iseqdat->defined_method_id = SYM2ID(id);
537
+ n = NEW_METHOD(iseqdat->self, klass, NUM2INT(noex));
538
+ goto add_node;
539
+ }
540
+ #endif
541
+
542
+ if(!rb_obj_is_kind_of(node, rb_cNode))
543
+ {
544
+ rb_raise(
545
+ rb_eTypeError,
546
+ "Expected Node for 2nd parameter, got %s",
547
+ rb_class2name(CLASS_OF(n)));
548
+ }
549
+
550
+ Data_Get_Struct(node, NODE, n);
551
+
552
+ #ifdef RUBY_HAS_YARV
553
+ if(nd_type(n) != NODE_METHOD)
554
+ {
555
+ rb_raise(
556
+ rb_eTypeError,
557
+ "Expected METHOD node, got %s",
558
+ rb_class2name(CLASS_OF(n)));
559
+ }
560
+
561
+ rb_iseq_t *iseqdat = iseq_check((VALUE)n->nd_body);
562
+ set_cref_stack(iseqdat, klass, noex);
563
+ iseqdat->klass = klass;
564
+ iseqdat->defined_method_id = SYM2ID(id);
565
+ n = NEW_METHOD(iseqdat->self, klass, NUM2INT(noex));
566
+
567
+ add_node:
568
+ #endif
569
+ /* TODO: if noex is NOEX_MODFUNC, add this method as a module function
570
+ * (that is, both as an instance and singleton method)
571
+ */
572
+ rb_add_method(klass, SYM2ID(id), n, NUM2INT(noex));
573
+ return Qnil;
574
+ }
575
+
576
+ /*
577
+ * call-seq:
578
+ * uninclude(module, ...) => self
579
+ *
580
+ * Removes the specified module(s) from the inheritance chain.
581
+ */
582
+ static VALUE module_uninclude(int argc, VALUE * argv, VALUE module)
583
+ {
584
+ int i;
585
+
586
+ for (i = 0; i < argc; i++)
587
+ Check_Type(argv[i], T_MODULE);
588
+ while (argc--) {
589
+ rb_funcall(argv[argc], rb_intern("remove_features"), 1, module);
590
+ rb_funcall(argv[argc], rb_intern("unincluded"), 1, module);
591
+ }
592
+ return module;
593
+ }
594
+
595
+ /*
596
+ * call-seq:
597
+ * remove_features(mod) => mod
598
+ *
599
+ * When this module is unincluded from another, Nodewrap calls
600
+ * remove_features in this module. The default behavior is to remove
601
+ * the constants, methods, and module variables of this module from
602
+ * _mod_. If this module has not been included by _mod_, an exception
603
+ * will be raised.
604
+ */
605
+ static VALUE module_remove_features(VALUE module, VALUE uninclude)
606
+ {
607
+ VALUE prev, mod;
608
+
609
+ if(TYPE(uninclude) != T_CLASS && TYPE(uninclude) != T_MODULE)
610
+ {
611
+ Check_Type(uninclude, T_CLASS);
612
+ }
613
+
614
+ rb_frozen_class_p(uninclude);
615
+ if(!OBJ_TAINTED(uninclude))
616
+ {
617
+ rb_secure(4);
618
+ }
619
+
620
+ OBJ_INFECT(uninclude, module);
621
+
622
+ if(RCLASS(uninclude)->m_tbl == RCLASS(module)->m_tbl)
623
+ {
624
+ rb_raise(rb_eArgError, "Cannot remove module from itself");
625
+ }
626
+
627
+ prev = uninclude;
628
+ mod = RCLASS(uninclude)->super;
629
+
630
+ while(mod)
631
+ {
632
+ if(RCLASS(module)->m_tbl == RCLASS(mod)->m_tbl)
633
+ {
634
+ RCLASS(prev)->super = RCLASS(mod)->super;
635
+ rb_clear_cache();
636
+ return module;
637
+ }
638
+
639
+ if(BUILTIN_TYPE(mod) == T_CLASS)
640
+ {
641
+ break;
642
+ }
643
+
644
+ prev = mod;
645
+ mod = RCLASS(mod)->super;
646
+ }
647
+
648
+ rb_raise(rb_eArgError, "Could not find included module");
649
+ return module;
650
+ }
651
+
652
+ static VALUE module_unincluded(VALUE module, VALUE uninclude)
653
+ {
654
+ return Qnil;
655
+ }
656
+
657
+ /* ---------------------------------------------------------------------
658
+ * Method methods
659
+ * ---------------------------------------------------------------------
660
+ */
661
+
662
+ /*
663
+ * call-seq:
664
+ * method.receiver => Object
665
+ *
666
+ * Given a Method, returns the Object to which it is bound.
667
+ */
668
+ static VALUE method_receiver(VALUE method)
669
+ {
670
+ struct METHOD * m;
671
+ Data_Get_Struct(method, struct METHOD, m);
672
+ return m->recv;
673
+ }
674
+
675
+ /*
676
+ * call-seq:
677
+ * method.method_id => Symbol
678
+ *
679
+ * Given a Method, returns the Symbol of the method it represents. If
680
+ * the method is an alias for another method, returns the Symbol of the
681
+ * new method, not the original. If the method changes name, returns
682
+ * the original name, not the new name.
683
+ */
684
+ static VALUE method_id(VALUE method)
685
+ {
686
+ struct METHOD * m;
687
+ Data_Get_Struct(method, struct METHOD, m);
688
+ return ID2SYM(m->id);
689
+ }
690
+
691
+ /*
692
+ * call-seq:
693
+ * method.method_oid => Symbol
694
+ *
695
+ * Given a Method, returns the Symbol of the method it represents. If
696
+ * the method is an alias for another method, returns the Symbol of the
697
+ * original method, not the alias. If the original method changes name,
698
+ * returns the original name.
699
+ */
700
+ static VALUE method_oid(VALUE method)
701
+ {
702
+ struct METHOD * m;
703
+ Data_Get_Struct(method, struct METHOD, m);
704
+ return ID2SYM(m->oid);
705
+ }
706
+
707
+ /*
708
+ * call-seq:
709
+ * method.origin_class => Class
710
+ *
711
+ * Given a Method, returns the Class in which the method it represents
712
+ * was defined. If the method was defined in a base class and
713
+ * Object#method is called on a derived instance of that base class,
714
+ * this method returns the base class.
715
+ */
716
+ static VALUE method_origin_class(VALUE method)
717
+ {
718
+ struct METHOD * m;
719
+ Data_Get_Struct(method, struct METHOD, m);
720
+ #if RUBY_VERSION_CODE < 180
721
+ return m->oklass;
722
+ #else
723
+ return m->rklass;
724
+ #endif
725
+ }
726
+
727
+ /*
728
+ * call-seq:
729
+ * method.body => Node
730
+ *
731
+ * Given a Method, returns the Node for that Method's body. This can be
732
+ * used to directly copy one class's method to another (using
733
+ * add_method).
734
+ */
735
+ static VALUE method_body(VALUE method)
736
+ {
737
+ struct METHOD * m;
738
+ if(ruby_safe_level >= 4)
739
+ {
740
+ /* no access to potentially sensitive data from the sandbox */
741
+ rb_raise(rb_eSecurityError, "Insecure: can't get method body");
742
+ }
743
+ Data_Get_Struct(method, struct METHOD, m);
744
+ return wrap_node(m->body);
745
+ }
746
+
747
+ /*
748
+ * call-seq:
749
+ * method.dump(limit) => String
750
+ *
751
+ * Dump a Method and the object to which it is bound to a String. The
752
+ * Method's class will not be dumped, only the name of the class.
753
+ *
754
+ * Unfortunately, this means that methods for anonymous classes can be
755
+ * dumped but cannot be loaded.
756
+ */
757
+ static VALUE method_dump(VALUE self, VALUE limit)
758
+ {
759
+ struct METHOD * method;
760
+ VALUE arr;
761
+
762
+ if(ruby_safe_level >= 4)
763
+ {
764
+ /* no access to potentially sensitive data from the sandbox */
765
+ rb_raise(rb_eSecurityError, "Insecure: can't dump method");
766
+ }
767
+
768
+ arr = rb_ary_new();
769
+ Data_Get_Struct(self, struct METHOD, method);
770
+ rb_ary_push(arr, rb_mod_name(method->klass));
771
+ #if RUBY_VERSION_CODE >= 180
772
+ rb_ary_push(arr, rb_mod_name(method->rklass));
773
+ #else
774
+ rb_ary_push(arr, rb_mod_name(method->oklass));
775
+ #endif
776
+ if(rb_class_of(self) == rb_cUnboundMethod)
777
+ {
778
+ rb_ary_push(arr, Qnil);
779
+ }
780
+ else
781
+ {
782
+ rb_ary_push(arr, method->recv);
783
+ }
784
+ rb_ary_push(arr, ID2SYM(method->id));
785
+ rb_ary_push(arr, ID2SYM(method->oid));
786
+ rb_ary_push(arr, method_body(self));
787
+
788
+ return marshal_dump(arr, limit);
789
+ }
790
+
791
+ /*
792
+ * call-seq:
793
+ * Method.load(String) => Method
794
+ *
795
+ * Load a Method from a String.
796
+ */
797
+ static VALUE method_load(VALUE klass, VALUE str)
798
+ {
799
+ struct METHOD * method;
800
+ VALUE rarr = marshal_load(str);
801
+ VALUE * arr;
802
+ NODE * n;
803
+ VALUE retval;
804
+
805
+ if( ruby_safe_level >= 4
806
+ || (ruby_safe_level >= 1 && OBJ_TAINTED(str)))
807
+ {
808
+ /* no playing with knives in the sandbox */
809
+ rb_raise(rb_eSecurityError, "Insecure: can't load method");
810
+ }
811
+
812
+ Check_Type(rarr, T_ARRAY);
813
+ if(RARRAY_LEN(rarr) != 6)
814
+ {
815
+ rb_raise(rb_eArgError, "corrupt data");
816
+ }
817
+
818
+ /* Create a METHOD object -- doesn't matter which method we use */
819
+ retval = rb_funcall(
820
+ rb_cObject, rb_intern("method"), 1, ID2SYM(rb_intern("__id__")));
821
+ Data_Get_Struct(retval, struct METHOD, method);
822
+ arr = RARRAY_PTR(rarr);
823
+ method->klass =
824
+ rb_funcall(lookup_module_proc, rb_intern("call"), 1, arr[0]);
825
+ #if RUBY_VERSION_CODE >= 180
826
+ method->rklass =
827
+ rb_funcall(lookup_module_proc, rb_intern("call"), 1, arr[1]);
828
+ #else
829
+ method->oklass =
830
+ rb_funcall(lookup_module_proc, rb_intern("call"), 1, arr[1]);
831
+ #endif
832
+ method->recv = arr[2];
833
+ method->id = SYM2ID(arr[3]);
834
+ method->oid = SYM2ID(arr[4]);
835
+ Data_Get_Struct(arr[5], NODE, n);
836
+ method->body = n;
837
+
838
+ if(klass == rb_cUnboundMethod)
839
+ {
840
+ retval = rb_funcall(retval, rb_intern("unbind"), 0);
841
+ }
842
+
843
+ return retval;
844
+ }
845
+
846
+ /* ---------------------------------------------------------------------
847
+ * Proc methods
848
+ * ---------------------------------------------------------------------
849
+ */
850
+
851
+ /*
852
+ * call-seq:
853
+ * proc.body => Node
854
+ *
855
+ * Returns the Proc's body Node.
856
+ *
857
+ * On YARV, this will return the instruction sequence for the proc's
858
+ * block.
859
+ */
860
+ static VALUE proc_body(VALUE self)
861
+ {
862
+ #ifdef RUBY_HAS_YARV
863
+ rb_proc_t * p;
864
+ GetProcPtr(self, p);
865
+ return p->block.iseq->self;
866
+ #else
867
+ struct BLOCK * b;
868
+ if(ruby_safe_level >= 4)
869
+ {
870
+ /* no access to potentially sensitive data from the sandbox */
871
+ rb_raise(rb_eSecurityError, "Insecure: can't get proc body");
872
+ }
873
+ Data_Get_Struct(self, struct BLOCK, b);
874
+ return wrap_node(b->body);
875
+ #endif
876
+ }
877
+
878
+ #ifndef RUBY_HAS_YARV
879
+ /*
880
+ * call-seq:
881
+ * proc.var => Node
882
+ *
883
+ * Returns the Proc's argument Node.
884
+ *
885
+ * This method is undefined on YARV.
886
+ */
887
+ static VALUE proc_var(VALUE self)
888
+ {
889
+ struct BLOCK * b;
890
+ if(ruby_safe_level >= 4)
891
+ {
892
+ /* no access to potentially sensitive data from the sandbox */
893
+ rb_raise(rb_eSecurityError, "Insecure: can't get proc var");
894
+ }
895
+ Data_Get_Struct(self, struct BLOCK, b);
896
+ if(b->var == (NODE*)1)
897
+ {
898
+ /* no parameter || */
899
+ return INT2NUM(1);
900
+ }
901
+ else if(b->var == (NODE*)2)
902
+ {
903
+ /* also no params, but I'm not sure how this one gets generated */
904
+ return INT2NUM(2);
905
+ }
906
+ else
907
+ {
908
+ return wrap_node(b->var);
909
+ }
910
+ }
911
+ #endif
912
+
913
+ /*
914
+ * call-seq:
915
+ * proc.dump(limit) => String
916
+ *
917
+ * Dump a Proc to a String.
918
+ */
919
+ static VALUE proc_dump(VALUE self, VALUE limit)
920
+ {
921
+ if(ruby_safe_level >= 4)
922
+ {
923
+ /* no access to potentially sensitive data from the sandbox */
924
+ rb_raise(rb_eSecurityError, "Insecure: can't dump proc");
925
+ }
926
+
927
+ {
928
+ #ifdef RUBY_HAS_YARV
929
+ rb_proc_t * p;
930
+ VALUE iseq;
931
+ rb_iseq_t * iseqdat;
932
+ GetProcPtr(self, p);
933
+ iseq = p->block.iseq->self;
934
+ iseqdat = iseq_check(iseq);
935
+ iseqdat->type = ISEQ_TYPE_TOP; /* TODO: is this right? */
936
+ VALUE str = marshal_dump(iseq, limit);
937
+ return str;
938
+ #else
939
+ struct BLOCK * b;
940
+ VALUE body, var, arr;
941
+
942
+ Data_Get_Struct(self, struct BLOCK, b);
943
+ body = wrap_node(b->body);
944
+ var = wrap_node(b->var);
945
+ arr = rb_assoc_new(body, var);
946
+ return marshal_dump(arr, limit);
947
+ #endif
948
+ }
949
+ }
950
+
951
+ #ifdef RUBY_HAS_YARV
952
+
953
+ static VALUE create_proc(VALUE klass, VALUE binding, rb_iseq_t * iseq)
954
+ {
955
+ VALUE new_proc = rb_funcall(
956
+ rb_cObject, rb_intern("eval"), 2, rb_str_new2("proc { }"), binding);
957
+ rb_proc_t * p;
958
+ GetProcPtr(new_proc, p);
959
+ p->block.iseq = iseq;
960
+ RBASIC(new_proc)->klass = klass;
961
+ return new_proc;
962
+ }
963
+
964
+ #else
965
+
966
+ static VALUE create_proc(VALUE klass, VALUE binding, NODE * body, NODE * var)
967
+ {
968
+ /* Calling eval will do a security check */
969
+ VALUE new_proc = rb_funcall(
970
+ rb_cObject, rb_intern("eval"), 2, rb_str_new2("proc { }"), binding);
971
+ struct BLOCK * b;
972
+ Data_Get_Struct(new_proc, struct BLOCK, b);
973
+ b->body = body;
974
+ b->var = var;
975
+ RBASIC(new_proc)->klass = klass;
976
+ return new_proc;
977
+ }
978
+
979
+ #endif
980
+
981
+ /*
982
+ * call-seq:
983
+ * Proc.load(str) => UnboundProc
984
+ *
985
+ * Load a Proc from a String. When it is loaded, it will be an
986
+ * UnboundProc, until it is bound to a Binding with UnboundProc#bind.
987
+ */
988
+ static VALUE proc_load(VALUE klass, VALUE str)
989
+ {
990
+ #ifdef RUBY_HAS_YARV
991
+ VALUE iseq = marshal_load(str);
992
+ return create_proc(rb_cUnboundProc, Qnil, iseq_check(iseq));
993
+ #else
994
+ VALUE arr = marshal_load(str);
995
+ NODE * body, * var;
996
+
997
+ if( ruby_safe_level >= 4
998
+ || (ruby_safe_level >= 1 && OBJ_TAINTED(str)))
999
+ {
1000
+ /* no playing with knives in the sandbox */
1001
+ rb_raise(rb_eSecurityError, "Insecure: can't load proc");
1002
+ }
1003
+
1004
+ Check_Type(arr, T_ARRAY);
1005
+ body = unwrap_node(RARRAY_PTR(arr)[0]);
1006
+ var = unwrap_node(RARRAY_PTR(arr)[1]);
1007
+ return create_proc(rb_cUnboundProc, Qnil, body, var);
1008
+ #endif
1009
+ }
1010
+
1011
+ /*
1012
+ * call-seq:
1013
+ * proc.unbind => UnboundProc
1014
+ *
1015
+ * Create an UnboundProc from a Proc.
1016
+ */
1017
+ static VALUE proc_unbind(VALUE self)
1018
+ {
1019
+ #ifdef RUBY_HAS_YARV
1020
+ rb_proc_t * p;
1021
+ GetProcPtr(self, p);
1022
+ return create_proc(rb_cUnboundProc, Qnil, p->block.iseq);
1023
+ #else
1024
+ struct BLOCK * b;
1025
+ Data_Get_Struct(self, struct BLOCK, b);
1026
+ /* no need for a security check to unbind a proc -- though without the
1027
+ * ability to bind, this doesn't seem very useful.
1028
+ */
1029
+ return create_proc(rb_cUnboundProc, Qnil, b->body, b->var);
1030
+ #endif
1031
+ }
1032
+
1033
+ /*
1034
+ * call-seq:
1035
+ * unbound_proc.bind(Binding) => Proc
1036
+ *
1037
+ * Bind an UnboundProc to a Binding. Returns a Proc that has been bound
1038
+ * to the given binding.
1039
+ */
1040
+ static VALUE unboundproc_bind(VALUE self, VALUE binding)
1041
+ {
1042
+ #ifdef RUBY_HAS_YARV
1043
+ rb_proc_t * p;
1044
+ GetProcPtr(self, p);
1045
+ return create_proc(rb_cProc, binding, p->block.iseq);
1046
+ #else
1047
+ struct BLOCK * b;
1048
+ Data_Get_Struct(self, struct BLOCK, b);
1049
+ /* create_proc will do a security check */
1050
+ return create_proc(rb_cProc, binding, b->body, b->var);
1051
+ #endif
1052
+ }
1053
+
1054
+ /*
1055
+ * call-seq:
1056
+ * unbound_proc.call => raises TypeError
1057
+ *
1058
+ * Raises a TypeError; UnboundProc objects cannot be called.
1059
+ */
1060
+ static VALUE unboundproc_call(VALUE self, VALUE args)
1061
+ {
1062
+ rb_raise(rb_eTypeError, "you cannot call unbound proc; bind first");
1063
+ }
1064
+
1065
+ /*
1066
+ * call-seq:
1067
+ * unbound_proc.binding => raises TypeError
1068
+ *
1069
+ * Raises a TypeError; UnboundProc objects have no binding.
1070
+ */
1071
+ static VALUE unboundproc_binding(VALUE self)
1072
+ {
1073
+ rb_raise(rb_eTypeError, "unbound proc has no binding");
1074
+ }
1075
+
1076
+ /* ---------------------------------------------------------------------
1077
+ * Binding methods
1078
+ * ---------------------------------------------------------------------
1079
+ */
1080
+
1081
+ /*
1082
+ * call-seq:
1083
+ * binding.body => Binding
1084
+ *
1085
+ * Given a Binding, returns the Node for that Binding's body.
1086
+ *
1087
+ * On YARV, this will returning the Binding's instruction sequence.
1088
+ */
1089
+ static VALUE binding_body(VALUE self)
1090
+ {
1091
+ #ifdef RUBY_HAS_YARV
1092
+ rb_binding_t * binding;
1093
+ rb_env_t * env;
1094
+ GetBindingPtr(self, binding);
1095
+ GetEnvPtr(binding->env, env);
1096
+ return env->block.iseq->self;
1097
+ #else
1098
+ struct BLOCK * b;
1099
+ if(ruby_safe_level >= 4)
1100
+ {
1101
+ /* no access to potentially sensitive data from the sandbox */
1102
+ rb_raise(rb_eSecurityError, "Insecure: can't get binding body");
1103
+ }
1104
+ Data_Get_Struct(self, struct BLOCK, b);
1105
+ return wrap_node(b->body);
1106
+ #endif
1107
+ }
1108
+
1109
+ /* ---------------------------------------------------------------------
1110
+ * Node evaluation
1111
+ * ---------------------------------------------------------------------
1112
+ */
1113
+
1114
+ /*
1115
+ * call-seq:
1116
+ * node.eval(Object) => Object
1117
+ *
1118
+ * Evaluate a node with the given object as self and returns the result.
1119
+ */
1120
+ static VALUE node_eval(VALUE node, VALUE self)
1121
+ {
1122
+ NODE * n = unwrap_node(node);
1123
+
1124
+ if(ruby_safe_level >= 2)
1125
+ {
1126
+ /* evaluating a node can cause a crash */
1127
+ rb_raise(rb_eSecurityError, "Insecure: can't add method");
1128
+ }
1129
+
1130
+ #ifdef RUBY_HAS_YARV
1131
+ return yarvcore_eval_parsed(n, rb_str_new2("(eval)"));
1132
+ #else
1133
+ {
1134
+ /* Ruby doesn't give us access to rb_eval, so we have to fake it. */
1135
+ struct BLOCK * b;
1136
+ VALUE proc;
1137
+
1138
+ proc = create_proc(rb_cProc, Qnil, n, 0);
1139
+ Data_Get_Struct(proc, struct BLOCK, b);
1140
+ b->self = self;
1141
+ return rb_funcall(proc, rb_intern("call"), 0);
1142
+ }
1143
+ #endif
1144
+ }
1145
+
1146
+ /* ---------------------------------------------------------------------
1147
+ * Node marshalling
1148
+ * ---------------------------------------------------------------------
1149
+ */
1150
+
1151
+ void dump_node_to_hash(NODE * n, VALUE node_hash)
1152
+ {
1153
+ VALUE s1 = Qnil, s2 = Qnil, s3 = Qnil;
1154
+ Node_Type_Descrip const *descrip = node_type_descrip(nd_type(n));
1155
+ VALUE nd_file;
1156
+ VALUE arr;
1157
+
1158
+ if(RTEST(rb_hash_aref(node_hash, node_id(n))))
1159
+ {
1160
+ return;
1161
+ }
1162
+
1163
+ if(TYPE(n) != T_NODE)
1164
+ {
1165
+ rb_raise(
1166
+ rb_eTypeError,
1167
+ "wrong argument type %s (expected Node)",
1168
+ rb_class2name(CLASS_OF(n)));
1169
+ }
1170
+
1171
+ s1 = dump_node_elem(descrip->n1, n, node_hash);
1172
+ s2 = dump_node_elem(descrip->n2, n, node_hash);
1173
+ s3 = dump_node_elem(descrip->n3, n, node_hash);
1174
+
1175
+ nd_file = Qnil;
1176
+ if(n->nd_file)
1177
+ {
1178
+ nd_file = rb_str_new2(n->nd_file);
1179
+ }
1180
+
1181
+ arr = rb_ary_new();
1182
+ rb_ary_push(arr, INT2NUM(n->flags));
1183
+ rb_ary_push(arr, nd_file);
1184
+ rb_ary_push(arr, s1);
1185
+ rb_ary_push(arr, s2);
1186
+ rb_ary_push(arr, s3);
1187
+
1188
+ rb_hash_aset(node_hash, node_id(n), arr);
1189
+ }
1190
+
1191
+ void dump_node_or_iseq_to_hash(VALUE n, VALUE node_hash)
1192
+ {
1193
+ #ifdef RUBY_HAS_YARV
1194
+ if(TYPE(n) == T_DATA && CLASS_OF(n) == rb_cISeq)
1195
+ {
1196
+ return dump_iseq_to_hash(n, node_hash);
1197
+ }
1198
+ #endif
1199
+
1200
+ dump_node_to_hash((NODE *)n, node_hash);
1201
+ }
1202
+
1203
+ NODE * load_node_from_hash(VALUE arr, VALUE orig_node_id, VALUE node_hash, VALUE id_hash)
1204
+ {
1205
+ NODE * n = NEW_NIL();
1206
+ VALUE s3, s2, s1, rb_nd_file, rb_flags;
1207
+ unsigned long flags;
1208
+ char *nd_file = 0;
1209
+ Node_Type_Descrip const *descrip;
1210
+ NODE tmp_node;
1211
+
1212
+ nd_set_type(&tmp_node, NODE_NIL);
1213
+
1214
+ Check_Type(arr, T_ARRAY);
1215
+ s3 = rb_ary_pop(arr);
1216
+ s2 = rb_ary_pop(arr);
1217
+ s1 = rb_ary_pop(arr);
1218
+ rb_nd_file = rb_ary_pop(arr);
1219
+ rb_flags = rb_ary_pop(arr);
1220
+ flags = NUM2INT(rb_flags);
1221
+ tmp_node.flags = flags;
1222
+
1223
+ rb_hash_aset(id_hash, orig_node_id, node_id(n));
1224
+
1225
+ descrip = node_type_descrip(nd_type(&tmp_node));
1226
+ load_node_elem(descrip->n1, s1, &tmp_node, node_hash, id_hash);
1227
+ load_node_elem(descrip->n2, s2, &tmp_node, node_hash, id_hash);
1228
+ load_node_elem(descrip->n3, s3, &tmp_node, node_hash, id_hash);
1229
+
1230
+ /* Note that the garbage collector CAN be invoked at this point, so
1231
+ * any node object the GC knowns about must be in a consistent state.
1232
+ */
1233
+ if(rb_nd_file != Qnil)
1234
+ {
1235
+ Check_Type(rb_nd_file, T_STRING);
1236
+ nd_file = rb_source_filename(RSTRING_PTR(rb_nd_file));
1237
+ }
1238
+
1239
+ /* 1) We must NOT get an exception from here on out, since we are
1240
+ * modifying a live node, and so nd_file_buf won't be leaked.
1241
+ * 2) We must NOT invoke the garbage collector from here on out, since
1242
+ * we are modifying a live node.
1243
+ */
1244
+ memcpy(n, &tmp_node, sizeof(NODE));
1245
+ n->flags = flags;
1246
+ n->nd_file = nd_file;
1247
+
1248
+ return n;
1249
+ }
1250
+
1251
+
1252
+ VALUE load_node_or_iseq_from_hash(VALUE orig_node_id, VALUE node_hash, VALUE id_hash)
1253
+ {
1254
+ VALUE data = rb_hash_aref(node_hash, orig_node_id);
1255
+
1256
+ if(!RTEST(data))
1257
+ {
1258
+ rb_raise(rb_eArgError, "Could not find node %d in hash", NUM2INT(orig_node_id));
1259
+ }
1260
+
1261
+ #ifdef RUBY_HAS_YARV
1262
+ if(TYPE(data) == T_DATA)
1263
+ {
1264
+ return (VALUE)load_iseq_from_hash(data, orig_node_id, node_hash, id_hash);
1265
+ }
1266
+ #endif
1267
+
1268
+ return (VALUE)load_node_from_hash(data, orig_node_id, node_hash, id_hash);
1269
+ }
1270
+
1271
+
1272
+ static VALUE node_to_hash(NODE * n)
1273
+ {
1274
+ VALUE node_hash;
1275
+ node_hash = rb_hash_new();
1276
+ dump_node_to_hash(n, node_hash);
1277
+ return node_hash;
1278
+ }
1279
+
1280
+ /*
1281
+ * call-seq:
1282
+ * Node.compile_string(str) => Node
1283
+ *
1284
+ * Compile a string into a node.
1285
+ */
1286
+ static VALUE node_compile_string(int argc, VALUE * argv, VALUE self)
1287
+ {
1288
+ NODE * node;
1289
+ VALUE str = Qnil, file = Qnil, line = Qnil;
1290
+
1291
+ rb_scan_args(argc, argv, "12", &str, &file, &line);
1292
+
1293
+ file = NIL_P(file) ? rb_str_new2("(compiled)") : file;
1294
+ line = NIL_P(line) ? INT2NUM(1) : line;
1295
+
1296
+ node = rb_compile_string(STR2CSTR(file), str, NUM2INT(line));
1297
+
1298
+ if(ruby_nerrs > 0)
1299
+ {
1300
+ #ifdef RUBY_HAS_YARV
1301
+ ruby_nerrs = 0;
1302
+ rb_exc_raise(GET_THREAD()->errinfo);
1303
+ #else
1304
+ compile_error(0);
1305
+ #endif
1306
+ }
1307
+
1308
+ return wrap_node(node);
1309
+ }
1310
+
1311
+ #ifdef RUBY_HAS_YARV
1312
+ /*
1313
+ * call-seq:
1314
+ * node.bytecode_compile => VM::InstructionSequence
1315
+ *
1316
+ * Compile a parsed node tree into a bytecode sequence.
1317
+ */
1318
+ static VALUE node_bytecode_compile(int argc, VALUE * argv, VALUE self)
1319
+ {
1320
+ NODE * node = unwrap_node(self);
1321
+ VALUE opt = Qnil;
1322
+ rb_compile_option_t option;
1323
+
1324
+ rb_scan_args(argc, argv, "01", &opt);
1325
+ make_compile_option(&option, opt);
1326
+
1327
+ return rb_iseq_new_with_opt(
1328
+ node,
1329
+ rb_str_new2("<main>"),
1330
+ rb_str_new2(node->nd_file),
1331
+ Qfalse,
1332
+ ISEQ_TYPE_TOP,
1333
+ &option);
1334
+ }
1335
+
1336
+ #endif
1337
+
1338
+ /*
1339
+ * call-seq:
1340
+ * node._dump => String
1341
+ *
1342
+ * Dump a node.
1343
+ */
1344
+ static VALUE node_dump(VALUE self, VALUE limit)
1345
+ {
1346
+ NODE * n;
1347
+ VALUE node_hash, arr;
1348
+
1349
+ if(ruby_safe_level >= 4)
1350
+ {
1351
+ /* no access to potentially sensitive data from the sandbox */
1352
+ rb_raise(rb_eSecurityError, "Insecure: can't dump node");
1353
+ }
1354
+
1355
+ Data_Get_Struct(self, NODE, n);
1356
+ node_hash = node_to_hash(n);
1357
+ arr = rb_ary_new();
1358
+ rb_ary_push(arr, node_id(n));
1359
+ rb_ary_push(arr, node_hash);
1360
+ VALUE s = marshal_dump(arr, limit);
1361
+ return s;
1362
+ }
1363
+
1364
+ /*
1365
+ * call-seq:
1366
+ * Node._load(str) => Node
1367
+ *
1368
+ * Load a dumped node.
1369
+ */
1370
+ static VALUE node_load(VALUE klass, VALUE str)
1371
+ {
1372
+ VALUE arr, node_hash, node_id, id_hash;
1373
+ NODE * n;
1374
+ VALUE data;
1375
+
1376
+ if( ruby_safe_level >= 4
1377
+ || (ruby_safe_level >= 1 && OBJ_TAINTED(str)))
1378
+ {
1379
+ /* no playing with knives in the sandbox */
1380
+ rb_raise(rb_eSecurityError, "Insecure: can't load node");
1381
+ }
1382
+
1383
+ arr = marshal_load(str);
1384
+ node_hash = rb_ary_pop(arr);
1385
+ node_id = rb_ary_pop(arr);
1386
+ id_hash = rb_hash_new();
1387
+ data = rb_hash_aref(node_hash, node_id);
1388
+ n = load_node_from_hash(data, node_id, node_hash, id_hash);
1389
+ /* TODO: Need a free function in this case */
1390
+ return wrap_node(n);
1391
+ }
1392
+
1393
+ /* ---------------------------------------------------------------------
1394
+ * Class marshalling
1395
+ * ---------------------------------------------------------------------
1396
+ */
1397
+
1398
+ #if RUBY_VERSION_CODE >= 180
1399
+ static VALUE module_instance_allocate(VALUE klass)
1400
+ {
1401
+ NEWOBJ(obj, struct RClass);
1402
+ OBJSETUP(obj, klass, T_CLASS);
1403
+ return (VALUE)obj;
1404
+ }
1405
+ #endif
1406
+
1407
+ static int add_to_method_hash(ID id, NODE * body, VALUE methods)
1408
+ {
1409
+ VALUE v = wrap_node(body);
1410
+ rb_hash_aset(methods, ID2SYM(id), v);
1411
+
1412
+ return ST_CONTINUE;
1413
+ }
1414
+
1415
+ static VALUE instance_method_hash(VALUE module)
1416
+ {
1417
+ VALUE methods = rb_hash_new();
1418
+ st_foreach(
1419
+ RCLASS(module)->m_tbl,
1420
+ add_to_method_hash,
1421
+ #ifdef ST_DATA_T_DEFINED
1422
+ (st_data_t)methods
1423
+ #else
1424
+ methods
1425
+ #endif
1426
+ );
1427
+ return methods;
1428
+ }
1429
+
1430
+ static VALUE included_modules_list(VALUE module)
1431
+ {
1432
+ VALUE included_modules = rb_mod_included_modules(module);
1433
+ VALUE included_module_list = rb_ary_new();
1434
+ size_t j;
1435
+
1436
+ for(j = 0; j < RARRAY_LEN(included_modules); ++j)
1437
+ {
1438
+ rb_ary_push(
1439
+ included_module_list,
1440
+ rb_mod_name(RARRAY_PTR(included_modules)[j]));
1441
+ }
1442
+
1443
+ return included_module_list;
1444
+ }
1445
+
1446
+ static VALUE superclass_name(VALUE module)
1447
+ {
1448
+ if(TYPE(module) == T_MODULE)
1449
+ {
1450
+ return Qnil;
1451
+ }
1452
+ else
1453
+ {
1454
+ VALUE super = RCLASS(module)->super;
1455
+
1456
+ while(TYPE(super) == T_ICLASS)
1457
+ {
1458
+ super = RCLASS(super)->super;
1459
+ }
1460
+
1461
+ if(!super)
1462
+ {
1463
+ return Qnil;
1464
+ }
1465
+
1466
+ if(FL_TEST(super, FL_SINGLETON))
1467
+ {
1468
+ VALUE v = rb_iv_get(super, "__attached__");
1469
+ VALUE name = rb_mod_name(v);
1470
+ rb_str_cat2(name, "::<Singleton>");
1471
+ return name;
1472
+ }
1473
+ else
1474
+ {
1475
+ return rb_mod_name(super);
1476
+ }
1477
+ }
1478
+ }
1479
+
1480
+ static int add_var_to_hash(ID key, VALUE value, VALUE hash)
1481
+ {
1482
+ /* These are special variables and should not be dumped */
1483
+ if( key != rb_intern("__classpath__")
1484
+ && key != rb_intern("__classid__")
1485
+ && key != rb_intern("__attached__"))
1486
+ {
1487
+ rb_hash_aset(hash, ID2SYM(key), value);
1488
+ }
1489
+ return ST_CONTINUE;
1490
+ }
1491
+
1492
+ static VALUE class_variable_hash(VALUE module)
1493
+ {
1494
+ VALUE class_variables = rb_hash_new();
1495
+ if (ROBJECT(module)->iv_tbl) {
1496
+ st_foreach(RCLASS(module)->iv_tbl, add_var_to_hash, class_variables);
1497
+ }
1498
+ return class_variables;
1499
+ }
1500
+
1501
+ #if RUBY_VERSION_CODE >= 180
1502
+ static VALUE create_class_restorer(VALUE klass)
1503
+ {
1504
+ /* On Ruby 1.8, there is a check in marshal_dump() to ensure that
1505
+ * the object being dumped has no modifications to its singleton
1506
+ * class (e.g. no singleton instance variables, and no singleton
1507
+ * methods defined). Since we need to dump the class's singleton
1508
+ * class in order to dump class methods, we need a way around this
1509
+ * restriction. The solution found here temporarily removes the
1510
+ * singleton instance variables and singleton methods while the
1511
+ * class is being dumped, and sets a special singleton instance
1512
+ * variable that restores the tables when dumping is complete. A
1513
+ * hack for sure, but it seems to work.
1514
+ */
1515
+ struct RClass * singleton_class = RCLASS(CLASS_OF(klass));
1516
+ struct Class_Restorer * class_restorer;
1517
+
1518
+ if(!singleton_class->iv_tbl)
1519
+ {
1520
+ rb_raise(
1521
+ rb_eTypeError,
1522
+ "can't dump singleton class on Ruby 1.8 without iv_tbl");
1523
+ }
1524
+
1525
+ class_restorer = ALLOC(struct Class_Restorer);
1526
+ class_restorer->klass = CLASS_OF(klass);
1527
+ class_restorer->m_tbl = *singleton_class->m_tbl;
1528
+ class_restorer->iv_tbl = *singleton_class->iv_tbl;
1529
+ #ifndef RUBY_HAS_YARV
1530
+ class_restorer->thread_critical = rb_thread_critical;
1531
+ #endif
1532
+ return Data_Wrap_Struct(
1533
+ rb_cClass_Restorer, mark_class_restorer, ruby_xfree,
1534
+ class_restorer);
1535
+ }
1536
+
1537
+ static void set_class_restore_state(VALUE klass)
1538
+ {
1539
+ struct RClass * singleton_class = RCLASS(CLASS_OF(klass));
1540
+ singleton_class->iv_tbl->num_entries = 1;
1541
+ singleton_class->m_tbl->num_entries = 0;
1542
+ #ifndef RUBY_HAS_YARV
1543
+ rb_thread_critical = 1;
1544
+ #endif
1545
+ }
1546
+
1547
+ static void restore_class(VALUE ruby_class_restorer)
1548
+ {
1549
+ struct Class_Restorer * class_restorer;
1550
+ struct RClass * klass;
1551
+
1552
+ Data_Get_Struct(
1553
+ ruby_class_restorer,
1554
+ struct Class_Restorer,
1555
+ class_restorer);
1556
+ klass = RCLASS(class_restorer->klass);
1557
+ *klass->m_tbl = class_restorer->m_tbl;
1558
+ *klass->iv_tbl = class_restorer->iv_tbl;
1559
+ #ifndef RUBY_HAS_YARV
1560
+ rb_thread_critical = class_restorer->thread_critical;
1561
+ #endif
1562
+ }
1563
+
1564
+ static VALUE class_restorer_dump(VALUE ruby_class_restorer, VALUE limit)
1565
+ {
1566
+ restore_class(ruby_class_restorer);
1567
+ return rb_str_new2("");
1568
+ }
1569
+
1570
+ static VALUE class_restorer_load(VALUE klass, VALUE str)
1571
+ {
1572
+ return Qnil;
1573
+ }
1574
+
1575
+ static void mark_class_restorer(struct Class_Restorer * class_restorer)
1576
+ {
1577
+ rb_mark_tbl(&class_restorer->m_tbl);
1578
+ rb_mark_tbl(&class_restorer->iv_tbl);
1579
+ }
1580
+
1581
+ #endif
1582
+
1583
+ /*
1584
+ * call-seq:
1585
+ * module.dump(limit) => String
1586
+ *
1587
+ * Dump a module to a string. The module will be dumped along with its
1588
+ * instance methods, class variables, names of included modules, name of
1589
+ * superclass, its entire metaclass, and the name of the class.
1590
+ *
1591
+ * Note that on ruby 1.8 and newer the module is temporarily modified
1592
+ * while dumping in order to allow singleton classes to be dumped. To
1593
+ * prevent access to the modifed module, Thread.critical is temporarily
1594
+ * set, then restored to its original value once dumping is complete.
1595
+ * Note also that because YARV does not support Thread.critical, the
1596
+ * user must synchronize access to the class with a Mutex in order to
1597
+ * prevent accessing the modified class.
1598
+ */
1599
+ static VALUE module_dump(VALUE self, VALUE limit)
1600
+ {
1601
+ VALUE flags, instance_methods, class_variables;
1602
+ VALUE included_modules, superclass, metaclass, arr, str, class_name;
1603
+
1604
+ limit = INT2NUM(NUM2INT(limit) - 1);
1605
+
1606
+ if(ruby_safe_level >= 4)
1607
+ {
1608
+ /* no access to potentially sensitive data from the sandbox */
1609
+ rb_raise(rb_eSecurityError, "Insecure: can't dump module");
1610
+ }
1611
+
1612
+ flags = INT2NUM(RBASIC(self)->flags);
1613
+ instance_methods = instance_method_hash(self);
1614
+ class_variables = class_variable_hash(self);
1615
+ included_modules = included_modules_list(self);
1616
+ superclass = superclass_name(self);
1617
+ arr = rb_ary_new();
1618
+
1619
+ if(FL_TEST(self, FL_SINGLETON))
1620
+ {
1621
+ metaclass = Qnil;
1622
+ class_name = Qnil;
1623
+ }
1624
+ else
1625
+ {
1626
+ metaclass = rb_singleton_class(self);
1627
+ class_name = rb_class_path(self);
1628
+ }
1629
+
1630
+ rb_ary_push(arr, flags);
1631
+ rb_ary_push(arr, marshal_dump(instance_methods, limit));
1632
+ rb_ary_push(arr, marshal_dump(class_variables, limit));
1633
+ rb_ary_push(arr, included_modules);
1634
+ rb_ary_push(arr, superclass);
1635
+ rb_ary_push(arr, marshal_dump(metaclass, limit));
1636
+ rb_ary_push(arr, class_name);
1637
+
1638
+ str = marshal_dump(arr, limit);
1639
+
1640
+ #if RUBY_VERSION_CODE > 180
1641
+ {
1642
+ VALUE class_restorer = create_class_restorer(self);
1643
+ rb_iv_set(str, "__class_restorer__", class_restorer);
1644
+ set_class_restore_state(self);
1645
+ }
1646
+ #endif
1647
+
1648
+ return str;
1649
+ }
1650
+
1651
+ static void include_modules(module, included_modules)
1652
+ {
1653
+ size_t j;
1654
+ VALUE v;
1655
+ VALUE name;
1656
+
1657
+ rb_check_type(included_modules, T_ARRAY);
1658
+ for(j = 0; j < RARRAY_LEN(included_modules); ++j)
1659
+ {
1660
+ name = RARRAY_PTR(included_modules)[j];
1661
+ v = rb_funcall(lookup_module_proc, rb_intern("call"), 1, name);
1662
+ rb_funcall(module, rb_intern("include"), 1, v);
1663
+ }
1664
+ }
1665
+
1666
+ static int add_method_iter(VALUE name, VALUE value, VALUE module)
1667
+ {
1668
+ NODE * n;
1669
+ rb_check_type(name, T_SYMBOL);
1670
+ if(!rb_obj_is_kind_of(value, rb_cNode))
1671
+ {
1672
+ rb_raise(
1673
+ rb_eTypeError,
1674
+ "Expected Node, but got %s",
1675
+ rb_class2name(CLASS_OF(value)));
1676
+ }
1677
+ Data_Get_Struct(value, NODE, n);
1678
+ rb_add_method(module, SYM2ID(name), n->nd_body, n->nd_noex);
1679
+ return ST_CONTINUE;
1680
+ }
1681
+
1682
+ static void add_methods(VALUE module, VALUE methods)
1683
+ {
1684
+ rb_check_type(methods, T_HASH);
1685
+ st_foreach(RHASH(methods)->tbl, add_method_iter, module);
1686
+ }
1687
+
1688
+ static int set_cvar_from_hash(VALUE key, VALUE value, VALUE module)
1689
+ {
1690
+ #ifdef RB_CVAR_SET_4ARGS
1691
+ rb_cvar_set(module, SYM2ID(key), value, Qtrue);
1692
+ #else
1693
+ rb_cvar_set(module, SYM2ID(key), value);
1694
+ #endif
1695
+ return ST_CONTINUE;
1696
+ }
1697
+
1698
+ static void add_class_variables(VALUE module, VALUE class_variables)
1699
+ {
1700
+ rb_check_type(class_variables, T_HASH);
1701
+ st_foreach(RHASH(class_variables)->tbl, set_cvar_from_hash, module);
1702
+ }
1703
+
1704
+ /*
1705
+ * call-seq:
1706
+ * Module.load(String) => Module
1707
+ *
1708
+ * Load a module from a string.
1709
+ */
1710
+ static VALUE module_load(VALUE klass, VALUE str)
1711
+ {
1712
+ VALUE arr, class_name, metaclass_str, metaclass, superclass_name,
1713
+ included_modules, class_variables_str, class_variables,
1714
+ instance_methods_str, instance_methods, flags, module;
1715
+
1716
+ if( ruby_safe_level >= 4
1717
+ || (ruby_safe_level >= 1 && OBJ_TAINTED(str)))
1718
+ {
1719
+ /* no playing with knives in the sandbox */
1720
+ rb_raise(rb_eSecurityError, "Insecure: can't load module");
1721
+ }
1722
+
1723
+ arr = marshal_load(str);
1724
+ class_name = rb_ary_pop(arr);
1725
+ metaclass_str = rb_ary_pop(arr);
1726
+ superclass_name = rb_ary_pop(arr);
1727
+ included_modules = rb_ary_pop(arr);
1728
+ class_variables_str = rb_ary_pop(arr);
1729
+ instance_methods_str = rb_ary_pop(arr);
1730
+ flags = rb_ary_pop(arr);
1731
+
1732
+ if(RTEST(superclass_name))
1733
+ {
1734
+ VALUE superclass;
1735
+ rb_check_type(superclass_name, T_STRING);
1736
+ superclass = rb_funcall(
1737
+ lookup_module_proc,
1738
+ rb_intern("call"),
1739
+ 1,
1740
+ superclass_name);
1741
+ #if RUBY_VERSION_CODE >= 180
1742
+ /* Can't make subclass of Class on 1.8.x */
1743
+ module = rb_class_boot(superclass);
1744
+ rb_define_alloc_func(module, module_instance_allocate);
1745
+ #else
1746
+ module = rb_class_new(superclass);
1747
+ #endif
1748
+ }
1749
+ else
1750
+ {
1751
+ module = rb_module_new();
1752
+ }
1753
+
1754
+ if(!NIL_P(class_name))
1755
+ {
1756
+ VALUE outer_module = rb_funcall(outer_module_proc, rb_intern("call"), 1, class_name);
1757
+ VALUE module_name = rb_funcall(module_name_proc, rb_intern("call"), 1, class_name);
1758
+ rb_const_set(outer_module, SYM2ID(module_name), module);
1759
+ }
1760
+
1761
+ RBASIC(module)->flags = NUM2INT(flags);
1762
+ include_modules(module, included_modules);
1763
+ class_variables = marshal_load(class_variables_str);
1764
+ add_class_variables(module, class_variables);
1765
+ instance_methods = marshal_load(instance_methods_str);
1766
+ add_methods(module, instance_methods);
1767
+
1768
+ metaclass = marshal_load(metaclass_str);
1769
+ if(RTEST(metaclass))
1770
+ {
1771
+ rb_singleton_class_attached(metaclass, module);
1772
+ RBASIC(module)->klass = metaclass;
1773
+ }
1774
+
1775
+ return module;
1776
+ }
1777
+
1778
+ #if RUBY_VERSION_CODE == 180
1779
+
1780
+ static VALUE ruby180_marshal_dump(int argc, VALUE * argv, VALUE klass)
1781
+ {
1782
+ VALUE class_restorer = Qnil;
1783
+
1784
+ if(argc >= 1 && (TYPE(argv[0]) == T_CLASS || TYPE(argv[0]) == T_MODULE))
1785
+ {
1786
+ class_restorer = create_class_restorer(argv[0]);
1787
+ set_class_restore_state(argv[0]);
1788
+ }
1789
+
1790
+ VALUE str = rb_funcall2(klass, rb_intern("_Nodewrap__orig_dump"), argc, argv);
1791
+
1792
+ if(class_restorer != Qnil)
1793
+ {
1794
+ restore_class(class_restorer);
1795
+ }
1796
+
1797
+ return str;
1798
+ }
1799
+
1800
+ #endif
1801
+
1802
+ /* ---------------------------------------------------------------------
1803
+ * Methods for VM::InstructionSequence
1804
+ * ---------------------------------------------------------------------
1805
+ */
1806
+
1807
+ #ifdef RUBY_HAS_YARV
1808
+
1809
+ /* call-seq:
1810
+ * iseq.self => VM::InstructionSequence
1811
+ *
1812
+ * Returns the self member of the instruction sequence.
1813
+ */
1814
+ static VALUE iseq_self(VALUE self)
1815
+ {
1816
+ rb_iseq_t *iseqdat = iseq_check(self);
1817
+ return iseqdat->self;
1818
+ }
1819
+
1820
+ /* call-seq:
1821
+ * iseq.name => String
1822
+ *
1823
+ * Returns the name of the instruction sequence.
1824
+ */
1825
+ static VALUE iseq_name(VALUE self)
1826
+ {
1827
+ rb_iseq_t *iseqdat = iseq_check(self);
1828
+ return iseqdat->name;
1829
+ }
1830
+
1831
+ /* call-seq:
1832
+ * iseq.filename => String
1833
+ *
1834
+ * Returns the filename of the instruction sequence.
1835
+ */
1836
+ static VALUE iseq_filename(VALUE self)
1837
+ {
1838
+ rb_iseq_t *iseqdat = iseq_check(self);
1839
+ return iseqdat->filename;
1840
+ }
1841
+
1842
+ /* call-seq:
1843
+ * iseq.local_table => String
1844
+ *
1845
+ * Returns the sequence's local table.
1846
+ */
1847
+ static VALUE iseq_local_table(VALUE self)
1848
+ {
1849
+ rb_iseq_t *iseqdat = iseq_check(self);
1850
+ VALUE ary = rb_ary_new();
1851
+ int j;
1852
+
1853
+ for(j = 0; j < iseqdat->local_table_size; ++j)
1854
+ {
1855
+ ID id = iseqdat->local_table[j];
1856
+ if(rb_id2name(id))
1857
+ {
1858
+ rb_ary_push(ary, ID2SYM(id));
1859
+ }
1860
+ else
1861
+ {
1862
+ // Temporary
1863
+ rb_ary_push(ary, Qnil);
1864
+ }
1865
+ }
1866
+
1867
+ return ary;
1868
+ }
1869
+
1870
+ /* call-seq:
1871
+ * iseq.argc => String
1872
+ *
1873
+ * Returns the number of non-optional arguments.
1874
+ */
1875
+ static VALUE iseq_argc(VALUE self)
1876
+ {
1877
+ rb_iseq_t *iseqdat = iseq_check(self);
1878
+ return INT2NUM(iseqdat->argc);
1879
+ }
1880
+
1881
+ /* call-seq:
1882
+ * iseq.arg_simple => true or false
1883
+ *
1884
+ * Returns true if this sequence takes only simple (non-rest, non-opt,
1885
+ * non-block) args.
1886
+ */
1887
+ static VALUE iseq_arg_simple(VALUE self)
1888
+ {
1889
+ rb_iseq_t *iseqdat = iseq_check(self);
1890
+ return iseqdat->arg_simple ? Qtrue : Qfalse;
1891
+ }
1892
+
1893
+ /* call-seq:
1894
+ * iseq.arg_rest => true or false
1895
+ *
1896
+ * Returns the index of the rest (*x) arg.
1897
+ */
1898
+ static VALUE iseq_arg_rest(VALUE self)
1899
+ {
1900
+ rb_iseq_t *iseqdat = iseq_check(self);
1901
+ return INT2NUM(iseqdat->arg_rest);
1902
+ }
1903
+
1904
+ /* call-seq:
1905
+ * iseq.arg_block => true or false
1906
+ *
1907
+ * Returns the index of the block (&x) arg.
1908
+ */
1909
+ static VALUE iseq_arg_block(VALUE self)
1910
+ {
1911
+ rb_iseq_t *iseqdat = iseq_check(self);
1912
+ return INT2NUM(iseqdat->arg_block);
1913
+ }
1914
+
1915
+ /* call-seq:
1916
+ * iseq.arg_opt_table => Array of Integer
1917
+ *
1918
+ * Returns optional argument table. The value in the table represent
1919
+ * the index into the instruction sequence of the code to set the
1920
+ * optional argument. The last element is the index of the start of the
1921
+ * code sequence.
1922
+ */
1923
+ static VALUE iseq_arg_opt_table(VALUE self)
1924
+ {
1925
+ rb_iseq_t *iseqdat = iseq_check(self);
1926
+ VALUE ary = rb_ary_new();
1927
+ int j;
1928
+
1929
+ for(j = 0; j < iseqdat->arg_opts; ++j)
1930
+ {
1931
+ rb_ary_push(ary, INT2NUM(iseqdat->arg_opt_tbl[j]));
1932
+ }
1933
+
1934
+ return ary;
1935
+ }
1936
+
1937
+ /* call-seq:
1938
+ * iseq.each(&block) => nil
1939
+ *
1940
+ * Yields each instruction in the sequence.
1941
+ */
1942
+ static VALUE iseq_each(VALUE self)
1943
+ {
1944
+ rb_iseq_t *iseqdat = iseq_check(self);
1945
+ VALUE * seq;
1946
+
1947
+ for(seq = iseqdat->iseq; seq < iseqdat->iseq + iseqdat->size; )
1948
+ {
1949
+ VALUE insn = *seq++;
1950
+ int op_type_idx;
1951
+ int len = insn_len(insn);
1952
+ VALUE args = rb_ary_new();
1953
+
1954
+ for(op_type_idx = 0; op_type_idx < len-1; ++op_type_idx, ++seq)
1955
+ {
1956
+ switch(insn_op_type(insn, op_type_idx))
1957
+ {
1958
+ case TS_VALUE:
1959
+ rb_ary_push(args, *seq);
1960
+ break;
1961
+
1962
+ case TS_LINDEX:
1963
+ case TS_DINDEX:
1964
+ case TS_NUM:
1965
+ rb_ary_push(args, INT2FIX(*seq));
1966
+ break;
1967
+
1968
+ case TS_ISEQ:
1969
+ {
1970
+ rb_iseq_t * iseq = (rb_iseq_t *)*seq;
1971
+ if(iseq)
1972
+ {
1973
+ rb_ary_push(args, iseq->self);
1974
+ }
1975
+ else
1976
+ {
1977
+ rb_ary_push(args, Qnil);
1978
+ }
1979
+ break;
1980
+ }
1981
+
1982
+ case TS_GENTRY:
1983
+ {
1984
+ struct global_entry *entry = (struct global_entry *)*seq;
1985
+ rb_ary_push(args, ID2SYM(rb_intern(rb_id2name(entry->id))));
1986
+ break;
1987
+ }
1988
+
1989
+ case TS_OFFSET:
1990
+ rb_ary_push(args, Qnil);
1991
+ /* TODO */
1992
+ break;
1993
+
1994
+ case TS_VARIABLE:
1995
+ rb_ary_push(args, Qnil);
1996
+ /* TODO */
1997
+ break;
1998
+
1999
+ case TS_CDHASH:
2000
+ rb_ary_push(args, Qnil);
2001
+ /* TODO */
2002
+ break;
2003
+
2004
+ case TS_IC:
2005
+ {
2006
+ NODE * ic = (NODE *)*seq;
2007
+ ic->ic_klass = 0; /* TODO */
2008
+ rb_ary_push(args, wrap_node_as(ic, rb_cInlineCache));
2009
+ break;
2010
+ }
2011
+
2012
+ case TS_ID:
2013
+ rb_ary_push(args, ID2SYM(*seq));
2014
+ break;
2015
+ }
2016
+ }
2017
+
2018
+ rb_yield(rb_class_new_instance(
2019
+ RARRAY(args)->len,
2020
+ RARRAY(args)->ptr,
2021
+ instruction_class[insn]));
2022
+ }
2023
+
2024
+ return Qnil;
2025
+ }
2026
+
2027
+ /* call-seq:
2028
+ * iseq.insn_line(n) => Integer
2029
+ *
2030
+ * Returns the line number of the nth instruction in the sequence.
2031
+ */
2032
+ static VALUE iseq_insn_line(VALUE self, VALUE n)
2033
+ {
2034
+ rb_iseq_t *iseqdat = iseq_check(self);
2035
+ unsigned long pos = NUM2LONG(n);
2036
+ unsigned long i, size = iseqdat->insn_info_size;
2037
+ struct insn_info_struct *iiary = iseqdat->insn_info_tbl;
2038
+
2039
+ for (i = 0; i < size; i++) {
2040
+ if (iiary[i].position == pos) {
2041
+ return INT2NUM(iiary[i].line_no);
2042
+ }
2043
+ }
2044
+ return Qnil;
2045
+ }
2046
+
2047
+ /* The putobject instruction takes a VALUE as a parameter. But if this
2048
+ * value is a class, we'll end up trying to dump the class! That's
2049
+ * probably not what we want, so we use a placeholder instead.
2050
+ */
2051
+ void convert_modules_to_placeholders(VALUE array)
2052
+ {
2053
+ int j;
2054
+
2055
+ for(j = 0; j < RARRAY(array)->len; ++j)
2056
+ {
2057
+ VALUE v = RARRAY(array)->ptr[j];
2058
+ if(TYPE(v) == T_ARRAY)
2059
+ {
2060
+ convert_modules_to_placeholders(v);
2061
+ }
2062
+ else if(TYPE(v) == T_MODULE || TYPE(v) == T_CLASS)
2063
+ {
2064
+ VALUE p = rb_class_new_instance(0, 0, rb_cModulePlaceholder);
2065
+ VALUE sym = rb_mod_name(p);
2066
+ rb_iv_set(p, "name", sym);
2067
+ RARRAY(array)->ptr[j] = p;
2068
+ }
2069
+ }
2070
+ }
2071
+
2072
+ void convert_placeholders_to_modules(VALUE array)
2073
+ {
2074
+ int j;
2075
+
2076
+ for(j = 0; j < RARRAY(array)->len; ++j)
2077
+ {
2078
+ VALUE v = RARRAY(array)->ptr[j];
2079
+ if(TYPE(v) == T_ARRAY)
2080
+ {
2081
+ convert_placeholders_to_modules(v);
2082
+ }
2083
+ else if(CLASS_OF(v) == rb_cModulePlaceholder)
2084
+ {
2085
+ VALUE sym = rb_ivar_get(v, rb_intern("name"));
2086
+ VALUE klass =
2087
+ rb_funcall(lookup_module_proc, rb_intern("call"), 1, sym);
2088
+ RARRAY(array)->ptr[j] = klass;
2089
+ }
2090
+ }
2091
+ }
2092
+
2093
+ /*
2094
+ * call-seq:
2095
+ * iseq.dump(limit) => String
2096
+ *
2097
+ * Dumps VM::InstuctionSequence to a string (only available on YARV).
2098
+ */
2099
+ static VALUE iseq_marshal_dump(VALUE self, VALUE limit)
2100
+ {
2101
+ VALUE arr;
2102
+
2103
+ if(ruby_safe_level >= 4)
2104
+ {
2105
+ /* no access to potentially sensitive data from the sandbox */
2106
+ rb_raise(rb_eSecurityError, "Insecure: can't dump iseq");
2107
+ }
2108
+
2109
+ arr = iseq_data_to_ary((rb_iseq_t *)DATA_PTR(self));
2110
+ convert_modules_to_placeholders(arr);
2111
+
2112
+ return marshal_dump(arr, limit);
2113
+ }
2114
+
2115
+ /*
2116
+ * call-seq:
2117
+ * VM::InstructionSequence.load(String) => VM::InstructionSequence
2118
+ *
2119
+ * Load a VM::InstuctionSequence from a string (only available on YARV).
2120
+ */
2121
+ static VALUE iseq_marshal_load(VALUE klass, VALUE str)
2122
+ {
2123
+ VALUE arr;
2124
+
2125
+ if( ruby_safe_level >= 4
2126
+ || (ruby_safe_level >= 1 && OBJ_TAINTED(str)))
2127
+ {
2128
+ /* no playing with knives in the sandbox */
2129
+ rb_raise(rb_eSecurityError, "Insecure: can't load iseq");
2130
+ }
2131
+
2132
+ arr = marshal_load(str);
2133
+ convert_placeholders_to_modules(arr);
2134
+
2135
+ VALUE iseq = iseq_load(Qnil, arr, 0, Qnil);
2136
+ return iseq;
2137
+ }
2138
+
2139
+ void dump_iseq_to_hash(VALUE iseq, VALUE node_hash)
2140
+ {
2141
+ if(RTEST(rb_hash_aref(node_hash, rb_obj_id(iseq))))
2142
+ {
2143
+ return;
2144
+ }
2145
+
2146
+ rb_hash_aset(node_hash, rb_obj_id(iseq), iseq);
2147
+ }
2148
+
2149
+ VALUE load_iseq_from_hash(VALUE iseq, VALUE orig_node_id, VALUE node_hash, VALUE id_hash)
2150
+ {
2151
+ rb_hash_aset(id_hash, orig_node_id, rb_obj_id(iseq));
2152
+ return iseq;
2153
+ }
2154
+
2155
+ #endif
2156
+
2157
+ /* ---------------------------------------------------------------------
2158
+ * Methods for VM::Instruction
2159
+ * ---------------------------------------------------------------------
2160
+ */
2161
+
2162
+ #ifdef RUBY_HAS_YARV
2163
+
2164
+
2165
+ static VALUE instruction_initialize(int argc, VALUE * argv, VALUE self)
2166
+ {
2167
+ VALUE operands = rb_ary_new4(argc, argv);
2168
+ rb_iv_set(self, "@operands", operands);
2169
+ return Qnil;
2170
+ }
2171
+
2172
+ static VALUE instruction_operands(VALUE self)
2173
+ {
2174
+ return rb_iv_get(self, "@operands");
2175
+ }
2176
+
2177
+ #endif
2178
+
2179
+ /* ---------------------------------------------------------------------
2180
+ * Methods for VM::InlineCache
2181
+ * ---------------------------------------------------------------------
2182
+ */
2183
+
2184
+ #ifdef RUBY_HAS_YARV
2185
+
2186
+ static VALUE inline_cache_klass(VALUE self)
2187
+ {
2188
+ /* TODO: returning the real value can crash the interpreter */
2189
+ return Qnil;
2190
+ }
2191
+
2192
+ static VALUE inline_cache_value(VALUE self)
2193
+ {
2194
+ IC inline_cache = unwrap_node(self);
2195
+ return inline_cache->ic_value;
2196
+ }
2197
+
2198
+ static VALUE inline_cache_vmstat(VALUE self)
2199
+ {
2200
+ IC inline_cache = unwrap_node(self);
2201
+ return INT2NUM(inline_cache->ic_vmstat);
2202
+ }
2203
+
2204
+ #endif
2205
+
2206
+ /* ---------------------------------------------------------------------
2207
+ * Eval tree
2208
+ * ---------------------------------------------------------------------
2209
+ */
2210
+
2211
+ /* TODO Not quite sure how to get BEGIN nodes on 1.9.x... */
2212
+ #if RUBY_VERSION_CODE < 190
2213
+ extern NODE *ruby_eval_tree_begin;
2214
+ #endif
2215
+ extern NODE *ruby_eval_tree;
2216
+
2217
+ #if RUBY_VERSION_CODE < 190
2218
+ static VALUE ruby_eval_tree_begin_getter()
2219
+ {
2220
+ if(ruby_safe_level >= 4)
2221
+ {
2222
+ /* no access to potentially sensitive data from the sandbox */
2223
+ rb_raise(rb_eSecurityError, "Insecure: can't get eval tree");
2224
+ }
2225
+
2226
+ if(ruby_eval_tree_begin)
2227
+ {
2228
+ return wrap_node(ruby_eval_tree_begin);
2229
+ }
2230
+ else
2231
+ {
2232
+ return Qnil;
2233
+ }
2234
+ }
2235
+
2236
+ static void ruby_eval_tree_begin_setter()
2237
+ {
2238
+ rb_raise(rb_eNotImpError, "ruby_eval_tree_begin_setter() not implemented");
2239
+ }
2240
+ #endif
2241
+
2242
+ static VALUE ruby_eval_tree_getter()
2243
+ {
2244
+ if(ruby_safe_level >= 4)
2245
+ {
2246
+ /* no access to potentially sensitive data from the sandbox */
2247
+ rb_raise(rb_eSecurityError, "Insecure: can't get eval tree");
2248
+ }
2249
+
2250
+ if(ruby_eval_tree)
2251
+ {
2252
+ return wrap_node(ruby_eval_tree);
2253
+ }
2254
+ else
2255
+ {
2256
+ return Qnil;
2257
+ }
2258
+ }
2259
+
2260
+ static void ruby_eval_tree_setter()
2261
+ {
2262
+ rb_raise(rb_eNotImpError, "ruby_eval_tree_setter() not implemented");
2263
+ }
2264
+
2265
+ /* ---------------------------------------------------------------------
2266
+ * Methods for printing class tree
2267
+ * ---------------------------------------------------------------------
2268
+ */
2269
+
2270
+ /*
2271
+ * call-seq:
2272
+ * class.real_superclass => Class
2273
+ *
2274
+ * Return the immediate superclass of a class or module. This may be a
2275
+ * base class, a singleton class, or a module singleton.
2276
+ */
2277
+ VALUE real_superclass(VALUE self)
2278
+ {
2279
+ rb_include_module(rb_class_of(RCLASS(self)->super), rb_mKernel);
2280
+ return RCLASS(self)->super;
2281
+ }
2282
+
2283
+ /*
2284
+ * call-seq:
2285
+ * class.real_class => Class
2286
+ *
2287
+ * Return the object's first immediate ancestor; this may be the
2288
+ * object's class, its singleton class, or a module singleton.
2289
+ */
2290
+ VALUE real_class(VALUE self)
2291
+ {
2292
+ return RBASIC(self)->klass;
2293
+ }
2294
+
2295
+ /*
2296
+ * call-seq:
2297
+ * class.singleton? => true or false
2298
+ *
2299
+ * Return true if this object is a singleton (that is, it has the
2300
+ * FL_SINGLETON flag set).
2301
+ */
2302
+ VALUE is_singleton(VALUE self)
2303
+ {
2304
+ return FL_TEST(self, FL_SINGLETON) ? Qtrue : Qfalse;
2305
+ }
2306
+
2307
+ /*
2308
+ * call-seq:
2309
+ * class.has_singleton? => true or false
2310
+ *
2311
+ * Return true if this object has a singleton class.
2312
+ */
2313
+ VALUE has_singleton(VALUE self)
2314
+ {
2315
+ return FL_TEST(RBASIC(self)->klass, FL_SINGLETON) ? Qtrue : Qfalse;
2316
+ }
2317
+
2318
+ /*
2319
+ * call-seq:
2320
+ * class.singleton_class => Class
2321
+ *
2322
+ * Return the object's singleton class. Creats a new singleton class
2323
+ * for the object if it does not have one. See RCR#231.
2324
+ */
2325
+ VALUE singleton_class(VALUE self)
2326
+ {
2327
+ return rb_singleton_class(self);
2328
+ }
2329
+
2330
+ /* ---------------------------------------------------------------------
2331
+ * Initialization
2332
+ * ---------------------------------------------------------------------
2333
+ */
2334
+
2335
+ void Init_nodewrap(void)
2336
+ {
2337
+ VALUE rb_cBinding, rb_cModule, rb_mNoex;
2338
+
2339
+ {
2340
+ int actual_ruby_version_code = 0;
2341
+ VALUE ruby_version_str = rb_const_get(rb_cObject, rb_intern("RUBY_VERSION"));
2342
+ char const * s = STR2CSTR(ruby_version_str);
2343
+
2344
+ for(; *s != '\0'; ++s)
2345
+ {
2346
+ if(isdigit(*s))
2347
+ {
2348
+ actual_ruby_version_code *= 10;
2349
+ actual_ruby_version_code += *s - '0';
2350
+ }
2351
+ }
2352
+
2353
+ if(actual_ruby_version_code != RUBY_VERSION_CODE)
2354
+ {
2355
+ rb_raise(
2356
+ rb_eRuntimeError,
2357
+ "This version of nodewrap was built with a different version of ruby "
2358
+ "(built with %d, running on %d)",
2359
+ RUBY_VERSION_CODE,
2360
+ actual_ruby_version_code);
2361
+ }
2362
+ }
2363
+
2364
+ rb_mNodewrap = rb_define_module("Nodewrap");
2365
+
2366
+ rb_cNode = rb_define_class("Node", rb_cObject);
2367
+
2368
+ #if RUBY_VERSION_CODE >= 180
2369
+ rb_define_alloc_func(rb_cNode, node_allocate);
2370
+ #endif
2371
+
2372
+ rb_define_method(rb_cNode, "address", node_address, 0);
2373
+ rb_define_method(rb_cNode, "flags", node_flags, 0);
2374
+ rb_define_method(rb_cNode, "nd_file", node_nd_file, 0);
2375
+ rb_define_method(rb_cNode, "nd_line", node_nd_line, 0);
2376
+ rb_define_method(rb_cNode, "nd_type", node_nd_type, 0);
2377
+ rb_define_method(rb_cNode, "members", node_members, 0);
2378
+ rb_define_method(rb_cNode, "eval", node_eval, 1);
2379
+ rb_define_method(rb_cNode, "[]", node_bracket, 1);
2380
+ rb_define_method(rb_cNode, "inspect", node_inspect, 0);
2381
+ rb_define_singleton_method(rb_cNode, "compile_string", node_compile_string, -1);
2382
+ #ifdef RUBY_HAS_YARV
2383
+ rb_define_method(rb_cNode, "bytecode_compile", node_bytecode_compile, -1);
2384
+ #endif
2385
+ rb_define_method(rb_cNode, "_dump", node_dump, 1);
2386
+ rb_define_singleton_method(rb_cNode, "_load", node_load, 1);
2387
+
2388
+ define_node_subclass_methods();
2389
+
2390
+ /* For rdoc: rb_cNodeType = rb_define_class("NodeType", rb_cObject) */
2391
+ rb_cNodeType = rb_funcall(
2392
+ rb_cStruct,
2393
+ rb_intern("new"),
2394
+ 2,
2395
+ ID2SYM(rb_intern("name")),
2396
+ ID2SYM(rb_intern("value")));
2397
+ rb_const_set(rb_cNode, rb_intern("Type"), rb_cNodeType);
2398
+ rb_define_method(rb_cNodeType, "to_s", node_type_to_s, 0);
2399
+ rb_define_method(rb_cNodeType, "to_i", node_type_to_i, 0);
2400
+
2401
+ /* For rdoc: rb_cProc = rb_define_class("Proc", rb_cObject) */
2402
+ rb_define_method(rb_cProc, "body", proc_body, 0);
2403
+ #ifndef RUBY_HAS_YARV
2404
+ rb_define_method(rb_cProc, "var", proc_var, 0);
2405
+ #endif
2406
+ rb_define_method(rb_cProc, "unbind", proc_unbind, 0);
2407
+ rb_define_method(rb_cProc, "_dump", proc_dump, 1);
2408
+ rb_define_singleton_method(rb_cProc, "_load", proc_load, 1);
2409
+
2410
+ rb_cUnboundProc = rb_define_class("UnboundProc", rb_cProc);
2411
+ rb_define_method(rb_cUnboundProc, "bind", unboundproc_bind, 1);
2412
+ rb_define_method(rb_cUnboundProc, "call", unboundproc_call, -2);
2413
+ rb_define_method(rb_cUnboundProc, "[]", unboundproc_call, -2);
2414
+ rb_define_method(rb_cUnboundProc, "binding", unboundproc_binding, 0);
2415
+
2416
+ rb_mMarshal = rb_const_get(rb_cObject, rb_intern("Marshal"));
2417
+
2418
+ /* For rdoc: rb_cMethod = rb_define_class("Method", rb_cObject) */
2419
+ #if RUBY_VERSION_CODE < 185
2420
+ rb_cMethod = rb_const_get(rb_cObject, rb_intern("Method"));
2421
+ #endif
2422
+ rb_define_method(rb_cMethod, "receiver", method_receiver, 0);
2423
+ rb_define_method(rb_cMethod, "origin_class", method_origin_class, 0);
2424
+
2425
+ /* For rdoc: rb_cUnboundMethod = rb_define_class("UnboundMethod", rb_cObject) */
2426
+ #if RUBY_VERSION_CODE < 185
2427
+ rb_cUnboundMethod = rb_const_get(rb_cObject, rb_intern("UnboundMethod"));
2428
+ #endif
2429
+ rb_define_method(rb_cMethod, "method_id", method_id, 0);
2430
+ rb_define_method(rb_cUnboundMethod, "method_id", method_id, 0);
2431
+ rb_define_method(rb_cMethod, "method_oid", method_oid, 0);
2432
+ rb_define_method(rb_cUnboundMethod, "method_oid", method_oid, 0);
2433
+ rb_define_method(rb_cMethod, "body", method_body, 0);
2434
+ rb_define_method(rb_cUnboundMethod, "body", method_body, 0);
2435
+ rb_define_method(rb_cMethod, "_dump", method_dump, 1);
2436
+ rb_define_method(rb_cUnboundMethod, "_dump", method_dump, 1);
2437
+ rb_define_singleton_method(rb_cMethod, "_load", method_load, 1);
2438
+ rb_define_singleton_method(rb_cUnboundMethod, "_load", method_load, 1);
2439
+
2440
+ /* For rdoc: rb_cBinding = rb_define_class("Binding", rb_cObject) */
2441
+ rb_cBinding = rb_const_get(rb_cObject, rb_intern("Binding"));
2442
+ rb_define_method(rb_cBinding, "body", binding_body, 0);
2443
+
2444
+ /* For rdoc: rb_cModule = rb_define_class("Module", rb_cObject) */
2445
+ rb_cModule = rb_const_get(rb_cObject, rb_intern("Module"));
2446
+ rb_define_method(rb_cModule, "add_method", module_add_method, 3);
2447
+ rb_define_private_method(rb_cModule, "uninclude", module_uninclude, -1);
2448
+ rb_define_private_method(rb_cModule, "remove_features", module_remove_features, 1);
2449
+ rb_define_private_method(rb_cModule, "unincluded", module_unincluded, 1);
2450
+
2451
+ lookup_module_proc = rb_eval_string(lookup_module_str);
2452
+ rb_global_variable(&lookup_module_proc);
2453
+
2454
+ outer_module_proc = rb_eval_string(outer_module_str);
2455
+ rb_global_variable(&outer_module_proc);
2456
+
2457
+ module_name_proc = rb_eval_string(module_name_str);
2458
+ rb_global_variable(&module_name_proc);
2459
+
2460
+ #if RUBY_VERSION_CODE >= 180
2461
+ rb_cClass_Restorer = rb_define_class_under(rb_mNodewrap, "ClassRestorer", rb_cObject);
2462
+ rb_define_method(rb_cClass_Restorer, "_dump", class_restorer_dump, 1);
2463
+ rb_define_singleton_method(rb_cClass_Restorer, "_load", class_restorer_load, 1);
2464
+ #endif
2465
+
2466
+ #if RUBY_VERSION_CODE == 180
2467
+ rb_alias(CLASS_OF(rb_mMarshal), rb_intern("_Nodewrap__orig_dump"), rb_intern("dump"));
2468
+ rb_define_singleton_method(rb_mMarshal, "dump", ruby180_marshal_dump, -1);
2469
+ #endif
2470
+
2471
+ rb_define_method(rb_cModule, "_dump", module_dump, 1);
2472
+ rb_define_singleton_method(rb_cModule, "_load", module_load, 1);
2473
+
2474
+ wrapped_nodes = rb_hash_new();
2475
+
2476
+ rb_global_variable(&wrapped_nodes);
2477
+ rb_set_end_proc(wrapped_nodes_end_proc, Qnil);
2478
+
2479
+ /*
2480
+ * Document-module: Noex
2481
+ *
2482
+ * The Noex module contains all the Noex constants from node.h. These
2483
+ * constants can be passed to Module#add_method as modifiers to the
2484
+ * method being added.
2485
+ *
2486
+ * [+PUBLIC+] Method is public.
2487
+ * [+UNDEF+] Method is undefined.
2488
+ * [+PRIVATE+] Method is private.
2489
+ * [+PROTECTED+] Method is protected.
2490
+ *
2491
+ * The following are available in Ruby 1.8 and below:
2492
+ * [+CFUNC+] Method is a C function.
2493
+ *
2494
+ * And these are available in Ruby 1.9 and above:
2495
+ * [+NOSUPER+] ???
2496
+ * [+MASK+] ???
2497
+ */
2498
+ rb_mNoex = rb_define_module("Noex");
2499
+ rb_define_const(rb_mNoex, "PUBLIC", INT2NUM(NOEX_PUBLIC));
2500
+ rb_define_const(rb_mNoex, "UNDEF", INT2NUM(NOEX_UNDEF));
2501
+ rb_define_const(rb_mNoex, "PRIVATE", INT2NUM(NOEX_PRIVATE));
2502
+ rb_define_const(rb_mNoex, "PROTECTED", INT2NUM(NOEX_PROTECTED));
2503
+ #if RUBY_VERSION_CODE < 170
2504
+ rb_define_const(rb_mNoex, "CFUNC", INT2NUM(NOEX_CFUNC));
2505
+ #else
2506
+ rb_define_const(rb_mNoex, "NOSUPER", INT2NUM(NOEX_NOSUPER));
2507
+ rb_define_const(rb_mNoex, "MASK", INT2NUM(NOEX_MASK));
2508
+ #endif
2509
+
2510
+ #if RUBY_VERSION_CODE < 190
2511
+ rb_define_virtual_variable(
2512
+ "$ruby_eval_tree_begin",
2513
+ ruby_eval_tree_begin_getter,
2514
+ ruby_eval_tree_begin_setter);
2515
+ #endif
2516
+
2517
+ rb_define_virtual_variable(
2518
+ "$ruby_eval_tree",
2519
+ ruby_eval_tree_getter,
2520
+ ruby_eval_tree_setter);
2521
+
2522
+ rb_define_method(rb_cModule, "real_superclass", real_superclass, 0);
2523
+ rb_define_method(rb_mKernel, "real_class", real_class, 0);
2524
+ rb_define_method(rb_mKernel, "singleton?", is_singleton, 0);
2525
+ rb_define_method(rb_mKernel, "has_singleton?", has_singleton, 0);
2526
+ rb_define_method(rb_mKernel, "singleton_class", singleton_class, 0);
2527
+
2528
+ #ifdef RUBY_HAS_YARV
2529
+ /* For rdoc: rb_cVM = rb_define_class("VM", rb_cObject); */
2530
+ /* For rdoc: rb_cISeq = rb_define_class_under(rb_cVM, "InstructionSequence", rb_cObject) */
2531
+ rb_define_method(rb_cISeq, "self", iseq_self, 0);
2532
+ rb_define_method(rb_cISeq, "name", iseq_name, 0);
2533
+ rb_define_method(rb_cISeq, "filename", iseq_filename, 0);
2534
+ rb_define_method(rb_cISeq, "local_table", iseq_local_table, 0);
2535
+ rb_define_method(rb_cISeq, "argc", iseq_argc, 0);
2536
+ rb_define_method(rb_cISeq, "arg_simple", iseq_arg_simple, 0);
2537
+ rb_define_method(rb_cISeq, "arg_rest", iseq_arg_rest, 0);
2538
+ rb_define_method(rb_cISeq, "arg_block", iseq_arg_block, 0);
2539
+ rb_define_method(rb_cISeq, "arg_opt_table", iseq_arg_opt_table, 0);
2540
+ rb_define_method(rb_cISeq, "each", iseq_each, 0);
2541
+ rb_define_method(rb_cISeq, "insn_line", iseq_insn_line, 1);
2542
+ rb_include_module(rb_cISeq, rb_mEnumerable);
2543
+ rb_define_method(rb_cISeq, "_dump", iseq_marshal_dump, 1);
2544
+ rb_define_singleton_method(rb_cISeq, "_load", iseq_marshal_load, 1);
2545
+
2546
+ rb_cInstruction = rb_define_class_under(rb_cVM, "Instruction", rb_cObject);
2547
+ rb_define_method(rb_cInstruction, "initialize", instruction_initialize, -1);
2548
+ rb_define_method(rb_cInstruction, "operands", instruction_operands, 0);
2549
+ rb_undef_method(rb_cInstruction, "new");
2550
+
2551
+ define_instruction_subclasses(rb_cInstruction);
2552
+
2553
+ rb_cModulePlaceholder = rb_define_class("ModulePlaceholder", rb_cObject);
2554
+
2555
+ rb_define_const(rb_cVM, "CALL_ARGS_SPLAT_BIT", INT2NUM(VM_CALL_ARGS_SPLAT_BIT));
2556
+ rb_define_const(rb_cVM, "CALL_ARGS_BLOCKARG_BIT", INT2NUM(VM_CALL_ARGS_BLOCKARG_BIT));
2557
+ rb_define_const(rb_cVM, "CALL_FCALL_BIT", INT2NUM(VM_CALL_FCALL_BIT));
2558
+ rb_define_const(rb_cVM, "CALL_VCALL_BIT", INT2NUM(VM_CALL_VCALL_BIT));
2559
+ rb_define_const(rb_cVM, "CALL_TAILCALL_BIT", INT2NUM(VM_CALL_TAILCALL_BIT));
2560
+ rb_define_const(rb_cVM, "CALL_TAILRECURSION_BIT", INT2NUM(VM_CALL_TAILRECURSION_BIT));
2561
+ rb_define_const(rb_cVM, "CALL_SUPER_BIT", INT2NUM(VM_CALL_SUPER_BIT));
2562
+ rb_define_const(rb_cVM, "CALL_SEND_BIT", INT2NUM(VM_CALL_SEND_BIT));
2563
+
2564
+ rb_cInlineCache = rb_define_class_under(rb_cVM, "InlineCache", rb_cNode);
2565
+ rb_define_method(rb_cInlineCache, "klass", inline_cache_klass, 0);
2566
+ rb_define_method(rb_cInlineCache, "value", inline_cache_value, 0);
2567
+ rb_define_method(rb_cInlineCache, "vmstat", inline_cache_vmstat, 0);
2568
+ VALUE inline_cache_members = rb_ary_new();
2569
+ rb_ary_push(inline_cache_members, rb_str_new2("klass"));
2570
+ rb_ary_push(inline_cache_members, rb_str_new2("value"));
2571
+ rb_ary_push(inline_cache_members, rb_str_new2("vmstat"));
2572
+ rb_iv_set(rb_cInlineCache, "__member__", inline_cache_members);
2573
+ rb_define_singleton_method(rb_cInlineCache, "members", node_s_members, 0);
2574
+ #endif
2575
+ }
2576
+