(inhibit_pre_post_conversion): Removed (unused).
[bpt/emacs.git] / src / regex.c
index 9974b2d..453ca3d 100644 (file)
@@ -33,9 +33,6 @@
   #pragma alloca
 #endif
 
-#undef _GNU_SOURCE
-#define _GNU_SOURCE
-
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
 # define POS_AS_IN_BUFFER(p) ((p) + (NILP (re_match_object) || BUFFERP (re_match_object)))
 
 # define RE_MULTIBYTE_P(bufp) ((bufp)->multibyte)
+# define RE_TARGET_MULTIBYTE_P(bufp) ((bufp)->target_multibyte)
 # define RE_STRING_CHAR(p, s) \
   (multibyte ? (STRING_CHAR (p, s)) : (*(p)))
 # define RE_STRING_CHAR_AND_LENGTH(p, s, len) \
   (multibyte ? (STRING_CHAR_AND_LENGTH (p, s, len)) : ((len) = 1, *(p)))
 
-/* Set C a (possibly 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)                                                     \
-       {                                                               \
-        re_char *dtemp = (p) == (str2) ? (end1) : (p);                 \
-        re_char *dlimit = ((p) > (str2) && (p) <= (end2)) ? (str2) : (str1); \
-        while (dtemp-- > dlimit && !CHAR_HEAD_P (*dtemp));             \
-        c = STRING_CHAR (dtemp, (p) - dtemp);                          \
-       }                                                               \
-     else                                                              \
-       (c = ((p) == (str2) ? (end1) : (p))[-1]);                       \
+/* 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)                                                          \
+      {                                                                             \
+       re_char *dtemp = (p) == (str2) ? (end1) : (p);                       \
+       re_char *dlimit = ((p) > (str2) && (p) <= (end2)) ? (str2) : (str1); \
+       while (dtemp-- > dlimit && !CHAR_HEAD_P (*dtemp));                   \
+       c = STRING_CHAR (dtemp, (p) - dtemp);                                \
+      }                                                                             \
+    else                                                                    \
+      {                                                                             \
+       (c = ((p) == (str2) ? (end1) : (p))[-1]);                            \
+       MAKE_CHAR_MULTIBYTE (c);                                             \
+      }                                                                             \
   } while (0)
 
+/* Set C a (possibly converted to multibyte) character at P, and set
+   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);  \
+    else                                       \
+      {                                                \
+       c = *p;                                 \
+       len = 1;                                \
+       MAKE_CHAR_MULTIBYTE (c);                \
+      }                                                \
+   } while (0)
 
 #else  /* not emacs */
 
@@ -233,11 +247,13 @@ enum syntaxcode { Swhitespace = 0, Sword = 1 };
 # define CHARSET_LEADING_CODE_BASE(c) 0
 # define MAX_MULTIBYTE_LENGTH 1
 # define RE_MULTIBYTE_P(x) 0
+# define RE_TARGET_MULTIBYTE_P(x) 0
 # define WORD_BOUNDARY_P(c1, c2) (0)
 # define CHAR_HEAD_P(p) (1)
 # define SINGLE_BYTE_CHAR_P(c) (1)
 # define SAME_CHARSET_P(c1, c2) (1)
 # 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 CHAR_STRING(c, s) (*(s) = (c), 1)
@@ -245,9 +261,15 @@ enum syntaxcode { Swhitespace = 0, Sword = 1 };
 # define RE_STRING_CHAR_AND_LENGTH STRING_CHAR_AND_LENGTH
 # 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)     \
+  (c = *p, len = 1)
 # 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 */
 
 #ifndef RE_TRANSLATE
@@ -453,7 +475,7 @@ init_syntax_once ()
 #  ifdef __GNUC__
 #   define alloca __builtin_alloca
 #  else /* not __GNUC__ */
-#   if HAVE_ALLOCA_H
+#   ifdef HAVE_ALLOCA_H
 #    include <alloca.h>
 #   endif /* HAVE_ALLOCA_H */
 #  endif /* not __GNUC__ */
@@ -924,50 +946,49 @@ print_partial_compiled_pattern (start, end)
 
   if (start == NULL)
     {
-      printf ("(null)\n");
+      fprintf (stderr, "(null)\n");
       return;
     }
 
   /* Loop over pattern commands.  */
   while (p < pend)
     {
-      printf ("%d:\t", p - start);
+      fprintf (stderr, "%d:\t", p - start);
 
       switch ((re_opcode_t) *p++)
        {
        case no_op:
-         printf ("/no_op");
+         fprintf (stderr, "/no_op");
          break;
 
        case succeed:
-         printf ("/succeed");
+         fprintf (stderr, "/succeed");
          break;
 
        case exactn:
          mcnt = *p++;
-         printf ("/exactn/%d", mcnt);
+         fprintf (stderr, "/exactn/%d", mcnt);
          do
            {
-             putchar ('/');
-             putchar (*p++);
+             fprintf (stderr, "/%c", *p++);
            }
          while (--mcnt);
          break;
 
        case start_memory:
-         printf ("/start_memory/%d", *p++);
+         fprintf (stderr, "/start_memory/%d", *p++);
          break;
 
        case stop_memory:
-         printf ("/stop_memory/%d", *p++);
+         fprintf (stderr, "/stop_memory/%d", *p++);
          break;
 
        case duplicate:
-         printf ("/duplicate/%d", *p++);
+         fprintf (stderr, "/duplicate/%d", *p++);
          break;
 
        case anychar:
-         printf ("/anychar");
+         fprintf (stderr, "/anychar");
          break;
 
        case charset:
@@ -978,7 +999,7 @@ print_partial_compiled_pattern (start, end)
            int length = CHARSET_BITMAP_SIZE (p - 1);
            int has_range_table = CHARSET_RANGE_TABLE_EXISTS_P (p - 1);
 
-           printf ("/charset [%s",
+           fprintf (stderr, "/charset [%s",
                    (re_opcode_t) *(p - 1) == charset_not ? "^" : "");
 
            assert (p + *p < pend);
@@ -990,33 +1011,33 @@ print_partial_compiled_pattern (start, end)
                  /* Are we starting a range?  */
                  if (last + 1 == c && ! in_range)
                    {
-                     putchar ('-');
+                     fprintf (stderr, "-");
                      in_range = 1;
                    }
                  /* Have we broken a range?  */
                  else if (last + 1 != c && in_range)
                    {
-                     putchar (last);
+                     fprintf (stderr, "%c", last);
                      in_range = 0;
                    }
 
                  if (! in_range)
-                   putchar (c);
+                   fprintf (stderr, "%c", c);
 
                  last = c;
              }
 
            if (in_range)
-             putchar (last);
+             fprintf (stderr, "%c", last);
 
-           putchar (']');
+           fprintf (stderr, "]");
 
            p += 1 + length;
 
            if (has_range_table)
              {
                int count;
-               printf ("has-range-table");
+               fprintf (stderr, "has-range-table");
 
                /* ??? Should print the range table; for now, just skip it.  */
                p += 2;         /* skip range table bits */
@@ -1027,130 +1048,130 @@ print_partial_compiled_pattern (start, end)
          break;
 
        case begline:
-         printf ("/begline");
+         fprintf (stderr, "/begline");
          break;
 
        case endline:
-         printf ("/endline");
+         fprintf (stderr, "/endline");
          break;
 
        case on_failure_jump:
          extract_number_and_incr (&mcnt, &p);
-         printf ("/on_failure_jump to %d", p + mcnt - start);
+         fprintf (stderr, "/on_failure_jump to %d", p + mcnt - start);
          break;
 
        case on_failure_keep_string_jump:
          extract_number_and_incr (&mcnt, &p);
-         printf ("/on_failure_keep_string_jump to %d", p + mcnt - start);
+         fprintf (stderr, "/on_failure_keep_string_jump to %d", p + mcnt - start);
          break;
 
        case on_failure_jump_nastyloop:
          extract_number_and_incr (&mcnt, &p);
-         printf ("/on_failure_jump_nastyloop to %d", p + mcnt - start);
+         fprintf (stderr, "/on_failure_jump_nastyloop to %d", p + mcnt - start);
          break;
 
        case on_failure_jump_loop:
          extract_number_and_incr (&mcnt, &p);
-         printf ("/on_failure_jump_loop to %d", p + mcnt - start);
+         fprintf (stderr, "/on_failure_jump_loop to %d", p + mcnt - start);
          break;
 
        case on_failure_jump_smart:
          extract_number_and_incr (&mcnt, &p);
-         printf ("/on_failure_jump_smart to %d", p + mcnt - start);
+         fprintf (stderr, "/on_failure_jump_smart to %d", p + mcnt - start);
          break;
 
        case jump:
          extract_number_and_incr (&mcnt, &p);
-         printf ("/jump to %d", p + mcnt - start);
+         fprintf (stderr, "/jump to %d", p + mcnt - start);
          break;
 
        case succeed_n:
          extract_number_and_incr (&mcnt, &p);
          extract_number_and_incr (&mcnt2, &p);
-         printf ("/succeed_n to %d, %d times", p - 2 + mcnt - start, mcnt2);
+         fprintf (stderr, "/succeed_n to %d, %d times", p - 2 + mcnt - start, mcnt2);
          break;
 
        case jump_n:
          extract_number_and_incr (&mcnt, &p);
          extract_number_and_incr (&mcnt2, &p);
-         printf ("/jump_n to %d, %d times", p - 2 + mcnt - start, mcnt2);
+         fprintf (stderr, "/jump_n to %d, %d times", p - 2 + mcnt - start, mcnt2);
          break;
 
        case set_number_at:
          extract_number_and_incr (&mcnt, &p);
          extract_number_and_incr (&mcnt2, &p);
-         printf ("/set_number_at location %d to %d", p - 2 + mcnt - start, mcnt2);
+         fprintf (stderr, "/set_number_at location %d to %d", p - 2 + mcnt - start, mcnt2);
          break;
 
        case wordbound:
-         printf ("/wordbound");
+         fprintf (stderr, "/wordbound");
          break;
 
        case notwordbound:
-         printf ("/notwordbound");
+         fprintf (stderr, "/notwordbound");
          break;
 
        case wordbeg:
-         printf ("/wordbeg");
+         fprintf (stderr, "/wordbeg");
          break;
 
        case wordend:
-         printf ("/wordend");
+         fprintf (stderr, "/wordend");
 
        case syntaxspec:
-         printf ("/syntaxspec");
+         fprintf (stderr, "/syntaxspec");
          mcnt = *p++;
-         printf ("/%d", mcnt);
+         fprintf (stderr, "/%d", mcnt);
          break;
 
        case notsyntaxspec:
-         printf ("/notsyntaxspec");
+         fprintf (stderr, "/notsyntaxspec");
          mcnt = *p++;
-         printf ("/%d", mcnt);
+         fprintf (stderr, "/%d", mcnt);
          break;
 
 # ifdef emacs
        case before_dot:
-         printf ("/before_dot");
+         fprintf (stderr, "/before_dot");
          break;
 
        case at_dot:
-         printf ("/at_dot");
+         fprintf (stderr, "/at_dot");
          break;
 
        case after_dot:
-         printf ("/after_dot");
+         fprintf (stderr, "/after_dot");
          break;
 
        case categoryspec:
-         printf ("/categoryspec");
+         fprintf (stderr, "/categoryspec");
          mcnt = *p++;
-         printf ("/%d", mcnt);
+         fprintf (stderr, "/%d", mcnt);
          break;
 
        case notcategoryspec:
-         printf ("/notcategoryspec");
+         fprintf (stderr, "/notcategoryspec");
          mcnt = *p++;
-         printf ("/%d", mcnt);
+         fprintf (stderr, "/%d", mcnt);
          break;
 # endif /* emacs */
 
        case begbuf:
-         printf ("/begbuf");
+         fprintf (stderr, "/begbuf");
          break;
 
        case endbuf:
-         printf ("/endbuf");
+         fprintf (stderr, "/endbuf");
          break;
 
        default:
-         printf ("?%d", *(p-1));
+         fprintf (stderr, "?%d", *(p-1));
        }
 
-      putchar ('\n');
+      fprintf (stderr, "\n");
     }
 
-  printf ("%d:\tend of pattern.\n", p - start);
+  fprintf (stderr, "%d:\tend of pattern.\n", p - start);
 }
 
 
@@ -1523,22 +1544,25 @@ do {                                                                    \
 /* Check that we are not stuck in an infinite loop.  */
 #define CHECK_INFINITE_LOOP(pat_cur, string_place)                     \
 do {                                                                   \
-  int failure = TOP_FAILURE_HANDLE();                                  \
+  int failure = TOP_FAILURE_HANDLE ();                                 \
   /* Check for infinite matching loops */                              \
-  while (failure > 0 &&                                                        \
-        (FAILURE_STR (failure) == string_place                         \
-         || FAILURE_STR (failure) == NULL))                            \
+  while (failure > 0                                                   \
+        && (FAILURE_STR (failure) == string_place                      \
+            || FAILURE_STR (failure) == NULL))                         \
     {                                                                  \
       assert (FAILURE_PAT (failure) >= bufp->buffer                    \
              && FAILURE_PAT (failure) <= bufp->buffer + bufp->used);   \
       if (FAILURE_PAT (failure) == pat_cur)                            \
-       goto fail;                                                      \
+       {                                                               \
+         cycle = 1;                                                    \
+         break;                                                        \
+       }                                                               \
       DEBUG_PRINT2 ("  Other pattern: %p\n", FAILURE_PAT (failure));   \
       failure = NEXT_FAILURE_HANDLE(failure);                          \
     }                                                                  \
   DEBUG_PRINT2 ("  Other string: %p\n", FAILURE_STR (failure));                \
 } while (0)
-    
+
 /* Push the information about the state we will need
    if we ever fail back to it.
 
@@ -1660,17 +1684,9 @@ static re_char *skip_one_char _RE_ARGS ((re_char *p));
 static int analyse_first _RE_ARGS ((re_char *p, re_char *pend,
                                    char *fastmap, const int multibyte));
 
-/* Fetch the next character in the uncompiled pattern---translating it
-   if necessary.  */
-#define PATFETCH(c)                                                    \
-  do {                                                                 \
-    PATFETCH_RAW (c);                                                  \
-    c = TRANSLATE (c);                                                 \
-  } while (0)
-
 /* Fetch the next character in the uncompiled pattern, with no
    translation.  */
-#define PATFETCH_RAW(c)                                                        \
+#define PATFETCH(c)                                                    \
   do {                                                                 \
     int len;                                                           \
     if (p == pend) return REG_EEND;                                    \
@@ -1818,7 +1834,7 @@ static int analyse_first _RE_ARGS ((re_char *p, re_char *pend,
 
 /* But patterns can have more than `MAX_REGNUM' registers.  We just
    ignore the excess.  */
-typedef unsigned regnum_t;
+typedef int regnum_t;
 
 
 /* Macros for the compile stack.  */
@@ -1853,7 +1869,17 @@ typedef struct
 /* The next available element.  */
 #define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail])
 
-
+/* Explicit quit checking is only used on NTemacs.  */
+#if defined WINDOWSNT && defined emacs && defined QUIT
+extern int immediate_quit;
+# define IMMEDIATE_QUIT_CHECK                  \
+    do {                                       \
+      if (immediate_quit) QUIT;                        \
+    } while (0)
+#else
+# define IMMEDIATE_QUIT_CHECK    ((void)0)
+#endif
+\f
 /* Structure to manage work area for range table.  */
 struct range_table_work_area
 {
@@ -1863,21 +1889,19 @@ struct range_table_work_area
   int bits;                    /* flag to record character classes */
 };
 
-/* Make sure that WORK_AREA can hold more N multibyte characters.  */
-#define EXTEND_RANGE_TABLE_WORK_AREA(work_area, n)                       \
-  do {                                                                   \
-    if (((work_area).used + (n)) * sizeof (int) > (work_area).allocated)  \
-      {                                                                          \
-       (work_area).allocated += 16 * sizeof (int);                       \
-       if ((work_area).table)                                            \
-         (work_area).table                                               \
-           = (int *) realloc ((work_area).table, (work_area).allocated); \
-       else                                                              \
-         (work_area).table                                               \
-           = (int *) malloc ((work_area).allocated);                     \
-       if ((work_area).table == 0)                                       \
-         FREE_STACK_RETURN (REG_ESPACE);                                 \
-      }                                                                          \
+/* Make sure that WORK_AREA can hold more N multibyte characters.
+   This is used only in set_image_of_range and set_image_of_range_1.
+   It expects WORK_AREA to be a pointer.
+   If it can't get the space, it returns from the surrounding function.  */
+
+#define EXTEND_RANGE_TABLE(work_area, n)                               \
+  do {                                                                 \
+    if (((work_area).used + (n)) * sizeof (int) > (work_area).allocated) \
+      {                                                                        \
+        extend_range_table_work_area (&work_area);                     \
+        if ((work_area).table == 0)                                    \
+          return (REG_ESPACE);                                         \
+      }                                                                        \
   } while (0)
 
 #define SET_RANGE_TABLE_WORK_AREA_BIT(work_area, bit)          \
@@ -1895,7 +1919,7 @@ struct range_table_work_area
 /* Set a range (RANGE_START, RANGE_END) to WORK_AREA.  */
 #define SET_RANGE_TABLE_WORK_AREA(work_area, range_start, range_end)   \
   do {                                                                 \
-    EXTEND_RANGE_TABLE_WORK_AREA ((work_area), 2);                     \
+    EXTEND_RANGE_TABLE ((work_area), 2);                               \
     (work_area).table[(work_area).used++] = (range_start);             \
     (work_area).table[(work_area).used++] = (range_end);               \
   } while (0)
@@ -1911,29 +1935,69 @@ struct range_table_work_area
 #define RANGE_TABLE_WORK_USED(work_area) ((work_area).used)
 #define RANGE_TABLE_WORK_BITS(work_area) ((work_area).bits)
 #define RANGE_TABLE_WORK_ELT(work_area, i) ((work_area).table[i])
-
+\f
 
 /* Set the bit for character C in a list.  */
 #define SET_LIST_BIT(c) (b[((c)) / BYTEWIDTH] |= 1 << ((c) % BYTEWIDTH))
 
 
+#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.
+
+   Implementation note: It is better to implement this fairly big
+   macro 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);       \
+  } while (0)
+
+#endif /* emacs */
+
 /* Get the next unsigned number in the uncompiled pattern.  */
 #define GET_UNSIGNED_NUMBER(num)                                       \
  do { if (p != pend)                                                   \
      {                                                                 \
        PATFETCH (c);                                                   \
+       if (c == ' ')                                                   \
+        FREE_STACK_RETURN (REG_BADBR);                                 \
        while ('0' <= c && c <= '9')                                    \
         {                                                              \
+           int prev;                                                   \
           if (num < 0)                                                 \
-             num = 0;                                                  \
+            num = 0;                                                   \
+          prev = num;                                                  \
           num = num * 10 + c - '0';                                    \
+          if (num / 10 != prev)                                        \
+            FREE_STACK_RETURN (REG_BADBR);                             \
           if (p == pend)                                               \
-             break;                                                    \
+            break;                                                     \
           PATFETCH (c);                                                \
         }                                                              \
+       if (c == ' ')                                                   \
+        FREE_STACK_RETURN (REG_BADBR);                                 \
        }                                                               \
     } while (0)
-
+\f
 #if WIDE_CHAR_SUPPORT
 /* The GNU C library provides support for user-defined character classes
    and the functions from ISO C amendement 1.  */
@@ -2046,17 +2110,258 @@ re_wctype_to_bit (cc)
     }
 }
 #endif
+\f
+/* Filling in the work area of a range.  */
 
-/* Explicit quit checking is only used on NTemacs.  */
-#if defined WINDOWSNT && defined emacs && defined QUIT
-extern int immediate_quit;
-# define IMMEDIATE_QUIT_CHECK                  \
-    do {                                       \
-      if (immediate_quit) QUIT;                        \
-    } while (0)
-#else
-# define IMMEDIATE_QUIT_CHECK    ((void)0)
+/* Actually extend the space in WORK_AREA.  */
+
+static void
+extend_range_table_work_area (work_area)
+     struct range_table_work_area *work_area;
+{
+  work_area->allocated += 16 * sizeof (int);
+  if (work_area->table)
+    work_area->table
+      = (int *) realloc (work_area->table, work_area->allocated);
+  else
+    work_area->table
+      = (int *) malloc (work_area->allocated);
+}
+
+#if 0
+#ifdef emacs
+
+/* Carefully find the ranges of codes that are equivalent
+   under case conversion to the range start..end when passed through
+   TRANSLATE.  Handle the case where non-letters can come in between
+   two upper-case letters (which happens in Latin-1).
+   Also handle the case of groups of more than 2 case-equivalent chars.
+
+   The basic method is to look at consecutive characters and see
+   if they can form a run that can be handled as one.
+
+   Returns -1 if successful, REG_ESPACE if ran out of space.  */
+
+static int
+set_image_of_range_1 (work_area, start, end, translate)
+     RE_TRANSLATE_TYPE translate;
+     struct range_table_work_area *work_area;
+     re_wchar_t start, end;
+{
+  /* `one_case' indicates a character, or a run of characters,
+     each of which is an isolate (no case-equivalents).
+     This includes all ASCII non-letters.
+
+     `two_case' indicates a character, or a run of characters,
+     each of which has two case-equivalent forms.
+     This includes all ASCII letters.
+
+     `strange' indicates a character that has more than one
+     case-equivalent.  */
+
+  enum case_type {one_case, two_case, strange};
+
+  /* Describe the run that is in progress,
+     which the next character can try to extend.
+     If run_type is strange, that means there really is no run.
+     If run_type is one_case, then run_start...run_end is the run.
+     If run_type is two_case, then the run is run_start...run_end,
+     and the case-equivalents end at run_eqv_end.  */
+
+  enum case_type run_type = strange;
+  int run_start, run_end, run_eqv_end;
+
+  Lisp_Object eqv_table;
+
+  if (!RE_TRANSLATE_P (translate))
+    {
+      EXTEND_RANGE_TABLE (work_area, 2);
+      work_area->table[work_area->used++] = (start);
+      work_area->table[work_area->used++] = (end);
+      return -1;
+    }
+
+  eqv_table = XCHAR_TABLE (translate)->extras[2];
+
+  for (; start <= end; start++)
+    {
+      enum case_type this_type;
+      int eqv = RE_TRANSLATE (eqv_table, start);
+      int minchar, maxchar;
+
+      /* Classify this character */
+      if (eqv == start)
+       this_type = one_case;
+      else if (RE_TRANSLATE (eqv_table, eqv) == start)
+       this_type = two_case;
+      else
+       this_type = strange;
+
+      if (start < eqv)
+       minchar = start, maxchar = eqv;
+      else
+       minchar = eqv, maxchar = start;
+
+      /* Can this character extend the run in progress?  */
+      if (this_type == strange || this_type != run_type
+         || !(minchar == run_end + 1
+              && (run_type == two_case
+                  ? maxchar == run_eqv_end + 1 : 1)))
+       {
+         /* No, end the run.
+            Record each of its equivalent ranges.  */
+         if (run_type == one_case)
+           {
+             EXTEND_RANGE_TABLE (work_area, 2);
+             work_area->table[work_area->used++] = run_start;
+             work_area->table[work_area->used++] = run_end;
+           }
+         else if (run_type == two_case)
+           {
+             EXTEND_RANGE_TABLE (work_area, 4);
+             work_area->table[work_area->used++] = run_start;
+             work_area->table[work_area->used++] = run_end;
+             work_area->table[work_area->used++]
+               = RE_TRANSLATE (eqv_table, run_start);
+             work_area->table[work_area->used++]
+               = RE_TRANSLATE (eqv_table, run_end);
+           }
+         run_type = strange;
+       }
+
+      if (this_type == strange)
+       {
+         /* For a strange character, add each of its equivalents, one
+            by one.  Don't start a range.  */
+         do
+           {
+             EXTEND_RANGE_TABLE (work_area, 2);
+             work_area->table[work_area->used++] = eqv;
+             work_area->table[work_area->used++] = eqv;
+             eqv = RE_TRANSLATE (eqv_table, eqv);
+           }
+         while (eqv != start);
+       }
+
+      /* Add this char to the run, or start a new run.  */
+      else if (run_type == strange)
+       {
+         /* Initialize a new range.  */
+         run_type = this_type;
+         run_start = start;
+         run_end = start;
+         run_eqv_end = RE_TRANSLATE (eqv_table, run_end);
+       }
+      else
+       {
+         /* Extend a running range.  */
+         run_end = minchar;
+         run_eqv_end = RE_TRANSLATE (eqv_table, run_end);
+       }
+    }
+
+  /* If a run is still in progress at the end, finish it now
+     by recording its equivalent ranges.  */
+  if (run_type == one_case)
+    {
+      EXTEND_RANGE_TABLE (work_area, 2);
+      work_area->table[work_area->used++] = run_start;
+      work_area->table[work_area->used++] = run_end;
+    }
+  else if (run_type == two_case)
+    {
+      EXTEND_RANGE_TABLE (work_area, 4);
+      work_area->table[work_area->used++] = run_start;
+      work_area->table[work_area->used++] = run_end;
+      work_area->table[work_area->used++]
+       = RE_TRANSLATE (eqv_table, run_start);
+      work_area->table[work_area->used++]
+       = RE_TRANSLATE (eqv_table, run_end);
+    }
+
+  return -1;
+}
+
+#endif /* emacs */
+
+/* Record the the image of the range start..end when passed through
+   TRANSLATE.  This is not necessarily TRANSLATE(start)..TRANSLATE(end)
+   and is not even necessarily contiguous.
+   Normally we approximate it with the smallest contiguous range that contains
+   all the chars we need.  However, for Latin-1 we go to extra effort
+   to do a better job.
+
+   This function is not called for ASCII ranges.
+
+   Returns -1 if successful, REG_ESPACE if ran out of space.  */
+
+static int
+set_image_of_range (work_area, start, end, translate)
+     RE_TRANSLATE_TYPE translate;
+     struct range_table_work_area *work_area;
+     re_wchar_t start, end;
+{
+  re_wchar_t cmin, cmax;
+
+#ifdef emacs
+  /* For Latin-1 ranges, use set_image_of_range_1
+     to get proper handling of ranges that include letters and nonletters.
+     For a range that includes the whole of Latin-1, this is not necessary.
+     For other character sets, we don't bother to get this right.  */
+  if (RE_TRANSLATE_P (translate) && start < 04400
+      && !(start < 04200 && end >= 04377))
+    {
+      int newend;
+      int tem;
+      newend = end;
+      if (newend > 04377)
+       newend = 04377;
+      tem = set_image_of_range_1 (work_area, start, newend, translate);
+      if (tem > 0)
+       return tem;
+
+      start = 04400;
+      if (end < 04400)
+       return -1;
+    }
 #endif
+
+  EXTEND_RANGE_TABLE (work_area, 2);
+  work_area->table[work_area->used++] = (start);
+  work_area->table[work_area->used++] = (end);
+
+  cmin = -1, cmax = -1;
+
+  if (RE_TRANSLATE_P (translate))
+    {
+      int ch;
+
+      for (ch = start; ch <= end; ch++)
+       {
+         re_wchar_t c = TRANSLATE (ch);
+         if (! (start <= c && c <= end))
+           {
+             if (cmin == -1)
+               cmin = c, cmax = c;
+             else
+               {
+                 cmin = MIN (cmin, c);
+                 cmax = MAX (cmax, c);
+               }
+           }
+       }
+
+      if (cmin != -1)
+       {
+         EXTEND_RANGE_TABLE (work_area, 2);
+         work_area->table[work_area->used++] = (cmin);
+         work_area->table[work_area->used++] = (cmax);
+       }
+    }
+
+  return -1;
+}
+#endif /* 0 */
 \f
 #ifndef MATCH_MAY_ALLOCATE
 
@@ -2200,6 +2505,9 @@ regex_compile (pattern, size, syntax, bufp)
   /* If the object matched can contain multibyte characters.  */
   const boolean multibyte = RE_MULTIBYTE_P (bufp);
 
+  /* If a target of matching can contain multibyte characters.  */
+  const boolean target_multibyte = RE_TARGET_MULTIBYTE_P (bufp);
+
 #ifdef DEBUG
   debug++;
   DEBUG_PRINT1 ("\nCompiling pattern: ");
@@ -2371,10 +2679,10 @@ regex_compile (pattern, size, syntax, bufp)
                    unsigned int startoffset = 0;
                    re_opcode_t ofj =
                      /* Check if the loop can match the empty string.  */
-                     (simple || !analyse_first (laststart, b, NULL, 0)) ?
-                     on_failure_jump : on_failure_jump_loop;
+                     (simple || !analyse_first (laststart, b, NULL, 0))
+                     on_failure_jump : on_failure_jump_loop;
                    assert (skip_one_char (laststart) <= b);
-                   
+
                    if (!zero_times_ok && simple)
                      { /* Since simple * loops can be made faster by using
                           on_failure_keep_string_jump, we turn simple P+
@@ -2420,8 +2728,9 @@ regex_compile (pattern, size, syntax, bufp)
                  {
                    boolean emptyp = analyse_first (laststart, b, NULL, 0);
 
-                   /* The non-greedy multiple match looks like a repeat..until:
-                      we only need a conditional jump at the end of the loop */
+                   /* The non-greedy multiple match looks like
+                      a repeat..until: we only need a conditional jump
+                      at the end of the loop.  */
                    if (emptyp) BUF_PUSH (no_op);
                    STORE_JUMP (emptyp ? on_failure_jump_nastyloop
                                : on_failure_jump, b, laststart);
@@ -2430,7 +2739,7 @@ regex_compile (pattern, size, syntax, bufp)
                      {
                        /* The repeat...until naturally matches one or more.
                           To also match zero times, we need to first jump to
-                          the end of the loop (its conditional jump). */
+                          the end of the loop (its conditional jump).  */
                        INSERT_JUMP (jump, laststart, b);
                        b += 3;
                      }
@@ -2495,6 +2804,10 @@ regex_compile (pattern, size, syntax, bufp)
 
                if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
 
+               /* Don't translate yet.  The range TRANSLATE(X..Y) cannot
+                  always be determined from TRANSLATE(X) and TRANSLATE(Y)
+                  So the translation is done later in a loop.  Example:
+                  (let ((case-fold-search t)) (string-match "[A-_]" "A"))  */
                PATFETCH (c);
 
                /* \ might escape characters inside [...] and [^...].  */
@@ -2514,10 +2827,6 @@ regex_compile (pattern, size, syntax, bufp)
                      break;
                  }
 
-               /* What should we do for the character which is
-                  greater than 0x7F, but not BASE_LEADING_CODE_P?
-                  XXX */
-
                /* See if we're at the beginning of a possible character
                   class.  */
 
@@ -2554,8 +2863,9 @@ regex_compile (pattern, size, syntax, bufp)
                       them).  */
                    if (c == ':' && *p == ']')
                      {
-                       int ch;
+                       re_wchar_t ch;
                        re_wctype_t cc;
+                       int limit;
 
                        cc = re_wctype (str);
 
@@ -2575,15 +2885,31 @@ regex_compile (pattern, size, syntax, bufp)
                           don't need to handle them for multibyte.
                           They are distinguished by a negative wctype.  */
 
-                       if (multibyte)
-                         SET_RANGE_TABLE_WORK_AREA_BIT (range_table_work,
-                                                        re_wctype_to_bit (cc));
+                       for (ch = 0; ch < 128; ++ch)
+                         if (re_iswctype (btowc (ch), cc))
+                           {
+                             c = TRANSLATE (ch);
+                             SET_LIST_BIT (c);
+                           }
 
-                        for (ch = 0; ch < 1 << BYTEWIDTH; ++ch)
+                       if (target_multibyte)
+                         {
+                           SET_RANGE_TABLE_WORK_AREA_BIT
+                             (range_table_work, re_wctype_to_bit (cc));
+                         }
+                       else
                          {
-                           int translated = TRANSLATE (ch);
-                           if (re_iswctype (btowc (ch), cc))
-                             SET_LIST_BIT (translated);
+                           for (ch = 0; ch < (1 << BYTEWIDTH); ++ch)
+                             {
+                               c = ch;
+                               MAKE_CHAR_MULTIBYTE (c);
+                               if (re_iswctype (btowc (c), cc))
+                                 {
+                                   c = TRANSLATE (c);
+                                   MAKE_CHAR_UNIBYTE (c);
+                                   SET_LIST_BIT (c);
+                                 }
+                             }
                          }
 
                        /* Repeat the loop. */
@@ -2610,52 +2936,51 @@ regex_compile (pattern, size, syntax, bufp)
 
                    /* Fetch the character which ends the range. */
                    PATFETCH (c1);
-
-                   if (SINGLE_BYTE_CHAR_P (c)
-                       && ! SINGLE_BYTE_CHAR_P (c1))
+                   if (c > c1)
                      {
-                       /* Handle a range starting with a character
-                          fitting in a bitmap to a character not
-                          fitting in a bitmap (thus require range
-                          table).  We use both a bitmap (for the
-                          range from C to 255) and a range table (for
-                          the remaining range).  Here, we setup only
-                          a range table.  A bitmap is setup later.  */
-                       re_wchar_t c2
-                         = CHAR_BYTE8_P (c1) ? BYTE8_TO_CHAR (0x80) : 256;
-
-                       SET_RANGE_TABLE_WORK_AREA (range_table_work, c2, c1);
-                       c1 = 255;
+                       if (syntax & RE_NO_EMPTY_RANGES)
+                         FREE_STACK_RETURN (REG_ERANGE);
+                       /* Else, repeat the loop.  */
                      }
                  }
                else
                  /* Range from C to C. */
                  c1 = c;
 
-               /* Set the range ... */
-               if (SINGLE_BYTE_CHAR_P (c))
-                 /* ... into bitmap.  */
+#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)
                  {
-                   re_wchar_t this_char;
-                   int range_start = c, range_end = c1;
-
-                   /* If the start is after the end, the range is empty.  */
-                   if (range_start > range_end)
+                   if (c1 >= 128)
                      {
-                       if (syntax & RE_NO_EMPTY_RANGES)
-                         FREE_STACK_RETURN (REG_ERANGE);
-                       /* Else, repeat the loop.  */
+                       re_wchar_t c0 = MAX (c, 128);
+
+                       SETUP_MULTIBYTE_RANGE (range_table_work, c0, c1);
+                       c1 = 127;
                      }
-                   else
+                   for (; c <= c1; c++)
+                     SET_LIST_BIT (TRANSLATE (c));
+                 }
+               else
+                 {
+                   re_wchar_t c0;
+
+                   for (; c <= c1; c++)
                      {
-                       for (this_char = range_start; this_char <= range_end;
-                            this_char++)
-                         SET_LIST_BIT (TRANSLATE (this_char));
+                       c0 = c;
+                       if (! multibyte)
+                         MAKE_CHAR_MULTIBYTE (c0);
+                       c0 = TRANSLATE (c0);
+                       MAKE_CHAR_UNIBYTE (c0);
+                       SET_LIST_BIT (c0);
                      }
                  }
-               else
-                 /* ... into range table.  */
-                 SET_RANGE_TABLE_WORK_AREA (range_table_work, c, c1);
+#endif /* not emacs */
              }
 
            /* Discard any (non)matching list bytes that are all 0 at the
@@ -2734,7 +3059,7 @@ regex_compile (pattern, size, syntax, bufp)
          /* Do not translate the character after the \, so that we can
             distinguish, e.g., \B from \b, even if we normally would
             translate, e.g., B to b.  */
-         PATFETCH_RAW (c);
+         PATFETCH (c);
 
          switch (c)
            {
@@ -2958,99 +3283,99 @@ regex_compile (pattern, size, syntax, bufp)
                      goto unfetch_interval;
                  }
 
-                if (upper_bound == 0)
-                  /* If the upper bound is zero, just drop the sub pattern
-                     altogether.  */
-                  b = laststart;
-                else if (lower_bound == 1 && upper_bound == 1)
-                  /* Just match it once: nothing to do here.  */
-                  ;
-
-                /* Otherwise, we have a nontrivial interval.  When
-                   we're all done, the pattern will look like:
-                     set_number_at <jump count> <upper bound>
-                     set_number_at <succeed_n count> <lower bound>
-                     succeed_n <after jump addr> <succeed_n count>
-                     <body of loop>
-                     jump_n <succeed_n addr> <jump count>
-                   (The upper bound and `jump_n' are omitted if
-                   `upper_bound' is 1, though.)  */
-                else
-                  { /* If the upper bound is > 1, we need to insert
-                       more at the end of the loop.  */
-                    unsigned int nbytes = (upper_bound < 0 ? 3
-                                           : upper_bound > 1 ? 5 : 0);
-                    unsigned int startoffset = 0;
-
-                    GET_BUFFER_SPACE (20); /* We might use less.  */
-
-                    if (lower_bound == 0)
-                      {
-                        /* A succeed_n that starts with 0 is really a
-                           a simple on_failure_jump_loop.  */
-                        INSERT_JUMP (on_failure_jump_loop, laststart,
-                                     b + 3 + nbytes);
-                        b += 3;
-                      }
-                    else
-                      {
-                        /* Initialize lower bound of the `succeed_n', even
-                           though it will be set during matching by its
-                           attendant `set_number_at' (inserted next),
-                           because `re_compile_fastmap' needs to know.
-                           Jump to the `jump_n' we might insert below.  */
-                        INSERT_JUMP2 (succeed_n, laststart,
-                                      b + 5 + nbytes,
-                                      lower_bound);
-                        b += 5;
-
-                        /* Code to initialize the lower bound.  Insert
-                           before the `succeed_n'.      The `5' is the last two
-                           bytes of this `set_number_at', plus 3 bytes of
-                           the following `succeed_n'.  */
-                        insert_op2 (set_number_at, laststart, 5, lower_bound, b);
-                        b += 5;
-                        startoffset += 5;
-                      }
-
-                    if (upper_bound < 0)
-                      {
-                        /* A negative upper bound stands for infinity,
-                           in which case it degenerates to a plain jump.  */
-                        STORE_JUMP (jump, b, laststart + startoffset);
-                        b += 3;
-                      }
-                    else if (upper_bound > 1)
-                      { /* More than one repetition is allowed, so
-                           append a backward jump to the `succeed_n'
-                           that starts this interval.
-
-                           When we've reached this during matching,
-                           we'll have matched the interval once, so
-                           jump back only `upper_bound - 1' times.  */
-                        STORE_JUMP2 (jump_n, b, laststart + startoffset,
-                                     upper_bound - 1);
-                        b += 5;
-
-                        /* The location we want to set is the second
-                           parameter of the `jump_n'; that is `b-2' as
-                           an absolute address.  `laststart' will be
-                           the `set_number_at' we're about to insert;
-                           `laststart+3' the number to set, the source
-                           for the relative address.  But we are
-                           inserting into the middle of the pattern --
-                           so everything is getting moved up by 5.
-                           Conclusion: (b - 2) - (laststart + 3) + 5,
-                           i.e., b - laststart.
-
-                           We insert this at the beginning of the loop
-                           so that if we fail during matching, we'll
-                           reinitialize the bounds.  */
-                        insert_op2 (set_number_at, laststart, b - laststart,
-                                    upper_bound - 1, b);
-                        b += 5;
-                      }
-                  }
+               if (upper_bound == 0)
+                 /* If the upper bound is zero, just drop the sub pattern
+                    altogether.  */
+                 b = laststart;
+               else if (lower_bound == 1 && upper_bound == 1)
+                 /* Just match it once: nothing to do here.  */
+                 ;
+
+               /* Otherwise, we have a nontrivial interval.  When
+                  we're all done, the pattern will look like:
+                  set_number_at <jump count> <upper bound>
+                  set_number_at <succeed_n count> <lower bound>
+                  succeed_n <after jump addr> <succeed_n count>
+                  <body of loop>
+                  jump_n <succeed_n addr> <jump count>
+                  (The upper bound and `jump_n' are omitted if
+                  `upper_bound' is 1, though.)  */
+               else
+                 { /* If the upper bound is > 1, we need to insert
+                      more at the end of the loop.  */
+                   unsigned int nbytes = (upper_bound < 0 ? 3
+                                          : upper_bound > 1 ? 5 : 0);
+                   unsigned int startoffset = 0;
+
+                   GET_BUFFER_SPACE (20); /* We might use less.  */
+
+                   if (lower_bound == 0)
+                     {
+                       /* A succeed_n that starts with 0 is really a
+                          a simple on_failure_jump_loop.  */
+                       INSERT_JUMP (on_failure_jump_loop, laststart,
+                                    b + 3 + nbytes);
+                       b += 3;
+                     }
+                   else
+                     {
+                       /* Initialize lower bound of the `succeed_n', even
+                          though it will be set during matching by its
+                          attendant `set_number_at' (inserted next),
+                          because `re_compile_fastmap' needs to know.
+                          Jump to the `jump_n' we might insert below.  */
+                       INSERT_JUMP2 (succeed_n, laststart,
+                                     b + 5 + nbytes,
+                                     lower_bound);
+                       b += 5;
+
+                       /* Code to initialize the lower bound.  Insert
+                          before the `succeed_n'.       The `5' is the last two
+                          bytes of this `set_number_at', plus 3 bytes of
+                          the following `succeed_n'.  */
+                       insert_op2 (set_number_at, laststart, 5, lower_bound, b);
+                       b += 5;
+                       startoffset += 5;
+                     }
+
+                   if (upper_bound < 0)
+                     {
+                       /* A negative upper bound stands for infinity,
+                          in which case it degenerates to a plain jump.  */
+                       STORE_JUMP (jump, b, laststart + startoffset);
+                       b += 3;
+                     }
+                   else if (upper_bound > 1)
+                     { /* More than one repetition is allowed, so
+                          append a backward jump to the `succeed_n'
+                          that starts this interval.
+
+                          When we've reached this during matching,
+                          we'll have matched the interval once, so
+                          jump back only `upper_bound - 1' times.  */
+                       STORE_JUMP2 (jump_n, b, laststart + startoffset,
+                                    upper_bound - 1);
+                       b += 5;
+
+                       /* The location we want to set is the second
+                          parameter of the `jump_n'; that is `b-2' as
+                          an absolute address.  `laststart' will be
+                          the `set_number_at' we're about to insert;
+                          `laststart+3' the number to set, the source
+                          for the relative address.  But we are
+                          inserting into the middle of the pattern --
+                          so everything is getting moved up by 5.
+                          Conclusion: (b - 2) - (laststart + 3) + 5,
+                          i.e., b - laststart.
+
+                          We insert this at the beginning of the loop
+                          so that if we fail during matching, we'll
+                          reinitialize the bounds.  */
+                       insert_op2 (set_number_at, laststart, b - laststart,
+                                   upper_bound - 1, b);
+                       b += 5;
+                     }
+                 }
                pending_exact = 0;
                beg_interval = NULL;
              }
@@ -3094,13 +3419,13 @@ regex_compile (pattern, size, syntax, bufp)
 
            case 'c':
              laststart = b;
-             PATFETCH_RAW (c);
+             PATFETCH (c);
              BUF_PUSH_2 (categoryspec, c);
              break;
 
            case 'C':
              laststart = b;
-             PATFETCH_RAW (c);
+             PATFETCH (c);
              BUF_PUSH_2 (notcategoryspec, c);
              break;
 #endif /* emacs */
@@ -3190,7 +3515,6 @@ regex_compile (pattern, size, syntax, bufp)
              /* You might think it would be useful for \ to mean
                 not to translate; but if we don't translate it
                 it will never match anything.  */
-             c = TRANSLATE (c);
              goto normal_char;
            }
          break;
@@ -3199,7 +3523,7 @@ regex_compile (pattern, size, syntax, bufp)
        default:
        /* Expects the character in `c'.  */
        normal_char:
-             /* If no exactn currently being built.  */
+         /* If no exactn currently being built.  */
          if (!pending_exact
 
              /* If last exactn not at current position.  */
@@ -3230,11 +3554,20 @@ regex_compile (pattern, size, syntax, bufp)
          {
            int len;
 
-           if (multibyte)
-             len = CHAR_STRING (c, b);
+           if (! multibyte)
+             MAKE_CHAR_MULTIBYTE (c);
+           c = TRANSLATE (c);
+           if (target_multibyte)
+             {
+               len = CHAR_STRING (c, b);
+               b += len;
+             }
            else
-             *b = c, len = 1;
-           b += len;
+             {
+               MAKE_CHAR_UNIBYTE (c);
+               *b++ = c;
+               len = 1;
+             }
            (*pending_exact) += len;
          }
 
@@ -3260,6 +3593,11 @@ 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)
     {
@@ -3505,14 +3843,11 @@ analyse_first (p, pend, fastmap, multibyte)
 
        case exactn:
          if (fastmap)
-           {
-             int c = RE_STRING_CHAR (p + 1, pend - p);
-
-             if (SINGLE_BYTE_CHAR_P (c))
-               fastmap[c] = 1;
-             else
-               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;
          break;
 
 
@@ -3524,14 +3859,18 @@ analyse_first (p, pend, fastmap, multibyte)
 
 
        case charset_not:
-         /* Chars beyond end of bitmap are possible matches.
-            All the single-byte codes can occur in multibyte buffers.
-            So any that are not listed in the charset
-            are possible matches, even in multibyte buffers.  */
          if (!fastmap) break;
-         for (j = CHARSET_BITMAP_SIZE (&p[-1]) * BYTEWIDTH;
-              j < (1 << BYTEWIDTH); j++)
-           fastmap[j] = 1;
+         {
+           /* 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++)
+             fastmap[j] = 1;
+         }
+
          /* Fallthrough */
        case charset:
          if (!fastmap) break;
@@ -3542,19 +3881,17 @@ analyse_first (p, pend, fastmap, multibyte)
              fastmap[j] = 1;
 
          if ((not && multibyte)
-             /* Any character set can possibly contain a character
+             /* 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 character set.  */
+              any multibyte characters.  */
            {
-           set_fastmap_for_multibyte_characters:
              if (match_any_multibyte_characters == false)
                {
-                 for (j = 0x80; j < 0x100; j++) /* XXX */
-                   if (BASE_LEADING_CODE_P (j))
-                     fastmap[j] = 1;
+                 for (j = 0x80; j < (1 << BYTEWIDTH); j++)
+                   fastmap[j] = 1;
                  match_any_multibyte_characters = true;
                }
            }
@@ -3562,11 +3899,10 @@ analyse_first (p, pend, fastmap, multibyte)
          else if (!not && CHARSET_RANGE_TABLE_EXISTS_P (&p[-2])
                   && match_any_multibyte_characters == false)
            {
-             /* Set fastmap[I] to 1 where I is a base leading code of each
+             /* Set fastmap[I] to 1 where I is a leading code of each
                 multibyte characer in the range table. */
              int c, count;
-             unsigned char buf1[MAX_MULTIBYTE_LENGTH];
-             unsigned char buf2[MAX_MULTIBYTE_LENGTH];
+             unsigned char lc1, lc2;
 
              /* Make P points the range table.  `+ 2' is to skip flag
                 bits for a character class.  */
@@ -3578,11 +3914,11 @@ analyse_first (p, pend, fastmap, multibyte)
                {
                  /* Extract the start and end of each range.  */
                  EXTRACT_CHARACTER (c, p);
-                 CHAR_STRING (c, buf1);
+                 lc1 = CHAR_LEADING_CODE (c);
                  p += 3;
                  EXTRACT_CHARACTER (c, p);
-                 CHAR_STRING (c, buf2);
-                 for (j = buf1[0]; j <= buf2[0]; j++)
+                 lc2 = CHAR_LEADING_CODE (c);
+                 for (j = lc1; j <= lc2; j++)
                    fastmap[j] = 1;
                }
            }
@@ -3608,14 +3944,21 @@ analyse_first (p, pend, fastmap, multibyte)
          if (!fastmap) break;
          not = (re_opcode_t)p[-1] == notcategoryspec;
          k = *p++;
-         for (j = 0; j < (1 << BYTEWIDTH); j++)
+         for (j = (multibyte ? 127 : (1 << BYTEWIDTH)); j >= 0; j--)
            if ((CHAR_HAS_CATEGORY (j, k)) ^ not)
              fastmap[j] = 1;
 
          if (multibyte)
-           /* Any character set can possibly contain a character
-              whose category is K (or not).  */
-           goto set_fastmap_for_multibyte_characters;
+           {
+             /* 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;
+               }
+           }
          break;
 
       /* All cases after this match the empty string.  These end with
@@ -3687,7 +4030,7 @@ analyse_first (p, pend, fastmap, multibyte)
             case has already been handled, so we only need to look at the
             fallthrough case.  */
          continue;
-         
+
        case succeed_n:
          /* If N == 0, it should be an on_failure_jump_loop instead.  */
          DEBUG_STATEMENT (EXTRACT_NUMBER (j, p + 2); assert (j > 0));
@@ -3812,6 +4155,10 @@ re_search (bufp, string, size, startpos, range, regs)
 }
 WEAK_ALIAS (__re_search, re_search)
 
+/* Head address of virtual concatenation of string.  */
+#define HEAD_ADDR_VSTRING(P)           \
+  (((P) >= size1 ? string2 : string1))
+
 /* End address of virtual concatenation of string.  */
 #define STOP_ADDR_VSTRING(P)                           \
   (((P) >= size1 ? string2 + size2 : string1 + size1))
@@ -3859,8 +4206,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 we have to concern multibyte character.         */
+  /* 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);
 
   /* Check for out-of-range STARTPOS.  */
@@ -3957,30 +4304,47 @@ re_search_2 (bufp, str1, size1, str2, size2, startpos, range, regs, stop)
 
                        buf_ch = STRING_CHAR_AND_LENGTH (d, range - lim,
                                                         buf_charlen);
-
                        buf_ch = RE_TRANSLATE (translate, buf_ch);
-                       if (buf_ch >= 0400
-                           || fastmap[buf_ch])
+                       if (fastmap[CHAR_LEADING_CODE (buf_ch)])
                          break;
 
                        range -= buf_charlen;
                        d += buf_charlen;
                      }
                  else
-                   while (range > lim
-                          && !fastmap[RE_TRANSLATE (translate, *d)])
+                   while (range > lim)
                      {
+                       buf_ch = *d;
+                       MAKE_CHAR_MULTIBYTE (buf_ch);
+                       buf_ch = RE_TRANSLATE (translate, buf_ch);
+                       MAKE_CHAR_UNIBYTE (buf_ch);
+                       if (fastmap[buf_ch])
+                         break;
                        d++;
                        range--;
                      }
                }
              else
-               while (range > lim && !fastmap[*d])
-                 {
-                   d++;
-                   range--;
-                 }
+               {
+                 if (multibyte)
+                   while (range > lim)
+                     {
+                       int buf_charlen;
 
+                       buf_ch = STRING_CHAR_AND_LENGTH (d, range - lim,
+                                                        buf_charlen);
+                       if (fastmap[CHAR_LEADING_CODE (buf_ch)])
+                         break;
+                       range -= buf_charlen;
+                       d += buf_charlen;
+                     }
+                 else
+                   while (range > lim && !fastmap[*d])
+                     {
+                       d++;
+                       range--;
+                     }
+               }
              startpos += irange - range;
            }
          else                          /* Searching backwards.  */
@@ -3988,12 +4352,18 @@ re_search_2 (bufp, str1, size1, str2, size2, startpos, range, regs, stop)
              int room = (startpos >= size1
                          ? size2 + size1 - startpos
                          : size1 - startpos);
-             buf_ch = RE_STRING_CHAR (d, room);
-             buf_ch = TRANSLATE (buf_ch);
-
-             if (! (buf_ch >= 0400
-                    || fastmap[buf_ch]))
-               goto advance;
+             if (multibyte)
+               {
+                 buf_ch = STRING_CHAR (d, room);
+                 buf_ch = TRANSLATE (buf_ch);
+                 if (! fastmap[CHAR_LEADING_CODE (buf_ch)])
+                   goto advance;
+               }
+             else
+               {
+                 if (! fastmap[TRANSLATE (*d)])
+                   goto advance;
+               }
            }
        }
 
@@ -4047,26 +4417,17 @@ re_search_2 (bufp, str1, size1, str2, size2, startpos, range, regs, stop)
          /* Update STARTPOS to the previous character boundary.  */
          if (multibyte)
            {
-             re_char *p = POS_ADDR_VSTRING (startpos);
-             int len = 0;
+             re_char *p = POS_ADDR_VSTRING (startpos) + 1;
+             re_char *p0 = p;
+             re_char *phead = HEAD_ADDR_VSTRING (startpos);
 
              /* Find the head of multibyte form.  */
-             while (!CHAR_HEAD_P (*p))
-               p--, len++;
-
-             /* Adjust it. */
-#if 0                          /* XXX */
-             if (MULTIBYTE_FORM_LENGTH (p, len + 1) != (len + 1))
-               ;
-             else
-#endif
-               {
-                 range += len;
-                 if (range > 0)
-                   break;
+             PREV_CHAR_BOUNDARY (p, phead);
+             range += p0 - 1 - p;
+             if (range > 0)
+               break;
 
-                 startpos -= len;
-               }
+             startpos -= p0 - 1 - p;
            }
        }
     }
@@ -4175,7 +4536,7 @@ skip_one_char (p)
     {
     case anychar:
       break;
-      
+
     case exactn:
       p += *p + 1;
       break;
@@ -4192,7 +4553,7 @@ skip_one_char (p)
       else
        p += 1 + CHARSET_BITMAP_SIZE (p - 1);
       break;
-      
+
     case syntaxspec:
     case notsyntaxspec:
 #ifdef emacs
@@ -4275,7 +4636,7 @@ mutually_exclusive_p (bufp, p1, p2)
          return 1;
        }
       break;
-      
+
     case endline:
     case exactn:
       {
@@ -4299,7 +4660,7 @@ mutually_exclusive_p (bufp, p1, p2)
 
            /* Test if C is listed in charset (or charset_not)
               at `p1'.  */
-           if (SINGLE_BYTE_CHAR_P (c))
+           if (! multibyte || IS_REAL_ASCII (c))
              {
                if (c < CHARSET_BITMAP_SIZE (p1) * BYTEWIDTH
                    && p1[2 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
@@ -4342,9 +4703,10 @@ mutually_exclusive_p (bufp, p1, p2)
             size of bitmap table of P1 is extracted by
             using macro `CHARSET_BITMAP_SIZE'.
 
-            Since we know that all the character listed in
-            P2 is ASCII, it is enough to test only bitmap
-            table of P1.  */
+            In a multibyte case, we know that all the character
+            listed in P2 is ASCII.  In a unibyte case, P1 has only a
+            bitmap table.  So, in both cases, it is enough to test
+            only the bitmap table of P1.  */
 
          if ((re_opcode_t) *p1 == charset)
            {
@@ -4385,7 +4747,7 @@ mutually_exclusive_p (bufp, p1, p2)
          }
       }
       break;
-      
+
     case charset_not:
       switch (SWITCH_ENUM_CAST (*p1))
        {
@@ -4398,7 +4760,7 @@ mutually_exclusive_p (bufp, p1, p2)
             they don't overlap.  The union of the two sets of excluded
             chars should cover all possible chars, which, as a matter of
             fact, is virtually impossible in multibyte buffers.  */
-         ;
+         break;
        }
       break;
 
@@ -4502,6 +4864,24 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
 }
 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. */
 static int
@@ -4541,7 +4921,8 @@ 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 we have to concern multibyte character.         */
+  /* 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);
 
   /* Failure point stack.  Each place that can handle a failure further
@@ -4895,58 +5276,71 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
          /* Remember the start point to rollback upon failure.  */
          dfail = d;
 
+#ifndef emacs
          /* This is written out as an if-else so we don't waste time
             testing `translate' inside the loop.  */
          if (RE_TRANSLATE_P (translate))
-           {
-             if (multibyte)
-               do
+           do
+             {
+               PREFETCH ();
+               if (RE_TRANSLATE (translate, *d) != *p++)
                  {
-                   int pat_charlen, buf_charlen;
-                   unsigned int pat_ch, buf_ch;
-
-                   PREFETCH ();
-                   pat_ch = STRING_CHAR_AND_LENGTH (p, pend - p, pat_charlen);
-                   buf_ch = STRING_CHAR_AND_LENGTH (d, dend - d, buf_charlen);
+                   d = dfail;
+                   goto fail;
+                 }
+               d++;
+             }
+           while (--mcnt);
+         else
+           do
+             {
+               PREFETCH ();
+               if (*d++ != *p++)
+                 {
+                   d = dfail;
+                   goto fail;
+                 }
+             }
+           while (--mcnt);
+#else  /* emacs */
+         /* The cost of testing `translate' is comparatively small.  */
+         if (multibyte)
+           do
+             {
+               int pat_charlen, buf_charlen;
+               unsigned int pat_ch, buf_ch;
 
-                   if (RE_TRANSLATE (translate, buf_ch)
-                       != pat_ch)
-                     {
-                       d = dfail;
-                       goto fail;
-                     }
+               PREFETCH ();
+               pat_ch = STRING_CHAR_AND_LENGTH (p, pend - p, pat_charlen);
+               buf_ch = STRING_CHAR_AND_LENGTH (d, dend - d, buf_charlen);
 
-                   p += pat_charlen;
-                   d += buf_charlen;
-                   mcnt -= pat_charlen;
-                 }
-               while (mcnt > 0);
-             else
-               do
+               if (TRANSLATE (buf_ch) != pat_ch)
                  {
-                   PREFETCH ();
-                   if (RE_TRANSLATE (translate, *d) != *p++)
-                     {
-                       d = dfail;
-                       goto fail;
-                     }
-                   d++;
+                   d = dfail;
+                   goto fail;
                  }
-               while (--mcnt);
-           }
+
+               p += pat_charlen;
+               d += buf_charlen;
+               mcnt -= pat_charlen;
+             }
+           while (mcnt > 0);
          else
-           {
-             do
-               {
-                 PREFETCH ();
-                 if (*d++ != *p++)
-                   {
-                     d = dfail;
-                     goto fail;
-                   }
-               }
-             while (--mcnt);
-           }
+           do
+             {
+               unsigned int buf_ch;
+
+               PREFETCH ();
+               buf_ch = *d++;
+               TRANSLATE_VIA_MULTIBYTE (buf_ch);
+               if (buf_ch != *p++)
+                 {
+                   d = dfail;
+                   goto fail;
+                 }
+             }
+           while (--mcnt);
+#endif
          break;
 
 
@@ -5004,9 +5398,9 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
 
            PREFETCH ();
            c = RE_STRING_CHAR_AND_LENGTH (d, dend - d, len);
-           c = TRANSLATE (c); /* The character to match.  */
+           TRANSLATE_VIA_MULTIBYTE (c); /* The character to match.  */
 
-           if (SINGLE_BYTE_CHAR_P (c))
+           if (! multibyte || IS_REAL_ASCII (c))
              {                 /* Lookup bitmap.  */
                /* Cast to `unsigned' instead of `unsigned char' in
                   case the bit list is a full 32 bytes long.  */
@@ -5069,7 +5463,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
 
          assert (!REG_UNSET (regstart[*p]));
          /* Strictly speaking, there should be code such as:
-            
+
                assert (REG_UNSET (regend[*p]));
                PUSH_FAILURE_REGSTOP ((unsigned int)*p);
 
@@ -5169,7 +5563,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
            }
          else
            {
-             unsigned char c;
+             unsigned c;
              GET_CHAR_BEFORE_2 (c, d, string1, end1, string2, end2);
              if (c == '\n')
                break;
@@ -5241,7 +5635,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
             cycle detection cannot work.  Worse yet, such a detection
             can not only fail to detect a cycle, but it can also wrongly
             detect a cycle (between different instantiations of the same
-            loop.
+            loop).
             So the method used for those nasty loops is a little different:
             We use a special cycle-detection-stack-frame which is pushed
             when the on_failure_jump_nastyloop failure-point is *popped*.
@@ -5255,11 +5649,18 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
                        mcnt, p + mcnt);
 
          assert ((re_opcode_t)p[-4] == no_op);
-         CHECK_INFINITE_LOOP (p - 4, d);
-         PUSH_FAILURE_POINT (p - 3, d);
+         {
+           int cycle = 0;
+           CHECK_INFINITE_LOOP (p - 4, d);
+           if (!cycle)
+             /* If there's a cycle, just continue without pushing
+                this failure point.  The failure point is the "try again"
+                option, which shouldn't be tried.
+                We want (x?)*?y\1z to match both xxyz and xxyxz.  */
+             PUSH_FAILURE_POINT (p - 3, d);
+         }
          break;
 
-
          /* Simple loop detecting on_failure_jump:  just check on the
             failure stack if the same spot was already hit earlier.  */
        case on_failure_jump_loop:
@@ -5267,9 +5668,19 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
          EXTRACT_NUMBER_AND_INCR (mcnt, p);
          DEBUG_PRINT3 ("EXECUTING on_failure_jump_loop %d (to %p):\n",
                        mcnt, p + mcnt);
-
-         CHECK_INFINITE_LOOP (p - 3, d);
-         PUSH_FAILURE_POINT (p - 3, d);
+         {
+           int cycle = 0;
+           CHECK_INFINITE_LOOP (p - 3, d);
+           if (cycle)
+             /* If there's a cycle, get out of the loop, as if the matching
+                had failed.  We used to just `goto fail' here, but that was
+                aborting the search a bit too early: we want to keep the
+                empty-loop-match and keep matching after the loop.
+                We want (x?)*y\1z to match both xxyz and xxyxz.  */
+             p += mcnt;
+           else
+             PUSH_FAILURE_POINT (p - 3, d);
+         }
          break;
 
 
@@ -5421,6 +5832,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
                 is the character at D, and S2 is the syntax of C2.  */
              re_wchar_t c1, c2;
              int s1, s2;
+             int dummy;
 #ifdef emacs
              int offset = PTR_TO_OFFSET (d - 1);
              int charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset);
@@ -5432,7 +5844,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
              UPDATE_SYNTAX_TABLE_FORWARD (charpos + 1);
 #endif
              PREFETCH_NOLIMIT ();
-             c2 = RE_STRING_CHAR (d, dend - d);
+             GET_CHAR_AFTER (c2, d, dummy);
              s2 = SYNTAX (c2);
 
              if (/* Case 2: Only one of S1 and S2 is Sword.  */
@@ -5461,15 +5873,16 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
                 is the character at D, and S2 is the syntax of C2.  */
              re_wchar_t c1, c2;
              int s1, s2;
+             int dummy;
 #ifdef emacs
              int offset = PTR_TO_OFFSET (d);
              int charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset);
              UPDATE_SYNTAX_TABLE (charpos);
 #endif
              PREFETCH ();
-             c2 = RE_STRING_CHAR (d, dend - d);
+             GET_CHAR_AFTER (c2, d, dummy);
              s2 = SYNTAX (c2);
-       
+
              /* Case 2: S2 is not Sword. */
              if (s2 != Sword)
                goto fail;
@@ -5505,6 +5918,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
                 is the character at D, and S2 is the syntax of C2.  */
              re_wchar_t c1, c2;
              int s1, s2;
+             int dummy;
 #ifdef emacs
              int offset = PTR_TO_OFFSET (d) - 1;
              int charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset);
@@ -5521,7 +5935,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);
+                 GET_CHAR_AFTER (c2, d, dummy);
 #ifdef emacs
                  UPDATE_SYNTAX_TABLE_FORWARD (charpos);
 #endif
@@ -5552,8 +5966,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
            int len;
            re_wchar_t c;
 
-           c = RE_STRING_CHAR_AND_LENGTH (d, dend - d, len);
-
+           GET_CHAR_AFTER (c, d, len);
            if ((SYNTAX (c) != (enum syntaxcode) mcnt) ^ not)
              goto fail;
            d += len;
@@ -5589,8 +6002,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
            int len;
            re_wchar_t c;
 
-           c = RE_STRING_CHAR_AND_LENGTH (d, dend - d, len);
-
+           GET_CHAR_AFTER (c, d, len);
            if ((!CHAR_HAS_CATEGORY (c, mcnt)) ^ not)
              goto fail;
            d += len;
@@ -5682,8 +6094,8 @@ bcmp_translate (s1, s2, len, translate, multibyte)
       int p1_charlen, p2_charlen;
       re_wchar_t p1_ch, p2_ch;
 
-      p1_ch = RE_STRING_CHAR_AND_LENGTH (p1, p1_end - p1, p1_charlen);
-      p2_ch = RE_STRING_CHAR_AND_LENGTH (p2, p2_end - p2, p2_charlen);
+      GET_CHAR_AFTER (p1_ch, p1, p1_charlen);
+      GET_CHAR_AFTER (p2_ch, p2, p2_charlen);
 
       if (RE_TRANSLATE (translate, p1_ch)
          != RE_TRANSLATE (translate, p2_ch))
@@ -5930,7 +6342,7 @@ regexec (preg, string, nmatch, pmatch, eflags)
     const regex_t *__restrict preg;
     const char *__restrict string;
     size_t nmatch;
-    regmatch_t pmatch[];
+    regmatch_t pmatch[__restrict_arr];
     int eflags;
 {
   int ret;