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.
@@ -18,10 +18,43 @@
18
18
  static VALUE cNodeObjAddresses, cNodeInfo;
19
19
 
20
20
  /*
21
- * Part 1. "Citations" from Ruby 2.2.1 internal include files
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", ut[2]);
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
- rb_ary_push(lits, rb_funcall(relocs->lits_adr[i], rb_intern("dup"), 0));
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
- // Allocate memory for the information about node
1519
- val_info = Data_Make_Struct(cNodeInfo, NODEInfo,
1520
- NODEInfo_mark, NODEInfo_free, info); // This data envelope cannot exist without NODE
1521
- NODEInfo_init(info);
1522
- rb_iv_set(self, "@nodeinfo", val_info);
1523
- // Convert node to NODEInfo structure
1524
- num = INT2FIX(count_num_of_nodes(node, node, info));
1525
- ans = NODEInfo_toHash(info);
1526
- rb_hash_aset(ans, ID2SYM(rb_intern("num_of_nodes")), num);
1527
- rb_hash_aset(ans, ID2SYM(rb_intern("nodename")), rb_iv_get(self, "@nodename"));
1528
- rb_hash_aset(ans, ID2SYM(rb_intern("filename")), rb_iv_get(self, "@filename"));
1529
- rb_hash_aset(ans, ID2SYM(rb_intern("filepath")), rb_iv_get(self, "@filepath"));
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.2.1 support
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
@@ -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 == 2)
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
@@ -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, NT_VALUE}, // ???
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++)