node-marshal 0.1.1 → 0.1.2
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.
- checksums.yaml +4 -4
- data/README.rdoc +11 -2
- data/bin/noderbc +43 -5
- data/ext/node-marshal/node193.h +10 -1
- data/ext/node-marshal/node220.h +10 -1
- data/ext/node-marshal/node230.h +361 -0
- data/ext/node-marshal/nodedump.c +161 -28
- data/ext/node-marshal/nodedump.h +3 -12
- data/ext/node-marshal/nodeinfo.c +125 -2
- data/lib/node-marshal.rb +157 -2
- data/test/test_base.rb +39 -1
- data/test/test_lifegame.rb +2 -2
- data/test/test_obfuscator.rb +36 -0
- data/test/test_qcall.rb +46 -0
- metadata +6 -3
data/ext/node-marshal/nodedump.c
CHANGED
@@ -18,10 +18,43 @@
|
|
18
18
|
static VALUE cNodeObjAddresses, cNodeInfo;
|
19
19
|
|
20
20
|
/*
|
21
|
-
* Part 1.
|
21
|
+
* Part 1. .H files: nodedump functions + parts of Ruby internals
|
22
22
|
*/
|
23
23
|
#include "nodedump.h"
|
24
24
|
|
25
|
+
#ifdef WITH_CUSTOM_RB_GLOBAL_ENTRY
|
26
|
+
/* Custom (and slow) implementation of rb_global_entry internal API for Ruby 2.3
|
27
|
+
(original rb_global_entry API was opened before Ruby 2.3)
|
28
|
+
It uses a hack with the node creation. The main idea of the hack is
|
29
|
+
to create a node from the expression containing only a name of the global variable
|
30
|
+
and extract global entry address from NODE_GVAR u3 "leaf" */
|
31
|
+
static struct rb_global_entry *rb_global_entry(ID id)
|
32
|
+
{
|
33
|
+
NODE *node, *gvar_node;
|
34
|
+
struct rb_global_entry *gentry;
|
35
|
+
/* a) Step 1: create node from the expression consisting only from
|
36
|
+
our global variable */
|
37
|
+
node = rb_compile_string("<compiled>", rb_id2str(id), NUM2INT(1));
|
38
|
+
if (nd_type(node) != NODE_SCOPE)
|
39
|
+
{
|
40
|
+
return NULL;
|
41
|
+
}
|
42
|
+
/* b) Trace the node to the NODE_GVAR */
|
43
|
+
gvar_node = node->u2.node;
|
44
|
+
if (nd_type(gvar_node) == NODE_PRELUDE) /* Present only in 2.3 */
|
45
|
+
{
|
46
|
+
gvar_node = gvar_node->u2.node;
|
47
|
+
}
|
48
|
+
if (nd_type(gvar_node) != NODE_GVAR) /* Error: no GVAR found */
|
49
|
+
{
|
50
|
+
return NULL;
|
51
|
+
}
|
52
|
+
/* c) Get the global entry address and return its address */
|
53
|
+
gentry = gvar_node->u3.entry;
|
54
|
+
return gentry;
|
55
|
+
}
|
56
|
+
#endif
|
57
|
+
|
25
58
|
|
26
59
|
/*
|
27
60
|
* Part 2. Information about the nodes
|
@@ -703,7 +736,8 @@ int count_num_of_nodes(NODE *node, NODE *parent, NODEInfo *info)
|
|
703
736
|
}
|
704
737
|
else if (ut[2] != NT_LONG && ut[2] != NT_NULL)
|
705
738
|
{
|
706
|
-
rb_raise(rb_eArgError, "Invalid child node 3: %d",
|
739
|
+
rb_raise(rb_eArgError, "Invalid child node 3 of node %s: TYPE %d, VALUE %"PRIxPTR,
|
740
|
+
ruby_node_name(nd_type(node)), ut[2], (uintptr_t) (node->u3.value));
|
707
741
|
}
|
708
742
|
|
709
743
|
return num;
|
@@ -861,6 +895,13 @@ void print_node(VALUE str, NODE *node, int tab)
|
|
861
895
|
PRINT_NODE_TAB; rbstr_printf(str, " ");
|
862
896
|
rbstr_printf(str, ">| IDTABLE\n");
|
863
897
|
}
|
898
|
+
else if (ut[i] == NT_ENTRY)
|
899
|
+
{
|
900
|
+
struct rb_global_entry *gentry;
|
901
|
+
gentry = (struct rb_global_entry *) uref[i];
|
902
|
+
PRINT_NODE_TAB; rbstr_printf(str, " ");
|
903
|
+
rbstr_printf(str, ">| [GLOBAL ENTRY PTR=0x%"PRIxPTR" ID=%X]\n", (uintptr_t) gentry->var, gentry->id);
|
904
|
+
}
|
864
905
|
else
|
865
906
|
{
|
866
907
|
PRINT_NODE_TAB; rbstr_printf(str, " ");
|
@@ -1172,8 +1213,8 @@ static VALUE get_hash_strfield(VALUE hash, const char *idtxt)
|
|
1172
1213
|
static VALUE check_hash_magic(VALUE data)
|
1173
1214
|
{
|
1174
1215
|
VALUE val, refval;
|
1175
|
-
// MAGIC signature must be valid
|
1176
|
-
val = get_hash_strfield(data, "MAGIC");
|
1216
|
+
// MAGIC signature must be valid
|
1217
|
+
val = get_hash_strfield(data, "MAGIC");
|
1177
1218
|
if (strcmp("NODEMARSHAL10", RSTRING_PTR(val)))
|
1178
1219
|
rb_raise(rb_eArgError, "Bad value of MAGIC signature");
|
1179
1220
|
// RUBY_PLATFORM signature must match the current platform
|
@@ -1221,7 +1262,7 @@ static VALUE m_nodedump_from_memory(VALUE self, VALUE dump)
|
|
1221
1262
|
rb_raise(rb_eArgError, "num_of_nodes not found");
|
1222
1263
|
}
|
1223
1264
|
else
|
1224
|
-
{
|
1265
|
+
{
|
1225
1266
|
num_of_nodes = FIX2INT(val);
|
1226
1267
|
}
|
1227
1268
|
/* Check "magic" signature and platform identifiers */
|
@@ -1301,6 +1342,46 @@ static VALUE m_nodedump_symbols(VALUE self)
|
|
1301
1342
|
rb_raise(rb_eArgError, "Symbol information not initialized. Run to_hash before reading.");
|
1302
1343
|
}
|
1303
1344
|
|
1345
|
+
/*
|
1346
|
+
* Replace one symbol by another
|
1347
|
+
* (to be used for code obfuscation)
|
1348
|
+
*/
|
1349
|
+
static VALUE m_nodedump_change_symbol(VALUE self, VALUE old_sym, VALUE new_sym)
|
1350
|
+
{
|
1351
|
+
VALUE val_nodehash = rb_iv_get(self, "@nodehash");
|
1352
|
+
VALUE syms, key;
|
1353
|
+
// Check if node is position-independent
|
1354
|
+
// (i.e. with initialized NODEInfo structure that contains
|
1355
|
+
// relocations for symbols)
|
1356
|
+
if (val_nodehash == Qnil)
|
1357
|
+
rb_raise(rb_eArgError, "This node is not preparsed into Hash");
|
1358
|
+
// Check data types of the input array
|
1359
|
+
if (TYPE(old_sym) != T_STRING)
|
1360
|
+
{
|
1361
|
+
rb_raise(rb_eArgError, "old_sym argument must be a string");
|
1362
|
+
}
|
1363
|
+
if (TYPE(new_sym) != T_STRING)
|
1364
|
+
{
|
1365
|
+
rb_raise(rb_eArgError, "new_sym argument must be a string");
|
1366
|
+
}
|
1367
|
+
// Get the symbol table from the Hash
|
1368
|
+
syms = rb_hash_aref(val_nodehash, ID2SYM(rb_intern("symbols")));
|
1369
|
+
if (syms == Qnil)
|
1370
|
+
rb_raise(rb_eArgError, "Preparsed hash has no :symbols field");
|
1371
|
+
// Check if new_sym is present in the symbol table
|
1372
|
+
key = rb_funcall(syms, rb_intern("find_index"), 1, new_sym);
|
1373
|
+
if (key != Qnil)
|
1374
|
+
{
|
1375
|
+
rb_raise(rb_eArgError, "new_sym value must be absent in table of symbols");
|
1376
|
+
}
|
1377
|
+
// Change the symbol in the preparsed Hash
|
1378
|
+
key = rb_funcall(syms, rb_intern("find_index"), 1, old_sym);
|
1379
|
+
if (key == Qnil)
|
1380
|
+
return Qnil;
|
1381
|
+
RARRAY_PTR(syms)[FIX2INT(key)] = new_sym;
|
1382
|
+
return self;
|
1383
|
+
}
|
1384
|
+
|
1304
1385
|
/*
|
1305
1386
|
* Return array with the list of literals
|
1306
1387
|
*/
|
@@ -1308,7 +1389,8 @@ static VALUE m_nodedump_literals(VALUE self)
|
|
1308
1389
|
{
|
1309
1390
|
int i;
|
1310
1391
|
VALUE val_relocs, val_nodeinfo, lits;
|
1311
|
-
// Variant 1: node loaded from file
|
1392
|
+
// Variant 1: node loaded from file. It uses NODEObjAddresses struct
|
1393
|
+
// with the results of Ruby NODE structure parsing.
|
1312
1394
|
val_relocs = rb_iv_get(self, "@obj_addresses");
|
1313
1395
|
if (val_relocs != Qnil)
|
1314
1396
|
{
|
@@ -1317,10 +1399,17 @@ static VALUE m_nodedump_literals(VALUE self)
|
|
1317
1399
|
Data_Get_Struct(val_relocs, NODEObjAddresses, relocs);
|
1318
1400
|
lits = rb_ary_new();
|
1319
1401
|
for (i = 0; i < relocs->lits_len; i++)
|
1320
|
-
|
1402
|
+
{
|
1403
|
+
VALUE val = relocs->lits_adr[i];
|
1404
|
+
int t = TYPE(val);
|
1405
|
+
if (t != T_SYMBOL && t != T_FLOAT && t != T_FIXNUM)
|
1406
|
+
val = rb_funcall(val, rb_intern("dup"), 0);
|
1407
|
+
rb_ary_push(lits, val);
|
1408
|
+
}
|
1321
1409
|
return lits;
|
1322
1410
|
}
|
1323
|
-
// Variant 2: node saved to file (parsed from memory)
|
1411
|
+
// Variant 2: node saved to file (parsed from memory). It uses
|
1412
|
+
// NODEInfo struct that is initialized during node dump parsing.
|
1324
1413
|
val_nodeinfo = rb_iv_get(self, "@nodeinfo");
|
1325
1414
|
if (val_nodeinfo != Qnil)
|
1326
1415
|
{
|
@@ -1337,9 +1426,19 @@ static VALUE m_nodedump_literals(VALUE self)
|
|
1337
1426
|
}
|
1338
1427
|
return lits;
|
1339
1428
|
}
|
1340
|
-
rb_raise(rb_eArgError, "Literals information not initialized. Run to_hash before reading.");
|
1429
|
+
rb_raise(rb_eArgError, "Literals information not initialized. Run to_hash before reading.");
|
1341
1430
|
}
|
1342
1431
|
|
1432
|
+
/*
|
1433
|
+
* Update the array with the list of literals
|
1434
|
+
* (to be used for code obfuscation)
|
1435
|
+
* Warning! This function is a stub!
|
1436
|
+
*/
|
1437
|
+
static VALUE m_nodedump_change_literal(VALUE self, VALUE old_lit, VALUE new_lit)
|
1438
|
+
{
|
1439
|
+
/* TO BE IMPLEMENTED */
|
1440
|
+
return self;
|
1441
|
+
}
|
1343
1442
|
|
1344
1443
|
|
1345
1444
|
/*
|
@@ -1354,7 +1453,13 @@ static VALUE m_nodedump_compile(VALUE self)
|
|
1354
1453
|
VALUE nodename = rb_iv_get(self, "@nodename");
|
1355
1454
|
VALUE filename = rb_iv_get(self, "@filename");
|
1356
1455
|
VALUE filepath = rb_iv_get(self, "@filepath");
|
1456
|
+
#ifndef WITH_RB_ISEQW_NEW
|
1457
|
+
/* For Pre-2.3 */
|
1357
1458
|
return rb_iseq_new_top(node, nodename, filename, filepath, Qfalse);
|
1459
|
+
#else
|
1460
|
+
/* For Ruby 2.3 */
|
1461
|
+
return rb_iseqw_new(rb_iseq_new_top(node, nodename, filename, filepath, Qfalse));
|
1462
|
+
#endif
|
1358
1463
|
}
|
1359
1464
|
|
1360
1465
|
/*
|
@@ -1365,6 +1470,7 @@ static VALUE m_nodedump_from_source(VALUE self, VALUE file)
|
|
1365
1470
|
VALUE line = INT2FIX(1), f, node, filepath;
|
1366
1471
|
const char *fname;
|
1367
1472
|
|
1473
|
+
rb_gc_disable();
|
1368
1474
|
rb_secure(1);
|
1369
1475
|
FilePathValue(file);
|
1370
1476
|
fname = StringValueCStr(file);
|
@@ -1376,7 +1482,12 @@ static VALUE m_nodedump_from_source(VALUE self, VALUE file)
|
|
1376
1482
|
/* Create node from the source */
|
1377
1483
|
f = rb_file_open_str(file, "r");
|
1378
1484
|
node = (VALUE) rb_compile_file(fname, f, NUM2INT(line));
|
1485
|
+
rb_gc_enable();
|
1379
1486
|
rb_iv_set(self, "@node", node);
|
1487
|
+
if ((void *) node == NULL)
|
1488
|
+
{
|
1489
|
+
rb_raise(rb_eArgError, "Error during string parsing");
|
1490
|
+
}
|
1380
1491
|
return self;
|
1381
1492
|
}
|
1382
1493
|
|
@@ -1387,7 +1498,7 @@ static VALUE m_nodedump_from_string(VALUE self, VALUE str)
|
|
1387
1498
|
{
|
1388
1499
|
VALUE line = INT2FIX(1), node;
|
1389
1500
|
const char *fname = "STRING";
|
1390
|
-
Check_Type(str, T_STRING);
|
1501
|
+
Check_Type(str, T_STRING);
|
1391
1502
|
rb_secure(1);
|
1392
1503
|
/* Create empty information about the file */
|
1393
1504
|
rb_iv_set(self, "@nodename", rb_str_new2("<main>"));
|
@@ -1407,6 +1518,10 @@ static VALUE m_nodedump_from_string(VALUE self, VALUE str)
|
|
1407
1518
|
rb_iv_set(self, "@node", node);
|
1408
1519
|
rb_gc_enable();
|
1409
1520
|
rb_gc_start();
|
1521
|
+
if ((void *) node == NULL)
|
1522
|
+
{
|
1523
|
+
rb_raise(rb_eArgError, "Error during string parsing");
|
1524
|
+
}
|
1410
1525
|
return self;
|
1411
1526
|
}
|
1412
1527
|
|
@@ -1492,9 +1607,9 @@ static VALUE m_nodedump_dump_tree_short(VALUE self)
|
|
1492
1607
|
* - <tt>MAGIC</tt> -- NODEMARSHAL10
|
1493
1608
|
* - <tt>RUBY_PLATFORM</tt> -- saved <tt>RUBY_PLATFORM</tt> constant value
|
1494
1609
|
* - <tt>RUBY_VERSION</tt> -- saved <tt>RUBY_VERSION</tt> constant value
|
1495
|
-
*
|
1610
|
+
*
|
1496
1611
|
* <i>Part 2: Program loadable elements.</i>
|
1497
|
-
*
|
1612
|
+
*
|
1498
1613
|
* All loadable elements are arrays. Index of the array element means
|
1499
1614
|
* its identifier that is used in the node tree.
|
1500
1615
|
*
|
@@ -1507,6 +1622,10 @@ static VALUE m_nodedump_dump_tree_short(VALUE self)
|
|
1507
1622
|
* <i>Part 3: Nodes information</i>
|
1508
1623
|
* - <tt>nodes</tt> -- string that contains binary encoded information
|
1509
1624
|
* about the nodes
|
1625
|
+
* - <tt>num_of_nodes</tt> -- number of nodes in the <tt>nodes</tt> field
|
1626
|
+
* - <tt>nodename</tt> -- name of the node (usually "<main>")
|
1627
|
+
* - <tt>filename</tt> -- name (without path) of .rb file used for the node generation
|
1628
|
+
* - <tt>filepath</tt> -- name (with full path) of .rb file used for the node generation
|
1510
1629
|
*/
|
1511
1630
|
static VALUE m_nodedump_to_hash(VALUE self)
|
1512
1631
|
{
|
@@ -1515,18 +1634,29 @@ static VALUE m_nodedump_to_hash(VALUE self)
|
|
1515
1634
|
VALUE ans, num, val_info;
|
1516
1635
|
// DISABLE GARBAGE COLLECTOR (important for dumping)
|
1517
1636
|
rb_gc_disable();
|
1518
|
-
//
|
1519
|
-
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1637
|
+
// Convert the node to the form with relocs (i.e. the information about node)
|
1638
|
+
// if such form is not present
|
1639
|
+
val_info = rb_iv_get(self, "@nodeinfo");
|
1640
|
+
if (val_info == Qnil)
|
1641
|
+
{
|
1642
|
+
val_info = Data_Make_Struct(cNodeInfo, NODEInfo,
|
1643
|
+
NODEInfo_mark, NODEInfo_free, info); // This data envelope cannot exist without NODE
|
1644
|
+
NODEInfo_init(info);
|
1645
|
+
rb_iv_set(self, "@nodeinfo", val_info);
|
1646
|
+
num = INT2FIX(count_num_of_nodes(node, node, info));
|
1647
|
+
rb_iv_set(self, "@nodeinfo_num_of_nodes", num);
|
1648
|
+
// Convert node to NODEInfo structure
|
1649
|
+
ans = NODEInfo_toHash(info);
|
1650
|
+
rb_hash_aset(ans, ID2SYM(rb_intern("num_of_nodes")), num);
|
1651
|
+
rb_hash_aset(ans, ID2SYM(rb_intern("nodename")), rb_iv_get(self, "@nodename"));
|
1652
|
+
rb_hash_aset(ans, ID2SYM(rb_intern("filename")), rb_iv_get(self, "@filename"));
|
1653
|
+
rb_hash_aset(ans, ID2SYM(rb_intern("filepath")), rb_iv_get(self, "@filepath"));
|
1654
|
+
rb_iv_set(self, "@nodehash", ans);
|
1655
|
+
}
|
1656
|
+
else
|
1657
|
+
{
|
1658
|
+
ans = rb_iv_get(self, "@nodehash");
|
1659
|
+
}
|
1530
1660
|
// ENABLE GARBAGE COLLECTOR (important for dumping)
|
1531
1661
|
rb_gc_enable();
|
1532
1662
|
return ans;
|
@@ -1565,7 +1695,7 @@ static VALUE m_nodedump_inspect(VALUE self)
|
|
1565
1695
|
sprintf(str,
|
1566
1696
|
"----- NodeMarshal:0x%"PRIxPTR"\n"
|
1567
1697
|
" num_of_nodes: %d\n nodename: %s\n filepath: %s\n filename: %s\n",
|
1568
|
-
self,
|
1698
|
+
(uintptr_t) (self),
|
1569
1699
|
(num_of_nodes == Qnil) ? -1 : FIX2INT(num_of_nodes),
|
1570
1700
|
(nodename == Qnil) ? "nil" : RSTRING_PTR(nodename),
|
1571
1701
|
(filepath == Qnil) ? "nil" : RSTRING_PTR(filepath),
|
@@ -1767,15 +1897,16 @@ static VALUE m_nodedump_node(VALUE self)
|
|
1767
1897
|
* - Irreversible transformation of Ruby source code to the syntax tree
|
1768
1898
|
* - Representation of syntax tree in binary form dependent from the platform and Ruby version
|
1769
1899
|
* - Simple options for node inspection
|
1770
|
-
* - Ruby 1.9.3 and 2.
|
1900
|
+
* - Ruby 1.9.3, 2.2.x and 2.3.x support
|
1901
|
+
* - Subroutines for custom code obfuscation
|
1771
1902
|
*/
|
1772
1903
|
void Init_nodemarshal()
|
1773
1904
|
{
|
1774
1905
|
static VALUE cNodeMarshal;
|
1775
1906
|
init_nodes_table(nodes_ctbl, NODES_CTBL_SIZE);
|
1776
1907
|
base85r_init_tables();
|
1777
|
-
|
1778
|
-
cNodeMarshal = rb_define_class("NodeMarshal", rb_cObject);
|
1908
|
+
|
1909
|
+
cNodeMarshal = rb_define_class("NodeMarshal", rb_cObject);
|
1779
1910
|
rb_define_singleton_method(cNodeMarshal, "base85r_encode", RUBY_METHOD_FUNC(m_base85r_encode), 1);
|
1780
1911
|
rb_define_singleton_method(cNodeMarshal, "base85r_decode", RUBY_METHOD_FUNC(m_base85r_decode), 1);
|
1781
1912
|
|
@@ -1789,7 +1920,9 @@ void Init_nodemarshal()
|
|
1789
1920
|
// Methods for working with the information about the node
|
1790
1921
|
// a) literals, symbols, generic information
|
1791
1922
|
rb_define_method(cNodeMarshal, "symbols", RUBY_METHOD_FUNC(m_nodedump_symbols), 0);
|
1923
|
+
rb_define_method(cNodeMarshal, "change_symbol", RUBY_METHOD_FUNC(m_nodedump_change_symbol), 2);
|
1792
1924
|
rb_define_method(cNodeMarshal, "literals", RUBY_METHOD_FUNC(m_nodedump_literals), 0);
|
1925
|
+
rb_define_method(cNodeMarshal, "change_literal", RUBY_METHOD_FUNC(m_nodedump_change_literal), 2);
|
1793
1926
|
rb_define_method(cNodeMarshal, "inspect", RUBY_METHOD_FUNC(m_nodedump_inspect), 0);
|
1794
1927
|
rb_define_method(cNodeMarshal, "node", RUBY_METHOD_FUNC(m_nodedump_node), 0);
|
1795
1928
|
// b) node and file names
|
data/ext/node-marshal/nodedump.h
CHANGED
@@ -46,7 +46,9 @@ void check_nodes_child_info(int pos);
|
|
46
46
|
void init_nodes_table(int *nodes_ctbl, int num_of_entries);
|
47
47
|
|
48
48
|
/* Parts of node.h from Ruby source code */
|
49
|
-
#if (RUBY_API_VERSION_MAJOR == 2) && (RUBY_API_VERSION_MINOR ==
|
49
|
+
#if (RUBY_API_VERSION_MAJOR == 2) && (RUBY_API_VERSION_MINOR == 3)
|
50
|
+
#include "node230.h"
|
51
|
+
#elif (RUBY_API_VERSION_MAJOR == 2) && (RUBY_API_VERSION_MINOR == 2)
|
50
52
|
#include "node220.h"
|
51
53
|
#elif (RUBY_API_VERSION_MAJOR == 1) && (RUBY_API_VERSION_MINOR == 9)
|
52
54
|
#include "node193.h"
|
@@ -54,14 +56,3 @@ void init_nodes_table(int *nodes_ctbl, int num_of_entries);
|
|
54
56
|
#include "node220.h"
|
55
57
|
#error Unsupported version of Ruby
|
56
58
|
#endif
|
57
|
-
|
58
|
-
/* Some Ruby internals */
|
59
|
-
#if defined(__cplusplus)
|
60
|
-
extern "C" {
|
61
|
-
#endif
|
62
|
-
extern char *ruby_node_name(int type);
|
63
|
-
extern VALUE rb_iseq_new_top(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE parent);
|
64
|
-
extern VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict);
|
65
|
-
#if defined(__cplusplus)
|
66
|
-
}
|
67
|
-
#endif
|
data/ext/node-marshal/nodeinfo.c
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
* Supported Ruby versions:
|
4
4
|
* - Ruby 1.9.3
|
5
5
|
* - Ruby 2.2.1
|
6
|
+
* - Ruby 2.3.0
|
6
7
|
*
|
7
8
|
* Fragments from Ruby source code are used here
|
8
9
|
* (mainly from node.c, gc.c)
|
@@ -70,6 +71,9 @@ static int nodes_child_info[][4] =
|
|
70
71
|
{NODE_CALL, NT_NODE, NT_ID, NT_NODE},
|
71
72
|
{NODE_FCALL, NT_NULL, NT_ID, NT_NODE},
|
72
73
|
{NODE_VCALL, NT_NULL, NT_ID, NT_NULL},
|
74
|
+
#ifdef NODE_QCALL
|
75
|
+
{NODE_QCALL, NT_NODE, NT_ID, NT_NODE}, /* &. operator from Ruby 2.3 */
|
76
|
+
#endif
|
73
77
|
|
74
78
|
{NODE_SUPER, NT_NULL, NT_NULL, NT_NODE},
|
75
79
|
{NODE_ZSUPER, NT_NULL, NT_NULL, NT_NULL},
|
@@ -93,6 +97,7 @@ static int nodes_child_info[][4] =
|
|
93
97
|
|
94
98
|
{NODE_MATCH, NT_VALUE, NT_NULL, NT_NULL},
|
95
99
|
{NODE_MATCH2, NT_NODE, NT_NODE, NT_NULL},
|
100
|
+
{NODE_MATCH3, NT_NODE, NT_NODE, NT_NULL},
|
96
101
|
|
97
102
|
{NODE_LIT, NT_VALUE, NT_NULL, NT_NULL},
|
98
103
|
{NODE_STR, NT_VALUE, NT_NULL, NT_NULL},
|
@@ -109,7 +114,7 @@ static int nodes_child_info[][4] =
|
|
109
114
|
{NODE_ARGSCAT, NT_NODE, NT_NODE, NT_NULL},
|
110
115
|
{NODE_ARGSPUSH, NT_NODE, NT_NODE, NT_NULL},
|
111
116
|
{NODE_SPLAT, NT_NODE, NT_NULL, NT_NULL},
|
112
|
-
{NODE_BLOCK_PASS, NT_NODE, NT_NODE,
|
117
|
+
{NODE_BLOCK_PASS, NT_NODE, NT_NODE, NT_NODE}, // ???
|
113
118
|
|
114
119
|
{NODE_DEFN, NT_NULL, NT_ID, NT_NODE},
|
115
120
|
{NODE_DEFS, NT_NODE, NT_ID, NT_NODE},
|
@@ -298,7 +303,7 @@ void check_nodes_child_info(int pos)
|
|
298
303
|
default:
|
299
304
|
return;
|
300
305
|
}
|
301
|
-
#elif RUBY_API_VERSION_MAJOR == 2
|
306
|
+
#elif (RUBY_API_VERSION_MAJOR == 2) && (RUBY_API_VERSION_MINOR == 2)
|
302
307
|
/* RUBY 2.2.1 VARIANT */
|
303
308
|
switch (type)
|
304
309
|
{
|
@@ -426,6 +431,124 @@ void check_nodes_child_info(int pos)
|
|
426
431
|
// ruby_node_name(nodes_child_info[pos][0]));
|
427
432
|
return;
|
428
433
|
}
|
434
|
+
#elif (RUBY_API_VERSION_MAJOR == 2) && (RUBY_API_VERSION_MINOR == 3)
|
435
|
+
switch (type)
|
436
|
+
{
|
437
|
+
case NODE_IF: /* 1,2,3 */
|
438
|
+
case NODE_FOR:
|
439
|
+
case NODE_ITER:
|
440
|
+
case NODE_WHEN:
|
441
|
+
case NODE_MASGN:
|
442
|
+
case NODE_RESCUE:
|
443
|
+
case NODE_RESBODY:
|
444
|
+
case NODE_CLASS:
|
445
|
+
case NODE_BLOCK_PASS:
|
446
|
+
isval[1] = 1;
|
447
|
+
/* fall through */
|
448
|
+
case NODE_BLOCK: /* 1,3 */
|
449
|
+
case NODE_ARRAY:
|
450
|
+
case NODE_DSTR:
|
451
|
+
case NODE_DXSTR:
|
452
|
+
case NODE_DREGX:
|
453
|
+
case NODE_DREGX_ONCE:
|
454
|
+
case NODE_ENSURE:
|
455
|
+
case NODE_CALL:
|
456
|
+
case NODE_DEFS:
|
457
|
+
case NODE_OP_ASGN1:
|
458
|
+
isval[0] = 1;
|
459
|
+
/* fall through */
|
460
|
+
case NODE_SUPER: /* 3 */
|
461
|
+
case NODE_FCALL:
|
462
|
+
case NODE_DEFN:
|
463
|
+
case NODE_ARGS_AUX:
|
464
|
+
isval[2] = 1;
|
465
|
+
break;
|
466
|
+
|
467
|
+
case NODE_WHILE: /* 1,2 */
|
468
|
+
case NODE_UNTIL:
|
469
|
+
case NODE_AND:
|
470
|
+
case NODE_OR:
|
471
|
+
case NODE_CASE:
|
472
|
+
case NODE_SCLASS:
|
473
|
+
case NODE_DOT2:
|
474
|
+
case NODE_DOT3:
|
475
|
+
case NODE_FLIP2:
|
476
|
+
case NODE_FLIP3:
|
477
|
+
case NODE_MATCH2:
|
478
|
+
case NODE_MATCH3:
|
479
|
+
case NODE_OP_ASGN_OR:
|
480
|
+
case NODE_OP_ASGN_AND:
|
481
|
+
case NODE_MODULE:
|
482
|
+
case NODE_ALIAS:
|
483
|
+
//case NODE_VALIAS:
|
484
|
+
case NODE_ARGSCAT:
|
485
|
+
isval[0] = 1;
|
486
|
+
/* fall through */
|
487
|
+
case NODE_GASGN: /* 2 */
|
488
|
+
case NODE_LASGN:
|
489
|
+
case NODE_DASGN:
|
490
|
+
case NODE_DASGN_CURR:
|
491
|
+
case NODE_IASGN:
|
492
|
+
case NODE_IASGN2:
|
493
|
+
case NODE_CVASGN:
|
494
|
+
//case NODE_COLON3:
|
495
|
+
case NODE_OPT_N:
|
496
|
+
case NODE_EVSTR:
|
497
|
+
case NODE_UNDEF:
|
498
|
+
case NODE_POSTEXE:
|
499
|
+
isval[1] = 1;
|
500
|
+
break;
|
501
|
+
|
502
|
+
case NODE_HASH: /* 1 */
|
503
|
+
case NODE_LIT:
|
504
|
+
case NODE_STR:
|
505
|
+
case NODE_XSTR:
|
506
|
+
case NODE_DEFINED:
|
507
|
+
case NODE_MATCH:
|
508
|
+
case NODE_RETURN:
|
509
|
+
case NODE_BREAK:
|
510
|
+
case NODE_NEXT:
|
511
|
+
case NODE_YIELD:
|
512
|
+
case NODE_COLON2:
|
513
|
+
case NODE_SPLAT:
|
514
|
+
case NODE_TO_ARY:
|
515
|
+
isval[0] = 1;
|
516
|
+
break;
|
517
|
+
|
518
|
+
case NODE_SCOPE: /* 2,3 */
|
519
|
+
case NODE_CDECL:
|
520
|
+
case NODE_OPT_ARG:
|
521
|
+
isval[1] = 1;
|
522
|
+
isval[2] = 1;
|
523
|
+
break;
|
524
|
+
|
525
|
+
case NODE_ARGS: /* custom */
|
526
|
+
isval[1] = 1;
|
527
|
+
break;
|
528
|
+
|
529
|
+
case NODE_ZARRAY: /* - */
|
530
|
+
case NODE_ZSUPER:
|
531
|
+
case NODE_VCALL:
|
532
|
+
case NODE_GVAR:
|
533
|
+
case NODE_LVAR:
|
534
|
+
case NODE_DVAR:
|
535
|
+
case NODE_IVAR:
|
536
|
+
case NODE_CVAR:
|
537
|
+
case NODE_NTH_REF:
|
538
|
+
case NODE_BACK_REF:
|
539
|
+
case NODE_REDO:
|
540
|
+
case NODE_RETRY:
|
541
|
+
case NODE_SELF:
|
542
|
+
case NODE_NIL:
|
543
|
+
case NODE_TRUE:
|
544
|
+
case NODE_FALSE:
|
545
|
+
case NODE_ERRINFO:
|
546
|
+
case NODE_BLOCK_ARG:
|
547
|
+
break;
|
548
|
+
/* NODE_ALLOCA EXCLUDED */
|
549
|
+
default: /* unlisted NODE */
|
550
|
+
return;
|
551
|
+
}
|
429
552
|
#endif
|
430
553
|
|
431
554
|
for (i = 0; i < 3; i++)
|