summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-01-14 08:36:49 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-01-14 08:36:49 +0000
commit92e803c9c8e7cebe937c5ba05312417dbf99d688 (patch)
tree01475f3c7b7fe9a38d1d563e8358f25a19e41cb3
parent1301d1f5bccc10daf93c816ef4e177776d0668de (diff)
variable.c: matched backrefs only
* variable.c (rb_f_global_variables): add matched back references only, as well as defiend? operator. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53534 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog5
-rw-r--r--internal.h2
-rw-r--r--re.c27
-rw-r--r--test/ruby/test_variable.rb8
-rw-r--r--variable.c20
5 files changed, 55 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index 15ce86f766..b59d440f6a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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;
diff --git a/re.c b/re.c
index d827e05245..f8ea30f393 100644
--- a/re.c
+++ b/re.c
@@ -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;