00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "ruby/ruby.h"
00013 #include "ruby/re.h"
00014 #include "ruby/encoding.h"
00015 #include "ruby/util.h"
00016 #include "internal.h"
00017 #include "regint.h"
00018 #include <ctype.h>
00019
00020 VALUE rb_eRegexpError;
00021
00022 typedef char onig_errmsg_buffer[ONIG_MAX_ERROR_MESSAGE_LEN];
00023 #define errcpy(err, msg) strlcpy((err), (msg), ONIG_MAX_ERROR_MESSAGE_LEN)
00024
00025 #define BEG(no) (regs->beg[(no)])
00026 #define END(no) (regs->end[(no)])
00027
00028 #if 'a' == 97
00029 static const char casetable[] = {
00030 '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
00031 '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
00032 '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
00033 '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
00034
00035 '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
00036
00037 '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
00038
00039 '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
00040
00041 '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
00042
00043 '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
00044
00045 '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
00046
00047 '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
00048
00049 '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
00050
00051 '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
00052
00053 '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
00054
00055 '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
00056
00057 '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
00058 '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
00059 '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
00060 '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
00061 '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
00062 '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
00063 '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
00064 '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
00065 '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
00066 '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
00067 '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
00068 '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
00069 '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
00070 '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
00071 '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
00072 '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
00073 '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
00074 };
00075 #else
00076 # error >>> "You lose. You will need a translation table for your character set." <<<
00077 #endif
00078
00079 int
00080 rb_memcicmp(const void *x, const void *y, long len)
00081 {
00082 const unsigned char *p1 = x, *p2 = y;
00083 int tmp;
00084
00085 while (len--) {
00086 if ((tmp = casetable[(unsigned)*p1++] - casetable[(unsigned)*p2++]))
00087 return tmp;
00088 }
00089 return 0;
00090 }
00091
00092 #undef rb_memcmp
00093
00094 int
00095 rb_memcmp(const void *p1, const void *p2, long len)
00096 {
00097 return memcmp(p1, p2, len);
00098 }
00099
00100 #ifdef HAVE_MEMMEM
00101 static inline long
00102 rb_memsearch_ss(const unsigned char *xs, long m, const unsigned char *ys, long n)
00103 {
00104 const unsigned char *y;
00105
00106 if (y = memmem(ys, n, xs, m))
00107 return y - ys;
00108 else
00109 return -1;
00110 }
00111 #else
00112 static inline long
00113 rb_memsearch_ss(const unsigned char *xs, long m, const unsigned char *ys, long n)
00114 {
00115 const unsigned char *x = xs, *xe = xs + m;
00116 const unsigned char *y = ys, *ye = ys + n;
00117 #ifndef VALUE_MAX
00118 # if SIZEOF_VALUE == 8
00119 # define VALUE_MAX 0xFFFFFFFFFFFFFFFFULL
00120 # elif SIZEOF_VALUE == 4
00121 # define VALUE_MAX 0xFFFFFFFFUL
00122 # endif
00123 #endif
00124 VALUE hx, hy, mask = VALUE_MAX >> ((SIZEOF_VALUE - m) * CHAR_BIT);
00125
00126 if (m > SIZEOF_VALUE)
00127 rb_bug("!!too long pattern string!!");
00128
00129 if (!(y = memchr(y, *x, n - m + 1)))
00130 return -1;
00131
00132
00133 for (hx = *x++, hy = *y++; x < xe; ++x, ++y) {
00134 hx <<= CHAR_BIT;
00135 hy <<= CHAR_BIT;
00136 hx |= *x;
00137 hy |= *y;
00138 }
00139
00140 while (hx != hy) {
00141 if (y == ye)
00142 return -1;
00143 hy <<= CHAR_BIT;
00144 hy |= *y;
00145 hy &= mask;
00146 y++;
00147 }
00148 return y - ys - m;
00149 }
00150 #endif
00151
00152 static inline long
00153 rb_memsearch_qs(const unsigned char *xs, long m, const unsigned char *ys, long n)
00154 {
00155 const unsigned char *x = xs, *xe = xs + m;
00156 const unsigned char *y = ys;
00157 VALUE i, qstable[256];
00158
00159
00160 for (i = 0; i < 256; ++i)
00161 qstable[i] = m + 1;
00162 for (; x < xe; ++x)
00163 qstable[*x] = xe - x;
00164
00165 for (; y + m <= ys + n; y += *(qstable + y[m])) {
00166 if (*xs == *y && memcmp(xs, y, m) == 0)
00167 return y - ys;
00168 }
00169 return -1;
00170 }
00171
00172 static inline unsigned int
00173 rb_memsearch_qs_utf8_hash(const unsigned char *x)
00174 {
00175 register const unsigned int mix = 8353;
00176 register unsigned int h = *x;
00177 if (h < 0xC0) {
00178 return h + 256;
00179 }
00180 else if (h < 0xE0) {
00181 h *= mix;
00182 h += x[1];
00183 }
00184 else if (h < 0xF0) {
00185 h *= mix;
00186 h += x[1];
00187 h *= mix;
00188 h += x[2];
00189 }
00190 else if (h < 0xF5) {
00191 h *= mix;
00192 h += x[1];
00193 h *= mix;
00194 h += x[2];
00195 h *= mix;
00196 h += x[3];
00197 }
00198 else {
00199 return h + 256;
00200 }
00201 return (unsigned char)h;
00202 }
00203
00204 static inline long
00205 rb_memsearch_qs_utf8(const unsigned char *xs, long m, const unsigned char *ys, long n)
00206 {
00207 const unsigned char *x = xs, *xe = xs + m;
00208 const unsigned char *y = ys;
00209 VALUE i, qstable[512];
00210
00211
00212 for (i = 0; i < 512; ++i) {
00213 qstable[i] = m + 1;
00214 }
00215 for (; x < xe; ++x) {
00216 qstable[rb_memsearch_qs_utf8_hash(x)] = xe - x;
00217 }
00218
00219 for (; y + m <= ys + n; y += qstable[rb_memsearch_qs_utf8_hash(y+m)]) {
00220 if (*xs == *y && memcmp(xs, y, m) == 0)
00221 return y - ys;
00222 }
00223 return -1;
00224 }
00225
00226 long
00227 rb_memsearch(const void *x0, long m, const void *y0, long n, rb_encoding *enc)
00228 {
00229 const unsigned char *x = x0, *y = y0;
00230
00231 if (m > n) return -1;
00232 else if (m == n) {
00233 return memcmp(x0, y0, m) == 0 ? 0 : -1;
00234 }
00235 else if (m < 1) {
00236 return 0;
00237 }
00238 else if (m == 1) {
00239 const unsigned char *ys = memchr(y, *x, n);
00240
00241 if (ys)
00242 return ys - y;
00243 else
00244 return -1;
00245 }
00246 else if (m <= SIZEOF_VALUE) {
00247 return rb_memsearch_ss(x0, m, y0, n);
00248 }
00249 else if (enc == rb_utf8_encoding()){
00250 return rb_memsearch_qs_utf8(x0, m, y0, n);
00251 }
00252 else {
00253 return rb_memsearch_qs(x0, m, y0, n);
00254 }
00255 }
00256
00257 #define REG_LITERAL FL_USER5
00258 #define REG_ENCODING_NONE FL_USER6
00259
00260 #define KCODE_FIXED FL_USER4
00261
00262 #define ARG_REG_OPTION_MASK \
00263 (ONIG_OPTION_IGNORECASE|ONIG_OPTION_MULTILINE|ONIG_OPTION_EXTEND)
00264 #define ARG_ENCODING_FIXED 16
00265 #define ARG_ENCODING_NONE 32
00266
00267 static int
00268 char_to_option(int c)
00269 {
00270 int val;
00271
00272 switch (c) {
00273 case 'i':
00274 val = ONIG_OPTION_IGNORECASE;
00275 break;
00276 case 'x':
00277 val = ONIG_OPTION_EXTEND;
00278 break;
00279 case 'm':
00280 val = ONIG_OPTION_MULTILINE;
00281 break;
00282 default:
00283 val = 0;
00284 break;
00285 }
00286 return val;
00287 }
00288
00289 static char *
00290 option_to_str(char str[4], int options)
00291 {
00292 char *p = str;
00293 if (options & ONIG_OPTION_MULTILINE) *p++ = 'm';
00294 if (options & ONIG_OPTION_IGNORECASE) *p++ = 'i';
00295 if (options & ONIG_OPTION_EXTEND) *p++ = 'x';
00296 *p = 0;
00297 return str;
00298 }
00299
00300 extern int
00301 rb_char_to_option_kcode(int c, int *option, int *kcode)
00302 {
00303 *option = 0;
00304
00305 switch (c) {
00306 case 'n':
00307 *kcode = rb_ascii8bit_encindex();
00308 return (*option = ARG_ENCODING_NONE);
00309 case 'e':
00310 *kcode = ENCINDEX_EUC_JP;
00311 break;
00312 case 's':
00313 *kcode = ENCINDEX_Windows_31J;
00314 break;
00315 case 'u':
00316 *kcode = rb_utf8_encindex();
00317 break;
00318 default:
00319 *kcode = -1;
00320 return (*option = char_to_option(c));
00321 }
00322 *option = ARG_ENCODING_FIXED;
00323 return 1;
00324 }
00325
00326 static void
00327 rb_reg_check(VALUE re)
00328 {
00329 if (!RREGEXP(re)->ptr || !RREGEXP_SRC(re) || !RREGEXP_SRC_PTR(re)) {
00330 rb_raise(rb_eTypeError, "uninitialized Regexp");
00331 }
00332 }
00333
00334 static void
00335 rb_reg_expr_str(VALUE str, const char *s, long len,
00336 rb_encoding *enc, rb_encoding *resenc)
00337 {
00338 const char *p, *pend;
00339 int cr = ENC_CODERANGE_UNKNOWN;
00340 int need_escape = 0;
00341 int c, clen;
00342
00343 p = s; pend = p + len;
00344 rb_str_coderange_scan_restartable(p, pend, enc, &cr);
00345 if (rb_enc_asciicompat(enc) &&
00346 (cr == ENC_CODERANGE_VALID || cr == ENC_CODERANGE_7BIT)) {
00347 while (p < pend) {
00348 c = rb_enc_ascget(p, pend, &clen, enc);
00349 if (c == -1) {
00350 if (enc == resenc) {
00351 p += mbclen(p, pend, enc);
00352 }
00353 else {
00354 need_escape = 1;
00355 break;
00356 }
00357 }
00358 else if (c != '/' && rb_enc_isprint(c, enc)) {
00359 p += clen;
00360 }
00361 else {
00362 need_escape = 1;
00363 break;
00364 }
00365 }
00366 }
00367 else {
00368 need_escape = 1;
00369 }
00370
00371 if (!need_escape) {
00372 rb_str_buf_cat(str, s, len);
00373 }
00374 else {
00375 int unicode_p = rb_enc_unicode_p(enc);
00376 p = s;
00377 while (p<pend) {
00378 c = rb_enc_ascget(p, pend, &clen, enc);
00379 if (c == '\\' && p+clen < pend) {
00380 int n = clen + mbclen(p+clen, pend, enc);
00381 rb_str_buf_cat(str, p, n);
00382 p += n;
00383 continue;
00384 }
00385 else if (c == '/') {
00386 char c = '\\';
00387 rb_str_buf_cat(str, &c, 1);
00388 rb_str_buf_cat(str, p, clen);
00389 }
00390 else if (c == -1) {
00391 clen = rb_enc_precise_mbclen(p, pend, enc);
00392 if (!MBCLEN_CHARFOUND_P(clen)) {
00393 c = (unsigned char)*p;
00394 clen = 1;
00395 goto hex;
00396 }
00397 if (resenc) {
00398 unsigned int c = rb_enc_mbc_to_codepoint(p, pend, enc);
00399 rb_str_buf_cat_escaped_char(str, c, unicode_p);
00400 }
00401 else {
00402 clen = MBCLEN_CHARFOUND_LEN(clen);
00403 rb_str_buf_cat(str, p, clen);
00404 }
00405 }
00406 else if (rb_enc_isprint(c, enc)) {
00407 rb_str_buf_cat(str, p, clen);
00408 }
00409 else if (!rb_enc_isspace(c, enc)) {
00410 char b[8];
00411
00412 hex:
00413 snprintf(b, sizeof(b), "\\x%02X", c);
00414 rb_str_buf_cat(str, b, 4);
00415 }
00416 else {
00417 rb_str_buf_cat(str, p, clen);
00418 }
00419 p += clen;
00420 }
00421 }
00422 }
00423
00424 static VALUE
00425 rb_reg_desc(const char *s, long len, VALUE re)
00426 {
00427 rb_encoding *enc = rb_enc_get(re);
00428 VALUE str = rb_str_buf_new2("/");
00429 rb_encoding *resenc = rb_default_internal_encoding();
00430 if (resenc == NULL) resenc = rb_default_external_encoding();
00431
00432 if (re && rb_enc_asciicompat(enc)) {
00433 rb_enc_copy(str, re);
00434 }
00435 else {
00436 rb_enc_associate(str, rb_usascii_encoding());
00437 }
00438 rb_reg_expr_str(str, s, len, enc, resenc);
00439 rb_str_buf_cat2(str, "/");
00440 if (re) {
00441 char opts[4];
00442 rb_reg_check(re);
00443 if (*option_to_str(opts, RREGEXP(re)->ptr->options))
00444 rb_str_buf_cat2(str, opts);
00445 if (RBASIC(re)->flags & REG_ENCODING_NONE)
00446 rb_str_buf_cat2(str, "n");
00447 }
00448 OBJ_INFECT(str, re);
00449 return str;
00450 }
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467 static VALUE
00468 rb_reg_source(VALUE re)
00469 {
00470 VALUE str;
00471
00472 rb_reg_check(re);
00473 str = rb_enc_str_new(RREGEXP_SRC_PTR(re),RREGEXP_SRC_LEN(re), rb_enc_get(re));
00474 if (OBJ_TAINTED(re)) OBJ_TAINT(str);
00475 return str;
00476 }
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 static VALUE
00491 rb_reg_inspect(VALUE re)
00492 {
00493 if (!RREGEXP(re)->ptr || !RREGEXP_SRC(re) || !RREGEXP_SRC_PTR(re)) {
00494 return rb_any_to_s(re);
00495 }
00496 return rb_reg_desc(RREGEXP_SRC_PTR(re), RREGEXP_SRC_LEN(re), re);
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 static VALUE
00521 rb_reg_to_s(VALUE re)
00522 {
00523 int options, opt;
00524 const int embeddable = ONIG_OPTION_MULTILINE|ONIG_OPTION_IGNORECASE|ONIG_OPTION_EXTEND;
00525 long len;
00526 const UChar* ptr;
00527 VALUE str = rb_str_buf_new2("(?");
00528 char optbuf[5];
00529 rb_encoding *enc = rb_enc_get(re);
00530
00531 rb_reg_check(re);
00532
00533 rb_enc_copy(str, re);
00534 options = RREGEXP(re)->ptr->options;
00535 ptr = (UChar*)RREGEXP_SRC_PTR(re);
00536 len = RREGEXP_SRC_LEN(re);
00537 again:
00538 if (len >= 4 && ptr[0] == '(' && ptr[1] == '?') {
00539 int err = 1;
00540 ptr += 2;
00541 if ((len -= 2) > 0) {
00542 do {
00543 opt = char_to_option((int )*ptr);
00544 if (opt != 0) {
00545 options |= opt;
00546 }
00547 else {
00548 break;
00549 }
00550 ++ptr;
00551 } while (--len > 0);
00552 }
00553 if (len > 1 && *ptr == '-') {
00554 ++ptr;
00555 --len;
00556 do {
00557 opt = char_to_option((int )*ptr);
00558 if (opt != 0) {
00559 options &= ~opt;
00560 }
00561 else {
00562 break;
00563 }
00564 ++ptr;
00565 } while (--len > 0);
00566 }
00567 if (*ptr == ')') {
00568 --len;
00569 ++ptr;
00570 goto again;
00571 }
00572 if (*ptr == ':' && ptr[len-1] == ')') {
00573 Regexp *rp;
00574 VALUE verbose = ruby_verbose;
00575 ruby_verbose = Qfalse;
00576
00577 ++ptr;
00578 len -= 2;
00579 err = onig_new(&rp, ptr, ptr + len, ONIG_OPTION_DEFAULT,
00580 enc, OnigDefaultSyntax, NULL);
00581 onig_free(rp);
00582 ruby_verbose = verbose;
00583 }
00584 if (err) {
00585 options = RREGEXP(re)->ptr->options;
00586 ptr = (UChar*)RREGEXP_SRC_PTR(re);
00587 len = RREGEXP_SRC_LEN(re);
00588 }
00589 }
00590
00591 if (*option_to_str(optbuf, options)) rb_str_buf_cat2(str, optbuf);
00592
00593 if ((options & embeddable) != embeddable) {
00594 optbuf[0] = '-';
00595 option_to_str(optbuf + 1, ~options);
00596 rb_str_buf_cat2(str, optbuf);
00597 }
00598
00599 rb_str_buf_cat2(str, ":");
00600 if (rb_enc_asciicompat(enc)) {
00601 rb_reg_expr_str(str, (char*)ptr, len, enc, NULL);
00602 rb_str_buf_cat2(str, ")");
00603 }
00604 else {
00605 const char *s, *e;
00606 char *paren;
00607 ptrdiff_t n;
00608 rb_str_buf_cat2(str, ")");
00609 rb_enc_associate(str, rb_usascii_encoding());
00610 str = rb_str_encode(str, rb_enc_from_encoding(enc), 0, Qnil);
00611
00612
00613 s = RSTRING_PTR(str);
00614 e = RSTRING_END(str);
00615 s = rb_enc_left_char_head(s, e-1, e, enc);
00616 n = e - s;
00617 paren = ALLOCA_N(char, n);
00618 memcpy(paren, s, n);
00619 rb_str_resize(str, RSTRING_LEN(str) - n);
00620
00621 rb_reg_expr_str(str, (char*)ptr, len, enc, NULL);
00622 rb_str_buf_cat(str, paren, n);
00623 }
00624 rb_enc_copy(str, re);
00625
00626 OBJ_INFECT(str, re);
00627 return str;
00628 }
00629
00630 static void
00631 rb_reg_raise(const char *s, long len, const char *err, VALUE re)
00632 {
00633 volatile VALUE desc = rb_reg_desc(s, len, re);
00634
00635 rb_raise(rb_eRegexpError, "%s: %"PRIsVALUE, err, desc);
00636 }
00637
00638 static VALUE
00639 rb_enc_reg_error_desc(const char *s, long len, rb_encoding *enc, int options, const char *err)
00640 {
00641 char opts[6];
00642 VALUE desc = rb_str_buf_new2(err);
00643 rb_encoding *resenc = rb_default_internal_encoding();
00644 if (resenc == NULL) resenc = rb_default_external_encoding();
00645
00646 rb_enc_associate(desc, enc);
00647 rb_str_buf_cat2(desc, ": /");
00648 rb_reg_expr_str(desc, s, len, enc, resenc);
00649 opts[0] = '/';
00650 option_to_str(opts + 1, options);
00651 rb_str_buf_cat2(desc, opts);
00652 return rb_exc_new3(rb_eRegexpError, desc);
00653 }
00654
00655 static void
00656 rb_enc_reg_raise(const char *s, long len, rb_encoding *enc, int options, const char *err)
00657 {
00658 rb_exc_raise(rb_enc_reg_error_desc(s, len, enc, options, err));
00659 }
00660
00661 static VALUE
00662 rb_reg_error_desc(VALUE str, int options, const char *err)
00663 {
00664 return rb_enc_reg_error_desc(RSTRING_PTR(str), RSTRING_LEN(str),
00665 rb_enc_get(str), options, err);
00666 }
00667
00668 static void
00669 rb_reg_raise_str(VALUE str, int options, const char *err)
00670 {
00671 rb_exc_raise(rb_reg_error_desc(str, options, err));
00672 }
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686 static VALUE
00687 rb_reg_casefold_p(VALUE re)
00688 {
00689 rb_reg_check(re);
00690 if (RREGEXP(re)->ptr->options & ONIG_OPTION_IGNORECASE) return Qtrue;
00691 return Qfalse;
00692 }
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718 static VALUE
00719 rb_reg_options_m(VALUE re)
00720 {
00721 int options = rb_reg_options(re);
00722 return INT2NUM(options);
00723 }
00724
00725 static int
00726 reg_names_iter(const OnigUChar *name, const OnigUChar *name_end,
00727 int back_num, int *back_refs, OnigRegex regex, void *arg)
00728 {
00729 VALUE ary = (VALUE)arg;
00730 rb_ary_push(ary, rb_str_new((const char *)name, name_end-name));
00731 return 0;
00732 }
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750 static VALUE
00751 rb_reg_names(VALUE re)
00752 {
00753 VALUE ary = rb_ary_new();
00754 rb_reg_check(re);
00755 onig_foreach_name(RREGEXP(re)->ptr, reg_names_iter, (void*)ary);
00756 return ary;
00757 }
00758
00759 static int
00760 reg_named_captures_iter(const OnigUChar *name, const OnigUChar *name_end,
00761 int back_num, int *back_refs, OnigRegex regex, void *arg)
00762 {
00763 VALUE hash = (VALUE)arg;
00764 VALUE ary = rb_ary_new2(back_num);
00765 int i;
00766
00767 for (i = 0; i < back_num; i++)
00768 rb_ary_store(ary, i, INT2NUM(back_refs[i]));
00769
00770 rb_hash_aset(hash, rb_str_new((const char*)name, name_end-name),ary);
00771
00772 return 0;
00773 }
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797 static VALUE
00798 rb_reg_named_captures(VALUE re)
00799 {
00800 VALUE hash = rb_hash_new();
00801 rb_reg_check(re);
00802 onig_foreach_name(RREGEXP(re)->ptr, reg_named_captures_iter, (void*)hash);
00803 return hash;
00804 }
00805
00806 static int
00807 onig_new_with_source(regex_t** reg, const UChar* pattern, const UChar* pattern_end,
00808 OnigOptionType option, OnigEncoding enc, const OnigSyntaxType* syntax,
00809 OnigErrorInfo* einfo, const char *sourcefile, int sourceline)
00810 {
00811 int r;
00812
00813 *reg = (regex_t* )malloc(sizeof(regex_t));
00814 if (IS_NULL(*reg)) return ONIGERR_MEMORY;
00815
00816 r = onig_reg_init(*reg, option, ONIGENC_CASE_FOLD_DEFAULT, enc, syntax);
00817 if (r) goto err;
00818
00819 r = onig_compile(*reg, pattern, pattern_end, einfo, sourcefile, sourceline);
00820 if (r) {
00821 err:
00822 onig_free(*reg);
00823 *reg = NULL;
00824 }
00825 return r;
00826 }
00827
00828 static Regexp*
00829 make_regexp(const char *s, long len, rb_encoding *enc, int flags, onig_errmsg_buffer err,
00830 const char *sourcefile, int sourceline)
00831 {
00832 Regexp *rp;
00833 int r;
00834 OnigErrorInfo einfo;
00835
00836
00837
00838
00839
00840
00841
00842
00843 r = onig_new_with_source(&rp, (UChar*)s, (UChar*)(s + len), flags,
00844 enc, OnigDefaultSyntax, &einfo, sourcefile, sourceline);
00845 if (r) {
00846 onig_error_code_to_str((UChar*)err, r, &einfo);
00847 return 0;
00848 }
00849 return rp;
00850 }
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865 VALUE rb_cMatch;
00866
00867 static VALUE
00868 match_alloc(VALUE klass)
00869 {
00870 NEWOBJ_OF(match, struct RMatch, klass, T_MATCH);
00871
00872 match->str = 0;
00873 match->rmatch = 0;
00874 match->regexp = 0;
00875 match->rmatch = ALLOC(struct rmatch);
00876 MEMZERO(match->rmatch, struct rmatch, 1);
00877
00878 return (VALUE)match;
00879 }
00880
00881 typedef struct {
00882 long byte_pos;
00883 long char_pos;
00884 } pair_t;
00885
00886 static int
00887 pair_byte_cmp(const void *pair1, const void *pair2)
00888 {
00889 long diff = ((pair_t*)pair1)->byte_pos - ((pair_t*)pair2)->byte_pos;
00890 #if SIZEOF_LONG > SIZEOF_INT
00891 return diff ? diff > 0 ? 1 : -1 : 0;
00892 #else
00893 return (int)diff;
00894 #endif
00895 }
00896
00897 static void
00898 update_char_offset(VALUE match)
00899 {
00900 struct rmatch *rm = RMATCH(match)->rmatch;
00901 struct re_registers *regs;
00902 int i, num_regs, num_pos;
00903 long c;
00904 char *s, *p, *q;
00905 rb_encoding *enc;
00906 pair_t *pairs;
00907
00908 if (rm->char_offset_updated)
00909 return;
00910
00911 regs = &rm->regs;
00912 num_regs = rm->regs.num_regs;
00913
00914 if (rm->char_offset_num_allocated < num_regs) {
00915 REALLOC_N(rm->char_offset, struct rmatch_offset, num_regs);
00916 rm->char_offset_num_allocated = num_regs;
00917 }
00918
00919 enc = rb_enc_get(RMATCH(match)->str);
00920 if (rb_enc_mbmaxlen(enc) == 1) {
00921 for (i = 0; i < num_regs; i++) {
00922 rm->char_offset[i].beg = BEG(i);
00923 rm->char_offset[i].end = END(i);
00924 }
00925 rm->char_offset_updated = 1;
00926 return;
00927 }
00928
00929 pairs = ALLOCA_N(pair_t, num_regs*2);
00930 num_pos = 0;
00931 for (i = 0; i < num_regs; i++) {
00932 if (BEG(i) < 0)
00933 continue;
00934 pairs[num_pos++].byte_pos = BEG(i);
00935 pairs[num_pos++].byte_pos = END(i);
00936 }
00937 qsort(pairs, num_pos, sizeof(pair_t), pair_byte_cmp);
00938
00939 s = p = RSTRING_PTR(RMATCH(match)->str);
00940 c = 0;
00941 for (i = 0; i < num_pos; i++) {
00942 q = s + pairs[i].byte_pos;
00943 c += rb_enc_strlen(p, q, enc);
00944 pairs[i].char_pos = c;
00945 p = q;
00946 }
00947
00948 for (i = 0; i < num_regs; i++) {
00949 pair_t key, *found;
00950 if (BEG(i) < 0) {
00951 rm->char_offset[i].beg = -1;
00952 rm->char_offset[i].end = -1;
00953 continue;
00954 }
00955
00956 key.byte_pos = BEG(i);
00957 found = bsearch(&key, pairs, num_pos, sizeof(pair_t), pair_byte_cmp);
00958 rm->char_offset[i].beg = found->char_pos;
00959
00960 key.byte_pos = END(i);
00961 found = bsearch(&key, pairs, num_pos, sizeof(pair_t), pair_byte_cmp);
00962 rm->char_offset[i].end = found->char_pos;
00963 }
00964
00965 rm->char_offset_updated = 1;
00966 }
00967
00968 static void
00969 match_check(VALUE match)
00970 {
00971 if (!RMATCH(match)->regexp) {
00972 rb_raise(rb_eTypeError, "uninitialized Match");
00973 }
00974 }
00975
00976
00977 static VALUE
00978 match_init_copy(VALUE obj, VALUE orig)
00979 {
00980 struct rmatch *rm;
00981
00982 if (!OBJ_INIT_COPY(obj, orig)) return obj;
00983
00984 RMATCH(obj)->str = RMATCH(orig)->str;
00985 RMATCH(obj)->regexp = RMATCH(orig)->regexp;
00986
00987 rm = RMATCH(obj)->rmatch;
00988 onig_region_copy(&rm->regs, RMATCH_REGS(orig));
00989
00990 if (!RMATCH(orig)->rmatch->char_offset_updated) {
00991 rm->char_offset_updated = 0;
00992 }
00993 else {
00994 if (rm->char_offset_num_allocated < rm->regs.num_regs) {
00995 REALLOC_N(rm->char_offset, struct rmatch_offset, rm->regs.num_regs);
00996 rm->char_offset_num_allocated = rm->regs.num_regs;
00997 }
00998 MEMCPY(rm->char_offset, RMATCH(orig)->rmatch->char_offset,
00999 struct rmatch_offset, rm->regs.num_regs);
01000 rm->char_offset_updated = 1;
01001 }
01002
01003 return obj;
01004 }
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017 static VALUE
01018 match_regexp(VALUE match)
01019 {
01020 match_check(match);
01021 return RMATCH(match)->regexp;
01022 }
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038 static VALUE
01039 match_names(VALUE match)
01040 {
01041 match_check(match);
01042 return rb_reg_names(RMATCH(match)->regexp);
01043 }
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057 static VALUE
01058 match_size(VALUE match)
01059 {
01060 match_check(match);
01061 return INT2FIX(RMATCH_REGS(match)->num_regs);
01062 }
01063
01064 static int
01065 match_backref_number(VALUE match, VALUE backref)
01066 {
01067 const char *name;
01068 int num;
01069
01070 struct re_registers *regs = RMATCH_REGS(match);
01071 VALUE regexp = RMATCH(match)->regexp;
01072
01073 match_check(match);
01074 switch (TYPE(backref)) {
01075 default:
01076 return NUM2INT(backref);
01077
01078 case T_SYMBOL:
01079 name = rb_id2name(SYM2ID(backref));
01080 break;
01081
01082 case T_STRING:
01083 name = StringValueCStr(backref);
01084 break;
01085 }
01086
01087 num = onig_name_to_backref_number(RREGEXP(regexp)->ptr,
01088 (const unsigned char*)name,
01089 (const unsigned char*)name + strlen(name),
01090 regs);
01091
01092 if (num < 1) {
01093 rb_raise(rb_eIndexError, "undefined group name reference: %s", name);
01094 }
01095
01096 return num;
01097 }
01098
01099 int
01100 rb_reg_backref_number(VALUE match, VALUE backref)
01101 {
01102 return match_backref_number(match, backref);
01103 }
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123 static VALUE
01124 match_offset(VALUE match, VALUE n)
01125 {
01126 int i = match_backref_number(match, n);
01127 struct re_registers *regs = RMATCH_REGS(match);
01128
01129 match_check(match);
01130 if (i < 0 || regs->num_regs <= i)
01131 rb_raise(rb_eIndexError, "index %d out of matches", i);
01132
01133 if (BEG(i) < 0)
01134 return rb_assoc_new(Qnil, Qnil);
01135
01136 update_char_offset(match);
01137 return rb_assoc_new(INT2FIX(RMATCH(match)->rmatch->char_offset[i].beg),
01138 INT2FIX(RMATCH(match)->rmatch->char_offset[i].end));
01139 }
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159 static VALUE
01160 match_begin(VALUE match, VALUE n)
01161 {
01162 int i = match_backref_number(match, n);
01163 struct re_registers *regs = RMATCH_REGS(match);
01164
01165 match_check(match);
01166 if (i < 0 || regs->num_regs <= i)
01167 rb_raise(rb_eIndexError, "index %d out of matches", i);
01168
01169 if (BEG(i) < 0)
01170 return Qnil;
01171
01172 update_char_offset(match);
01173 return INT2FIX(RMATCH(match)->rmatch->char_offset[i].beg);
01174 }
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194 static VALUE
01195 match_end(VALUE match, VALUE n)
01196 {
01197 int i = match_backref_number(match, n);
01198 struct re_registers *regs = RMATCH_REGS(match);
01199
01200 match_check(match);
01201 if (i < 0 || regs->num_regs <= i)
01202 rb_raise(rb_eIndexError, "index %d out of matches", i);
01203
01204 if (BEG(i) < 0)
01205 return Qnil;
01206
01207 update_char_offset(match);
01208 return INT2FIX(RMATCH(match)->rmatch->char_offset[i].end);
01209 }
01210
01211 #define MATCH_BUSY FL_USER2
01212
01213 void
01214 rb_match_busy(VALUE match)
01215 {
01216 FL_SET(match, MATCH_BUSY);
01217 }
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248 static VALUE
01249 rb_reg_fixed_encoding_p(VALUE re)
01250 {
01251 if (FL_TEST(re, KCODE_FIXED))
01252 return Qtrue;
01253 else
01254 return Qfalse;
01255 }
01256
01257 static VALUE
01258 rb_reg_preprocess(const char *p, const char *end, rb_encoding *enc,
01259 rb_encoding **fixed_enc, onig_errmsg_buffer err);
01260
01261
01262 static void
01263 reg_enc_error(VALUE re, VALUE str)
01264 {
01265 rb_raise(rb_eEncCompatError,
01266 "incompatible encoding regexp match (%s regexp with %s string)",
01267 rb_enc_name(rb_enc_get(re)),
01268 rb_enc_name(rb_enc_get(str)));
01269 }
01270
01271 static rb_encoding*
01272 rb_reg_prepare_enc(VALUE re, VALUE str, int warn)
01273 {
01274 rb_encoding *enc = 0;
01275
01276 if (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN) {
01277 rb_raise(rb_eArgError,
01278 "invalid byte sequence in %s",
01279 rb_enc_name(rb_enc_get(str)));
01280 }
01281
01282 rb_reg_check(re);
01283 enc = rb_enc_get(str);
01284 if (!rb_enc_str_asciicompat_p(str)) {
01285 if (RREGEXP(re)->ptr->enc != enc) {
01286 reg_enc_error(re, str);
01287 }
01288 }
01289 else if (rb_reg_fixed_encoding_p(re)) {
01290 if (RREGEXP(re)->ptr->enc != enc &&
01291 (!rb_enc_asciicompat(RREGEXP(re)->ptr->enc) ||
01292 rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT)) {
01293 reg_enc_error(re, str);
01294 }
01295 enc = RREGEXP(re)->ptr->enc;
01296 }
01297 if (warn && (RBASIC(re)->flags & REG_ENCODING_NONE) &&
01298 enc != rb_ascii8bit_encoding() &&
01299 rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
01300 rb_warn("regexp match /.../n against to %s string",
01301 rb_enc_name(enc));
01302 }
01303 return enc;
01304 }
01305
01306 regex_t *
01307 rb_reg_prepare_re(VALUE re, VALUE str)
01308 {
01309 regex_t *reg = RREGEXP(re)->ptr;
01310 onig_errmsg_buffer err = "";
01311 int r;
01312 OnigErrorInfo einfo;
01313 const char *pattern;
01314 VALUE unescaped;
01315 rb_encoding *fixed_enc = 0;
01316 rb_encoding *enc = rb_reg_prepare_enc(re, str, 1);
01317
01318 if (reg->enc == enc) return reg;
01319
01320 rb_reg_check(re);
01321 reg = RREGEXP(re)->ptr;
01322 pattern = RREGEXP_SRC_PTR(re);
01323
01324 unescaped = rb_reg_preprocess(
01325 pattern, pattern + RREGEXP_SRC_LEN(re), enc,
01326 &fixed_enc, err);
01327
01328 if (unescaped == Qnil) {
01329 rb_raise(rb_eArgError, "regexp preprocess failed: %s", err);
01330 }
01331
01332 r = onig_new(®, (UChar* )RSTRING_PTR(unescaped),
01333 (UChar* )(RSTRING_PTR(unescaped) + RSTRING_LEN(unescaped)),
01334 reg->options, enc,
01335 OnigDefaultSyntax, &einfo);
01336 if (r) {
01337 onig_error_code_to_str((UChar*)err, r, &einfo);
01338 rb_reg_raise(pattern, RREGEXP_SRC_LEN(re), err, re);
01339 }
01340
01341 RB_GC_GUARD(unescaped);
01342 return reg;
01343 }
01344
01345 long
01346 rb_reg_adjust_startpos(VALUE re, VALUE str, long pos, int reverse)
01347 {
01348 long range;
01349 rb_encoding *enc;
01350 UChar *p, *string;
01351
01352 enc = rb_reg_prepare_enc(re, str, 0);
01353
01354 if (reverse) {
01355 range = -pos;
01356 }
01357 else {
01358 range = RSTRING_LEN(str) - pos;
01359 }
01360
01361 if (pos > 0 && ONIGENC_MBC_MAXLEN(enc) != 1 && pos < RSTRING_LEN(str)) {
01362 string = (UChar*)RSTRING_PTR(str);
01363
01364 if (range > 0) {
01365 p = onigenc_get_right_adjust_char_head(enc, string, string + pos, string + RSTRING_LEN(str));
01366 }
01367 else {
01368 p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, string, string + pos, string + RSTRING_LEN(str));
01369 }
01370 return p - string;
01371 }
01372
01373 return pos;
01374 }
01375
01376
01377 long
01378 rb_reg_search(VALUE re, VALUE str, long pos, int reverse)
01379 {
01380 long result;
01381 VALUE match;
01382 struct re_registers regi, *regs = ®i;
01383 char *range = RSTRING_PTR(str);
01384 regex_t *reg;
01385 int tmpreg;
01386
01387 if (pos > RSTRING_LEN(str) || pos < 0) {
01388 rb_backref_set(Qnil);
01389 return -1;
01390 }
01391
01392 reg = rb_reg_prepare_re(re, str);
01393 tmpreg = reg != RREGEXP(re)->ptr;
01394 if (!tmpreg) RREGEXP(re)->usecnt++;
01395
01396 match = rb_backref_get();
01397 if (!NIL_P(match)) {
01398 if (FL_TEST(match, MATCH_BUSY)) {
01399 match = Qnil;
01400 }
01401 else {
01402 regs = RMATCH_REGS(match);
01403 }
01404 }
01405 if (NIL_P(match)) {
01406 MEMZERO(regs, struct re_registers, 1);
01407 }
01408 if (!reverse) {
01409 range += RSTRING_LEN(str);
01410 }
01411 result = onig_search(reg,
01412 (UChar*)(RSTRING_PTR(str)),
01413 ((UChar*)(RSTRING_PTR(str)) + RSTRING_LEN(str)),
01414 ((UChar*)(RSTRING_PTR(str)) + pos),
01415 ((UChar*)range),
01416 regs, ONIG_OPTION_NONE);
01417 if (!tmpreg) RREGEXP(re)->usecnt--;
01418 if (tmpreg) {
01419 if (RREGEXP(re)->usecnt) {
01420 onig_free(reg);
01421 }
01422 else {
01423 onig_free(RREGEXP(re)->ptr);
01424 RREGEXP(re)->ptr = reg;
01425 }
01426 }
01427 if (result < 0) {
01428 if (regs == ®i)
01429 onig_region_free(regs, 0);
01430 if (result == ONIG_MISMATCH) {
01431 rb_backref_set(Qnil);
01432 return result;
01433 }
01434 else {
01435 onig_errmsg_buffer err = "";
01436 onig_error_code_to_str((UChar*)err, (int)result);
01437 rb_reg_raise(RREGEXP_SRC_PTR(re), RREGEXP_SRC_LEN(re), err, re);
01438 }
01439 }
01440
01441 if (NIL_P(match)) {
01442 match = match_alloc(rb_cMatch);
01443 onig_region_copy(RMATCH_REGS(match), regs);
01444 onig_region_free(regs, 0);
01445 }
01446 else {
01447 if (rb_safe_level() >= 3)
01448 OBJ_TAINT(match);
01449 else
01450 FL_UNSET(match, FL_TAINT);
01451 }
01452
01453 RMATCH(match)->str = rb_str_new4(str);
01454 RMATCH(match)->regexp = re;
01455 RMATCH(match)->rmatch->char_offset_updated = 0;
01456 rb_backref_set(match);
01457
01458 OBJ_INFECT(match, re);
01459 OBJ_INFECT(match, str);
01460
01461 return result;
01462 }
01463
01464 VALUE
01465 rb_reg_nth_defined(int nth, VALUE match)
01466 {
01467 struct re_registers *regs;
01468 if (NIL_P(match)) return Qnil;
01469 match_check(match);
01470 regs = RMATCH_REGS(match);
01471 if (nth >= regs->num_regs) {
01472 return Qnil;
01473 }
01474 if (nth < 0) {
01475 nth += regs->num_regs;
01476 if (nth <= 0) return Qnil;
01477 }
01478 if (BEG(nth) == -1) return Qfalse;
01479 return Qtrue;
01480 }
01481
01482 VALUE
01483 rb_reg_nth_match(int nth, VALUE match)
01484 {
01485 VALUE str;
01486 long start, end, len;
01487 struct re_registers *regs;
01488
01489 if (NIL_P(match)) return Qnil;
01490 match_check(match);
01491 regs = RMATCH_REGS(match);
01492 if (nth >= regs->num_regs) {
01493 return Qnil;
01494 }
01495 if (nth < 0) {
01496 nth += regs->num_regs;
01497 if (nth <= 0) return Qnil;
01498 }
01499 start = BEG(nth);
01500 if (start == -1) return Qnil;
01501 end = END(nth);
01502 len = end - start;
01503 str = rb_str_subseq(RMATCH(match)->str, start, len);
01504 OBJ_INFECT(str, match);
01505 return str;
01506 }
01507
01508 VALUE
01509 rb_reg_last_match(VALUE match)
01510 {
01511 return rb_reg_nth_match(0, match);
01512 }
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526 VALUE
01527 rb_reg_match_pre(VALUE match)
01528 {
01529 VALUE str;
01530 struct re_registers *regs;
01531
01532 if (NIL_P(match)) return Qnil;
01533 match_check(match);
01534 regs = RMATCH_REGS(match);
01535 if (BEG(0) == -1) return Qnil;
01536 str = rb_str_subseq(RMATCH(match)->str, 0, BEG(0));
01537 if (OBJ_TAINTED(match)) OBJ_TAINT(str);
01538 return str;
01539 }
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553 VALUE
01554 rb_reg_match_post(VALUE match)
01555 {
01556 VALUE str;
01557 long pos;
01558 struct re_registers *regs;
01559
01560 if (NIL_P(match)) return Qnil;
01561 match_check(match);
01562 regs = RMATCH_REGS(match);
01563 if (BEG(0) == -1) return Qnil;
01564 str = RMATCH(match)->str;
01565 pos = END(0);
01566 str = rb_str_subseq(str, pos, RSTRING_LEN(str) - pos);
01567 if (OBJ_TAINTED(match)) OBJ_TAINT(str);
01568 return str;
01569 }
01570
01571 VALUE
01572 rb_reg_match_last(VALUE match)
01573 {
01574 int i;
01575 struct re_registers *regs;
01576
01577 if (NIL_P(match)) return Qnil;
01578 match_check(match);
01579 regs = RMATCH_REGS(match);
01580 if (BEG(0) == -1) return Qnil;
01581
01582 for (i=regs->num_regs-1; BEG(i) == -1 && i > 0; i--)
01583 ;
01584 if (i == 0) return Qnil;
01585 return rb_reg_nth_match(i, match);
01586 }
01587
01588 static VALUE
01589 last_match_getter(void)
01590 {
01591 return rb_reg_last_match(rb_backref_get());
01592 }
01593
01594 static VALUE
01595 prematch_getter(void)
01596 {
01597 return rb_reg_match_pre(rb_backref_get());
01598 }
01599
01600 static VALUE
01601 postmatch_getter(void)
01602 {
01603 return rb_reg_match_post(rb_backref_get());
01604 }
01605
01606 static VALUE
01607 last_paren_match_getter(void)
01608 {
01609 return rb_reg_match_last(rb_backref_get());
01610 }
01611
01612 static VALUE
01613 match_array(VALUE match, int start)
01614 {
01615 struct re_registers *regs;
01616 VALUE ary;
01617 VALUE target;
01618 int i;
01619 int taint = OBJ_TAINTED(match);
01620
01621 match_check(match);
01622 regs = RMATCH_REGS(match);
01623 ary = rb_ary_new2(regs->num_regs);
01624 target = RMATCH(match)->str;
01625
01626 for (i=start; i<regs->num_regs; i++) {
01627 if (regs->beg[i] == -1) {
01628 rb_ary_push(ary, Qnil);
01629 }
01630 else {
01631 VALUE str = rb_str_subseq(target, regs->beg[i], regs->end[i]-regs->beg[i]);
01632 if (taint) OBJ_TAINT(str);
01633 rb_ary_push(ary, str);
01634 }
01635 }
01636 return ary;
01637 }
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666 static VALUE
01667 match_to_a(VALUE match)
01668 {
01669 return match_array(match, 0);
01670 }
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685 static VALUE
01686 match_captures(VALUE match)
01687 {
01688 return match_array(match, 1);
01689 }
01690
01691 static int
01692 name_to_backref_number(struct re_registers *regs, VALUE regexp, const char* name, const char* name_end)
01693 {
01694 return onig_name_to_backref_number(RREGEXP(regexp)->ptr,
01695 (const unsigned char* )name, (const unsigned char* )name_end, regs);
01696 }
01697
01698 NORETURN(static void name_to_backref_error(VALUE name));
01699 static void
01700 name_to_backref_error(VALUE name)
01701 {
01702 rb_raise(rb_eIndexError, "undefined group name reference: % "PRIsVALUE,
01703 name);
01704 }
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733 static VALUE
01734 match_aref(int argc, VALUE *argv, VALUE match)
01735 {
01736 VALUE idx, rest;
01737
01738 match_check(match);
01739 rb_scan_args(argc, argv, "11", &idx, &rest);
01740
01741 if (NIL_P(rest)) {
01742 if (FIXNUM_P(idx)) {
01743 if (FIX2INT(idx) >= 0) {
01744 return rb_reg_nth_match(FIX2INT(idx), match);
01745 }
01746 }
01747 else {
01748 const char *p;
01749 int num;
01750
01751 switch (TYPE(idx)) {
01752 case T_SYMBOL:
01753 idx = rb_id2str(SYM2ID(idx));
01754
01755 case T_STRING:
01756 p = StringValuePtr(idx);
01757 if (!rb_enc_compatible(RREGEXP(RMATCH(match)->regexp)->src, idx) ||
01758 (num = name_to_backref_number(RMATCH_REGS(match), RMATCH(match)->regexp,
01759 p, p + RSTRING_LEN(idx))) < 1) {
01760 name_to_backref_error(idx);
01761 }
01762 return rb_reg_nth_match(num, match);
01763
01764 default:
01765 break;
01766 }
01767 }
01768 }
01769
01770 return rb_ary_aref(argc, argv, match_to_a(match));
01771 }
01772
01773 static VALUE
01774 match_entry(VALUE match, long n)
01775 {
01776
01777 return rb_reg_nth_match((int)n, match);
01778 }
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794 static VALUE
01795 match_values_at(int argc, VALUE *argv, VALUE match)
01796 {
01797 struct re_registers *regs;
01798
01799 match_check(match);
01800 regs = RMATCH_REGS(match);
01801 return rb_get_values_at(match, regs->num_regs, argc, argv, match_entry);
01802 }
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815 static VALUE
01816 match_to_s(VALUE match)
01817 {
01818 VALUE str = rb_reg_last_match(match);
01819
01820 match_check(match);
01821 if (NIL_P(str)) str = rb_str_new(0,0);
01822 if (OBJ_TAINTED(match)) OBJ_TAINT(str);
01823 if (OBJ_TAINTED(RMATCH(match)->str)) OBJ_TAINT(str);
01824 return str;
01825 }
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838 static VALUE
01839 match_string(VALUE match)
01840 {
01841 match_check(match);
01842 return RMATCH(match)->str;
01843 }
01844
01845 struct backref_name_tag {
01846 const UChar *name;
01847 long len;
01848 };
01849
01850 static int
01851 match_inspect_name_iter(const OnigUChar *name, const OnigUChar *name_end,
01852 int back_num, int *back_refs, OnigRegex regex, void *arg0)
01853 {
01854 struct backref_name_tag *arg = (struct backref_name_tag *)arg0;
01855 int i;
01856
01857 for (i = 0; i < back_num; i++) {
01858 arg[back_refs[i]].name = name;
01859 arg[back_refs[i]].len = name_end - name;
01860 }
01861 return 0;
01862 }
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884 static VALUE
01885 match_inspect(VALUE match)
01886 {
01887 const char *cname = rb_obj_classname(match);
01888 VALUE str;
01889 int i;
01890 struct re_registers *regs = RMATCH_REGS(match);
01891 int num_regs = regs->num_regs;
01892 struct backref_name_tag *names;
01893 VALUE regexp = RMATCH(match)->regexp;
01894
01895 if (regexp == 0) {
01896 return rb_sprintf("#<%s:%p>", cname, (void*)match);
01897 }
01898
01899 names = ALLOCA_N(struct backref_name_tag, num_regs);
01900 MEMZERO(names, struct backref_name_tag, num_regs);
01901
01902 onig_foreach_name(RREGEXP(regexp)->ptr,
01903 match_inspect_name_iter, names);
01904
01905 str = rb_str_buf_new2("#<");
01906 rb_str_buf_cat2(str, cname);
01907
01908 for (i = 0; i < num_regs; i++) {
01909 VALUE v;
01910 rb_str_buf_cat2(str, " ");
01911 if (0 < i) {
01912 if (names[i].name)
01913 rb_str_buf_cat(str, (const char *)names[i].name, names[i].len);
01914 else {
01915 rb_str_catf(str, "%d", i);
01916 }
01917 rb_str_buf_cat2(str, ":");
01918 }
01919 v = rb_reg_nth_match(i, match);
01920 if (v == Qnil)
01921 rb_str_buf_cat2(str, "nil");
01922 else
01923 rb_str_buf_append(str, rb_str_inspect(v));
01924 }
01925 rb_str_buf_cat2(str, ">");
01926
01927 return str;
01928 }
01929
01930 VALUE rb_cRegexp;
01931
01932 static int
01933 read_escaped_byte(const char **pp, const char *end, onig_errmsg_buffer err)
01934 {
01935 const char *p = *pp;
01936 int code;
01937 int meta_prefix = 0, ctrl_prefix = 0;
01938 size_t len;
01939
01940 if (p == end || *p++ != '\\') {
01941 errcpy(err, "too short escaped multibyte character");
01942 return -1;
01943 }
01944
01945 again:
01946 if (p == end) {
01947 errcpy(err, "too short escape sequence");
01948 return -1;
01949 }
01950 switch (*p++) {
01951 case '\\': code = '\\'; break;
01952 case 'n': code = '\n'; break;
01953 case 't': code = '\t'; break;
01954 case 'r': code = '\r'; break;
01955 case 'f': code = '\f'; break;
01956 case 'v': code = '\013'; break;
01957 case 'a': code = '\007'; break;
01958 case 'e': code = '\033'; break;
01959
01960
01961 case '0': case '1': case '2': case '3':
01962 case '4': case '5': case '6': case '7':
01963 p--;
01964 code = scan_oct(p, end < p+3 ? end-p : 3, &len);
01965 p += len;
01966 break;
01967
01968 case 'x':
01969 code = scan_hex(p, end < p+2 ? end-p : 2, &len);
01970 if (len < 1) {
01971 errcpy(err, "invalid hex escape");
01972 return -1;
01973 }
01974 p += len;
01975 break;
01976
01977 case 'M':
01978 if (meta_prefix) {
01979 errcpy(err, "duplicate meta escape");
01980 return -1;
01981 }
01982 meta_prefix = 1;
01983 if (p+1 < end && *p++ == '-' && (*p & 0x80) == 0) {
01984 if (*p == '\\') {
01985 p++;
01986 goto again;
01987 }
01988 else {
01989 code = *p++;
01990 break;
01991 }
01992 }
01993 errcpy(err, "too short meta escape");
01994 return -1;
01995
01996 case 'C':
01997 if (p == end || *p++ != '-') {
01998 errcpy(err, "too short control escape");
01999 return -1;
02000 }
02001 case 'c':
02002 if (ctrl_prefix) {
02003 errcpy(err, "duplicate control escape");
02004 return -1;
02005 }
02006 ctrl_prefix = 1;
02007 if (p < end && (*p & 0x80) == 0) {
02008 if (*p == '\\') {
02009 p++;
02010 goto again;
02011 }
02012 else {
02013 code = *p++;
02014 break;
02015 }
02016 }
02017 errcpy(err, "too short control escape");
02018 return -1;
02019
02020 default:
02021 errcpy(err, "unexpected escape sequence");
02022 return -1;
02023 }
02024 if (code < 0 || 0xff < code) {
02025 errcpy(err, "invalid escape code");
02026 return -1;
02027 }
02028
02029 if (ctrl_prefix)
02030 code &= 0x1f;
02031 if (meta_prefix)
02032 code |= 0x80;
02033
02034 *pp = p;
02035 return code;
02036 }
02037
02038 static int
02039 unescape_escaped_nonascii(const char **pp, const char *end, rb_encoding *enc,
02040 VALUE buf, rb_encoding **encp, onig_errmsg_buffer err)
02041 {
02042 const char *p = *pp;
02043 int chmaxlen = rb_enc_mbmaxlen(enc);
02044 char *chbuf = ALLOCA_N(char, chmaxlen);
02045 int chlen = 0;
02046 int byte;
02047 int l;
02048
02049 memset(chbuf, 0, chmaxlen);
02050
02051 byte = read_escaped_byte(&p, end, err);
02052 if (byte == -1) {
02053 return -1;
02054 }
02055
02056 chbuf[chlen++] = byte;
02057 while (chlen < chmaxlen &&
02058 MBCLEN_NEEDMORE_P(rb_enc_precise_mbclen(chbuf, chbuf+chlen, enc))) {
02059 byte = read_escaped_byte(&p, end, err);
02060 if (byte == -1) {
02061 return -1;
02062 }
02063 chbuf[chlen++] = byte;
02064 }
02065
02066 l = rb_enc_precise_mbclen(chbuf, chbuf+chlen, enc);
02067 if (MBCLEN_INVALID_P(l)) {
02068 errcpy(err, "invalid multibyte escape");
02069 return -1;
02070 }
02071 if (1 < chlen || (chbuf[0] & 0x80)) {
02072 rb_str_buf_cat(buf, chbuf, chlen);
02073
02074 if (*encp == 0)
02075 *encp = enc;
02076 else if (*encp != enc) {
02077 errcpy(err, "escaped non ASCII character in UTF-8 regexp");
02078 return -1;
02079 }
02080 }
02081 else {
02082 char escbuf[5];
02083 snprintf(escbuf, sizeof(escbuf), "\\x%02X", chbuf[0]&0xff);
02084 rb_str_buf_cat(buf, escbuf, 4);
02085 }
02086 *pp = p;
02087 return 0;
02088 }
02089
02090 static int
02091 check_unicode_range(unsigned long code, onig_errmsg_buffer err)
02092 {
02093 if ((0xd800 <= code && code <= 0xdfff) ||
02094 0x10ffff < code) {
02095 errcpy(err, "invalid Unicode range");
02096 return -1;
02097 }
02098 return 0;
02099 }
02100
02101 static int
02102 append_utf8(unsigned long uv,
02103 VALUE buf, rb_encoding **encp, onig_errmsg_buffer err)
02104 {
02105 if (check_unicode_range(uv, err) != 0)
02106 return -1;
02107 if (uv < 0x80) {
02108 char escbuf[5];
02109 snprintf(escbuf, sizeof(escbuf), "\\x%02X", (int)uv);
02110 rb_str_buf_cat(buf, escbuf, 4);
02111 }
02112 else {
02113 int len;
02114 char utf8buf[6];
02115 len = rb_uv_to_utf8(utf8buf, uv);
02116 rb_str_buf_cat(buf, utf8buf, len);
02117
02118 if (*encp == 0)
02119 *encp = rb_utf8_encoding();
02120 else if (*encp != rb_utf8_encoding()) {
02121 errcpy(err, "UTF-8 character in non UTF-8 regexp");
02122 return -1;
02123 }
02124 }
02125 return 0;
02126 }
02127
02128 static int
02129 unescape_unicode_list(const char **pp, const char *end,
02130 VALUE buf, rb_encoding **encp, onig_errmsg_buffer err)
02131 {
02132 const char *p = *pp;
02133 int has_unicode = 0;
02134 unsigned long code;
02135 size_t len;
02136
02137 while (p < end && ISSPACE(*p)) p++;
02138
02139 while (1) {
02140 code = ruby_scan_hex(p, end-p, &len);
02141 if (len == 0)
02142 break;
02143 if (6 < len) {
02144 errcpy(err, "invalid Unicode range");
02145 return -1;
02146 }
02147 p += len;
02148 if (append_utf8(code, buf, encp, err) != 0)
02149 return -1;
02150 has_unicode = 1;
02151
02152 while (p < end && ISSPACE(*p)) p++;
02153 }
02154
02155 if (has_unicode == 0) {
02156 errcpy(err, "invalid Unicode list");
02157 return -1;
02158 }
02159
02160 *pp = p;
02161
02162 return 0;
02163 }
02164
02165 static int
02166 unescape_unicode_bmp(const char **pp, const char *end,
02167 VALUE buf, rb_encoding **encp, onig_errmsg_buffer err)
02168 {
02169 const char *p = *pp;
02170 size_t len;
02171 unsigned long code;
02172
02173 if (end < p+4) {
02174 errcpy(err, "invalid Unicode escape");
02175 return -1;
02176 }
02177 code = ruby_scan_hex(p, 4, &len);
02178 if (len != 4) {
02179 errcpy(err, "invalid Unicode escape");
02180 return -1;
02181 }
02182 if (append_utf8(code, buf, encp, err) != 0)
02183 return -1;
02184 *pp = p + 4;
02185 return 0;
02186 }
02187
02188 static int
02189 unescape_nonascii(const char *p, const char *end, rb_encoding *enc,
02190 VALUE buf, rb_encoding **encp, int *has_property,
02191 onig_errmsg_buffer err)
02192 {
02193 char c;
02194 char smallbuf[2];
02195
02196 while (p < end) {
02197 int chlen = rb_enc_precise_mbclen(p, end, enc);
02198 if (!MBCLEN_CHARFOUND_P(chlen)) {
02199 errcpy(err, "invalid multibyte character");
02200 return -1;
02201 }
02202 chlen = MBCLEN_CHARFOUND_LEN(chlen);
02203 if (1 < chlen || (*p & 0x80)) {
02204 rb_str_buf_cat(buf, p, chlen);
02205 p += chlen;
02206 if (*encp == 0)
02207 *encp = enc;
02208 else if (*encp != enc) {
02209 errcpy(err, "non ASCII character in UTF-8 regexp");
02210 return -1;
02211 }
02212 continue;
02213 }
02214
02215 switch (c = *p++) {
02216 case '\\':
02217 if (p == end) {
02218 errcpy(err, "too short escape sequence");
02219 return -1;
02220 }
02221 switch (c = *p++) {
02222 case '1': case '2': case '3':
02223 case '4': case '5': case '6': case '7':
02224 {
02225 size_t octlen;
02226 if (ruby_scan_oct(p-1, end-(p-1), &octlen) <= 0177) {
02227
02228
02229
02230 goto escape_asis;
02231 }
02232 }
02233
02234
02235 case '0':
02236
02237 case 'x':
02238 case 'c':
02239 case 'C':
02240 case 'M':
02241 p = p-2;
02242 if (unescape_escaped_nonascii(&p, end, enc, buf, encp, err) != 0)
02243 return -1;
02244 break;
02245
02246 case 'u':
02247 if (p == end) {
02248 errcpy(err, "too short escape sequence");
02249 return -1;
02250 }
02251 if (*p == '{') {
02252
02253 p++;
02254 if (unescape_unicode_list(&p, end, buf, encp, err) != 0)
02255 return -1;
02256 if (p == end || *p++ != '}') {
02257 errcpy(err, "invalid Unicode list");
02258 return -1;
02259 }
02260 break;
02261 }
02262 else {
02263
02264 if (unescape_unicode_bmp(&p, end, buf, encp, err) != 0)
02265 return -1;
02266 break;
02267 }
02268
02269 case 'p':
02270 case 'P':
02271 if (!*encp) {
02272 *has_property = 1;
02273 }
02274 goto escape_asis;
02275
02276 default:
02277 escape_asis:
02278 smallbuf[0] = '\\';
02279 smallbuf[1] = c;
02280 rb_str_buf_cat(buf, smallbuf, 2);
02281 break;
02282 }
02283 break;
02284
02285 default:
02286 rb_str_buf_cat(buf, &c, 1);
02287 break;
02288 }
02289 }
02290
02291 return 0;
02292 }
02293
02294 static VALUE
02295 rb_reg_preprocess(const char *p, const char *end, rb_encoding *enc,
02296 rb_encoding **fixed_enc, onig_errmsg_buffer err)
02297 {
02298 VALUE buf;
02299 int has_property = 0;
02300
02301 buf = rb_str_buf_new(0);
02302
02303 if (rb_enc_asciicompat(enc))
02304 *fixed_enc = 0;
02305 else {
02306 *fixed_enc = enc;
02307 rb_enc_associate(buf, enc);
02308 }
02309
02310 if (unescape_nonascii(p, end, enc, buf, fixed_enc, &has_property, err) != 0)
02311 return Qnil;
02312
02313 if (has_property && !*fixed_enc) {
02314 *fixed_enc = enc;
02315 }
02316
02317 if (*fixed_enc) {
02318 rb_enc_associate(buf, *fixed_enc);
02319 }
02320
02321 return buf;
02322 }
02323
02324 VALUE
02325 rb_reg_check_preprocess(VALUE str)
02326 {
02327 rb_encoding *fixed_enc = 0;
02328 onig_errmsg_buffer err = "";
02329 VALUE buf;
02330 char *p, *end;
02331 rb_encoding *enc;
02332
02333 StringValue(str);
02334 p = RSTRING_PTR(str);
02335 end = p + RSTRING_LEN(str);
02336 enc = rb_enc_get(str);
02337
02338 buf = rb_reg_preprocess(p, end, enc, &fixed_enc, err);
02339 RB_GC_GUARD(str);
02340
02341 if (buf == Qnil) {
02342 return rb_reg_error_desc(str, 0, err);
02343 }
02344 return Qnil;
02345 }
02346
02347 static VALUE
02348 rb_reg_preprocess_dregexp(VALUE ary, int options)
02349 {
02350 rb_encoding *fixed_enc = 0;
02351 rb_encoding *regexp_enc = 0;
02352 onig_errmsg_buffer err = "";
02353 int i;
02354 VALUE result = 0;
02355 rb_encoding *ascii8bit = rb_ascii8bit_encoding();
02356
02357 if (RARRAY_LEN(ary) == 0) {
02358 rb_raise(rb_eArgError, "no arguments given");
02359 }
02360
02361 for (i = 0; i < RARRAY_LEN(ary); i++) {
02362 VALUE str = RARRAY_AREF(ary, i);
02363 VALUE buf;
02364 char *p, *end;
02365 rb_encoding *src_enc;
02366
02367 src_enc = rb_enc_get(str);
02368 if (options & ARG_ENCODING_NONE &&
02369 src_enc != ascii8bit) {
02370 if (rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT)
02371 rb_raise(rb_eRegexpError, "/.../n has a non escaped non ASCII character in non ASCII-8BIT script");
02372 else
02373 src_enc = ascii8bit;
02374 }
02375
02376 StringValue(str);
02377 p = RSTRING_PTR(str);
02378 end = p + RSTRING_LEN(str);
02379
02380 buf = rb_reg_preprocess(p, end, src_enc, &fixed_enc, err);
02381
02382 if (buf == Qnil)
02383 rb_raise(rb_eArgError, "%s", err);
02384
02385 if (fixed_enc != 0) {
02386 if (regexp_enc != 0 && regexp_enc != fixed_enc) {
02387 rb_raise(rb_eRegexpError, "encoding mismatch in dynamic regexp : %s and %s",
02388 rb_enc_name(regexp_enc), rb_enc_name(fixed_enc));
02389 }
02390 regexp_enc = fixed_enc;
02391 }
02392
02393 if (!result)
02394 result = rb_str_new3(str);
02395 else
02396 rb_str_buf_append(result, str);
02397 }
02398 if (regexp_enc) {
02399 rb_enc_associate(result, regexp_enc);
02400 }
02401
02402 return result;
02403 }
02404
02405 static int
02406 rb_reg_initialize(VALUE obj, const char *s, long len, rb_encoding *enc,
02407 int options, onig_errmsg_buffer err,
02408 const char *sourcefile, int sourceline)
02409 {
02410 struct RRegexp *re = RREGEXP(obj);
02411 VALUE unescaped;
02412 rb_encoding *fixed_enc = 0;
02413 rb_encoding *a_enc = rb_ascii8bit_encoding();
02414
02415 rb_check_frozen(obj);
02416 if (FL_TEST(obj, REG_LITERAL))
02417 rb_raise(rb_eSecurityError, "can't modify literal regexp");
02418 if (re->ptr)
02419 rb_raise(rb_eTypeError, "already initialized regexp");
02420 re->ptr = 0;
02421
02422 if (rb_enc_dummy_p(enc)) {
02423 errcpy(err, "can't make regexp with dummy encoding");
02424 return -1;
02425 }
02426
02427 unescaped = rb_reg_preprocess(s, s+len, enc, &fixed_enc, err);
02428 if (unescaped == Qnil)
02429 return -1;
02430
02431 if (fixed_enc) {
02432 if ((fixed_enc != enc && (options & ARG_ENCODING_FIXED)) ||
02433 (fixed_enc != a_enc && (options & ARG_ENCODING_NONE))) {
02434 errcpy(err, "incompatible character encoding");
02435 return -1;
02436 }
02437 if (fixed_enc != a_enc) {
02438 options |= ARG_ENCODING_FIXED;
02439 enc = fixed_enc;
02440 }
02441 }
02442 else if (!(options & ARG_ENCODING_FIXED)) {
02443 enc = rb_usascii_encoding();
02444 }
02445
02446 rb_enc_associate((VALUE)re, enc);
02447 if ((options & ARG_ENCODING_FIXED) || fixed_enc) {
02448 re->basic.flags |= KCODE_FIXED;
02449 }
02450 if (options & ARG_ENCODING_NONE) {
02451 re->basic.flags |= REG_ENCODING_NONE;
02452 }
02453
02454 re->ptr = make_regexp(RSTRING_PTR(unescaped), RSTRING_LEN(unescaped), enc,
02455 options & ARG_REG_OPTION_MASK, err,
02456 sourcefile, sourceline);
02457 if (!re->ptr) return -1;
02458 RB_OBJ_WRITE(obj, &re->src, rb_fstring(rb_enc_str_new(s, len, enc)));
02459 RB_GC_GUARD(unescaped);
02460 return 0;
02461 }
02462
02463 static int
02464 rb_reg_initialize_str(VALUE obj, VALUE str, int options, onig_errmsg_buffer err,
02465 const char *sourcefile, int sourceline)
02466 {
02467 int ret;
02468 rb_encoding *enc = rb_enc_get(str);
02469 if (options & ARG_ENCODING_NONE) {
02470 rb_encoding *ascii8bit = rb_ascii8bit_encoding();
02471 if (enc != ascii8bit) {
02472 if (rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
02473 errcpy(err, "/.../n has a non escaped non ASCII character in non ASCII-8BIT script");
02474 return -1;
02475 }
02476 enc = ascii8bit;
02477 }
02478 }
02479 ret = rb_reg_initialize(obj, RSTRING_PTR(str), RSTRING_LEN(str), enc,
02480 options, err, sourcefile, sourceline);
02481 OBJ_INFECT(obj, str);
02482 RB_GC_GUARD(str);
02483 return ret;
02484 }
02485
02486 static VALUE
02487 rb_reg_s_alloc(VALUE klass)
02488 {
02489 NEWOBJ_OF(re, struct RRegexp, klass, T_REGEXP | (RGENGC_WB_PROTECTED_REGEXP ? FL_WB_PROTECTED : 0));
02490
02491 re->ptr = 0;
02492 RB_OBJ_WRITE(re, &re->src, 0);
02493 re->usecnt = 0;
02494
02495 return (VALUE)re;
02496 }
02497
02498 VALUE
02499 rb_reg_alloc(void)
02500 {
02501 return rb_reg_s_alloc(rb_cRegexp);
02502 }
02503
02504 VALUE
02505 rb_reg_new_str(VALUE s, int options)
02506 {
02507 return rb_reg_init_str(rb_reg_alloc(), s, options);
02508 }
02509
02510 VALUE
02511 rb_reg_init_str(VALUE re, VALUE s, int options)
02512 {
02513 onig_errmsg_buffer err = "";
02514
02515 if (rb_reg_initialize_str(re, s, options, err, NULL, 0) != 0) {
02516 rb_reg_raise_str(s, options, err);
02517 }
02518
02519 return re;
02520 }
02521
02522 VALUE
02523 rb_reg_new_ary(VALUE ary, int opt)
02524 {
02525 return rb_reg_new_str(rb_reg_preprocess_dregexp(ary, opt), opt);
02526 }
02527
02528 VALUE
02529 rb_enc_reg_new(const char *s, long len, rb_encoding *enc, int options)
02530 {
02531 VALUE re = rb_reg_alloc();
02532 onig_errmsg_buffer err = "";
02533
02534 if (rb_reg_initialize(re, s, len, enc, options, err, NULL, 0) != 0) {
02535 rb_enc_reg_raise(s, len, enc, options, err);
02536 }
02537
02538 return re;
02539 }
02540
02541 VALUE
02542 rb_reg_new(const char *s, long len, int options)
02543 {
02544 return rb_enc_reg_new(s, len, rb_ascii8bit_encoding(), options);
02545 }
02546
02547 VALUE
02548 rb_reg_compile(VALUE str, int options, const char *sourcefile, int sourceline)
02549 {
02550 VALUE re = rb_reg_alloc();
02551 onig_errmsg_buffer err = "";
02552
02553 if (!str) str = rb_str_new(0,0);
02554 if (rb_reg_initialize_str(re, str, options, err, sourcefile, sourceline) != 0) {
02555 rb_set_errinfo(rb_reg_error_desc(str, options, err));
02556 return Qnil;
02557 }
02558 FL_SET(re, REG_LITERAL);
02559 return re;
02560 }
02561
02562 static VALUE reg_cache;
02563
02564 VALUE
02565 rb_reg_regcomp(VALUE str)
02566 {
02567 volatile VALUE save_str = str;
02568 if (reg_cache && RREGEXP_SRC_LEN(reg_cache) == RSTRING_LEN(str)
02569 && ENCODING_GET(reg_cache) == ENCODING_GET(str)
02570 && memcmp(RREGEXP_SRC_PTR(reg_cache), RSTRING_PTR(str), RSTRING_LEN(str)) == 0)
02571 return reg_cache;
02572
02573 return reg_cache = rb_reg_new_str(save_str, 0);
02574 }
02575
02576 static st_index_t reg_hash(VALUE re);
02577
02578
02579
02580
02581
02582
02583
02584 static VALUE
02585 rb_reg_hash(VALUE re)
02586 {
02587 st_index_t hashval = reg_hash(re);
02588 return LONG2FIX(hashval);
02589 }
02590
02591 static st_index_t
02592 reg_hash(VALUE re)
02593 {
02594 st_index_t hashval;
02595
02596 rb_reg_check(re);
02597 hashval = RREGEXP(re)->ptr->options;
02598 hashval = rb_hash_uint(hashval, rb_memhash(RREGEXP_SRC_PTR(re), RREGEXP_SRC_LEN(re)));
02599 return rb_hash_end(hashval);
02600 }
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618 static VALUE
02619 rb_reg_equal(VALUE re1, VALUE re2)
02620 {
02621 if (re1 == re2) return Qtrue;
02622 if (!RB_TYPE_P(re2, T_REGEXP)) return Qfalse;
02623 rb_reg_check(re1); rb_reg_check(re2);
02624 if (FL_TEST(re1, KCODE_FIXED) != FL_TEST(re2, KCODE_FIXED)) return Qfalse;
02625 if (RREGEXP(re1)->ptr->options != RREGEXP(re2)->ptr->options) return Qfalse;
02626 if (RREGEXP_SRC_LEN(re1) != RREGEXP_SRC_LEN(re2)) return Qfalse;
02627 if (ENCODING_GET(re1) != ENCODING_GET(re2)) return Qfalse;
02628 if (memcmp(RREGEXP_SRC_PTR(re1), RREGEXP_SRC_PTR(re2), RREGEXP_SRC_LEN(re1)) == 0) {
02629 return Qtrue;
02630 }
02631 return Qfalse;
02632 }
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642 static VALUE
02643 match_hash(VALUE match)
02644 {
02645 const struct re_registers *regs;
02646 st_index_t hashval = rb_hash_start(rb_str_hash(RMATCH(match)->str));
02647
02648 rb_hash_uint(hashval, reg_hash(RMATCH(match)->regexp));
02649 regs = RMATCH_REGS(match);
02650 hashval = rb_hash_uint(hashval, regs->num_regs);
02651 hashval = rb_hash_uint(hashval, rb_memhash(regs->beg, regs->num_regs * sizeof(*regs->beg)));
02652 hashval = rb_hash_uint(hashval, rb_memhash(regs->end, regs->num_regs * sizeof(*regs->end)));
02653 hashval = rb_hash_end(hashval);
02654 return LONG2FIX(hashval);
02655 }
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665
02666 static VALUE
02667 match_equal(VALUE match1, VALUE match2)
02668 {
02669 const struct re_registers *regs1, *regs2;
02670 if (match1 == match2) return Qtrue;
02671 if (!RB_TYPE_P(match2, T_MATCH)) return Qfalse;
02672 if (!rb_str_equal(RMATCH(match1)->str, RMATCH(match2)->str)) return Qfalse;
02673 if (!rb_reg_equal(RMATCH(match1)->regexp, RMATCH(match2)->regexp)) return Qfalse;
02674 regs1 = RMATCH_REGS(match1);
02675 regs2 = RMATCH_REGS(match2);
02676 if (regs1->num_regs != regs2->num_regs) return Qfalse;
02677 if (memcmp(regs1->beg, regs2->beg, regs1->num_regs * sizeof(*regs1->beg))) return Qfalse;
02678 if (memcmp(regs1->end, regs2->end, regs1->num_regs * sizeof(*regs1->end))) return Qfalse;
02679 return Qtrue;
02680 }
02681
02682 static VALUE
02683 reg_operand(VALUE s, int check)
02684 {
02685 if (SYMBOL_P(s)) {
02686 return rb_sym_to_s(s);
02687 }
02688 else {
02689 return (check ? rb_str_to_str : rb_check_string_type)(s);
02690 }
02691 }
02692
02693 static long
02694 reg_match_pos(VALUE re, VALUE *strp, long pos)
02695 {
02696 VALUE str = *strp;
02697
02698 if (NIL_P(str)) {
02699 rb_backref_set(Qnil);
02700 return -1;
02701 }
02702 *strp = str = reg_operand(str, TRUE);
02703 if (pos != 0) {
02704 if (pos < 0) {
02705 VALUE l = rb_str_length(str);
02706 pos += NUM2INT(l);
02707 if (pos < 0) {
02708 return pos;
02709 }
02710 }
02711 pos = rb_str_offset(str, pos);
02712 }
02713 return rb_reg_search(re, str, pos, 0);
02714 }
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764 VALUE
02765 rb_reg_match(VALUE re, VALUE str)
02766 {
02767 long pos = reg_match_pos(re, &str, 0);
02768 if (pos < 0) return Qnil;
02769 pos = rb_str_sublen(str, pos);
02770 return LONG2FIX(pos);
02771 }
02772
02773
02774
02775
02776
02777
02778
02779
02780
02781
02782
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792
02793
02794 VALUE
02795 rb_reg_eqq(VALUE re, VALUE str)
02796 {
02797 long start;
02798
02799 str = reg_operand(str, FALSE);
02800 if (NIL_P(str)) {
02801 rb_backref_set(Qnil);
02802 return Qfalse;
02803 }
02804 start = rb_reg_search(re, str, 0, 0);
02805 if (start < 0) {
02806 return Qfalse;
02807 }
02808 return Qtrue;
02809 }
02810
02811
02812
02813
02814
02815
02816
02817
02818
02819
02820
02821
02822
02823 VALUE
02824 rb_reg_match2(VALUE re)
02825 {
02826 long start;
02827 VALUE line = rb_lastline_get();
02828
02829 if (!RB_TYPE_P(line, T_STRING)) {
02830 rb_backref_set(Qnil);
02831 return Qnil;
02832 }
02833
02834 start = rb_reg_search(re, line, 0, 0);
02835 if (start < 0) {
02836 return Qnil;
02837 }
02838 start = rb_str_sublen(line, start);
02839 return LONG2FIX(start);
02840 }
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871 static VALUE
02872 rb_reg_match_m(int argc, VALUE *argv, VALUE re)
02873 {
02874 VALUE result, str, initpos;
02875 long pos;
02876
02877 if (rb_scan_args(argc, argv, "11", &str, &initpos) == 2) {
02878 pos = NUM2LONG(initpos);
02879 }
02880 else {
02881 pos = 0;
02882 }
02883
02884 pos = reg_match_pos(re, &str, pos);
02885 if (pos < 0) {
02886 rb_backref_set(Qnil);
02887 return Qnil;
02888 }
02889 result = rb_backref_get();
02890 rb_match_busy(result);
02891 if (!NIL_P(result) && rb_block_given_p()) {
02892 return rb_yield(result);
02893 }
02894 return result;
02895 }
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905
02906
02907
02908
02909
02910
02911
02912
02913
02914
02915
02916
02917
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929 static VALUE
02930 rb_reg_initialize_m(int argc, VALUE *argv, VALUE self)
02931 {
02932 onig_errmsg_buffer err = "";
02933 int flags = 0;
02934 VALUE str;
02935 rb_encoding *enc;
02936 const char *ptr;
02937 long len;
02938
02939 rb_check_arity(argc, 1, 3);
02940 if (RB_TYPE_P(argv[0], T_REGEXP)) {
02941 VALUE re = argv[0];
02942
02943 if (argc > 1) {
02944 rb_warn("flags ignored");
02945 }
02946 rb_reg_check(re);
02947 flags = rb_reg_options(re);
02948 ptr = RREGEXP_SRC_PTR(re);
02949 len = RREGEXP_SRC_LEN(re);
02950 enc = rb_enc_get(re);
02951 if (rb_reg_initialize(self, ptr, len, enc, flags, err, NULL, 0)) {
02952 str = rb_enc_str_new(ptr, len, enc);
02953 rb_reg_raise_str(str, flags, err);
02954 }
02955 }
02956 else {
02957 if (argc >= 2) {
02958 if (FIXNUM_P(argv[1])) flags = FIX2INT(argv[1]);
02959 else if (RTEST(argv[1])) flags = ONIG_OPTION_IGNORECASE;
02960 }
02961 enc = 0;
02962 if (argc == 3 && !NIL_P(argv[2])) {
02963 char *kcode = StringValuePtr(argv[2]);
02964 if (kcode[0] == 'n' || kcode[0] == 'N') {
02965 enc = rb_ascii8bit_encoding();
02966 flags |= ARG_ENCODING_NONE;
02967 }
02968 else {
02969 rb_warn("encoding option is ignored - %s", kcode);
02970 }
02971 }
02972 str = argv[0];
02973 ptr = StringValuePtr(str);
02974 if (enc
02975 ? rb_reg_initialize(self, ptr, RSTRING_LEN(str), enc, flags, err, NULL, 0)
02976 : rb_reg_initialize_str(self, str, flags, err, NULL, 0)) {
02977 rb_reg_raise_str(str, flags, err);
02978 }
02979 }
02980 return self;
02981 }
02982
02983 VALUE
02984 rb_reg_quote(VALUE str)
02985 {
02986 rb_encoding *enc = rb_enc_get(str);
02987 char *s, *send, *t;
02988 VALUE tmp;
02989 int c, clen;
02990 int ascii_only = rb_enc_str_asciionly_p(str);
02991
02992 s = RSTRING_PTR(str);
02993 send = s + RSTRING_LEN(str);
02994 while (s < send) {
02995 c = rb_enc_ascget(s, send, &clen, enc);
02996 if (c == -1) {
02997 s += mbclen(s, send, enc);
02998 continue;
02999 }
03000 switch (c) {
03001 case '[': case ']': case '{': case '}':
03002 case '(': case ')': case '|': case '-':
03003 case '*': case '.': case '\\':
03004 case '?': case '+': case '^': case '$':
03005 case ' ': case '#':
03006 case '\t': case '\f': case '\v': case '\n': case '\r':
03007 goto meta_found;
03008 }
03009 s += clen;
03010 }
03011 tmp = rb_str_new3(str);
03012 if (ascii_only) {
03013 rb_enc_associate(tmp, rb_usascii_encoding());
03014 }
03015 return tmp;
03016
03017 meta_found:
03018 tmp = rb_str_new(0, RSTRING_LEN(str)*2);
03019 if (ascii_only) {
03020 rb_enc_associate(tmp, rb_usascii_encoding());
03021 }
03022 else {
03023 rb_enc_copy(tmp, str);
03024 }
03025 t = RSTRING_PTR(tmp);
03026
03027 memcpy(t, RSTRING_PTR(str), s - RSTRING_PTR(str));
03028 t += s - RSTRING_PTR(str);
03029
03030 while (s < send) {
03031 c = rb_enc_ascget(s, send, &clen, enc);
03032 if (c == -1) {
03033 int n = mbclen(s, send, enc);
03034
03035 while (n--)
03036 *t++ = *s++;
03037 continue;
03038 }
03039 s += clen;
03040 switch (c) {
03041 case '[': case ']': case '{': case '}':
03042 case '(': case ')': case '|': case '-':
03043 case '*': case '.': case '\\':
03044 case '?': case '+': case '^': case '$':
03045 case '#':
03046 t += rb_enc_mbcput('\\', t, enc);
03047 break;
03048 case ' ':
03049 t += rb_enc_mbcput('\\', t, enc);
03050 t += rb_enc_mbcput(' ', t, enc);
03051 continue;
03052 case '\t':
03053 t += rb_enc_mbcput('\\', t, enc);
03054 t += rb_enc_mbcput('t', t, enc);
03055 continue;
03056 case '\n':
03057 t += rb_enc_mbcput('\\', t, enc);
03058 t += rb_enc_mbcput('n', t, enc);
03059 continue;
03060 case '\r':
03061 t += rb_enc_mbcput('\\', t, enc);
03062 t += rb_enc_mbcput('r', t, enc);
03063 continue;
03064 case '\f':
03065 t += rb_enc_mbcput('\\', t, enc);
03066 t += rb_enc_mbcput('f', t, enc);
03067 continue;
03068 case '\v':
03069 t += rb_enc_mbcput('\\', t, enc);
03070 t += rb_enc_mbcput('v', t, enc);
03071 continue;
03072 }
03073 t += rb_enc_mbcput(c, t, enc);
03074 }
03075 rb_str_resize(tmp, t - RSTRING_PTR(tmp));
03076 OBJ_INFECT(tmp, str);
03077 return tmp;
03078 }
03079
03080
03081
03082
03083
03084
03085
03086
03087
03088
03089
03090
03091
03092
03093
03094
03095 static VALUE
03096 rb_reg_s_quote(VALUE c, VALUE str)
03097 {
03098 return rb_reg_quote(reg_operand(str, TRUE));
03099 }
03100
03101 int
03102 rb_reg_options(VALUE re)
03103 {
03104 int options;
03105
03106 rb_reg_check(re);
03107 options = RREGEXP(re)->ptr->options & ARG_REG_OPTION_MASK;
03108 if (RBASIC(re)->flags & KCODE_FIXED) options |= ARG_ENCODING_FIXED;
03109 if (RBASIC(re)->flags & REG_ENCODING_NONE) options |= ARG_ENCODING_NONE;
03110 return options;
03111 }
03112
03113 VALUE
03114 rb_check_regexp_type(VALUE re)
03115 {
03116 return rb_check_convert_type(re, T_REGEXP, "Regexp", "to_regexp");
03117 }
03118
03119
03120
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130
03131
03132
03133
03134
03135
03136 static VALUE
03137 rb_reg_s_try_convert(VALUE dummy, VALUE re)
03138 {
03139 return rb_check_regexp_type(re);
03140 }
03141
03142 static VALUE
03143 rb_reg_s_union(VALUE self, VALUE args0)
03144 {
03145 long argc = RARRAY_LEN(args0);
03146
03147 if (argc == 0) {
03148 VALUE args[1];
03149 args[0] = rb_str_new2("(?!)");
03150 return rb_class_new_instance(1, args, rb_cRegexp);
03151 }
03152 else if (argc == 1) {
03153 VALUE arg = rb_ary_entry(args0, 0);
03154 VALUE re = rb_check_regexp_type(arg);
03155 if (!NIL_P(re))
03156 return re;
03157 else {
03158 VALUE quoted;
03159 quoted = rb_reg_s_quote(Qnil, arg);
03160 return rb_reg_new_str(quoted, 0);
03161 }
03162 }
03163 else {
03164 int i;
03165 VALUE source = rb_str_buf_new(0);
03166 rb_encoding *result_enc;
03167
03168 int has_asciionly = 0;
03169 rb_encoding *has_ascii_compat_fixed = 0;
03170 rb_encoding *has_ascii_incompat = 0;
03171
03172 for (i = 0; i < argc; i++) {
03173 volatile VALUE v;
03174 VALUE e = rb_ary_entry(args0, i);
03175
03176 if (0 < i)
03177 rb_str_buf_cat_ascii(source, "|");
03178
03179 v = rb_check_regexp_type(e);
03180 if (!NIL_P(v)) {
03181 rb_encoding *enc = rb_enc_get(v);
03182 if (!rb_enc_asciicompat(enc)) {
03183 if (!has_ascii_incompat)
03184 has_ascii_incompat = enc;
03185 else if (has_ascii_incompat != enc)
03186 rb_raise(rb_eArgError, "incompatible encodings: %s and %s",
03187 rb_enc_name(has_ascii_incompat), rb_enc_name(enc));
03188 }
03189 else if (rb_reg_fixed_encoding_p(v)) {
03190 if (!has_ascii_compat_fixed)
03191 has_ascii_compat_fixed = enc;
03192 else if (has_ascii_compat_fixed != enc)
03193 rb_raise(rb_eArgError, "incompatible encodings: %s and %s",
03194 rb_enc_name(has_ascii_compat_fixed), rb_enc_name(enc));
03195 }
03196 else {
03197 has_asciionly = 1;
03198 }
03199 v = rb_reg_to_s(v);
03200 }
03201 else {
03202 rb_encoding *enc;
03203 StringValue(e);
03204 enc = rb_enc_get(e);
03205 if (!rb_enc_str_asciicompat_p(e)) {
03206 if (!has_ascii_incompat)
03207 has_ascii_incompat = enc;
03208 else if (has_ascii_incompat != enc)
03209 rb_raise(rb_eArgError, "incompatible encodings: %s and %s",
03210 rb_enc_name(has_ascii_incompat), rb_enc_name(enc));
03211 }
03212 else if (rb_enc_str_asciionly_p(e)) {
03213 has_asciionly = 1;
03214 }
03215 else {
03216 if (!has_ascii_compat_fixed)
03217 has_ascii_compat_fixed = enc;
03218 else if (has_ascii_compat_fixed != enc)
03219 rb_raise(rb_eArgError, "incompatible encodings: %s and %s",
03220 rb_enc_name(has_ascii_compat_fixed), rb_enc_name(enc));
03221 }
03222 v = rb_reg_s_quote(Qnil, e);
03223 }
03224 if (has_ascii_incompat) {
03225 if (has_asciionly) {
03226 rb_raise(rb_eArgError, "ASCII incompatible encoding: %s",
03227 rb_enc_name(has_ascii_incompat));
03228 }
03229 if (has_ascii_compat_fixed) {
03230 rb_raise(rb_eArgError, "incompatible encodings: %s and %s",
03231 rb_enc_name(has_ascii_incompat), rb_enc_name(has_ascii_compat_fixed));
03232 }
03233 }
03234
03235 if (i == 0) {
03236 rb_enc_copy(source, v);
03237 }
03238 rb_str_append(source, v);
03239 }
03240
03241 if (has_ascii_incompat) {
03242 result_enc = has_ascii_incompat;
03243 }
03244 else if (has_ascii_compat_fixed) {
03245 result_enc = has_ascii_compat_fixed;
03246 }
03247 else {
03248 result_enc = rb_ascii8bit_encoding();
03249 }
03250
03251 rb_enc_associate(source, result_enc);
03252 return rb_class_new_instance(1, &source, rb_cRegexp);
03253 }
03254 }
03255
03256
03257
03258
03259
03260
03261
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277 static VALUE
03278 rb_reg_s_union_m(VALUE self, VALUE args)
03279 {
03280 VALUE v;
03281 if (RARRAY_LEN(args) == 1 &&
03282 !NIL_P(v = rb_check_array_type(rb_ary_entry(args, 0)))) {
03283 return rb_reg_s_union(self, v);
03284 }
03285 return rb_reg_s_union(self, args);
03286 }
03287
03288
03289 static VALUE
03290 rb_reg_init_copy(VALUE copy, VALUE re)
03291 {
03292 onig_errmsg_buffer err = "";
03293 const char *s;
03294 long len;
03295
03296 if (!OBJ_INIT_COPY(copy, re)) return copy;
03297 rb_reg_check(re);
03298 s = RREGEXP_SRC_PTR(re);
03299 len = RREGEXP_SRC_LEN(re);
03300 if (rb_reg_initialize(copy, s, len, rb_enc_get(re), rb_reg_options(re),
03301 err, NULL, 0) != 0) {
03302 rb_reg_raise(s, len, err, re);
03303 }
03304 return copy;
03305 }
03306
03307 VALUE
03308 rb_reg_regsub(VALUE str, VALUE src, struct re_registers *regs, VALUE regexp)
03309 {
03310 VALUE val = 0;
03311 char *p, *s, *e;
03312 int no, clen;
03313 rb_encoding *str_enc = rb_enc_get(str);
03314 rb_encoding *src_enc = rb_enc_get(src);
03315 int acompat = rb_enc_asciicompat(str_enc);
03316 #define ASCGET(s,e,cl) (acompat ? (*(cl)=1,ISASCII((s)[0])?(s)[0]:-1) : rb_enc_ascget((s), (e), (cl), str_enc))
03317
03318 p = s = RSTRING_PTR(str);
03319 e = s + RSTRING_LEN(str);
03320
03321 while (s < e) {
03322 int c = ASCGET(s, e, &clen);
03323 char *ss;
03324
03325 if (c == -1) {
03326 s += mbclen(s, e, str_enc);
03327 continue;
03328 }
03329 ss = s;
03330 s += clen;
03331
03332 if (c != '\\' || s == e) continue;
03333
03334 if (!val) {
03335 val = rb_str_buf_new(ss-p);
03336 }
03337 rb_enc_str_buf_cat(val, p, ss-p, str_enc);
03338
03339 c = ASCGET(s, e, &clen);
03340 if (c == -1) {
03341 s += mbclen(s, e, str_enc);
03342 rb_enc_str_buf_cat(val, ss, s-ss, str_enc);
03343 p = s;
03344 continue;
03345 }
03346 s += clen;
03347
03348 p = s;
03349 switch (c) {
03350 case '1': case '2': case '3': case '4':
03351 case '5': case '6': case '7': case '8': case '9':
03352 if (onig_noname_group_capture_is_active(RREGEXP(regexp)->ptr)) {
03353 no = c - '0';
03354 }
03355 else {
03356 continue;
03357 }
03358 break;
03359
03360 case 'k':
03361 if (s < e && ASCGET(s, e, &clen) == '<') {
03362 char *name, *name_end;
03363
03364 name_end = name = s + clen;
03365 while (name_end < e) {
03366 c = ASCGET(name_end, e, &clen);
03367 if (c == '>') break;
03368 name_end += c == -1 ? mbclen(name_end, e, str_enc) : clen;
03369 }
03370 if (name_end < e) {
03371 VALUE n = rb_str_subseq(str, (long)(name - RSTRING_PTR(str)),
03372 (long)(name_end - name));
03373 if (!rb_enc_compatible(RREGEXP(regexp)->src, n) ||
03374 (no = name_to_backref_number(regs, regexp, name, name_end)) < 1) {
03375 name_to_backref_error(n);
03376 }
03377 p = s = name_end + clen;
03378 break;
03379 }
03380 else {
03381 rb_raise(rb_eRuntimeError, "invalid group name reference format");
03382 }
03383 }
03384
03385 rb_enc_str_buf_cat(val, ss, s-ss, str_enc);
03386 continue;
03387
03388 case '0':
03389 case '&':
03390 no = 0;
03391 break;
03392
03393 case '`':
03394 rb_enc_str_buf_cat(val, RSTRING_PTR(src), BEG(0), src_enc);
03395 continue;
03396
03397 case '\'':
03398 rb_enc_str_buf_cat(val, RSTRING_PTR(src)+END(0), RSTRING_LEN(src)-END(0), src_enc);
03399 continue;
03400
03401 case '+':
03402 no = regs->num_regs-1;
03403 while (BEG(no) == -1 && no > 0) no--;
03404 if (no == 0) continue;
03405 break;
03406
03407 case '\\':
03408 rb_enc_str_buf_cat(val, s-clen, clen, str_enc);
03409 continue;
03410
03411 default:
03412 rb_enc_str_buf_cat(val, ss, s-ss, str_enc);
03413 continue;
03414 }
03415
03416 if (no >= 0) {
03417 if (no >= regs->num_regs) continue;
03418 if (BEG(no) == -1) continue;
03419 rb_enc_str_buf_cat(val, RSTRING_PTR(src)+BEG(no), END(no)-BEG(no), src_enc);
03420 }
03421 }
03422
03423 if (!val) return str;
03424 if (p < e) {
03425 rb_enc_str_buf_cat(val, p, e-p, str_enc);
03426 }
03427
03428 return val;
03429 }
03430
03431 static VALUE
03432 kcode_getter(void)
03433 {
03434 rb_warn("variable $KCODE is no longer effective");
03435 return Qnil;
03436 }
03437
03438 static void
03439 kcode_setter(VALUE val, ID id)
03440 {
03441 rb_warn("variable $KCODE is no longer effective; ignored");
03442 }
03443
03444 static VALUE
03445 ignorecase_getter(void)
03446 {
03447 rb_warn("variable $= is no longer effective");
03448 return Qfalse;
03449 }
03450
03451 static void
03452 ignorecase_setter(VALUE val, ID id)
03453 {
03454 rb_warn("variable $= is no longer effective; ignored");
03455 }
03456
03457 static VALUE
03458 match_getter(void)
03459 {
03460 VALUE match = rb_backref_get();
03461
03462 if (NIL_P(match)) return Qnil;
03463 rb_match_busy(match);
03464 return match;
03465 }
03466
03467 static void
03468 match_setter(VALUE val)
03469 {
03470 if (!NIL_P(val)) {
03471 Check_Type(val, T_MATCH);
03472 }
03473 rb_backref_set(val);
03474 }
03475
03476
03477
03478
03479
03480
03481
03482
03483
03484
03485
03486
03487
03488
03489
03490
03491
03492
03493
03494
03495
03496
03497
03498
03499
03500
03501
03502
03503
03504 static VALUE
03505 rb_reg_s_last_match(int argc, VALUE *argv)
03506 {
03507 VALUE nth;
03508
03509 if (argc > 0 && rb_scan_args(argc, argv, "01", &nth) == 1) {
03510 VALUE match = rb_backref_get();
03511 int n;
03512 if (NIL_P(match)) return Qnil;
03513 n = match_backref_number(match, nth);
03514 return rb_reg_nth_match(n, match);
03515 }
03516 return match_getter();
03517 }
03518
03519 static void
03520 re_warn(const char *s)
03521 {
03522 rb_warn("%s", s);
03523 }
03524
03525
03526
03527
03528
03529
03530
03531
03532
03533
03534
03535
03536
03537
03538
03539
03540
03541
03542
03543
03544
03545
03546
03547
03548 void
03549 Init_Regexp(void)
03550 {
03551 rb_eRegexpError = rb_define_class("RegexpError", rb_eStandardError);
03552
03553 onigenc_set_default_caseconv_table((UChar*)casetable);
03554 onigenc_set_default_encoding(ONIG_ENCODING_ASCII);
03555 onig_set_warn_func(re_warn);
03556 onig_set_verb_warn_func(re_warn);
03557
03558 rb_define_virtual_variable("$~", match_getter, match_setter);
03559 rb_define_virtual_variable("$&", last_match_getter, 0);
03560 rb_define_virtual_variable("$`", prematch_getter, 0);
03561 rb_define_virtual_variable("$'", postmatch_getter, 0);
03562 rb_define_virtual_variable("$+", last_paren_match_getter, 0);
03563
03564 rb_define_virtual_variable("$=", ignorecase_getter, ignorecase_setter);
03565 rb_define_virtual_variable("$KCODE", kcode_getter, kcode_setter);
03566 rb_define_virtual_variable("$-K", kcode_getter, kcode_setter);
03567
03568 rb_cRegexp = rb_define_class("Regexp", rb_cObject);
03569 rb_define_alloc_func(rb_cRegexp, rb_reg_s_alloc);
03570 rb_define_singleton_method(rb_cRegexp, "compile", rb_class_new_instance, -1);
03571 rb_define_singleton_method(rb_cRegexp, "quote", rb_reg_s_quote, 1);
03572 rb_define_singleton_method(rb_cRegexp, "escape", rb_reg_s_quote, 1);
03573 rb_define_singleton_method(rb_cRegexp, "union", rb_reg_s_union_m, -2);
03574 rb_define_singleton_method(rb_cRegexp, "last_match", rb_reg_s_last_match, -1);
03575 rb_define_singleton_method(rb_cRegexp, "try_convert", rb_reg_s_try_convert, 1);
03576
03577 rb_define_method(rb_cRegexp, "initialize", rb_reg_initialize_m, -1);
03578 rb_define_method(rb_cRegexp, "initialize_copy", rb_reg_init_copy, 1);
03579 rb_define_method(rb_cRegexp, "hash", rb_reg_hash, 0);
03580 rb_define_method(rb_cRegexp, "eql?", rb_reg_equal, 1);
03581 rb_define_method(rb_cRegexp, "==", rb_reg_equal, 1);
03582 rb_define_method(rb_cRegexp, "=~", rb_reg_match, 1);
03583 rb_define_method(rb_cRegexp, "===", rb_reg_eqq, 1);
03584 rb_define_method(rb_cRegexp, "~", rb_reg_match2, 0);
03585 rb_define_method(rb_cRegexp, "match", rb_reg_match_m, -1);
03586 rb_define_method(rb_cRegexp, "to_s", rb_reg_to_s, 0);
03587 rb_define_method(rb_cRegexp, "inspect", rb_reg_inspect, 0);
03588 rb_define_method(rb_cRegexp, "source", rb_reg_source, 0);
03589 rb_define_method(rb_cRegexp, "casefold?", rb_reg_casefold_p, 0);
03590 rb_define_method(rb_cRegexp, "options", rb_reg_options_m, 0);
03591 rb_define_method(rb_cRegexp, "encoding", rb_obj_encoding, 0);
03592 rb_define_method(rb_cRegexp, "fixed_encoding?", rb_reg_fixed_encoding_p, 0);
03593 rb_define_method(rb_cRegexp, "names", rb_reg_names, 0);
03594 rb_define_method(rb_cRegexp, "named_captures", rb_reg_named_captures, 0);
03595
03596
03597 rb_define_const(rb_cRegexp, "IGNORECASE", INT2FIX(ONIG_OPTION_IGNORECASE));
03598
03599 rb_define_const(rb_cRegexp, "EXTENDED", INT2FIX(ONIG_OPTION_EXTEND));
03600
03601 rb_define_const(rb_cRegexp, "MULTILINE", INT2FIX(ONIG_OPTION_MULTILINE));
03602
03603 rb_define_const(rb_cRegexp, "FIXEDENCODING", INT2FIX(ARG_ENCODING_FIXED));
03604
03605 rb_define_const(rb_cRegexp, "NOENCODING", INT2FIX(ARG_ENCODING_NONE));
03606
03607 rb_global_variable(®_cache);
03608
03609 rb_cMatch = rb_define_class("MatchData", rb_cObject);
03610 rb_define_alloc_func(rb_cMatch, match_alloc);
03611 rb_undef_method(CLASS_OF(rb_cMatch), "new");
03612
03613 rb_define_method(rb_cMatch, "initialize_copy", match_init_copy, 1);
03614 rb_define_method(rb_cMatch, "regexp", match_regexp, 0);
03615 rb_define_method(rb_cMatch, "names", match_names, 0);
03616 rb_define_method(rb_cMatch, "size", match_size, 0);
03617 rb_define_method(rb_cMatch, "length", match_size, 0);
03618 rb_define_method(rb_cMatch, "offset", match_offset, 1);
03619 rb_define_method(rb_cMatch, "begin", match_begin, 1);
03620 rb_define_method(rb_cMatch, "end", match_end, 1);
03621 rb_define_method(rb_cMatch, "to_a", match_to_a, 0);
03622 rb_define_method(rb_cMatch, "[]", match_aref, -1);
03623 rb_define_method(rb_cMatch, "captures", match_captures, 0);
03624 rb_define_method(rb_cMatch, "values_at", match_values_at, -1);
03625 rb_define_method(rb_cMatch, "pre_match", rb_reg_match_pre, 0);
03626 rb_define_method(rb_cMatch, "post_match", rb_reg_match_post, 0);
03627 rb_define_method(rb_cMatch, "to_s", match_to_s, 0);
03628 rb_define_method(rb_cMatch, "inspect", match_inspect, 0);
03629 rb_define_method(rb_cMatch, "string", match_string, 0);
03630 rb_define_method(rb_cMatch, "hash", match_hash, 0);
03631 rb_define_method(rb_cMatch, "eql?", match_equal, 1);
03632 rb_define_method(rb_cMatch, "==", match_equal, 1);
03633 }
03634