This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Fix more shared threads leaks: add SAVETMPS to the second branch
[perl5.git] / regexec.c
index 4692dcd..464ceaf 100644 (file)
--- a/regexec.c
+++ b/regexec.c
@@ -67,7 +67,8 @@
  *
  ****    Alterations to Henry's code are...
  ****
- ****    Copyright (c) 1991-2003, Larry Wall
+ ****    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ ****    2000, 2001, 2002, 2003, by Larry Wall and others
  ****
  ****    You may distribute under the terms of either the GNU General Public
  ****    License or the Artistic License, as specified in the README file.
@@ -86,6 +87,7 @@
 #define RF_warned      2               /* warned about big count? */
 #define RF_evaled      4               /* Did an EVAL with setting? */
 #define RF_utf8                8               /* String contains multibyte chars? */
+#define RF_false       16              /* odd number of nested negatives */
 
 #define UTF ((PL_reg_flags & RF_utf8) != 0)
 
@@ -171,7 +173,7 @@ S_regcppush(pTHX_ I32 parenfloor)
        Perl_croak(aTHX_ "panic: paren_elems_to_push < 0");
 
 #define REGCP_OTHER_ELEMS 6
-    SSCHECK(paren_elems_to_push + REGCP_OTHER_ELEMS);
+    SSGROW(paren_elems_to_push + REGCP_OTHER_ELEMS);
     for (p = PL_regsize; p > parenfloor; p--) {
 /* REGCP_PARENS_ELEMS are pushed per pairs of parentheses. */
        SSPUSHINT(PL_regendp[p]);
@@ -544,7 +546,7 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
            goto fail_finish;
        /* we may be pointing at the wrong string */
        if (s && RX_MATCH_COPIED(prog))
-           s = prog->subbeg + (s - SvPVX(sv));
+           s = strbeg + (s - SvPVX(sv));
        if (data)
            *data->scream_olds = s;
     }
@@ -951,6 +953,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
        I32 doevery = (prog->reganch & ROPT_SKIP) == 0;
        char *m;
        STRLEN ln;
+       STRLEN lnc;
        unsigned int c1;
        unsigned int c2;
        char *e;
@@ -1006,10 +1009,12 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
            }
            break;
        case EXACTF:
-           m = STRING(c);
-           ln = STR_LEN(c);
+           m   = STRING(c);
+           ln  = STR_LEN(c);   /* length to match in octets/bytes */
+           lnc = (I32) ln;     /* length to match in characters */
            if (UTF) {
                STRLEN ulen1, ulen2;
+               U8 *sm = (U8 *) m;
                U8 tmpbuf1[UTF8_MAXLEN_UCLC+1];
                U8 tmpbuf2[UTF8_MAXLEN_UCLC+1];
 
@@ -1020,6 +1025,11 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
                                    0, ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANY);
                c2 = utf8n_to_uvchr(tmpbuf2, UTF8_MAXLEN_UCLC,
                                    0, ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANY);
+               lnc = 0;
+               while (sm < ((U8 *) m + ln)) {
+                   lnc++;
+                   sm += UTF8SKIP(sm);
+               }
            }
            else {
                c1 = *(U8*)m;
@@ -1027,12 +1037,13 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
            }
            goto do_exactf;
        case EXACTFL:
-           m = STRING(c);
-           ln = STR_LEN(c);
+           m   = STRING(c);
+           ln  = STR_LEN(c);
+           lnc = (I32) ln;
            c1 = *(U8*)m;
            c2 = PL_fold_locale[c1];
          do_exactf:
-           e = HOP3c(strend, -(I32)ln, s);
+           e = HOP3c(strend, -((I32)lnc), s);
 
            if (norun && e < s)
                e = s;                  /* Due to minlen logic of intuit() */
@@ -1055,6 +1066,8 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta
                STRLEN len, foldlen;
                
                if (c1 == c2) {
+                   /* Upper and lower of 1st char are equal -
+                    * probably not a "letter". */
                    while (s <= e) {
                        c = utf8n_to_uvchr((U8*)s, UTF8_MAXLEN, &len,
                                           ckWARN(WARN_UTF8) ?
@@ -1862,7 +1875,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
                                  PL_multiline ? FBMrf_MULTILINE : 0))) ) {
            /* we may be pointing at the wrong string */
            if ((flags & REXEC_SCREAM) && RX_MATCH_COPIED(prog))
-               s = prog->subbeg + (s - SvPVX(sv));
+               s = strbeg + (s - SvPVX(sv));
            DEBUG_r( did_match = 1 );
            if (HOPc(s, -back_max) > last1) {
                last1 = HOPc(s, -back_min);
@@ -1951,7 +1964,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
                    last = scream_olds; /* Only one occurrence. */
                /* we may be pointing at the wrong string */
                else if (RX_MATCH_COPIED(prog))
-                   s = prog->subbeg + (s - SvPVX(sv));
+                   s = strbeg + (s - SvPVX(sv));
            }
            else {
                STRLEN len;
@@ -2834,6 +2847,7 @@ S_regmatch(pTHX_ regnode *prog)
            COP *ocurcop = PL_curcop;
            PAD *old_comppad;
            SV *ret;
+           struct regexp *oreg = PL_reg_re;
        
            n = ARG(scan);
            PL_op = (OP_4tree*)PL_regdata->data[n];
@@ -2966,8 +2980,10 @@ S_regmatch(pTHX_ regnode *prog)
                sw = SvTRUE(ret);
                logical = 0;
            }
-           else
+           else {
                sv_setsv(save_scalar(PL_replgv), ret);
+               cache_re(oreg);
+           }
            break;
        }
        case OPEN:
@@ -3200,7 +3216,10 @@ S_regmatch(pTHX_ regnode *prog)
                                      "%*s  already tried at this position...\n",
                                      REPORT_CODE_OFF+PL_regindent*2, "")
                        );
-                       sayNO_SILENT;
+                       if (PL_reg_flags & RF_false)
+                           sayYES;
+                       else
+                           sayNO_SILENT;
                    }
                    PL_reg_poscache[o] |= (1<<b);
                }
@@ -3386,19 +3405,8 @@ S_regmatch(pTHX_ regnode *prog)
                    if (! HAS_TEXT(text_node)) c1 = c2 = -1000;
                    else {
                        if (PL_regkind[(U8)OP(text_node)] == REF) {
-                           I32 n, ln;
-                           n = ARG(text_node);  /* which paren pair */
-                           ln = PL_regstartp[n];
-                           /* assume yes if we haven't seen CLOSEn */
-                           if (
-                               (I32)*PL_reglastparen < n ||
-                               ln == -1 ||
-                               ln == PL_regendp[n]
-                           ) {
-                               c1 = c2 = -1000;
-                               goto assume_ok_MM;
-                           }
-                           c1 = *(PL_bostr + ln);
+                           c1 = c2 = -1000;
+                           goto assume_ok_MM;
                        }
                        else { c1 = (U8)*STRING(text_node); }
                        if (OP(text_node) == EXACTF || OP(text_node) == REFF)
@@ -3468,19 +3476,8 @@ S_regmatch(pTHX_ regnode *prog)
                        if (! HAS_TEXT(text_node)) c1 = c2 = -1000;
                        else {
                            if (PL_regkind[(U8)OP(text_node)] == REF) {
-                               I32 n, ln;
-                               n = ARG(text_node);  /* which paren pair */
-                               ln = PL_regstartp[n];
-                               /* assume yes if we haven't seen CLOSEn */
-                               if (
-                                   (I32)*PL_reglastparen < n ||
-                                   ln == -1 ||
-                                   ln == PL_regendp[n]
-                               ) {
-                                   c1 = c2 = -1000;
-                                   goto assume_ok_REG;
-                               }
-                               c1 = *(PL_bostr + ln);
+                               c1 = c2 = -1000;
+                               goto assume_ok_REG;
                            }
                            else { c1 = (U8)*STRING(text_node); }
 
@@ -3577,19 +3574,8 @@ S_regmatch(pTHX_ regnode *prog)
                if (! HAS_TEXT(text_node)) c1 = c2 = -1000;
                else {
                    if (PL_regkind[(U8)OP(text_node)] == REF) {
-                       I32 n, ln;
-                       n = ARG(text_node);  /* which paren pair */
-                       ln = PL_regstartp[n];
-                       /* assume yes if we haven't seen CLOSEn */
-                       if (
-                           (I32)*PL_reglastparen < n ||
-                           ln == -1 ||
-                           ln == PL_regendp[n]
-                       ) {
-                           c1 = c2 = -1000;
-                           goto assume_ok_easy;
-                       }
-                       s = (U8*)PL_bostr + ln;
+                       c1 = c2 = -1000;
+                       goto assume_ok_easy;
                    }
                    else { s = (U8*)STRING(text_node); }
 
@@ -3883,6 +3869,7 @@ S_regmatch(pTHX_ regnode *prog)
            }
            else
                PL_reginput = locinput;
+           PL_reg_flags ^= RF_false;
            goto do_ifmatch;
        case IFMATCH:
            n = 1;
@@ -3898,6 +3885,8 @@ S_regmatch(pTHX_ regnode *prog)
          do_ifmatch:
            inner = NEXTOPER(NEXTOPER(scan));
            if (regmatch(inner) != n) {
+               if (n == 0)
+                   PL_reg_flags ^= RF_false;
              say_no:
                if (logical) {
                    logical = 0;
@@ -3907,6 +3896,8 @@ S_regmatch(pTHX_ regnode *prog)
                else
                    sayNO;
            }
+           if (n == 0)
+               PL_reg_flags ^= RF_false;
          say_yes:
            if (logical) {
                logical = 0;