]> code.delx.au - gnu-emacs/blobdiff - src/regex.c
Merge from emacs--devo--0
[gnu-emacs] / src / regex.c
index 4b011634ae151742081f6c9c77e49d98f7c51c97..a0d6b945cf1afdfd2c698bbafe74a2f439366841 100644 (file)
@@ -3,11 +3,12 @@
    internationalization features.)
 
    Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-                 2002, 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+                 2002, 2003, 2004, 2005, 2006, 2007
+                 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -67,8 +68,8 @@
 # define regfree(preg) __regfree (preg)
 # define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
 # define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
-# define regerror(errcode, preg, errbuf, errbuf_size) \
-       __regerror(errcode, preg, errbuf, errbuf_size)
+# define regerror(err_code, preg, errbuf, errbuf_size) \
+       __regerror(err_code, preg, errbuf, errbuf_size)
 # define re_set_registers(bu, re, nu, st, en) \
        __re_set_registers (bu, re, nu, st, en)
 # define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
 
 # define RE_MULTIBYTE_P(bufp) ((bufp)->multibyte)
 # define RE_TARGET_MULTIBYTE_P(bufp) ((bufp)->target_multibyte)
-# define RE_STRING_CHAR(p, s) \
+# define RE_STRING_CHAR(p, s, multibyte) \
   (multibyte ? (STRING_CHAR (p, s)) : (*(p)))
-# define RE_STRING_CHAR_AND_LENGTH(p, s, len) \
+# define RE_STRING_CHAR_AND_LENGTH(p, s, len, multibyte) \
   (multibyte ? (STRING_CHAR_AND_LENGTH (p, s, len)) : ((len) = 1, *(p)))
 
+# define RE_CHAR_TO_MULTIBYTE(c) unibyte_to_multibyte_table[(c)]
+
+# define RE_CHAR_TO_UNIBYTE(c)                 \
+  (ASCII_CHAR_P (c) ? (c)                      \
+   : CHAR_BYTE8_P (c) ? CHAR_TO_BYTE8 (c)      \
+   : multibyte_char_to_unibyte_safe (c))
+
 /* Set C a (possibly converted to multibyte) character before P.  P
    points into a string which is the virtual concatenation of STR1
    (which ends at END1) or STR2 (which ends at END2).  */
 # define GET_CHAR_BEFORE_2(c, p, str1, end1, str2, end2)                    \
   do {                                                                      \
-    if (multibyte)                                                          \
+    if (target_multibyte)                                                   \
       {                                                                             \
        re_char *dtemp = (p) == (str2) ? (end1) : (p);                       \
        re_char *dlimit = ((p) > (str2) && (p) <= (end2)) ? (str2) : (str1); \
     else                                                                    \
       {                                                                             \
        (c = ((p) == (str2) ? (end1) : (p))[-1]);                            \
-       MAKE_CHAR_MULTIBYTE (c);                                             \
+       (c) = RE_CHAR_TO_MULTIBYTE (c);                                      \
       }                                                                             \
   } while (0)
 
    LEN to the byte length of that character.  */
 # define GET_CHAR_AFTER(c, p, len)             \
   do {                                         \
-    if (multibyte)                             \
-      c = STRING_CHAR_AND_LENGTH (p, 0, len);  \
+    if (target_multibyte)                      \
+      (c) = STRING_CHAR_AND_LENGTH (p, 0, len);        \
     else                                       \
       {                                                \
-       c = *p;                                 \
+       (c) = *p;                               \
        len = 1;                                \
-       MAKE_CHAR_MULTIBYTE (c);                \
+       (c) = RE_CHAR_TO_MULTIBYTE (c);         \
       }                                                \
    } while (0)
 
@@ -301,10 +309,12 @@ enum syntaxcode { Swhitespace = 0, Sword = 1, Ssymbol = 2 };
 # define MULTIBYTE_FORM_LENGTH(p, s) (1)
 # define PREV_CHAR_BOUNDARY(p, limit) ((p)--)
 # define STRING_CHAR(p, s) (*(p))
-# define RE_STRING_CHAR STRING_CHAR
+# define RE_STRING_CHAR(p, s, multibyte) STRING_CHAR ((p), (s))
 # define CHAR_STRING(c, s) (*(s) = (c), 1)
 # define STRING_CHAR_AND_LENGTH(p, s, actual_len) ((actual_len) = 1, *(p))
-# define RE_STRING_CHAR_AND_LENGTH STRING_CHAR_AND_LENGTH
+# define RE_STRING_CHAR_AND_LENGTH(p, s, len, multibyte) STRING_CHAR_AND_LENGTH ((p), (s), (len))
+# define RE_CHAR_TO_MULTIBYTE(c) (c)
+# define RE_CHAR_TO_UNIBYTE(c) (c)
 # define GET_CHAR_BEFORE_2(c, p, str1, end1, str2, end2) \
   (c = ((p) == (str2) ? *((end1) - 1) : *((p) - 1)))
 # define GET_CHAR_AFTER(c, p, len)     \
@@ -312,8 +322,6 @@ enum syntaxcode { Swhitespace = 0, Sword = 1, Ssymbol = 2 };
 # define MAKE_CHAR(charset, c1, c2) (c1)
 # define BYTE8_TO_CHAR(c) (c)
 # define CHAR_BYTE8_P(c) (0)
-# define MAKE_CHAR_MULTIBYTE(c) (c)
-# define MAKE_CHAR_UNIBYTE(c) (c)
 # define CHAR_LEADING_CODE(c) (c)
 
 #endif /* not emacs */
@@ -1390,18 +1398,12 @@ static const char *re_error_msgid[] =
 /* Normally, this is fine.  */
 #define MATCH_MAY_ALLOCATE
 
-/* When using GNU C, we are not REALLY using the C alloca, no matter
-   what config.h may say.  So don't take precautions for it.  */
-#ifdef __GNUC__
-# undef C_ALLOCA
-#endif
-
 /* The match routines may not allocate if (1) they would do it with malloc
    and (2) it's not safe for them to use malloc.
    Note that if REL_ALLOC is defined, matching would not use malloc for the
    failure stack, but we would still use it for the register vectors;
    so REL_ALLOC should not affect this.  */
-#if (defined C_ALLOCA || defined REGEX_MALLOC) && defined emacs
+#if defined REGEX_MALLOC && defined emacs
 # undef MATCH_MAY_ALLOCATE
 #endif
 
@@ -1761,7 +1763,7 @@ static int analyse_first _RE_ARGS ((re_char *p, re_char *pend,
   do {                                                                 \
     int len;                                                           \
     if (p == pend) return REG_EEND;                                    \
-    c = RE_STRING_CHAR_AND_LENGTH (p, pend - p, len);                  \
+    c = RE_STRING_CHAR_AND_LENGTH (p, pend - p, len, multibyte);       \
     p += len;                                                          \
   } while (0)
 
@@ -2019,32 +2021,107 @@ struct range_table_work_area
 
 #ifdef emacs
 
-/* Store characters in the rage range C0 to C1 in WORK_AREA while
-   translating them and paying attention to the continuity of
-   translated characters.
+/* Store characters in the range FROM to TO in the bitmap at B (for
+   ASCII and unibyte characters) and WORK_AREA (for multibyte
+   characters) while translating them and paying attention to the
+   continuity of translated characters.
 
-   Implementation note: It is better to implement this fairly big
-   macro by a function, but it's not that easy because macros called
+   Implementation note: It is better to implement these fairly big
+   macros by a function, but it's not that easy because macros called
    in this macro assume various local variables already declared.  */
 
-#define SETUP_MULTIBYTE_RANGE(work_area, c0, c1)                             \
-  do {                                                                       \
-    re_wchar_t c, t, t_last;                                                 \
-    int n;                                                                   \
-                                                                             \
-    c = (c0);                                                                \
-    t_last = multibyte ? TRANSLATE (c) : TRANSLATE (MAKE_CHAR_MULTIBYTE (c)); \
-    for (c++, n = 1; c <= (c1); c++, n++)                                    \
-      {                                                                              \
-       t = multibyte ? TRANSLATE (c) : TRANSLATE (MAKE_CHAR_MULTIBYTE (c));  \
-       if (t_last + n == t)                                                  \
-         continue;                                                           \
-       SET_RANGE_TABLE_WORK_AREA ((work_area), t_last, t_last + n - 1);      \
-       t_last = t;                                                           \
-       n = 0;                                                                \
-      }                                                                              \
-    if (n > 0)                                                               \
-      SET_RANGE_TABLE_WORK_AREA ((work_area), t_last, t_last + n - 1);       \
+/* Both FROM and TO are ASCII characters.  */
+
+#define SETUP_ASCII_RANGE(work_area, FROM, TO)                 \
+  do {                                                         \
+    int C0, C1;                                                        \
+                                                               \
+    for (C0 = (FROM); C0 <= (TO); C0++)                                \
+      {                                                                \
+       C1 = TRANSLATE (C0);                                    \
+       if (! ASCII_CHAR_P (C1))                                \
+         {                                                     \
+           SET_RANGE_TABLE_WORK_AREA ((work_area), C1, C1);    \
+           if ((C1 = RE_CHAR_TO_UNIBYTE (C1)) < 0)             \
+             C1 = C0;                                          \
+         }                                                     \
+       SET_LIST_BIT (C1);                                      \
+      }                                                                \
+  } while (0)
+
+
+/* Both FROM and TO are unibyte characters (0x80..0xFF).  */
+
+#define SETUP_UNIBYTE_RANGE(work_area, FROM, TO)                              \
+  do {                                                                        \
+    int C0, C1, C2, I;                                                        \
+    int USED = RANGE_TABLE_WORK_USED (work_area);                             \
+                                                                              \
+    for (C0 = (FROM); C0 <= (TO); C0++)                                               \
+      {                                                                               \
+       C1 = RE_CHAR_TO_MULTIBYTE (C0);                                        \
+       if (CHAR_BYTE8_P (C1))                                                 \
+         SET_LIST_BIT (C0);                                                   \
+       else                                                                   \
+         {                                                                    \
+           C2 = TRANSLATE (C1);                                               \
+           if (C2 == C1                                                       \
+               || (C1 = RE_CHAR_TO_UNIBYTE (C2)) < 0)                         \
+             C1 = C0;                                                         \
+           SET_LIST_BIT (C1);                                                 \
+           for (I = RANGE_TABLE_WORK_USED (work_area) - 2; I >= USED; I -= 2) \
+             {                                                                \
+               int from = RANGE_TABLE_WORK_ELT (work_area, I);                \
+               int to = RANGE_TABLE_WORK_ELT (work_area, I + 1);              \
+                                                                              \
+               if (C2 >= from - 1 && C2 <= to + 1)                            \
+                 {                                                            \
+                   if (C2 == from - 1)                                        \
+                     RANGE_TABLE_WORK_ELT (work_area, I)--;                   \
+                   else if (C2 == to + 1)                                     \
+                     RANGE_TABLE_WORK_ELT (work_area, I + 1)++;               \
+                   break;                                                     \
+                 }                                                            \
+             }                                                                \
+           if (I < USED)                                                      \
+             SET_RANGE_TABLE_WORK_AREA ((work_area), C2, C2);                 \
+         }                                                                    \
+      }                                                                               \
+  } while (0)
+
+
+/* Both FROM and TO are mulitbyte characters.  */
+
+#define SETUP_MULTIBYTE_RANGE(work_area, FROM, TO)                        \
+  do {                                                                    \
+    int C0, C1, C2, I, USED = RANGE_TABLE_WORK_USED (work_area);          \
+                                                                          \
+    SET_RANGE_TABLE_WORK_AREA ((work_area), (FROM), (TO));                \
+    for (C0 = (FROM); C0 <= (TO); C0++)                                           \
+      {                                                                           \
+       C1 = TRANSLATE (C0);                                               \
+       if ((C2 = RE_CHAR_TO_UNIBYTE (C1)) >= 0                            \
+           || (C1 != C0 && (C2 = RE_CHAR_TO_UNIBYTE (C0)) >= 0))          \
+         SET_LIST_BIT (C2);                                               \
+       if (C1 >= (FROM) && C1 <= (TO))                                    \
+         continue;                                                        \
+       for (I = RANGE_TABLE_WORK_USED (work_area) - 2; I >= USED; I -= 2) \
+         {                                                                \
+           int from = RANGE_TABLE_WORK_ELT (work_area, I);                \
+           int to = RANGE_TABLE_WORK_ELT (work_area, I + 1);              \
+                                                                          \
+           if (C1 >= from - 1 && C1 <= to + 1)                            \
+             {                                                            \
+               if (C1 == from - 1)                                        \
+                 RANGE_TABLE_WORK_ELT (work_area, I)--;                   \
+               else if (C1 == to + 1)                                     \
+                 RANGE_TABLE_WORK_ELT (work_area, I + 1)++;               \
+               break;                                                     \
+             }                                                            \
+         }                                                                \
+       if (I < USED)                                                      \
+         SET_RANGE_TABLE_WORK_AREA ((work_area), C1, C1);                 \
+      }                                                                           \
   } while (0)
 
 #endif /* emacs */
@@ -2101,7 +2178,7 @@ re_wctype (str)
   else return 0;
 }
 
-/* True iff CH is in the char class CC.  */
+/* True if CH is in the char class CC.  */
 boolean
 re_iswctype (ch, cc)
      int ch;
@@ -2538,11 +2615,6 @@ regex_compile (pattern, size, syntax, bufp)
      last -- ends with a forward jump of this sort.  */
   unsigned char *fixup_alt_jump = 0;
 
-  /* Counts open-groups as they are encountered.  Remembered for the
-     matching close-group on the compile stack, so the same register
-     number is put in the stop_memory as the start_memory.  */
-  regnum_t regnum = 0;
-
   /* Work area for range table of charset.  */
   struct range_table_work_area range_table_work;
 
@@ -2904,6 +2976,7 @@ regex_compile (pattern, size, syntax, bufp)
              {
                boolean escaped_char = false;
                const unsigned char *p2 = p;
+               re_wchar_t ch, c2;
 
                if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
 
@@ -2966,7 +3039,6 @@ regex_compile (pattern, size, syntax, bufp)
                       them).  */
                    if (c == ':' && *p == ']')
                      {
-                       re_wchar_t ch;
                        re_wctype_t cc;
                        int limit;
 
@@ -2981,41 +3053,41 @@ regex_compile (pattern, size, syntax, bufp)
 
                         if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
 
-                       /* Most character classes in a multibyte match
-                          just set a flag.  Exceptions are is_blank,
-                          is_digit, is_cntrl, and is_xdigit, since
-                          they can only match ASCII characters.  We
-                          don't need to handle them for multibyte.
-                          They are distinguished by a negative wctype.  */
-
-                       for (ch = 0; ch < 128; ++ch)
+#ifndef emacs
+                       for (ch = 0; ch < (1 << BYTEWIDTH); ++ch)
                          if (re_iswctype (btowc (ch), cc))
                            {
                              c = TRANSLATE (ch);
                              if (c < (1 << BYTEWIDTH))
                                SET_LIST_BIT (c);
                            }
+#else  /* emacs */
+                       /* Most character classes in a multibyte match
+                          just set a flag.  Exceptions are is_blank,
+                          is_digit, is_cntrl, and is_xdigit, since
+                          they can only match ASCII characters.  We
+                          don't need to handle them for multibyte.
+                          They are distinguished by a negative wctype.  */
 
-                       if (target_multibyte)
+                       for (ch = 0; ch < 256; ++ch)
                          {
-                           SET_RANGE_TABLE_WORK_AREA_BIT
-                             (range_table_work, re_wctype_to_bit (cc));
-                         }
-                       else
-                         {
-                           for (ch = 0; ch < (1 << BYTEWIDTH); ++ch)
+                           c = RE_CHAR_TO_MULTIBYTE (ch);
+                           if (! CHAR_BYTE8_P (c)
+                               && re_iswctype (c, cc))
                              {
-                               c = ch;
-                               MAKE_CHAR_MULTIBYTE (c);
-                               if (re_iswctype (btowc (c), cc))
-                                 {
-                                   c = TRANSLATE (c);
-                                   MAKE_CHAR_UNIBYTE (c);
-                                   SET_LIST_BIT (c);
-                                 }
+                               SET_LIST_BIT (ch);
+                               c1 = TRANSLATE (c);
+                               if (c1 == c)
+                                 continue;
+                               if (ASCII_CHAR_P (c1))
+                                 SET_LIST_BIT (c1);
+                               else if ((c1 = RE_CHAR_TO_UNIBYTE (c1)) >= 0)
+                                 SET_LIST_BIT (c1);
                              }
                          }
-
+                       SET_RANGE_TABLE_WORK_AREA_BIT
+                         (range_table_work, re_wctype_to_bit (cc));
+#endif /* emacs */
                        /* In most cases the matching rule for char classes
                           only uses the syntax table for multibyte chars,
                           so that the content of the syntax-table it is not
@@ -3048,51 +3120,63 @@ regex_compile (pattern, size, syntax, bufp)
 
                    /* Fetch the character which ends the range. */
                    PATFETCH (c1);
-                   if (c > c1)
-                     {
-                       if (syntax & RE_NO_EMPTY_RANGES)
-                         FREE_STACK_RETURN (REG_ERANGEX);
-                       /* Else, repeat the loop.  */
-                     }
+#ifdef emacs
+                   if (CHAR_BYTE8_P (c1)
+                       && ! ASCII_CHAR_P (c) && ! CHAR_BYTE8_P (c))
+                     /* Treat the range from a multibyte character to
+                        raw-byte character as empty.  */
+                     c = c1 + 1;
+#endif /* emacs */
                  }
                else
                  /* Range from C to C. */
                  c1 = c;
 
-#ifndef emacs
-               c = TRANSLATE (c);
-               c1 = TRANSLATE (c1);
-               /* Set the range into bitmap */
-               for (; c <= c1; c++)
-                 SET_LIST_BIT (TRANSLATE (c));
-#else  /* not emacs */
-               if (target_multibyte)
+               if (c > c1)
                  {
-                   if (c1 >= 128)
-                     {
-                       re_wchar_t c0 = MAX (c, 128);
-
-                       SETUP_MULTIBYTE_RANGE (range_table_work, c0, c1);
-                       c1 = 127;
-                     }
-                   for (; c <= c1; c++)
-                     SET_LIST_BIT (TRANSLATE (c));
+                   if (syntax & RE_NO_EMPTY_RANGES)
+                     FREE_STACK_RETURN (REG_ERANGEX);
+                   /* Else, repeat the loop.  */
                  }
                else
                  {
-                   re_wchar_t c0;
-
+#ifndef emacs
+                   /* Set the range into bitmap */
                    for (; c <= c1; c++)
                      {
-                       c0 = c;
-                       if (! multibyte)
-                         MAKE_CHAR_MULTIBYTE (c0);
-                       c0 = TRANSLATE (c0);
-                       MAKE_CHAR_UNIBYTE (c0);
-                       SET_LIST_BIT (c0);
+                       ch = TRANSLATE (c);
+                       if (ch < (1 << BYTEWIDTH))
+                         SET_LIST_BIT (ch);
+                     }
+#else  /* emacs */
+                   if (c < 128)
+                     {
+                       ch = MIN (127, c1);
+                       SETUP_ASCII_RANGE (range_table_work, c, ch);
+                       c = ch + 1;
+                       if (CHAR_BYTE8_P (c1))
+                         c = BYTE8_TO_CHAR (128);
+                     }
+                   if (c <= c1)
+                     {
+                       if (CHAR_BYTE8_P (c))
+                         {
+                           c = CHAR_TO_BYTE8 (c);
+                           c1 = CHAR_TO_BYTE8 (c1);
+                           for (; c <= c1; c++)
+                             SET_LIST_BIT (c);
+                         }
+                       else if (multibyte)
+                         {
+                           SETUP_MULTIBYTE_RANGE (range_table_work, c, c1);
+                         }
+                       else
+                         {
+                           SETUP_UNIBYTE_RANGE (range_table_work, c, c1);
+                         }
                      }
+#endif /* emacs */
                  }
-#endif /* not emacs */
              }
 
            /* Discard any (non)matching list bytes that are all 0 at the
@@ -3182,28 +3266,54 @@ regex_compile (pattern, size, syntax, bufp)
            handle_open:
              {
                int shy = 0;
+               regnum_t regnum = 0;
                if (p+1 < pend)
                  {
                    /* Look for a special (?...) construct */
                    if ((syntax & RE_SHY_GROUPS) && *p == '?')
                      {
                        PATFETCH (c); /* Gobble up the '?'.  */
-                       PATFETCH (c);
-                       switch (c)
+                       while (!shy)
                          {
-                         case ':': shy = 1; break;
-                         default:
-                           /* Only (?:...) is supported right now. */
-                           FREE_STACK_RETURN (REG_BADPAT);
+                           PATFETCH (c);
+                           switch (c)
+                             {
+                             case ':': shy = 1; break;
+                             case '0':
+                               /* An explicitly specified regnum must start
+                                  with non-0. */
+                               if (regnum == 0)
+                                 FREE_STACK_RETURN (REG_BADPAT);
+                             case '1': case '2': case '3': case '4':
+                             case '5': case '6': case '7': case '8': case '9':
+                               regnum = 10*regnum + (c - '0'); break;
+                             default:
+                               /* Only (?:...) is supported right now. */
+                               FREE_STACK_RETURN (REG_BADPAT);
+                             }
                          }
                      }
                  }
 
                if (!shy)
-                 {
-                   bufp->re_nsub++;
-                   regnum++;
+                 regnum = ++bufp->re_nsub;
+               else if (regnum)
+                 { /* It's actually not shy, but explicitly numbered.  */
+                   shy = 0;
+                   if (regnum > bufp->re_nsub)
+                     bufp->re_nsub = regnum;
+                   else if (regnum > bufp->re_nsub
+                            /* Ideally, we'd want to check that the specified
+                               group can't have matched (i.e. all subgroups
+                               using the same regnum are in other branches of
+                               OR patterns), but we don't currently keep track
+                               of enough info to do that easily.  */
+                            || group_in_compile_stack (compile_stack, regnum))
+                     FREE_STACK_RETURN (REG_BADPAT);
                  }
+               else
+                 /* It's really shy.  */
+                 regnum = - bufp->re_nsub;
 
                if (COMPILE_STACK_FULL)
                  {
@@ -3222,12 +3332,11 @@ regex_compile (pattern, size, syntax, bufp)
                COMPILE_STACK_TOP.fixup_alt_jump
                  = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0;
                COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer;
-               COMPILE_STACK_TOP.regnum = shy ? -regnum : regnum;
+               COMPILE_STACK_TOP.regnum = regnum;
 
-               /* Do not push a
-                  start_memory for groups beyond the last one we can
-                  represent in the compiled pattern.  */
-               if (regnum <= MAX_REGNUM && !shy)
+               /* Do not push a start_memory for groups beyond the last one
+                  we can represent in the compiled pattern.  */
+               if (regnum <= MAX_REGNUM && regnum > 0)
                  BUF_PUSH_2 (start_memory, regnum);
 
                compile_stack.avail++;
@@ -3272,7 +3381,7 @@ regex_compile (pattern, size, syntax, bufp)
                /* We don't just want to restore into `regnum', because
                   later groups should continue to be numbered higher,
                   as in `(ab)c(de)' -- the second group is #2.  */
-               regnum_t this_group_regnum;
+               regnum_t regnum;
 
                compile_stack.avail--;
                begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset;
@@ -3281,7 +3390,7 @@ regex_compile (pattern, size, syntax, bufp)
                    ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1
                    : 0;
                laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset;
-               this_group_regnum = COMPILE_STACK_TOP.regnum;
+               regnum = COMPILE_STACK_TOP.regnum;
                /* If we've reached MAX_REGNUM groups, then this open
                   won't actually generate any code, so we'll have to
                   clear pending_exact explicitly.  */
@@ -3289,8 +3398,8 @@ regex_compile (pattern, size, syntax, bufp)
 
                /* We're at the end of the group, so now we know how many
                   groups were inside this one.  */
-               if (this_group_regnum <= MAX_REGNUM && this_group_regnum > 0)
-                 BUF_PUSH_2 (stop_memory, this_group_regnum);
+               if (regnum <= MAX_REGNUM && regnum > 0)
+                 BUF_PUSH_2 (stop_memory, regnum);
              }
              break;
 
@@ -3616,8 +3725,9 @@ regex_compile (pattern, size, syntax, bufp)
 
                reg = c - '0';
 
-               /* Can't back reference to a subexpression before its end.  */
-               if (reg > regnum || group_in_compile_stack (compile_stack, reg))
+               if (reg > bufp->re_nsub || reg < 1
+                   /* Can't back reference to a subexp before its end.  */
+                   || group_in_compile_stack (compile_stack, reg))
                  FREE_STACK_RETURN (REG_ESUBREG);
 
                laststart = b;
@@ -3677,17 +3787,22 @@ regex_compile (pattern, size, syntax, bufp)
          {
            int len;
 
-           if (! multibyte)
-             MAKE_CHAR_MULTIBYTE (c);
-           c = TRANSLATE (c);
-           if (target_multibyte)
+           if (multibyte)
              {
+               c = TRANSLATE (c);
                len = CHAR_STRING (c, b);
                b += len;
              }
            else
              {
-               MAKE_CHAR_UNIBYTE (c);
+               c1 = RE_CHAR_TO_MULTIBYTE (c);
+               if (! CHAR_BYTE8_P (c1))
+                 {
+                   re_wchar_t c2 = TRANSLATE (c1);
+
+                   if (c1 != c2 && (c1 = RE_CHAR_TO_UNIBYTE (c2)) >= 0)
+                     c = c1;
+                 }                   
                *b++ = c;
                len = 1;
              }
@@ -3714,11 +3829,6 @@ regex_compile (pattern, size, syntax, bufp)
   /* We have succeeded; set the length of the buffer.  */
   bufp->used = b - bufp->buffer;
 
-#ifdef emacs
-  /* Now the buffer is adjusted for the multibyteness of a target.  */
-  bufp->multibyte = bufp->target_multibyte;
-#endif
-
 #ifdef DEBUG
   if (debug > 0)
     {
@@ -3964,11 +4074,23 @@ analyse_first (p, pend, fastmap, multibyte)
 
        case exactn:
          if (fastmap)
-           /* If multibyte is nonzero, the first byte of each
-              character is an ASCII or a leading code.  Otherwise,
-              each byte is a character.  Thus, this works in both
-              cases. */
-           fastmap[p[1]] = 1;
+           {
+             /* If multibyte is nonzero, the first byte of each
+                character is an ASCII or a leading code.  Otherwise,
+                each byte is a character.  Thus, this works in both
+                cases. */
+             fastmap[p[1]] = 1;
+             if (! multibyte)
+               {
+                 /* For the case of matching this unibyte regex
+                    against multibyte, we must set a leading code of
+                    the corresponding multibyte character.  */
+                 int c = RE_CHAR_TO_MULTIBYTE (p[1]);
+
+                 if (! CHAR_BYTE8_P (c))
+                   fastmap[CHAR_LEADING_CODE (c)] = 1;
+               }
+           }
          break;
 
 
@@ -3983,12 +4105,8 @@ analyse_first (p, pend, fastmap, multibyte)
          if (!fastmap) break;
          {
            /* Chars beyond end of bitmap are possible matches.  */
-           /* In a multibyte case, the bitmap is used only for ASCII
-              characters.  */
-           int limit = multibyte ? 128 : (1 << BYTEWIDTH);
-
            for (j = CHARSET_BITMAP_SIZE (&p[-1]) * BYTEWIDTH;
-                j < limit; j++)
+                j < (1 << BYTEWIDTH); j++)
              fastmap[j] = 1;
          }
 
@@ -4001,17 +4119,21 @@ analyse_first (p, pend, fastmap, multibyte)
            if (!!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) ^ not)
              fastmap[j] = 1;
 
-         if ((not && multibyte)
-             /* Any leading code can possibly start a character
+#ifdef emacs
+         if (/* Any leading code can possibly start a character
                 which doesn't match the specified set of characters.  */
-             || (CHARSET_RANGE_TABLE_EXISTS_P (&p[-2])
-                 && CHARSET_RANGE_TABLE_BITS (&p[-2]) != 0))
-           /* If we can match a character class, we can match
-              any multibyte characters.  */
+             not
+             || 
+             /* If we can match a character class, we can match any
+                multibyte characters.  */
+             (CHARSET_RANGE_TABLE_EXISTS_P (&p[-2])
+              && CHARSET_RANGE_TABLE_BITS (&p[-2]) != 0))
+
            {
              if (match_any_multibyte_characters == false)
                {
-                 for (j = 0x80; j < (1 << BYTEWIDTH); j++)
+                 for (j = MIN_MULTIBYTE_LEADING_CODE;
+                      j <= MAX_MULTIBYTE_LEADING_CODE; j++)
                    fastmap[j] = 1;
                  match_any_multibyte_characters = true;
                }
@@ -4031,7 +4153,7 @@ analyse_first (p, pend, fastmap, multibyte)
 
              /* Extract the number of ranges in range table into COUNT.  */
              EXTRACT_NUMBER_AND_INCR (count, p);
-             for (; count > 0; count--, p += 2 * 3) /* XXX */
+             for (; count > 0; count--, p += 3)
                {
                  /* Extract the start and end of each range.  */
                  EXTRACT_CHARACTER (c, p);
@@ -4043,6 +4165,7 @@ analyse_first (p, pend, fastmap, multibyte)
                    fastmap[j] = 1;
                }
            }
+#endif
          break;
 
        case syntaxspec:
@@ -4065,20 +4188,18 @@ analyse_first (p, pend, fastmap, multibyte)
          if (!fastmap) break;
          not = (re_opcode_t)p[-1] == notcategoryspec;
          k = *p++;
-         for (j = (multibyte ? 127 : (1 << BYTEWIDTH)); j >= 0; j--)
+         for (j = (1 << BYTEWIDTH); j >= 0; j--)
            if ((CHAR_HAS_CATEGORY (j, k)) ^ not)
              fastmap[j] = 1;
 
-         if (multibyte)
+         /* Any leading code can possibly start a character which
+            has or doesn't has the specified category.  */
+         if (match_any_multibyte_characters == false)
            {
-             /* Any character set can possibly contain a character
-                whose category is K (or not).  */
-             if (match_any_multibyte_characters == false)
-               {
-                 for (j = 0x80; j < (1 << BYTEWIDTH); j++)
-                   fastmap[j] = 1;
-                 match_any_multibyte_characters = true;
-               }
+             for (j = MIN_MULTIBYTE_LEADING_CODE;
+                  j <= MAX_MULTIBYTE_LEADING_CODE; j++)
+               fastmap[j] = 1;
+             match_any_multibyte_characters = true;
            }
          break;
 
@@ -4329,9 +4450,8 @@ re_search_2 (bufp, str1, size1, str2, size2, startpos, range, regs, stop)
   int total_size = size1 + size2;
   int endpos = startpos + range;
   boolean anchored_start;
-  /* Nonzero if BUFP is setup for multibyte characters.  We are sure
-     that it is the same as RE_TARGET_MULTIBYTE_P (bufp).  */
-  const boolean multibyte = RE_MULTIBYTE_P (bufp);
+  /* Nonzero if we are searching multibyte string.  */
+  const boolean multibyte = RE_TARGET_MULTIBYTE_P (bufp);
 
   /* Check for out-of-range STARTPOS.  */
   if (startpos < 0 || startpos > total_size)
@@ -4437,10 +4557,14 @@ re_search_2 (bufp, str1, size1, str2, size2, startpos, range, regs, stop)
                  else
                    while (range > lim)
                      {
+                       register re_wchar_t ch, translated;
+
                        buf_ch = *d;
-                       MAKE_CHAR_MULTIBYTE (buf_ch);
-                       buf_ch = RE_TRANSLATE (translate, buf_ch);
-                       MAKE_CHAR_UNIBYTE (buf_ch);
+                       ch = RE_CHAR_TO_MULTIBYTE (buf_ch);
+                       translated = RE_TRANSLATE (translate, ch);
+                       if (translated != ch
+                           && (ch = RE_CHAR_TO_UNIBYTE (translated)) >= 0)
+                         buf_ch = ch;
                        if (fastmap[buf_ch])
                          break;
                        d++;
@@ -4484,7 +4608,15 @@ re_search_2 (bufp, str1, size1, str2, size2, startpos, range, regs, stop)
                }
              else
                {
-                 if (! fastmap[TRANSLATE (*d)])
+                 register re_wchar_t ch, translated;
+
+                 buf_ch = *d;
+                 ch = RE_CHAR_TO_MULTIBYTE (buf_ch);
+                 translated = TRANSLATE (ch);
+                 if (translated != ch
+                     && (ch = RE_CHAR_TO_UNIBYTE (translated)) >= 0)
+                   buf_ch = ch;
+                 if (! fastmap[TRANSLATE (buf_ch)])
                    goto advance;
                }
            }
@@ -4497,11 +4629,6 @@ re_search_2 (bufp, str1, size1, str2, size2, startpos, range, regs, stop)
 
       val = re_match_2_internal (bufp, string1, size1, string2, size2,
                                 startpos, regs, stop);
-#ifndef REGEX_MALLOC
-# ifdef C_ALLOCA
-      alloca (0);
-# endif
-#endif
 
       if (val >= 0)
        return startpos;
@@ -4765,11 +4892,11 @@ mutually_exclusive_p (bufp, p1, p2)
       {
        register re_wchar_t c
          = (re_opcode_t) *p2 == endline ? '\n'
-         : RE_STRING_CHAR (p2 + 2, pend - p2 - 2);
+         : RE_STRING_CHAR (p2 + 2, pend - p2 - 2, multibyte);
 
        if ((re_opcode_t) *p1 == exactn)
          {
-           if (c != RE_STRING_CHAR (p1 + 2, pend - p1 - 2))
+           if (c != RE_STRING_CHAR (p1 + 2, pend - p1 - 2, multibyte))
              {
                DEBUG_PRINT3 ("  '%c' != '%c' => fast loop.\n", c, p1[2]);
                return 1;
@@ -4938,9 +5065,6 @@ re_match (bufp, string, size, pos, regs)
 {
   int result = re_match_2_internal (bufp, NULL, 0, (re_char*) string, size,
                                    pos, regs, size);
-# if defined C_ALLOCA && !defined REGEX_MALLOC
-  alloca (0);
-# endif
   return result;
 }
 WEAK_ALIAS (__re_match, re_match)
@@ -4986,30 +5110,10 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
   result = re_match_2_internal (bufp, (re_char*) string1, size1,
                                (re_char*) string2, size2,
                                pos, regs, stop);
-#if defined C_ALLOCA && !defined REGEX_MALLOC
-  alloca (0);
-#endif
   return result;
 }
 WEAK_ALIAS (__re_match_2, re_match_2)
 
-#ifdef emacs
-#define TRANSLATE_VIA_MULTIBYTE(c)     \
-  do {                                 \
-    if (multibyte)                     \
-      (c) = TRANSLATE (c);             \
-    else                               \
-      {                                        \
-       MAKE_CHAR_MULTIBYTE (c);        \
-       (c) = TRANSLATE (c);            \
-       MAKE_CHAR_UNIBYTE (c);          \
-      }                                        \
-  } while (0)
-
-#else
-#define TRANSLATE_VIA_MULTIBYTE(c) ((c) = TRANSLATE (c))
-#endif
-
 
 /* This is a separate function so that we can force an alloca cleanup
    afterwards.  */
@@ -5050,10 +5154,12 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
   /* We use this to map every character in the string. */
   RE_TRANSLATE_TYPE translate = bufp->translate;
 
-  /* Nonzero if BUFP is setup for multibyte characters.  We are sure
-     that it is the same as RE_TARGET_MULTIBYTE_P (bufp).  */
+  /* Nonzero if BUFP is setup from a multibyte regex.  */
   const boolean multibyte = RE_MULTIBYTE_P (bufp);
 
+  /* Nonzero if STRING1/STRING2 are multibyte.  */
+  const boolean target_multibyte = RE_TARGET_MULTIBYTE_P (bufp);
+
   /* Failure point stack.  Each place that can handle a failure further
      down the line pushes a failure point on this stack.  It consists of
      regstart, and regend for all registers corresponding to
@@ -5433,14 +5539,20 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
            while (--mcnt);
 #else  /* emacs */
          /* The cost of testing `translate' is comparatively small.  */
-         if (multibyte)
+         if (target_multibyte)
            do
              {
                int pat_charlen, buf_charlen;
-               unsigned int pat_ch, buf_ch;
+               int pat_ch, buf_ch;
 
                PREFETCH ();
-               pat_ch = STRING_CHAR_AND_LENGTH (p, pend - p, pat_charlen);
+               if (multibyte)
+                 pat_ch = STRING_CHAR_AND_LENGTH (p, pend - p, pat_charlen);
+               else
+                 {
+                   pat_ch = RE_CHAR_TO_MULTIBYTE (*p);
+                   pat_charlen = 1;
+                 }
                buf_ch = STRING_CHAR_AND_LENGTH (d, dend - d, buf_charlen);
 
                if (TRANSLATE (buf_ch) != pat_ch)
@@ -5457,16 +5569,38 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
          else
            do
              {
-               unsigned int buf_ch;
+               int pat_charlen, buf_charlen;
+               int pat_ch, buf_ch;
 
                PREFETCH ();
-               buf_ch = *d++;
-               TRANSLATE_VIA_MULTIBYTE (buf_ch);
-               if (buf_ch != *p++)
+               if (multibyte)
+                 {
+                   pat_ch = STRING_CHAR_AND_LENGTH (p, pend - p, pat_charlen);
+                   if (CHAR_BYTE8_P (pat_ch))
+                     pat_ch = CHAR_TO_BYTE8 (pat_ch);
+                   else
+                     pat_ch = RE_CHAR_TO_UNIBYTE (pat_ch);
+                 }
+               else
+                 {
+                   pat_ch = *p;
+                   pat_charlen = 1;
+                 }
+               buf_ch = RE_CHAR_TO_MULTIBYTE (*d);
+               if (! CHAR_BYTE8_P (buf_ch))
+                 {
+                   buf_ch = TRANSLATE (buf_ch);
+                   buf_ch = RE_CHAR_TO_UNIBYTE (buf_ch);
+                   if (buf_ch < 0)
+                     buf_ch = *d;
+                 }
+               if (buf_ch != pat_ch)
                  {
                    d = dfail;
                    goto fail;
                  }
+               p += pat_charlen;
+               d++;
              }
            while (--mcnt);
 #endif
@@ -5482,7 +5616,8 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
            DEBUG_PRINT1 ("EXECUTING anychar.\n");
 
            PREFETCH ();
-           buf_ch = RE_STRING_CHAR_AND_LENGTH (d, dend - d, buf_charlen);
+           buf_ch = RE_STRING_CHAR_AND_LENGTH (d, dend - d, buf_charlen,
+                                               target_multibyte);
            buf_ch = TRANSLATE (buf_ch);
 
            if ((!(bufp->syntax & RE_DOT_NEWLINE)
@@ -5526,10 +5661,30 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
              }
 
            PREFETCH ();
-           c = RE_STRING_CHAR_AND_LENGTH (d, dend - d, len);
-           TRANSLATE_VIA_MULTIBYTE (c); /* The character to match.  */
+           c = RE_STRING_CHAR_AND_LENGTH (d, dend - d, len, target_multibyte);
+           if (target_multibyte)
+             {
+               int c1;
 
-           if (! multibyte || IS_REAL_ASCII (c))
+               c = TRANSLATE (c);
+               c1 = RE_CHAR_TO_UNIBYTE (c);
+               if (c1 >= 0)
+                 c = c1;
+             }
+           else
+             {
+               int c1 = RE_CHAR_TO_MULTIBYTE (c);
+
+               if (! CHAR_BYTE8_P (c1))
+                 {
+                   c1 = TRANSLATE (c1);
+                   c1 = RE_CHAR_TO_UNIBYTE (c1);
+                   if (c1 >= 0)
+                     c = c1;
+                 }
+             }
+
+           if (c < (1 << BYTEWIDTH))
              {                 /* Lookup bitmap.  */
                /* Cast to `unsigned' instead of `unsigned char' in
                   case the bit list is a full 32 bytes long.  */
@@ -5669,7 +5824,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
                /* Compare that many; failure if mismatch, else move
                   past them.  */
                if (RE_TRANSLATE_P (translate)
-                   ? bcmp_translate (d, d2, mcnt, translate, multibyte)
+                   ? bcmp_translate (d, d2, mcnt, translate, target_multibyte)
                    : memcmp (d, d2, mcnt))
                  {
                    d = dfail;
@@ -6096,7 +6251,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
              UPDATE_SYNTAX_TABLE (charpos);
 #endif
              PREFETCH ();
-             c2 = RE_STRING_CHAR (d, dend - d);
+             c2 = RE_STRING_CHAR (d, dend - d, target_multibyte);
              s2 = SYNTAX (c2);
 
              /* Case 2: S2 is neither Sword nor Ssymbol. */
@@ -6149,7 +6304,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
              if (!AT_STRINGS_END (d))
                {
                  PREFETCH_NOLIMIT ();
-                 c2 = RE_STRING_CHAR (d, dend - d);
+                 c2 = RE_STRING_CHAR (d, dend - d, target_multibyte);
 #ifdef emacs
                  UPDATE_SYNTAX_TABLE_FORWARD (charpos + 1);
 #endif
@@ -6290,11 +6445,11 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
    bytes; nonzero otherwise.  */
 
 static int
-bcmp_translate (s1, s2, len, translate, multibyte)
+bcmp_translate (s1, s2, len, translate, target_multibyte)
      re_char *s1, *s2;
      register int len;
      RE_TRANSLATE_TYPE translate;
-     const int multibyte;
+     const int target_multibyte;
 {
   register re_char *p1 = s1, *p2 = s2;
   re_char *p1_end = s1 + len;
@@ -6625,12 +6780,15 @@ regexec (preg, string, nmatch, pmatch, eflags)
 WEAK_ALIAS (__regexec, regexec)
 
 
-/* Returns a message corresponding to an error code, ERRCODE, returned
-   from either regcomp or regexec.   We don't use PREG here.  */
+/* Returns a message corresponding to an error code, ERR_CODE, returned
+   from either regcomp or regexec.   We don't use PREG here.
+
+   ERR_CODE was previously called ERRCODE, but that name causes an
+   error with msvc8 compiler.  */
 
 size_t
-regerror (errcode, preg, errbuf, errbuf_size)
-    int errcode;
+regerror (err_code, preg, errbuf, errbuf_size)
+    int err_code;
     const regex_t *preg;
     char *errbuf;
     size_t errbuf_size;
@@ -6638,15 +6796,15 @@ regerror (errcode, preg, errbuf, errbuf_size)
   const char *msg;
   size_t msg_size;
 
-  if (errcode < 0
-      || errcode >= (sizeof (re_error_msgid) / sizeof (re_error_msgid[0])))
+  if (err_code < 0
+      || err_code >= (sizeof (re_error_msgid) / sizeof (re_error_msgid[0])))
     /* Only error codes returned by the rest of the code should be passed
        to this routine.  If we are given anything else, or if other regex
        code generates an invalid error code, then the program has a bug.
        Dump core so we can fix it.  */
     abort ();
 
-  msg = gettext (re_error_msgid[errcode]);
+  msg = gettext (re_error_msgid[err_code]);
 
   msg_size = strlen (msg) + 1; /* Includes the null.  */