[前][次][番号順一覧][スレッド一覧]

ruby-changes:4528

From: ko1@a...
Date: Tue, 15 Apr 2008 00:48:38 +0900 (JST)
Subject: [ruby-changes:4528] matz - Ruby:r16021 (trunk): * re.c (rb_reg_search): make search reentrant.

matz	2008-04-15 00:47:51 +0900 (Tue, 15 Apr 2008)

  New Revision: 16021

  Modified files:
    trunk/ChangeLog
    trunk/re.c
    trunk/test/ruby/test_parse.rb
    trunk/version.h

  Log:
    * re.c (rb_reg_search): make search reentrant.  [ruby-dev:34223]
    
    * test/ruby/test_parse.rb (TestParse::test_global_variable):
      should preserve $& variable.

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/version.h?r1=16021&r2=16020&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ChangeLog?r1=16021&r2=16020&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/re.c?r1=16021&r2=16020&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/test/ruby/test_parse.rb?r1=16021&r2=16020&diff_format=u

Index: re.c
===================================================================
--- re.c	(revision 16020)
+++ re.c	(revision 16021)
@@ -238,6 +238,7 @@
 
 #define REG_LITERAL FL_USER5
 #define REG_ENCODING_NONE FL_USER6
+#define REG_BUSY FL_USER7
 
 #define KCODE_FIXED FL_USER4
 
@@ -1144,11 +1145,12 @@
 rb_reg_preprocess(const char *p, const char *end, rb_encoding *enc,
         rb_encoding **fixed_enc, onig_errmsg_buffer err);
 
-static void
-rb_reg_prepare_re(VALUE re, VALUE str, int enable_warning)
+
+static rb_encoding*
+rb_reg_prepare_enc(VALUE re, VALUE str, int warn)
 {
-    int need_recompile = 0;
-    rb_encoding *enc;
+    rb_encoding *enc = 0;
+    regex_t *reg;
 
     if (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN) {
         rb_raise(rb_eArgError,
@@ -1168,63 +1170,65 @@
         }
     }
     else {
-        if ((enc = rb_enc_get(str)) != 0 &&
-	     RREGEXP(re)->ptr->enc != enc) {
-            need_recompile = 1;
-        }
-        if (enable_warning &&
-            (RBASIC(re)->flags & REG_ENCODING_NONE) &&
+	enc = rb_enc_get(str);
+	if (warn && (RBASIC(re)->flags & REG_ENCODING_NONE) &&
 	    enc != rb_ascii8bit_encoding() &&
-            rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
-            rb_warn("regexp match /.../n against to %s string",
-                    rb_enc_name(enc));
-        }
+	    rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
+	    rb_warn("regexp match /.../n against to %s string",
+		    rb_enc_name(enc));
+	}
+	return enc;
     }
+    return RREGEXP(re)->ptr->enc;
+}
 
-    if (need_recompile) {
-	onig_errmsg_buffer err = "";
-	int r;
-	OnigErrorInfo einfo;
-	regex_t *reg, *reg2;
-	UChar *pattern;
-        VALUE unescaped;
-        rb_encoding *fixed_enc = 0;
+static regex_t *
+rb_reg_prepare_re(VALUE re, rb_encoding *enc)
+{
+    regex_t *reg = RREGEXP(re)->ptr;
+    onig_errmsg_buffer err = "";
+    int r;
+    OnigErrorInfo einfo;
+    UChar *pattern;
+    VALUE unescaped;
+    rb_encoding *fixed_enc = 0;
 
-	rb_reg_check(re);
-	reg = RREGEXP(re)->ptr;
-	pattern = ((UChar*)RREGEXP(re)->str);
+    if (reg->enc == enc) return reg;
 
-        unescaped = rb_reg_preprocess(
-            RREGEXP(re)->str, RREGEXP(re)->str + RREGEXP(re)->len, enc,
-            &fixed_enc, err);
+    rb_reg_check(re);
+    reg = RREGEXP(re)->ptr;
+    pattern = ((UChar*)RREGEXP(re)->str);
 
-        if (unescaped == Qnil) {
-            rb_raise(rb_eArgError, "regexp preprocess failed: %s", err);
-        }
+    unescaped = rb_reg_preprocess(
+	pattern, pattern + RREGEXP(re)->len, enc,
+	&fixed_enc, err);
 
-	r = onig_new(&reg2, (UChar* )RSTRING_PTR(unescaped),
-		     (UChar* )(RSTRING_PTR(unescaped) + RSTRING_LEN(unescaped)),
-		     reg->options, enc,
-		     OnigDefaultSyntax, &einfo);
-	if (r) {
-	    onig_error_code_to_str((UChar*)err, r, &einfo);
-	    rb_reg_raise((char* )pattern, RREGEXP(re)->len, err, re);
-	}
+    if (unescaped == Qnil) {
+	rb_raise(rb_eArgError, "regexp preprocess failed: %s", err);
+    }
 
-	RREGEXP(re)->ptr = reg2;
-	onig_free(reg);
-        RB_GC_GUARD(unescaped);
+    r = onig_new(&reg, (UChar* )RSTRING_PTR(unescaped),
+		 (UChar* )(RSTRING_PTR(unescaped) + RSTRING_LEN(unescaped)),
+		 reg->options, enc,
+		 OnigDefaultSyntax, &einfo);
+    if (r) {
+	onig_error_code_to_str((UChar*)err, r, &einfo);
+	rb_reg_raise((char*)pattern, RREGEXP(re)->len, err, re);
     }
+
+    RB_GC_GUARD(unescaped);
+    return reg;
 }
 
 int
 rb_reg_adjust_startpos(VALUE re, VALUE str, int pos, int reverse)
 {
     int range;
-    OnigEncoding enc;
+    rb_encoding *enc;
     UChar *p, *string;
+    regex_t *reg;
 
-    rb_reg_prepare_re(re, str, 0);
+    enc = rb_reg_prepare_enc(re, str, 0);
 
     if (reverse) {
 	range = -pos;
@@ -1233,8 +1237,6 @@
 	range = RSTRING_LEN(str) - pos;
     }
 
-    enc = (RREGEXP(re)->ptr)->enc;
-
     if (pos > 0 && ONIGENC_MBC_MAXLEN(enc) != 1 && pos < RSTRING_LEN(str)) {
 	 string = (UChar*)RSTRING_PTR(str);
 
@@ -1257,24 +1259,37 @@
     VALUE match;
     static struct re_registers regs;
     char *range = RSTRING_PTR(str);
+    regex_t *reg0 = RREGEXP(re)->ptr, *reg;
+    int busy = FL_TEST(re, REG_BUSY);
 
     if (pos > RSTRING_LEN(str) || pos < 0) {
 	rb_backref_set(Qnil);
 	return -1;
     }
 
-    rb_reg_prepare_re(re, str, 1);
+    reg = rb_reg_prepare_re(re, rb_reg_prepare_enc(re, str, 1));
 
+    FL_SET(re, REG_BUSY);
     if (!reverse) {
 	range += RSTRING_LEN(str);
     }
-    result = onig_search(RREGEXP(re)->ptr,
+    result = onig_search(reg,
 			 (UChar*)(RSTRING_PTR(str)),
 			 ((UChar*)(RSTRING_PTR(str)) + RSTRING_LEN(str)),
 			 ((UChar*)(RSTRING_PTR(str)) + pos),
 			 ((UChar*)range),
 			 &regs, ONIG_OPTION_NONE);
 
+    if (RREGEXP(re)->ptr != reg) {
+	if (busy) {
+	    onig_free(reg);
+	}
+	else {
+	    onig_free(reg0);
+	    RREGEXP(re)->ptr = reg;
+	}
+    }
+    if (!busy) FL_UNSET(re, REG_BUSY);
     if (result < 0) {
 	if (result == ONIG_MISMATCH) {
 	    rb_backref_set(Qnil);
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 16020)
+++ ChangeLog	(revision 16021)
@@ -8,6 +8,11 @@
 	* file.c (SET_EXTERNAL_ENCODING): avoid call rb_enc_check() on
 	  half-baked result string.
 
+	* re.c (rb_reg_search): make search reentrant.  [ruby-dev:34223]
+
+	* test/ruby/test_parse.rb (TestParse::test_global_variable):
+	  should preserve $& variable.
+
 Mon Apr 14 17:23:27 2008  Akinori MUSHA  <knu@i...>
 
 	* hash.c (rb_hash_delete_if, rb_hash_reject_bang, env_delete_if,
Index: version.h
===================================================================
--- version.h	(revision 16020)
+++ version.h	(revision 16021)
@@ -1,7 +1,7 @@
 #define RUBY_VERSION "1.9.0"
-#define RUBY_RELEASE_DATE "2008-04-14"
+#define RUBY_RELEASE_DATE "2008-04-15"
 #define RUBY_VERSION_CODE 190
-#define RUBY_RELEASE_CODE 20080414
+#define RUBY_RELEASE_CODE 20080415
 #define RUBY_PATCHLEVEL 0
 
 #define RUBY_VERSION_MAJOR 1
@@ -9,7 +9,7 @@
 #define RUBY_VERSION_TEENY 0
 #define RUBY_RELEASE_YEAR 2008
 #define RUBY_RELEASE_MONTH 4
-#define RUBY_RELEASE_DAY 14
+#define RUBY_RELEASE_DAY 15
 
 #ifdef RUBY_EXTERN
 RUBY_EXTERN const char ruby_version[];
Index: test/ruby/test_parse.rb
===================================================================
--- test/ruby/test_parse.rb	(revision 16020)
+++ test/ruby/test_parse.rb	(revision 16021)
@@ -670,8 +670,11 @@
 
   def test_global_variable
     assert_equal(nil, eval('$-x'))
+    assert_equal(nil, eval('alias $preserve_last_match $&'))
     assert_equal(nil, eval('alias $& $test_parse_foobarbazqux'))
     $test_parse_foobarbazqux = nil
+    assert_equal(nil, $&)
+    assert_equal(nil, eval('alias $& $preserve_last_match'))
     assert_raise(SyntaxError) { eval('$#') }
   end
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]