mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* re.c (rb_reg_search): make search reentrant. [ruby-dev:34223]
* test/ruby/test_parse.rb (TestParse::test_global_variable): should preserve $& variable. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16021 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
71263844e2
commit
fee4ed204f
4 changed files with 80 additions and 57 deletions
|
@ -8,6 +8,11 @@ Mon Apr 14 22:44:24 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
* file.c (SET_EXTERNAL_ENCODING): avoid call rb_enc_check() on
|
* file.c (SET_EXTERNAL_ENCODING): avoid call rb_enc_check() on
|
||||||
half-baked result string.
|
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@iDaemons.org>
|
Mon Apr 14 17:23:27 2008 Akinori MUSHA <knu@iDaemons.org>
|
||||||
|
|
||||||
* hash.c (rb_hash_delete_if, rb_hash_reject_bang, env_delete_if,
|
* hash.c (rb_hash_delete_if, rb_hash_reject_bang, env_delete_if,
|
||||||
|
|
123
re.c
123
re.c
|
@ -238,6 +238,7 @@ rb_memsearch(const void *x0, long m, const void *y0, long n, rb_encoding *enc)
|
||||||
|
|
||||||
#define REG_LITERAL FL_USER5
|
#define REG_LITERAL FL_USER5
|
||||||
#define REG_ENCODING_NONE FL_USER6
|
#define REG_ENCODING_NONE FL_USER6
|
||||||
|
#define REG_BUSY FL_USER7
|
||||||
|
|
||||||
#define KCODE_FIXED FL_USER4
|
#define KCODE_FIXED FL_USER4
|
||||||
|
|
||||||
|
@ -1144,11 +1145,12 @@ static VALUE
|
||||||
rb_reg_preprocess(const char *p, const char *end, rb_encoding *enc,
|
rb_reg_preprocess(const char *p, const char *end, rb_encoding *enc,
|
||||||
rb_encoding **fixed_enc, onig_errmsg_buffer err);
|
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 = 0;
|
||||||
rb_encoding *enc;
|
regex_t *reg;
|
||||||
|
|
||||||
if (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN) {
|
if (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN) {
|
||||||
rb_raise(rb_eArgError,
|
rb_raise(rb_eArgError,
|
||||||
|
@ -1168,63 +1170,65 @@ rb_reg_prepare_re(VALUE re, VALUE str, int enable_warning)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ((enc = rb_enc_get(str)) != 0 &&
|
enc = rb_enc_get(str);
|
||||||
RREGEXP(re)->ptr->enc != enc) {
|
if (warn && (RBASIC(re)->flags & REG_ENCODING_NONE) &&
|
||||||
need_recompile = 1;
|
|
||||||
}
|
|
||||||
if (enable_warning &&
|
|
||||||
(RBASIC(re)->flags & REG_ENCODING_NONE) &&
|
|
||||||
enc != rb_ascii8bit_encoding() &&
|
enc != rb_ascii8bit_encoding() &&
|
||||||
rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
|
rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
|
||||||
rb_warn("regexp match /.../n against to %s string",
|
rb_warn("regexp match /.../n against to %s string",
|
||||||
rb_enc_name(enc));
|
rb_enc_name(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;
|
|
||||||
|
|
||||||
rb_reg_check(re);
|
|
||||||
reg = RREGEXP(re)->ptr;
|
|
||||||
pattern = ((UChar*)RREGEXP(re)->str);
|
|
||||||
|
|
||||||
unescaped = rb_reg_preprocess(
|
|
||||||
RREGEXP(re)->str, RREGEXP(re)->str + RREGEXP(re)->len, enc,
|
|
||||||
&fixed_enc, err);
|
|
||||||
|
|
||||||
if (unescaped == Qnil) {
|
|
||||||
rb_raise(rb_eArgError, "regexp preprocess failed: %s", 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);
|
|
||||||
}
|
}
|
||||||
|
return enc;
|
||||||
RREGEXP(re)->ptr = reg2;
|
|
||||||
onig_free(reg);
|
|
||||||
RB_GC_GUARD(unescaped);
|
|
||||||
}
|
}
|
||||||
|
return RREGEXP(re)->ptr->enc;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (reg->enc == enc) return reg;
|
||||||
|
|
||||||
|
rb_reg_check(re);
|
||||||
|
reg = RREGEXP(re)->ptr;
|
||||||
|
pattern = ((UChar*)RREGEXP(re)->str);
|
||||||
|
|
||||||
|
unescaped = rb_reg_preprocess(
|
||||||
|
pattern, pattern + RREGEXP(re)->len, enc,
|
||||||
|
&fixed_enc, err);
|
||||||
|
|
||||||
|
if (unescaped == Qnil) {
|
||||||
|
rb_raise(rb_eArgError, "regexp preprocess failed: %s", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
int
|
||||||
rb_reg_adjust_startpos(VALUE re, VALUE str, int pos, int reverse)
|
rb_reg_adjust_startpos(VALUE re, VALUE str, int pos, int reverse)
|
||||||
{
|
{
|
||||||
int range;
|
int range;
|
||||||
OnigEncoding enc;
|
rb_encoding *enc;
|
||||||
UChar *p, *string;
|
UChar *p, *string;
|
||||||
|
regex_t *reg;
|
||||||
|
|
||||||
rb_reg_prepare_re(re, str, 0);
|
enc = rb_reg_prepare_enc(re, str, 0);
|
||||||
|
|
||||||
if (reverse) {
|
if (reverse) {
|
||||||
range = -pos;
|
range = -pos;
|
||||||
|
@ -1233,8 +1237,6 @@ rb_reg_adjust_startpos(VALUE re, VALUE str, int pos, int reverse)
|
||||||
range = RSTRING_LEN(str) - pos;
|
range = RSTRING_LEN(str) - pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
enc = (RREGEXP(re)->ptr)->enc;
|
|
||||||
|
|
||||||
if (pos > 0 && ONIGENC_MBC_MAXLEN(enc) != 1 && pos < RSTRING_LEN(str)) {
|
if (pos > 0 && ONIGENC_MBC_MAXLEN(enc) != 1 && pos < RSTRING_LEN(str)) {
|
||||||
string = (UChar*)RSTRING_PTR(str);
|
string = (UChar*)RSTRING_PTR(str);
|
||||||
|
|
||||||
|
@ -1257,24 +1259,37 @@ rb_reg_search(VALUE re, VALUE str, int pos, int reverse)
|
||||||
VALUE match;
|
VALUE match;
|
||||||
static struct re_registers regs;
|
static struct re_registers regs;
|
||||||
char *range = RSTRING_PTR(str);
|
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) {
|
if (pos > RSTRING_LEN(str) || pos < 0) {
|
||||||
rb_backref_set(Qnil);
|
rb_backref_set(Qnil);
|
||||||
return -1;
|
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) {
|
if (!reverse) {
|
||||||
range += RSTRING_LEN(str);
|
range += RSTRING_LEN(str);
|
||||||
}
|
}
|
||||||
result = onig_search(RREGEXP(re)->ptr,
|
result = onig_search(reg,
|
||||||
(UChar*)(RSTRING_PTR(str)),
|
(UChar*)(RSTRING_PTR(str)),
|
||||||
((UChar*)(RSTRING_PTR(str)) + RSTRING_LEN(str)),
|
((UChar*)(RSTRING_PTR(str)) + RSTRING_LEN(str)),
|
||||||
((UChar*)(RSTRING_PTR(str)) + pos),
|
((UChar*)(RSTRING_PTR(str)) + pos),
|
||||||
((UChar*)range),
|
((UChar*)range),
|
||||||
®s, ONIG_OPTION_NONE);
|
®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 < 0) {
|
||||||
if (result == ONIG_MISMATCH) {
|
if (result == ONIG_MISMATCH) {
|
||||||
rb_backref_set(Qnil);
|
rb_backref_set(Qnil);
|
||||||
|
|
|
@ -670,8 +670,11 @@ x = __ENCODING__
|
||||||
|
|
||||||
def test_global_variable
|
def test_global_variable
|
||||||
assert_equal(nil, eval('$-x'))
|
assert_equal(nil, eval('$-x'))
|
||||||
|
assert_equal(nil, eval('alias $preserve_last_match $&'))
|
||||||
assert_equal(nil, eval('alias $& $test_parse_foobarbazqux'))
|
assert_equal(nil, eval('alias $& $test_parse_foobarbazqux'))
|
||||||
$test_parse_foobarbazqux = nil
|
$test_parse_foobarbazqux = nil
|
||||||
|
assert_equal(nil, $&)
|
||||||
|
assert_equal(nil, eval('alias $& $preserve_last_match'))
|
||||||
assert_raise(SyntaxError) { eval('$#') }
|
assert_raise(SyntaxError) { eval('$#') }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#define RUBY_VERSION "1.9.0"
|
#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_VERSION_CODE 190
|
||||||
#define RUBY_RELEASE_CODE 20080414
|
#define RUBY_RELEASE_CODE 20080415
|
||||||
#define RUBY_PATCHLEVEL 0
|
#define RUBY_PATCHLEVEL 0
|
||||||
|
|
||||||
#define RUBY_VERSION_MAJOR 1
|
#define RUBY_VERSION_MAJOR 1
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
#define RUBY_VERSION_TEENY 0
|
#define RUBY_VERSION_TEENY 0
|
||||||
#define RUBY_RELEASE_YEAR 2008
|
#define RUBY_RELEASE_YEAR 2008
|
||||||
#define RUBY_RELEASE_MONTH 4
|
#define RUBY_RELEASE_MONTH 4
|
||||||
#define RUBY_RELEASE_DAY 14
|
#define RUBY_RELEASE_DAY 15
|
||||||
|
|
||||||
#ifdef RUBY_EXTERN
|
#ifdef RUBY_EXTERN
|
||||||
RUBY_EXTERN const char ruby_version[];
|
RUBY_EXTERN const char ruby_version[];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue