From 0fa1086760eb0a5964789eb619769764107458ca Mon Sep 17 00:00:00 2001 From: kosako Date: Wed, 22 Mar 2006 15:03:40 +0000 Subject: [PATCH] add back reference by name in replace string git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10046 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 11 +++++++++++ re.c | 56 ++++++++++++++++++++++++++++++++++++++++++++----------- re.h | 2 +- string.c | 4 ++-- version.h | 6 +++--- 5 files changed, 62 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 60c4b21c47..c72bacefc8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +Thu Mar 23 00:01:32 2006 K.Kosako + + * re.c (rb_reg_regsub): add back reference by name \k in + replace string. + + * re.h : add regexp argument to rb_reg_regsub(). + + * string.c (rb_str_sub_bang): ditto. + + * string.c (str_gsub): ditto. + Tue Mar 21 22:14:01 2006 K.Kosako * re.c (match_alloc): initialize member regexp. diff --git a/re.c b/re.c index 9570a775e1..e2b27bdbd6 100644 --- a/re.c +++ b/re.c @@ -1158,6 +1158,22 @@ match_captures(VALUE match) return match_array(match, 1); } +static int +name_to_backref_number(struct re_registers *regs, VALUE regexp, char* name, char* name_end) +{ + int num; + + num = onig_name_to_backref_number(RREGEXP(regexp)->ptr, + (unsigned char* )name, (unsigned char* )name_end, regs); + if (num >= 1) { + return num; + } + else { + VALUE s = rb_str_new(name, (long )(name_end - name)); + rb_raise(rb_eRuntimeError, "undefined group name reference: %s", + StringValuePtr(s)); + } +} /* * call-seq: @@ -1192,7 +1208,7 @@ match_aref(int argc, VALUE *argv, VALUE match) } } else { - char *p, *end; + char *p; int num; switch (TYPE(idx)) { @@ -1204,15 +1220,9 @@ match_aref(int argc, VALUE *argv, VALUE match) p = StringValuePtr(idx); name_to_backref: - end = p + strlen(p); - num = onig_name_to_backref_number(RREGEXP(RMATCH(match)->regexp)->ptr, - (unsigned char* )p, (unsigned char* )end, RMATCH(match)->regs); - if (num >= 1) { - return rb_reg_nth_match(num, match); - } - else { - rb_raise(rb_eArgError, "undefined group name reference: %s", p); - } + num = name_to_backref_number(RMATCH(match)->regs, + RMATCH(match)->regexp, p, p + strlen(p)); + return rb_reg_nth_match(num, match); break; default: @@ -2013,7 +2023,7 @@ rb_reg_init_copy(VALUE copy, VALUE re) } VALUE -rb_reg_regsub(VALUE str, VALUE src, struct re_registers *regs) +rb_reg_regsub(VALUE str, VALUE src, struct re_registers *regs, VALUE regexp) { VALUE val = 0; char *p, *s, *e; @@ -2049,6 +2059,30 @@ rb_reg_regsub(VALUE str, VALUE src, struct re_registers *regs) case '5': case '6': case '7': case '8': case '9': no = uc - '0'; break; + + case 'k': + if (s < e && *s == '<') { + char *name, *name_end; + + name_end = name = s + 1; + while (name_end < e) { + if (*name_end == '>') break; + uc = (unsigned char)*name_end; + name_end += mbclen(uc); + } + if (name_end < e) { + no = name_to_backref_number(regs, regexp, name, name_end); + p = s = name_end + 1; + break; + } + else { + rb_raise(rb_eRuntimeError, "invalid group name reference format"); + } + } + + rb_str_buf_cat(val, s-2, 2); + continue; + case '&': no = 0; break; diff --git a/re.h b/re.h index 8690932bb5..ab66352288 100644 --- a/re.h +++ b/re.h @@ -31,7 +31,7 @@ struct RMatch { VALUE rb_reg_regcomp(VALUE); long rb_reg_search(VALUE, VALUE, long, long); -VALUE rb_reg_regsub(VALUE, VALUE, struct re_registers *); +VALUE rb_reg_regsub(VALUE, VALUE, struct re_registers *, VALUE); long rb_reg_adjust_startpos(VALUE, VALUE, long, long); void rb_match_busy(VALUE); VALUE rb_reg_quote(VALUE); diff --git a/string.c b/string.c index a9adc6200a..84f9e843dc 100644 --- a/string.c +++ b/string.c @@ -1848,7 +1848,7 @@ rb_str_sub_bang(int argc, VALUE *argv, VALUE str) rb_backref_set(match); } else { - repl = rb_reg_regsub(repl, str, regs); + repl = rb_reg_regsub(repl, str, regs, pat); } if (OBJ_TAINTED(repl)) tainted = 1; plen = END(0) - BEG(0); @@ -1966,7 +1966,7 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang) rb_backref_set(match); } else { - val = rb_reg_regsub(repl, str, regs); + val = rb_reg_regsub(repl, str, regs, pat); } if (OBJ_TAINTED(val)) tainted = 1; len = (bp - buf) + (beg - offset) + RSTRING(val)->len + 3; diff --git a/version.h b/version.h index 55aea3dcf6..60c681f072 100644 --- a/version.h +++ b/version.h @@ -1,14 +1,14 @@ #define RUBY_VERSION "1.9.0" -#define RUBY_RELEASE_DATE "2006-03-21" +#define RUBY_RELEASE_DATE "2006-03-23" #define RUBY_VERSION_CODE 190 -#define RUBY_RELEASE_CODE 20060321 +#define RUBY_RELEASE_CODE 20060323 #define RUBY_VERSION_MAJOR 1 #define RUBY_VERSION_MINOR 9 #define RUBY_VERSION_TEENY 0 #define RUBY_RELEASE_YEAR 2006 #define RUBY_RELEASE_MONTH 3 -#define RUBY_RELEASE_DAY 21 +#define RUBY_RELEASE_DAY 23 RUBY_EXTERN const char ruby_version[]; RUBY_EXTERN const char ruby_release_date[];