Merge r21-4-11-chise-0_20-=ucs.
[chise/xemacs-chise.git.1] / src / regex.c
index ff570ea..fe19076 100644 (file)
@@ -6,6 +6,7 @@
    Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
    Copyright (C) 1995 Sun Microsystems, Inc.
    Copyright (C) 1995 Ben Wing.
+   Copyright (C) 1999,2000,2001 MORIOKA Tomohiko
 
    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
 #define _GNU_SOURCE 1
 #endif
 
+#ifdef emacs
+/* Converts the pointer to the char to BEG-based offset from the start.         */
+#define PTR_TO_OFFSET(d) (MATCHING_IN_FIRST_STRING                     \
+                         ? (d) - string1 : (d) - (string2 - size1))
+#else
+#define PTR_TO_OFFSET(d) 0
+#endif
+
 /* We assume non-Mule if emacs isn't defined. */
 #ifndef emacs
 #undef MULE
@@ -123,16 +132,19 @@ char *malloc ();
 char *realloc ();
 #endif
 
-#define charptr_emchar(str)            ((Emchar) (str)[0])
+/* Types normally included via lisp.h */
+#include <stddef.h> /* for ptrdiff_t */
 
-#if (LONGBITS > INTBITS)
-# define EMACS_INT long
-#else
-# define EMACS_INT int
+#ifdef REGEX_MALLOC
+#ifndef DECLARE_NOTHING
+#define DECLARE_NOTHING struct nosuchstruct
+#endif
 #endif
 
 typedef int Emchar;
 
+#define charptr_emchar(str)            ((Emchar) (str)[0])
+
 #define INC_CHARPTR(p) ((p)++)
 #define DEC_CHARPTR(p) ((p)--)
 
@@ -179,6 +191,8 @@ init_syntax_once (void)
 #endif /* SYNTAX_TABLE */
 
 #define SYNTAX_UNSAFE(ignored, c) re_syntax_table[c]
+#undef SYNTAX_FROM_CACHE
+#define SYNTAX_FROM_CACHE SYNTAX_UNSAFE
 
 #define RE_TRANSLATE(c) translate[(unsigned char) (c)]
 #define TRANSLATE_P(tr) tr
@@ -368,7 +382,7 @@ void *alloca ();
 /* Type of source-pattern and string chars.  */
 typedef const unsigned char re_char;
 
-typedef char boolean;
+typedef char re_bool;
 #define false 0
 #define true 1
 
@@ -981,7 +995,7 @@ print_double_string (re_char *where, re_char *string1, int size1,
     printf ("(null)");
   else
     {
-      unsigned int this_char;
+      Element_count this_char;
 
       if (FIRST_STRING_P (where))
         {
@@ -1141,8 +1155,8 @@ typedef union fail_stack_elt fail_stack_elt_t;
 typedef struct
 {
   fail_stack_elt_t *stack;
-  size_t size;
-  size_t avail;                        /* Offset of next open position.  */
+  Element_count size;
+  Element_count avail;                 /* Offset of next open position.  */
 } fail_stack_type;
 
 #define FAIL_STACK_EMPTY()     (fail_stack.avail == 0)
@@ -1185,7 +1199,7 @@ typedef struct
    REGEX_REALLOCATE_STACK requires `destination' be declared.   */
 
 #define DOUBLE_FAIL_STACK(fail_stack)                                  \
-  ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS             \
+  ((int) (fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS       \
    ? 0                                                                 \
    : ((fail_stack).stack = (fail_stack_elt_t *)                                \
         REGEX_REALLOCATE_STACK ((fail_stack).stack,                    \
@@ -1252,85 +1266,89 @@ typedef struct
    Does `return FAILURE_CODE' if runs out of memory.  */
 
 #if !defined (REGEX_MALLOC) && !defined (REL_ALLOC)
-#define DECLARE_DESTINATION char *destination;
+#define DECLARE_DESTINATION char *destination
 #else
-#define DECLARE_DESTINATION
+#define DECLARE_DESTINATION DECLARE_NOTHING
 #endif
 
 #define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code)  \
-  do {                                                                 \
-    DECLARE_DESTINATION                                                        \
-    /* Must be int, so when we don't save any registers, the arithmetic        \
-       of 0 + -1 isn't done as unsigned.  */                           \
-    int this_reg;                                                      \
-                                                                       \
-    DEBUG_STATEMENT (failure_id++);                                    \
-    DEBUG_STATEMENT (nfailure_points_pushed++);                                \
-    DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id);          \
-    DEBUG_PRINT2 ("  Before push, next avail: %d\n", (fail_stack).avail);\
-    DEBUG_PRINT2 ("                     size: %d\n", (fail_stack).size);\
+do {                                                                   \
+  DECLARE_DESTINATION;                                                 \
+  /* Must be int, so when we don't save any registers, the arithmetic  \
+     of 0 + -1 isn't done as unsigned.  */                             \
+  int this_reg;                                                                \
                                                                        \
-    DEBUG_PRINT2 ("  slots needed: %d\n", NUM_FAILURE_ITEMS);          \
-    DEBUG_PRINT2 ("     available: %d\n", REMAINING_AVAIL_SLOTS);      \
+  DEBUG_STATEMENT (failure_id++);                                      \
+  DEBUG_STATEMENT (nfailure_points_pushed++);                          \
+  DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id);            \
+  DEBUG_PRINT2 ("  Before push, next avail: %lu\n",                    \
+               (unsigned long) (fail_stack).avail);                    \
+  DEBUG_PRINT2 ("                     size: %lu\n",                    \
+               (unsigned long) (fail_stack).size);                     \
                                                                        \
-    /* Ensure we have enough space allocated for what we will push.  */        \
-    while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS)                  \
-      {                                                                        \
-        if (!DOUBLE_FAIL_STACK (fail_stack))                           \
-          return failure_code;                                         \
+  DEBUG_PRINT2 ("  slots needed: %d\n", NUM_FAILURE_ITEMS);            \
+  DEBUG_PRINT2 ("     available: %ld\n",                               \
+               (long) REMAINING_AVAIL_SLOTS);                          \
                                                                        \
-        DEBUG_PRINT2 ("\n  Doubled stack; size now: %d\n",             \
-                      (fail_stack).size);                              \
-        DEBUG_PRINT2 ("  slots available: %d\n", REMAINING_AVAIL_SLOTS);\
-      }                                                                        \
+  /* Ensure we have enough space allocated for what we will push.  */  \
+  while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS)                    \
+    {                                                                  \
+      if (!DOUBLE_FAIL_STACK (fail_stack))                             \
+       return failure_code;                                            \
                                                                        \
-    /* Push the info, starting with the registers.  */                 \
-    DEBUG_PRINT1 ("\n");                                               \
+      DEBUG_PRINT2 ("\n  Doubled stack; size now: %lu\n",              \
+                   (unsigned long) (fail_stack).size);                 \
+      DEBUG_PRINT2 ("  slots available: %ld\n",                                \
+                   (long) REMAINING_AVAIL_SLOTS);                      \
+    }                                                                  \
                                                                        \
-    for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \
-         this_reg++)                                                   \
-      {                                                                        \
-       DEBUG_PRINT2 ("  Pushing reg: %d\n", this_reg);                 \
-        DEBUG_STATEMENT (num_regs_pushed++);                           \
+  /* Push the info, starting with the registers.  */                   \
+  DEBUG_PRINT1 ("\n");                                                 \
                                                                        \
-       DEBUG_PRINT2 ("    start: 0x%lx\n", (long) regstart[this_reg]); \
-        PUSH_FAILURE_POINTER (regstart[this_reg]);                     \
-                                                                        \
-       DEBUG_PRINT2 ("    end: 0x%lx\n", (long) regend[this_reg]);     \
-        PUSH_FAILURE_POINTER (regend[this_reg]);                       \
+  for (this_reg = lowest_active_reg; this_reg <= highest_active_reg;   \
+       this_reg++)                                                     \
+    {                                                                  \
+      DEBUG_PRINT2 ("  Pushing reg: %d\n", this_reg);                  \
+      DEBUG_STATEMENT (num_regs_pushed++);                             \
                                                                        \
-       DEBUG_PRINT2 ("    info: 0x%lx\n      ",                        \
-                     * (long *) (&reg_info[this_reg]));                \
-        DEBUG_PRINT2 (" match_null=%d",                                        \
-                      REG_MATCH_NULL_STRING_P (reg_info[this_reg]));   \
-        DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg]));   \
-        DEBUG_PRINT2 (" matched_something=%d",                         \
-                      MATCHED_SOMETHING (reg_info[this_reg]));         \
-        DEBUG_PRINT2 (" ever_matched=%d",                              \
-                      EVER_MATCHED_SOMETHING (reg_info[this_reg]));    \
-       DEBUG_PRINT1 ("\n");                                            \
-        PUSH_FAILURE_ELT (reg_info[this_reg].word);                    \
-      }                                                                        \
+      DEBUG_PRINT2 ("    start: 0x%lx\n", (long) regstart[this_reg]);  \
+      PUSH_FAILURE_POINTER (regstart[this_reg]);                       \
                                                                        \
-    DEBUG_PRINT2 ("  Pushing  low active reg: %d\n", lowest_active_reg);\
-    PUSH_FAILURE_INT (lowest_active_reg);                              \
+      DEBUG_PRINT2 ("    end: 0x%lx\n", (long) regend[this_reg]);      \
+      PUSH_FAILURE_POINTER (regend[this_reg]);                         \
                                                                        \
-    DEBUG_PRINT2 ("  Pushing high active reg: %d\n", highest_active_reg);\
-    PUSH_FAILURE_INT (highest_active_reg);                             \
+      DEBUG_PRINT2 ("    info: 0x%lx\n      ",                         \
+                   * (long *) (&reg_info[this_reg]));                  \
+      DEBUG_PRINT2 (" match_null=%d",                                  \
+                   REG_MATCH_NULL_STRING_P (reg_info[this_reg]));      \
+      DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg]));     \
+      DEBUG_PRINT2 (" matched_something=%d",                           \
+                   MATCHED_SOMETHING (reg_info[this_reg]));            \
+      DEBUG_PRINT2 (" ever_matched_something=%d",                      \
+                   EVER_MATCHED_SOMETHING (reg_info[this_reg]));       \
+      DEBUG_PRINT1 ("\n");                                             \
+      PUSH_FAILURE_ELT (reg_info[this_reg].word);                      \
+    }                                                                  \
                                                                        \
-    DEBUG_PRINT2 ("  Pushing pattern 0x%lx: \n", (long) pattern_place);        \
-    DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend);          \
-    PUSH_FAILURE_POINTER (pattern_place);                              \
+  DEBUG_PRINT2 ("  Pushing  low active reg: %d\n", lowest_active_reg); \
+  PUSH_FAILURE_INT (lowest_active_reg);                                        \
                                                                        \
-    DEBUG_PRINT2 ("  Pushing string 0x%lx: `", (long) string_place);   \
-    DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2,   \
-                                size2);                                \
-    DEBUG_PRINT1 ("'\n");                                              \
-    PUSH_FAILURE_POINTER (string_place);                               \
+  DEBUG_PRINT2 ("  Pushing high active reg: %d\n", highest_active_reg);        \
+  PUSH_FAILURE_INT (highest_active_reg);                               \
                                                                        \
-    DEBUG_PRINT2 ("  Pushing failure id: %u\n", failure_id);           \
-    DEBUG_PUSH (failure_id);                                           \
-  } while (0)
+  DEBUG_PRINT2 ("  Pushing pattern 0x%lx: \n", (long) pattern_place);  \
+  DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend);            \
+  PUSH_FAILURE_POINTER (pattern_place);                                        \
+                                                                       \
+  DEBUG_PRINT2 ("  Pushing string 0x%lx: `", (long) string_place);     \
+  DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2,    \
+                            size2);                                    \
+  DEBUG_PRINT1 ("'\n");                                                        \
+  PUSH_FAILURE_POINTER (string_place);                                 \
+                                                                       \
+  DEBUG_PRINT2 ("  Pushing failure id: %u\n", failure_id);             \
+  DEBUG_PUSH (failure_id);                                             \
+} while (0)
 
 /* This is the number of items that are pushed and popped on the stack
    for each register.  */
@@ -1355,7 +1373,7 @@ typedef struct
     + NUM_NONREG_ITEMS)
 
 /* How many items can still be added to the stack without overflowing it.  */
-#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail)
+#define REMAINING_AVAIL_SLOTS ((int) ((fail_stack).size - (fail_stack).avail))
 
 
 /* Pops what PUSH_FAIL_STACK pushes.
@@ -1370,8 +1388,9 @@ typedef struct
    Also assumes the variables `fail_stack' and (if debugging), `bufp',
    `pend', `string1', `size1', `string2', and `size2'.  */
 
-#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\
-{                                                                      \
+#define POP_FAILURE_POINT(str, pat, low_reg, high_reg,                 \
+                          regstart, regend, reg_info)                  \
+do {                                                                   \
   DEBUG_STATEMENT (fail_stack_elt_t ffailure_id;)                      \
   int this_reg;                                                                \
   const unsigned char *string_temp;                                    \
@@ -1380,8 +1399,10 @@ typedef struct
                                                                        \
   /* Remove failure points and point to how many regs pushed.  */      \
   DEBUG_PRINT1 ("POP_FAILURE_POINT:\n");                               \
-  DEBUG_PRINT2 ("  Before pop, next avail: %d\n", fail_stack.avail);   \
-  DEBUG_PRINT2 ("                    size: %d\n", fail_stack.size);    \
+  DEBUG_PRINT2 ("  Before pop, next avail: %lu\n",                     \
+               (unsigned long) fail_stack.avail);                      \
+  DEBUG_PRINT2 ("                    size: %lu\n",                     \
+               (unsigned long) fail_stack.size);                       \
                                                                        \
   assert (fail_stack.avail >= NUM_NONREG_ITEMS);                       \
                                                                        \
@@ -1428,7 +1449,7 @@ typedef struct
                                                                        \
   set_regs_matched_done = 0;                                           \
   DEBUG_STATEMENT (nfailure_points_popped++);                          \
-} /* POP_FAILURE_POINT */
+} while (0) /* POP_FAILURE_POINT */
 
 
 \f
@@ -1472,7 +1493,7 @@ typedef union
     {                                                                  \
       if (!set_regs_matched_done)                                      \
        {                                                               \
-         unsigned r;                                                   \
+         Element_count r;                                              \
          set_regs_matched_done = 1;                                    \
          for (r = lowest_active_reg; r <= highest_active_reg; r++)     \
            {                                                           \
@@ -1585,7 +1606,7 @@ static unsigned char reg_unset_dummy;
 
 /* Make sure we have at least N more bytes of space in buffer.  */
 #define GET_BUFFER_SPACE(n)                                            \
-    while (buf_end - bufp->buffer + (n) > bufp->allocated)             \
+    while (buf_end - bufp->buffer + (n) > (ptrdiff_t) bufp->allocated) \
       EXTEND_BUFFER ()
 
 /* Make sure we have one more byte of buffer space and then add C to it.  */
@@ -1773,10 +1794,10 @@ static void insert_op1 (re_opcode_t op, unsigned char *loc, int arg,
                        unsigned char *end);
 static void insert_op2 (re_opcode_t op, unsigned char *loc, int arg1, int arg2,
                        unsigned char *end);
-static boolean at_begline_loc_p (re_char *pattern, re_char *p,
+static re_bool at_begline_loc_p (re_char *pattern, re_char *p,
                                 reg_syntax_t syntax);
-static boolean at_endline_loc_p (re_char *p, re_char *pend, int syntax);
-static boolean group_in_compile_stack (compile_stack_type compile_stack,
+static re_bool at_endline_loc_p (re_char *p, re_char *pend, int syntax);
+static re_bool group_in_compile_stack (compile_stack_type compile_stack,
                                       regnum_t regnum);
 static reg_errcode_t compile_range (re_char **p_ptr, re_char *pend,
                                    RE_TRANSLATE_TYPE translate,
@@ -1789,12 +1810,12 @@ static reg_errcode_t compile_extended_range (re_char **p_ptr,
                                             reg_syntax_t syntax,
                                             Lisp_Object rtab);
 #endif /* MULE */
-static boolean group_match_null_string_p (unsigned char **p,
+static re_bool group_match_null_string_p (unsigned char **p,
                                          unsigned char *end,
                                          register_info_type *reg_info);
-static boolean alt_match_null_string_p (unsigned char *p, unsigned char *end,
+static re_bool alt_match_null_string_p (unsigned char *p, unsigned char *end,
                                        register_info_type *reg_info);
-static boolean common_op_match_null_string_p (unsigned char **p,
+static re_bool common_op_match_null_string_p (unsigned char **p,
                                              unsigned char *end,
                                              register_info_type *reg_info);
 static int bcmp_translate (const unsigned char *s1, const unsigned char *s2,
@@ -1933,7 +1954,7 @@ regex_compile (re_char *pattern, int size, reg_syntax_t syntax,
   DEBUG_PRINT1 ("\nCompiling pattern: ");
   if (debug)
     {
-      unsigned debug_count;
+      int debug_count;
 
       for (debug_count = 0; debug_count < size; debug_count++)
         putchar (pattern[debug_count]);
@@ -2041,11 +2062,11 @@ regex_compile (re_char *pattern, int size, reg_syntax_t syntax,
 
           {
            /* true means zero/many matches are allowed. */
-           boolean zero_times_ok = c != '+';
-            boolean many_times_ok = c != '?';
+           re_bool zero_times_ok = c != '+';
+            re_bool many_times_ok = c != '?';
 
             /* true means match shortest string possible. */
-            boolean minimal = false;
+            re_bool minimal = false;
 
             /* If there is a sequence of repetition chars, collapse it
                down to just one (the right one).  We can't combine
@@ -2149,7 +2170,7 @@ regex_compile (re_char *pattern, int size, reg_syntax_t syntax,
             else
               {
                 /* Are we optimizing this jump?  */
-                boolean keep_string_p = false;
+                re_bool keep_string_p = false;
 
                 if (many_times_ok)
                   { /* More than one repetition is allowed, so put in
@@ -2225,9 +2246,9 @@ regex_compile (re_char *pattern, int size, reg_syntax_t syntax,
         case '[':
           {
            /* XEmacs change: this whole section */
-            boolean had_char_class = false;
+            re_bool had_char_class = false;
 #ifdef MULE
-           boolean has_extended_chars = false;
+           re_bool has_extended_chars = false;
            REGISTER Lisp_Object rtab = Qnil;
 #endif
 
@@ -2409,18 +2430,18 @@ regex_compile (re_char *pattern, int size, reg_syntax_t syntax,
                     if (c == ':' && *p == ']')
                       {
                         int ch;
-                        boolean is_alnum = STREQ (str, "alnum");
-                        boolean is_alpha = STREQ (str, "alpha");
-                        boolean is_blank = STREQ (str, "blank");
-                        boolean is_cntrl = STREQ (str, "cntrl");
-                        boolean is_digit = STREQ (str, "digit");
-                        boolean is_graph = STREQ (str, "graph");
-                        boolean is_lower = STREQ (str, "lower");
-                        boolean is_print = STREQ (str, "print");
-                        boolean is_punct = STREQ (str, "punct");
-                        boolean is_space = STREQ (str, "space");
-                        boolean is_upper = STREQ (str, "upper");
-                        boolean is_xdigit = STREQ (str, "xdigit");
+                        re_bool is_alnum = STREQ (str, "alnum");
+                        re_bool is_alpha = STREQ (str, "alpha");
+                        re_bool is_blank = STREQ (str, "blank");
+                        re_bool is_cntrl = STREQ (str, "cntrl");
+                        re_bool is_digit = STREQ (str, "digit");
+                        re_bool is_graph = STREQ (str, "graph");
+                        re_bool is_lower = STREQ (str, "lower");
+                        re_bool is_print = STREQ (str, "print");
+                        re_bool is_punct = STREQ (str, "punct");
+                        re_bool is_space = STREQ (str, "space");
+                        re_bool is_upper = STREQ (str, "upper");
+                        re_bool is_xdigit = STREQ (str, "xdigit");
 
                         if (!IS_CHAR_CLASS (str))
                          FREE_STACK_RETURN (REG_ECTYPE);
@@ -2819,7 +2840,7 @@ regex_compile (re_char *pattern, int size, reg_syntax_t syntax,
                  else
                    { /* If the upper bound is > 1, we need to insert
                         more at the end of the loop.  */
-                     unsigned nbytes = 10 + (upper_bound > 1) * 10;
+                     Memory_count nbytes = 10 + (upper_bound > 1) * 10;
 
                      GET_BUFFER_SPACE (nbytes);
 
@@ -3206,11 +3227,11 @@ insert_op2 (re_opcode_t op, unsigned char *loc, int arg1, int arg2,
    after an alternative or a begin-subexpression.  We assume there is at
    least one character before the ^.  */
 
-static boolean
+static re_bool
 at_begline_loc_p (re_char *pattern, re_char *p, reg_syntax_t syntax)
 {
   re_char *prev = p - 2;
-  boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\';
+  re_bool prev_prev_backslash = prev > pattern && prev[-1] == '\\';
 
   return
        /* After a subexpression?  */
@@ -3223,11 +3244,11 @@ at_begline_loc_p (re_char *pattern, re_char *p, reg_syntax_t syntax)
 /* The dual of at_begline_loc_p.  This one is for $.  We assume there is
    at least one character after the $, i.e., `P < PEND'.  */
 
-static boolean
+static re_bool
 at_endline_loc_p (re_char *p, re_char *pend, int syntax)
 {
   re_char *next = p;
-  boolean next_backslash = *next == '\\';
+  re_bool next_backslash = *next == '\\';
   re_char *next_next = p + 1 < pend ? p + 1 : 0;
 
   return
@@ -3243,7 +3264,7 @@ at_endline_loc_p (re_char *p, re_char *pend, int syntax)
 /* Returns true if REGNUM is in one of COMPILE_STACK's elements and
    false if it's not.  */
 
-static boolean
+static re_bool
 group_in_compile_stack (compile_stack_type compile_stack, regnum_t regnum)
 {
   int this_element;
@@ -3273,7 +3294,7 @@ static reg_errcode_t
 compile_range (re_char **p_ptr, re_char *pend, RE_TRANSLATE_TYPE translate,
               reg_syntax_t syntax, unsigned char *buf_end)
 {
-  unsigned this_char;
+  Element_count this_char;
 
   re_char *p = *p_ptr;
   int range_start, range_end;
@@ -3342,8 +3363,12 @@ compile_extended_range (re_char **p_ptr, re_char *pend,
      ranges entirely within the first 256 chars. */
 
   if ((range_start >= 0x100 || range_end >= 0x100)
-      && CHAR_LEADING_BYTE (range_start) !=
-      CHAR_LEADING_BYTE (range_end))
+#ifdef UTF2000
+      && CHAR_CHARSET_ID (range_start) != CHAR_CHARSET_ID (range_end)
+#else
+      && CHAR_LEADING_BYTE (range_start) != CHAR_LEADING_BYTE (range_end)
+#endif
+      )
     return REG_ERANGESPAN;
 
   /* As advertised, translations only work over the 0 - 0x7F range.
@@ -3395,7 +3420,7 @@ re_compile_fastmap (struct re_pattern_buffer *bufp)
 #ifdef MATCH_MAY_ALLOCATE
   fail_stack_type fail_stack;
 #endif
-  DECLARE_DESTINATION
+  DECLARE_DESTINATION;
   /* We don't push any register information onto the failure stack.  */
 
   REGISTER char *fastmap = bufp->fastmap;
@@ -3414,10 +3439,10 @@ re_compile_fastmap (struct re_pattern_buffer *bufp)
      proven otherwise.  We set this false at the bottom of switch
      statement, to which we get only if a particular path doesn't
      match the empty string.  */
-  boolean path_can_be_null = true;
+  re_bool path_can_be_null = true;
 
   /* We aren't doing a `succeed_n' to begin with.  */
-  boolean succeed_n_p = false;
+  re_bool succeed_n_p = false;
 
   assert (fastmap != NULL && p != NULL);
 
@@ -3617,23 +3642,48 @@ re_compile_fastmap (struct re_pattern_buffer *bufp)
          }
 
 #ifdef emacs
+       case wordbound:
+       case notwordbound:
+       case wordbeg:
+       case wordend:
+       case notsyntaxspec:
+       case syntaxspec:
+         /* This match depends on text properties.  These end with
+            aborting optimizations.  */
+         bufp->can_be_null = 1;
+         goto done;
+
+#ifdef emacs
+#if 0  /* Removed during syntax-table properties patch -- 2000/12/07 mct */
         case syntaxspec:
          k = *p++;
+#endif
          matchsyntax:
 #ifdef MULE
+#ifdef UTF2000
+         for (j = 0; j < 0x80; j++)
+           if (SYNTAX_UNSAFE
+               (XCHAR_TABLE
+                (regex_emacs_buffer->syntax_table), j) ==
+               (enum syntaxcode) k)
+             fastmap[j] = 1;
+#else
          for (j = 0; j < 0x80; j++)
            if (SYNTAX_UNSAFE
                (XCHAR_TABLE
                 (regex_emacs_buffer->mirror_syntax_table), j) ==
                (enum syntaxcode) k)
              fastmap[j] = 1;
+#endif
          for (j = 0x80; j < 0xA0; j++)
            {
+#ifndef UTF2000
              if (LEADING_BYTE_PREFIX_P(j))
                /* too complicated to calculate this right */
                fastmap[j] = 1;
              else
                {
+#endif
                  int multi_p;
                  Lisp_Object cset;
 
@@ -3645,7 +3695,9 @@ re_compile_fastmap (struct re_pattern_buffer *bufp)
                          == Sword || multi_p)
                        fastmap[j] = 1;
                    }
+#ifndef UTF2000
                }
+#endif
            }
 #else /* not MULE */
          for (j = 0; j < (1 << BYTEWIDTH); j++)
@@ -3658,23 +3710,36 @@ re_compile_fastmap (struct re_pattern_buffer *bufp)
          break;
 
 
+#if 0  /* Removed during syntax-table properties patch -- 2000/12/07 mct */
        case notsyntaxspec:
          k = *p++;
+#endif
          matchnotsyntax:
 #ifdef MULE
+#ifdef UTF2000
+         for (j = 0; j < 0x80; j++)
+           if (SYNTAX_UNSAFE
+               (XCHAR_TABLE
+                (regex_emacs_buffer->syntax_table), j) !=
+               (enum syntaxcode) k)
+             fastmap[j] = 1;
+#else
          for (j = 0; j < 0x80; j++)
            if (SYNTAX_UNSAFE
                (XCHAR_TABLE
                 (regex_emacs_buffer->mirror_syntax_table), j) !=
                (enum syntaxcode) k)
              fastmap[j] = 1;
+#endif
          for (j = 0x80; j < 0xA0; j++)
            {
+#ifndef UTF2000
              if (LEADING_BYTE_PREFIX_P(j))
                /* too complicated to calculate this right */
                fastmap[j] = 1;
              else
                {
+#endif
                  int multi_p;
                  Lisp_Object cset;
 
@@ -3686,7 +3751,9 @@ re_compile_fastmap (struct re_pattern_buffer *bufp)
                          != Sword || multi_p)
                        fastmap[j] = 1;
                    }
+#ifndef UTF2000
                }
+#endif
            }
 #else /* not MULE */
          for (j = 0; j < (1 << BYTEWIDTH); j++)
@@ -3697,6 +3764,7 @@ re_compile_fastmap (struct re_pattern_buffer *bufp)
              fastmap[j] = 1;
 #endif /* MULE */
          break;
+#endif /* emacs */
 
 #ifdef MULE
 /* 97/2/17 jhod category patch */
@@ -3715,7 +3783,7 @@ re_compile_fastmap (struct re_pattern_buffer *bufp)
        case at_dot:
        case after_dot:
           continue;
-#endif /* not emacs */
+#endif /* emacs */
 
 
         case no_op:
@@ -3723,10 +3791,12 @@ re_compile_fastmap (struct re_pattern_buffer *bufp)
         case endline:
        case begbuf:
        case endbuf:
+#ifndef emacs
        case wordbound:
        case notwordbound:
        case wordbeg:
        case wordend:
+#endif
         case push_dummy_failure:
           continue;
 
@@ -3967,6 +4037,18 @@ re_search_2 (struct re_pattern_buffer *bufp, const char *str1,
        }
     }
 
+#ifdef emacs
+  /* In a forward search for something that starts with \=.
+     don't keep searching past point.  */
+  if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0)
+    {
+      range = BUF_PT (regex_emacs_buffer) - BUF_BEGV (regex_emacs_buffer)
+             - startpos;
+      if (range < 0)
+       return -1;
+    }
+#endif /* emacs */
+
   /* Update the fastmap now if not correct already.  */
   if (fastmap && !bufp->fastmap_accurate)
     if (re_compile_fastmap (bufp) == -2)
@@ -3974,7 +4056,7 @@ re_search_2 (struct re_pattern_buffer *bufp, const char *str1,
 
 #ifdef REGEX_BEGLINE_CHECK
   {
-    int i = 0;
+    unsigned long i = 0;
 
     while (i < bufp->used)
       {
@@ -3988,6 +4070,15 @@ re_search_2 (struct re_pattern_buffer *bufp, const char *str1,
   }
 #endif
 
+#ifdef emacs
+    SETUP_SYNTAX_CACHE_FOR_OBJECT (regex_match_object,
+                                  regex_emacs_buffer,
+                                  SYNTAX_CACHE_OBJECT_BYTE_TO_CHAR (regex_match_object,
+                                                                    regex_emacs_buffer,
+                                                                    startpos),
+                                  1);
+#endif
+
   /* Loop through the string, looking for a place to start matching.  */
   for (;;)
     {
@@ -4157,7 +4248,7 @@ re_search_2 (struct re_pattern_buffer *bufp, const char *str1,
 
 /* Call before fetching a character with *d.  This switches over to
    string2 if necessary.  */
-#define PREFETCH()                                                     \
+#define REGEX_PREFETCH()                                                       \
   while (d == dend)                                                    \
     {                                                                  \
       /* End of string2 => fail.  */                                   \
@@ -4182,9 +4273,15 @@ re_search_2 (struct re_pattern_buffer *bufp, const char *str1,
 #define POS_AFTER_GAP_UNSAFE(d) ((d) == end1 ? string2 : (d))
 
 /* Test if CH is a word-constituent character. (XEmacs change) */
+#ifdef UTF2000
+#define WORDCHAR_P_UNSAFE(ch)                                     \
+  (SYNTAX_UNSAFE (XCHAR_TABLE (regex_emacs_buffer->syntax_table),  \
+                               ch) == Sword)
+#else
 #define WORDCHAR_P_UNSAFE(ch)                                             \
   (SYNTAX_UNSAFE (XCHAR_TABLE (regex_emacs_buffer->mirror_syntax_table),   \
                                ch) == Sword)
+#endif
 
 /* Free everything we malloc.  */
 #ifdef MATCH_MAY_ALLOCATE
@@ -4251,9 +4348,21 @@ re_match_2 (struct re_pattern_buffer *bufp, const char *string1,
            int size1, const char *string2, int size2, int pos,
            struct re_registers *regs, int stop)
 {
-  int result = re_match_2_internal (bufp, (re_char *) string1, size1,
-                                   (re_char *) string2, size2,
-                                   pos, regs, stop);
+  int result;
+
+#ifdef emacs
+    SETUP_SYNTAX_CACHE_FOR_OBJECT (regex_match_object,
+                                  regex_emacs_buffer,
+                                  SYNTAX_CACHE_OBJECT_BYTE_TO_CHAR (regex_match_object,
+                                                                    regex_emacs_buffer,
+                                                                    pos),
+                                  1);
+#endif
+
+  result = re_match_2_internal (bufp, (re_char *) string1, size1,
+                               (re_char *) string2, size2,
+                               pos, regs, stop);
+
   alloca (0);
   return result;
 }
@@ -4305,7 +4414,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
 #endif
 #ifdef DEBUG
   static unsigned failure_id;
-  unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
+  int nfailure_points_pushed = 0, nfailure_points_popped = 0;
 #endif
 
 #ifdef REL_ALLOC
@@ -4317,11 +4426,11 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
   /* We fill all the registers internally, independent of what we
      return, for use in backreferences.  The number here includes
      an element for register zero.  */
-  unsigned num_regs = bufp->re_nsub + 1;
+  int num_regs = bufp->re_nsub + 1;
 
   /* The currently active registers.  */
-  unsigned lowest_active_reg = NO_LOWEST_ACTIVE_REG;
-  unsigned highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+  int lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+  int highest_active_reg = NO_HIGHEST_ACTIVE_REG;
 
   /* Information on the contents of registers. These are pointers into
      the input strings; they record just what was matched (on this
@@ -4388,10 +4497,10 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
 
   /* 1 if this match ends in the same string (string1 or string2)
      as the best previous match.  */
-  boolean same_str_p;
+  re_bool same_str_p;
 
   /* 1 if this match is the best seen so far.  */
-  boolean best_match_p;
+  re_bool best_match_p;
 
   DEBUG_PRINT1 ("\n\nEntering re_match_2.\n");
 
@@ -4644,16 +4753,24 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
                        = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]);
                     }
                }
-
-              /* If the regs structure we return has more elements than
-                 were in the pattern, set the extra elements to -1.  If
-                 we (re)allocated the registers, this is the case,
-                 because we always allocate enough to have at least one
-                 -1 at the end.  */
-              for (mcnt = num_regs; mcnt < regs->num_regs; mcnt++)
-                regs->start[mcnt] = regs->end[mcnt] = -1;
            } /* regs && !bufp->no_sub */
 
+         /* If we have regs and the regs structure has more elements than
+             were in the pattern, set the extra elements to -1.  If we
+            (re)allocated the registers, this is the case, because we
+            always allocate enough to have at least one -1 at the end.
+
+            We do this even when no_sub is set because some applications
+             (XEmacs) reuse register structures which may contain stale
+            information, and permit attempts to access those registers.
+
+            It would be possible to require the caller to do this, but we'd
+            have to change the API for this function to reflect that, and
+            audit all callers. */
+         if (regs && regs->num_regs > 0)
+           for (mcnt = num_regs; mcnt < regs->num_regs; mcnt++)
+             regs->start[mcnt] = regs->end[mcnt] = -1;
+
           DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n",
                         nfailure_points_pushed, nfailure_points_popped,
                         nfailure_points_pushed - nfailure_points_popped);
@@ -4699,7 +4816,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
                  Emchar pat_ch, buf_ch;
                  Bytecount pat_len;
 
-                 PREFETCH ();
+                 REGEX_PREFETCH ();
                  pat_ch = charptr_emchar (p);
                  buf_ch = charptr_emchar (d);
                  if (RE_TRANSLATE (buf_ch) != pat_ch)
@@ -4711,7 +4828,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
                  
                  mcnt -= pat_len;
 #else /* not MULE */
-                 PREFETCH ();
+                 REGEX_PREFETCH ();
                  if ((unsigned char) RE_TRANSLATE (*d++) != *p++)
                     goto fail;
                  mcnt--;
@@ -4723,7 +4840,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
            {
              do
                {
-                 PREFETCH ();
+                 REGEX_PREFETCH ();
                  if (*d++ != *p++) goto fail;
                }
              while (--mcnt);
@@ -4736,7 +4853,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
        case anychar:
           DEBUG_PRINT1 ("EXECUTING anychar.\n");
 
-          PREFETCH ();
+          REGEX_PREFETCH ();
 
           if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n')
               || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000'))
@@ -4752,22 +4869,22 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
        case charset_not:
          {
            REGISTER unsigned char c;
-           boolean not = (re_opcode_t) *(p - 1) == charset_not;
+           re_bool not_p = (re_opcode_t) *(p - 1) == charset_not;
 
-            DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : "");
+            DEBUG_PRINT2 ("EXECUTING charset%s.\n", not_p ? "_not" : "");
 
-           PREFETCH ();
+           REGEX_PREFETCH ();
            c = TRANSLATE (*d); /* The character to match.  */
 
             /* Cast to `unsigned' instead of `unsigned char' in case the
                bit list is a full 32 bytes long.  */
            if (c < (unsigned) (*p * BYTEWIDTH)
                && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
-             not = !not;
+             not_p = !not_p;
 
            p += 1 + *p;
 
-           if (!not) goto fail;
+           if (!not_p) goto fail;
 
            SET_REGS_MATCHED ();
             INC_CHARPTR (d); /* XEmacs change */
@@ -4779,20 +4896,20 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
        case charset_mule_not:
          {
            REGISTER Emchar c;
-           boolean not = (re_opcode_t) *(p - 1) == charset_mule_not;
+           re_bool not_p = (re_opcode_t) *(p - 1) == charset_mule_not;
 
-            DEBUG_PRINT2 ("EXECUTING charset_mule%s.\n", not ? "_not" : "");
+            DEBUG_PRINT2 ("EXECUTING charset_mule%s.\n", not_p ? "_not" : "");
 
-           PREFETCH ();
+           REGEX_PREFETCH ();
            c = charptr_emchar ((const Bufbyte *) d);
            c = TRANSLATE_EXTENDED_UNSAFE (c); /* The character to match.  */
 
            if (EQ (Qt, unified_range_table_lookup (p, c, Qnil)))
-             not = !not;
+             not_p = !not_p;
 
            p += unified_range_table_bytes_used (p);
 
-           if (!not) goto fail;
+           if (!not_p) goto fail;
 
            SET_REGS_MATCHED ();
            INC_CHARPTR (d);
@@ -4926,7 +5043,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
                || just_past_start_mem == p - 1)
              && (p + 2) < pend)
             {
-              boolean is_a_jump_n = false;
+              re_bool is_a_jump_n = false;
 
               p1 = p + 2;
               mcnt = 0;
@@ -4968,7 +5085,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
 
                   if (EVER_MATCHED_SOMETHING (reg_info[*p]))
                    {
-                     unsigned r;
+                     int r;
 
                       EVER_MATCHED_SOMETHING (reg_info[*p]) = 0;
 
@@ -5035,7 +5152,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
                if (d2 == dend2) break;
 
                /* If necessary, advance to next segment in data.  */
-               PREFETCH ();
+               REGEX_PREFETCH ();
 
                /* How many characters left in this segment to match.  */
                mcnt = dend - d;
@@ -5262,15 +5379,15 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
                else if ((re_opcode_t) p1[3] == charset
                         || (re_opcode_t) p1[3] == charset_not)
                  {
-                   int not = (re_opcode_t) p1[3] == charset_not;
+                   int not_p = (re_opcode_t) p1[3] == charset_not;
 
                    if (c < (unsigned char) (p1[4] * BYTEWIDTH)
                        && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
-                     not = !not;
+                     not_p = !not_p;
 
-                    /* `not' is equal to 1 if c would match, which means
+                    /* `not_p' is equal to 1 if c would match, which means
                         that we can't change to pop_failure_jump.  */
-                   if (!not)
+                   if (!not_p)
                       {
                        p[-3] = (unsigned char) pop_failure_jump;
                         DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
@@ -5353,7 +5470,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
                actual values.  Otherwise, we will restore only one
                register from the stack, since lowest will == highest in
                `pop_failure_point'.  */
-            unsigned dummy_low_reg, dummy_high_reg;
+            int dummy_low_reg, dummy_high_reg;
             unsigned char *pdummy;
             re_char *sdummy = NULL;
 
@@ -5471,17 +5588,34 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
              result = 1;
            else
              {
-               const unsigned char *d_before =
-                 (const unsigned char *) POS_BEFORE_GAP_UNSAFE (d);
-               const unsigned char *d_after =
-                 (const unsigned char *) POS_AFTER_GAP_UNSAFE (d);
+               re_char *d_before = POS_BEFORE_GAP_UNSAFE (d);
+               re_char *d_after = POS_AFTER_GAP_UNSAFE (d);
+
+               /* emch1 is the character before d, syn1 is the syntax of emch1,
+                  emch2 is the character at d, and syn2 is the syntax of emch2. */
                Emchar emch1, emch2;
+               int syn1, syn2;
+#ifdef emacs
+               int pos_before;
+#endif
 
                DEC_CHARPTR (d_before);
                emch1 = charptr_emchar (d_before);
                emch2 = charptr_emchar (d_after);
-               result = (WORDCHAR_P_UNSAFE (emch1) !=
-                         WORDCHAR_P_UNSAFE (emch2));
+
+#ifdef emacs
+               pos_before = SYNTAX_CACHE_BYTE_TO_CHAR (PTR_TO_OFFSET (d)) - 1;
+               UPDATE_SYNTAX_CACHE (pos_before);
+#endif
+               syn1 = SYNTAX_FROM_CACHE (XCHAR_TABLE (regex_emacs_buffer->mirror_syntax_table),
+                                         emch1);
+#ifdef emacs
+               UPDATE_SYNTAX_CACHE_FORWARD (pos_before + 1);
+#endif
+               syn2 = SYNTAX_FROM_CACHE (XCHAR_TABLE (regex_emacs_buffer->mirror_syntax_table),
+                                         emch2);
+
+               result = ((syn1 == Sword) != (syn2 == Sword));
              }
            if (result == should_succeed)
              break;
@@ -5495,6 +5629,8 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
 
        case wordbeg:
           DEBUG_PRINT1 ("EXECUTING wordbeg.\n");
+         if (AT_STRINGS_END (d))
+           goto fail;
          {
            /* XEmacs: this originally read:
 
@@ -5502,23 +5638,33 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
              break;
 
              */
-           const unsigned char *dtmp =
-             (const unsigned char *) POS_AFTER_GAP_UNSAFE (d);
+           re_char *dtmp = POS_AFTER_GAP_UNSAFE (d);
            Emchar emch = charptr_emchar (dtmp);
-           if (!WORDCHAR_P_UNSAFE (emch))
+#ifdef emacs
+           int charpos = SYNTAX_CACHE_BYTE_TO_CHAR (PTR_TO_OFFSET (d));
+           UPDATE_SYNTAX_CACHE (charpos);
+#endif
+           if (SYNTAX_FROM_CACHE (XCHAR_TABLE (regex_emacs_buffer->mirror_syntax_table),
+                                  emch) != Sword)
              goto fail;
            if (AT_STRINGS_BEG (d))
              break;
-           dtmp = (const unsigned char *) POS_BEFORE_GAP_UNSAFE (d);
+           dtmp = POS_BEFORE_GAP_UNSAFE (d);
            DEC_CHARPTR (dtmp);
            emch = charptr_emchar (dtmp);
-           if (!WORDCHAR_P_UNSAFE (emch))
+#ifdef emacs
+           UPDATE_SYNTAX_CACHE_BACKWARD (charpos - 1);
+#endif
+           if (SYNTAX_FROM_CACHE (XCHAR_TABLE (regex_emacs_buffer->mirror_syntax_table),
+                                  emch) != Sword)
              break;
            goto fail;
          }
 
        case wordend:
           DEBUG_PRINT1 ("EXECUTING wordend.\n");
+         if (AT_STRINGS_BEG (d))
+           goto fail;
          {
            /* XEmacs: this originally read:
 
@@ -5528,20 +5674,27 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
 
              The or condition is incorrect (reversed).
              */
-           const unsigned char *dtmp;
+           re_char *dtmp;
            Emchar emch;
-           if (AT_STRINGS_BEG (d))
-             goto fail;
-           dtmp = (const unsigned char *) POS_BEFORE_GAP_UNSAFE (d);
+#ifdef emacs
+           int charpos = SYNTAX_CACHE_BYTE_TO_CHAR (PTR_TO_OFFSET (d)) - 1;
+           UPDATE_SYNTAX_CACHE (charpos);
+#endif
+           dtmp = POS_BEFORE_GAP_UNSAFE (d);
            DEC_CHARPTR (dtmp);
            emch = charptr_emchar (dtmp);
-           if (!WORDCHAR_P_UNSAFE (emch))
+           if (SYNTAX_FROM_CACHE (XCHAR_TABLE (regex_emacs_buffer->mirror_syntax_table),
+                                  emch) != Sword)
              goto fail;
            if (AT_STRINGS_END (d))
              break;
-           dtmp = (const unsigned char *) POS_AFTER_GAP_UNSAFE (d);
+           dtmp = POS_AFTER_GAP_UNSAFE (d);
            emch = charptr_emchar (dtmp);
-           if (!WORDCHAR_P_UNSAFE (emch))
+#ifdef emacs
+           UPDATE_SYNTAX_CACHE_FORWARD (charpos + 1);
+#endif
+           if (SYNTAX_FROM_CACHE (XCHAR_TABLE (regex_emacs_buffer->mirror_syntax_table),
+                                  emch) != Sword)
              break;
            goto fail;
          }
@@ -5549,7 +5702,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
 #ifdef emacs
        case before_dot:
           DEBUG_PRINT1 ("EXECUTING before_dot.\n");
-         if (!regex_emacs_buffer_p
+         if (! (NILP (regex_match_object) || BUFFERP (regex_match_object))
              || (BUF_PTR_BYTE_POS (regex_emacs_buffer, (unsigned char *) d)
                  >= BUF_PT (regex_emacs_buffer)))
            goto fail;
@@ -5557,7 +5710,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
 
        case at_dot:
           DEBUG_PRINT1 ("EXECUTING at_dot.\n");
-         if (!regex_emacs_buffer_p
+         if (! (NILP (regex_match_object) || BUFFERP (regex_match_object))
              || (BUF_PTR_BYTE_POS (regex_emacs_buffer, (unsigned char *) d)
                  != BUF_PT (regex_emacs_buffer)))
            goto fail;
@@ -5565,7 +5718,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
 
        case after_dot:
           DEBUG_PRINT1 ("EXECUTING after_dot.\n");
-          if (!regex_emacs_buffer_p
+          if (! (NILP (regex_match_object) || BUFFERP (regex_match_object))
              || (BUF_PTR_BYTE_POS (regex_emacs_buffer, (unsigned char *) d)
                  <= BUF_PT (regex_emacs_buffer)))
            goto fail;
@@ -5594,11 +5747,22 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
            int matches;
            Emchar emch;
 
-           PREFETCH ();
+           REGEX_PREFETCH ();
+#ifdef emacs
+           {
+             int charpos = SYNTAX_CACHE_BYTE_TO_CHAR (PTR_TO_OFFSET (d));
+             UPDATE_SYNTAX_CACHE (charpos);
+           }
+#endif
+
            emch = charptr_emchar ((const Bufbyte *) d);
-           matches = (SYNTAX_UNSAFE
-                      (XCHAR_TABLE (regex_emacs_buffer->mirror_syntax_table),
+#ifdef UTF2000
+           matches = (SYNTAX_FROM_CACHE (XCHAR_TABLE (regex_emacs_buffer->syntax_table),
                        emch) == (enum syntaxcode) mcnt);
+#else
+           matches = (SYNTAX_FROM_CACHE (XCHAR_TABLE (regex_emacs_buffer->mirror_syntax_table),
+                       emch) == (enum syntaxcode) mcnt);
+#endif
            INC_CHARPTR (d);
            if (matches != should_succeed)
              goto fail;
@@ -5627,7 +5791,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
            Emchar emch;
 
            mcnt = *p++;
-           PREFETCH ();
+           REGEX_PREFETCH ();
            emch = charptr_emchar ((const Bufbyte *) d);
            INC_CHARPTR (d);
            if (check_category_char(emch, regex_emacs_buffer->category_table,
@@ -5645,7 +5809,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
 #else /* not emacs */
        case wordchar:
           DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n");
-         PREFETCH ();
+         REGEX_PREFETCH ();
           if (!WORDCHAR_P_UNSAFE ((int) (*d)))
             goto fail;
          SET_REGS_MATCHED ();
@@ -5654,7 +5818,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
 
        case notwordchar:
           DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n");
-         PREFETCH ();
+         REGEX_PREFETCH ();
           if (!WORDCHAR_P_UNSAFE ((int) (*d)))
             goto fail;
           SET_REGS_MATCHED ();
@@ -5685,7 +5849,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
          assert (p <= pend);
           if (p < pend)
             {
-              boolean is_a_jump_n = false;
+              re_bool is_a_jump_n = false;
 
               /* If failed to a backwards jump that's part of a repetition
                  loop, need to pop this failure point and use the next one.  */
@@ -5738,7 +5902,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1,
 
    We don't handle duplicates properly (yet).  */
 
-static boolean
+static re_bool
 group_match_null_string_p (unsigned char **p, unsigned char *end,
                           register_info_type *reg_info)
 {
@@ -5846,7 +6010,7 @@ group_match_null_string_p (unsigned char **p, unsigned char *end,
    It expects P to be the first byte of a single alternative and END one
    byte past the last. The alternative can contain groups.  */
 
-static boolean
+static re_bool
 alt_match_null_string_p (unsigned char *p, unsigned char *end,
                         register_info_type *reg_info)
 {
@@ -5882,12 +6046,12 @@ alt_match_null_string_p (unsigned char *p, unsigned char *end,
 
    Sets P to one after the op and its arguments, if any.  */
 
-static boolean
+static re_bool
 common_op_match_null_string_p (unsigned char **p, unsigned char *end,
                               register_info_type *reg_info)
 {
   int mcnt;
-  boolean ret;
+  re_bool ret;
   int reg_no;
   unsigned char *p1 = *p;
 
@@ -6206,14 +6370,14 @@ regcomp (regex_t *preg, const char *pattern, int cflags)
    We return 0 if we find a match and REG_NOMATCH if not.  */
 
 int
-regexec (const regex_t *preg, const char *string, size_t nmatch,
+regexec (const regex_t *preg, const char *string, Element_count nmatch,
         regmatch_t pmatch[], int eflags)
 {
   int ret;
   struct re_registers regs;
   regex_t private_preg;
   int len = strlen (string);
-  boolean want_reg_info = !preg->no_sub && nmatch > 0;
+  re_bool want_reg_info = !preg->no_sub && nmatch > 0;
 
   private_preg = *preg;
 
@@ -6244,7 +6408,7 @@ regexec (const regex_t *preg, const char *string, size_t nmatch,
     {
       if (ret >= 0)
         {
-          unsigned r;
+          Element_count r;
 
           for (r = 0; r < nmatch; r++)
             {
@@ -6266,14 +6430,16 @@ regexec (const regex_t *preg, const char *string, size_t nmatch,
 /* Returns a message corresponding to an error code, ERRCODE, returned
    from either regcomp or regexec.   We don't use PREG here.  */
 
-size_t
-regerror (int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
+Memory_count
+regerror (int errcode, const regex_t *preg, char *errbuf,
+         Memory_count errbuf_size)
 {
   const char *msg;
-  size_t msg_size;
+  Memory_count msg_size;
 
   if (errcode < 0
-      || errcode >= (sizeof (re_error_msgid) / sizeof (re_error_msgid[0])))
+      || (size_t) errcode >= (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.