]> code.delx.au - gnu-emacs/blobdiff - src/syntax.c
Port USE_STACK_LISP_OBJECTS fix to Clang
[gnu-emacs] / src / syntax.c
index 390d732944dbe4d83ba1a0b4b27a0a0cc19793c3..7e98854767549bca4d4fd05f39755ea6ffca8cc2 100644 (file)
@@ -1,5 +1,5 @@
 /* GNU Emacs routines to deal with syntax tables; also word and list parsing.
-   Copyright (C) 1985, 1987, 1993-1995, 1997-1999, 2001-2013 Free
+   Copyright (C) 1985, 1987, 1993-1995, 1997-1999, 2001-2016 Free
    Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -23,20 +23,19 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <sys/types.h>
 
 #include "lisp.h"
-#include "commands.h"
 #include "character.h"
 #include "buffer.h"
-#include "keymap.h"
 #include "regex.h"
-
-/* Make syntax table lookup grant data in gl_state.  */
-#define SYNTAX_ENTRY_VIA_PROPERTY
-
 #include "syntax.h"
 #include "intervals.h"
 #include "category.h"
 
-/* Then there are seven single-bit flags that have the following meanings:
+/* Make syntax table lookup grant data in gl_state.  */
+#define SYNTAX(c) syntax_property (c, 1)
+#define SYNTAX_ENTRY(c) syntax_property_entry (c, 1)
+#define SYNTAX_WITH_FLAGS(c) syntax_property_with_flags (c, 1)
+
+/* Eight single-bit flags have the following meanings:
   1. This character is the first of a two-character comment-start sequence.
   2. This character is the second of a two-character comment-start sequence.
   3. This character is the first of a two-character comment-end sequence.
@@ -48,63 +47,92 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
   Note that any two-character sequence whose first character has flag 1
   and whose second character has flag 2 will be interpreted as a comment start.
 
-  bit 6 and 8 are used to discriminate between different comment styles.
+  Bits 6 and 8 discriminate among different comment styles.
   Languages such as C++ allow two orthogonal syntax start/end pairs
-  and bit 6 is used to determine whether a comment-end or Scommentend
+  and bit 6 determines whether a comment-end or Scommentend
   ends style a or b.  Comment markers can start style a, b, c, or bc.
   Style a is always the default.
-  For 2-char comment markers, the style b flag is only looked up on the second
+  For 2-char comment markers, the style b flag is looked up only on the second
   char of the comment marker and on the first char of the comment ender.
-  For style c (like to for the nested flag), the flag can be placed on any
-  one of the chars.
-  */
+  For style c (like the nested flag), the flag can be placed on any of
+  the chars.  */
 
-/* These macros extract specific flags from an integer
+/* These functions extract specific flags from an integer
    that holds the syntax code and the flags.  */
 
-#define SYNTAX_FLAGS_COMSTART_FIRST(flags) (((flags) >> 16) & 1)
-
-#define SYNTAX_FLAGS_COMSTART_SECOND(flags) (((flags) >> 17) & 1)
-
-#define SYNTAX_FLAGS_COMEND_FIRST(flags) (((flags) >> 18) & 1)
-
-#define SYNTAX_FLAGS_COMEND_SECOND(flags) (((flags) >> 19) & 1)
-
-#define SYNTAX_FLAGS_PREFIX(flags) (((flags) >> 20) & 1)
+static bool
+SYNTAX_FLAGS_COMSTART_FIRST (int flags)
+{
+  return (flags >> 16) & 1;
+}
+static bool
+SYNTAX_FLAGS_COMSTART_SECOND (int flags)
+{
+  return (flags >> 17) & 1;
+}
+static bool
+SYNTAX_FLAGS_COMEND_FIRST (int flags)
+{
+  return (flags >> 18) & 1;
+}
+static bool
+SYNTAX_FLAGS_COMEND_SECOND (int flags)
+{
+  return (flags >> 19) & 1;
+}
+static bool
+SYNTAX_FLAGS_PREFIX (int flags)
+{
+  return (flags >> 20) & 1;
+}
+static bool
+SYNTAX_FLAGS_COMMENT_STYLEB (int flags)
+{
+  return (flags >> 21) & 1;
+}
+static bool
+SYNTAX_FLAGS_COMMENT_STYLEC (int flags)
+{
+  return (flags >> 23) & 1;
+}
+static int
+SYNTAX_FLAGS_COMMENT_STYLEC2 (int flags)
+{
+  return (flags >> 22) & 2; /* SYNTAX_FLAGS_COMMENT_STYLEC (flags) * 2 */
+}
+static bool
+SYNTAX_FLAGS_COMMENT_NESTED (int flags)
+{
+  return (flags >> 22) & 1;
+}
 
-#define SYNTAX_FLAGS_COMMENT_STYLEB(flags) (((flags) >> 21) & 1)
-#define SYNTAX_FLAGS_COMMENT_STYLEC(flags) (((flags) >> 22) & 2)
 /* FLAGS should be the flags of the main char of the comment marker, e.g.
    the second for comstart and the first for comend.  */
-#define SYNTAX_FLAGS_COMMENT_STYLE(flags, other_flags) \
-  (SYNTAX_FLAGS_COMMENT_STYLEB (flags) \
-   | SYNTAX_FLAGS_COMMENT_STYLEC (flags) \
-   | SYNTAX_FLAGS_COMMENT_STYLEC (other_flags))
-
-#define SYNTAX_FLAGS_COMMENT_NESTED(flags) (((flags) >> 22) & 1)
+static int
+SYNTAX_FLAGS_COMMENT_STYLE (int flags, int other_flags)
+{
+  return (SYNTAX_FLAGS_COMMENT_STYLEB (flags)
+         | SYNTAX_FLAGS_COMMENT_STYLEC2 (flags)
+         | SYNTAX_FLAGS_COMMENT_STYLEC2 (other_flags));
+}
 
-/* These macros extract a particular flag for a given character.  */
+/* Extract a particular flag for a given character.  */
 
-#define SYNTAX_COMEND_FIRST(c) \
-  (SYNTAX_FLAGS_COMEND_FIRST (SYNTAX_WITH_FLAGS (c)))
-#define SYNTAX_PREFIX(c) (SYNTAX_FLAGS_PREFIX (SYNTAX_WITH_FLAGS (c)))
+static bool
+SYNTAX_COMEND_FIRST (int c)
+{
+  return SYNTAX_FLAGS_COMEND_FIRST (SYNTAX_WITH_FLAGS (c));
+}
 
 /* We use these constants in place for comment-style and
-   string-ender-char to distinguish  comments/strings started by
+   string-ender-char to distinguish comments/strings started by
    comment_fence and string_fence codes.  */
 
-#define ST_COMMENT_STYLE (256 + 1)
-#define ST_STRING_STYLE (256 + 2)
-
-static Lisp_Object Qsyntax_table_p;
-static Lisp_Object Qsyntax_table, Qscan_error;
-
-#ifndef __GNUC__
-/* Used as a temporary in SYNTAX_ENTRY and other macros in syntax.h,
-   if not compiled with GCC.  No need to mark it, since it is used
-   only very temporarily.  */
-Lisp_Object syntax_temp;
-#endif
+enum
+  {
+    ST_COMMENT_STYLE = 256 + 1,
+    ST_STRING_STYLE = 256 + 2
+  };
 
 /* This is the internal form of the parse state used in parse-partial-sexp.  */
 
@@ -114,7 +142,7 @@ struct lisp_parse_state
     int instring;  /* -1 if not within string, else desired terminator.  */
     EMACS_INT incomment; /* -1 if in unnestable comment else comment nesting */
     int comstyle;  /* comment style a=0, or b=1, or ST_COMMENT_STYLE.  */
-    int quoted;           /* Nonzero if just after an escape char at end of parsing */
+    bool quoted;   /* True if just after an escape char at end of parsing.  */
     EMACS_INT mindepth;        /* Minimum depth seen while scanning.  */
     /* Char number of most recent start-of-expression at current level */
     ptrdiff_t thislevelstart;
@@ -143,32 +171,134 @@ static ptrdiff_t find_start_begv;
 static EMACS_INT find_start_modiff;
 
 
-static Lisp_Object skip_chars (int, Lisp_Object, Lisp_Object, int);
-static Lisp_Object skip_syntaxes (int, Lisp_Object, Lisp_Object);
-static Lisp_Object scan_lists (EMACS_INT, EMACS_INT, EMACS_INT, int);
+static Lisp_Object skip_chars (bool, Lisp_Object, Lisp_Object, bool);
+static Lisp_Object skip_syntaxes (bool, Lisp_Object, Lisp_Object);
+static Lisp_Object scan_lists (EMACS_INT, EMACS_INT, EMACS_INT, bool);
 static void scan_sexps_forward (struct lisp_parse_state *,
                                 ptrdiff_t, ptrdiff_t, ptrdiff_t, EMACS_INT,
-                                int, Lisp_Object, int);
-static int in_classes (int, Lisp_Object);
+                                bool, Lisp_Object, int);
+static bool in_classes (int, Lisp_Object);
+static void parse_sexp_propertize (ptrdiff_t charpos);
 
 /* This setter is used only in this file, so it can be private.  */
 static void
 bset_syntax_table (struct buffer *b, Lisp_Object val)
 {
-  b->INTERNAL_FIELD (syntax_table) = val;
+  b->syntax_table_ = val;
 }
 \f
 /* Whether the syntax of the character C has the prefix flag set.  */
-int syntax_prefix_flag_p (int c)
+bool
+syntax_prefix_flag_p (int c)
 {
-  return SYNTAX_PREFIX (c);
+  return SYNTAX_FLAGS_PREFIX (SYNTAX_WITH_FLAGS (c));
 }
 
 struct gl_state_s gl_state;            /* Global state of syntax parser.  */
 
-#define INTERVALS_AT_ONCE 10           /* 1 + max-number of intervals
+enum { INTERVALS_AT_ONCE = 10 };       /* 1 + max-number of intervals
                                           to scan to property-change.  */
 
+/* Set the syntax entry VAL for char C in table TABLE.  */
+
+static void
+SET_RAW_SYNTAX_ENTRY (Lisp_Object table, int c, Lisp_Object val)
+{
+  CHAR_TABLE_SET (table, c, val);
+}
+
+/* Set the syntax entry VAL for char-range RANGE in table TABLE.
+   RANGE is a cons (FROM . TO) specifying the range of characters.  */
+
+static void
+SET_RAW_SYNTAX_ENTRY_RANGE (Lisp_Object table, Lisp_Object range,
+                           Lisp_Object val)
+{
+  Fset_char_table_range (table, range, val);
+}
+
+/* Extract the information from the entry for character C
+   in the current syntax table.  */
+
+static Lisp_Object
+SYNTAX_MATCH (int c)
+{
+  Lisp_Object ent = SYNTAX_ENTRY (c);
+  return CONSP (ent) ? XCDR (ent) : Qnil;
+}
+
+/* This should be called with FROM at the start of forward
+   search, or after the last position of the backward search.  It
+   makes sure that the first char is picked up with correct table, so
+   one does not need to call UPDATE_SYNTAX_TABLE immediately after the
+   call.
+   Sign of COUNT gives the direction of the search.
+ */
+
+static void
+SETUP_SYNTAX_TABLE (ptrdiff_t from, ptrdiff_t count)
+{
+  SETUP_BUFFER_SYNTAX_TABLE ();
+  gl_state.b_property = BEGV;
+  gl_state.e_property = ZV + 1;
+  gl_state.object = Qnil;
+  gl_state.offset = 0;
+  if (parse_sexp_lookup_properties)
+    {
+      if (count > 0)
+       update_syntax_table_forward (from, true, Qnil);
+      else if (from > BEGV)
+       {
+         update_syntax_table (from - 1, count, true, Qnil);
+         parse_sexp_propertize (from - 1);
+       }
+    }
+}
+
+/* Same as above, but in OBJECT.  If OBJECT is nil, use current buffer.
+   If it is t (which is only used in fast_c_string_match_ignore_case),
+   ignore properties altogether.
+
+   This is meant for regex.c to use.  For buffers, regex.c passes arguments
+   to the UPDATE_SYNTAX_TABLE functions which are relative to BEGV.
+   So if it is a buffer, we set the offset field to BEGV.  */
+
+void
+SETUP_SYNTAX_TABLE_FOR_OBJECT (Lisp_Object object,
+                              ptrdiff_t from, ptrdiff_t count)
+{
+  SETUP_BUFFER_SYNTAX_TABLE ();
+  gl_state.object = object;
+  if (BUFFERP (gl_state.object))
+    {
+      struct buffer *buf = XBUFFER (gl_state.object);
+      gl_state.b_property = 1;
+      gl_state.e_property = BUF_ZV (buf) - BUF_BEGV (buf) + 1;
+      gl_state.offset = BUF_BEGV (buf) - 1;
+    }
+  else if (NILP (gl_state.object))
+    {
+      gl_state.b_property = 1;
+      gl_state.e_property = ZV - BEGV + 1;
+      gl_state.offset = BEGV - 1;
+    }
+  else if (EQ (gl_state.object, Qt))
+    {
+      gl_state.b_property = 0;
+      gl_state.e_property = PTRDIFF_MAX;
+      gl_state.offset = 0;
+    }
+  else
+    {
+      gl_state.b_property = 0;
+      gl_state.e_property = 1 + SCHARS (gl_state.object);
+      gl_state.offset = 0;
+    }
+  if (parse_sexp_lookup_properties)
+    update_syntax_table (from + gl_state.offset - (count <= 0),
+                        count, 1, gl_state.object);
+}
+
 /* Update gl_state to an appropriate interval which contains CHARPOS.  The
    sign of COUNT give the relative position of CHARPOS wrt the previously
    valid interval.  If INIT, only [be]_property fields of gl_state are
@@ -183,12 +313,12 @@ struct gl_state_s gl_state;               /* Global state of syntax parser.  */
    start/end of OBJECT.  */
 
 void
-update_syntax_table (ptrdiff_t charpos, EMACS_INT count, int init,
+update_syntax_table (ptrdiff_t charpos, EMACS_INT count, bool init,
                     Lisp_Object object)
 {
   Lisp_Object tmp_table;
-  unsigned cnt = 0;
-  int invalidate = 1;
+  int cnt = 0;
+  bool invalidate = true;
   INTERVAL i;
 
   if (init)
@@ -198,7 +328,7 @@ update_syntax_table (ptrdiff_t charpos, EMACS_INT count, int init,
       gl_state.stop = gl_state.e_property;
       i = interval_of (charpos, object);
       gl_state.backward_i = gl_state.forward_i = i;
-      invalidate = 0;
+      invalidate = false;
       if (!i)
        return;
       /* interval_of updates only ->position of the return value, so
@@ -234,7 +364,7 @@ update_syntax_table (ptrdiff_t charpos, EMACS_INT count, int init,
       i = update_interval (i, charpos);
       if (INTERVAL_LAST_POS (i) != gl_state.b_property)
        {
-         invalidate = 0;
+         invalidate = false;
          gl_state.forward_i = i;
          gl_state.e_property = INTERVAL_LAST_POS (i) - gl_state.offset;
        }
@@ -247,7 +377,7 @@ update_syntax_table (ptrdiff_t charpos, EMACS_INT count, int init,
       i = update_interval (i, charpos);
       if (i->position != gl_state.e_property)
        {
-         invalidate = 0;
+         invalidate = false;
          gl_state.backward_i = i;
          gl_state.b_property = i->position - gl_state.offset;
        }
@@ -335,21 +465,75 @@ update_syntax_table (ptrdiff_t charpos, EMACS_INT count, int init,
     }
   eassert (i == NULL); /* This property goes to the end.  */
   if (count > 0)
-    gl_state.e_property = gl_state.stop;
+    {
+      gl_state.e_property = gl_state.stop;
+      gl_state.forward_i = i;
+    }
   else
     gl_state.b_property = gl_state.start;
 }
+
+static void
+parse_sexp_propertize (ptrdiff_t charpos)
+{
+  EMACS_INT zv = ZV;
+  if (syntax_propertize__done <= charpos
+      && syntax_propertize__done < zv)
+    {
+      EMACS_INT modiffs = CHARS_MODIFF;
+      safe_call1 (Qinternal__syntax_propertize,
+                 make_number (min (zv, 1 + charpos)));
+      if (modiffs != CHARS_MODIFF)
+       error ("parse-sexp-propertize-function modified the buffer!");
+      if (syntax_propertize__done <= charpos
+         && syntax_propertize__done < zv)
+       error ("parse-sexp-propertize-function did not move"
+              " syntax-propertize--done");
+      SETUP_SYNTAX_TABLE (charpos, 1);
+    }
+  else if (gl_state.e_property > syntax_propertize__done)
+    {
+      gl_state.e_property = syntax_propertize__done;
+      gl_state.e_property_truncated = true;
+    }
+  else if (gl_state.e_property_truncated
+          && gl_state.e_property < syntax_propertize__done)
+    { /* When moving backward, e_property might be set without resetting
+        e_property_truncated, so the e_property_truncated flag may
+        occasionally be left raised spuriously.  This should be rare.  */
+      gl_state.e_property_truncated = false;
+      update_syntax_table_forward (charpos, false, Qnil);
+    }
+}
+
+void
+update_syntax_table_forward (ptrdiff_t charpos, bool init,
+                            Lisp_Object object)
+{
+  if (gl_state.e_property_truncated)
+    {
+      eassert (NILP (object));
+      eassert (charpos >= gl_state.e_property);
+      parse_sexp_propertize (charpos);
+    }
+  else
+    {
+      update_syntax_table (charpos, 1, init, object);
+      if (NILP (object) && gl_state.e_property > syntax_propertize__done)
+       parse_sexp_propertize (charpos);
+    }
+}
 \f
-/* Returns TRUE if char at CHARPOS is quoted.
+/* Returns true if char at CHARPOS is quoted.
    Global syntax-table data should be set up already to be good at CHARPOS
-   or after.  On return global syntax data is good for lookup at CHARPOS. */
+   or after.  On return global syntax data is good for lookup at CHARPOS.  */
 
-static int
+static bool
 char_quoted (ptrdiff_t charpos, ptrdiff_t bytepos)
 {
-  register enum syntaxcode code;
-  register ptrdiff_t beg = BEGV;
-  register int quoted = 0;
+  enum syntaxcode code;
+  ptrdiff_t beg = BEGV;
+  bool quoted = 0;
   ptrdiff_t orig = charpos;
 
   while (charpos > beg)
@@ -402,17 +586,6 @@ find_defun_start (ptrdiff_t pos, ptrdiff_t pos_byte)
 {
   ptrdiff_t opoint = PT, opoint_byte = PT_BYTE;
 
-  if (!open_paren_in_column_0_is_defun_start)
-    {
-      find_start_value = BEGV;
-      find_start_value_byte = BEGV_BYTE;
-      find_start_buffer = current_buffer;
-      find_start_modiff = MODIFF;
-      find_start_begv = BEGV;
-      find_start_pos = pos;
-      return BEGV;
-    }
-
   /* Use previous finding, if it's valid and applies to this inquiry.  */
   if (current_buffer == find_start_buffer
       /* Reuse the defun-start even if POS is a little farther on.
@@ -424,6 +597,13 @@ find_defun_start (ptrdiff_t pos, ptrdiff_t pos_byte)
       && MODIFF == find_start_modiff)
     return find_start_value;
 
+  if (!open_paren_in_column_0_is_defun_start)
+    {
+      find_start_value = BEGV;
+      find_start_value_byte = BEGV_BYTE;
+      goto found;
+    }
+
   /* Back up to start of line.  */
   scan_newline (pos, pos_byte, BEGV, BEGV_BYTE, -1, 1);
 
@@ -454,22 +634,24 @@ find_defun_start (ptrdiff_t pos, ptrdiff_t pos_byte)
   /* Record what we found, for the next try.  */
   find_start_value = PT;
   find_start_value_byte = PT_BYTE;
+  TEMP_SET_PT_BOTH (opoint, opoint_byte);
+
+ found:
   find_start_buffer = current_buffer;
   find_start_modiff = MODIFF;
   find_start_begv = BEGV;
   find_start_pos = pos;
 
-  TEMP_SET_PT_BOTH (opoint, opoint_byte);
-
   return find_start_value;
 }
 \f
 /* Return the SYNTAX_COMEND_FIRST of the character before POS, POS_BYTE.  */
 
-static int
+static bool
 prev_char_comend_first (ptrdiff_t pos, ptrdiff_t pos_byte)
 {
-  int c, val;
+  int c;
+  bool val;
 
   DEC_BOTH (pos, pos_byte);
   UPDATE_SYNTAX_TABLE_BACKWARD (pos);
@@ -479,28 +661,11 @@ prev_char_comend_first (ptrdiff_t pos, ptrdiff_t pos_byte)
   return val;
 }
 
-/* Return the SYNTAX_COMSTART_FIRST of the character before POS, POS_BYTE.  */
-
-/* static int
- * prev_char_comstart_first (pos, pos_byte)
- *      int pos, pos_byte;
- * {
- *   int c, val;
- *
- *   DEC_BOTH (pos, pos_byte);
- *   UPDATE_SYNTAX_TABLE_BACKWARD (pos);
- *   c = FETCH_CHAR (pos_byte);
- *   val = SYNTAX_COMSTART_FIRST (c);
- *   UPDATE_SYNTAX_TABLE_FORWARD (pos + 1);
- *   return val;
- * } */
-
-/* Checks whether charpos FROM is at the end of a comment.
+/* Check whether charpos FROM is at the end of a comment.
    FROM_BYTE is the bytepos corresponding to FROM.
    Do not move back before STOP.
 
-   Return a positive value if we find a comment ending at FROM/FROM_BYTE;
-   return -1 otherwise.
+   Return true if we find a comment ending at FROM/FROM_BYTE.
 
    If successful, store the charpos of the comment's beginning
    into *CHARPOS_PTR, and the bytepos into *BYTEPOS_PTR.
@@ -508,8 +673,10 @@ prev_char_comend_first (ptrdiff_t pos, ptrdiff_t pos_byte)
    Global syntax data remains valid for backward search starting at
    the returned value (or at FROM, if the search was not successful).  */
 
-static int
-back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop, int comnested, int comstyle, ptrdiff_t *charpos_ptr, ptrdiff_t *bytepos_ptr)
+static bool
+back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop,
+             bool comnested, int comstyle, ptrdiff_t *charpos_ptr,
+             ptrdiff_t *bytepos_ptr)
 {
   /* Look back, counting the parity of string-quotes,
      and recording the comment-starters seen.
@@ -520,14 +687,14 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop, int comnested
      OFROM[I] is position of the earliest comment-starter seen
      which is I+2X quotes from the comment-end.
      PARITY is current parity of quotes from the comment end.  */
-  int string_style = -1;       /* Presumed outside of any string. */
-  int string_lossage = 0;
+  int string_style = -1;       /* Presumed outside of any string.  */
+  bool string_lossage = 0;
   /* Not a real lossage: indicates that we have passed a matching comment
      starter plus a non-matching comment-ender, meaning that any matching
      comment-starter we might see later could be a false positive (hidden
      inside another comment).
      Test case:  { a (* b } c (* d *) */
-  int comment_lossage = 0;
+  bool comment_lossage = 0;
   ptrdiff_t comment_end = from;
   ptrdiff_t comment_end_byte = from_byte;
   ptrdiff_t comstart_pos = 0;
@@ -536,8 +703,8 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop, int comnested
      or 0 if we didn't come across it yet.  */
   ptrdiff_t defun_start = 0;
   ptrdiff_t defun_start_byte = 0;
-  register enum syntaxcode code;
-  int nesting = 1;             /* current comment nesting */
+  enum syntaxcode code;
+  ptrdiff_t nesting = 1;               /* Current comment nesting.  */
   int c;
   int syntax = 0;
 
@@ -550,8 +717,8 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop, int comnested
   while (from != stop)
     {
       ptrdiff_t temp_byte;
-      int prev_syntax, com2start, com2end;
-      int comstart;
+      int prev_syntax;
+      bool com2start, com2end, comstart;
 
       /* Move back and examine a character.  */
       DEC_BOTH (from, from_byte);
@@ -623,8 +790,10 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop, int comnested
                   || SYNTAX_FLAGS_COMMENT_NESTED (syntax) != comnested))
        continue;
 
-      /* Ignore escaped characters, except comment-enders.  */
-      if (code != Sendcomment && char_quoted (from, from_byte))
+      /* Ignore escaped characters, except comment-enders which cannot
+         be escaped.  */
+      if ((Vcomment_end_can_be_escaped || code != Sendcomment)
+          && char_quoted (from, from_byte))
        continue;
 
       switch (code)
@@ -714,7 +883,7 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop, int comnested
     {
       from = comment_end;
       from_byte = comment_end_byte;
-      UPDATE_SYNTAX_TABLE_FORWARD (comment_end - 1);
+      UPDATE_SYNTAX_TABLE_FORWARD (comment_end);
     }
   /* If comstart_pos is set and we get here (ie. didn't jump to `lossage'
      or `done'), then we've found the beginning of the non-nested comment.  */
@@ -724,10 +893,10 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop, int comnested
       from_byte = comstart_byte;
       UPDATE_SYNTAX_TABLE_FORWARD (from - 1);
     }
-  else
+  else lossage:
     {
       struct lisp_parse_state state;
-    lossage:
+      bool adjusted = true;
       /* We had two kinds of string delimiters mixed up
         together.  Decode this going forwards.
         Scan fwd from a known safe place (beginning-of-defun)
@@ -738,6 +907,7 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop, int comnested
        {
          defun_start = find_defun_start (comment_end, comment_end_byte);
          defun_start_byte = find_start_value_byte;
+         adjusted = (defun_start > BEGV);
        }
       do
        {
@@ -746,6 +916,16 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop, int comnested
                              comment_end, TYPE_MINIMUM (EMACS_INT),
                              0, Qnil, 0);
          defun_start = comment_end;
+         if (!adjusted)
+           {
+             adjusted = true;
+             find_start_value
+               = CONSP (state.levelstarts) ? XINT (XCAR (state.levelstarts))
+               : state.thislevelstart >= 0 ? state.thislevelstart
+               : find_start_value;
+             find_start_value_byte = CHAR_TO_BYTE (find_start_value);
+           }
+
          if (state.incomment == (comnested ? 1 : -1)
              && state.comstyle == comstyle)
            from = state.comstr_start;
@@ -757,7 +937,7 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop, int comnested
                   is nested, so we need to try again from within the
                   surrounding comment.  Example: { a (* " *)  */
                {
-                 /* FIXME: We should advance by one or two chars. */
+                 /* FIXME: We should advance by one or two chars.  */
                  defun_start = state.comstr_start + 2;
                  defun_start_byte = CHAR_TO_BYTE (defun_start);
                }
@@ -772,7 +952,7 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop, int comnested
   *charpos_ptr = from;
   *bytepos_ptr = from_byte;
 
-  return (from == comment_end) ? -1 : from;
+  return from != comment_end;
 }
 \f
 DEFUN ("syntax-table-p", Fsyntax_table_p, Ssyntax_table_p, 1, 1, 0,
@@ -854,31 +1034,28 @@ One argument, a syntax table.  */)
  into the code it signifies.
  This is used by modify-syntax-entry, and other things.  */
 
-unsigned char syntax_spec_code[0400] =
+unsigned char const syntax_spec_code[0400] =
   { 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
     0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
     0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
     0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
-    (char) Swhitespace, (char) Scomment_fence, (char) Sstring, 0377,
-        (char) Smath, 0377, 0377, (char) Squote,
-    (char) Sopen, (char) Sclose, 0377, 0377,
-       0377, (char) Swhitespace, (char) Spunct, (char) Scharquote,
+    Swhitespace, Scomment_fence, Sstring, 0377, Smath, 0377, 0377, Squote,
+    Sopen, Sclose, 0377, 0377, 0377, Swhitespace, Spunct, Scharquote,
     0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
-    0377, 0377, 0377, 0377,
-       (char) Scomment, 0377, (char) Sendcomment, 0377,
-    (char) Sinherit, 0377, 0377, 0377, 0377, 0377, 0377, 0377,   /* @, A ... */
+    0377, 0377, 0377, 0377, Scomment, 0377, Sendcomment, 0377,
+    Sinherit, 0377, 0377, 0377, 0377, 0377, 0377, 0377,   /* @, A ... */
     0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
-    0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword,
-    0377, 0377, 0377, 0377, (char) Sescape, 0377, 0377, (char) Ssymbol,
+    0377, 0377, 0377, 0377, 0377, 0377, 0377, Sword,
+    0377, 0377, 0377, 0377, Sescape, 0377, 0377, Ssymbol,
     0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,   /* `, a, ... */
     0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
-    0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword,
-    0377, 0377, 0377, 0377, (char) Sstring_fence, 0377, 0377, 0377
+    0377, 0377, 0377, 0377, 0377, 0377, 0377, Sword,
+    0377, 0377, 0377, 0377, Sstring_fence, 0377, 0377, 0377
   };
 
 /* Indexed by syntax code, give the letter that describes it.  */
 
-char syntax_code_spec[16] =
+char const syntax_code_spec[16] =
   {
     ' ', '.', 'w', '_', '(', ')', '\'', '\"', '$', '\\', '/', '<', '>', '@',
     '!', '|'
@@ -904,15 +1081,16 @@ are listed in the documentation of `modify-syntax-entry'.  */)
   CHECK_CHARACTER (character);
   char_int = XINT (character);
   SETUP_BUFFER_SYNTAX_TABLE ();
-  return make_number (syntax_code_spec[(int) SYNTAX (char_int)]);
+  return make_number (syntax_code_spec[SYNTAX (char_int)]);
 }
 
 DEFUN ("matching-paren", Fmatching_paren, Smatching_paren, 1, 1, 0,
        doc: /* Return the matching parenthesis of CHARACTER, or nil if none.  */)
   (Lisp_Object character)
 {
-  int char_int, code;
-  CHECK_NUMBER (character);
+  int char_int;
+  enum syntaxcode code;
+  CHECK_CHARACTER (character);
   char_int = XINT (character);
   SETUP_BUFFER_SYNTAX_TABLE ();
   code = SYNTAX (char_int);
@@ -925,23 +1103,22 @@ DEFUN ("string-to-syntax", Fstring_to_syntax, Sstring_to_syntax, 1, 1, 0,
        doc: /* Convert a syntax descriptor STRING into a raw syntax descriptor.
 STRING should be a string of the form allowed as argument of
 `modify-syntax-entry'.  The return value is a raw syntax descriptor: a
-cons cell \(CODE . MATCHING-CHAR) which can be used, for example, as
+cons cell (CODE . MATCHING-CHAR) which can be used, for example, as
 the value of a `syntax-table' text property.  */)
   (Lisp_Object string)
 {
-  register const unsigned char *p;
-  register enum syntaxcode code;
+  const unsigned char *p;
   int val;
   Lisp_Object match;
 
   CHECK_STRING (string);
 
   p = SDATA (string);
-  code = (enum syntaxcode) syntax_spec_code[*p++];
-  if (((int) code & 0377) == 0377)
+  val = syntax_spec_code[*p++];
+  if (val == 0377)
     error ("Invalid syntax description letter: %c", p[-1]);
 
-  if (code == Sinherit)
+  if (val == Sinherit)
     return Qnil;
 
   if (*p)
@@ -956,7 +1133,6 @@ the value of a `syntax-table' text property.  */)
   else
     match = Qnil;
 
-  val = (int) code;
   while (*p)
     switch (*p++)
       {
@@ -1014,7 +1190,7 @@ The first character of NEWENTRY should be one of the following:
   _           symbol constituent.   .   punctuation.
   (           open-parenthesis.     )   close-parenthesis.
   "           string quote.         \\   escape.
-  $           paired delimiter.     '   expression quote or prefix operator.
+  $           paired delimiter.     \\='   expression quote or prefix operator.
   <           comment starter.      >   comment ender.
   /           character-quote.      @   inherit from parent table.
   |           generic string fence. !   generic comment fence.
@@ -1078,10 +1254,8 @@ DEFUN ("internal-describe-syntax-value", Finternal_describe_syntax_value,
        doc: /* Insert a description of the internal syntax description SYNTAX at point.  */)
   (Lisp_Object syntax)
 {
-  register enum syntaxcode code;
-  int syntax_code;
-  char desc, start1, start2, end1, end2, prefix,
-    comstyleb, comstylec, comnested;
+  int code, syntax_code;
+  bool start1, start2, end1, end2, prefix, comstyleb, comstylec, comnested;
   char str[2];
   Lisp_Object first, match_lisp, value = syntax;
 
@@ -1113,9 +1287,9 @@ DEFUN ("internal-describe-syntax-value", Finternal_describe_syntax_value,
     }
 
   syntax_code = XINT (first) & INT_MAX;
-  code = (enum syntaxcode) (syntax_code & 0377);
+  code = syntax_code & 0377;
   start1 = SYNTAX_FLAGS_COMSTART_FIRST (syntax_code);
-  start2 = SYNTAX_FLAGS_COMSTART_SECOND (syntax_code);;
+  start2 = SYNTAX_FLAGS_COMSTART_SECOND (syntax_code);
   end1 = SYNTAX_FLAGS_COMEND_FIRST (syntax_code);
   end2 = SYNTAX_FLAGS_COMEND_SECOND (syntax_code);
   prefix = SYNTAX_FLAGS_PREFIX (syntax_code);
@@ -1123,14 +1297,13 @@ DEFUN ("internal-describe-syntax-value", Finternal_describe_syntax_value,
   comstylec = SYNTAX_FLAGS_COMMENT_STYLEC (syntax_code);
   comnested = SYNTAX_FLAGS_COMMENT_NESTED (syntax_code);
 
-  if ((int) code < 0 || (int) code >= (int) Smax)
+  if (Smax <= code)
     {
       insert_string ("invalid");
       return syntax;
     }
-  desc = syntax_code_spec[(int) code];
 
-  str[0] = desc, str[1] = 0;
+  str[0] = syntax_code_spec[code], str[1] = 0;
   insert (str, 1);
 
   if (NILP (match_lisp))
@@ -1221,7 +1394,11 @@ DEFUN ("internal-describe-syntax-value", Finternal_describe_syntax_value,
     insert_string (" (nestable)");
 
   if (prefix)
-    insert_string (",\n\t  is a prefix character for `backward-prefix-chars'");
+    {
+      AUTO_STRING (prefixdoc,
+                  ",\n\t  is a prefix character for `backward-prefix-chars'");
+      insert1 (Fsubstitute_command_keys (prefixdoc));
+    }
 
   return syntax;
 }
@@ -1357,10 +1534,17 @@ scan_words (register ptrdiff_t from, register EMACS_INT count)
 
 DEFUN ("forward-word", Fforward_word, Sforward_word, 0, 1, "^p",
        doc: /* Move point forward ARG words (backward if ARG is negative).
+If ARG is omitted or nil, move point forward one word.
 Normally returns t.
-If an edge of the buffer or a field boundary is reached, point is left there
-and the function returns nil.  Field boundaries are not noticed if
-`inhibit-field-text-motion' is non-nil.  */)
+If an edge of the buffer or a field boundary is reached, point is
+left there and the function returns nil.  Field boundaries are not
+noticed if `inhibit-field-text-motion' is non-nil.
+
+The word boundaries are normally determined by the buffer's syntax
+table, but `find-word-boundary-function-table', such as set up
+by `subword-mode', can change that.  If a Lisp program needs to
+move by words determined strictly by the syntax table, it should
+use `forward-word-strictly' instead.  */)
   (Lisp_Object arg)
 {
   Lisp_Object tmp;
@@ -1377,7 +1561,7 @@ and the function returns nil.  Field boundaries are not noticed if
 
   /* Avoid jumping out of an input field.  */
   tmp = Fconstrain_to_field (make_number (val), make_number (PT),
-                            Qt, Qnil, Qnil);
+                            Qnil, Qnil, Qnil);
   val = XFASTINT (tmp);
 
   SET_PT (val);
@@ -1424,32 +1608,34 @@ DEFUN ("skip-syntax-backward", Fskip_syntax_backward, Sskip_syntax_backward, 1,
 SYNTAX is a string of syntax code characters.
 Stop on reaching a char whose syntax is not in SYNTAX, or at position LIM.
 If SYNTAX starts with ^, skip characters whose syntax is NOT in SYNTAX.
-This function returns the distance traveled, either zero or negative.  */)
+This function returns either zero or a negative number, and the absolute value
+of this is the distance traveled.  */)
   (Lisp_Object syntax, Lisp_Object lim)
 {
   return skip_syntaxes (0, syntax, lim);
 }
 
 static Lisp_Object
-skip_chars (int forwardp, Lisp_Object string, Lisp_Object lim, int handle_iso_classes)
+skip_chars (bool forwardp, Lisp_Object string, Lisp_Object lim,
+           bool handle_iso_classes)
 {
-  register unsigned int c;
-  unsigned char fastmap[0400];
+  int c;
+  char fastmap[0400];
   /* Store the ranges of non-ASCII characters.  */
   int *char_ranges IF_LINT (= NULL);
   int n_char_ranges = 0;
-  int negate = 0;
-  register ptrdiff_t i, i_byte;
-  /* Set to 1 if the current buffer is multibyte and the region
-     contains non-ASCII chars.  */
-  int multibyte;
-  /* Set to 1 if STRING is multibyte and it contains non-ASCII
-     chars.  */
-  int string_multibyte;
+  bool negate = 0;
+  ptrdiff_t i, i_byte;
+  /* True if the current buffer is multibyte and the region contains
+     non-ASCII chars.  */
+  bool multibyte;
+  /* True if STRING is multibyte and it contains non-ASCII chars.  */
+  bool string_multibyte;
   ptrdiff_t size_byte;
   const unsigned char *str;
   int len;
   Lisp_Object iso_classes;
+  USE_SAFE_ALLOCA;
 
   CHECK_STRING (string);
   iso_classes = Qnil;
@@ -1489,7 +1675,7 @@ skip_chars (int forwardp, Lisp_Object string, Lisp_Object lim, int handle_iso_cl
 
   if (! string_multibyte)
     {
-      int string_has_eight_bit = 0;
+      bool string_has_eight_bit = 0;
 
       /* At first setup fastmap.  */
       while (i_byte < size_byte)
@@ -1544,7 +1730,7 @@ skip_chars (int forwardp, Lisp_Object string, Lisp_Object lim, int handle_iso_cl
          if (i_byte + 1 < size_byte
              && str[i_byte] == '-')
            {
-             unsigned int c2;
+             int c2;
 
              /* Skip over the dash.  */
              i_byte++;
@@ -1557,7 +1743,7 @@ skip_chars (int forwardp, Lisp_Object string, Lisp_Object lim, int handle_iso_cl
 
              if (c <= c2)
                {
-                 unsigned lim2 = c2 + 1;
+                 int lim2 = c2 + 1;
                  while (c < lim2)
                    fastmap[c++] = 1;
                  if (! ASCII_CHAR_P (c2))
@@ -1577,45 +1763,40 @@ skip_chars (int forwardp, Lisp_Object string, Lisp_Object lim, int handle_iso_cl
         the corresponding multibyte chars.  */
       if (multibyte && string_has_eight_bit)
        {
-         unsigned char fastmap2[0400];
-         int range_start_byte, range_start_char;
-
-         memcpy (fastmap + 0200, fastmap2 + 0200, 0200);
+         char *p1;
+         char himap[0200 + 1];
+         memcpy (himap, fastmap + 0200, 0200);
+         himap[0200] = 0;
          memset (fastmap + 0200, 0, 0200);
-         /* We are sure that this loop stops.  */
-         for (i = 0200; ! fastmap2[i]; i++);
-         c = BYTE8_TO_CHAR (i);
-         fastmap[CHAR_LEADING_CODE (c)] = 1;
-         range_start_byte = i;
-         range_start_char = c;
-         char_ranges = alloca (sizeof *char_ranges * 128 * 2);
-         for (i = 129; i < 0400; i++)
+         SAFE_NALLOCA (char_ranges, 2, 128);
+         i = 0;
+
+         while ((p1 = memchr (himap + i, 1, 0200 - i)))
            {
-             c = BYTE8_TO_CHAR (i);
-             fastmap[CHAR_LEADING_CODE (c)] = 1;
-             if (i - range_start_byte != c - range_start_char)
-               {
-                 char_ranges[n_char_ranges++] = range_start_char;
-                 char_ranges[n_char_ranges++] = ((i - 1 - range_start_byte)
-                                                 + range_start_char);
-                 range_start_byte = i;
-                 range_start_char = c;
-               }
+             /* Deduce the next range C..C2 from the next clump of 1s
+                in HIMAP starting with &HIMAP[I].  HIMAP is the high
+                order half of the old FASTMAP.  */
+             int c2, leading_code;
+             i = p1 - himap;
+             c = BYTE8_TO_CHAR (i + 0200);
+             i += strlen (p1);
+             c2 = BYTE8_TO_CHAR (i + 0200 - 1);
+
+             char_ranges[n_char_ranges++] = c;
+             char_ranges[n_char_ranges++] = c2;
+             leading_code = CHAR_LEADING_CODE (c);
+             memset (fastmap + leading_code, 1,
+                     CHAR_LEADING_CODE (c2) - leading_code + 1);
            }
-         char_ranges[n_char_ranges++] = range_start_char;
-         char_ranges[n_char_ranges++] = ((i - 1 - range_start_byte)
-                                         + range_start_char);
        }
     }
   else                         /* STRING is multibyte */
     {
-      char_ranges = alloca (sizeof *char_ranges * SCHARS (string) * 2);
+      SAFE_NALLOCA (char_ranges, 2, SCHARS (string));
 
       while (i_byte < size_byte)
        {
-         unsigned char leading_code;
-
-         leading_code = str[i_byte];
+         int leading_code = str[i_byte];
          c = STRING_CHAR_AND_LENGTH (str + i_byte, len);
          i_byte += len;
 
@@ -1669,8 +1850,7 @@ skip_chars (int forwardp, Lisp_Object string, Lisp_Object lim, int handle_iso_cl
          if (i_byte + 1 < size_byte
              && str[i_byte] == '-')
            {
-             unsigned int c2;
-             unsigned char leading_code2;
+             int c2, leading_code2;
 
              /* Skip over the dash.  */
              i_byte++;
@@ -1684,7 +1864,7 @@ skip_chars (int forwardp, Lisp_Object string, Lisp_Object lim, int handle_iso_cl
                  && i_byte < size_byte)
                {
                  leading_code2 = str[i_byte];
-                 c2 =STRING_CHAR_AND_LENGTH (str + i_byte, len);
+                 c2 = STRING_CHAR_AND_LENGTH (str + i_byte, len);
                  i_byte += len;
                }
 
@@ -1698,7 +1878,7 @@ skip_chars (int forwardp, Lisp_Object string, Lisp_Object lim, int handle_iso_cl
                }
              if (! ASCII_CHAR_P (c))
                {
-                 unsigned lim2 = leading_code2 + 1;
+                 int lim2 = leading_code2 + 1;
                  while (leading_code < lim2)
                    fastmap[leading_code++] = 1;
                  if (c <= c2)
@@ -1731,7 +1911,7 @@ skip_chars (int forwardp, Lisp_Object string, Lisp_Object lim, int handle_iso_cl
          for (i = 0; i < n_char_ranges; i += 2)
            {
              int c1 = char_ranges[i];
-             unsigned lim2 = char_ranges[i + 1] + 1;
+             int lim2 = char_ranges[i + 1] + 1;
 
              for (; c1 < lim2; c1++)
                {
@@ -1777,7 +1957,7 @@ skip_chars (int forwardp, Lisp_Object string, Lisp_Object lim, int handle_iso_cl
       }
 
     immediate_quit = 1;
-    /* This code may look up syntax tables using macros that rely on the
+    /* This code may look up syntax tables using functions that rely on the
        gl_state object.  To make sure this object is not out of date,
        let's initialize it manually.
        We ignore syntax-table text-properties for now, since that's
@@ -1921,19 +2101,20 @@ skip_chars (int forwardp, Lisp_Object string, Lisp_Object lim, int handle_iso_cl
     SET_PT_BOTH (pos, pos_byte);
     immediate_quit = 0;
 
+    SAFE_FREE ();
     return make_number (PT - start_point);
   }
 }
 
 
 static Lisp_Object
-skip_syntaxes (int forwardp, Lisp_Object string, Lisp_Object lim)
+skip_syntaxes (bool forwardp, Lisp_Object string, Lisp_Object lim)
 {
-  register unsigned int c;
+  int c;
   unsigned char fastmap[0400];
-  int negate = 0;
-  register ptrdiff_t i, i_byte;
-  int multibyte;
+  bool negate = 0;
+  ptrdiff_t i, i_byte;
+  bool multibyte;
   ptrdiff_t size_byte;
   unsigned char *str;
 
@@ -2021,7 +2202,7 @@ skip_syntaxes (int forwardp, Lisp_Object string, Lisp_Object lim)
                    stop = endp;
                  }
                c = STRING_CHAR_AND_LENGTH (p, nbytes);
-               if (! fastmap[(int) SYNTAX (c)])
+               if (! fastmap[SYNTAX (c)])
                  break;
                p += nbytes, pos++, pos_byte += nbytes;
                UPDATE_SYNTAX_TABLE_FORWARD (pos);
@@ -2038,7 +2219,7 @@ skip_syntaxes (int forwardp, Lisp_Object string, Lisp_Object lim)
                    p = GAP_END_ADDR;
                    stop = endp;
                  }
-               if (! fastmap[(int) SYNTAX (*p)])
+               if (! fastmap[SYNTAX (*p)])
                  break;
                p++, pos++, pos_byte++;
                UPDATE_SYNTAX_TABLE_FORWARD (pos);
@@ -2064,7 +2245,7 @@ skip_syntaxes (int forwardp, Lisp_Object string, Lisp_Object lim)
                prev_p = p;
                while (--p >= stop && ! CHAR_HEAD_P (*p));
                c = STRING_CHAR (p);
-               if (! fastmap[(int) SYNTAX (c)])
+               if (! fastmap[SYNTAX (c)])
                  break;
                pos--, pos_byte -= prev_p - p;
              }
@@ -2081,7 +2262,7 @@ skip_syntaxes (int forwardp, Lisp_Object string, Lisp_Object lim)
                    stop = endp;
                  }
                UPDATE_SYNTAX_TABLE_BACKWARD (pos - 1);
-               if (! fastmap[(int) SYNTAX (p[-1])])
+               if (! fastmap[SYNTAX (p[-1])])
                  break;
                p--, pos--, pos_byte--;
              }
@@ -2095,14 +2276,14 @@ skip_syntaxes (int forwardp, Lisp_Object string, Lisp_Object lim)
   }
 }
 
-/* Return 1 if character C belongs to one of the ISO classes
+/* Return true if character C belongs to one of the ISO classes
    in the list ISO_CLASSES.  Each class is represented by an
    integer which is its type according to re_wctype.  */
 
-static int
+static bool
 in_classes (int c, Lisp_Object iso_classes)
 {
-  int fits_class = 0;
+  bool fits_class = 0;
 
   while (CONSP (iso_classes))
     {
@@ -2122,26 +2303,26 @@ in_classes (int c, Lisp_Object iso_classes)
    FROM_BYTE is the bytepos corresponding to FROM.
    Do not move past STOP (a charpos).
    The comment over which we have to jump is of style STYLE
-     (either SYNTAX_FLAGS_COMMENT_STYLE(foo) or ST_COMMENT_STYLE).
+     (either SYNTAX_FLAGS_COMMENT_STYLE (foo) or ST_COMMENT_STYLE).
    NESTING should be positive to indicate the nesting at the beginning
      for nested comments and should be zero or negative else.
      ST_COMMENT_STYLE cannot be nested.
    PREV_SYNTAX is the SYNTAX_WITH_FLAGS of the previous character
      (or 0 If the search cannot start in the middle of a two-character).
 
-   If successful, return 1 and store the charpos of the comment's end
+   If successful, return true and store the charpos of the comment's end
    into *CHARPOS_PTR and the corresponding bytepos into *BYTEPOS_PTR.
-   Else, return 0 and store the charpos STOP into *CHARPOS_PTR, the
+   Else, return false and store the charpos STOP into *CHARPOS_PTR, the
    corresponding bytepos into *BYTEPOS_PTR and the current nesting
    (as defined for state.incomment) in *INCOMMENT_PTR.
 
    The comment end is the last character of the comment rather than the
-     character just after the comment.
+   character just after the comment.
 
    Global syntax data is assumed to initially be valid for FROM and
    remains valid for forward search starting at the returned position. */
 
-static int
+static bool
 forw_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop,
              EMACS_INT nesting, int style, int prev_syntax,
              ptrdiff_t *charpos_ptr, ptrdiff_t *bytepos_ptr,
@@ -2173,14 +2354,15 @@ forw_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop,
       if (code == Sendcomment
          && SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0) == style
          && (SYNTAX_FLAGS_COMMENT_NESTED (syntax) ?
-             (nesting > 0 && --nesting == 0) : nesting < 0))
-       /* we have encountered a comment end of the same style
+             (nesting > 0 && --nesting == 0) : nesting < 0)
+          && !(Vcomment_end_can_be_escaped && char_quoted (from, from_byte)))
+       /* We have encountered a comment end of the same style
           as the comment sequence which began this comment
-          section */
+          section */
        break;
       if (code == Scomment_fence
          && style == ST_COMMENT_STYLE)
-       /* we have encountered a comment end of the same style
+       /* We have encountered a comment end of the same style
           as the comment sequence which began this comment
           section.  */
        break;
@@ -2188,8 +2370,8 @@ forw_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop,
          && code == Scomment
          && SYNTAX_FLAGS_COMMENT_NESTED (syntax)
          && SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0) == style)
-       /* we have encountered a nested comment of the same style
-          as the comment sequence which began this comment section */
+       /* We have encountered a nested comment of the same style
+          as the comment sequence which began this comment section */
        nesting++;
       INC_BOTH (from, from_byte);
       UPDATE_SYNTAX_TABLE_FORWARD (from);
@@ -2205,9 +2387,8 @@ forw_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop,
              ? nesting > 0 : nesting < 0))
        {
          if (--nesting <= 0)
-           /* we have encountered a comment end of the same style
-              as the comment sequence which began this comment
-              section */
+           /* We have encountered a comment end of the same style
+              as the comment sequence which began this comment section.  */
            break;
          else
            {
@@ -2224,9 +2405,8 @@ forw_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop,
              && SYNTAX_FLAGS_COMSTART_SECOND (other_syntax))
          && (SYNTAX_FLAGS_COMMENT_NESTED (syntax) ||
              SYNTAX_FLAGS_COMMENT_NESTED (other_syntax)))
-       /* we have encountered a nested comment of the same style
-          as the comment sequence which began this comment
-          section */
+       /* We have encountered a nested comment of the same style
+          as the comment sequence which began this comment section.  */
        {
          INC_BOTH (from, from_byte);
          UPDATE_SYNTAX_TABLE_FORWARD (from);
@@ -2247,14 +2427,12 @@ If COUNT comments are found as expected, with nothing except whitespace
 between them, return t; otherwise return nil.  */)
   (Lisp_Object count)
 {
-  register ptrdiff_t from;
-  ptrdiff_t from_byte;
-  register ptrdiff_t stop;
-  register int c, c1;
-  register enum syntaxcode code;
+  ptrdiff_t from, from_byte, stop;
+  int c, c1;
+  enum syntaxcode code;
   int comstyle = 0;        /* style of comment encountered */
-  int comnested = 0;       /* whether the comment is nestable or not */
-  int found;
+  bool comnested = 0;      /* whether the comment is nestable or not */
+  bool found;
   EMACS_INT count1;
   ptrdiff_t out_charpos, out_bytepos;
   EMACS_INT dummy;
@@ -2274,7 +2452,8 @@ between them, return t; otherwise return nil.  */)
     {
       do
        {
-         int comstart_first, syntax, other_syntax;
+         bool comstart_first;
+         int syntax, other_syntax;
 
          if (from == stop)
            {
@@ -2302,8 +2481,7 @@ between them, return t; otherwise return nil.  */)
                 the comment section.  */
              code = Scomment;
              comstyle = SYNTAX_FLAGS_COMMENT_STYLE (other_syntax, syntax);
-             comnested
-               = comnested || SYNTAX_FLAGS_COMMENT_NESTED (other_syntax);
+             comnested |= SYNTAX_FLAGS_COMMENT_NESTED (other_syntax);
              INC_BOTH (from, from_byte);
              UPDATE_SYNTAX_TABLE_FORWARD (from);
            }
@@ -2339,7 +2517,8 @@ between them, return t; otherwise return nil.  */)
     {
       while (1)
        {
-         int quoted, syntax;
+         bool quoted;
+         int syntax;
 
          if (from <= stop)
            {
@@ -2373,14 +2552,13 @@ between them, return t; otherwise return nil.  */)
              c1 = FETCH_CHAR_AS_MULTIBYTE (from_byte);
              other_syntax = SYNTAX_WITH_FLAGS (c1);
              comstyle = SYNTAX_FLAGS_COMMENT_STYLE (other_syntax, syntax);
-             comnested
-               = comnested || SYNTAX_FLAGS_COMMENT_NESTED (other_syntax);
+             comnested |= SYNTAX_FLAGS_COMMENT_NESTED (other_syntax);
            }
 
          if (code == Scomment_fence)
            {
              /* Skip until first preceding unquoted comment_fence.  */
-             int fence_found = 0;
+             bool fence_found = 0;
              ptrdiff_t ini = from, ini_byte = from_byte;
 
              while (1)
@@ -2411,7 +2589,7 @@ between them, return t; otherwise return nil.  */)
            {
              found = back_comment (from, from_byte, stop, comnested, comstyle,
                                    &out_charpos, &out_bytepos);
-             if (found == -1)
+             if (!found)
                {
                  if (c == '\n')
                    /* This end-of-line is not an end-of-comment.
@@ -2454,33 +2632,34 @@ between them, return t; otherwise return nil.  */)
 }
 \f
 /* Return syntax code of character C if C is an ASCII character
-   or `multibyte_symbol_p' is zero.  Otherwise, return Ssymbol.  */
+   or if MULTIBYTE_SYMBOL_P is false.  Otherwise, return Ssymbol.  */
 
-#define SYNTAX_WITH_MULTIBYTE_CHECK(c)         \
-  ((ASCII_CHAR_P (c) || !multibyte_symbol_p)   \
-   ? SYNTAX (c) : Ssymbol)
+static enum syntaxcode
+syntax_multibyte (int c, bool multibyte_symbol_p)
+{
+  return ASCII_CHAR_P (c) || !multibyte_symbol_p ? SYNTAX (c) : Ssymbol;
+}
 
 static Lisp_Object
-scan_lists (register EMACS_INT from, EMACS_INT count, EMACS_INT depth, int sexpflag)
+scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
 {
   Lisp_Object val;
-  register ptrdiff_t stop = count > 0 ? ZV : BEGV;
-  register int c, c1;
+  ptrdiff_t stop = count > 0 ? ZV : BEGV;
+  int c, c1;
   int stringterm;
-  int quoted;
-  int mathexit = 0;
-  register enum syntaxcode code, temp_code;
-  EMACS_INT min_depth = depth;    /* Err out if depth gets less than this.  */
-  int comstyle = 0;        /* style of comment encountered */
-  int comnested = 0;       /* whether the comment is nestable or not */
+  bool quoted;
+  bool mathexit = 0;
+  enum syntaxcode code;
+  EMACS_INT min_depth = depth;  /* Err out if depth gets less than this.  */
+  int comstyle = 0;            /* Style of comment encountered.  */
+  bool comnested = 0;          /* Whether the comment is nestable or not.  */
   ptrdiff_t temp_pos;
   EMACS_INT last_good = from;
-  int found;
+  bool found;
   ptrdiff_t from_byte;
   ptrdiff_t out_bytepos, out_charpos;
-  int temp;
   EMACS_INT dummy;
-  int multibyte_symbol_p = sexpflag && multibyte_syntax_as_symbol;
+  bool multibyte_symbol_p = sexpflag && multibyte_syntax_as_symbol;
 
   if (depth > 0) min_depth = 0;
 
@@ -2497,11 +2676,12 @@ scan_lists (register EMACS_INT from, EMACS_INT count, EMACS_INT depth, int sexpf
     {
       while (from < stop)
        {
-         int comstart_first, prefix, syntax, other_syntax;
+         bool comstart_first, prefix;
+         int syntax, other_syntax;
          UPDATE_SYNTAX_TABLE_FORWARD (from);
          c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
          syntax = SYNTAX_WITH_FLAGS (c);
-         code = SYNTAX_WITH_MULTIBYTE_CHECK (c);
+         code = syntax_multibyte (c, multibyte_symbol_p);
          comstart_first = SYNTAX_FLAGS_COMSTART_FIRST (syntax);
          comnested = SYNTAX_FLAGS_COMMENT_NESTED (syntax);
          comstyle = SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0);
@@ -2516,15 +2696,14 @@ scan_lists (register EMACS_INT from, EMACS_INT count, EMACS_INT depth, int sexpf
                  SYNTAX_FLAGS_COMSTART_SECOND (other_syntax))
              && parse_sexp_ignore_comments)
            {
-             /* we have encountered a comment start sequence and we
+             /* We have encountered a comment start sequence and we
                 are ignoring all text inside comments.  We must record
                 the comment style this sequence begins so that later,
                 only a comment end of the same style actually ends
-                the comment section */
+                the comment section */
              code = Scomment;
              comstyle = SYNTAX_FLAGS_COMMENT_STYLE (other_syntax, syntax);
-             comnested
-               = comnested || SYNTAX_FLAGS_COMMENT_NESTED (other_syntax);
+             comnested |= SYNTAX_FLAGS_COMMENT_NESTED (other_syntax);
              INC_BOTH (from, from_byte);
              UPDATE_SYNTAX_TABLE_FORWARD (from);
            }
@@ -2539,7 +2718,7 @@ scan_lists (register EMACS_INT from, EMACS_INT count, EMACS_INT depth, int sexpf
              if (from == stop)
                goto lose;
              INC_BOTH (from, from_byte);
-             /* treat following character as a word constituent */
+             /* Treat following character as a word constituent.  */
            case Sword:
            case Ssymbol:
              if (depth || !sexpflag) break;
@@ -2548,10 +2727,8 @@ scan_lists (register EMACS_INT from, EMACS_INT count, EMACS_INT depth, int sexpf
                {
                  UPDATE_SYNTAX_TABLE_FORWARD (from);
 
-                 /* Some compilers can't handle this inside the switch.  */
                  c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
-                 temp = SYNTAX_WITH_MULTIBYTE_CHECK (c);
-                 switch (temp)
+                 switch (syntax_multibyte (c, multibyte_symbol_p))
                    {
                    case Scharquote:
                    case Sescape:
@@ -2623,24 +2800,19 @@ scan_lists (register EMACS_INT from, EMACS_INT count, EMACS_INT depth, int sexpf
              stringterm = FETCH_CHAR_AS_MULTIBYTE (temp_pos);
              while (1)
                {
+                 enum syntaxcode c_code;
                  if (from >= stop)
                    goto lose;
                  UPDATE_SYNTAX_TABLE_FORWARD (from);
                  c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
+                 c_code = syntax_multibyte (c, multibyte_symbol_p);
                  if (code == Sstring
-                     ? (c == stringterm
-                        && SYNTAX_WITH_MULTIBYTE_CHECK (c) == Sstring)
-                     : SYNTAX_WITH_MULTIBYTE_CHECK (c) == Sstring_fence)
+                     ? c == stringterm && c_code == Sstring
+                     : c_code == Sstring_fence)
                    break;
 
-                 /* Some compilers can't handle this inside the switch.  */
-                 temp = SYNTAX_WITH_MULTIBYTE_CHECK (c);
-                 switch (temp)
-                   {
-                   case Scharquote:
-                   case Sescape:
-                     INC_BOTH (from, from_byte);
-                   }
+                 if (c_code == Scharquote || c_code == Sescape)
+                   INC_BOTH (from, from_byte);
                  INC_BOTH (from, from_byte);
                }
              INC_BOTH (from, from_byte);
@@ -2673,7 +2845,7 @@ scan_lists (register EMACS_INT from, EMACS_INT count, EMACS_INT depth, int sexpf
          UPDATE_SYNTAX_TABLE_BACKWARD (from);
          c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
          syntax= SYNTAX_WITH_FLAGS (c);
-         code = SYNTAX_WITH_MULTIBYTE_CHECK (c);
+         code = syntax_multibyte (c, multibyte_symbol_p);
          if (depth == min_depth)
            last_good = from;
          comstyle = 0;
@@ -2694,8 +2866,7 @@ scan_lists (register EMACS_INT from, EMACS_INT count, EMACS_INT depth, int sexpf
              c2 = FETCH_CHAR_AS_MULTIBYTE (from_byte);
              other_syntax = SYNTAX_WITH_FLAGS (c2);
              comstyle = SYNTAX_FLAGS_COMMENT_STYLE (other_syntax, syntax);
-             comnested
-               = comnested || SYNTAX_FLAGS_COMMENT_NESTED (other_syntax);
+             comnested |= SYNTAX_FLAGS_COMMENT_NESTED (other_syntax);
            }
 
          /* Quoting turns anything except a comment-ender
@@ -2727,9 +2898,8 @@ scan_lists (register EMACS_INT from, EMACS_INT count, EMACS_INT depth, int sexpf
                    temp_pos--;
                  UPDATE_SYNTAX_TABLE_BACKWARD (from - 1);
                  c1 = FETCH_CHAR_AS_MULTIBYTE (temp_pos);
-                 temp_code = SYNTAX_WITH_MULTIBYTE_CHECK (c1);
                  /* Don't allow comment-end to be quoted.  */
-                 if (temp_code == Sendcomment)
+                 if (syntax_multibyte (c1, multibyte_symbol_p) == Sendcomment)
                    goto done2;
                  quoted = char_quoted (from - 1, temp_pos);
                  if (quoted)
@@ -2739,11 +2909,12 @@ scan_lists (register EMACS_INT from, EMACS_INT count, EMACS_INT depth, int sexpf
                      UPDATE_SYNTAX_TABLE_BACKWARD (from - 1);
                    }
                  c1 = FETCH_CHAR_AS_MULTIBYTE (temp_pos);
-                 temp_code = SYNTAX_WITH_MULTIBYTE_CHECK (c1);
-                 if (! (quoted || temp_code == Sword
-                        || temp_code == Ssymbol
-                        || temp_code == Squote))
-                   goto done2;
+                 if (! quoted)
+                   switch (syntax_multibyte (c1, multibyte_symbol_p))
+                     {
+                     case Sword: case Ssymbol: case Squote: break;
+                     default: goto done2;
+                     }
                  DEC_BOTH (from, from_byte);
                }
              goto done2;
@@ -2751,10 +2922,13 @@ scan_lists (register EMACS_INT from, EMACS_INT count, EMACS_INT depth, int sexpf
            case Smath:
              if (!sexpflag)
                break;
-             temp_pos = dec_bytepos (from_byte);
-             UPDATE_SYNTAX_TABLE_BACKWARD (from - 1);
-             if (from != stop && c == FETCH_CHAR_AS_MULTIBYTE (temp_pos))
-               DEC_BOTH (from, from_byte);
+             if (from > BEGV)
+               {
+                 temp_pos = dec_bytepos (from_byte);
+                 UPDATE_SYNTAX_TABLE_BACKWARD (from - 1);
+                 if (from != stop && c == FETCH_CHAR_AS_MULTIBYTE (temp_pos))
+                   DEC_BOTH (from, from_byte);
+               }
              if (mathexit)
                {
                  mathexit = 0;
@@ -2780,13 +2954,13 @@ scan_lists (register EMACS_INT from, EMACS_INT count, EMACS_INT depth, int sexpf
                break;
              found = back_comment (from, from_byte, stop, comnested, comstyle,
                                    &out_charpos, &out_bytepos);
-             /* FIXME:  if found == -1, then it really wasn't a comment-end.
+             /* FIXME:  if !found, it really wasn't a comment-end.
                 For single-char Sendcomment, we can't do much about it apart
                 from skipping the char.
                 For 2-char endcomments, we could try again, taking both
                 chars as separate entities, but it's a lot of trouble
                 for very little gain, so we don't bother either.  -sm */
-             if (found != -1)
+             if (found)
                from = out_charpos, from_byte = out_bytepos;
              break;
 
@@ -2798,10 +2972,12 @@ scan_lists (register EMACS_INT from, EMACS_INT count, EMACS_INT depth, int sexpf
                    goto lose;
                  DEC_BOTH (from, from_byte);
                  UPDATE_SYNTAX_TABLE_BACKWARD (from);
-                 if (!char_quoted (from, from_byte)
-                     && (c = FETCH_CHAR_AS_MULTIBYTE (from_byte),
-                         SYNTAX_WITH_MULTIBYTE_CHECK (c) == code))
-                   break;
+                 if (!char_quoted (from, from_byte))
+                   {
+                     c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
+                     if (syntax_multibyte (c, multibyte_symbol_p) == code)
+                       break;
+                   }
                }
              if (code == Sstring_fence && !depth && sexpflag) goto done2;
              break;
@@ -2814,11 +2990,14 @@ scan_lists (register EMACS_INT from, EMACS_INT count, EMACS_INT depth, int sexpf
                    goto lose;
                  DEC_BOTH (from, from_byte);
                  UPDATE_SYNTAX_TABLE_BACKWARD (from);
-                 if (!char_quoted (from, from_byte)
-                     && (stringterm
-                         == (c = FETCH_CHAR_AS_MULTIBYTE (from_byte)))
-                     && SYNTAX_WITH_MULTIBYTE_CHECK (c) == Sstring)
-                   break;
+                 if (!char_quoted (from, from_byte))
+                   {
+                     c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
+                     if (c == stringterm
+                         && (syntax_multibyte (c, multibyte_symbol_p)
+                             == Sstring))
+                       break;
+                   }
                }
              if (!depth && sexpflag) goto done2;
              break;
@@ -2900,7 +3079,8 @@ but before count is used up, nil is returned.  */)
 DEFUN ("backward-prefix-chars", Fbackward_prefix_chars, Sbackward_prefix_chars,
        0, 0, 0,
        doc: /* Move point backward over any number of chars with prefix syntax.
-This includes chars with "quote" or "prefix" syntax (' or p).  */)
+This includes chars with expression prefix syntax class (') and those with
+the prefix syntax flag (p).  */)
   (void)
 {
   ptrdiff_t beg = BEGV;
@@ -2924,7 +3104,7 @@ This includes chars with "quote" or "prefix" syntax (' or p).  */)
   while (!char_quoted (pos, pos_byte)
         /* Previous statement updates syntax table.  */
         && ((c = FETCH_CHAR_AS_MULTIBYTE (pos_byte), SYNTAX (c) == Squote)
-            || SYNTAX_PREFIX (c)))
+            || syntax_prefix_flag_p (c)))
     {
       opoint = pos;
       opoint_byte = pos_byte;
@@ -2941,7 +3121,7 @@ This includes chars with "quote" or "prefix" syntax (' or p).  */)
 /* Parse forward from FROM / FROM_BYTE to END,
    assuming that FROM has state OLDSTATE (nil means FROM is start of function),
    and return a description of the state of the parse at END.
-   If STOPBEFORE is nonzero, stop at the start of an atom.
+   If STOPBEFORE, stop at the start of an atom.
    If COMMENTSTOP is 1, stop at the start of a comment.
    If COMMENTSTOP is -1, stop at the start or end of a comment,
    after the beginning of a string, or after the end of a string.  */
@@ -2949,30 +3129,29 @@ This includes chars with "quote" or "prefix" syntax (' or p).  */)
 static void
 scan_sexps_forward (struct lisp_parse_state *stateptr,
                    ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t end,
-                   EMACS_INT targetdepth, int stopbefore,
+                   EMACS_INT targetdepth, bool stopbefore,
                    Lisp_Object oldstate, int commentstop)
 {
   struct lisp_parse_state state;
-
-  register enum syntaxcode code;
+  enum syntaxcode code;
   int c1;
-  int comnested;
+  bool comnested;
   struct level { ptrdiff_t last, prev; };
   struct level levelstart[100];
-  register struct level *curlevel = levelstart;
+  struct level *curlevel = levelstart;
   struct level *endlevel = levelstart + 100;
-  register EMACS_INT depth; /* Paren depth of current scanning location.
+  EMACS_INT depth;      /* Paren depth of current scanning location.
                           level - levelstart equals this except
                           when the depth becomes negative.  */
   EMACS_INT mindepth;          /* Lowest DEPTH value seen.  */
-  int start_quoted = 0;                /* Nonzero means starting after a char quote */
+  bool start_quoted = 0;       /* True means starting after a char quote.  */
   Lisp_Object tem;
   ptrdiff_t prev_from;         /* Keep one character before FROM.  */
   ptrdiff_t prev_from_byte;
   int prev_from_syntax;
-  int boundary_stop = commentstop == -1;
-  int nofence;
-  int found;
+  bool boundary_stop = commentstop == -1;
+  bool nofence;
+  bool found;
   ptrdiff_t out_bytepos, out_charpos;
   int temp;
 
@@ -3103,8 +3282,8 @@ do { prev_from = from;                            \
             terminates the comment section.  */
          state.comstyle
            = SYNTAX_FLAGS_COMMENT_STYLE (syntax, prev_from_syntax);
-         comnested = SYNTAX_FLAGS_COMMENT_NESTED (prev_from_syntax);
-         comnested = comnested || SYNTAX_FLAGS_COMMENT_NESTED (syntax);
+         comnested = (SYNTAX_FLAGS_COMMENT_NESTED (prev_from_syntax)
+                      | SYNTAX_FLAGS_COMMENT_NESTED (syntax));
          state.incomment = comnested ? 1 : -1;
          state.comstr_start = prev_from;
          INC_FROM;
@@ -3148,10 +3327,8 @@ do { prev_from = from;                           \
        symstarted:
          while (from < end)
            {
-             /* Some compilers can't handle this inside the switch.  */
-             temp = FETCH_CHAR_AS_MULTIBYTE (from_byte);
-             temp = SYNTAX (temp);
-             switch (temp)
+             int symchar = FETCH_CHAR_AS_MULTIBYTE (from_byte);
+             switch (SYNTAX (symchar))
                {
                case Scharquote:
                case Sescape:
@@ -3233,28 +3410,33 @@ do { prev_from = from;                          \
            while (1)
              {
                int c;
+               enum syntaxcode c_code;
 
                if (from >= end) goto done;
                c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
-               /* Some compilers can't handle this inside the switch.  */
-               temp = SYNTAX (c);
+               c_code = SYNTAX (c);
 
-               /* Check TEMP here so that if the char has
+               /* Check C_CODE here so that if the char has
                   a syntax-table property which says it is NOT
                   a string character, it does not end the string.  */
-               if (nofence && c == state.instring && temp == Sstring)
+               if (nofence && c == state.instring && c_code == Sstring)
                  break;
 
-               switch (temp)
+               switch (c_code)
                  {
                  case Sstring_fence:
                    if (!nofence) goto string_end;
                    break;
+
                  case Scharquote:
                  case Sescape:
                    INC_FROM;
                  startquotedinstring:
                    if (from >= end) goto endquoted;
+                   break;
+
+                 default:
+                   break;
                  }
                INC_FROM;
              }
@@ -3342,7 +3524,7 @@ Sixth arg COMMENTSTOP non-nil means stop at the start of a comment.
       target = XINT (targetdepth);
     }
   else
-    target = TYPE_MINIMUM (EMACS_INT); /* We won't reach this depth */
+    target = TYPE_MINIMUM (EMACS_INT); /* We won't reach this depth */
 
   validate_region (&from, &to);
   scan_sexps_forward (&state, XINT (from), CHAR_TO_BYTE (XINT (from)),
@@ -3387,11 +3569,6 @@ init_syntax_once (void)
   /* This has to be done here, before we call Fmake_char_table.  */
   DEFSYM (Qsyntax_table, "syntax-table");
 
-  /* Intern_C_String this now in case it isn't already done.
-     Setting this variable twice is harmless.
-     But don't staticpro it here--that is done in alloc.c.  */
-  Qchar_table_extra_slots = intern_c_string ("char-table-extra-slots");
-
   /* Create objects which can be shared among syntax tables.  */
   Vsyntax_code_object = make_uninit_vector (Smax);
   for (i = 0; i < Smax; i++)
@@ -3401,25 +3578,25 @@ init_syntax_once (void)
      create syntax tables.  */
   Fput (Qsyntax_table, Qchar_table_extra_slots, make_number (0));
 
-  temp = AREF (Vsyntax_code_object, (int) Swhitespace);
+  temp = AREF (Vsyntax_code_object, Swhitespace);
 
   Vstandard_syntax_table = Fmake_char_table (Qsyntax_table, temp);
 
   /* Control characters should not be whitespace.  */
-  temp = AREF (Vsyntax_code_object, (int) Spunct);
+  temp = AREF (Vsyntax_code_object, Spunct);
   for (i = 0; i <= ' ' - 1; i++)
     SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, i, temp);
   SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, 0177, temp);
 
   /* Except that a few really are whitespace.  */
-  temp = AREF (Vsyntax_code_object, (int) Swhitespace);
+  temp = AREF (Vsyntax_code_object, Swhitespace);
   SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, ' ', temp);
   SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '\t', temp);
   SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '\n', temp);
   SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, 015, temp);
   SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, 014, temp);
 
-  temp = AREF (Vsyntax_code_object, (int) Sword);
+  temp = AREF (Vsyntax_code_object, Sword);
   for (i = 'a'; i <= 'z'; i++)
     SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, i, temp);
   for (i = 'A'; i <= 'Z'; i++)
@@ -3443,18 +3620,18 @@ init_syntax_once (void)
   SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '}',
                        Fcons (make_number (Sclose), make_number ('{')));
   SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '"',
-                       Fcons (make_number ((int) Sstring), Qnil));
+                       Fcons (make_number (Sstring), Qnil));
   SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '\\',
-                       Fcons (make_number ((int) Sescape), Qnil));
+                       Fcons (make_number (Sescape), Qnil));
 
-  temp = AREF (Vsyntax_code_object, (int) Ssymbol);
+  temp = AREF (Vsyntax_code_object, Ssymbol);
   for (i = 0; i < 10; i++)
     {
       c = "_-+*/&|<>="[i];
       SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, c, temp);
     }
 
-  temp = AREF (Vsyntax_code_object, (int) Spunct);
+  temp = AREF (Vsyntax_code_object, Spunct);
   for (i = 0; i < 12; i++)
     {
       c = ".,;:?!#@~^'`"[i];
@@ -3462,7 +3639,7 @@ init_syntax_once (void)
     }
 
   /* All multibyte characters have syntax `word' by default.  */
-  temp = AREF (Vsyntax_code_object, (int) Sword);
+  temp = AREF (Vsyntax_code_object, Sword);
   char_table_set_range (Vstandard_syntax_table, 0x80, MAX_CHAR, temp);
 }
 
@@ -3478,7 +3655,7 @@ syms_of_syntax (void)
   staticpro (&gl_state.current_syntax_table);
   staticpro (&gl_state.old_prop);
 
-  /* Defined in regex.c */
+  /* Defined in regex.c */
   staticpro (&re_match_object);
 
   DEFSYM (Qscan_error, "scan-error");
@@ -3496,6 +3673,12 @@ Otherwise, that text property is simply ignored.
 See the info node `(elisp)Syntax Properties' for a description of the
 `syntax-table' property.  */);
 
+  DEFVAR_INT ("syntax-propertize--done", syntax_propertize__done,
+             doc: /* Position up to which syntax-table properties have been set.  */);
+  syntax_propertize__done = -1;
+  DEFSYM (Qinternal__syntax_propertize, "internal--syntax-propertize");
+  Fmake_variable_buffer_local (intern ("syntax-propertize--done"));
+
   words_include_escapes = 0;
   DEFVAR_BOOL ("words-include-escapes", words_include_escapes,
               doc: /* Non-nil means `forward-word', etc., should treat escape chars part of words.  */);
@@ -3518,16 +3701,22 @@ Each function is called with two arguments; POS and LIMIT.
 POS and LIMIT are character positions in the current buffer.
 
 If POS is less than LIMIT, POS is at the first character of a word,
-and the return value of a function is a position after the last
-character of that word.
+and the return value of a function should be a position after the
+last character of that word.
 
 If POS is not less than LIMIT, POS is at the last character of a word,
-and the return value of a function is a position at the first
+and the return value of a function should be a position at the first
 character of that word.
 
 In both cases, LIMIT bounds the search. */);
   Vfind_word_boundary_function_table = Fmake_char_table (Qnil, Qnil);
 
+  DEFVAR_BOOL ("comment-end-can-be-escaped", Vcomment_end_can_be_escaped,
+               doc: /* Non-nil means an escaped ender inside a comment doesn'tend the comment.  */);
+  Vcomment_end_can_be_escaped = 0;
+  DEFSYM (Qcomment_end_can_be_escaped, "comment-end-can-be-escaped");
+  Fmake_variable_buffer_local (Qcomment_end_can_be_escaped);
+
   defsubr (&Ssyntax_table_p);
   defsubr (&Ssyntax_table);
   defsubr (&Sstandard_syntax_table);