diff options
-rw-r--r-- | ChangeLog | 2 | ||||
-rw-r--r-- | eval.c | 68 | ||||
-rw-r--r-- | ext/extmk.rb.nt | 2 | ||||
-rw-r--r-- | node.h | 4 | ||||
-rw-r--r-- | parse.c | 593 | ||||
-rw-r--r-- | parse.y | 21 | ||||
-rw-r--r-- | regex.c | 2721 | ||||
-rw-r--r-- | sample/test.rb | 27 | ||||
-rw-r--r-- | win32/ruby.def | 1 |
9 files changed, 1710 insertions, 1729 deletions
@@ -1,5 +1,7 @@ Fri Apr 9 17:45:11 1999 Yukihiro Matsumoto <matz@netlab.co.jp> + * parse.y (rb_compile_string): bug for nested eval(). + * regex.c (re_match): should pop non-greedy stack items on failure, after best_regs are fixed. @@ -416,7 +416,6 @@ struct BLOCK { struct BLOCK *prev; }; static struct BLOCK *ruby_block; -static struct BLOCK *ruby_calling_block; #define PUSH_BLOCK(v,b) { \ struct BLOCK _block; \ @@ -443,12 +442,9 @@ static struct BLOCK *ruby_calling_block; struct BLOCK * volatile _old; \ struct BLOCK * volatile _old_call; \ _old = ruby_block; \ - _old_call = ruby_calling_block; \ - ruby_calling_block = b; \ ruby_block = b; #define POP_BLOCK2() \ - ruby_calling_block = _old_call; \ ruby_block = _old; \ } @@ -476,6 +472,14 @@ new_dvar(id, value) return vars; } +static void +mark_dvar(vars) + struct RVarmap *vars; +{ + ruby_dyna_vars = new_dvar(0, 0); + ruby_dyna_vars->next = vars; +} + VALUE rb_dvar_defined(id) ID id; @@ -512,14 +516,16 @@ rb_dvar_push(id, value) ruby_dyna_vars = new_dvar(id, value); } -void -rb_dvar_asgn(id, value) +static void +dvar_asgn(id, value, push) ID id; VALUE value; + int push; { struct RVarmap *vars = ruby_dyna_vars; while (vars) { + if (push && vars->id == 0) break; if (vars->id == id) { vars->val = value; return; @@ -527,7 +533,14 @@ rb_dvar_asgn(id, value) vars = vars->next; } rb_dvar_push(id, value); - return; +} + +void +rb_dvar_asgn(id, value) + ID id; + VALUE value; +{ + dvar_asgn(id, value, 0); } static void @@ -535,9 +548,16 @@ dvar_asgn_push(id, value) ID id; VALUE value; { - rb_dvar_asgn(id, value); - if (ruby_calling_block) { - ruby_calling_block->d_vars = ruby_dyna_vars; + struct RVarmap* vars = 0; + + if (ruby_dyna_vars && ruby_dyna_vars->id == 0) { + vars = ruby_dyna_vars; + ruby_dyna_vars = ruby_dyna_vars->next; + } + dvar_asgn(id, value, 1); + if (vars) { + vars->next = ruby_dyna_vars; + ruby_dyna_vars = vars; } } @@ -653,7 +673,7 @@ static VALUE ruby_wrapper; /* security wrapper */ static VALUE rb_eval _((VALUE,NODE*)); static VALUE eval _((VALUE,VALUE,VALUE,char*,int)); -static NODE *compile _((VALUE)); +static NODE *compile _((VALUE, char*, int)); static VALUE rb_yield_0 _((VALUE, VALUE, VALUE)); static VALUE rb_call _((VALUE,VALUE,ID,int,VALUE*,int)); @@ -2451,7 +2471,9 @@ rb_eval(self, node) case NODE_EVSTR: ruby_sourceline = nd_line(node); ruby_in_eval++; - list->nd_head = compile(list->nd_head->nd_lit); + list->nd_head = compile(list->nd_head->nd_lit, + ruby_sourcefile, + ruby_sourceline); ruby_eval_tree = 0; ruby_in_eval--; if (ruby_nerrs > 0) { @@ -3106,7 +3128,7 @@ rb_yield_0(val, self, klass) old_scope = ruby_scope; ruby_scope = block->scope; ruby_block = block->prev; - ruby_dyna_vars = block->d_vars; + mark_dvar(block->d_vars); ruby_class = klass?klass:block->klass; if (!self) self = block->self; node = block->body; @@ -4086,13 +4108,15 @@ rb_frame_last_func() } static NODE* -compile(src) +compile(src, file, line) VALUE src; + char *file; + int line; { NODE *node; Check_Type(src, T_STRING); - node = rb_compile_string("(eval)", src); + node = rb_compile_string(file, src, line); if (ruby_nerrs == 0) return node; return 0; @@ -4135,8 +4159,6 @@ eval(self, src, scope, file, line) ruby_frame = &(frame); old_scope = ruby_scope; ruby_scope = data->scope; - old_call_block = ruby_calling_block; - ruby_calling_block = data; old_block = ruby_block; ruby_block = data->prev; old_d_vars = ruby_dyna_vars; @@ -4161,9 +4183,7 @@ eval(self, src, scope, file, line) } PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { - ruby_sourcefile = file; - ruby_sourceline = line - 1; - compile(src); + compile(src, file, line); if (ruby_nerrs > 0) { compile_error(0); } @@ -4178,9 +4198,6 @@ eval(self, src, scope, file, line) FL_SET(old_scope, SCOPE_DONT_RECYCLE); ruby_scope = old_scope; ruby_block = old_block; - ruby_calling_block = old_call_block; - data->d_vars = ruby_dyna_vars; - ruby_dyna_vars = old_d_vars; data->vmode = scope_vmode; /* write back visibility mode */ scope_vmode = old_vmode; } @@ -4235,7 +4252,7 @@ rb_f_eval(argc, argv, self) } Check_SafeStr(src); - return eval(self, src, scope, file, line); + return eval(self, src, scope, file, line-1); } static VALUE @@ -5738,7 +5755,6 @@ struct thread { struct SCOPE *scope; struct RVarmap *dyna_vars; struct BLOCK *block; - struct BLOCK *cblock; struct iter *iter; struct tag *tag; VALUE klass; @@ -5899,7 +5915,6 @@ rb_thread_save_context(th) th->wrapper = ruby_wrapper; th->dyna_vars = ruby_dyna_vars; th->block = ruby_block; - th->cblock = ruby_calling_block; th->misc = scope_vmode | (rb_trap_immediate<<8); th->iter = ruby_iter; th->tag = prot_tag; @@ -5970,7 +5985,6 @@ rb_thread_restore_context(th, exit) ruby_wrapper = th->wrapper; ruby_dyna_vars = th->dyna_vars; ruby_block = th->block; - ruby_calling_block = th->cblock; scope_vmode = th->misc&SCOPE_MASK; rb_trap_immediate = th->misc>>8; ruby_iter = th->iter; diff --git a/ext/extmk.rb.nt b/ext/extmk.rb.nt index 5836e5c681..dd979a45a3 100644 --- a/ext/extmk.rb.nt +++ b/ext/extmk.rb.nt @@ -451,7 +451,7 @@ if $extlist.size > 0 if File.exist?(l) $extinit += format("\ \tInit_%s();\n\ -\trb_provide(\"%s.o\");\n\ +\trb_provide(\"%s.so\");\n\ ", s, s) $extobjs += "ext/" #$extobjs += f # *.obj @@ -331,8 +331,8 @@ VALUE rb_method_booundp(); #define NOEX_PRIVATE 2 #define NOEX_PROTECTED 4 -NODE *rb_compile_cstr _((const char*, const char*, int)); -NODE *rb_compile_string _((const char*, VALUE)); +NODE *rb_compile_cstr _((const char*, const char*, int, int)); +NODE *rb_compile_string _((const char*, VALUE, int)); NODE *rb_compile_file _((const char*, VALUE, int)); void rb_add_method _((VALUE, ID, NODE *, int)); @@ -418,43 +418,43 @@ static const short yyrhs[] = { -1, #if YYDEBUG != 0 static const short yyrline[] = { 0, - 238, 247, 265, 271, 272, 276, 280, 285, 286, 287, - 292, 298, 307, 312, 318, 324, 330, 340, 350, 357, - 364, 372, 377, 379, 385, 392, 397, 398, 402, 406, - 411, 416, 418, 423, 429, 435, 443, 444, 449, 450, - 455, 459, 463, 467, 471, 476, 477, 482, 487, 491, - 496, 500, 504, 508, 514, 518, 522, 526, 532, 536, - 538, 539, 540, 541, 546, 552, 556, 557, 561, 562, - 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, - 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, - 583, 584, 585, 586, 587, 589, 589, 589, 589, 590, - 590, 590, 590, 590, 590, 590, 591, 591, 591, 591, - 591, 591, 591, 592, 592, 592, 592, 592, 592, 592, - 593, 593, 593, 593, 593, 593, 593, 594, 594, 594, - 594, 594, 594, 595, 595, 597, 602, 603, 618, 633, - 644, 655, 660, 664, 668, 672, 676, 680, 684, 688, - 692, 696, 700, 704, 708, 712, 716, 720, 724, 728, - 732, 736, 740, 744, 748, 752, 757, 761, 765, 769, - 773, 777, 778, 782, 788, 793, 801, 802, 804, 809, - 813, 817, 822, 826, 831, 836, 841, 845, 850, 855, - 857, 863, 867, 869, 870, 872, 877, 883, 895, 900, - 906, 920, 921, 923, 927, 932, 936, 940, 941, 945, - 946, 947, 948, 949, 954, 962, 966, 973, 979, 985, - 990, 994, 998, 998, 1003, 1007, 1012, 1013, 1022, 1031, - 1040, 1048, 1056, 1064, 1072, 1092, 1096, 1106, 1114, 1121, - 1129, 1138, 1146, 1154, 1163, 1164, 1171, 1179, 1183, 1187, - 1191, 1196, 1197, 1198, 1200, 1201, 1203, 1204, 1213, 1214, - 1219, 1220, 1222, 1223, 1227, 1231, 1236, 1241, 1249, 1254, - 1261, 1265, 1269, 1273, 1274, 1276, 1286, 1291, 1297, 1303, - 1309, 1314, 1321, 1330, 1331, 1333, 1340, 1341, 1346, 1352, - 1353, 1355, 1362, 1364, 1365, 1370, 1371, 1375, 1377, 1378, - 1379, 1381, 1382, 1384, 1385, 1386, 1387, 1388, 1389, 1390, - 1391, 1392, 1393, 1395, 1400, 1401, 1403, 1407, 1411, 1415, - 1417, 1422, 1427, 1431, 1435, 1439, 1443, 1447, 1451, 1455, - 1459, 1464, 1471, 1479, 1486, 1491, 1496, 1503, 1508, 1512, - 1514, 1527, 1545, 1546, 1550, 1558, 1559, 1564, 1569, 1570, - 1571, 1573, 1574, 1576, 1577, 1579, 1580, 1582, 1583, 1585, - 1586, 1587, 1589, 1590, 1592, 1593, 1595 + 238, 247, 266, 272, 273, 277, 281, 286, 287, 288, + 293, 299, 308, 313, 319, 325, 331, 341, 351, 358, + 365, 373, 378, 380, 386, 393, 398, 399, 403, 407, + 412, 417, 419, 424, 430, 436, 444, 445, 450, 451, + 456, 460, 464, 468, 472, 477, 478, 483, 488, 492, + 497, 501, 505, 509, 515, 519, 523, 527, 533, 537, + 539, 540, 541, 542, 547, 553, 557, 558, 562, 563, + 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, + 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, + 584, 585, 586, 587, 588, 590, 590, 590, 590, 591, + 591, 591, 591, 591, 591, 591, 592, 592, 592, 592, + 592, 592, 592, 593, 593, 593, 593, 593, 593, 593, + 594, 594, 594, 594, 594, 594, 594, 595, 595, 595, + 595, 595, 595, 596, 596, 598, 603, 604, 619, 634, + 645, 656, 661, 665, 669, 673, 677, 681, 685, 689, + 693, 697, 701, 705, 709, 713, 717, 721, 725, 729, + 733, 737, 741, 745, 749, 753, 758, 762, 766, 770, + 774, 778, 779, 783, 789, 794, 802, 803, 805, 810, + 814, 818, 823, 827, 832, 837, 842, 846, 851, 856, + 858, 864, 868, 870, 871, 873, 878, 884, 896, 901, + 907, 921, 922, 924, 928, 933, 937, 941, 942, 946, + 947, 948, 949, 950, 955, 963, 967, 974, 980, 986, + 991, 995, 999, 999, 1004, 1008, 1013, 1014, 1023, 1032, + 1041, 1049, 1057, 1065, 1073, 1093, 1097, 1107, 1115, 1122, + 1130, 1139, 1147, 1155, 1164, 1165, 1172, 1180, 1184, 1188, + 1192, 1197, 1198, 1199, 1201, 1202, 1204, 1205, 1214, 1215, + 1220, 1221, 1223, 1224, 1228, 1232, 1237, 1242, 1250, 1255, + 1262, 1266, 1270, 1274, 1275, 1277, 1287, 1292, 1298, 1304, + 1310, 1315, 1322, 1331, 1332, 1334, 1341, 1342, 1347, 1353, + 1354, 1356, 1363, 1365, 1366, 1371, 1372, 1376, 1378, 1379, + 1380, 1382, 1383, 1385, 1386, 1387, 1388, 1389, 1390, 1391, + 1392, 1393, 1394, 1396, 1401, 1402, 1404, 1408, 1412, 1416, + 1418, 1423, 1428, 1432, 1436, 1440, 1444, 1448, 1452, 1456, + 1460, 1465, 1472, 1480, 1487, 1492, 1497, 1504, 1509, 1513, + 1515, 1528, 1546, 1547, 1551, 1559, 1560, 1565, 1570, 1571, + 1572, 1574, 1575, 1577, 1578, 1580, 1581, 1583, 1584, 1586, + 1587, 1588, 1590, 1591, 1593, 1594, 1596 }; #endif @@ -2632,7 +2632,8 @@ case 1: case 2: #line 247 "parse.y" { - if (yyvsp[0].node) { /* last expression is void */ + if (yyvsp[0].node && !compile_for_eval) { + /* last expression should not be void */ if (nd_type(yyvsp[0].node) != NODE_BLOCK) void_expr(yyvsp[0].node); else { NODE *node = yyvsp[0].node; @@ -2650,36 +2651,36 @@ case 2: ; break;} case 3: -#line 266 "parse.y" +#line 267 "parse.y" { void_stmts(yyvsp[-1].node); yyval.node = yyvsp[-1].node; ; break;} case 5: -#line 273 "parse.y" +#line 274 "parse.y" { yyval.node = newline_node(yyvsp[0].node); ; break;} case 6: -#line 277 "parse.y" +#line 278 "parse.y" { yyval.node = block_append(yyvsp[-2].node, newline_node(yyvsp[0].node)); ; break;} case 7: -#line 281 "parse.y" +#line 282 "parse.y" { yyval.node = yyvsp[0].node; ; break;} case 9: -#line 286 "parse.y" +#line 287 "parse.y" {lex_state = EXPR_FNAME;; break;} case 10: -#line 287 "parse.y" +#line 288 "parse.y" { if (cur_mid || in_single) yyerror("alias within method"); @@ -2687,7 +2688,7 @@ case 10: ; break;} case 11: -#line 293 "parse.y" +#line 294 "parse.y" { if (cur_mid || in_single) yyerror("alias within method"); @@ -2695,7 +2696,7 @@ case 11: ; break;} case 12: -#line 299 "parse.y" +#line 300 "parse.y" { char buf[3]; @@ -2706,14 +2707,14 @@ case 12: ; break;} case 13: -#line 308 "parse.y" +#line 309 "parse.y" { yyerror("can't make alias for the number variables"); yyval.node = 0; ; break;} case 14: -#line 313 "parse.y" +#line 314 "parse.y" { if (cur_mid || in_single) yyerror("undef within method"); @@ -2721,7 +2722,7 @@ case 14: ; break;} case 15: -#line 319 "parse.y" +#line 320 "parse.y" { value_expr(yyvsp[0].node); yyval.node = NEW_IF(cond(yyvsp[0].node), yyvsp[-2].node, 0); @@ -2729,7 +2730,7 @@ case 15: ; break;} case 16: -#line 325 "parse.y" +#line 326 "parse.y" { value_expr(yyvsp[0].node); yyval.node = NEW_UNLESS(cond(yyvsp[0].node), yyvsp[-2].node, 0); @@ -2737,7 +2738,7 @@ case 16: ; break;} case 17: -#line 331 "parse.y" +#line 332 "parse.y" { value_expr(yyvsp[0].node); if (nd_type(yyvsp[-2].node) == NODE_BEGIN) { @@ -2749,7 +2750,7 @@ case 17: ; break;} case 18: -#line 341 "parse.y" +#line 342 "parse.y" { value_expr(yyvsp[0].node); if (nd_type(yyvsp[-2].node) == NODE_BEGIN) { @@ -2761,7 +2762,7 @@ case 18: ; break;} case 19: -#line 351 "parse.y" +#line 352 "parse.y" { if (cur_mid || in_single) { yyerror("BEGIN in method"); @@ -2770,7 +2771,7 @@ case 19: ; break;} case 20: -#line 358 "parse.y" +#line 359 "parse.y" { ruby_eval_tree_begin = block_append(ruby_eval_tree_begin, NEW_PREEXE(yyvsp[-1].node)); @@ -2779,7 +2780,7 @@ case 20: ; break;} case 21: -#line 365 "parse.y" +#line 366 "parse.y" { if (compile_for_eval && (cur_mid || in_single)) { yyerror("END in method; use at_exit"); @@ -2789,14 +2790,14 @@ case 21: ; break;} case 22: -#line 373 "parse.y" +#line 374 "parse.y" { value_expr(yyvsp[0].node); yyval.node = node_assign(yyvsp[-2].node, yyvsp[0].node); ; break;} case 24: -#line 380 "parse.y" +#line 381 "parse.y" { value_expr(yyvsp[0].node); yyvsp[-2].node->nd_value = yyvsp[0].node; @@ -2804,7 +2805,7 @@ case 24: ; break;} case 25: -#line 386 "parse.y" +#line 387 "parse.y" { value_expr(yyvsp[0].node); if (!compile_for_eval && !cur_mid && !in_single) @@ -2813,47 +2814,47 @@ case 25: ; break;} case 26: -#line 393 "parse.y" +#line 394 "parse.y" { value_expr(yyvsp[0].node); yyval.node = NEW_YIELD(yyvsp[0].node); ; break;} case 28: -#line 399 "parse.y" +#line 400 "parse.y" { yyval.node = logop(NODE_AND, yyvsp[-2].node, yyvsp[0].node); ; break;} case 29: -#line 403 "parse.y" +#line 404 "parse.y" { yyval.node = logop(NODE_OR, yyvsp[-2].node, yyvsp[0].node); ; break;} case 30: -#line 407 "parse.y" +#line 408 "parse.y" { value_expr(yyvsp[0].node); yyval.node = NEW_NOT(cond(yyvsp[0].node)); ; break;} case 31: -#line 412 "parse.y" +#line 413 "parse.y" { value_expr(yyvsp[0].node); yyval.node = NEW_NOT(cond(yyvsp[0].node)); ; break;} case 33: -#line 419 "parse.y" +#line 420 "parse.y" { yyval.node = new_fcall(yyvsp[-1].id, yyvsp[0].node); fixpos(yyval.node, yyvsp[0].node); ; break;} case 34: -#line 424 "parse.y" +#line 425 "parse.y" { value_expr(yyvsp[-3].node); yyval.node = new_call(yyvsp[-3].node, yyvsp[-1].id, yyvsp[0].node); @@ -2861,7 +2862,7 @@ case 34: ; break;} case 35: -#line 430 "parse.y" +#line 431 "parse.y" { value_expr(yyvsp[-3].node); yyval.node = new_call(yyvsp[-3].node, yyvsp[-1].id, yyvsp[0].node); @@ -2869,7 +2870,7 @@ case 35: ; break;} case 36: -#line 436 "parse.y" +#line 437 "parse.y" { if (!compile_for_eval && !cur_mid && !in_single) yyerror("super called outside of method"); @@ -2878,278 +2879,278 @@ case 36: ; break;} case 38: -#line 445 "parse.y" +#line 446 "parse.y" { yyval.node = yyvsp[-1].node; ; break;} case 40: -#line 451 "parse.y" +#line 452 "parse.y" { yyval.node = NEW_MASGN(NEW_LIST(yyvsp[-1].node), 0); ; break;} case 41: -#line 456 "parse.y" +#line 457 "parse.y" { yyval.node = NEW_MASGN(NEW_LIST(yyvsp[0].node), 0); ; break;} case 42: -#line 460 "parse.y" +#line 461 "parse.y" { yyval.node = NEW_MASGN(NEW_LIST(yyvsp[-2].node), yyvsp[0].node); ; break;} case 43: -#line 464 "parse.y" +#line 465 "parse.y" { yyval.node = NEW_MASGN(list_concat(NEW_LIST(yyvsp[-1].node),yyvsp[0].node), 0); ; break;} case 44: -#line 468 "parse.y" +#line 469 "parse.y" { yyval.node = NEW_MASGN(list_concat(NEW_LIST(yyvsp[-4].node),yyvsp[-3].node),yyvsp[0].node); ; break;} case 45: -#line 472 "parse.y" +#line 473 "parse.y" { yyval.node = NEW_MASGN(0, yyvsp[0].node); ; break;} case 47: -#line 478 "parse.y" +#line 479 "parse.y" { yyval.node = yyvsp[-1].node; ; break;} case 48: -#line 483 "parse.y" +#line 484 "parse.y" { yyval.node = yyvsp[-1].node; ; break;} case 49: -#line 488 "parse.y" +#line 489 "parse.y" { yyval.node = NEW_LIST(yyvsp[0].node); ; break;} case 50: -#line 492 "parse.y" +#line 493 "parse.y" { yyval.node = list_append(yyvsp[-2].node, yyvsp[0].node); ; break;} case 51: -#line 497 "parse.y" +#line 498 "parse.y" { yyval.node = assignable(yyvsp[0].id, 0); ; break;} case 52: -#line 501 "parse.y" +#line 502 "parse.y" { yyval.node = aryset(yyvsp[-3].node, yyvsp[-1].node); ; break;} case 53: -#line 505 "parse.y" +#line 506 "parse.y" { yyval.node = attrset(yyvsp[-2].node, yyvsp[0].id); ; break;} case 54: -#line 509 "parse.y" +#line 510 "parse.y" { rb_backref_error(yyvsp[0].node); yyval.node = 0; ; break;} case 55: -#line 515 "parse.y" +#line 516 "parse.y" { yyval.node = assignable(yyvsp[0].id, 0); ; break;} case 56: -#line 519 "parse.y" +#line 520 "parse.y" { yyval.node = aryset(yyvsp[-3].node, yyvsp[-1].node); ; break;} case 57: -#line 523 "parse.y" +#line 524 "parse.y" { yyval.node = attrset(yyvsp[-2].node, yyvsp[0].id); ; break;} case 58: -#line 527 "parse.y" +#line 528 "parse.y" { rb_backref_error(yyvsp[0].node); yyval.node = 0; ; break;} case 59: -#line 533 "parse.y" +#line 534 "parse.y" { yyerror("class/module name must be CONSTANT"); ; break;} case 64: -#line 542 "parse.y" +#line 543 "parse.y" { lex_state = EXPR_END; yyval.id = yyvsp[0].id; ; break;} case 65: -#line 547 "parse.y" +#line 548 "parse.y" { lex_state = EXPR_END; yyval.id = yyvsp[0].id; ; break;} case 66: -#line 553 "parse.y" +#line 554 "parse.y" { yyval.node = NEW_UNDEF(yyvsp[0].id); ; break;} case 67: -#line 556 "parse.y" +#line 557 "parse.y" {lex_state = EXPR_FNAME;; break;} case 68: -#line 557 "parse.y" +#line 558 "parse.y" { yyval.node = block_append(yyvsp[-3].node, NEW_UNDEF(yyvsp[0].id)); ; break;} case 69: -#line 561 "parse.y" +#line 562 "parse.y" { yyval.id = tDOT2; ; break;} case 70: -#line 562 "parse.y" +#line 563 "parse.y" { yyval.id = '|'; ; break;} case 71: -#line 563 "parse.y" +#line 564 "parse.y" { yyval.id = '^'; ; break;} case 72: -#line 564 "parse.y" +#line 565 "parse.y" { yyval.id = '&'; ; break;} case 73: -#line 565 "parse.y" +#line 566 "parse.y" { yyval.id = tCMP; ; break;} case 74: -#line 566 "parse.y" +#line 567 "parse.y" { yyval.id = tEQ; ; break;} case 75: -#line 567 "parse.y" +#line 568 "parse.y" { yyval.id = tEQQ; ; break;} case 76: -#line 568 "parse.y" +#line 569 "parse.y" { yyval.id = tMATCH; ; break;} case 77: -#line 569 "parse.y" +#line 570 "parse.y" { yyval.id = '>'; ; break;} case 78: -#line 570 "parse.y" +#line 571 "parse.y" { yyval.id = tGEQ; ; break;} case 79: -#line 571 "parse.y" +#line 572 "parse.y" { yyval.id = '<'; ; break;} case 80: -#line 572 "parse.y" +#line 573 "parse.y" { yyval.id = tLEQ; ; break;} case 81: -#line 573 "parse.y" +#line 574 "parse.y" { yyval.id = tLSHFT; ; break;} case 82: -#line 574 "parse.y" +#line 575 "parse.y" { yyval.id = tRSHFT; ; break;} case 83: -#line 575 "parse.y" +#line 576 "parse.y" { yyval.id = '+'; ; break;} case 84: -#line 576 "parse.y" +#line 577 "parse.y" { yyval.id = '-'; ; break;} case 85: -#line 577 "parse.y" +#line 578 "parse.y" { yyval.id = '*'; ; break;} case 86: -#line 578 "parse.y" +#line 579 "parse.y" { yyval.id = '*'; ; break;} case 87: -#line 579 "parse.y" +#line 580 "parse.y" { yyval.id = '/'; ; break;} case 88: -#line 580 "parse.y" +#line 581 "parse.y" { yyval.id = '%'; ; break;} case 89: -#line 581 "parse.y" +#line 582 "parse.y" { yyval.id = tPOW; ; break;} case 90: -#line 582 "parse.y" +#line 583 "parse.y" { yyval.id = '~'; ; break;} case 91: -#line 583 "parse.y" +#line 584 "parse.y" { yyval.id = tUPLUS; ; break;} case 92: -#line 584 "parse.y" +#line 585 "parse.y" { yyval.id = tUMINUS; ; break;} case 93: -#line 585 "parse.y" +#line 586 "parse.y" { yyval.id = tAREF; ; break;} case 94: -#line 586 "parse.y" +#line 587 "parse.y" { yyval.id = tASET; ; break;} case 95: -#line 587 "parse.y" +#line 588 "parse.y" { yyval.id = '`'; ; break;} case 136: -#line 598 "parse.y" +#line 599 "parse.y" { value_expr(yyvsp[0].node); yyval.node = node_assign(yyvsp[-2].node, yyvsp[0].node); ; break;} case 137: -#line 602 "parse.y" +#line 603 "parse.y" {yyval.node = assignable(yyvsp[-1].id, 0);; break;} case 138: -#line 603 "parse.y" +#line 604 "parse.y" { if (yyvsp[-2].id == tOROP) { yyvsp[-1].node->nd_value = yyvsp[0].node; @@ -3167,7 +3168,7 @@ case 138: ; break;} case 139: -#line 619 "parse.y" +#line 620 "parse.y" { NODE *args = NEW_LIST(yyvsp[0].node); @@ -3184,7 +3185,7 @@ case 139: ; break;} case 140: -#line 634 "parse.y" +#line 635 "parse.y" { if (yyvsp[-1].id == tOROP) { yyvsp[-1].id = 0; @@ -3197,7 +3198,7 @@ case 140: ; break;} case 141: -#line 645 "parse.y" +#line 646 "parse.y" { if (yyvsp[-1].id == tOROP) { yyvsp[-1].id = 0; @@ -3210,200 +3211,200 @@ case 141: ; break;} case 142: -#line 656 "parse.y" +#line 657 "parse.y" { rb_backref_error(yyvsp[-2].node); yyval.node = 0; ; break;} case 143: -#line 661 "parse.y" +#line 662 "parse.y" { yyval.node = NEW_DOT2(yyvsp[-2].node, yyvsp[0].node); ; break;} case 144: -#line 665 "parse.y" +#line 666 "parse.y" { yyval.node = NEW_DOT3(yyvsp[-2].node, yyvsp[0].node); ; break;} case 145: -#line 669 "parse.y" +#line 670 "parse.y" { yyval.node = call_op(yyvsp[-2].node, '+', 1, yyvsp[0].node); ; break;} case 146: -#line 673 "parse.y" +#line 674 "parse.y" { yyval.node = call_op(yyvsp[-2].node, '-', 1, yyvsp[0].node); ; break;} case 147: -#line 677 "parse.y" +#line 678 "parse.y" { yyval.node = call_op(yyvsp[-2].node, '*', 1, yyvsp[0].node); ; break;} case 148: -#line 681 "parse.y" +#line 682 "parse.y" { yyval.node = call_op(yyvsp[-2].node, '/', 1, yyvsp[0].node); ; break;} case 149: -#line 685 "parse.y" +#line 686 "parse.y" { yyval.node = call_op(yyvsp[-2].node, '%', 1, yyvsp[0].node); ; break;} case 150: -#line 689 "parse.y" +#line 690 "parse.y" { yyval.node = call_op(yyvsp[-2].node, tPOW, 1, yyvsp[0].node); ; break;} case 151: -#line 693 "parse.y" +#line 694 "parse.y" { yyval.node = call_op(yyvsp[0].node, tUPLUS, 0); ; break;} case 152: -#line 697 "parse.y" +#line 698 "parse.y" { yyval.node = call_op(yyvsp[0].node, tUMINUS, 0); ; break;} case 153: -#line 701 "parse.y" +#line 702 "parse.y" { yyval.node = call_op(yyvsp[-2].node, '|', 1, yyvsp[0].node); ; break;} case 154: -#line 705 "parse.y" +#line 706 "parse.y" { yyval.node = call_op(yyvsp[-2].node, '^', 1, yyvsp[0].node); ; break;} case 155: -#line 709 "parse.y" +#line 710 "parse.y" { yyval.node = call_op(yyvsp[-2].node, '&', 1, yyvsp[0].node); ; break;} case 156: -#line 713 "parse.y" +#line 714 "parse.y" { yyval.node = call_op(yyvsp[-2].node, tCMP, 1, yyvsp[0].node); ; break;} case 157: -#line 717 "parse.y" +#line 718 "parse.y" { yyval.node = call_op(yyvsp[-2].node, '>', 1, yyvsp[0].node); ; break;} case 158: -#line 721 "parse.y" +#line 722 "parse.y" { yyval.node = call_op(yyvsp[-2].node, tGEQ, 1, yyvsp[0].node); ; break;} case 159: -#line 725 "parse.y" +#line 726 "parse.y" { yyval.node = call_op(yyvsp[-2].node, '<', 1, yyvsp[0].node); ; break;} case 160: -#line 729 "parse.y" +#line 730 "parse.y" { yyval.node = call_op(yyvsp[-2].node, tLEQ, 1, yyvsp[0].node); ; break;} case 161: -#line 733 "parse.y" +#line 734 "parse.y" { yyval.node = call_op(yyvsp[-2].node, tEQ, 1, yyvsp[0].node); ; break;} case 162: -#line 737 "parse.y" +#line 738 "parse.y" { yyval.node = call_op(yyvsp[-2].node, tEQQ, 1, yyvsp[0].node); ; break;} case 163: -#line 741 "parse.y" +#line 742 "parse.y" { yyval.node = NEW_NOT(call_op(yyvsp[-2].node, tEQ, 1, yyvsp[0].node)); ; break;} case 164: -#line 745 "parse.y" +#line 746 "parse.y" { yyval.node = match_gen(yyvsp[-2].node, yyvsp[0].node); ; break;} case 165: -#line 749 "parse.y" +#line 750 "parse.y" { yyval.node = NEW_NOT(match_gen(yyvsp[-2].node, yyvsp[0].node)); ; break;} case 166: -#line 753 "parse.y" +#line 754 "parse.y" { value_expr(yyvsp[0].node); yyval.node = NEW_NOT(cond(yyvsp[0].node)); ; break;} case 167: -#line 758 "parse.y" +#line 759 "parse.y" { yyval.node = call_op(yyvsp[0].node, '~', 0); ; break;} case 168: -#line 762 "parse.y" +#line 763 "parse.y" { yyval.node = call_op(yyvsp[-2].node, tLSHFT, 1, yyvsp[0].node); ; break;} case 169: -#line 766 "parse.y" +#line 767 "parse.y" { yyval.node = call_op(yyvsp[-2].node, tRSHFT, 1, yyvsp[0].node); ; break;} case 170: -#line 770 "parse.y" +#line 771 "parse.y" { yyval.node = logop(NODE_AND, yyvsp[-2].node, yyvsp[0].node); ; break;} case 171: -#line 774 "parse.y" +#line 775 "parse.y" { yyval.node = logop(NODE_OR, yyvsp[-2].node, yyvsp[0].node); ; break;} case 172: -#line 777 "parse.y" +#line 778 "parse.y" {in_defined = 1;; break;} case 173: -#line 778 "parse.y" +#line 779 "parse.y" { in_defined = 0; yyval.node = NEW_DEFINED(yyvsp[0].node); ; break;} case 174: -#line 783 "parse.y" +#line 784 "parse.y" { value_expr(yyvsp[-4].node); yyval.node = NEW_IF(cond(yyvsp[-4].node), yyvsp[-2].node, yyvsp[0].node); @@ -3411,13 +3412,13 @@ case 174: ; break;} case 175: -#line 789 "parse.y" +#line 790 "parse.y" { yyval.node = yyvsp[0].node; ; break;} case 176: -#line 794 "parse.y" +#line 795 "parse.y" { if (yyvsp[0].node && nd_type(yyvsp[0].node) == NODE_BLOCK_PASS) { rb_compile_error("block argument should not be given"); @@ -3426,107 +3427,107 @@ case 176: ; break;} case 179: -#line 805 "parse.y" +#line 806 "parse.y" { value_expr(yyvsp[0].node); yyval.node = NEW_LIST(yyvsp[0].node); ; break;} case 180: -#line 810 "parse.y" +#line 811 "parse.y" { yyval.node = yyvsp[-1].node; ; break;} case 181: -#line 814 "parse.y" +#line 815 "parse.y" { yyval.node = arg_blk_pass(yyvsp[-1].node, yyvsp[0].node); ; break;} case 182: -#line 818 "parse.y" +#line 819 "parse.y" { yyval.node = arg_concat(yyvsp[-4].node, yyvsp[-1].node); yyval.node = arg_blk_pass(yyval.node, yyvsp[0].node); ; break;} case 183: -#line 823 "parse.y" +#line 824 "parse.y" { yyval.node = NEW_LIST(NEW_HASH(yyvsp[-1].node)); ; break;} case 184: -#line 827 "parse.y" +#line 828 "parse.y" { yyval.node = NEW_LIST(NEW_HASH(yyvsp[-1].node)); yyval.node = arg_blk_pass(yyval.node, yyvsp[0].node); ; break;} case 185: -#line 832 "parse.y" +#line 833 "parse.y" { yyval.node = arg_concat(NEW_LIST(NEW_HASH(yyvsp[-4].node)), yyvsp[-1].node); yyval.node = arg_blk_pass(yyval.node, yyvsp[0].node); ; break;} case 186: -#line 837 "parse.y" +#line 838 "parse.y" { yyval.node = list_append(yyvsp[-3].node, NEW_HASH(yyvsp[-1].node)); yyval.node = arg_blk_pass(yyval.node, yyvsp[0].node); ; break;} case 187: -#line 842 "parse.y" +#line 843 "parse.y" { yyval.node = list_append(yyvsp[-3].node, NEW_HASH(yyvsp[-1].node)); ; break;} case 188: -#line 846 "parse.y" +#line 847 "parse.y" { yyval.node = arg_concat(list_append(yyvsp[-6].node, NEW_HASH(yyvsp[-4].node)), yyvsp[-1].node); yyval.node = arg_blk_pass(yyval.node, yyvsp[0].node); ; break;} case 189: -#line 851 "parse.y" +#line 852 "parse.y" { value_expr(yyvsp[-1].node); yyval.node = arg_blk_pass(NEW_RESTARGS(yyvsp[-1].node), yyvsp[0].node); ; break;} case 191: -#line 858 "parse.y" +#line 859 "parse.y" { value_expr(yyvsp[0].node); yyval.node = NEW_BLOCK_PASS(yyvsp[0].node); ; break;} case 192: -#line 864 "parse.y" +#line 865 "parse.y" { yyval.node = yyvsp[0].node; ; break;} case 196: -#line 873 "parse.y" +#line 874 "parse.y" { value_expr(yyvsp[0].node); yyval.node = NEW_LIST(yyvsp[0].node); ; break;} case 197: -#line 878 "parse.y" +#line 879 "parse.y" { value_expr(yyvsp[0].node); yyval.node = list_append(yyvsp[-2].node, yyvsp[0].node); ; break;} case 198: -#line 884 "parse.y" +#line 885 "parse.y" { if (yyvsp[0].node && nd_type(yyvsp[0].node) == NODE_ARRAY && @@ -3540,21 +3541,21 @@ case 198: ; break;} case 199: -#line 896 "parse.y" +#line 897 "parse.y" { value_expr(yyvsp[0].node); yyval.node = arg_concat(yyvsp[-3].node, yyvsp[0].node); ; break;} case 200: -#line 901 "parse.y" +#line 902 "parse.y" { value_expr(yyvsp[0].node); yyval.node = yyvsp[0].node; ; break;} case 201: -#line 907 "parse.y" +#line 908 "parse.y" { yyval.node = yyvsp[0].node; if (yyvsp[0].node) { @@ -3569,45 +3570,45 @@ case 201: ; break;} case 204: -#line 924 "parse.y" +#line 925 "parse.y" { yyval.node = NEW_LIT(yyvsp[0].val); ; break;} case 205: -#line 928 "parse.y" +#line 929 "parse.y" { value_expr(yyvsp[-2].node); yyval.node = NEW_COLON2(yyvsp[-2].node, yyvsp[0].id); ; break;} case 206: -#line 933 "parse.y" +#line 934 "parse.y" { yyval.node = NEW_COLON3(yyvsp[0].id); ; break;} case 207: -#line 937 "parse.y" +#line 938 "parse.y" { yyval.node = NEW_STR(yyvsp[0].val); ; break;} case 209: -#line 942 "parse.y" +#line 943 "parse.y" { yyval.node = NEW_XSTR(yyvsp[0].val); ; break;} case 214: -#line 950 "parse.y" +#line 951 "parse.y" { value_expr(yyvsp[-3].node); yyval.node = NEW_CALL(yyvsp[-3].node, tAREF, yyvsp[-1].node); ; break;} case 215: -#line 955 "parse.y" +#line 956 "parse.y" { if (yyvsp[-1].node == 0) yyval.node = NEW_ZARRAY(); /* zero length array*/ @@ -3617,13 +3618,13 @@ case 215: ; break;} case 216: -#line 963 "parse.y" +#line 964 "parse.y" { yyval.node = NEW_HASH(yyvsp[-1].node); ; break;} case 217: -#line 967 "parse.y" +#line 968 "parse.y" { if (!compile_for_eval && !cur_mid && !in_single) yyerror("return appeared outside of method"); @@ -3632,7 +3633,7 @@ case 217: ; break;} case 218: -#line 974 "parse.y" +#line 975 "parse.y" { if (!compile_for_eval && !cur_mid && !in_single) yyerror("return appeared outside of method"); @@ -3640,7 +3641,7 @@ case 218: ; break;} case 219: -#line 980 "parse.y" +#line 981 "parse.y" { if (!compile_for_eval && !cur_mid && !in_single) yyerror("return appeared outside of method"); @@ -3648,50 +3649,50 @@ case 219: ; break;} case 220: -#line 986 "parse.y" +#line 987 "parse.y" { value_expr(yyvsp[-1].node); yyval.node = NEW_YIELD(yyvsp[-1].node); ; break;} case 221: -#line 991 "parse.y" +#line 992 "parse.y" { yyval.node = NEW_YIELD(0); ; break;} case 222: -#line 995 "parse.y" +#line 996 "parse.y" { yyval.node = NEW_YIELD(0); ; break;} case 223: -#line 998 "parse.y" +#line 999 "parse.y" {in_defined = 1;; break;} case 224: -#line 999 "parse.y" +#line 1000 "parse.y" { in_defined = 0; yyval.node = NEW_DEFINED(yyvsp[-1].node); ; break;} case 225: -#line 1004 "parse.y" +#line 1005 "parse.y" { yyval.node = NEW_VCALL(yyvsp[0].id); ; break;} case 226: -#line 1008 "parse.y" +#line 1009 "parse.y" { yyvsp[0].node->nd_iter = NEW_FCALL(yyvsp[-1].id, 0); yyval.node = yyvsp[0].node; ; break;} case 228: -#line 1014 "parse.y" +#line 1015 "parse.y" { if (yyvsp[-1].node && nd_type(yyvsp[-1].node) == NODE_BLOCK_PASS) { rb_compile_error("both block arg and actual block given"); @@ -3702,7 +3703,7 @@ case 228: ; break;} case 229: -#line 1026 "parse.y" +#line 1027 "parse.y" { value_expr(yyvsp[-4].node); yyval.node = NEW_IF(cond(yyvsp[-4].node), yyvsp[-2].node, yyvsp[-1].node); @@ -3710,7 +3711,7 @@ case 229: ; break;} case 230: -#line 1035 "parse.y" +#line 1036 "parse.y" { value_expr(yyvsp[-4].node); yyval.node = NEW_UNLESS(cond(yyvsp[-4].node), yyvsp[-2].node, yyvsp[-1].node); @@ -3718,7 +3719,7 @@ case 230: ; break;} case 231: -#line 1043 "parse.y" +#line 1044 "parse.y" { value_expr(yyvsp[-3].node); yyval.node = NEW_WHILE(cond(yyvsp[-3].node), yyvsp[-1].node, 1); @@ -3726,7 +3727,7 @@ case 231: ; break;} case 232: -#line 1051 "parse.y" +#line 1052 "parse.y" { value_expr(yyvsp[-3].node); yyval.node = NEW_UNTIL(cond(yyvsp[-3].node), yyvsp[-1].node, 1); @@ -3734,7 +3735,7 @@ case 232: ; break;} case 233: -#line 1059 "parse.y" +#line 1060 "parse.y" { value_expr(yyvsp[-2].node); yyval.node = NEW_CASE(yyvsp[-2].node, yyvsp[-1].node); @@ -3742,7 +3743,7 @@ case 233: ; break;} case 234: -#line 1067 "parse.y" +#line 1068 "parse.y" { value_expr(yyvsp[-5].node); yyval.node = NEW_FOR(yyvsp[-5].node, yyvsp[-3].node, yyvsp[-1].node); @@ -3750,7 +3751,7 @@ case 234: ; break;} case 235: -#line 1078 "parse.y" +#line 1079 "parse.y" { if (!yyvsp[-3].node && !yyvsp[-2].node && !yyvsp[-1].node) yyval.node = NEW_BEGIN(yyvsp[-4].node); @@ -3767,13 +3768,13 @@ case 235: ; break;} case 236: -#line 1093 "parse.y" +#line 1094 "parse.y" { yyval.node = yyvsp[-1].node; ; break;} case 237: -#line 1097 "parse.y" +#line 1098 "parse.y" { if (cur_mid || in_single) yyerror("class definition in method body"); @@ -3784,7 +3785,7 @@ case 237: ; break;} case 238: -#line 1107 "parse.y" +#line 1108 "parse.y" { yyval.node = NEW_CLASS(yyvsp[-4].id, yyvsp[-1].node, yyvsp[-3].node); fixpos(yyval.node, yyvsp[-3].node); @@ -3794,7 +3795,7 @@ case 238: ; break;} case 239: -#line 1115 "parse.y" +#line 1116 "parse.y" { class_nest++; cref_push(); @@ -3802,7 +3803,7 @@ case 239: ; break;} case 240: -#line 1122 "parse.y" +#line 1123 "parse.y" { yyval.node = NEW_SCLASS(yyvsp[-4].node, yyvsp[-1].node); fixpos(yyval.node, yyvsp[-4].node); @@ -3812,7 +3813,7 @@ case 240: ; break;} case 241: -#line 1130 "parse.y" +#line 1131 "parse.y" { if (cur_mid || in_single) yyerror("module definition in method body"); @@ -3822,7 +3823,7 @@ case 241: ; break;} case 242: -#line 1139 "parse.y" +#line 1140 "parse.y" { yyval.node = NEW_MODULE(yyvsp[-3].id, yyvsp[-1].node); fixpos(yyval.node, yyvsp[-1].node); @@ -3832,7 +3833,7 @@ case 242: ; break;} case 243: -#line 1147 "parse.y" +#line 1148 "parse.y" { if (cur_mid || in_single) yyerror("nested method definition"); @@ -3841,7 +3842,7 @@ case 243: ; break;} case 244: -#line 1156 "parse.y" +#line 1157 "parse.y" { /* NOEX_PRIVATE for toplevel */ yyval.node = NEW_DEFN(yyvsp[-4].id, yyvsp[-2].node, yyvsp[-1].node, class_nest?0:1); @@ -3851,11 +3852,11 @@ case 244: ; break;} case 245: -#line 1163 "parse.y" +#line 1164 "parse.y" {lex_state = EXPR_FNAME;; break;} case 246: -#line 1164 "parse.y" +#line 1165 "parse.y" { value_expr(yyvsp[-3].node); in_single++; @@ -3864,7 +3865,7 @@ case 246: ; break;} case 247: -#line 1173 "parse.y" +#line 1174 "parse.y" { yyval.node = NEW_DEFS(yyvsp[-7].node, yyvsp[-4].id, yyvsp[-2].node, yyvsp[-1].node); fixpos(yyval.node, yyvsp[-7].node); @@ -3873,31 +3874,31 @@ case 247: ; break;} case 248: -#line 1180 "parse.y" +#line 1181 "parse.y" { yyval.node = NEW_BREAK(); ; break;} case 249: -#line 1184 "parse.y" +#line 1185 "parse.y" { yyval.node = NEW_NEXT(); ; break;} case 250: -#line 1188 "parse.y" +#line 1189 "parse.y" { yyval.node = NEW_REDO(); ; break;} case 251: -#line 1192 "parse.y" +#line 1193 "parse.y" { yyval.node = NEW_RETRY(); ; break;} case 258: -#line 1207 "parse.y" +#line 1208 "parse.y" { value_expr(yyvsp[-3].node); yyval.node = NEW_IF(cond(yyvsp[-3].node), yyvsp[-1].node, yyvsp[0].node); @@ -3905,37 +3906,37 @@ case 258: ; break;} case 260: -#line 1215 "parse.y" +#line 1216 "parse.y" { yyval.node = yyvsp[0].node; ; break;} case 264: -#line 1224 "parse.y" +#line 1225 "parse.y" { yyval.node = 0; ; break;} case 265: -#line 1228 "parse.y" +#line 1229 "parse.y" { yyval.node = 0; ; break;} case 266: -#line 1232 "parse.y" +#line 1233 "parse.y" { yyval.node = yyvsp[-1].node; ; break;} case 267: -#line 1237 "parse.y" +#line 1238 "parse.y" { yyval.vars = dyna_push(); ; break;} case 268: -#line 1243 "parse.y" +#line 1244 "parse.y" { yyval.node = NEW_ITER(yyvsp[-2].node, 0, yyvsp[-1].node); fixpos(yyval.node, yyvsp[-2].node?yyvsp[-2].node:yyvsp[-1].node); @@ -3943,13 +3944,13 @@ case 268: ; break;} case 269: -#line 1250 "parse.y" +#line 1251 "parse.y" { yyval.vars = dyna_push(); ; break;} case 270: -#line 1255 "parse.y" +#line 1256 "parse.y" { yyval.node = NEW_ITER(yyvsp[-2].node, 0, yyvsp[-1].node); fixpos(yyval.node, yyvsp[-2].node?yyvsp[-2].node:yyvsp[-1].node); @@ -3957,25 +3958,25 @@ case 270: ; break;} case 271: -#line 1262 "parse.y" +#line 1263 "parse.y" { yyval.node = NEW_VCALL(yyvsp[0].id); ; break;} case 272: -#line 1266 "parse.y" +#line 1267 "parse.y" { yyval.node = NEW_VCALL(yyvsp[0].id); ; break;} case 273: -#line 1270 "parse.y" +#line 1271 "parse.y" { yyval.node = NEW_VCALL(yyvsp[0].id); ; break;} case 276: -#line 1277 "parse.y" +#line 1278 "parse.y" { if (yyvsp[-1].node && nd_type(yyvsp[-1].node) == NODE_BLOCK_PASS) { rb_compile_error("both block arg and actual block given"); @@ -3986,14 +3987,14 @@ case 276: ; break;} case 277: -#line 1287 "parse.y" +#line 1288 "parse.y" { yyval.node = new_fcall(yyvsp[-3].id, yyvsp[-1].node); fixpos(yyval.node, yyvsp[-1].node); ; break;} case 278: -#line 1292 "parse.y" +#line 1293 "parse.y" { value_expr(yyvsp[-5].node); yyval.node = new_call(yyvsp[-5].node, yyvsp[-3].id, yyvsp[-1].node); @@ -4001,7 +4002,7 @@ case 278: ; break;} case 279: -#line 1298 "parse.y" +#line 1299 "parse.y" { value_expr(yyvsp[-2].node); yyval.node = new_call(yyvsp[-2].node, yyvsp[0].id, 0); @@ -4009,7 +4010,7 @@ case 279: ; break;} case 280: -#line 1304 "parse.y" +#line 1305 "parse.y" { value_expr(yyvsp[-5].node); yyval.node = new_call(yyvsp[-5].node, yyvsp[-3].id, yyvsp[-1].node); @@ -4017,14 +4018,14 @@ case 280: ; break;} case 281: -#line 1310 "parse.y" +#line 1311 "parse.y" { value_expr(yyvsp[-2].node); yyval.node = new_call(yyvsp[-2].node, yyvsp[0].id, 0); ; break;} case 282: -#line 1315 "parse.y" +#line 1316 "parse.y" { if (!compile_for_eval && !cur_mid && !in_single && !in_defined) @@ -4033,7 +4034,7 @@ case 282: ; break;} case 283: -#line 1322 "parse.y" +#line 1323 "parse.y" { if (!compile_for_eval && !cur_mid && !in_single && !in_defined) @@ -4042,165 +4043,165 @@ case 283: ; break;} case 286: -#line 1336 "parse.y" +#line 1337 "parse.y" { yyval.node = NEW_WHEN(yyvsp[-3].node, yyvsp[-1].node, yyvsp[0].node); ; break;} case 288: -#line 1342 "parse.y" +#line 1343 "parse.y" { value_expr(yyvsp[0].node); yyval.node = list_append(yyvsp[-3].node, NEW_WHEN(yyvsp[0].node, 0, 0)); ; break;} case 289: -#line 1347 "parse.y" +#line 1348 "parse.y" { value_expr(yyvsp[0].node); yyval.node = NEW_LIST(NEW_WHEN(yyvsp[0].node, 0, 0)); ; break;} case 292: -#line 1358 "parse.y" +#line 1359 "parse.y" { yyval.node = NEW_RESBODY(yyvsp[-3].node, yyvsp[-1].node, yyvsp[0].node); fixpos(yyval.node, yyvsp[-3].node?yyvsp[-3].node:yyvsp[-1].node); ; break;} case 295: -#line 1366 "parse.y" +#line 1367 "parse.y" { yyval.node = yyvsp[0].node; ; break;} case 297: -#line 1372 "parse.y" +#line 1373 "parse.y" { yyval.val = INT2FIX(yyvsp[0].id); ; break;} case 308: -#line 1388 "parse.y" +#line 1389 "parse.y" {yyval.id = kNIL;; break;} case 309: -#line 1389 "parse.y" +#line 1390 "parse.y" {yyval.id = kSELF;; break;} case 310: -#line 1390 "parse.y" +#line 1391 "parse.y" {yyval.id = kTRUE;; break;} case 311: -#line 1391 "parse.y" +#line 1392 "parse.y" {yyval.id = kFALSE;; break;} case 312: -#line 1392 "parse.y" +#line 1393 "parse.y" {yyval.id = k__FILE__;; break;} case 313: -#line 1393 "parse.y" +#line 1394 "parse.y" {yyval.id = k__LINE__;; break;} case 314: -#line 1396 "parse.y" +#line 1397 "parse.y" { yyval.node = gettable(yyvsp[0].id); ; break;} case 317: -#line 1404 "parse.y" +#line 1405 "parse.y" { yyval.node = 0; ; break;} case 318: -#line 1408 "parse.y" +#line 1409 "parse.y" { lex_state = EXPR_BEG; ; break;} case 319: -#line 1412 "parse.y" +#line 1413 "parse.y" { yyval.node = yyvsp[-1].node; ; break;} case 320: -#line 1415 "parse.y" +#line 1416 "parse.y" {yyerrok; yyval.node = 0;; break;} case 321: -#line 1418 "parse.y" +#line 1419 "parse.y" { yyval.node = yyvsp[-2].node; lex_state = EXPR_BEG; ; break;} case 322: -#line 1423 "parse.y" +#line 1424 "parse.y" { yyval.node = yyvsp[-1].node; ; break;} case 323: -#line 1428 "parse.y" +#line 1429 "parse.y" { yyval.node = block_append(NEW_ARGS(yyvsp[-5].num, yyvsp[-3].node, yyvsp[-1].id), yyvsp[0].node); ; break;} case 324: -#line 1432 "parse.y" +#line 1433 "parse.y" { yyval.node = block_append(NEW_ARGS(yyvsp[-3].num, yyvsp[-1].node, -1), yyvsp[0].node); ; break;} case 325: -#line 1436 "parse.y" +#line 1437 "parse.y" { yyval.node = block_append(NEW_ARGS(yyvsp[-3].num, 0, yyvsp[-1].id), yyvsp[0].node); ; break;} case 326: -#line 1440 "parse.y" +#line 1441 "parse.y" { yyval.node = block_append(NEW_ARGS(yyvsp[-1].num, 0, -1), yyvsp[0].node); ; break;} case 327: -#line 1444 "parse.y" +#line 1445 "parse.y" { yyval.node = block_append(NEW_ARGS(0, yyvsp[-3].node, yyvsp[-1].id), yyvsp[0].node); ; break;} case 328: -#line 1448 "parse.y" +#line 1449 "parse.y" { yyval.node = block_append(NEW_ARGS(0, yyvsp[-1].node, -1), yyvsp[0].node); ; break;} case 329: -#line 1452 "parse.y" +#line 1453 "parse.y" { yyval.node = block_append(NEW_ARGS(0, 0, yyvsp[-1].id), yyvsp[0].node); ; break;} case 330: -#line 1456 "parse.y" +#line 1457 "parse.y" { yyval.node = block_append(NEW_ARGS(0, 0, -1), yyvsp[0].node); ; break;} case 331: -#line 1460 "parse.y" +#line 1461 "parse.y" { yyval.node = NEW_ARGS(0, 0, -1); ; break;} case 332: -#line 1465 "parse.y" +#line 1466 "parse.y" { if (!is_local_id(yyvsp[0].id)) yyerror("formal argument must be local variable"); @@ -4209,7 +4210,7 @@ case 332: ; break;} case 333: -#line 1472 "parse.y" +#line 1473 "parse.y" { if (!is_local_id(yyvsp[0].id)) yyerror("formal argument must be local variable"); @@ -4218,7 +4219,7 @@ case 333: ; break;} case 334: -#line 1480 "parse.y" +#line 1481 "parse.y" { if (!is_local_id(yyvsp[-2].id)) yyerror("formal argument must be local variable"); @@ -4226,20 +4227,20 @@ case 334: ; break;} case 335: -#line 1487 "parse.y" +#line 1488 "parse.y" { yyval.node = NEW_BLOCK(yyvsp[0].node); yyval.node->nd_end = yyval.node; ; break;} case 336: -#line 1492 "parse.y" +#line 1493 "parse.y" { yyval.node = block_append(yyvsp[-2].node, yyvsp[0].node); ; break;} case 337: -#line 1497 "parse.y" +#line 1498 "parse.y" { if (!is_local_id(yyvsp[0].id)) yyerror("rest argument must be local variable"); @@ -4247,19 +4248,19 @@ case 337: ; break;} case 338: -#line 1504 "parse.y" +#line 1505 "parse.y" { yyval.node = NEW_BLOCK_ARG(yyvsp[0].id); ; break;} case 339: -#line 1509 "parse.y" +#line 1510 "parse.y" { yyval.node = yyvsp[0].node; ; break;} case 341: -#line 1515 "parse.y" +#line 1516 "parse.y" { if (nd_type(yyvsp[0].node) == NODE_SELF) { yyval.node = NEW_SELF(); @@ -4274,7 +4275,7 @@ case 341: ; break;} case 342: -#line 1528 "parse.y" +#line 1529 "parse.y" { switch (nd_type(yyvsp[-2].node)) { case NODE_STR: @@ -4293,13 +4294,13 @@ case 342: ; break;} case 344: -#line 1547 "parse.y" +#line 1548 "parse.y" { yyval.node = yyvsp[-1].node; ; break;} case 345: -#line 1551 "parse.y" +#line 1552 "parse.y" { if (yyvsp[-1].node->nd_alen%2 != 0) { yyerror("odd number list for Hash"); @@ -4308,27 +4309,27 @@ case 345: ; break;} case 347: -#line 1560 "parse.y" +#line 1561 "parse.y" { yyval.node = list_concat(yyvsp[-2].node, yyvsp[0].node); ; break;} case 348: -#line 1565 "parse.y" +#line 1566 "parse.y" { yyval.node = list_append(NEW_LIST(yyvsp[-2].node), yyvsp[0].node); ; break;} case 363: -#line 1589 "parse.y" +#line 1590 "parse.y" {yyerrok;; break;} case 366: -#line 1593 "parse.y" +#line 1594 "parse.y" {yyerrok;; break;} case 367: -#line 1596 "parse.y" +#line 1597 "parse.y" { yyval.node = 0; ; @@ -4555,7 +4556,7 @@ yyerrhandle: } return 1; } -#line 1599 "parse.y" +#line 1600 "parse.y" #include <ctype.h> #include <sys/types.h> @@ -4672,28 +4673,27 @@ lex_get_str(s) } NODE* -rb_compile_string(f, s) +rb_compile_string(f, s, line) const char *f; VALUE s; + int line; { lex_gets = lex_get_str; lex_gets_ptr = 0; lex_input = s; lex_pbeg = lex_p = lex_pend = 0; - if (!ruby_sourcefile || strcmp(f, ruby_sourcefile)) /* not in eval() */ - ruby_sourceline = 0; - else /* in eval() */ - compile_for_eval = 1; + ruby_sourceline = line; + compile_for_eval = 1; return yycompile(f); } NODE* -rb_compile_cstr(f, s, len) +rb_compile_cstr(f, s, len, line) const char *f, *s; - int len; + int len, line; { - return rb_compile_string(f, rb_str_new(s, len)); + return rb_compile_string(f, rb_str_new(s, len), line); } NODE* @@ -6758,10 +6758,7 @@ void_expr(node) case '<': case tLEQ: case tEQ: - case tEQQ: case tNEQ: - case tMATCH: - case tNMATCH: case tAREF: case tRSHFT: case tCOLON2: @@ -245,7 +245,8 @@ program : { } compstmt { - if ($2) { /* last expression is void */ + if ($2 && !compile_for_eval) { + /* last expression should not be void */ if (nd_type($2) != NODE_BLOCK) void_expr($2); else { NODE *node = $2; @@ -1712,28 +1713,27 @@ lex_get_str(s) } NODE* -rb_compile_string(f, s) +rb_compile_string(f, s, line) const char *f; VALUE s; + int line; { lex_gets = lex_get_str; lex_gets_ptr = 0; lex_input = s; lex_pbeg = lex_p = lex_pend = 0; - if (!ruby_sourcefile || strcmp(f, ruby_sourcefile)) /* not in eval() */ - ruby_sourceline = 0; - else /* in eval() */ - compile_for_eval = 1; + ruby_sourceline = line; + compile_for_eval = 1; return yycompile(f); } NODE* -rb_compile_cstr(f, s, len) +rb_compile_cstr(f, s, len, line) const char *f, *s; - int len; + int len, line; { - return rb_compile_string(f, rb_str_new(s, len)); + return rb_compile_string(f, rb_str_new(s, len), line); } NODE* @@ -3798,10 +3798,7 @@ void_expr(node) case '<': case tLEQ: case tEQ: - case tEQQ: case tNEQ: - case tMATCH: - case tNMATCH: case tAREF: case tRSHFT: case tCOLON2: @@ -141,8 +141,8 @@ char *alloca(); #define TMALLOC(n,t) ((t*)xmalloc((n)*sizeof(t))) #define TREALLOC(s,n,t) (s=((t*)xrealloc(s,(n)*sizeof(t)))) -#define EXPAND_FAIL_STACK(stackx,stackb,len) \ - do {\ +#define EXPAND_FAIL_STACK(stackx,stackb,len) \ + do { \ /* Roughly double the size of the stack. */ \ stackx = DOUBLE_STACK(stackx,stackb,len,unsigned char*); \ /* Rearrange the pointers. */ \ @@ -401,7 +401,7 @@ enum regexpcode such as p, not, e.g., p + 1. */ #define EXTRACT_NUMBER_AND_INCR(destination, source) \ do { EXTRACT_NUMBER(destination, source); \ - (source) += 2; } while (0) + (source) += 2; } while (0) /* Specify the precise syntax of regexps for compilation. This provides @@ -443,29 +443,29 @@ re_set_syntax(syntax) /* Go backwards one character in the pattern. */ #define PATUNFETCH p-- -#define MBC2WC(c, p)\ - do {\ - if (current_mbctype == MBCTYPE_UTF8) {\ - int n = mbclen(c) - 1;\ - int c1;\ - c &= (1<<(BYTEWIDTH-2-n)) - 1;\ - while (n--) {\ - c = c << 6 | *p++ & ((1<<6)-1);\ - }\ - }\ - else {\ - c <<= 8;\ - c |= (unsigned char)*(p)++;\ - }\ +#define MBC2WC(c, p) \ + do { \ + if (current_mbctype == MBCTYPE_UTF8) { \ + int n = mbclen(c) - 1; \ + int c1; \ + c &= (1<<(BYTEWIDTH-2-n)) - 1; \ + while (n--) { \ + c = c << 6 | *p++ & ((1<<6)-1); \ + } \ + } \ + else { \ + c <<= 8; \ + c |= (unsigned char)*(p)++; \ + } \ } while (0) -#define PATFETCH_MBC(c) \ - do {\ - if (p + mbclen(c) - 1 >= pend) goto end_of_pattern;\ - MBC2WC(c, p);\ +#define PATFETCH_MBC(c) \ + do { \ + if (p + mbclen(c) - 1 >= pend) goto end_of_pattern; \ + MBC2WC(c, p); \ } while(0) -#define WC2MBC1ST(c) \ +#define WC2MBC1ST(c) \ ((current_mbctype != MBCTYPE_UTF8)?(((c)>>8)&0xff):utf8_firstbyte(c)) static unsigned int @@ -1181,14 +1181,13 @@ re_compile_pattern(pattern, size, bufp) /* When testing what follows the $, look past the \-constructs that don't consume anything. */ - while (p0 != pend) - { - if (*p0 == '\\' && p0 + 1 != pend - && (p0[1] == 'b' || p0[1] == 'B')) - p0 += 2; - else - break; - } + while (p0 != pend) { + if (*p0 == '\\' && p0 + 1 != pend + && (p0[1] == 'b' || p0[1] == 'B')) + p0 += 2; + else + break; + } BUFPUSH(endline); break; } @@ -1279,11 +1278,10 @@ re_compile_pattern(pattern, size, bufp) EXTEND_BUFFER; laststart = b; - if (*p == '^') - { - BUFPUSH(charset_not); - p++; - } + if (*p == '^') { + BUFPUSH(charset_not); + p++; + } else BUFPUSH(charset); p0 = p; @@ -1304,225 +1302,222 @@ re_compile_pattern(pattern, size, bufp) } /* Read in characters and ranges, setting map bits. */ - for (;;) - { - int size; - unsigned last = (unsigned)-1; - - if ((size = EXTRACT_UNSIGNED(&b[(1 << BYTEWIDTH) / BYTEWIDTH])) - || current_mbctype) { - /* Ensure the space is enough to hold another interval - of multi-byte chars in charset(_not)?. */ - size = (1 << BYTEWIDTH) / BYTEWIDTH + 2 + size*8 + 8; - while (b + size + 1 > bufp->buffer + bufp->allocated) - EXTEND_BUFFER; + for (;;) { + int size; + unsigned last = (unsigned)-1; + + if ((size = EXTRACT_UNSIGNED(&b[(1 << BYTEWIDTH) / BYTEWIDTH])) + || current_mbctype) { + /* Ensure the space is enough to hold another interval + of multi-byte chars in charset(_not)?. */ + size = (1 << BYTEWIDTH) / BYTEWIDTH + 2 + size*8 + 8; + while (b + size + 1 > bufp->buffer + bufp->allocated) + EXTEND_BUFFER; + } + range_retry: + PATFETCH(c); + + if (c == ']') { + if (p == p0 + 1) { + if (p == pend) + goto invalid_pattern; } - range_retry: - PATFETCH(c); + else + /* Stop if this isn't merely a ] inside a bracket + expression, but rather the end of a bracket + expression. */ + break; + } + /* Look ahead to see if it's a range when the last thing + was a character class. */ + if (had_char_class && c == '-' && *p != ']') + goto invalid_pattern; + if (ismbchar(c)) { + PATFETCH_MBC(c); + had_mbchar++; + } - if (c == ']') { - if (p == p0 + 1) { - if (p == pend) - goto invalid_pattern; + /* \ escapes characters when inside [...]. */ + if (c == '\\') { + PATFETCH(c); + switch (c) { + case 'w': + for (c = 0; c < (1 << BYTEWIDTH); c++) { + if (SYNTAX(c) == Sword || + (!current_mbctype && SYNTAX(c) == Sword2)) + SET_LIST_BIT(c); } - else - /* Stop if this isn't merely a ] inside a bracket - expression, but rather the end of a bracket - expression. */ - break; - } - /* Look ahead to see if it's a range when the last thing - was a character class. */ - if (had_char_class && c == '-' && *p != ']') - goto invalid_pattern; - if (ismbchar(c)) { - PATFETCH_MBC(c); - had_mbchar++; - } + if (current_mbctype) { + set_list_bits(0x80, 0xffffffff, b); + } + last = -1; + continue; - /* \ escapes characters when inside [...]. */ - if (c == '\\') { - PATFETCH(c); - switch (c) { - case 'w': - for (c = 0; c < (1 << BYTEWIDTH); c++) { - if (SYNTAX(c) == Sword || - (!current_mbctype && SYNTAX(c) == Sword2)) - SET_LIST_BIT(c); - } - if (current_mbctype) { - set_list_bits(0x80, 0xffffffff, b); - } - last = -1; - continue; + case 'W': + for (c = 0; c < (1 << BYTEWIDTH); c++) { + if (SYNTAX(c) != Sword && + (current_mbctype || SYNTAX(c) != Sword2)) + SET_LIST_BIT(c); + } + last = -1; + continue; - case 'W': - for (c = 0; c < (1 << BYTEWIDTH); c++) { - if (SYNTAX(c) != Sword && - (current_mbctype || SYNTAX(c) != Sword2)) - SET_LIST_BIT(c); - } - last = -1; - continue; + case 's': + for (c = 0; c < 256; c++) + if (ISSPACE(c)) + SET_LIST_BIT(c); + last = -1; + continue; - case 's': - for (c = 0; c < 256; c++) - if (ISSPACE(c)) - SET_LIST_BIT(c); - last = -1; - continue; + case 'S': + for (c = 0; c < 256; c++) + if (!ISSPACE(c)) + SET_LIST_BIT(c); + if (current_mbctype) + set_list_bits(0x80, 0xffffffff, b); + last = -1; + continue; - case 'S': - for (c = 0; c < 256; c++) - if (!ISSPACE(c)) - SET_LIST_BIT(c); - if (current_mbctype) { - set_list_bits(0x80, 0xffffffff, b); - } - last = -1; - continue; + case 'd': + for (c = '0'; c <= '9'; c++) + SET_LIST_BIT(c); + last = -1; + continue; - case 'd': - for (c = '0'; c <= '9'; c++) + case 'D': + for (c = 0; c < 256; c++) + if (!ISDIGIT(c)) SET_LIST_BIT(c); - last = -1; - continue; - - case 'D': - for (c = 0; c < 256; c++) - if (!ISDIGIT(c)) - SET_LIST_BIT(c); - if (current_mbctype) { - set_list_bits(0x80, 0xffffffff, b); - } - last = -1; - continue; + if (current_mbctype) + set_list_bits(0x80, 0xffffffff, b); + last = -1; + continue; - case 'x': - c = scan_hex(p, 2, &numlen); - p += numlen; - break; + case 'x': + c = scan_hex(p, 2, &numlen); + p += numlen; + break; - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - PATUNFETCH; - c = scan_oct(p, 3, &numlen); - p += numlen; - break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + PATUNFETCH; + c = scan_oct(p, 3, &numlen); + p += numlen; + break; - default: - if (ismbchar(c)) { - PATFETCH_MBC(c); - had_mbchar++; - } - break; + default: + if (ismbchar(c)) { + PATFETCH_MBC(c); + had_mbchar++; } + break; } + } - /* Get a range. */ - if (range) { - if (last > c) - goto invalid_pattern; + /* Get a range. */ + if (range) { + if (last > c) + goto invalid_pattern; - range = 0; - if (had_mbchar == 0) { - for (;last<=c;last++) - SET_LIST_BIT(last); - } - else if (had_mbchar == 2) { - set_list_bits(last, c, b); - } - else { - /* restriction: range between sbc and mbc */ - goto invalid_pattern; - } + range = 0; + if (had_mbchar == 0) { + for (;last<=c;last++) + SET_LIST_BIT(last); } - else if (p[0] == '-' && p[1] != ']') { - last = c; - PATFETCH(c1); - range = 1; - goto range_retry; + else if (had_mbchar == 2) { + set_list_bits(last, c, b); } - else if (c == '[' && *p == ':') { - /* Leave room for the null. */ - char str[CHAR_CLASS_MAX_LENGTH + 1]; + else { + /* restriction: range between sbc and mbc */ + goto invalid_pattern; + } + } + else if (p[0] == '-' && p[1] != ']') { + last = c; + PATFETCH(c1); + range = 1; + goto range_retry; + } + else if (c == '[' && *p == ':') { + /* Leave room for the null. */ + char str[CHAR_CLASS_MAX_LENGTH + 1]; - PATFETCH_RAW (c); - c1 = 0; + PATFETCH_RAW (c); + c1 = 0; + + /* If pattern is `[[:'. */ + if (p == pend) + goto invalid_pattern; + + for (;;) { + PATFETCH (c); + if (c == ':' || c == ']' || p == pend + || c1 == CHAR_CLASS_MAX_LENGTH) + break; + str[c1++] = c; + } + str[c1] = '\0'; + + /* If isn't a word bracketed by `[:' and:`]': + undo the ending character, the letters, and leave + the leading `:' and `[' (but set bits for them). */ + if (c == ':' && *p == ']') { + int ch; + char is_alnum = STREQ(str, "alnum"); + char is_alpha = STREQ(str, "alpha"); + char is_blank = STREQ(str, "blank"); + char is_cntrl = STREQ(str, "cntrl"); + char is_digit = STREQ(str, "digit"); + char is_graph = STREQ(str, "graph"); + char is_lower = STREQ(str, "lower"); + char is_print = STREQ(str, "print"); + char is_punct = STREQ(str, "punct"); + char is_space = STREQ(str, "space"); + char is_upper = STREQ(str, "upper"); + char is_xdigit = STREQ(str, "xdigit"); + + if (!IS_CHAR_CLASS (str)) + goto invalid_pattern; + + /* Throw away the ] at the end of the character class. */ + PATFETCH (c); - /* If pattern is `[[:'. */ if (p == pend) goto invalid_pattern; - for (;;) { - PATFETCH (c); - if (c == ':' || c == ']' || p == pend - || c1 == CHAR_CLASS_MAX_LENGTH) - break; - str[c1++] = c; - } - str[c1] = '\0'; - - /* If isn't a word bracketed by `[:' and:`]': - undo the ending character, the letters, and leave - the leading `:' and `[' (but set bits for them). */ - if (c == ':' && *p == ']') { - int ch; - char is_alnum = STREQ(str, "alnum"); - char is_alpha = STREQ(str, "alpha"); - char is_blank = STREQ(str, "blank"); - char is_cntrl = STREQ(str, "cntrl"); - char is_digit = STREQ(str, "digit"); - char is_graph = STREQ(str, "graph"); - char is_lower = STREQ(str, "lower"); - char is_print = STREQ(str, "print"); - char is_punct = STREQ(str, "punct"); - char is_space = STREQ(str, "space"); - char is_upper = STREQ(str, "upper"); - char is_xdigit = STREQ(str, "xdigit"); - - if (!IS_CHAR_CLASS (str)) - goto invalid_pattern; - - /* Throw away the ] at the end of the character class. */ - PATFETCH (c); - - if (p == pend) - goto invalid_pattern; - - for (ch = 0; ch < 1 << BYTEWIDTH; ch++) { - if ( (is_alnum && ISALNUM(ch)) - || (is_alpha && ISALPHA(ch)) - || (is_blank && ISBLANK(ch)) - || (is_cntrl && ISCNTRL(ch)) - || (is_digit && ISDIGIT(ch)) - || (is_graph && ISGRAPH(ch)) - || (is_lower && ISLOWER(ch)) - || (is_print && ISPRINT(ch)) - || (is_punct && ISPUNCT(ch)) - || (is_space && ISSPACE(ch)) - || (is_upper && ISUPPER(ch)) - || (is_xdigit && ISXDIGIT(ch))) - SET_LIST_BIT (ch); - } - had_char_class = 1; - } - else { - c1++; - while (c1--) - PATUNFETCH; - SET_LIST_BIT(translate?translate['[']:'['); - SET_LIST_BIT(translate?translate[':']:':'); - had_char_class = 0; - last = ':'; + for (ch = 0; ch < 1 << BYTEWIDTH; ch++) { + if ( (is_alnum && ISALNUM(ch)) + || (is_alpha && ISALPHA(ch)) + || (is_blank && ISBLANK(ch)) + || (is_cntrl && ISCNTRL(ch)) + || (is_digit && ISDIGIT(ch)) + || (is_graph && ISGRAPH(ch)) + || (is_lower && ISLOWER(ch)) + || (is_print && ISPRINT(ch)) + || (is_punct && ISPUNCT(ch)) + || (is_space && ISSPACE(ch)) + || (is_upper && ISUPPER(ch)) + || (is_xdigit && ISXDIGIT(ch))) + SET_LIST_BIT (ch); } + had_char_class = 1; + } + else { + c1++; + while (c1--) + PATUNFETCH; + SET_LIST_BIT(TRANSLATE_P()?translate['[']:'['); + SET_LIST_BIT(TRANSLATE_P()?translate[':']:':'); + had_char_class = 0; + last = ':'; } - else if (had_mbchar == 0) - SET_LIST_BIT(c); - else - set_list_bits(c, c, b); - had_mbchar = 0; } + else if (had_mbchar == 0) + SET_LIST_BIT(c); + else + set_list_bits(c, c, b); + had_mbchar = 0; + } /* Discard any character set/class bitmap bytes that are all 0 at the end of the map. Decrement the map-length byte too. */ @@ -1680,17 +1675,17 @@ re_compile_pattern(pattern, size, bufp) BUFPUSH((options&RE_OPTION_POSIX)?posix_off:posix_on); } pending_exact = 0; - if (fixup_alt_jump) - { /* Push a dummy failure point at the end of the - alternative for a possible future - `finalize_jump' to pop. See comments at - `push_dummy_failure' in `re_match'. */ - BUFPUSH(push_dummy_failure); - - /* We allocated space for this jump when we assigned - to `fixup_alt_jump', in the `handle_alt' case below. */ - store_jump(fixup_alt_jump, jump, b); - } + if (fixup_alt_jump) { + /* Push a dummy failure point at the end of the + alternative for a possible future + `finalize_jump' to pop. See comments at + `push_dummy_failure' in `re_match'. */ + BUFPUSH(push_dummy_failure); + + /* We allocated space for this jump when we assigned + to `fixup_alt_jump', in the `handle_alt' case below. */ + store_jump(fixup_alt_jump, jump, b); + } options = *--stackp; switch (c = *--stackp) { case '(': @@ -1772,10 +1767,9 @@ re_compile_pattern(pattern, size, bufp) case '{': /* If there is no previous pattern, this isn't an interval. */ - if (!laststart || p == pend) - { - goto normal_char; - } + if (!laststart || p == pend) { + goto normal_char; + } beg_interval = p - 1; @@ -1872,37 +1866,37 @@ re_compile_pattern(pattern, size, bufp) insert_op_2(set_number_at, laststart, b, 5, lower_bound); b += 5; - if (upper_bound > 1) - { /* More than one repetition is allowed, so - append a backward jump to the `succeed_n' - that starts this interval. - - When we've reached this during matching, - we'll have matched the interval once, so - jump back only `upper_bound - 1' times. */ - GET_BUFFER_SPACE(5); - store_jump_n(b, greedy?jump_n:finalize_push_n, laststart + 5, - upper_bound - 1); - b += 5; - - /* The location we want to set is the second - parameter of the `jump_n'; that is `b-2' as - an absolute address. `laststart' will be - the `set_number_at' we're about to insert; - `laststart+3' the number to set, the source - for the relative address. But we are - inserting into the middle of the pattern -- - so everything is getting moved up by 5. - Conclusion: (b - 2) - (laststart + 3) + 5, - i.e., b - laststart. - - We insert this at the beginning of the loop - so that if we fail during matching, we'll - reinitialize the bounds. */ - insert_op_2(set_number_at, laststart, b, b - laststart, - upper_bound - 1); - b += 5; - } + if (upper_bound > 1) { + /* More than one repetition is allowed, so + append a backward jump to the `succeed_n' + that starts this interval. + + When we've reached this during matching, + we'll have matched the interval once, so + jump back only `upper_bound - 1' times. */ + GET_BUFFER_SPACE(5); + store_jump_n(b, greedy?jump_n:finalize_push_n, laststart + 5, + upper_bound - 1); + b += 5; + + /* The location we want to set is the second + parameter of the `jump_n'; that is `b-2' as + an absolute address. `laststart' will be + the `set_number_at' we're about to insert; + `laststart+3' the number to set, the source + for the relative address. But we are + inserting into the middle of the pattern -- + so everything is getting moved up by 5. + Conclusion: (b - 2) - (laststart + 3) + 5, + i.e., b - laststart. + + We insert this at the beginning of the loop + so that if we fail during matching, we'll + reinitialize the bounds. */ + insert_op_2(set_number_at, laststart, b, b - laststart, + upper_bound - 1); + b += 5; + } } break; @@ -1921,149 +1915,147 @@ re_compile_pattern(pattern, size, bufp) distinguish, e.g., \B from \b, even if we normally would translate, e.g., B to b. */ PATFETCH_RAW(c); - switch (c) - { - case 's': - case 'S': - case 'd': - case 'D': - while (b - bufp->buffer + 9 + (1 << BYTEWIDTH) / BYTEWIDTH - > bufp->allocated) - EXTEND_BUFFER; + switch (c) { + case 's': + case 'S': + case 'd': + case 'D': + while (b - bufp->buffer + 9 + (1 << BYTEWIDTH) / BYTEWIDTH + > bufp->allocated) + EXTEND_BUFFER; - laststart = b; - if (c == 's' || c == 'd') { - BUFPUSH(charset); - } - else { - BUFPUSH(charset_not); - } + laststart = b; + if (c == 's' || c == 'd') { + BUFPUSH(charset); + } + else { + BUFPUSH(charset_not); + } - BUFPUSH((1 << BYTEWIDTH) / BYTEWIDTH); - memset(b, 0, (1 << BYTEWIDTH) / BYTEWIDTH + 2); - if (c == 's' || c == 'S') { - SET_LIST_BIT(' '); - SET_LIST_BIT('\t'); - SET_LIST_BIT('\n'); - SET_LIST_BIT('\r'); - SET_LIST_BIT('\f'); - } - else { - char cc; + BUFPUSH((1 << BYTEWIDTH) / BYTEWIDTH); + memset(b, 0, (1 << BYTEWIDTH) / BYTEWIDTH + 2); + if (c == 's' || c == 'S') { + SET_LIST_BIT(' '); + SET_LIST_BIT('\t'); + SET_LIST_BIT('\n'); + SET_LIST_BIT('\r'); + SET_LIST_BIT('\f'); + } + else { + char cc; - for (cc = '0'; cc <= '9'; cc++) { - SET_LIST_BIT(cc); - } + for (cc = '0'; cc <= '9'; cc++) { + SET_LIST_BIT(cc); } + } - while ((int)b[-1] > 0 && b[b[-1] - 1] == 0) - b[-1]--; - if (b[-1] != (1 << BYTEWIDTH) / BYTEWIDTH) - memmove(&b[b[-1]], &b[(1 << BYTEWIDTH) / BYTEWIDTH], - 2 + EXTRACT_UNSIGNED(&b[(1 << BYTEWIDTH) / BYTEWIDTH])*8); - b += b[-1] + 2 + EXTRACT_UNSIGNED(&b[b[-1]])*8; - break; - - case 'w': - laststart = b; - BUFPUSH(wordchar); - break; - - case 'W': - laststart = b; - BUFPUSH(notwordchar); - break; + while ((int)b[-1] > 0 && b[b[-1] - 1] == 0) + b[-1]--; + if (b[-1] != (1 << BYTEWIDTH) / BYTEWIDTH) + memmove(&b[b[-1]], &b[(1 << BYTEWIDTH) / BYTEWIDTH], + 2 + EXTRACT_UNSIGNED(&b[(1 << BYTEWIDTH) / BYTEWIDTH])*8); + b += b[-1] + 2 + EXTRACT_UNSIGNED(&b[b[-1]])*8; + break; - case '<': - BUFPUSH(wordbeg); - break; + case 'w': + laststart = b; + BUFPUSH(wordchar); + break; - case '>': - BUFPUSH(wordend); - break; + case 'W': + laststart = b; + BUFPUSH(notwordchar); + break; - case 'b': - BUFPUSH(wordbound); - break; + case '<': + BUFPUSH(wordbeg); + break; - case 'B': - BUFPUSH(notwordbound); - break; + case '>': + BUFPUSH(wordend); + break; - case 'A': - BUFPUSH(begbuf); - break; + case 'b': + BUFPUSH(wordbound); + break; - case 'Z': - BUFPUSH(endbuf2); - break; + case 'B': + BUFPUSH(notwordbound); + break; - case 'z': - BUFPUSH(endbuf); - break; + case 'A': + BUFPUSH(begbuf); + break; - /* hex */ - case 'x': - had_mbchar = 0; - c = scan_hex(p, 2, &numlen); - p += numlen; - goto numeric_char; + case 'Z': + BUFPUSH(endbuf2); + break; - /* octal */ - case '0': - had_mbchar = 0; - c = scan_oct(p, 3, &numlen); - p += numlen; - goto numeric_char; + case 'z': + BUFPUSH(endbuf); + break; - /* back-ref or octal */ - case '1': case '2': case '3': - case '4': case '5': case '6': - case '7': case '8': case '9': - { - const char *p_save; + /* hex */ + case 'x': + had_mbchar = 0; + c = scan_hex(p, 2, &numlen); + p += numlen; + goto numeric_char; + + /* octal */ + case '0': + had_mbchar = 0; + c = scan_oct(p, 3, &numlen); + p += numlen; + goto numeric_char; + + /* back-ref or octal */ + case '1': case '2': case '3': + case '4': case '5': case '6': + case '7': case '8': case '9': + { + const char *p_save; - PATUNFETCH; - p_save = p; + PATUNFETCH; + p_save = p; - had_mbchar = 0; + had_mbchar = 0; + c1 = 0; + GET_UNSIGNED_NUMBER(c1); + if (!ISDIGIT(c)) PATUNFETCH; + + if (c1 >= regnum) { + /* need to get octal */ + p = p_save; + c = scan_oct(p_save, 3, &numlen) & 0xff; + p = p_save + numlen; c1 = 0; - GET_UNSIGNED_NUMBER(c1); - if (!ISDIGIT(c)) PATUNFETCH; - - if (c1 >= regnum) { - /* need to get octal */ - p = p_save; - c = scan_oct(p_save, 3, &numlen) & 0xff; - p = p_save + numlen; - c1 = 0; - goto numeric_char; - } + goto numeric_char; } + } - /* Can't back reference to a subexpression if inside of it. */ - for (stackt = stackp - 2; stackt > stackb; stackt -= 5) - if (*stackt == c1) - goto normal_char; - laststart = b; - BUFPUSH(duplicate); - BUFPUSH(c1); - break; + /* Can't back reference to a subexpression if inside of it. */ + for (stackt = stackp - 2; stackt > stackb; stackt -= 5) + if (*stackt == c1) + goto normal_char; + laststart = b; + BUFPUSH(duplicate); + BUFPUSH(c1); + break; - default: - goto normal_char; - } + default: + goto normal_char; + } break; case '#': - if (options & RE_OPTION_EXTENDED) - { - while (p != pend) { - PATFETCH(c); - if (c == '\n') break; - } - break; + if (options & RE_OPTION_EXTENDED) { + while (p != pend) { + PATFETCH(c); + if (c == '\n') break; } + break; + } goto normal_char; case ' ': @@ -2503,303 +2495,300 @@ re_compile_fastmap(bufp) while (p) { is_a_succeed_n = 0; - if (p == pend) - { - bufp->can_be_null = 1; - break; - } + if (p == pend) { + bufp->can_be_null = 1; + break; + } #ifdef SWITCH_ENUM_BUG switch ((int)((enum regexpcode)*p++)) #else - switch ((enum regexpcode)*p++) + switch ((enum regexpcode)*p++) #endif - { - case exactn: - if (p[1] == 0xff) { - if (TRANSLATE_P()) - fastmap[translate[p[2]]] = 2; - else - fastmap[p[2]] = 2; - } - else if (TRANSLATE_P()) - fastmap[translate[p[1]]] = 1; + { + case exactn: + if (p[1] == 0xff) { + if (TRANSLATE_P()) + fastmap[translate[p[2]]] = 2; else - fastmap[p[1]] = 1; - break; + fastmap[p[2]] = 2; + } + else if (TRANSLATE_P()) + fastmap[translate[p[1]]] = 1; + else + fastmap[p[1]] = 1; + break; - case begline: - case begbuf: - case endbuf: - case endbuf2: - case wordbound: - case notwordbound: - case wordbeg: - case wordend: - case pop_and_fail: - case push_dummy_failure: - case stop_paren: - continue; + case begline: + case begbuf: + case endbuf: + case endbuf2: + case wordbound: + case notwordbound: + case wordbeg: + case wordend: + case pop_and_fail: + case push_dummy_failure: + case stop_paren: + continue; - case casefold_on: - bufp->options |= RE_MAY_IGNORECASE; - case casefold_off: - options ^= RE_OPTION_IGNORECASE; - continue; + case casefold_on: + bufp->options |= RE_MAY_IGNORECASE; + case casefold_off: + options ^= RE_OPTION_IGNORECASE; + continue; - case posix_on: - case posix_off: - options ^= RE_OPTION_POSIX; - continue; + case posix_on: + case posix_off: + options ^= RE_OPTION_POSIX; + continue; - case endline: - if (TRANSLATE_P()) - fastmap[translate['\n']] = 1; - else - fastmap['\n'] = 1; + case endline: + if (TRANSLATE_P()) + fastmap[translate['\n']] = 1; + else + fastmap['\n'] = 1; - if (bufp->can_be_null == 0) - bufp->can_be_null = 2; - break; + if (bufp->can_be_null == 0) + bufp->can_be_null = 2; + break; - case jump_n: - case finalize_jump: - case maybe_finalize_jump: - case jump: - case jump_past_alt: - case dummy_failure_jump: - EXTRACT_NUMBER_AND_INCR(j, p); - p += j; - if (j > 0) - continue; - /* Jump backward reached implies we just went through - the body of a loop and matched nothing. - Opcode jumped to should be an on_failure_jump. - Just treat it like an ordinary jump. - For a * loop, it has pushed its failure point already; - If so, discard that as redundant. */ - - if ((enum regexpcode)*p != on_failure_jump - && (enum regexpcode)*p != try_next - && (enum regexpcode)*p != succeed_n - && (enum regexpcode)*p != finalize_push - && (enum regexpcode)*p != finalize_push_n) - continue; - p++; - EXTRACT_NUMBER_AND_INCR(j, p); - p += j; - if (stackp != stackb && *stackp == p) - stackp--; /* pop */ + case jump_n: + case finalize_jump: + case maybe_finalize_jump: + case jump: + case jump_past_alt: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR(j, p); + p += j; + if (j > 0) continue; - - case start_nowidth: - case stop_nowidth: - case finalize_push: - p += 2; + /* Jump backward reached implies we just went through + the body of a loop and matched nothing. + Opcode jumped to should be an on_failure_jump. + Just treat it like an ordinary jump. + For a * loop, it has pushed its failure point already; + If so, discard that as redundant. */ + + if ((enum regexpcode)*p != on_failure_jump + && (enum regexpcode)*p != try_next + && (enum regexpcode)*p != succeed_n + && (enum regexpcode)*p != finalize_push + && (enum regexpcode)*p != finalize_push_n) continue; + p++; + EXTRACT_NUMBER_AND_INCR(j, p); + p += j; + if (stackp != stackb && *stackp == p) + stackp--; /* pop */ + continue; - case finalize_push_n: - p += 4; - continue; + case start_nowidth: + case stop_nowidth: + case finalize_push: + p += 2; + continue; - case try_next: - case on_failure_jump: - handle_on_failure_jump: - EXTRACT_NUMBER_AND_INCR(j, p); - if (p + j < pend) { - if (stackp == stacke) { - unsigned char **stackx; - unsigned int len = stacke - stackb; + case finalize_push_n: + p += 4; + continue; - EXPAND_FAIL_STACK(stackx, stackb, len); - } - *++stackp = p + j; /* push */ + case try_next: + case on_failure_jump: + handle_on_failure_jump: + EXTRACT_NUMBER_AND_INCR(j, p); + if (p + j < pend) { + if (stackp == stacke) { + unsigned char **stackx; + unsigned int len = stacke - stackb; + + EXPAND_FAIL_STACK(stackx, stackb, len); + } + *++stackp = p + j; /* push */ + } + else { + bufp->can_be_null = 1; + } + if (is_a_succeed_n) + EXTRACT_NUMBER_AND_INCR(k, p); /* Skip the n. */ + continue; + + case succeed_n: + is_a_succeed_n = 1; + /* Get to the number of times to succeed. */ + EXTRACT_NUMBER(k, p + 2); + /* Increment p past the n for when k != 0. */ + if (k == 0) { + p += 4; } else { - bufp->can_be_null = 1; + goto handle_on_failure_jump; } - if (is_a_succeed_n) - EXTRACT_NUMBER_AND_INCR(k, p); /* Skip the n. */ continue; - case succeed_n: - is_a_succeed_n = 1; - /* Get to the number of times to succeed. */ - EXTRACT_NUMBER(k, p + 2); - /* Increment p past the n for when k != 0. */ - if (k == 0) { - p += 4; - } - else { - goto handle_on_failure_jump; - } - continue; - - case set_number_at: - p += 4; - continue; + case set_number_at: + p += 4; + continue; - case start_memory: - case stop_memory: - p += 2; - continue; + case start_memory: + case stop_memory: + p += 2; + continue; - case duplicate: - bufp->can_be_null = 1; - fastmap['\n'] = 1; - case anychar: - { - char ex = (options & RE_OPTION_POSIX)?'\0':'\n'; + case duplicate: + bufp->can_be_null = 1; + fastmap['\n'] = 1; + case anychar: + { + char ex = (options & RE_OPTION_POSIX)?'\0':'\n'; - for (j = 0; j < (1 << BYTEWIDTH); j++) { - if (j != ex) fastmap[j] = 1; - } - if (bufp->can_be_null) { - FREE_AND_RETURN_VOID(stackb); - } + for (j = 0; j < (1 << BYTEWIDTH); j++) { + if (j != ex) fastmap[j] = 1; } - /* Don't return; check the alternative paths - so we can set can_be_null if appropriate. */ - break; + if (bufp->can_be_null) { + FREE_AND_RETURN_VOID(stackb); + } + } + /* Don't return; check the alternative paths + so we can set can_be_null if appropriate. */ + break; - case wordchar: - for (j = 0; j < 0x80; j++) { - if (SYNTAX(j) == Sword) + case wordchar: + for (j = 0; j < 0x80; j++) { + if (SYNTAX(j) == Sword) + fastmap[j] = 1; + } + switch (current_mbctype) { + case MBCTYPE_ASCII: + for (j = 0x80; j < (1 << BYTEWIDTH); j++) { + if (SYNTAX(j) == Sword2) fastmap[j] = 1; } - switch (current_mbctype) { - case MBCTYPE_ASCII: - for (j = 0x80; j < (1 << BYTEWIDTH); j++) { - if (SYNTAX(j) == Sword2) - fastmap[j] = 1; - } - break; - case MBCTYPE_EUC: - case MBCTYPE_SJIS: - case MBCTYPE_UTF8: - for (j = 0x80; j < (1 << BYTEWIDTH); j++) { - if (re_mbctab[j]) - fastmap[j] = 1; - } - break; + break; + case MBCTYPE_EUC: + case MBCTYPE_SJIS: + case MBCTYPE_UTF8: + for (j = 0x80; j < (1 << BYTEWIDTH); j++) { + if (re_mbctab[j]) + fastmap[j] = 1; } break; + } + break; - case notwordchar: - for (j = 0; j < 0x80; j++) - if (SYNTAX(j) != Sword) + case notwordchar: + for (j = 0; j < 0x80; j++) + if (SYNTAX(j) != Sword) + fastmap[j] = 1; + switch (current_mbctype) { + case MBCTYPE_ASCII: + for (j = 0x80; j < (1 << BYTEWIDTH); j++) { + if (SYNTAX(j) != Sword2) + fastmap[j] = 1; + } + break; + case MBCTYPE_EUC: + case MBCTYPE_SJIS: + case MBCTYPE_UTF8: + for (j = 0x80; j < (1 << BYTEWIDTH); j++) { + if (!re_mbctab[j]) fastmap[j] = 1; - switch (current_mbctype) { - case MBCTYPE_ASCII: - for (j = 0x80; j < (1 << BYTEWIDTH); j++) { - if (SYNTAX(j) != Sword2) - fastmap[j] = 1; - } - break; - case MBCTYPE_EUC: - case MBCTYPE_SJIS: - case MBCTYPE_UTF8: - for (j = 0x80; j < (1 << BYTEWIDTH); j++) { - if (!re_mbctab[j]) - fastmap[j] = 1; - } - break; } break; + } + break; - case charset: - /* NOTE: Charset for single-byte chars never contain - multi-byte char. See set_list_bits(). */ - for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) - if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) - { - if (TRANSLATE_P()) - j = translate[j]; - fastmap[j] = (j>0x7f?(ismbchar(j)?0:2):1); - } - { - unsigned short size; - unsigned int c, beg, end; - - p += p[-1] + 2; - size = EXTRACT_UNSIGNED(&p[-2]); - for (j = 0; j < (int)size; j++) { - c = EXTRACT_MBC(&p[j*8]); - beg = WC2MBC1ST(c); - c = EXTRACT_MBC(&p[j*8+4]); - end = WC2MBC1ST(c); - /* set bits for 1st bytes of multi-byte chars. */ - while (beg <= end) { - /* NOTE: Charset for multi-byte chars might contain - single-byte chars. We must reject them. */ - if (ismbchar(beg)) - fastmap[beg] = 1; - beg++; - } + case charset: + /* NOTE: Charset for single-byte chars never contain + multi-byte char. See set_list_bits(). */ + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) { + if (TRANSLATE_P()) + j = translate[j]; + fastmap[j] = (j>0x7f?(ismbchar(j)?0:2):1); + } + { + unsigned short size; + unsigned int c, beg, end; + + p += p[-1] + 2; + size = EXTRACT_UNSIGNED(&p[-2]); + for (j = 0; j < (int)size; j++) { + c = EXTRACT_MBC(&p[j*8]); + beg = WC2MBC1ST(c); + c = EXTRACT_MBC(&p[j*8+4]); + end = WC2MBC1ST(c); + /* set bits for 1st bytes of multi-byte chars. */ + while (beg <= end) { + /* NOTE: Charset for multi-byte chars might contain + single-byte chars. We must reject them. */ + if (ismbchar(beg)) + fastmap[beg] = 1; + beg++; } } - break; + } + break; - case charset_not: - /* S: set of all single-byte chars. - M: set of all first bytes that can start multi-byte chars. - s: any set of single-byte chars. - m: any set of first bytes that can start multi-byte chars. - - We assume S+M = U. - ___ _ _ - s+m = (S*s+M*m). */ - /* Chars beyond end of map must be allowed */ - /* NOTE: Charset_not for single-byte chars might contain - multi-byte chars. See set_list_bits(). */ - for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) + case charset_not: + /* S: set of all single-byte chars. + M: set of all first bytes that can start multi-byte chars. + s: any set of single-byte chars. + m: any set of first bytes that can start multi-byte chars. + + We assume S+M = U. + ___ _ _ + s+m = (S*s+M*m). */ + /* Chars beyond end of map must be allowed */ + /* NOTE: Charset_not for single-byte chars might contain + multi-byte chars. See set_list_bits(). */ + for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) + if (!ismbchar(j)) + fastmap[j] = 1; + + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) { if (!ismbchar(j)) fastmap[j] = 1; - - for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + } + if (current_mbctype) { + for (j = 0x80; j < (1 << BYTEWIDTH); j++) if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) - { - if (!ismbchar(j)) - fastmap[j] = 1; - } - if (current_mbctype) { + fastmap[j] = 2; + } + { + unsigned short size; + unsigned int c, beg, end; + + p += p[-1] + 2; + size = EXTRACT_UNSIGNED(&p[-2]); + if (size == 0) { for (j = 0x80; j < (1 << BYTEWIDTH); j++) - if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) - fastmap[j] = 2; + if (ismbchar(j)) + fastmap[j] = 1; + break; } - { - unsigned short size; - unsigned int c, beg, end; - - p += p[-1] + 2; - size = EXTRACT_UNSIGNED(&p[-2]); - if (size == 0) { - for (j = 0x80; j < (1 << BYTEWIDTH); j++) - if (ismbchar(j)) - fastmap[j] = 1; - break; - } - for (j = 0,c = 0x80;j < (int)size; j++) { - int cc = EXTRACT_MBC(&p[j*8]); - beg = WC2MBC1ST(cc); - while (c < beg) { - if (ismbchar(c)) - fastmap[c] = 1; - c++; - } - - cc = EXTRACT_MBC(&p[j*8+4]); - c = WC2MBC1ST(cc) + 1; + for (j = 0,c = 0x80;j < (int)size; j++) { + int cc = EXTRACT_MBC(&p[j*8]); + beg = WC2MBC1ST(cc); + while (c < beg) { + if (ismbchar(c)) + fastmap[c] = 1; + c++; } - for (j = c; j < (1 << BYTEWIDTH); j++) - if (ismbchar(j)) - fastmap[j] = 1; + cc = EXTRACT_MBC(&p[j*8+4]); + c = WC2MBC1ST(cc) + 1; } - break; - case unused: /* pacify gcc -Wall */ - break; + for (j = c; j < (1 << BYTEWIDTH); j++) + if (ismbchar(j)) + fastmap[j] = 1; } + break; + + case unused: /* pacify gcc -Wall */ + break; + } /* Get here means we have successfully found the possible starting characters of one path of the pattern. We need not follow this @@ -2907,45 +2896,42 @@ re_search(bufp, string, size, startpos, range, regs) string we get. */ if (fastmap && startpos < size - && bufp->can_be_null != 1 && !(anchor && startpos == 0)) - { - if (range > 0) /* Searching forwards. */ - { - register unsigned char *p, c; - int irange = range; + && bufp->can_be_null != 1 && !(anchor && startpos == 0)) { + if (range > 0) { /* Searching forwards. */ + register unsigned char *p, c; + int irange = range; - p = (unsigned char*)string+startpos; + p = (unsigned char*)string+startpos; - while (range > 0) { - c = *p++; - if (ismbchar(c)) { - int len = mbclen(c) - 1; - if (fastmap[c]) - break; - p += len; - range -= len + 1; - c = *p; - if (fastmap[c] == 2) - break; - } - else { - if (fastmap[MAY_TRANSLATE() ? translate[c] : c]) - break; - range--; - } - } - startpos += irange - range; + while (range > 0) { + c = *p++; + if (ismbchar(c)) { + int len = mbclen(c) - 1; + if (fastmap[c]) + break; + p += len; + range -= len + 1; + c = *p; + if (fastmap[c] == 2) + break; } - else /* Searching backwards. */ - { - register unsigned char c; - - c = string[startpos]; - c &= 0xff; - if (MAY_TRANSLATE() ? !fastmap[translate[c]] : !fastmap[c]) - goto advance; + else { + if (fastmap[MAY_TRANSLATE() ? translate[c] : c]) + break; + range--; } + } + startpos += irange - range; } + else { /* Searching backwards. */ + register unsigned char c; + + c = string[startpos]; + c &= 0xff; + if (MAY_TRANSLATE() ? !fastmap[translate[c]] : !fastmap[c]) + goto advance; + } + } if (startpos > size) return -1; if (anchor && size > 0 && startpos == size) return -1; @@ -3331,66 +3317,60 @@ re_match(bufp, string_arg, size, pos, regs) *p); #endif /* End of pattern means we might have succeeded. */ - if (p == pend) - { - /* If not end of string, try backtracking. Otherwise done. */ - if (d != dend) - { - while (stackp != stackb && (int)stackp[-1] == 1) { - if (best_regs_set) /* non-greedy, no need to backtrack */ - goto restore_best_regs; - POP_FAILURE_POINT(); - } - if (stackp != stackb) { - /* More failure points to try. */ + if (p == pend) { + /* If not end of string, try backtracking. Otherwise done. */ + if (d != dend) { + while (stackp != stackb && (int)stackp[-1] == 1) { + if (best_regs_set) /* non-greedy, no need to backtrack */ + goto restore_best_regs; + POP_FAILURE_POINT(); + } + if (stackp != stackb) { + /* More failure points to try. */ - /* If exceeds best match so far, save it. */ - if (! best_regs_set || (d > best_regend[0])) { - best_regs_set = 1; - best_regend[0] = d; /* Never use regstart[0]. */ + /* If exceeds best match so far, save it. */ + if (! best_regs_set || (d > best_regend[0])) { + best_regs_set = 1; + best_regend[0] = d; /* Never use regstart[0]. */ - for (mcnt = 1; mcnt < num_regs; mcnt++) { - best_regstart[mcnt] = regstart[mcnt]; - best_regend[mcnt] = regend[mcnt]; - } - } - goto fail; - } - /* If no failure points, don't restore garbage. */ - else if (best_regs_set) { - restore_best_regs: - /* Restore best match. */ - d = best_regend[0]; - - for (mcnt = 0; mcnt < num_regs; mcnt++) - { - regstart[mcnt] = best_regstart[mcnt]; - regend[mcnt] = best_regend[mcnt]; - } + for (mcnt = 1; mcnt < num_regs; mcnt++) { + best_regstart[mcnt] = regstart[mcnt]; + best_regend[mcnt] = regend[mcnt]; } } + goto fail; + } + /* If no failure points, don't restore garbage. */ + else if (best_regs_set) { + restore_best_regs: + /* Restore best match. */ + d = best_regend[0]; + + for (mcnt = 0; mcnt < num_regs; mcnt++) { + regstart[mcnt] = best_regstart[mcnt]; + regend[mcnt] = best_regend[mcnt]; + } + } + } - /* If caller wants register contents data back, convert it - to indices. */ - if (regs) - { - regs->beg[0] = pos; - regs->end[0] = d - string; - for (mcnt = 1; mcnt < num_regs; mcnt++) - { - if (REG_UNSET(regend[mcnt])) - { - regs->beg[mcnt] = -1; - regs->end[mcnt] = -1; - continue; - } - regs->beg[mcnt] = regstart[mcnt] - string; - regs->end[mcnt] = regend[mcnt] - string; - } + /* If caller wants register contents data back, convert it + to indices. */ + if (regs) { + regs->beg[0] = pos; + regs->end[0] = d - string; + for (mcnt = 1; mcnt < num_regs; mcnt++) { + if (REG_UNSET(regend[mcnt])) { + regs->beg[mcnt] = -1; + regs->end[mcnt] = -1; + continue; } - FREE_VARIABLES(); - FREE_AND_RETURN(stackb, (d - pos - string)); + regs->beg[mcnt] = regstart[mcnt] - string; + regs->end[mcnt] = regend[mcnt] - string; + } } + FREE_VARIABLES(); + FREE_AND_RETURN(stackb, (d - pos - string)); + } /* Otherwise match next pattern command. */ #ifdef SWITCH_ENUM_BUG @@ -3398,612 +3378,595 @@ re_match(bufp, string_arg, size, pos, regs) #else switch ((enum regexpcode)*p++) #endif + { + /* ( [or `(', as appropriate] is represented by start_memory, + ) by stop_memory. Both of those commands are followed by + a register number in the next byte. The text matched + within the ( and ) is recorded under that number. */ + case start_memory: + /* Find out if this group can match the empty string. */ + p1 = p; /* To send to group_match_null_string_p. */ + if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE) + REG_MATCH_NULL_STRING_P (reg_info[*p]) + = group_match_null_string_p (&p1, pend, reg_info); + + /* Save the position in the string where we were the last time + we were at this open-group operator in case the group is + operated upon by a repetition operator, e.g., with `(a*)*b' + against `ab'; then we want to ignore where we are now in + the string in case this attempt to match fails. */ + old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) + ? REG_UNSET (regstart[*p]) ? d : regstart[*p] + : regstart[*p]; + regstart[*p] = d; + IS_ACTIVE(reg_info[*p]) = 1; + MATCHED_SOMETHING(reg_info[*p]) = 0; + p += 2; + continue; + + case stop_memory: + /* We need to save the string position the last time we were at + this close-group operator in case the group is operated + upon by a repetition operator, e.g., with `((a*)*(b*)*)*' + against `aba'; then we want to ignore where we are now in + the string in case this attempt to match fails. */ + old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) + ? REG_UNSET (regend[*p]) ? d : regend[*p] + : regend[*p]; + + regend[*p] = d; + IS_ACTIVE(reg_info[*p]) = 0; + + /* If just failed to match something this time around with a sub- + expression that's in a loop, try to force exit from the loop. */ + if ((p + 1) != pend && + (! MATCHED_SOMETHING(reg_info[*p]) + || (enum regexpcode)p[-3] == start_memory)) { + p1 = p + 2; + mcnt = 0; + switch (*p1++) { + case jump_n: + case finalize_push_n: + case finalize_jump: + case maybe_finalize_jump: + case jump: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR(mcnt, p1); + break; + } + p1 += mcnt; + + /* If the next operation is a jump backwards in the pattern + to an on_failure_jump, exit from the loop by forcing a + failure after pushing on the stack the on_failure_jump's + jump in the pattern, and d. */ + if (mcnt < 0 && (enum regexpcode)*p1 == on_failure_jump + && (enum regexpcode)p1[3] == start_memory && p1[4] == *p) { + /* If this group ever matched anything, then restore + what its registers were before trying this last + failed match, e.g., with `(a*)*b' against `ab' for + regstart[1], and, e.g., with `((a*)*(b*)*)*' + against `aba' for regend[3]. + + Also restore the registers for inner groups for, + e.g., `((a*)(b*))*' against `aba' (register 3 would + otherwise get trashed). */ + + if (EVER_MATCHED_SOMETHING (reg_info[*p])) { + unsigned r; + + EVER_MATCHED_SOMETHING (reg_info[*p]) = 0; + + /* Restore this and inner groups' (if any) registers. */ + for (r = *p; r < *p + *(p + 1); r++) { + regstart[r] = old_regstart[r]; + + /* xx why this test? */ + if ((int)old_regend[r] >= (int)regstart[r]) + regend[r] = old_regend[r]; + } + } + p1++; + EXTRACT_NUMBER_AND_INCR(mcnt, p1); + PUSH_FAILURE_POINT(p1 + mcnt, d); + goto fail; + } + } + p += 2; + continue; + + case stop_paren: + break; + + /* \<digit> has been turned into a `duplicate' command which is + followed by the numeric value of <digit> as the register number. */ + case duplicate: { + int regno = *p++; /* Get which register to match against */ + register unsigned char *d2, *dend2; - /* ( [or `(', as appropriate] is represented by start_memory, - ) by stop_memory. Both of those commands are followed by - a register number in the next byte. The text matched - within the ( and ) is recorded under that number. */ - case start_memory: - /* Find out if this group can match the empty string. */ - p1 = p; /* To send to group_match_null_string_p. */ - if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE) - REG_MATCH_NULL_STRING_P (reg_info[*p]) - = group_match_null_string_p (&p1, pend, reg_info); - - /* Save the position in the string where we were the last time - we were at this open-group operator in case the group is - operated upon by a repetition operator, e.g., with `(a*)*b' - against `ab'; then we want to ignore where we are now in - the string in case this attempt to match fails. */ - old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) - ? REG_UNSET (regstart[*p]) ? d : regstart[*p] - : regstart[*p]; - regstart[*p] = d; - IS_ACTIVE(reg_info[*p]) = 1; - MATCHED_SOMETHING(reg_info[*p]) = 0; - p += 2; - continue; + if (IS_ACTIVE(reg_info[regno])) break; - case stop_memory: - /* We need to save the string position the last time we were at - this close-group operator in case the group is operated - upon by a repetition operator, e.g., with `((a*)*(b*)*)*' - against `aba'; then we want to ignore where we are now in - the string in case this attempt to match fails. */ - old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) - ? REG_UNSET (regend[*p]) ? d : regend[*p] - : regend[*p]; - - regend[*p] = d; - IS_ACTIVE(reg_info[*p]) = 0; - - /* If just failed to match something this time around with a sub- - expression that's in a loop, try to force exit from the loop. */ - if ((p + 1) != pend && - (! MATCHED_SOMETHING(reg_info[*p]) - || (enum regexpcode)p[-3] == start_memory)) - { - p1 = p + 2; - mcnt = 0; - switch (*p1++) - { - case jump_n: - case finalize_push_n: - case finalize_jump: - case maybe_finalize_jump: - case jump: - case dummy_failure_jump: - EXTRACT_NUMBER_AND_INCR(mcnt, p1); - break; - } - p1 += mcnt; - - /* If the next operation is a jump backwards in the pattern - to an on_failure_jump, exit from the loop by forcing a - failure after pushing on the stack the on_failure_jump's - jump in the pattern, and d. */ - if (mcnt < 0 && (enum regexpcode)*p1 == on_failure_jump - && (enum regexpcode)p1[3] == start_memory && p1[4] == *p) - { - /* If this group ever matched anything, then restore - what its registers were before trying this last - failed match, e.g., with `(a*)*b' against `ab' for - regstart[1], and, e.g., with `((a*)*(b*)*)*' - against `aba' for regend[3]. - - Also restore the registers for inner groups for, - e.g., `((a*)(b*))*' against `aba' (register 3 would - otherwise get trashed). */ - - if (EVER_MATCHED_SOMETHING (reg_info[*p])) - { - unsigned r; - - EVER_MATCHED_SOMETHING (reg_info[*p]) = 0; - - /* Restore this and inner groups' (if any) registers. */ - for (r = *p; r < *p + *(p + 1); r++) - { - regstart[r] = old_regstart[r]; - - /* xx why this test? */ - if ((int)old_regend[r] >= (int)regstart[r]) - regend[r] = old_regend[r]; - } - } - p1++; - EXTRACT_NUMBER_AND_INCR(mcnt, p1); - PUSH_FAILURE_POINT(p1 + mcnt, d); - goto fail; - } - } - p += 2; - continue; + /* Where in input to try to start matching. */ + d2 = regstart[regno]; + if (REG_UNSET(d2)) break; - case stop_paren: - break; + /* Where to stop matching; if both the place to start and + the place to stop matching are in the same string, then + set to the place to stop, otherwise, for now have to use + the end of the first string. */ - /* \<digit> has been turned into a `duplicate' command which is - followed by the numeric value of <digit> as the register number. */ - case duplicate: - { - int regno = *p++; /* Get which register to match against */ - register unsigned char *d2, *dend2; - - if (IS_ACTIVE(reg_info[regno])) break; - - /* Where in input to try to start matching. */ - d2 = regstart[regno]; - if (REG_UNSET(d2)) break; - - /* Where to stop matching; if both the place to start and - the place to stop matching are in the same string, then - set to the place to stop, otherwise, for now have to use - the end of the first string. */ - - dend2 = regend[regno]; - if (REG_UNSET(dend2)) break; - for (;;) - { - /* At end of register contents => success */ - if (d2 == dend2) break; - - /* If necessary, advance to next segment in data. */ - PREFETCH; - - /* How many characters left in this segment to match. */ - mcnt = dend - d; - - /* Want how many consecutive characters we can match in - one shot, so, if necessary, adjust the count. */ - if (mcnt > dend2 - d2) - mcnt = dend2 - d2; - - /* Compare that many; failure if mismatch, else move - past them. */ - if ((options & RE_OPTION_IGNORECASE) - ? memcmp_translate(d, d2, mcnt) - : memcmp((char*)d, (char*)d2, mcnt)) - goto fail; - d += mcnt, d2 += mcnt; - } - } - break; + dend2 = regend[regno]; + if (REG_UNSET(dend2)) break; + for (;;) { + /* At end of register contents => success */ + if (d2 == dend2) break; - case start_nowidth: - PUSH_FAILURE_POINT(0, d); - EXTRACT_NUMBER_AND_INCR(mcnt, p); - STORE_NUMBER(p+mcnt, stackp - stackb); - continue; + /* If necessary, advance to next segment in data. */ + PREFETCH; - case stop_nowidth: - EXTRACT_NUMBER_AND_INCR(mcnt, p); - stackp = stackb + mcnt; - d = stackp[-2]; - POP_FAILURE_POINT(); - continue; + /* How many characters left in this segment to match. */ + mcnt = dend - d; - case pop_and_fail: - EXTRACT_NUMBER(mcnt, p+1); - stackp = stackb + mcnt; - POP_FAILURE_POINT(); - goto fail; + /* Want how many consecutive characters we can match in + one shot, so, if necessary, adjust the count. */ + if (mcnt > dend2 - d2) + mcnt = dend2 - d2; - case anychar: - PREFETCH; - if (ismbchar(*d)) { - if (d + mbclen(*d) > dend) + /* Compare that many; failure if mismatch, else move + past them. */ + if ((options & RE_OPTION_IGNORECASE) + ? memcmp_translate(d, d2, mcnt) + : memcmp((char*)d, (char*)d2, mcnt)) goto fail; - SET_REGS_MATCHED; - d += mbclen(*d); - break; + d += mcnt, d2 += mcnt; } - if (((TRANSLATE_P()) ? translate[*d] : *d) == - ((options&RE_OPTION_POSIX) ? '\0' : '\n')) + } + break; + + case start_nowidth: + PUSH_FAILURE_POINT(0, d); + EXTRACT_NUMBER_AND_INCR(mcnt, p); + STORE_NUMBER(p+mcnt, stackp - stackb); + continue; + + case stop_nowidth: + EXTRACT_NUMBER_AND_INCR(mcnt, p); + stackp = stackb + mcnt; + d = stackp[-2]; + POP_FAILURE_POINT(); + continue; + + case pop_and_fail: + EXTRACT_NUMBER(mcnt, p+1); + stackp = stackb + mcnt; + POP_FAILURE_POINT(); + goto fail; + + case anychar: + PREFETCH; + if (ismbchar(*d)) { + if (d + mbclen(*d) > dend) goto fail; SET_REGS_MATCHED; - d++; + d += mbclen(*d); break; + } + if (((TRANSLATE_P()) ? translate[*d] : *d) == + ((options&RE_OPTION_POSIX) ? '\0' : '\n')) + goto fail; + SET_REGS_MATCHED; + d++; + break; - case charset: - case charset_not: - { - int not; /* Nonzero for charset_not. */ - int part; /* 2 if matched part of mbc */ - unsigned char *dsave = d + 1; - int cc, c; - - PREFETCH; - cc = c = (unsigned char)*d++; - if (ismbchar(c)) { - if (d + mbclen(c) - 1 <= dend) { - MBC2WC(c, d); - } - } - else if (TRANSLATE_P()) - cc = c = (unsigned char)translate[c]; + case charset: + case charset_not: + { + int not; /* Nonzero for charset_not. */ + int part; /* 2 if matched part of mbc */ + unsigned char *dsave = d + 1; + int cc, c; - part = not = is_in_list(c, p); - if (*(p - 1) == (unsigned char)charset_not) { - not = !not; + PREFETCH; + cc = c = (unsigned char)*d++; + if (ismbchar(c)) { + if (d + mbclen(c) - 1 <= dend) { + MBC2WC(c, d); } - if (!not) goto fail; - - p += 1 + *p + 2 + EXTRACT_UNSIGNED(&p[1 + *p])*8; - SET_REGS_MATCHED; - - if (part == 2) d = dsave; - break; } + else if (TRANSLATE_P()) + cc = c = (unsigned char)translate[c]; - case begline: - if (size == 0 || AT_STRINGS_BEG(d)) - break; - if (d[-1] == '\n' && !AT_STRINGS_END(d)) - break; - goto fail; - - case endline: - if (AT_STRINGS_END(d)) { - if (size == 0 || d[-1] != '\n') - break; + part = not = is_in_list(c, p); + if (*(p - 1) == (unsigned char)charset_not) { + not = !not; } - else if (*d == '\n') - break; - goto fail; + if (!not) goto fail; - /* Match at the very beginning of the string. */ - case begbuf: - if (AT_STRINGS_BEG(d)) - break; - goto fail; + p += 1 + *p + 2 + EXTRACT_UNSIGNED(&p[1 + *p])*8; + SET_REGS_MATCHED; - /* Match at the very end of the data. */ - case endbuf: - if (AT_STRINGS_END(d)) - break; - goto fail; + if (part == 2) d = dsave; + break; + } - /* Match at the very end of the data. */ - case endbuf2: - if (AT_STRINGS_END(d)) - break; - /* .. or newline just before the end of the data. */ - if (*d == '\n' && AT_STRINGS_END(d+1)) - break; - goto fail; + case begline: + if (size == 0 || AT_STRINGS_BEG(d)) + break; + if (d[-1] == '\n' && !AT_STRINGS_END(d)) + break; + goto fail; - /* `or' constructs are handled by starting each alternative with - an on_failure_jump that points to the start of the next - alternative. Each alternative except the last ends with a - jump to the joining point. (Actually, each jump except for - the last one really jumps to the following jump, because - tensioning the jumps is a hassle.) */ + case endline: + if (AT_STRINGS_END(d)) { + if (size == 0 || d[-1] != '\n') + break; + } + else if (*d == '\n') + break; + goto fail; - /* The start of a stupid repeat has an on_failure_jump that points - past the end of the repeat text. This makes a failure point so - that on failure to match a repetition, matching restarts past - as many repetitions have been found with no way to fail and - look for another one. */ + /* Match at the very beginning of the string. */ + case begbuf: + if (AT_STRINGS_BEG(d)) + break; + goto fail; - /* A smart repeat is similar but loops back to the on_failure_jump - so that each repetition makes another failure point. */ + /* Match at the very end of the data. */ + case endbuf: + if (AT_STRINGS_END(d)) + break; + goto fail; - case on_failure_jump: - on_failure: + /* Match at the very end of the data. */ + case endbuf2: + if (AT_STRINGS_END(d)) + break; + /* .. or newline just before the end of the data. */ + if (*d == '\n' && AT_STRINGS_END(d+1)) + break; + goto fail; + + /* `or' constructs are handled by starting each alternative with + an on_failure_jump that points to the start of the next + alternative. Each alternative except the last ends with a + jump to the joining point. (Actually, each jump except for + the last one really jumps to the following jump, because + tensioning the jumps is a hassle.) */ + + /* The start of a stupid repeat has an on_failure_jump that points + past the end of the repeat text. This makes a failure point so + that on failure to match a repetition, matching restarts past + as many repetitions have been found with no way to fail and + look for another one. */ + + /* A smart repeat is similar but loops back to the on_failure_jump + so that each repetition makes another failure point. */ + + case on_failure_jump: + on_failure: + EXTRACT_NUMBER_AND_INCR(mcnt, p); + PUSH_FAILURE_POINT(p + mcnt, d); + continue; + + /* The end of a smart repeat has a maybe_finalize_jump back. + Change it either to a finalize_jump or an ordinary jump. */ + case maybe_finalize_jump: EXTRACT_NUMBER_AND_INCR(mcnt, p); - PUSH_FAILURE_POINT(p + mcnt, d); - continue; - - /* The end of a smart repeat has a maybe_finalize_jump back. - Change it either to a finalize_jump or an ordinary jump. */ - case maybe_finalize_jump: - EXTRACT_NUMBER_AND_INCR(mcnt, p); - { - register unsigned char *p2 = p; - - /* Compare the beginning of the repeat with what in the - pattern follows its end. If we can establish that there - is nothing that they would both match, i.e., that we - would have to backtrack because of (as in, e.g., `a*a') - then we can change to pop_failure_jump, because we'll - never have to backtrack. - - This is not true in the case of alternatives: in - `(a|ab)*' we do need to backtrack to the `ab' alternative - (e.g., if the string was `ab'). But instead of trying to - detect that here, the alternative has put on a dummy - failure point which is what we will end up popping. */ - - /* Skip over open/close-group commands. */ - while (p2 + 2 < pend) { - if ((enum regexpcode)*p2 == stop_memory || - (enum regexpcode)*p2 == start_memory) - p2 += 3; /* Skip over args, too. */ - else if ((enum regexpcode)*p2 == stop_paren) - p2 += 1; - else - break; - } + { + register unsigned char *p2 = p; + + /* Compare the beginning of the repeat with what in the + pattern follows its end. If we can establish that there + is nothing that they would both match, i.e., that we + would have to backtrack because of (as in, e.g., `a*a') + then we can change to pop_failure_jump, because we'll + never have to backtrack. + + This is not true in the case of alternatives: in + `(a|ab)*' we do need to backtrack to the `ab' alternative + (e.g., if the string was `ab'). But instead of trying to + detect that here, the alternative has put on a dummy + failure point which is what we will end up popping. */ + + /* Skip over open/close-group commands. */ + while (p2 + 2 < pend) { + if ((enum regexpcode)*p2 == stop_memory || + (enum regexpcode)*p2 == start_memory) + p2 += 3; /* Skip over args, too. */ + else if ((enum regexpcode)*p2 == stop_paren) + p2 += 1; + else + break; + } - if (p2 == pend) + if (p2 == pend) + p[-3] = (unsigned char)finalize_jump; + else if (*p2 == (unsigned char)exactn + || *p2 == (unsigned char)endline) { + register int c = *p2 == (unsigned char)endline ? '\n' : p2[2]; + register unsigned char *p1 = p + mcnt; + /* p1[0] ... p1[2] are an on_failure_jump. + Examine what follows that. */ + if (p1[3] == (unsigned char)exactn && p1[5] != c) p[-3] = (unsigned char)finalize_jump; - else if (*p2 == (unsigned char)exactn - || *p2 == (unsigned char)endline) - { - register int c = *p2 == (unsigned char)endline ? '\n' : p2[2]; - register unsigned char *p1 = p + mcnt; - /* p1[0] ... p1[2] are an on_failure_jump. - Examine what follows that. */ - if (p1[3] == (unsigned char)exactn && p1[5] != c) - p[-3] = (unsigned char)finalize_jump; - else if (p1[3] == (unsigned char)charset - || p1[3] == (unsigned char)charset_not) { - int not; - if (ismbchar(c)) { - unsigned char *pp = p2+3; - MBC2WC(c, pp); - } - /* `is_in_list()' is TRUE if c would match */ - /* That means it is not safe to finalize. */ - not = is_in_list(c, p1 + 4); - if (p1[3] == (unsigned char)charset_not) - not = !not; - if (!not) - p[-3] = (unsigned char)finalize_jump; - } + else if (p1[3] == (unsigned char)charset + || p1[3] == (unsigned char)charset_not) { + int not; + if (ismbchar(c)) { + unsigned char *pp = p2+3; + MBC2WC(c, pp); } - } - p -= 2; /* Point at relative address again. */ - if (p[-1] != (unsigned char)finalize_jump) - { - p[-1] = (unsigned char)jump; - goto nofinalize; + /* `is_in_list()' is TRUE if c would match */ + /* That means it is not safe to finalize. */ + not = is_in_list(c, p1 + 4); + if (p1[3] == (unsigned char)charset_not) + not = !not; + if (!not) + p[-3] = (unsigned char)finalize_jump; } - /* Note fall through. */ - - /* The end of a stupid repeat has a finalize_jump back to the - start, where another failure point will be made which will - point to after all the repetitions found so far. */ - - /* Take off failure points put on by matching on_failure_jump - because didn't fail. Also remove the register information - put on by the on_failure_jump. */ - case finalize_jump: - if (stackp[-2] == d) { - p = stackp[-3]; - POP_FAILURE_POINT(); - continue; } - POP_FAILURE_POINT(); - /* Note fall through. */ - - /* Jump without taking off any failure points. */ - case jump: - nofinalize: - EXTRACT_NUMBER_AND_INCR(mcnt, p); - p += mcnt; - continue; - - /* We need this opcode so we can detect where alternatives end - in `group_match_null_string_p' et al. */ - case jump_past_alt: + } + p -= 2; /* Point at relative address again. */ + if (p[-1] != (unsigned char)finalize_jump) { + p[-1] = (unsigned char)jump; goto nofinalize; + } + /* Note fall through. */ + + /* The end of a stupid repeat has a finalize_jump back to the + start, where another failure point will be made which will + point to after all the repetitions found so far. */ + + /* Take off failure points put on by matching on_failure_jump + because didn't fail. Also remove the register information + put on by the on_failure_jump. */ + case finalize_jump: + if (stackp[-2] == d) { + p = stackp[-3]; + POP_FAILURE_POINT(); + continue; + } + POP_FAILURE_POINT(); + /* Note fall through. */ - case dummy_failure_jump: - /* Normally, the on_failure_jump pushes a failure point, which - then gets popped at finalize_jump. We will end up at - finalize_jump, also, and with a pattern of, say, `a+', we - are skipping over the on_failure_jump, so we have to push - something meaningless for finalize_jump to pop. */ - PUSH_FAILURE_POINT(0, 0); - goto nofinalize; + /* Jump without taking off any failure points. */ + case jump: + nofinalize: + EXTRACT_NUMBER_AND_INCR(mcnt, p); + p += mcnt; + continue; + + /* We need this opcode so we can detect where alternatives end + in `group_match_null_string_p' et al. */ + case jump_past_alt: + goto nofinalize; + + case dummy_failure_jump: + /* Normally, the on_failure_jump pushes a failure point, which + then gets popped at finalize_jump. We will end up at + finalize_jump, also, and with a pattern of, say, `a+', we + are skipping over the on_failure_jump, so we have to push + something meaningless for finalize_jump to pop. */ + PUSH_FAILURE_POINT(0, 0); + goto nofinalize; + + /* At the end of an alternative, we need to push a dummy failure + point in case we are followed by a `finalize_jump', because + we don't want the failure point for the alternative to be + popped. For example, matching `(a|ab)*' against `aab' + requires that we match the `ab' alternative. */ + case push_dummy_failure: + /* See comments just above at `dummy_failure_jump' about the + two zeroes. */ + PUSH_FAILURE_POINT(0, 0); + break; - /* At the end of an alternative, we need to push a dummy failure - point in case we are followed by a `finalize_jump', because - we don't want the failure point for the alternative to be - popped. For example, matching `(a|ab)*' against `aab' - requires that we match the `ab' alternative. */ - case push_dummy_failure: - /* See comments just above at `dummy_failure_jump' about the - two zeroes. */ + /* Have to succeed matching what follows at least n times. Then + just handle like an on_failure_jump. */ + case succeed_n: + EXTRACT_NUMBER(mcnt, p + 2); + /* Originally, this is how many times we HAVE to succeed. */ + if (mcnt > 0) { + mcnt--; + p += 2; + STORE_NUMBER_AND_INCR(p, mcnt); PUSH_FAILURE_POINT(0, 0); - break; - - /* Have to succeed matching what follows at least n times. Then - just handle like an on_failure_jump. */ - case succeed_n: - EXTRACT_NUMBER(mcnt, p + 2); - /* Originally, this is how many times we HAVE to succeed. */ - if (mcnt > 0) - { - mcnt--; - p += 2; - STORE_NUMBER_AND_INCR(p, mcnt); - PUSH_FAILURE_POINT(0, 0); - } - else if (mcnt == 0) - { - p[2] = unused; - p[3] = unused; - goto on_failure; - } - continue; + } + else if (mcnt == 0) { + p[2] = unused; + p[3] = unused; + goto on_failure; + } + continue; - case jump_n: - EXTRACT_NUMBER(mcnt, p + 2); - /* Originally, this is how many times we CAN jump. */ - if (mcnt) - { - mcnt--; - STORE_NUMBER(p + 2, mcnt); - goto nofinalize; /* Do the jump without taking off + case jump_n: + EXTRACT_NUMBER(mcnt, p + 2); + /* Originally, this is how many times we CAN jump. */ + if (mcnt) { + mcnt--; + STORE_NUMBER(p + 2, mcnt); + goto nofinalize; /* Do the jump without taking off any failure points. */ - } - /* If don't have to jump any more, skip over the rest of command. */ - else - p += 4; - continue; + } + /* If don't have to jump any more, skip over the rest of command. */ + else + p += 4; + continue; - case set_number_at: - EXTRACT_NUMBER_AND_INCR(mcnt, p); - p1 = p + mcnt; - EXTRACT_NUMBER_AND_INCR(mcnt, p); - STORE_NUMBER(p1, mcnt); - continue; + case set_number_at: + EXTRACT_NUMBER_AND_INCR(mcnt, p); + p1 = p + mcnt; + EXTRACT_NUMBER_AND_INCR(mcnt, p); + STORE_NUMBER(p1, mcnt); + continue; - case try_next: - EXTRACT_NUMBER_AND_INCR(mcnt, p); - if (p + mcnt < pend) { - PUSH_FAILURE_POINT(p, d); - stackp[-1] = (unsigned char*)1; - } - p += mcnt; - continue; + case try_next: + EXTRACT_NUMBER_AND_INCR(mcnt, p); + if (p + mcnt < pend) { + PUSH_FAILURE_POINT(p, d); + stackp[-1] = (unsigned char*)1; + } + p += mcnt; + continue; - case finalize_push: + case finalize_push: + POP_FAILURE_POINT(); + EXTRACT_NUMBER_AND_INCR(mcnt, p); + PUSH_FAILURE_POINT(p + mcnt, d); + stackp[-1] = (unsigned char*)1; + continue; + + case finalize_push_n: + EXTRACT_NUMBER(mcnt, p + 2); + /* Originally, this is how many times we CAN jump. */ + if (mcnt) { + int pos, i; + + mcnt--; + STORE_NUMBER(p + 2, mcnt); + EXTRACT_NUMBER(pos, p); + EXTRACT_NUMBER(i, p+pos+5); + if (i > 0) goto nofinalize; POP_FAILURE_POINT(); EXTRACT_NUMBER_AND_INCR(mcnt, p); PUSH_FAILURE_POINT(p + mcnt, d); stackp[-1] = (unsigned char*)1; - continue; + p += 2; /* skip n */ + } + /* If don't have to push any more, skip over the rest of command. */ + else + p += 4; + continue; - case finalize_push_n: - EXTRACT_NUMBER(mcnt, p + 2); - /* Originally, this is how many times we CAN jump. */ - if (mcnt) { - int pos, i; - - mcnt--; - STORE_NUMBER(p + 2, mcnt); - EXTRACT_NUMBER(pos, p); - EXTRACT_NUMBER(i, p+pos+5); - if (i > 0) goto nofinalize; - POP_FAILURE_POINT(); - EXTRACT_NUMBER_AND_INCR(mcnt, p); - PUSH_FAILURE_POINT(p + mcnt, d); - stackp[-1] = (unsigned char*)1; - p += 2; /* skip n */ - } - /* If don't have to push any more, skip over the rest of command. */ - else - p += 4; - continue; + /* Ignore these. Used to ignore the n of succeed_n's which + currently have n == 0. */ + case unused: + continue; - /* Ignore these. Used to ignore the n of succeed_n's which - currently have n == 0. */ - case unused: - continue; + case casefold_on: + options |= RE_OPTION_IGNORECASE; + continue; - case casefold_on: - options |= RE_OPTION_IGNORECASE; - continue; + case casefold_off: + options &= ~RE_OPTION_IGNORECASE; + continue; - case casefold_off: - options &= ~RE_OPTION_IGNORECASE; - continue; + case posix_on: + options |= RE_OPTION_POSIX; + continue; - case posix_on: - options |= RE_OPTION_POSIX; - continue; + case posix_off: + options &= ~RE_OPTION_POSIX; + continue; - case posix_off: - options &= ~RE_OPTION_POSIX; - continue; + case wordbound: + if (AT_STRINGS_BEG(d)) { + if (IS_A_LETTER(d)) break; + else goto fail; + } + if (AT_STRINGS_BEG(d)) { + if (PREV_IS_A_LETTER(d)) break; + else goto fail; + } + if (PREV_IS_A_LETTER(d) != IS_A_LETTER(d)) + break; + goto fail; - case wordbound: - if (AT_STRINGS_BEG(d)) { - if (IS_A_LETTER(d)) break; - else goto fail; - } - if (AT_STRINGS_BEG(d)) { - if (PREV_IS_A_LETTER(d)) break; - else goto fail; - } - if (PREV_IS_A_LETTER(d) != IS_A_LETTER(d)) - break; + case notwordbound: + if (AT_STRINGS_BEG(d)) { + if (IS_A_LETTER(d)) goto fail; + else break; + } + if (AT_STRINGS_END(d)) { + if (PREV_IS_A_LETTER(d)) goto fail; + else break; + } + if (PREV_IS_A_LETTER(d) != IS_A_LETTER(d)) goto fail; + break; - case notwordbound: - if (AT_STRINGS_BEG(d)) { - if (IS_A_LETTER(d)) goto fail; - else break; - } - if (AT_STRINGS_END(d)) { - if (PREV_IS_A_LETTER(d)) goto fail; - else break; - } - if (PREV_IS_A_LETTER(d) != IS_A_LETTER(d)) - goto fail; + case wordbeg: + if (IS_A_LETTER(d) && (AT_STRINGS_BEG(d) || !PREV_IS_A_LETTER(d))) break; + goto fail; - case wordbeg: - if (IS_A_LETTER(d) && (AT_STRINGS_BEG(d) || !PREV_IS_A_LETTER(d))) - break; - goto fail; + case wordend: + if (!AT_STRINGS_BEG(d) && PREV_IS_A_LETTER(d) + && (!IS_A_LETTER(d) || AT_STRINGS_END(d))) + break; + goto fail; - case wordend: - if (!AT_STRINGS_BEG(d) && PREV_IS_A_LETTER(d) - && (!IS_A_LETTER(d) || AT_STRINGS_END(d))) - break; + case wordchar: + PREFETCH; + if (!IS_A_LETTER(d)) goto fail; + if (ismbchar(*d) && d + mbclen(*d) - 1 < dend) + d += mbclen(*d) - 1; + d++; + SET_REGS_MATCHED; + break; - case wordchar: - PREFETCH; - if (!IS_A_LETTER(d)) - goto fail; - if (ismbchar(*d) && d + mbclen(*d) - 1 < dend) - d += mbclen(*d) - 1; - d++; - SET_REGS_MATCHED; - break; + case notwordchar: + PREFETCH; + if (IS_A_LETTER(d)) + goto fail; + if (ismbchar(*d) && d + mbclen(*d) - 1 < dend) + d += mbclen(*d) - 1; + d++; + SET_REGS_MATCHED; + break; - case notwordchar: - PREFETCH; - if (IS_A_LETTER(d)) - goto fail; - if (ismbchar(*d) && d + mbclen(*d) - 1 < dend) - d += mbclen(*d) - 1; - d++; - SET_REGS_MATCHED; - break; + case exactn: + /* Match the next few pattern characters exactly. + mcnt is how many characters to match. */ + mcnt = *p++; + /* This is written out as an if-else so we don't waste time + testing `translate' inside the loop. */ + if (TRANSLATE_P()) { + do { + unsigned char c; - case exactn: - /* Match the next few pattern characters exactly. - mcnt is how many characters to match. */ - mcnt = *p++; - /* This is written out as an if-else so we don't waste time - testing `translate' inside the loop. */ - if (TRANSLATE_P()) - { - do - { - unsigned char c; - - PREFETCH; - c = *d++; - if (*p == 0xff) { - p++; - if (!--mcnt - || AT_STRINGS_END(d) - || (unsigned char)*d++ != (unsigned char)*p++) - goto fail; - continue; - } - if (ismbchar(c)) { - int n; - - if (c != (unsigned char)*p++) - goto fail; - for (n = mbclen(c) - 1; n > 0; n--) - if (!--mcnt /* redundant check if pattern was - compiled properly. */ - || AT_STRINGS_END(d) - || (unsigned char)*d++ != (unsigned char)*p++) - goto fail; - continue; - } - /* compiled code translation needed for ruby */ - if ((unsigned char)translate[c] - != (unsigned char)translate[*p++]) - goto fail; - } - while (--mcnt); + PREFETCH; + c = *d++; + if (*p == 0xff) { + p++; + if (!--mcnt + || AT_STRINGS_END(d) + || (unsigned char)*d++ != (unsigned char)*p++) + goto fail; + continue; } - else - { - do - { - PREFETCH; - if (*p == 0xff) {p++; mcnt--;} - if (*d++ != *p++) goto fail; - } - while (--mcnt); + if (ismbchar(c)) { + int n; + + if (c != (unsigned char)*p++) + goto fail; + for (n = mbclen(c) - 1; n > 0; n--) + if (!--mcnt /* redundant check if pattern was + compiled properly. */ + || AT_STRINGS_END(d) + || (unsigned char)*d++ != (unsigned char)*p++) + goto fail; + continue; } - SET_REGS_MATCHED; - break; + /* compiled code translation needed for ruby */ + if ((unsigned char)translate[c] != (unsigned char)translate[*p++]) + goto fail; + } + while (--mcnt); } + else { + do { + PREFETCH; + if (*p == 0xff) {p++; mcnt--;} + if (*d++ != *p++) goto fail; + } + while (--mcnt); + } + SET_REGS_MATCHED; + break; + } #if 0 while (stackp != stackb && (int)stackp[-1] == 1) POP_FAILURE_POINT(); @@ -4012,78 +3975,77 @@ re_match(bufp, string_arg, size, pos, regs) /* Jump here if any matching operation fails. */ fail: - if (stackp != stackb) + if (stackp != stackb) { /* A restart point is known. Restart there and pop it. */ - { - short last_used_reg, this_reg; + short last_used_reg, this_reg; - /* If this failure point is from a dummy_failure_point, just - skip it. */ - if (stackp[-3] == 0 || (best_regs_set && stackp[-1] == 1)) { - POP_FAILURE_POINT(); - goto fail; - } - stackp--; /* discard flag */ - d = *--stackp; - p = *--stackp; - /* Restore register info. */ - last_used_reg = (long)*--stackp; - - /* Make the ones that weren't saved -1 or 0 again. */ - for (this_reg = num_regs - 1; this_reg > last_used_reg; this_reg--) { - regend[this_reg] = REG_UNSET_VALUE; - regstart[this_reg] = REG_UNSET_VALUE; - IS_ACTIVE(reg_info[this_reg]) = 0; - MATCHED_SOMETHING(reg_info[this_reg]) = 0; - } + /* If this failure point is from a dummy_failure_point, just + skip it. */ + if (stackp[-3] == 0 || (best_regs_set && (int)stackp[-1] == 1)) { + POP_FAILURE_POINT(); + goto fail; + } + stackp--; /* discard flag */ + d = *--stackp; + p = *--stackp; + /* Restore register info. */ + last_used_reg = (long)*--stackp; + + /* Make the ones that weren't saved -1 or 0 again. */ + for (this_reg = num_regs - 1; this_reg > last_used_reg; this_reg--) { + regend[this_reg] = REG_UNSET_VALUE; + regstart[this_reg] = REG_UNSET_VALUE; + IS_ACTIVE(reg_info[this_reg]) = 0; + MATCHED_SOMETHING(reg_info[this_reg]) = 0; + } - /* And restore the rest from the stack. */ - for ( ; this_reg > 0; this_reg--) { - reg_info[this_reg].word = *--stackp; - regend[this_reg] = *--stackp; - regstart[this_reg] = *--stackp; - } - if (p < pend) { - int is_a_jump_n = 0; - int failed_paren = 0; - - p1 = p; - /* If failed to a backwards jump that's part of a repetition - loop, need to pop this failure point and use the next one. */ - pop_loop: - switch ((enum regexpcode)*p1) { - case stop_paren: - failed_paren = 1; - p1++; - goto pop_loop; + /* And restore the rest from the stack. */ + for ( ; this_reg > 0; this_reg--) { + reg_info[this_reg].word = *--stackp; + regend[this_reg] = *--stackp; + regstart[this_reg] = *--stackp; + } + if (p < pend) { + int is_a_jump_n = 0; + int failed_paren = 0; + + p1 = p; + /* If failed to a backwards jump that's part of a repetition + loop, need to pop this failure point and use the next one. */ + pop_loop: + switch ((enum regexpcode)*p1) { + case stop_paren: + failed_paren = 1; + p1++; + goto pop_loop; - case jump_n: - case finalize_push_n: - is_a_jump_n = 1; - case maybe_finalize_jump: - case finalize_jump: - case finalize_push: - case jump: - p1++; - EXTRACT_NUMBER_AND_INCR (mcnt, p1); - p1 += mcnt; - - if (p1 >= pend) break; - if (( is_a_jump_n && (enum regexpcode)*p1 == succeed_n) || - (!is_a_jump_n && (enum regexpcode)*p1 == on_failure_jump)) { - if (failed_paren) { - p1++; - EXTRACT_NUMBER_AND_INCR(mcnt, p1); - PUSH_FAILURE_POINT(p1 + mcnt, d); - } - goto fail; + case jump_n: + case finalize_push_n: + is_a_jump_n = 1; + case maybe_finalize_jump: + case finalize_jump: + case finalize_push: + case jump: + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + + if (p1 >= pend) break; + if (( is_a_jump_n && (enum regexpcode)*p1 == succeed_n) || + (!is_a_jump_n && (enum regexpcode)*p1 == on_failure_jump)) { + if (failed_paren) { + p1++; + EXTRACT_NUMBER_AND_INCR(mcnt, p1); + PUSH_FAILURE_POINT(p1 + mcnt, d); } - break; - default: - /* do nothing */ ; + goto fail; } + break; + default: + /* do nothing */ ; } } + } else break; /* Matching at this starting point really fails. */ } @@ -4128,65 +4090,64 @@ group_match_null_string_p (p, end, reg_info) /* If the next operation is not a jump backwards in the pattern. */ - if (mcnt >= 0) - { - /* Go through the on_failure_jumps of the alternatives, - seeing if any of the alternatives cannot match nothing. - The last alternative starts with only a jump, - whereas the rest start with on_failure_jump and end - with a jump, e.g., here is the pattern for `a|b|c': + if (mcnt >= 0) { + /* Go through the on_failure_jumps of the alternatives, + seeing if any of the alternatives cannot match nothing. + The last alternative starts with only a jump, + whereas the rest start with on_failure_jump and end + with a jump, e.g., here is the pattern for `a|b|c': - /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6 - /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3 - /exactn/1/c + /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6 + /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3 + /exactn/1/c - So, we have to first go through the first (n-1) - alternatives and then deal with the last one separately. */ + So, we have to first go through the first (n-1) + alternatives and then deal with the last one separately. */ - /* Deal with the first (n-1) alternatives, which start - with an on_failure_jump (see above) that jumps to right - past a jump_past_alt. */ + /* Deal with the first (n-1) alternatives, which start + with an on_failure_jump (see above) that jumps to right + past a jump_past_alt. */ - while ((enum regexpcode)p1[mcnt-3] == jump_past_alt) { - /* `mcnt' holds how many bytes long the alternative - is, including the ending `jump_past_alt' and - its number. */ + while ((enum regexpcode)p1[mcnt-3] == jump_past_alt) { + /* `mcnt' holds how many bytes long the alternative + is, including the ending `jump_past_alt' and + its number. */ - if (!alt_match_null_string_p (p1, p1 + mcnt - 3, - reg_info)) - return 0; + if (!alt_match_null_string_p (p1, p1 + mcnt - 3, + reg_info)) + return 0; - /* Move to right after this alternative, including the - jump_past_alt. */ - p1 += mcnt; + /* Move to right after this alternative, including the + jump_past_alt. */ + p1 += mcnt; - /* Break if it's the beginning of an n-th alternative - that doesn't begin with an on_failure_jump. */ - if ((enum regexpcode)*p1 != on_failure_jump) - break; - - /* Still have to check that it's not an n-th - alternative that starts with an on_failure_jump. */ - p1++; - EXTRACT_NUMBER_AND_INCR (mcnt, p1); - if ((enum regexpcode)p1[mcnt-3] != jump_past_alt) { - /* Get to the beginning of the n-th alternative. */ - p1 -= 3; - break; - } + /* Break if it's the beginning of an n-th alternative + that doesn't begin with an on_failure_jump. */ + if ((enum regexpcode)*p1 != on_failure_jump) + break; + + /* Still have to check that it's not an n-th + alternative that starts with an on_failure_jump. */ + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if ((enum regexpcode)p1[mcnt-3] != jump_past_alt) { + /* Get to the beginning of the n-th alternative. */ + p1 -= 3; + break; } + } - /* Deal with the last alternative: go back and get number - of the `jump_past_alt' just before it. `mcnt' contains - the length of the alternative. */ - EXTRACT_NUMBER (mcnt, p1 - 2); + /* Deal with the last alternative: go back and get number + of the `jump_past_alt' just before it. `mcnt' contains + the length of the alternative. */ + EXTRACT_NUMBER (mcnt, p1 - 2); #if 0 - if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info)) - return 0; + if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info)) + return 0; #endif - p1 += mcnt; /* Get past the n-th alternative. */ - } /* if mcnt > 0 */ + p1 += mcnt; /* Get past the n-th alternative. */ + } /* if mcnt > 0 */ break; diff --git a/sample/test.rb b/sample/test.rb index 57641448ff..11fa499fd3 100644 --- a/sample/test.rb +++ b/sample/test.rb @@ -599,14 +599,21 @@ ok(("abc" =~ /d*$/) == 3) ok("" =~ /^$/) ok("\n" =~ /^$/) ok("a\n\n" =~ /^$/) -"abcabc" =~ /.*a/ -ok($& == "abca") -"abcabc" =~ /.*c/ -ok($& == "abcabc") -"abcabc" =~ /.*?a/ -ok($& == "a") -"abcabc" =~ /.*?c/ -ok($& == "abc") +ok("abcabc" =~ /.*a/ && $& == "abca") +ok("abcabc" =~ /.*c/ && $& == "abcabc") +ok("abcabc" =~ /.*?a/ && $& == "a") +ok("abcabc" =~ /.*?c/ && $& == "abc") +ok(/(.|\n)*?\n(b|\n)/ =~ "a\nb\n\n" && $& == "a\nb") +$x = <<END; +ABCD +ABCD +END + +$x.gsub!(/((.|\n)*?)B((.|\n)*?)D/){$1+$3} +ok($x == "AC\nAC\n") + +ok("foobar" =~ /foo(?=(bar)|(baz))/) +ok("foobaz" =~ /foo(?=(bar)|(baz))/) $foo = "abc" ok("#$foo = abc" == "abc = abc") @@ -845,9 +852,13 @@ ok($x[4].call == 8) proc { p = binding eval "foo11 = 1", p + foo22 = 5 proc{foo11=22}.call + proc{foo22=55}.call ok(eval("foo11", p) == eval("foo11")) ok(eval("foo11") == 1) + ok(eval("foo22", p) == eval("foo22")) + ok(eval("foo22") == 55) }.call p1 = proc{i6 = 0; proc{i6}}.call diff --git a/win32/ruby.def b/win32/ruby.def index 06820c8cf9..df8390b0be 100644 --- a/win32/ruby.def +++ b/win32/ruby.def @@ -197,7 +197,6 @@ EXPORTS ruby_run rb_eval_string rb_eval_cmd - rb_trap_eval rb_test_false_or_nil rb_respond_to rb_exit |