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(®2, (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(®, (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), ®s, 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/