nodewrap 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING +59 -0
- data/LEGAL +6 -0
- data/LGPL +515 -0
- data/LICENSE +6 -0
- data/README +31 -0
- data/TODO +9 -0
- data/example/README +5 -0
- data/example/simple_client.rb +12 -0
- data/example/simple_server.rb +11 -0
- data/example/triangle_client.rb +7 -0
- data/example/triangle_server.rb +24 -0
- data/ext/MANIFEST +11 -0
- data/ext/builtins.h +25 -0
- data/ext/cached/ruby-1.6.3/COPYING +340 -0
- data/ext/cached/ruby-1.6.3/README +3 -0
- data/ext/cached/ruby-1.6.3/classpath.c +3 -0
- data/ext/cached/ruby-1.6.3/classpath.h +8 -0
- data/ext/cached/ruby-1.6.3/evalinfo.h +62 -0
- data/ext/cached/ruby-1.6.3/global_entry.h +15 -0
- data/ext/cached/ruby-1.6.3/insns_info.c +40 -0
- data/ext/cached/ruby-1.6.3/insns_info.h +19 -0
- data/ext/cached/ruby-1.6.3/node_type_descrip.c +150 -0
- data/ext/cached/ruby-1.6.3/nodeinfo.c +3182 -0
- data/ext/cached/ruby-1.6.3/nodeinfo.h +66 -0
- data/ext/cached/ruby-1.6.4/COPYING +340 -0
- data/ext/cached/ruby-1.6.4/README +3 -0
- data/ext/cached/ruby-1.6.4/classpath.c +3 -0
- data/ext/cached/ruby-1.6.4/classpath.h +8 -0
- data/ext/cached/ruby-1.6.4/evalinfo.h +62 -0
- data/ext/cached/ruby-1.6.4/global_entry.h +15 -0
- data/ext/cached/ruby-1.6.4/insns_info.c +40 -0
- data/ext/cached/ruby-1.6.4/insns_info.h +19 -0
- data/ext/cached/ruby-1.6.4/node_type_descrip.c +150 -0
- data/ext/cached/ruby-1.6.4/nodeinfo.c +3182 -0
- data/ext/cached/ruby-1.6.4/nodeinfo.h +66 -0
- data/ext/cached/ruby-1.6.5/COPYING +56 -0
- data/ext/cached/ruby-1.6.5/GPL +340 -0
- data/ext/cached/ruby-1.6.5/LEGAL +325 -0
- data/ext/cached/ruby-1.6.5/LGPL +504 -0
- data/ext/cached/ruby-1.6.5/README +3 -0
- data/ext/cached/ruby-1.6.5/classpath.c +3 -0
- data/ext/cached/ruby-1.6.5/classpath.h +8 -0
- data/ext/cached/ruby-1.6.5/evalinfo.h +63 -0
- data/ext/cached/ruby-1.6.5/global_entry.h +15 -0
- data/ext/cached/ruby-1.6.5/insns_info.c +40 -0
- data/ext/cached/ruby-1.6.5/insns_info.h +19 -0
- data/ext/cached/ruby-1.6.5/node_type_descrip.c +150 -0
- data/ext/cached/ruby-1.6.5/nodeinfo.c +3182 -0
- data/ext/cached/ruby-1.6.5/nodeinfo.h +66 -0
- data/ext/cached/ruby-1.6.7/COPYING +56 -0
- data/ext/cached/ruby-1.6.7/GPL +340 -0
- data/ext/cached/ruby-1.6.7/LEGAL +308 -0
- data/ext/cached/ruby-1.6.7/LGPL +504 -0
- data/ext/cached/ruby-1.6.7/README +3 -0
- data/ext/cached/ruby-1.6.7/classpath.c +3 -0
- data/ext/cached/ruby-1.6.7/classpath.h +8 -0
- data/ext/cached/ruby-1.6.7/evalinfo.h +63 -0
- data/ext/cached/ruby-1.6.7/global_entry.h +15 -0
- data/ext/cached/ruby-1.6.7/insns_info.c +40 -0
- data/ext/cached/ruby-1.6.7/insns_info.h +19 -0
- data/ext/cached/ruby-1.6.7/node_type_descrip.c +150 -0
- data/ext/cached/ruby-1.6.7/nodeinfo.c +3182 -0
- data/ext/cached/ruby-1.6.7/nodeinfo.h +66 -0
- data/ext/cached/ruby-1.6.8/COPYING +56 -0
- data/ext/cached/ruby-1.6.8/GPL +340 -0
- data/ext/cached/ruby-1.6.8/LEGAL +308 -0
- data/ext/cached/ruby-1.6.8/LGPL +504 -0
- data/ext/cached/ruby-1.6.8/README +3 -0
- data/ext/cached/ruby-1.6.8/classpath.c +3 -0
- data/ext/cached/ruby-1.6.8/classpath.h +8 -0
- data/ext/cached/ruby-1.6.8/evalinfo.h +63 -0
- data/ext/cached/ruby-1.6.8/global_entry.h +15 -0
- data/ext/cached/ruby-1.6.8/insns_info.c +40 -0
- data/ext/cached/ruby-1.6.8/insns_info.h +19 -0
- data/ext/cached/ruby-1.6.8/node_type_descrip.c +150 -0
- data/ext/cached/ruby-1.6.8/nodeinfo.c +3182 -0
- data/ext/cached/ruby-1.6.8/nodeinfo.h +66 -0
- data/ext/cached/ruby-1.8.0/COPYING +56 -0
- data/ext/cached/ruby-1.8.0/GPL +340 -0
- data/ext/cached/ruby-1.8.0/LEGAL +371 -0
- data/ext/cached/ruby-1.8.0/LGPL +504 -0
- data/ext/cached/ruby-1.8.0/README +3 -0
- data/ext/cached/ruby-1.8.0/classpath.c +27 -0
- data/ext/cached/ruby-1.8.0/classpath.h +14 -0
- data/ext/cached/ruby-1.8.0/evalinfo.h +65 -0
- data/ext/cached/ruby-1.8.0/global_entry.h +10 -0
- data/ext/cached/ruby-1.8.0/insns_info.c +40 -0
- data/ext/cached/ruby-1.8.0/insns_info.h +19 -0
- data/ext/cached/ruby-1.8.0/node_type_descrip.c +150 -0
- data/ext/cached/ruby-1.8.0/nodeinfo.c +3199 -0
- data/ext/cached/ruby-1.8.0/nodeinfo.h +66 -0
- data/ext/cached/ruby-1.8.1/COPYING +56 -0
- data/ext/cached/ruby-1.8.1/GPL +340 -0
- data/ext/cached/ruby-1.8.1/LEGAL +371 -0
- data/ext/cached/ruby-1.8.1/LGPL +504 -0
- data/ext/cached/ruby-1.8.1/README +3 -0
- data/ext/cached/ruby-1.8.1/classpath.c +27 -0
- data/ext/cached/ruby-1.8.1/classpath.h +14 -0
- data/ext/cached/ruby-1.8.1/evalinfo.h +59 -0
- data/ext/cached/ruby-1.8.1/global_entry.h +10 -0
- data/ext/cached/ruby-1.8.1/insns_info.c +40 -0
- data/ext/cached/ruby-1.8.1/insns_info.h +19 -0
- data/ext/cached/ruby-1.8.1/node_type_descrip.c +150 -0
- data/ext/cached/ruby-1.8.1/nodeinfo.c +3199 -0
- data/ext/cached/ruby-1.8.1/nodeinfo.h +66 -0
- data/ext/cached/ruby-1.8.2/COPYING +56 -0
- data/ext/cached/ruby-1.8.2/GPL +340 -0
- data/ext/cached/ruby-1.8.2/LEGAL +371 -0
- data/ext/cached/ruby-1.8.2/LGPL +504 -0
- data/ext/cached/ruby-1.8.2/README +3 -0
- data/ext/cached/ruby-1.8.2/classpath.c +45 -0
- data/ext/cached/ruby-1.8.2/classpath.h +17 -0
- data/ext/cached/ruby-1.8.2/evalinfo.h +60 -0
- data/ext/cached/ruby-1.8.2/global_entry.h +10 -0
- data/ext/cached/ruby-1.8.2/insns_info.c +40 -0
- data/ext/cached/ruby-1.8.2/insns_info.h +19 -0
- data/ext/cached/ruby-1.8.2/node_type_descrip.c +150 -0
- data/ext/cached/ruby-1.8.2/nodeinfo.c +3199 -0
- data/ext/cached/ruby-1.8.2/nodeinfo.h +66 -0
- data/ext/cached/ruby-1.8.3/COPYING +56 -0
- data/ext/cached/ruby-1.8.3/GPL +340 -0
- data/ext/cached/ruby-1.8.3/LEGAL +370 -0
- data/ext/cached/ruby-1.8.3/LGPL +504 -0
- data/ext/cached/ruby-1.8.3/README +3 -0
- data/ext/cached/ruby-1.8.3/classpath.c +45 -0
- data/ext/cached/ruby-1.8.3/classpath.h +17 -0
- data/ext/cached/ruby-1.8.3/evalinfo.h +61 -0
- data/ext/cached/ruby-1.8.3/global_entry.h +10 -0
- data/ext/cached/ruby-1.8.3/insns_info.c +40 -0
- data/ext/cached/ruby-1.8.3/insns_info.h +19 -0
- data/ext/cached/ruby-1.8.3/node_type_descrip.c +150 -0
- data/ext/cached/ruby-1.8.3/nodeinfo.c +3199 -0
- data/ext/cached/ruby-1.8.3/nodeinfo.h +66 -0
- data/ext/cached/ruby-1.8.4/COPYING +56 -0
- data/ext/cached/ruby-1.8.4/GPL +340 -0
- data/ext/cached/ruby-1.8.4/LEGAL +370 -0
- data/ext/cached/ruby-1.8.4/LGPL +504 -0
- data/ext/cached/ruby-1.8.4/README +3 -0
- data/ext/cached/ruby-1.8.4/classpath.c +45 -0
- data/ext/cached/ruby-1.8.4/classpath.h +17 -0
- data/ext/cached/ruby-1.8.4/evalinfo.h +61 -0
- data/ext/cached/ruby-1.8.4/global_entry.h +10 -0
- data/ext/cached/ruby-1.8.4/insns_info.c +40 -0
- data/ext/cached/ruby-1.8.4/insns_info.h +19 -0
- data/ext/cached/ruby-1.8.4/node_type_descrip.c +150 -0
- data/ext/cached/ruby-1.8.4/nodeinfo.c +3199 -0
- data/ext/cached/ruby-1.8.4/nodeinfo.h +66 -0
- data/ext/cached/ruby-1.8.5/COPYING +56 -0
- data/ext/cached/ruby-1.8.5/GPL +340 -0
- data/ext/cached/ruby-1.8.5/LEGAL +370 -0
- data/ext/cached/ruby-1.8.5/LGPL +504 -0
- data/ext/cached/ruby-1.8.5/README +3 -0
- data/ext/cached/ruby-1.8.5/classpath.c +45 -0
- data/ext/cached/ruby-1.8.5/classpath.h +17 -0
- data/ext/cached/ruby-1.8.5/evalinfo.h +61 -0
- data/ext/cached/ruby-1.8.5/global_entry.h +10 -0
- data/ext/cached/ruby-1.8.5/insns_info.c +40 -0
- data/ext/cached/ruby-1.8.5/insns_info.h +19 -0
- data/ext/cached/ruby-1.8.5/node_type_descrip.c +150 -0
- data/ext/cached/ruby-1.8.5/nodeinfo.c +3187 -0
- data/ext/cached/ruby-1.8.5/nodeinfo.h +64 -0
- data/ext/cached/ruby-1.8.6/COPYING +56 -0
- data/ext/cached/ruby-1.8.6/GPL +340 -0
- data/ext/cached/ruby-1.8.6/LEGAL +370 -0
- data/ext/cached/ruby-1.8.6/LGPL +504 -0
- data/ext/cached/ruby-1.8.6/README +3 -0
- data/ext/cached/ruby-1.8.6/classpath.c +45 -0
- data/ext/cached/ruby-1.8.6/classpath.h +17 -0
- data/ext/cached/ruby-1.8.6/evalinfo.h +61 -0
- data/ext/cached/ruby-1.8.6/global_entry.h +10 -0
- data/ext/cached/ruby-1.8.6/insns_info.c +40 -0
- data/ext/cached/ruby-1.8.6/insns_info.h +19 -0
- data/ext/cached/ruby-1.8.6/node_type_descrip.c +150 -0
- data/ext/cached/ruby-1.8.6/nodeinfo.c +3187 -0
- data/ext/cached/ruby-1.8.6/nodeinfo.h +64 -0
- data/ext/classpath.c +42 -0
- data/ext/classpath.c.rpp +28 -0
- data/ext/classpath.h +17 -0
- data/ext/classpath.h.rpp +35 -0
- data/ext/evalinfo.h +21 -0
- data/ext/evalinfo.h.rpp +49 -0
- data/ext/extconf.rb +68 -0
- data/ext/generate.rb +201 -0
- data/ext/generate_cached.rb +49 -0
- data/ext/global_entry.h +10 -0
- data/ext/global_entry.h.rpp +25 -0
- data/ext/insns_info.c +6079 -0
- data/ext/insns_info.c.rpp +210 -0
- data/ext/insns_info.h +819 -0
- data/ext/insns_info.h.rpp +50 -0
- data/ext/node_type_descrip.c +148 -0
- data/ext/node_type_descrip.c.rpp +72 -0
- data/ext/node_type_descrip.h +17 -0
- data/ext/node_type_descrip.rb +169 -0
- data/ext/nodeinfo.c +3164 -0
- data/ext/nodeinfo.c.rpp +519 -0
- data/ext/nodeinfo.h +67 -0
- data/ext/nodeinfo.h.rpp +27 -0
- data/ext/nodewrap.c +2576 -0
- data/ext/nodewrap.h +20 -0
- data/ext/read_node_h.rb +19 -0
- data/ext/ruby_source_dir.rb +15 -0
- data/ext/ruby_version.h +12 -0
- data/ext/ruby_version_code.rb +16 -0
- data/ext/rubypp.rb +97 -0
- data/ext/test.rb +15 -0
- data/generate_rdoc.rb +33 -0
- data/install.rb +1022 -0
- data/lib/as_code.rb +347 -0
- data/lib/as_expression.rb +657 -0
- data/lib/bytedecoder.rb +848 -0
- data/lib/classtree.rb +54 -0
- data/lib/methodsig.rb +266 -0
- data/lib/node_to_a.rb +34 -0
- data/lib/nodepp.rb +71 -0
- data/lib/nwdebug.rb +18 -0
- data/lib/nwdump.rb +53 -0
- data/lib/nwobfusc.rb +57 -0
- data/lib/procsig.rb +182 -0
- data/lib/test.rb +8 -0
- data/metaconfig +10 -0
- data/post-config.rb +53 -0
- data/post-setup.rb +9 -0
- data/pre-config.rb +1 -0
- data/run_tests.rb +48 -0
- data/test/expression_samples.rb +158 -0
- data/test/node_samples.rb +122 -0
- data/test/test.rb +39 -0
- data/test/test2.rb +7 -0
- data/test/test3.rb +5 -0
- data/test/test4.rb +5 -0
- data/test/test_as_code.rb +249 -0
- data/test/test_as_expression.rb +222 -0
- data/test/test_methodsig.rb +189 -0
- data/test/test_nodewrap.rb +369 -0
- metadata +286 -0
data/ext/nodeinfo.h
ADDED
|
@@ -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
|
+
|
data/ext/nodeinfo.h.rpp
ADDED
|
@@ -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
|
+
|
data/ext/nodewrap.c
ADDED
|
@@ -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
|
+
|