This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Integrate:
[perl5.git] / regcomp.c
index 12e4d22..b0be233 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -5,6 +5,16 @@
  * "A fair jaw-cracker dwarf-language must be."  --Samwise Gamgee
  */
 
+/* This file contains functions for compiling a regular expression.  See
+ * also regexec.c which funnily enough, contains functions for executing
+ * a regular expression.
+ *
+ * This file is also copied at build time to ext/re/re_comp.c, where
+ * it's built with -DPERL_EXT_RE_BUILD -DPERL_EXT_RE_DEBUG -DPERL_EXT.
+ * This causes the main functions to be compiled under new names and with
+ * debugging support added, which makes "use re 'debug'" work.
+ */
+
 /* NOTE: this is derived from Henry Spencer's regexp code, and should not
  * confused with the original package (see point 3 below).  Thanks, Henry!
  */
@@ -69,7 +79,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, 2004, 2005, 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.
 #endif /* op */
 
 #ifdef MSDOS
-# if defined(BUGGY_MSC6)
+#  if defined(BUGGY_MSC6)
  /* MSC 6.00A breaks on op/regexp.t test 85 unless we turn this off */
- # pragma optimize("a",off)
+#    pragma optimize("a",off)
  /* But MSC 6.00A is happy with 'w', for aliases only across function calls*/
- # pragma optimize("w",on )
-# endif /* BUGGY_MSC6 */
+#    pragma optimize("w",on )
+#  endif /* BUGGY_MSC6 */
 #endif /* MSDOS */
 
 #ifndef STATIC
@@ -471,7 +482,7 @@ S_scan_commit(pTHX_ RExC_state_t *pRExC_state, scan_data_t *data)
     STRLEN old_l = CHR_SVLEN(*data->longest);
 
     if ((l >= old_l) && ((l > old_l) || (data->flags & SF_BEFORE_EOL))) {
-       sv_setsv(*data->longest, data->last_found);
+       SvSetMagicSV(*data->longest, data->last_found);
        if (*data->longest == data->longest_fixed) {
            data->offset_fixed = l ? data->last_start_min : data->pos_min;
            if (data->flags & SF_BEFORE_EOL)
@@ -495,6 +506,13 @@ S_scan_commit(pTHX_ RExC_state_t *pRExC_state, scan_data_t *data)
        }
     }
     SvCUR_set(data->last_found, 0);
+    {
+       SV * sv = data->last_found;
+       MAGIC *mg =
+           SvUTF8(sv) && SvMAGICAL(sv) ? mg_find(sv, PERL_MAGIC_utf8) : NULL;
+       if (mg && mg->mg_len > 0)
+           mg->mg_len = 0;
+    }
     data->last_end = -1;
     data->flags &= ~SF_BEFORE_EOL;
 }
@@ -568,14 +586,17 @@ S_cl_and(pTHX_ struct regnode_charclass_class *cl,
     if (!(and_with->flags & ANYOF_EOS))
        cl->flags &= ~ANYOF_EOS;
 
-    if (cl->flags & ANYOF_UNICODE_ALL && and_with->flags & ANYOF_UNICODE) {
+    if (cl->flags & ANYOF_UNICODE_ALL && and_with->flags & ANYOF_UNICODE &&
+       !(and_with->flags & ANYOF_INVERT)) {
        cl->flags &= ~ANYOF_UNICODE_ALL;
        cl->flags |= ANYOF_UNICODE;
        ARG_SET(cl, ARG(and_with));
     }
-    if (!(and_with->flags & ANYOF_UNICODE_ALL))
+    if (!(and_with->flags & ANYOF_UNICODE_ALL) &&
+       !(and_with->flags & ANYOF_INVERT))
        cl->flags &= ~ANYOF_UNICODE_ALL;
-    if (!(and_with->flags & (ANYOF_UNICODE|ANYOF_UNICODE_ALL)))
+    if (!(and_with->flags & (ANYOF_UNICODE|ANYOF_UNICODE_ALL)) &&
+       !(and_with->flags & ANYOF_INVERT))
        cl->flags &= ~ANYOF_UNICODE;
 }
 
@@ -913,6 +934,14 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, I32 *deltap, reg
                        ? I32_MAX : data->pos_min + data->pos_delta;
                }
                sv_catpvn(data->last_found, STRING(scan), STR_LEN(scan));
+               {
+                   SV * sv = data->last_found;
+                   MAGIC *mg = SvUTF8(sv) && SvMAGICAL(sv) ?
+                       mg_find(sv, PERL_MAGIC_utf8) : NULL;
+                   if (mg && mg->mg_len >= 0)
+                       mg->mg_len += utf8_length((U8*)STRING(scan),
+                                                 (U8*)STRING(scan)+STR_LEN(scan));
+               }
                if (UTF)
                    SvUTF8_on(data->last_found);
                data->last_end = data->pos_min + l;
@@ -1169,7 +1198,9 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, I32 *deltap, reg
                if (  OP(oscan) == CURLYX && data
                      && !(data->flags & SF_HAS_PAR)
                      && !(data->flags & SF_HAS_EVAL)
-                     && !deltanext  ) {
+                     && !deltanext     /* atom is fixed width */
+                     && minnext != 0   /* CURLYM can't handle zero width */
+               ) {
                    /* XXXX How to optimize if data == 0? */
                    /* Optimize to a simpler form.  */
                    regnode *nxt = NEXTOPER(oscan) + EXTRA_STEP_2ARGS; /* OPEN */
@@ -1278,11 +1309,19 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, I32 *deltap, reg
                                SvGROW(last_str, (mincount * l) + 1);
                                repeatcpy(SvPVX(last_str) + l,
                                          SvPVX(last_str), l, mincount - 1);
-                               SvCUR(last_str) *= mincount;
+                               SvCUR_set(last_str, SvCUR(last_str) * mincount);
                                /* Add additional parts. */
                                SvCUR_set(data->last_found,
                                          SvCUR(data->last_found) - l);
                                sv_catsv(data->last_found, last_str);
+                               {
+                                   SV * sv = data->last_found;
+                                   MAGIC *mg =
+                                       SvUTF8(sv) && SvMAGICAL(sv) ?
+                                       mg_find(sv, PERL_MAGIC_utf8) : NULL;
+                                   if (mg && mg->mg_len >= 0)
+                                       mg->mg_len += CHR_SVLEN(last_str);
+                               }
                                data->last_end += l * (mincount - 1);
                            }
                        } else {
@@ -2223,7 +2262,7 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp)
                }
                else {                                          /* First pass */
                    if (PL_reginterp_cnt < ++RExC_seen_evals
-                       && PL_curcop != &PL_compiling)
+                       && IN_PERL_RUNTIME)
                        /* No compiled RE interpolated, has runtime
                           components ===> unsafe.  */
                        FAIL("Eval-group not allowed at runtime, use re 'eval'");
@@ -2479,8 +2518,8 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp)
            if (paren == '>')
                node = SUSPEND, flag = 0;
            reginsert(pRExC_state, node,ret);
-           Set_Node_Offset(ret, oregcomp_parse);
-           Set_Node_Length(ret,  RExC_parse - oregcomp_parse + 2);
+           Set_Node_Cur_Length(ret);
+           Set_Node_Offset(ret, parse_start + 1);
            ret->flags = flag;
            regtail(pRExC_state, ret, reg_node(pRExC_state, TAIL));
        }
@@ -2761,7 +2800,7 @@ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp)
 {
     register regnode *ret = 0;
     I32 flags;
-    char *parse_start = 0;
+    char *parse_start = RExC_parse;
 
     *flagp = WORST;            /* Tentatively. */
 
@@ -3024,6 +3063,7 @@ tryagain:
        default:
            /* Do not generate `unrecognized' warnings here, we fall
               back into the quick-grab loop below */
+           parse_start--;
            goto defchar;
        }
        break;
@@ -3043,7 +3083,7 @@ tryagain:
            char *oldp, *s;
            STRLEN numlen;
            STRLEN foldlen;
-           U8 tmpbuf[UTF8_MAXLEN_FOLD+1], *foldbuf;
+           U8 tmpbuf[UTF8_MAXBYTES_CASE+1], *foldbuf;
 
             parse_start = RExC_parse - 1;
 
@@ -3130,11 +3170,6 @@ tryagain:
                                ender = grok_hex(p + 1, &numlen, &flags, NULL);
                                if (ender > 0xff)
                                    RExC_utf8 = 1;
-                               /* numlen is generous */
-                               if (numlen + len >= 127) {
-                                   p--;
-                                   goto loopdone;
-                               }
                                p = e + 1;
                            }
                        }
@@ -3278,7 +3313,7 @@ tryagain:
            }
            if (len > 0)
                *flagp |= HASWIDTH;
-           if (len == 1)
+           if (len == 1 && UNI_IS_INVARIANT(ender))
                *flagp |= SIMPLE;
            if (!SIZE_ONLY)
                STR_LEN(ret) = len;
@@ -3366,90 +3401,125 @@ S_regpposixcc(pTHX_ RExC_state_t *pRExC_state, I32 value)
        else {
            char* t = RExC_parse++; /* skip over the c */
 
+           assert(*t == c);
+
            if (UCHARAT(RExC_parse) == ']') {
                RExC_parse++; /* skip over the ending ] */
                posixcc = s + 1;
                if (*s == ':') {
                    I32 complement = *posixcc == '^' ? *posixcc++ : 0;
-                   I32 skip = 5; /* the most common skip */
-
-                   switch (*posixcc) {
-                   case 'a':
-                       if (strnEQ(posixcc, "alnum", 5))
-                           namedclass =
-                               complement ? ANYOF_NALNUMC : ANYOF_ALNUMC;
-                       else if (strnEQ(posixcc, "alpha", 5))
-                           namedclass =
-                               complement ? ANYOF_NALPHA : ANYOF_ALPHA;
-                       else if (strnEQ(posixcc, "ascii", 5))
-                           namedclass =
-                               complement ? ANYOF_NASCII : ANYOF_ASCII;
-                       break;
-                   case 'b':
-                       if (strnEQ(posixcc, "blank", 5))
-                           namedclass =
-                               complement ? ANYOF_NBLANK : ANYOF_BLANK;
-                       break;
-                   case 'c':
-                       if (strnEQ(posixcc, "cntrl", 5))
-                           namedclass =
-                               complement ? ANYOF_NCNTRL : ANYOF_CNTRL;
-                       break;
-                   case 'd':
-                       if (strnEQ(posixcc, "digit", 5))
-                           namedclass =
-                               complement ? ANYOF_NDIGIT : ANYOF_DIGIT;
-                       break;
-                   case 'g':
-                       if (strnEQ(posixcc, "graph", 5))
-                           namedclass =
-                               complement ? ANYOF_NGRAPH : ANYOF_GRAPH;
-                       break;
-                   case 'l':
-                       if (strnEQ(posixcc, "lower", 5))
-                           namedclass =
-                               complement ? ANYOF_NLOWER : ANYOF_LOWER;
-                       break;
-                   case 'p':
-                       if (strnEQ(posixcc, "print", 5))
-                           namedclass =
-                               complement ? ANYOF_NPRINT : ANYOF_PRINT;
-                       else if (strnEQ(posixcc, "punct", 5))
-                           namedclass =
-                               complement ? ANYOF_NPUNCT : ANYOF_PUNCT;
-                       break;
-                   case 's':
-                       if (strnEQ(posixcc, "space", 5))
-                           namedclass =
-                               complement ? ANYOF_NPSXSPC : ANYOF_PSXSPC;
+                   I32 skip = t - posixcc;
+
+                   /* Initially switch on the length of the name.  */
+                   switch (skip) {
+                   case 4:
+                       if (memEQ(posixcc, "word", 4)) {
+                           /* this is not POSIX, this is the Perl \w */;
+                           namedclass
+                               = complement ? ANYOF_NALNUM : ANYOF_ALNUM;
+                       }
                        break;
-                   case 'u':
-                       if (strnEQ(posixcc, "upper", 5))
-                           namedclass =
-                               complement ? ANYOF_NUPPER : ANYOF_UPPER;
-                       break;
-                   case 'w': /* this is not POSIX, this is the Perl \w */
-                       if (strnEQ(posixcc, "word", 4)) {
-                           namedclass =
-                               complement ? ANYOF_NALNUM : ANYOF_ALNUM;
-                           skip = 4;
+                   case 5:
+                       /* Names all of length 5.  */
+                       /* alnum alpha ascii blank cntrl digit graph lower
+                          print punct space upper  */
+                       /* Offset 4 gives the best switch position.  */
+                       switch (posixcc[4]) {
+                       case 'a':
+                           if (memEQ(posixcc, "alph", 4)) {
+                               /*                  a     */
+                               namedclass
+                                   = complement ? ANYOF_NALPHA : ANYOF_ALPHA;
+                           }
+                           break;
+                       case 'e':
+                           if (memEQ(posixcc, "spac", 4)) {
+                               /*                  e     */
+                               namedclass
+                                   = complement ? ANYOF_NPSXSPC : ANYOF_PSXSPC;
+                           }
+                           break;
+                       case 'h':
+                           if (memEQ(posixcc, "grap", 4)) {
+                               /*                  h     */
+                               namedclass
+                                   = complement ? ANYOF_NGRAPH : ANYOF_GRAPH;
+                           }
+                           break;
+                       case 'i':
+                           if (memEQ(posixcc, "asci", 4)) {
+                               /*                  i     */
+                               namedclass
+                                   = complement ? ANYOF_NASCII : ANYOF_ASCII;
+                           }
+                           break;
+                       case 'k':
+                           if (memEQ(posixcc, "blan", 4)) {
+                               /*                  k     */
+                               namedclass
+                                   = complement ? ANYOF_NBLANK : ANYOF_BLANK;
+                           }
+                           break;
+                       case 'l':
+                           if (memEQ(posixcc, "cntr", 4)) {
+                               /*                  l     */
+                               namedclass
+                                   = complement ? ANYOF_NCNTRL : ANYOF_CNTRL;
+                           }
+                           break;
+                       case 'm':
+                           if (memEQ(posixcc, "alnu", 4)) {
+                               /*                  m     */
+                               namedclass
+                                   = complement ? ANYOF_NALNUMC : ANYOF_ALNUMC;
+                           }
+                           break;
+                       case 'r':
+                           if (memEQ(posixcc, "lowe", 4)) {
+                               /*                  r     */
+                               namedclass
+                                   = complement ? ANYOF_NLOWER : ANYOF_LOWER;
+                           }
+                           if (memEQ(posixcc, "uppe", 4)) {
+                               /*                  r     */
+                               namedclass
+                                   = complement ? ANYOF_NUPPER : ANYOF_UPPER;
+                           }
+                           break;
+                       case 't':
+                           if (memEQ(posixcc, "digi", 4)) {
+                               /*                  t     */
+                               namedclass
+                                   = complement ? ANYOF_NDIGIT : ANYOF_DIGIT;
+                           }
+                           if (memEQ(posixcc, "prin", 4)) {
+                               /*                  t     */
+                               namedclass
+                                   = complement ? ANYOF_NPRINT : ANYOF_PRINT;
+                           }
+                           if (memEQ(posixcc, "punc", 4)) {
+                               /*                  t     */
+                               namedclass
+                                   = complement ? ANYOF_NPUNCT : ANYOF_PUNCT;
+                           }
+                           break;
                        }
                        break;
-                   case 'x':
-                       if (strnEQ(posixcc, "xdigit", 6)) {
-                           namedclass =
-                               complement ? ANYOF_NXDIGIT : ANYOF_XDIGIT;
-                           skip = 6;
+                   case 6:
+                       if (memEQ(posixcc, "xdigit", 6)) {
+                           namedclass
+                               = complement ? ANYOF_NXDIGIT : ANYOF_XDIGIT;
                        }
                        break;
                    }
-                   if (namedclass == OOB_NAMEDCLASS ||
-                       posixcc[skip] != ':' ||
-                       posixcc[skip+1] != ']')
+
+                   if (namedclass == OOB_NAMEDCLASS)
                    {
                        Simple_vFAIL3("POSIX class [:%.*s:] unknown",
                                      t - s - 1, s + 1);
                    }
+                   assert (posixcc[skip] == ':');
+                   assert (posixcc[skip+1] == ']');
                } else if (!SIZE_ONLY) {
                    /* [[=foo=]] and [[.foo.]] are still future. */
 
@@ -3631,7 +3701,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                }
                RExC_parse = e + 1;
                ANYOF_FLAGS(ret) |= ANYOF_UNICODE;
-               continue;
+               namedclass = ANYOF_MAX;  /* no official name, but it's named */
+               break;
            case 'n':   value = '\n';                   break;
            case 'r':   value = '\r';                   break;
            case 't':   value = '\t';                   break;
@@ -3715,6 +3786,9 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
            }
 
            if (!SIZE_ONLY) {
+               const char *what = NULL;
+               char yesno = 0;
+
                if (namedclass > OOB_NAMEDCLASS)
                    optimize_invert = FALSE;
                /* Possible truncation here but in some 64-bit environments
@@ -3730,7 +3804,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (isALNUM(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsWord\n");    
+                   yesno = '+';
+                   what = "Word";      
                    break;
                case ANYOF_NALNUM:
                    if (LOC)
@@ -3740,7 +3815,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (!isALNUM(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsWord\n");
+                   yesno = '!';
+                   what = "Word";
                    break;
                case ANYOF_ALNUMC:
                    if (LOC)
@@ -3750,7 +3826,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (isALNUMC(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsAlnum\n");
+                   yesno = '+';
+                   what = "Alnum";
                    break;
                case ANYOF_NALNUMC:
                    if (LOC)
@@ -3760,7 +3837,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (!isALNUMC(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsAlnum\n");
+                   yesno = '!';
+                   what = "Alnum";
                    break;
                case ANYOF_ALPHA:
                    if (LOC)
@@ -3770,7 +3848,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (isALPHA(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsAlpha\n");
+                   yesno = '+';
+                   what = "Alpha";
                    break;
                case ANYOF_NALPHA:
                    if (LOC)
@@ -3780,7 +3859,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (!isALPHA(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsAlpha\n");
+                   yesno = '!';
+                   what = "Alpha";
                    break;
                case ANYOF_ASCII:
                    if (LOC)
@@ -3796,7 +3876,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                        }
 #endif /* EBCDIC */
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsASCII\n");
+                   yesno = '+';
+                   what = "ASCII";
                    break;
                case ANYOF_NASCII:
                    if (LOC)
@@ -3812,7 +3893,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                        }
 #endif /* EBCDIC */
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsASCII\n");
+                   yesno = '!';
+                   what = "ASCII";
                    break;
                case ANYOF_BLANK:
                    if (LOC)
@@ -3822,7 +3904,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (isBLANK(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsBlank\n");
+                   yesno = '+';
+                   what = "Blank";
                    break;
                case ANYOF_NBLANK:
                    if (LOC)
@@ -3832,7 +3915,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (!isBLANK(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsBlank\n");
+                   yesno = '!';
+                   what = "Blank";
                    break;
                case ANYOF_CNTRL:
                    if (LOC)
@@ -3842,7 +3926,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (isCNTRL(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsCntrl\n");
+                   yesno = '+';
+                   what = "Cntrl";
                    break;
                case ANYOF_NCNTRL:
                    if (LOC)
@@ -3852,7 +3937,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (!isCNTRL(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsCntrl\n");
+                   yesno = '!';
+                   what = "Cntrl";
                    break;
                case ANYOF_DIGIT:
                    if (LOC)
@@ -3862,7 +3948,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                        for (value = '0'; value <= '9'; value++)
                            ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsDigit\n");
+                   yesno = '+';
+                   what = "Digit";
                    break;
                case ANYOF_NDIGIT:
                    if (LOC)
@@ -3874,7 +3961,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                        for (value = '9' + 1; value < 256; value++)
                            ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsDigit\n");
+                   yesno = '!';
+                   what = "Digit";
                    break;
                case ANYOF_GRAPH:
                    if (LOC)
@@ -3884,7 +3972,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (isGRAPH(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsGraph\n");
+                   yesno = '+';
+                   what = "Graph";
                    break;
                case ANYOF_NGRAPH:
                    if (LOC)
@@ -3894,7 +3983,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (!isGRAPH(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsGraph\n");
+                   yesno = '!';
+                   what = "Graph";
                    break;
                case ANYOF_LOWER:
                    if (LOC)
@@ -3904,7 +3994,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (isLOWER(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsLower\n");
+                   yesno = '+';
+                   what = "Lower";
                    break;
                case ANYOF_NLOWER:
                    if (LOC)
@@ -3914,7 +4005,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (!isLOWER(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsLower\n");
+                   yesno = '!';
+                   what = "Lower";
                    break;
                case ANYOF_PRINT:
                    if (LOC)
@@ -3924,7 +4016,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (isPRINT(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsPrint\n");
+                   yesno = '+';
+                   what = "Print";
                    break;
                case ANYOF_NPRINT:
                    if (LOC)
@@ -3934,7 +4027,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (!isPRINT(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsPrint\n");
+                   yesno = '!';
+                   what = "Print";
                    break;
                case ANYOF_PSXSPC:
                    if (LOC)
@@ -3944,7 +4038,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (isPSXSPC(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsSpace\n");
+                   yesno = '+';
+                   what = "Space";
                    break;
                case ANYOF_NPSXSPC:
                    if (LOC)
@@ -3954,7 +4049,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (!isPSXSPC(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsSpace\n");
+                   yesno = '!';
+                   what = "Space";
                    break;
                case ANYOF_PUNCT:
                    if (LOC)
@@ -3964,7 +4060,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (isPUNCT(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsPunct\n");
+                   yesno = '+';
+                   what = "Punct";
                    break;
                case ANYOF_NPUNCT:
                    if (LOC)
@@ -3974,7 +4071,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (!isPUNCT(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsPunct\n");
+                   yesno = '!';
+                   what = "Punct";
                    break;
                case ANYOF_SPACE:
                    if (LOC)
@@ -3984,7 +4082,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (isSPACE(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsSpacePerl\n");
+                   yesno = '+';
+                   what = "SpacePerl";
                    break;
                case ANYOF_NSPACE:
                    if (LOC)
@@ -3994,7 +4093,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (!isSPACE(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsSpacePerl\n");
+                   yesno = '!';
+                   what = "SpacePerl";
                    break;
                case ANYOF_UPPER:
                    if (LOC)
@@ -4004,7 +4104,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (isUPPER(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsUpper\n");
+                   yesno = '+';
+                   what = "Upper";
                    break;
                case ANYOF_NUPPER:
                    if (LOC)
@@ -4014,7 +4115,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (!isUPPER(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsUpper\n");
+                   yesno = '!';
+                   what = "Upper";
                    break;
                case ANYOF_XDIGIT:
                    if (LOC)
@@ -4024,7 +4126,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (isXDIGIT(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "+utf8::IsXDigit\n");
+                   yesno = '+';
+                   what = "XDigit";
                    break;
                case ANYOF_NXDIGIT:
                    if (LOC)
@@ -4034,12 +4137,20 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                            if (!isXDIGIT(value))
                                ANYOF_BITMAP_SET(ret, value);
                    }
-                   Perl_sv_catpvf(aTHX_ listsv, "!utf8::IsXDigit\n");
+                   yesno = '!';
+                   what = "XDigit";
+                   break;
+               case ANYOF_MAX:
+                   /* this is to handle \p and \P */
                    break;
                default:
                    vFAIL("Invalid [::] class");
                    break;
                }
+               if (what) {
+                   /* Strings such as "+utf8::isWord\n" */
+                   Perl_sv_catpvf(aTHX_ listsv, "%cutf8::Is%s\n", yesno, what);
+               }
                if (LOC)
                    ANYOF_FLAGS(ret) |= ANYOF_CLASS;
                continue;
@@ -4118,7 +4229,7 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state)
                else if (prevnatvalue == natvalue) {
                    Perl_sv_catpvf(aTHX_ listsv, "%04"UVxf"\n", natvalue);
                    if (FOLD) {
-                        U8 foldbuf[UTF8_MAXLEN_FOLD+1];
+                        U8 foldbuf[UTF8_MAXBYTES_CASE+1];
                         STRLEN foldlen;
                         UV f = to_uni_fold(natvalue, foldbuf, &foldlen);
 
@@ -4240,8 +4351,11 @@ S_nextchar(pTHX_ RExC_state_t *pRExC_state)
     for (;;) {
        if (*RExC_parse == '(' && RExC_parse[1] == '?' &&
                RExC_parse[2] == '#') {
-           while (*RExC_parse && *RExC_parse != ')')
+           while (*RExC_parse != ')') {
+               if (RExC_parse == RExC_end)
+                   FAIL("Sequence (?#... not terminated");
                RExC_parse++;
+           }
            RExC_parse++;
            continue;
        }
@@ -4251,9 +4365,8 @@ S_nextchar(pTHX_ RExC_state_t *pRExC_state)
                continue;
            }
            else if (*RExC_parse == '#') {
-               while (*RExC_parse && *RExC_parse != '\n')
-                   RExC_parse++;
-               RExC_parse++;
+               while (RExC_parse < RExC_end)
+                   if (*RExC_parse++ == '\n') break;
                continue;
            }
        }
@@ -4396,6 +4509,7 @@ S_reginsert(pTHX_ RExC_state_t *pRExC_state, U8 op, regnode *opnd)
               RExC_parse - RExC_start,
               RExC_offsets[0])); 
        Set_Node_Offset(place, RExC_parse);
+       Set_Node_Length(place, 1);
     }
     src = NEXTOPER(place);
     FILL_ADVANCE_NODE(place, op);
@@ -4711,7 +4825,7 @@ Perl_regprop(pTHX_ SV *sv, regnode *o)
     else if (k == ANYOF) {
        int i, rangestart = -1;
        U8 flags = ANYOF_FLAGS(o);
-       const char * const anyofs[] = { /* Should be syncronized with
+       const char * const anyofs[] = { /* Should be synchronized with
                                         * ANYOF_ #xdefines in regcomp.h */
            "\\w",
            "\\W",
@@ -4785,7 +4899,7 @@ Perl_regprop(pTHX_ SV *sv, regnode *o)
        
            if (lv) {
                if (sw) {
-                   U8 s[UTF8_MAXLEN+1];
+                   U8 s[UTF8_MAXBYTES_CASE+1];
                
                    for (i = 0; i <= 256; i++) { /* just the first 256 */
                        U8 *e = uvchr_to_utf8(s, i);
@@ -4816,7 +4930,7 @@ Perl_regprop(pTHX_ SV *sv, regnode *o)
                }
 
                {
-                   char *s = savepv(SvPVX(lv));
+                   char *s = savesvpv(lv);
                    char *origs = s;
                
                    while(*s && *s != '\n') s++;
@@ -4917,6 +5031,7 @@ Perl_pregfree(pTHX_ struct regexp *r)
        int n = r->data->count;
        PAD* new_comppad = NULL;
        PAD* old_comppad;
+       PADOFFSET refcnt;
 
        while (--n >= 0) {
           /* If you add a ->what type here, update the comment in regcomp.h */
@@ -4938,9 +5053,11 @@ Perl_pregfree(pTHX_ struct regexp *r)
                    (SvTYPE(new_comppad) == SVt_PVAV) ?
                                new_comppad : Null(PAD *)
                );
-               if (!OpREFCNT_dec((OP_4tree*)r->data->data[n])) {
+               OP_REFCNT_LOCK;
+               refcnt = OpREFCNT_dec((OP_4tree*)r->data->data[n]);
+               OP_REFCNT_UNLOCK;
+               if (!refcnt)
                     op_free((OP_4tree*)r->data->data[n]);
-               }
 
                PAD_RESTORE_LOCAL(old_comppad);
                SvREFCNT_dec((SV*)new_comppad);
@@ -5011,7 +5128,7 @@ S_re_croak2(pTHX_ const char* pat1,const char* pat2,...)
     if (l1 > 512)
        l1 = 512;
     Copy(message, buf, l1 , char);
-    buf[l1] = '\0';                    /* Overwrite \n */
+    buf[l1-1] = '\0';                  /* Overwrite \n */
     Perl_croak(aTHX_ "%s", buf);
 }
 
@@ -5071,7 +5188,7 @@ Perl_save_re_context(pTHX)
        U32 i;
        GV *mgv;
        REGEXP *rx;
-       char digits[16];
+       char digits[TYPE_CHARS(long)];
 
        if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
            for (i = 1; i <= rx->nparens; i++) {
@@ -5093,3 +5210,12 @@ clear_re(pTHX_ void *r)
     ReREFCNT_dec((regexp *)r);
 }
 
+/*
+ * Local variables:
+ * c-indentation-style: bsd
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vim: shiftwidth=4:
+*/