diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | internal.h | 2 | ||||
-rw-r--r-- | re.c | 27 | ||||
-rw-r--r-- | test/ruby/test_variable.rb | 8 | ||||
-rw-r--r-- | variable.c | 20 |
5 files changed, 55 insertions, 7 deletions
@@ -1,3 +1,8 @@ +Thu Jan 14 17:36:16 2016 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * variable.c (rb_f_global_variables): add matched back references + only, as well as defiend? operator. + Thu Jan 14 16:12:09 2016 Nobuyoshi Nakada <nobu@ruby-lang.org> * sprintf.c (rb_str_format): format exact number more exactly. diff --git a/internal.h b/internal.h index 5622998ff8..0ebda869c6 100644 --- a/internal.h +++ b/internal.h @@ -1104,6 +1104,8 @@ VALUE rb_reg_compile(VALUE str, int options, const char *sourcefile, int sourcel VALUE rb_reg_check_preprocess(VALUE); long rb_reg_search0(VALUE, VALUE, long, int, int); void rb_backref_set_string(VALUE string, long pos, long len); +int rb_match_count(VALUE match); +int rb_match_nth_defined(int nth, VALUE match); /* signal.c */ extern int ruby_enable_coredump; @@ -1265,6 +1265,33 @@ rb_match_busy(VALUE match) FL_SET(match, MATCH_BUSY); } +int +rb_match_count(VALUE match) +{ + struct re_registers *regs; + if (NIL_P(match)) return -1; + regs = RMATCH_REGS(match); + if (!regs) return -1; + return regs->num_regs; +} + +int +rb_match_nth_defined(int nth, VALUE match) +{ + struct re_registers *regs; + if (NIL_P(match)) return FALSE; + regs = RMATCH_REGS(match); + if (!regs) return FALSE; + if (nth >= regs->num_regs) { + return FALSE; + } + if (nth < 0) { + nth += regs->num_regs; + if (nth <= 0) return FALSE; + } + return (BEG(nth) != -1); +} + static void match_set_string(VALUE m, VALUE string, long pos, long len) { diff --git a/test/ruby/test_variable.rb b/test/ruby/test_variable.rb index 90afde19cb..3fba8d1884 100644 --- a/test/ruby/test_variable.rb +++ b/test/ruby/test_variable.rb @@ -105,9 +105,13 @@ class TestVariable < Test::Unit::TestCase assert_empty(gv.grep(/\A(?!\$)/)) assert_nil($~) assert_not_include(gv, :$1) - /.*/ =~ "global" + /(\w)(\d)?(.)(.)(.)(.)(.)(.)(.)(.)(\d)?(.)/ =~ "globalglobalglobal" assert_not_nil($~) - assert_include(global_variables-gv, :$1) + gv = global_variables - gv + assert_include(gv, :$1) + assert_not_include(gv, :$2) + assert_not_include(gv, :$11) + assert_include(gv, :$12) end def test_global_variable_0 diff --git a/variable.c b/variable.c index 26d9a4b944..b53d0c1d1d 100644 --- a/variable.c +++ b/variable.c @@ -880,15 +880,25 @@ VALUE rb_f_global_variables(void) { VALUE ary = rb_ary_new(); + VALUE sym, backref = rb_backref_get(); rb_id_table_foreach(rb_global_tbl, gvar_i, (void *)ary); - if (!NIL_P(rb_backref_get())) { + if (!NIL_P(backref)) { char buf[2]; - int i; + int i, nmatch = rb_match_count(backref); buf[0] = '$'; - for (i = 1; i <= 9; ++i) { - buf[1] = (char)(i + '0'); - rb_ary_push(ary, ID2SYM(rb_intern2(buf, 2))); + for (i = 1; i <= nmatch; ++i) { + if (!rb_match_nth_defined(i, backref)) continue; + if (i < 10) { + /* probably reused, make static ID */ + buf[1] = (char)(i + '0'); + sym = ID2SYM(rb_intern2(buf, 2)); + } + else { + /* dynamic symbol */ + sym = rb_str_intern(rb_sprintf("$%d", i)); + } + rb_ary_push(ary, sym); } } return ary; |