re.c

Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   re.c -
00004 
00005   $Author: nagachika $
00006   created at: Mon Aug  9 18:24:49 JST 1993
00007 
00008   Copyright (C) 1993-2007 Yukihiro Matsumoto
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   /* it's ascii */
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         /* '0'     '1'     '2'     '3'     '4'     '5'     '6'     '7' */
00039         '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
00040         /* '8'     '9'     ':'     ';'     '<'     '='     '>'     '?' */
00041         '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
00042         /* '@'     'A'     'B'     'C'     'D'     'E'     'F'     'G' */
00043         '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
00044         /* 'H'     'I'     'J'     'K'     'L'     'M'     'N'     'O' */
00045         '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
00046         /* 'P'     'Q'     'R'     'S'     'T'     'U'     'V'     'W' */
00047         '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
00048         /* 'X'     'Y'     'Z'     '['     '\'     ']'     '^'     '_' */
00049         '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
00050         /* '`'     'a'     'b'     'c'     'd'     'e'     'f'     'g' */
00051         '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
00052         /* 'h'     'i'     'j'     'k'     'l'     'm'     'n'     'o' */
00053         '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
00054         /* 'p'     'q'     'r'     's'     't'     'u'     'v'     'w' */
00055         '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
00056         /* 'x'     'y'     'z'     '{'     '|'     '}'     '~' */
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     /* Prepare hash value */
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     /* Searching */
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     /* Preprocessing */
00160     for (i = 0; i < 256; ++i)
00161         qstable[i] = m + 1;
00162     for (; x < xe; ++x)
00163         qstable[*x] = xe - x;
00164     /* Searching */
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     /* Preprocessing */
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     /* Searching */
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  *  call-seq:
00455  *      rxp.source   -> str
00456  *
00457  *  Returns the original string of the pattern.
00458  *
00459  *      /ab+c/ix.source #=> "ab+c"
00460  *
00461  *  Note that escape sequences are retained as is.
00462  *
00463  *     /\x20\+/.source  #=> "\\x20\\+"
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  * call-seq:
00480  *    rxp.inspect   -> string
00481  *
00482  * Produce a nicely formatted string-version of _rxp_. Perhaps surprisingly,
00483  * <code>#inspect</code> actually produces the more natural version of
00484  * the string than <code>#to_s</code>.
00485  *
00486  *      /ab+c/ix.inspect        #=> "/ab+c/ix"
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  *  call-seq:
00502  *     rxp.to_s   -> str
00503  *
00504  *  Returns a string containing the regular expression and its options (using the
00505  *  <code>(?opts:source)</code> notation. This string can be fed back in to
00506  *  <code>Regexp::new</code> to a regular expression with the same semantics as
00507  *  the original. (However, <code>Regexp#==</code> may not return true when
00508  *  comparing the two, as the source of the regular expression itself may
00509  *  differ, as the example shows).  <code>Regexp#inspect</code> produces a
00510  *  generally more readable version of <i>rxp</i>.
00511  *
00512  *      r1 = /ab+c/ix           #=> /ab+c/ix
00513  *      s1 = r1.to_s            #=> "(?ix-m:ab+c)"
00514  *      r2 = Regexp.new(s1)     #=> /(?ix-m:ab+c)/
00515  *      r1 == r2                #=> false
00516  *      r1.source               #=> "ab+c"
00517  *      r2.source               #=> "(?ix-m:ab+c)"
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         /* backup encoded ")" to paren */
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  *  call-seq:
00677  *     rxp.casefold?   -> true or false
00678  *
00679  *  Returns the value of the case-insensitive flag.
00680  *
00681  *      /a/.casefold?           #=> false
00682  *      /a/i.casefold?          #=> true
00683  *      /(?i:a)/.casefold?      #=> false
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  *  call-seq:
00697  *     rxp.options   -> fixnum
00698  *
00699  *  Returns the set of bits corresponding to the options used when creating this
00700  *  Regexp (see <code>Regexp::new</code> for details. Note that additional bits
00701  *  may be set in the returned options: these are used internally by the regular
00702  *  expression code. These extra bits are ignored if the options are passed to
00703  *  <code>Regexp::new</code>.
00704  *
00705  *     Regexp::IGNORECASE                  #=> 1
00706  *     Regexp::EXTENDED                    #=> 2
00707  *     Regexp::MULTILINE                   #=> 4
00708  *
00709  *     /cat/.options                       #=> 0
00710  *     /cat/ix.options                     #=> 3
00711  *     Regexp.new('cat', true).options     #=> 1
00712  *     /\xa1\xa2/e.options                 #=> 16
00713  *
00714  *     r = /cat/ix
00715  *     Regexp.new(r.source, r.options)     #=> /cat/ix
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  * call-seq:
00736  *    rxp.names   -> [name1, name2, ...]
00737  *
00738  * Returns a list of names of captures as an array of strings.
00739  *
00740  *     /(?<foo>.)(?<bar>.)(?<baz>.)/.names
00741  *     #=> ["foo", "bar", "baz"]
00742  *
00743  *     /(?<foo>.)(?<foo>.)/.names
00744  *     #=> ["foo"]
00745  *
00746  *     /(.)(.)/.names
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  * call-seq:
00777  *    rxp.named_captures  -> hash
00778  *
00779  * Returns a hash representing information about named captures of <i>rxp</i>.
00780  *
00781  * A key of the hash is a name of the named captures.
00782  * A value of the hash is an array which is list of indexes of corresponding
00783  * named captures.
00784  *
00785  *    /(?<foo>.)(?<bar>.)/.named_captures
00786  *    #=> {"foo"=>[1], "bar"=>[2]}
00787  *
00788  *    /(?<foo>.)(?<foo>.)/.named_captures
00789  *    #=> {"foo"=>[1, 2]}
00790  *
00791  * If there are no named captures, an empty hash is returned.
00792  *
00793  *    /(.)(.)/.named_captures
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     /* Handle escaped characters first. */
00837 
00838     /* Build a copy of the string (in dest) with the
00839        escaped characters translated,  and generate the regex
00840        from that.
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  *  Document-class: MatchData
00855  *
00856  *  <code>MatchData</code> is the type of the special variable <code>$~</code>,
00857  *  and is the type of the object returned by <code>Regexp#match</code> and
00858  *  <code>Regexp.last_match</code>. It encapsulates all the results of a pattern
00859  *  match, results normally accessed through the special variables
00860  *  <code>$&</code>, <code>$'</code>, <code>$`</code>, <code>$1</code>,
00861  *  <code>$2</code>, and so on.
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 /* :nodoc: */
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  * call-seq:
01009  *    mtch.regexp   -> regexp
01010  *
01011  * Returns the regexp.
01012  *
01013  *     m = /a.*b/.match("abc")
01014  *     m.regexp #=> /a.*b/
01015  */
01016 
01017 static VALUE
01018 match_regexp(VALUE match)
01019 {
01020     match_check(match);
01021     return RMATCH(match)->regexp;
01022 }
01023 
01024 /*
01025  * call-seq:
01026  *    mtch.names   -> [name1, name2, ...]
01027  *
01028  * Returns a list of names of captures as an array of strings.
01029  * It is same as mtch.regexp.names.
01030  *
01031  *     /(?<foo>.)(?<bar>.)(?<baz>.)/.match("hoge").names
01032  *     #=> ["foo", "bar", "baz"]
01033  *
01034  *     m = /(?<x>.)(?<y>.)?/.match("a") #=> #<MatchData "a" x:"a" y:nil>
01035  *     m.names                          #=> ["x", "y"]
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  *  call-seq:
01047  *     mtch.length   -> integer
01048  *     mtch.size     -> integer
01049  *
01050  *  Returns the number of elements in the match array.
01051  *
01052  *     m = /(.)(.)(\d+)(\d)/.match("THX1138.")
01053  *     m.length   #=> 5
01054  *     m.size     #=> 5
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  *  call-seq:
01107  *     mtch.offset(n)   -> array
01108  *
01109  *  Returns a two-element array containing the beginning and ending offsets of
01110  *  the <em>n</em>th match.
01111  *  <em>n</em> can be a string or symbol to reference a named capture.
01112  *
01113  *     m = /(.)(.)(\d+)(\d)/.match("THX1138.")
01114  *     m.offset(0)      #=> [1, 7]
01115  *     m.offset(4)      #=> [6, 7]
01116  *
01117  *     m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
01118  *     p m.offset(:foo) #=> [0, 1]
01119  *     p m.offset(:bar) #=> [2, 3]
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  *  call-seq:
01144  *     mtch.begin(n)   -> integer
01145  *
01146  *  Returns the offset of the start of the <em>n</em>th element of the match
01147  *  array in the string.
01148  *  <em>n</em> can be a string or symbol to reference a named capture.
01149  *
01150  *     m = /(.)(.)(\d+)(\d)/.match("THX1138.")
01151  *     m.begin(0)       #=> 1
01152  *     m.begin(2)       #=> 2
01153  *
01154  *     m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
01155  *     p m.begin(:foo)  #=> 0
01156  *     p m.begin(:bar)  #=> 2
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  *  call-seq:
01179  *     mtch.end(n)   -> integer
01180  *
01181  *  Returns the offset of the character immediately following the end of the
01182  *  <em>n</em>th element of the match array in the string.
01183  *  <em>n</em> can be a string or symbol to reference a named capture.
01184  *
01185  *     m = /(.)(.)(\d+)(\d)/.match("THX1138.")
01186  *     m.end(0)         #=> 7
01187  *     m.end(2)         #=> 3
01188  *
01189  *     m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
01190  *     p m.end(:foo)    #=> 1
01191  *     p m.end(:bar)    #=> 3
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  *  call-seq:
01221  *     rxp.fixed_encoding?   -> true or false
01222  *
01223  *  Returns false if rxp is applicable to
01224  *  a string with any ASCII compatible encoding.
01225  *  Returns true otherwise.
01226  *
01227  *      r = /a/
01228  *      r.fixed_encoding?                               #=> false
01229  *      r =~ "\u{6666} a"                               #=> 2
01230  *      r =~ "\xa1\xa2 a".force_encoding("euc-jp")      #=> 2
01231  *      r =~ "abc".force_encoding("euc-jp")             #=> 0
01232  *
01233  *      r = /a/u
01234  *      r.fixed_encoding?                               #=> true
01235  *      r.encoding                                      #=> #<Encoding:UTF-8>
01236  *      r =~ "\u{6666} a"                               #=> 2
01237  *      r =~ "\xa1\xa2".force_encoding("euc-jp")        #=> ArgumentError
01238  *      r =~ "abc".force_encoding("euc-jp")             #=> 0
01239  *
01240  *      r = /\u{6666}/
01241  *      r.fixed_encoding?                               #=> true
01242  *      r.encoding                                      #=> #<Encoding:UTF-8>
01243  *      r =~ "\u{6666} a"                               #=> 0
01244  *      r =~ "\xa1\xa2".force_encoding("euc-jp")        #=> ArgumentError
01245  *      r =~ "abc".force_encoding("euc-jp")             #=> nil
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(&reg, (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 /* returns byte offset */
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 = &regi;
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 == &regi)
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  *  call-seq:
01517  *     mtch.pre_match   -> str
01518  *
01519  *  Returns the portion of the original string before the current match.
01520  *  Equivalent to the special variable <code>$`</code>.
01521  *
01522  *     m = /(.)(.)(\d+)(\d)/.match("THX1138.")
01523  *     m.pre_match   #=> "T"
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  *  call-seq:
01544  *     mtch.post_match   -> str
01545  *
01546  *  Returns the portion of the original string after the current match.
01547  *  Equivalent to the special variable <code>$'</code>.
01548  *
01549  *     m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie")
01550  *     m.post_match   #=> ": The Movie"
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 /* [MG]:FIXME: I put parens around the /.../.match() in the first line of the
01641    second example to prevent the '*' followed by a '/' from ending the
01642    comment. */
01643 
01644 /*
01645  *  call-seq:
01646  *     mtch.to_a   -> anArray
01647  *
01648  *  Returns the array of matches.
01649  *
01650  *     m = /(.)(.)(\d+)(\d)/.match("THX1138.")
01651  *     m.to_a   #=> ["HX1138", "H", "X", "113", "8"]
01652  *
01653  *  Because <code>to_a</code> is called when expanding
01654  *  <code>*</code><em>variable</em>, there's a useful assignment
01655  *  shortcut for extracting matched fields. This is slightly slower than
01656  *  accessing the fields directly (as an intermediate array is
01657  *  generated).
01658  *
01659  *     all,f1,f2,f3 = *(/(.)(.)(\d+)(\d)/.match("THX1138."))
01660  *     all   #=> "HX1138"
01661  *     f1    #=> "H"
01662  *     f2    #=> "X"
01663  *     f3    #=> "113"
01664  */
01665 
01666 static VALUE
01667 match_to_a(VALUE match)
01668 {
01669     return match_array(match, 0);
01670 }
01671 
01672 
01673 /*
01674  *  call-seq:
01675  *     mtch.captures   -> array
01676  *
01677  *  Returns the array of captures; equivalent to <code>mtch.to_a[1..-1]</code>.
01678  *
01679  *     f1,f2,f3,f4 = /(.)(.)(\d+)(\d)/.match("THX1138.").captures
01680  *     f1    #=> "H"
01681  *     f2    #=> "X"
01682  *     f3    #=> "113"
01683  *     f4    #=> "8"
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  *  call-seq:
01708  *     mtch[i]               -> str or nil
01709  *     mtch[start, length]   -> array
01710  *     mtch[range]           -> array
01711  *     mtch[name]            -> str or nil
01712  *
01713  *  Match Reference -- <code>MatchData</code> acts as an array, and may be
01714  *  accessed using the normal array indexing techniques.  <code>mtch[0]</code>
01715  *  is equivalent to the special variable <code>$&</code>, and returns the
01716  *  entire matched string.  <code>mtch[1]</code>, <code>mtch[2]</code>, and so
01717  *  on return the values of the matched backreferences (portions of the
01718  *  pattern between parentheses).
01719  *
01720  *     m = /(.)(.)(\d+)(\d)/.match("THX1138.")
01721  *     m          #=> #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8">
01722  *     m[0]       #=> "HX1138"
01723  *     m[1, 2]    #=> ["H", "X"]
01724  *     m[1..3]    #=> ["H", "X", "113"]
01725  *     m[-3, 2]   #=> ["X", "113"]
01726  *
01727  *     m = /(?<foo>a+)b/.match("ccaaab")
01728  *     m          #=> #<MatchData "aaab" foo:"aaa">
01729  *     m["foo"]   #=> "aaa"
01730  *     m[:foo]    #=> "aaa"
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                 /* fall through */
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     /* n should not exceed num_regs */
01777     return rb_reg_nth_match((int)n, match);
01778 }
01779 
01780 
01781 /*
01782  *  call-seq:
01783  *
01784  *     mtch.values_at([index]*)   -> array
01785  *
01786  *  Uses each <i>index</i> to access the matching values, returning an array of
01787  *  the corresponding matches.
01788  *
01789  *     m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie")
01790  *     m.to_a               #=> ["HX1138", "H", "X", "113", "8"]
01791  *     m.values_at(0, 2, -2)   #=> ["HX1138", "X", "113"]
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  *  call-seq:
01807  *     mtch.to_s   -> str
01808  *
01809  *  Returns the entire matched string.
01810  *
01811  *     m = /(.)(.)(\d+)(\d)/.match("THX1138.")
01812  *     m.to_s   #=> "HX1138"
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  *  call-seq:
01830  *     mtch.string   -> str
01831  *
01832  *  Returns a frozen copy of the string passed in to <code>match</code>.
01833  *
01834  *     m = /(.)(.)(\d+)(\d)/.match("THX1138.")
01835  *     m.string   #=> "THX1138."
01836  */
01837 
01838 static VALUE
01839 match_string(VALUE match)
01840 {
01841     match_check(match);
01842     return RMATCH(match)->str;  /* str is frozen */
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  * call-seq:
01866  *    mtch.inspect   -> str
01867  *
01868  * Returns a printable version of <i>mtch</i>.
01869  *
01870  *     puts /.$/.match("foo").inspect
01871  *     #=> #<MatchData "o">
01872  *
01873  *     puts /(.)(.)(.)/.match("foo").inspect
01874  *     #=> #<MatchData "foo" 1:"f" 2:"o" 3:"o">
01875  *
01876  *     puts /(.)(.)?(.)/.match("fo").inspect
01877  *     #=> #<MatchData "fo" 1:"f" 2:nil 3:"o">
01878  *
01879  *     puts /(?<foo>.)(?<bar>.)(?<baz>.)/.match("hoge").inspect
01880  *     #=> #<MatchData "hog" foo:"h" bar:"o" baz:"g">
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       /* \OOO */
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': /* \xHH */
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': /* \M-X, \M-\C-X, \M-\cX */
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': /* \C-X, \C-\M-X */
01997         if (p == end || *p++ != '-') {
01998             errcpy(err, "too short control escape");
01999             return -1;
02000         }
02001       case 'c': /* \cX, \c\M-X */
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) || /* Surrogates */
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) { /* max 10FFFF */
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': /* \O, \OO, \OOO or backref */
02224                 {
02225                     size_t octlen;
02226                     if (ruby_scan_oct(p-1, end-(p-1), &octlen) <= 0177) {
02227                         /* backref or 7bit octal.
02228                            no need to unescape anyway.
02229                            re-escaping may break backref */
02230                         goto escape_asis;
02231                     }
02232                 }
02233                 /* xxx: How about more than 199 subexpressions? */
02234 
02235               case '0': /* \0, \0O, \0OO */
02236 
02237               case 'x': /* \xHH */
02238               case 'c': /* \cX, \c\M-X */
02239               case 'C': /* \C-X, \C-\M-X */
02240               case 'M': /* \M-X, \M-\C-X, \M-\cX */
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                     /* \u{H HH HHH HHHH HHHHH HHHHHH ...} */
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                     /* \uHHHH */
02264                     if (unescape_unicode_bmp(&p, end, buf, encp, err) != 0)
02265                         return -1;
02266                     break;
02267                 }
02268 
02269               case 'p': /* \p{Hiragana} */
02270               case 'P':
02271                 if (!*encp) {
02272                     *has_property = 1;
02273                 }
02274                 goto escape_asis;
02275 
02276               default: /* \n, \\, \d, \9, etc. */
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  * call-seq:
02579  *   rxp.hash   -> fixnum
02580  *
02581  * Produce a hash based on the text and options of this regular expression.
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  *  call-seq:
02605  *     rxp == other_rxp      -> true or false
02606  *     rxp.eql?(other_rxp)   -> true or false
02607  *
02608  *  Equality---Two regexps are equal if their patterns are identical, they have
02609  *  the same character set code, and their <code>casefold?</code> values are the
02610  *  same.
02611  *
02612  *     /abc/  == /abc/x   #=> false
02613  *     /abc/  == /abc/i   #=> false
02614  *     /abc/  == /abc/u   #=> false
02615  *     /abc/u == /abc/n   #=> false
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  * call-seq:
02636  *    mtch.hash   -> integer
02637  *
02638  * Produce a hash based on the target string, regexp and matched
02639  * positions of this matchdata.
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  * call-seq:
02659  *    mtch == mtch2   -> true or false
02660  *    mtch.eql?(mtch2)   -> true or false
02661  *
02662  *  Equality---Two matchdata are equal if their target strings,
02663  *  patterns, and matched positions are identical.
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  *  call-seq:
02718  *     rxp =~ str    -> integer or nil
02719  *
02720  *  Match---Matches <i>rxp</i> against <i>str</i>.
02721  *
02722  *     /at/ =~ "input data"   #=> 7
02723  *     /ax/ =~ "input data"   #=> nil
02724  *
02725  *  If <code>=~</code> is used with a regexp literal with named captures,
02726  *  captured strings (or nil) is assigned to local variables named by
02727  *  the capture names.
02728  *
02729  *     /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ "  x = y  "
02730  *     p lhs    #=> "x"
02731  *     p rhs    #=> "y"
02732  *
02733  *  If it is not matched, nil is assigned for the variables.
02734  *
02735  *     /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ "  x = "
02736  *     p lhs    #=> nil
02737  *     p rhs    #=> nil
02738  *
02739  *  This assignment is implemented in the Ruby parser.
02740  *  The parser detects 'regexp-literal =~ expression' for the assignment.
02741  *  The regexp must be a literal without interpolation and placed at left hand side.
02742  *
02743  *  The assignment does not occur if the regexp is not a literal.
02744  *
02745  *     re = /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/
02746  *     re =~ "  x = y  "
02747  *     p lhs    # undefined local variable
02748  *     p rhs    # undefined local variable
02749  *
02750  *  A regexp interpolation, <code>#{}</code>, also disables
02751  *  the assignment.
02752  *
02753  *     rhs_pat = /(?<rhs>\w+)/
02754  *     /(?<lhs>\w+)\s*=\s*#{rhs_pat}/ =~ "x = y"
02755  *     p lhs    # undefined local variable
02756  *
02757  *  The assignment does not occur if the regexp is placed at the right hand side.
02758  *
02759  *    "  x = y  " =~ /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/
02760  *    p lhs, rhs # undefined local variable
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  *  call-seq:
02775  *     rxp === str   -> true or false
02776  *
02777  *  Case Equality---Used in case statements.
02778  *
02779  *     a = "HELLO"
02780  *     case a
02781  *     when /^[a-z]*$/; print "Lower case\n"
02782  *     when /^[A-Z]*$/; print "Upper case\n"
02783  *     else;            print "Mixed case\n"
02784  *     end
02785  *     #=> "Upper case"
02786  *
02787  *  Following a regular expression literal with the #=== operator allows you to
02788  *  compare against a String.
02789  *
02790  *      /^[a-z]*$/ === "HELLO" #=> false
02791  *      /^[A-Z]*$/ === "HELLO" #=> true
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  *  call-seq:
02814  *     ~ rxp   -> integer or nil
02815  *
02816  *  Match---Matches <i>rxp</i> against the contents of <code>$_</code>.
02817  *  Equivalent to <code><i>rxp</i> =~ $_</code>.
02818  *
02819  *     $_ = "input data"
02820  *     ~ /at/   #=> 7
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  *  call-seq:
02845  *     rxp.match(str)       -> matchdata or nil
02846  *     rxp.match(str,pos)   -> matchdata or nil
02847  *
02848  *  Returns a <code>MatchData</code> object describing the match, or
02849  *  <code>nil</code> if there was no match. This is equivalent to retrieving the
02850  *  value of the special variable <code>$~</code> following a normal match.
02851  *  If the second parameter is present, it specifies the position in the string
02852  *  to begin the search.
02853  *
02854  *     /(.)(.)(.)/.match("abc")[2]   #=> "b"
02855  *     /(.)(.)/.match("abc", 1)[2]   #=> "c"
02856  *
02857  *  If a block is given, invoke the block with MatchData if match succeed, so
02858  *  that you can write
02859  *
02860  *     pat.match(str) {|m| ...}
02861  *
02862  *  instead of
02863  *
02864  *     if m = pat.match(str)
02865  *       ...
02866  *     end
02867  *
02868  *  The return value is a value from block execution in this case.
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  * Document-method: compile
02899  *
02900  * Synonym for <code>Regexp.new</code>
02901  */
02902 
02903 
02904 /*
02905  *  call-seq:
02906  *     Regexp.new(string, [options [, kcode]])        -> regexp
02907  *     Regexp.new(regexp)                            -> regexp
02908  *     Regexp.compile(string, [options [, kcode]])    -> regexp
02909  *     Regexp.compile(regexp)                        -> regexp
02910  *
02911  *  Constructs a new regular expression from +pattern+, which can be either a
02912  *  String or a Regexp (in which case that regexp's options are propagated),
02913  *  and new options may not be specified (a change as of Ruby 1.8).
02914  *
02915  *  If +options+ is a Fixnum, it should be one or more of the constants
02916  *  Regexp::EXTENDED, Regexp::IGNORECASE, and Regexp::MULTILINE,
02917  *  <em>or</em>-ed together.  Otherwise, if +options+ is not
02918  *  +nil+ or +false+, the regexp will be case insensitive.
02919  *
02920  *  When the +kcode+ parameter is `n' or `N' sets the regexp no encoding.
02921  *  It means that the regexp is for binary strings.
02922  *
02923  *    r1 = Regexp.new('^a-z+:\\s+\w+') #=> /^a-z+:\s+\w+/
02924  *    r2 = Regexp.new('cat', true)     #=> /cat/i
02925  *    r3 = Regexp.new(r2)              #=> /cat/i
02926  *    r4 = Regexp.new('dog', Regexp::EXTENDED | Regexp::IGNORECASE) #=> /dog/ix
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     /* copy upto metacharacter */
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  *  call-seq:
03083  *     Regexp.escape(str)   -> string
03084  *     Regexp.quote(str)    -> string
03085  *
03086  *  Escapes any characters that would have special meaning in a regular
03087  *  expression. Returns a new escaped string, or self if no characters are
03088  *  escaped.  For any string,
03089  *  <code>Regexp.new(Regexp.escape(<i>str</i>))=~<i>str</i></code> will be true.
03090  *
03091  *     Regexp.escape('\*?{}.')   #=> \\\*\?\{\}\.
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  *  call-seq:
03121  *     Regexp.try_convert(obj) -> re or nil
03122  *
03123  *  Try to convert <i>obj</i> into a Regexp, using to_regexp method.
03124  *  Returns converted regexp or nil if <i>obj</i> cannot be converted
03125  *  for any reason.
03126  *
03127  *     Regexp.try_convert(/re/)         #=> /re/
03128  *     Regexp.try_convert("re")         #=> nil
03129  *
03130  *     o = Object.new
03131  *     Regexp.try_convert(o)            #=> nil
03132  *     def o.to_regexp() /foo/ end
03133  *     Regexp.try_convert(o)            #=> /foo/
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  *  call-seq:
03258  *     Regexp.union(pat1, pat2, ...)            -> new_regexp
03259  *     Regexp.union(pats_ary)                   -> new_regexp
03260  *
03261  *  Return a <code>Regexp</code> object that is the union of the given
03262  *  <em>pattern</em>s, i.e., will match any of its parts. The <em>pattern</em>s
03263  *  can be Regexp objects, in which case their options will be preserved, or
03264  *  Strings. If no patterns are given, returns <code>/(?!)/</code>.
03265  *  The behavior is unspecified if any given <em>pattern</em> contains capture.
03266  *
03267  *     Regexp.union                         #=> /(?!)/
03268  *     Regexp.union("penzance")             #=> /penzance/
03269  *     Regexp.union("a+b*c")                #=> /a\+b\*c/
03270  *     Regexp.union("skiing", "sledding")   #=> /skiing|sledding/
03271  *     Regexp.union(["skiing", "sledding"]) #=> /skiing|sledding/
03272  *     Regexp.union(/dogs/, /cats/i)        #=> /(?-mix:dogs)|(?i-mx:cats)/
03273  *
03274  *  Note: the arguments for ::union will try to be converted into a regular
03275  *  expression literal via #to_regexp.
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 /* :nodoc: */
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  *  call-seq:
03478  *     Regexp.last_match           -> matchdata
03479  *     Regexp.last_match(n)        -> str
03480  *
03481  *  The first form returns the MatchData object generated by the
03482  *  last successful pattern match.  Equivalent to reading the special global
03483  *  variable <code>$~</code> (see Special global variables in Regexp for
03484  *  details).
03485  *
03486  *  The second form returns the <i>n</i>th field in this MatchData object.
03487  *  _n_ can be a string or symbol to reference a named capture.
03488  *
03489  *  Note that the last_match is local to the thread and method scope of the
03490  *  method that did the pattern match.
03491  *
03492  *     /c(.)t/ =~ 'cat'        #=> 0
03493  *     Regexp.last_match       #=> #<MatchData "cat" 1:"a">
03494  *     Regexp.last_match(0)    #=> "cat"
03495  *     Regexp.last_match(1)    #=> "a"
03496  *     Regexp.last_match(2)    #=> nil
03497  *
03498  *     /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ "var = val"
03499  *     Regexp.last_match       #=> #<MatchData "var = val" lhs:"var" rhs:"val">
03500  *     Regexp.last_match(:lhs) #=> "var"
03501  *     Regexp.last_match(:rhs) #=> "val"
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  *  Document-class: RegexpError
03527  *
03528  *  Raised when given an invalid regexp expression.
03529  *
03530  *     Regexp.new("?")
03531  *
03532  *  <em>raises the exception:</em>
03533  *
03534  *     RegexpError: target of repeat operator is not specified: /?/
03535  */
03536 
03537 /*
03538  *  Document-class: Regexp
03539  *
03540  *  A <code>Regexp</code> holds a regular expression, used to match a pattern
03541  *  against strings. Regexps are created using the <code>/.../</code> and
03542  *  <code>%r{...}</code> literals, and by the <code>Regexp::new</code>
03543  *  constructor.
03544  *
03545  *  :include: doc/regexp.rdoc
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); /* in encoding.c */
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     /* see Regexp.options and Regexp.new */
03597     rb_define_const(rb_cRegexp, "IGNORECASE", INT2FIX(ONIG_OPTION_IGNORECASE));
03598     /* see Regexp.options and Regexp.new */
03599     rb_define_const(rb_cRegexp, "EXTENDED", INT2FIX(ONIG_OPTION_EXTEND));
03600     /* see Regexp.options and Regexp.new */
03601     rb_define_const(rb_cRegexp, "MULTILINE", INT2FIX(ONIG_OPTION_MULTILINE));
03602     /* see Regexp.options and Regexp.new */
03603     rb_define_const(rb_cRegexp, "FIXEDENCODING", INT2FIX(ARG_ENCODING_FIXED));
03604     /* see Regexp.options and Regexp.new */
03605     rb_define_const(rb_cRegexp, "NOENCODING", INT2FIX(ARG_ENCODING_NONE));
03606 
03607     rb_global_variable(&reg_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 

Generated on 19 Jul 2016 for Ruby by  doxygen 1.4.7