]> git.eshelyaron.com Git - emacs.git/commitdiff
(char_quoted): Use FETCH_CHAR_AS_MULTIBYTE to convert
authorKenichi Handa <handa@m17n.org>
Tue, 3 Sep 2002 04:10:19 +0000 (04:10 +0000)
committerKenichi Handa <handa@m17n.org>
Tue, 3 Sep 2002 04:10:19 +0000 (04:10 +0000)
unibyte chars to multibyte.
(back_comment): Likewise.
(scan_words): Likewise.
(skip_chars): The arg syntaxp is deleted, and the code for
handling syntaxes is moved to skip_syntaxes.  Callers changed.
Fix the case that the multibyteness of STRING and the current
buffer doesn't match.
(skip_syntaxes): New function.
(SYNTAX_WITH_MULTIBYTE_CHECK): Check C by ASCII_CHAR_P, not by
SINGLE_BYTE_CHAR_P.
(Fforward_comment): Use FETCH_CHAR_AS_MULTIBYTE to convert unibyte
chars to multibyte.
(scan_lists): Likewise.
(Fbackward_prefix_chars): Likewise.
(scan_sexps_forward): Likewise.

src/syntax.c

index 716b3be6f6c129fe05198bf2e75fcf7e93417fdd..1795e588583dab439ec01d3a4fde3c109092778c 100644 (file)
@@ -97,7 +97,8 @@ static int find_start_modiff;
 static int find_defun_start P_ ((int, int));
 static int back_comment P_ ((int, int, int, int, int, int *, int *));
 static int char_quoted P_ ((int, int));
-static Lisp_Object skip_chars P_ ((int, int, Lisp_Object, Lisp_Object));
+static Lisp_Object skip_chars P_ ((int, Lisp_Object, Lisp_Object));
+static Lisp_Object skip_syntaxes P_ ((int, Lisp_Object, Lisp_Object));
 static Lisp_Object scan_lists P_ ((int, int, int, int));
 static void scan_sexps_forward P_ ((struct lisp_parse_state *,
                                    int, int, int, int,
@@ -293,7 +294,7 @@ char_quoted (charpos, bytepos)
   while (bytepos >= beg)
     {
       UPDATE_SYNTAX_TABLE_BACKWARD (charpos);
-      code = SYNTAX (FETCH_CHAR (bytepos));
+      code = SYNTAX (FETCH_CHAR_AS_MULTIBYTE (bytepos));
       if (! (code == Scharquote || code == Sescape))
        break;
 
@@ -378,10 +379,10 @@ find_defun_start (pos, pos_byte)
        {
          /* Open-paren at start of line means we may have found our
             defun-start.  */
-         if (SYNTAX (FETCH_CHAR (PT_BYTE)) == Sopen)
+         if (SYNTAX (FETCH_CHAR_AS_MULTIBYTE (PT_BYTE)) == Sopen)
            {
              SETUP_SYNTAX_TABLE (PT + 1, -1);  /* Try again... */
-             if (SYNTAX (FETCH_CHAR (PT_BYTE)) == Sopen)
+             if (SYNTAX (FETCH_CHAR_AS_MULTIBYTE (PT_BYTE)) == Sopen)
                break;
              /* Now fallback to the default value.  */
              gl_state.current_syntax_table = current_buffer->syntax_table;
@@ -502,7 +503,7 @@ back_comment (from, from_byte, stop, comnested, comstyle, charpos_ptr, bytepos_p
       UPDATE_SYNTAX_TABLE_BACKWARD (from);
 
       prev_syntax = syntax;
-      c = FETCH_CHAR (from_byte);
+      c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
       syntax = SYNTAX_WITH_FLAGS (c);
       code = SYNTAX (c);
 
@@ -531,7 +532,7 @@ back_comment (from, from_byte, stop, comnested, comstyle, charpos_ptr, bytepos_p
          int next = from, next_byte = from_byte, next_c, next_syntax;
          DEC_BOTH (next, next_byte);
          UPDATE_SYNTAX_TABLE_BACKWARD (next);
-         next_c = FETCH_CHAR (next_byte);
+         next_c = FETCH_CHAR_AS_MULTIBYTE (next_byte);
          next_syntax = SYNTAX_WITH_FLAGS (next_c);
          if (((com2start || comnested)
               && SYNTAX_FLAGS_COMEND_SECOND (syntax)
@@ -1195,7 +1196,7 @@ scan_words (from, count)
              return 0;
            }
          UPDATE_SYNTAX_TABLE_FORWARD (from);
-         ch0 = FETCH_CHAR (from_byte);
+         ch0 = FETCH_CHAR_AS_MULTIBYTE (from_byte);
          code = SYNTAX (ch0);
          INC_BOTH (from, from_byte);
          if (words_include_escapes
@@ -1224,7 +1225,7 @@ scan_words (from, count)
            {
              if (from == end) break;
              UPDATE_SYNTAX_TABLE_FORWARD (from);
-             ch1 = FETCH_CHAR (from_byte);
+             ch1 = FETCH_CHAR_AS_MULTIBYTE (from_byte);
              code = SYNTAX (ch1);
              if ((code != Sword
                   && (! words_include_escapes
@@ -1251,7 +1252,7 @@ scan_words (from, count)
            }
          DEC_BOTH (from, from_byte);
          UPDATE_SYNTAX_TABLE_BACKWARD (from);
-         ch1 = FETCH_CHAR (from_byte);
+         ch1 = FETCH_CHAR_AS_MULTIBYTE (from_byte);
          code = SYNTAX (ch1);
          if (words_include_escapes
              && (code == Sescape || code == Scharquote))
@@ -1283,7 +1284,7 @@ scan_words (from, count)
                break;
              temp_byte = dec_bytepos (from_byte);
              UPDATE_SYNTAX_TABLE_BACKWARD (from);
-             ch0 = FETCH_CHAR (temp_byte);
+             ch0 = FETCH_CHAR_AS_MULTIBYTE (temp_byte);
              code = SYNTAX (ch0);
              if ((code != Sword
                   && (! words_include_escapes
@@ -1339,7 +1340,7 @@ Returns the distance traveled, either zero or positive.  */)
      (string, lim)
      Lisp_Object string, lim;
 {
-  return skip_chars (1, 0, string, lim);
+  return skip_chars (1, string, lim);
 }
 
 DEFUN ("skip-chars-backward", Fskip_chars_backward, Sskip_chars_backward, 1, 2, 0,
@@ -1349,7 +1350,7 @@ Returns the distance traveled, either zero or negative.  */)
      (string, lim)
      Lisp_Object string, lim;
 {
-  return skip_chars (0, 0, string, lim);
+  return skip_chars (0, string, lim);
 }
 
 DEFUN ("skip-syntax-forward", Fskip_syntax_forward, Sskip_syntax_forward, 1, 2, 0,
@@ -1361,7 +1362,7 @@ This function returns the distance traveled, either zero or positive.  */)
      (syntax, lim)
      Lisp_Object syntax, lim;
 {
-  return skip_chars (1, 1, syntax, lim);
+  return skip_syntaxes (1, syntax, lim);
 }
 
 DEFUN ("skip-syntax-backward", Fskip_syntax_backward, Sskip_syntax_backward, 1, 2, 0,
@@ -1373,53 +1374,32 @@ This function returns the distance traveled, either zero or negative.  */)
      (syntax, lim)
      Lisp_Object syntax, lim;
 {
-  return skip_chars (0, 1, syntax, lim);
+  return skip_syntaxes (0, syntax, lim);
 }
 
 static Lisp_Object
-skip_chars (forwardp, syntaxp, string, lim)
-     int forwardp, syntaxp;
+skip_chars (forwardp, string, lim)
+     int forwardp;
      Lisp_Object string, lim;
 {
   register unsigned int c;
   unsigned char fastmap[0400];
-  /* If SYNTAXP is 0, STRING may contain multi-byte form of characters
-     of which codes don't fit in FASTMAP.  In that case, set the
-     ranges of characters in CHAR_RANGES.  */
+  /* Store the ranges of non-ASCII characters.  */
   int *char_ranges;
   int n_char_ranges = 0;
   int negate = 0;
   register int i, i_byte;
-  int multibyte = !NILP (current_buffer->enable_multibyte_characters);
+  /* 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;
   int size_byte;
   unsigned char *str;
   int len;
 
   CHECK_STRING (string);
-  char_ranges = (int *) alloca (XSTRING (string)->size * (sizeof (int)) * 2);
-  string_multibyte = STRING_MULTIBYTE (string);
-  str = XSTRING (string)->data;
-  size_byte = STRING_BYTES (XSTRING (string));
-
-  /* Adjust the multibyteness of the string to that of the buffer.  */
-  if (multibyte != string_multibyte)
-    {
-      int nbytes;
-
-      if (multibyte)
-       nbytes = count_size_as_multibyte (XSTRING (string)->data,
-                                         XSTRING (string)->size);
-      else
-       nbytes = XSTRING (string)->size;
-      if (nbytes != size_byte)
-       {
-         str = (unsigned char *) alloca (nbytes);
-         copy_text (XSTRING (string)->data, str, size_byte,
-                    string_multibyte, multibyte);
-         size_byte = nbytes;
-       }
-    }
 
   if (NILP (lim))
     XSETINT (lim, forwardp ? ZV : BEGV);
@@ -1432,10 +1412,15 @@ skip_chars (forwardp, syntaxp, string, lim)
   if (XINT (lim) < BEGV)
     XSETFASTINT (lim, BEGV);
 
+  multibyte = (!NILP (current_buffer->enable_multibyte_characters)
+              && (lim - PT != CHAR_TO_BYTE (lim) - PT_BYTE));
+  string_multibyte = STRING_BYTES (XSTRING (string)) > XSTRING (string)->size;
+
   bzero (fastmap, sizeof fastmap);
+  if (multibyte)
+    char_ranges = (int *) alloca (XSTRING (string)->size * (sizeof (int)) * 2);
 
   i_byte = 0;
-
   if (i_byte < size_byte
       && XSTRING (string)->data[0] == '^')
     {
@@ -1443,20 +1428,25 @@ skip_chars (forwardp, syntaxp, string, lim)
     }
 
   /* Find the characters specified and set their elements of fastmap.
-     If syntaxp, each character counts as itself.
-     Otherwise, handle backslashes and ranges specially.  */
+     Handle backslashes and ranges specially.
 
-  if (size_byte == XSTRING (string)->size)
-    while (i_byte < size_byte)
-      {
-       c = str[i_byte++];
+     If STRING contains non-ASCII characters, setup char_ranges for
+     them and use fastmap only for their leading codes.  */
 
-       if (syntaxp)
-         fastmap[syntax_spec_code[c]] = 1;       
-       else
-         {
-           if (c == '\\')
-             {
+  str = XSTRING (string)->data;
+  size_byte = STRING_BYTES (XSTRING (string));
+
+  if (! string_multibyte)
+    {
+      int string_has_eight_bit = 0;
+
+      /* At first setup fastmap.  */
+      while (i_byte < size_byte)
+       {
+         c = str[i_byte++];
+
+         if (c == '\\')
+           {
              if (i_byte == size_byte)
                break;
 
@@ -1475,67 +1465,299 @@ skip_chars (forwardp, syntaxp, string, lim)
 
              /* Get the end of the range.  */
              c2 = str[i_byte++];
+             if (c2 == '\\'
+                 && i_byte < size_byte)
+               c2 = str[i_byte++];
+
              while (c <= c2)
                fastmap[c++] = 1;
+             if (! ASCII_CHAR_P (c2))
+               string_has_eight_bit = 1;
            }
          else
-           fastmap[c] = 1;
+           {
+             fastmap[c] = 1;
+             if (! ASCII_CHAR_P (c))
+               string_has_eight_bit = 1;
+           }
+       }
+
+      /* If the current range is multibyte and STRING contains
+        eight-bit chars, arrange fastmap and setup char_ranges for
+        the corresponding multibyte chars.  */
+      if (multibyte && string_has_eight_bit)
+       {
+         unsigned char fastmap2[0400];
+         int range_start_byte, range_start_char;
+
+         bcopy (fastmap2 + 0200, fastmap + 0200, 0200);
+         bzero (fastmap + 0200, 0200);
+         /* We are sure that this loop stops.  */
+         for (i = 0200; ! fastmap2[i]; i++);
+         c = unibyte_char_to_multibyte (i);
+         fastmap[CHAR_LEADING_CODE (c)] = 1;
+         range_start_byte = i;
+         range_start_char = c;
+         for (i = 129; i < 0400; i++)
+           {
+             c = unibyte_char_to_multibyte (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;
+               }                     
+           }
+         char_ranges[n_char_ranges++] = range_start_char;
+         char_ranges[n_char_ranges++] = ((i - 1 - range_start_byte)
+                                         + range_start_char);
        }
     }
   else
-    while (i_byte < size_byte)
-      {
-       c = STRING_CHAR_AND_LENGTH (str + i_byte, size_byte-i_byte, len);
-       i_byte += len;
+    {
+      while (i_byte < size_byte)
+       {
+         unsigned char leading_code;
 
-       if (syntaxp)
-         fastmap[syntax_spec_code[c & 0377]] = 1;
-       else
-         {
-           if (c == '\\')
-             {
-               if (i_byte == size_byte)
-                 break;
+         leading_code = str[i_byte];
+         c = STRING_CHAR_AND_LENGTH (str + i_byte, size_byte-i_byte, len);
+         i_byte += len;
 
-               c = STRING_CHAR_AND_LENGTH (str+i_byte, size_byte-i_byte, len);
-               i_byte += len;
-             }
-           if (i_byte < size_byte
-               && str[i_byte] == '-')
-             {
-               unsigned int c2;
+         if (c == '\\')
+           {
+             if (i_byte == size_byte)
+               break;
+
+             leading_code = str[i_byte];
+             c = STRING_CHAR_AND_LENGTH (str+i_byte, size_byte-i_byte, len);
+             i_byte += len;
+           }
+         if (i_byte < size_byte
+             && str[i_byte] == '-')
+           {
+             unsigned int c2;
+             unsigned char leading_code2;
 
-               /* Skip over the dash.  */
-               i_byte++;
+             /* Skip over the dash.  */
+             i_byte++;
 
-               if (i_byte == size_byte)
-                 break;
+             if (i_byte == size_byte)
+               break;
 
-               /* Get the end of the range.  */
-               c2 =STRING_CHAR_AND_LENGTH (str + i_byte, size_byte-i_byte, len);
-               i_byte += len;
+             /* Get the end of the range.  */
+             leading_code2 = str[i_byte];
+             c2 =STRING_CHAR_AND_LENGTH (str + i_byte, size_byte-i_byte, len);
+             i_byte += len;
 
-               if (ASCII_CHAR_P (c))
+             if (c2 == '\\'
+                 && i_byte < size_byte)
+               {
+                 leading_code2 = str[i_byte];
+                 c2 =STRING_CHAR_AND_LENGTH (str + i_byte, size_byte-i_byte, len);
+                 i_byte += len;
+               }
+
+             if (ASCII_CHAR_P (c))
+               {
                  while (c <= c2 && c < 0x80)
                    fastmap[c++] = 1;
-               if (c <= c2)
-                 {
-                   char_ranges[n_char_ranges++] = c;
-                   char_ranges[n_char_ranges++] = c2;
-                 }
-             }
-           else
-             {
-               if (ASCII_CHAR_P (c))
-                 fastmap[c] = 1;
-               else
-                 {
-                   char_ranges[n_char_ranges++] = c;
-                   char_ranges[n_char_ranges++] = c;
-                 }
-             }
+                 leading_code = CHAR_LEADING_CODE (c);
+               }
+             if (! ASCII_CHAR_P (c))
+               {
+                 while (leading_code <= leading_code2)
+                   fastmap[leading_code++] = 1;
+                 if (c <= c2)
+                   {
+                     char_ranges[n_char_ranges++] = c;
+                     char_ranges[n_char_ranges++] = c2;
+                   }
+               }
+           }
+         else
+           {
+             if (ASCII_CHAR_P (c))
+               fastmap[c] = 1;
+             else
+               {
+                 fastmap[leading_code] = 1;
+                 char_ranges[n_char_ranges++] = c;
+                 char_ranges[n_char_ranges++] = c;
+               }
+           }
+       }
+
+      /* If the current range is unibyte and STRING contains non-ASCII
+        chars, arrange fastmap for the corresponding unibyte
+        chars.  */
+
+      if (! multibyte && n_char_ranges > 0)
+       {
+         bzero (fastmap + 0200, 0200);
+         for (i = 0; i < n_char_ranges; i += 2)
+           {
+             int c1 = char_ranges[i];
+             int c2 = char_ranges[i + 1];
+
+             for (; c1 <= c2; c1++)
+               fastmap[CHAR_TO_BYTE8 (c1)] = 1;
+           }
+       }
+    }
+
+  /* If ^ was the first character, complement the fastmap.  */
+  if (negate)
+    {
+      if (! multibyte)
+       for (i = 0; i < sizeof fastmap; i++)
+         fastmap[i] ^= 1;
+      else
+       {
+         for (i = 0; i < 0200; i++)
+           fastmap[i] ^= 1;
+         /* All non-ASCII chars possibly match.  */
+         for (; i < sizeof fastmap; i++)
+           fastmap[i] = 1;
+       }
+    }
+
+  {
+    int start_point = PT;
+    int pos = PT;
+    int pos_byte = PT_BYTE;
+
+    immediate_quit = 1;
+    if (forwardp)
+      {
+       if (multibyte)
+         while (pos < XINT (lim))
+           {
+             c = FETCH_BYTE (pos_byte);
+             if (! fastmap[c])
+               break;
+             if (! ASCII_CHAR_P (c))
+               {
+                 c = FETCH_MULTIBYTE_CHAR (pos_byte);
+                 /* As we are looking at a multibyte character, we
+                    must look up the character in the table
+                    CHAR_RANGES.  If there's no data in the table,
+                    that character is not what we want to skip.  */
+
+                 /* The following code do the right thing even if
+                    n_char_ranges is zero (i.e. no data in
+                    CHAR_RANGES).  */
+                 for (i = 0; i < n_char_ranges; i += 2)
+                   if (c >= char_ranges[i] && c <= char_ranges[i + 1])
+                     break;
+                 if (!(negate ^ (i < n_char_ranges)))
+                   break;
+               }
+             /* Since we already checked for multibyteness, avoid
+                using INC_BOTH which checks again.  */
+             INC_POS (pos_byte);
+             pos++;
+           }
+       else
+         {
+           while (pos < XINT (lim) && fastmap[FETCH_BYTE (pos)])
+             pos++;
+           pos_byte = pos;
          }
       }
+    else
+      {
+       if (multibyte)
+         while (pos > XINT (lim))
+           {
+             int prev_pos_byte = pos_byte;
+
+             DEC_POS (prev_pos_byte);
+             c = FETCH_BYTE (prev_pos_byte);
+             if (! fastmap[c])
+               break;
+             if (! ASCII_CHAR_P (c))
+               {
+                 c = FETCH_MULTIBYTE_CHAR (prev_pos_byte);
+                 /* See the comment in the previous similar code.  */
+                 for (i = 0; i < n_char_ranges; i += 2)
+                   if (c >= char_ranges[i] && c <= char_ranges[i + 1])
+                     break;
+                 if (!(negate ^ (i < n_char_ranges)))
+                   break;
+               }
+             pos--;
+             pos_byte = prev_pos_byte;
+           }
+       else
+         {
+           while (pos > XINT (lim) && fastmap[FETCH_BYTE (pos - 1)])
+             pos--;
+           pos_byte = pos;
+         }
+      }
+
+    SET_PT_BOTH (pos, pos_byte);
+    immediate_quit = 0;
+
+    return make_number (PT - start_point);
+  }
+}
+
+
+static Lisp_Object
+skip_syntaxes (forwardp, string, lim)
+     int forwardp;
+     Lisp_Object string, lim;
+{
+  register unsigned int c;
+  unsigned char fastmap[0400];
+  int negate = 0;
+  register int i, i_byte;
+  int multibyte;
+  int size_byte;
+  unsigned char *str;
+
+  CHECK_STRING (string);
+
+  if (NILP (lim))
+    XSETINT (lim, forwardp ? ZV : BEGV);
+  else
+    CHECK_NUMBER_COERCE_MARKER (lim);
+
+  /* In any case, don't allow scan outside bounds of buffer.  */
+  if (XINT (lim) > ZV)
+    XSETFASTINT (lim, ZV);
+  if (XINT (lim) < BEGV)
+    XSETFASTINT (lim, BEGV);
+
+  multibyte = (!NILP (current_buffer->enable_multibyte_characters)
+              && (lim - PT != CHAR_TO_BYTE (lim) - PT_BYTE));
+
+  bzero (fastmap, sizeof fastmap);
+
+  i_byte = 0;
+  if (i_byte < size_byte
+      && XSTRING (string)->data[0] == '^')
+    {
+      negate = 1; i_byte++;
+    }
+
+  if (STRING_BYTES (XSTRING (string)) > XSTRING (string)->size)
+    /* As this is very rare case, don't consider efficiency.  */
+    string = string_make_unibyte (string);
+  str = XSTRING (string)->data;
+  size_byte = STRING_BYTES (XSTRING (string));
+
+  /* Find the syntaxes specified and set their elements of fastmap.  */
+
+  while (i_byte < size_byte)
+    {
+      c = str[i_byte++];
+      fastmap[syntax_spec_code[c]] = 1;          
+    }
 
   /* If ^ was the first character, complement the fastmap.  */
   if (negate)
@@ -1548,139 +1770,75 @@ skip_chars (forwardp, syntaxp, string, lim)
     int pos_byte = PT_BYTE;
 
     immediate_quit = 1;
-    if (syntaxp)
+    SETUP_SYNTAX_TABLE (pos, forwardp ? 1 : -1);
+    if (forwardp)
       {
-        SETUP_SYNTAX_TABLE (pos, forwardp ? 1 : -1);
-       if (forwardp)
+       if (multibyte)
          {
-           if (multibyte)
-             {
-               if (pos < XINT (lim))
-                 while (fastmap[(int) SYNTAX (FETCH_CHAR (pos_byte))])
-                   {
-                     /* Since we already checked for multibyteness,
-                        avoid using INC_BOTH which checks again.  */
-                     INC_POS (pos_byte);
-                     pos++;
-                     if (pos >= XINT (lim))
-                       break;
-                     UPDATE_SYNTAX_TABLE_FORWARD (pos);
-                   }
-             }
-           else
-             {
-               while (pos < XINT (lim)
-                      && fastmap[(int) SYNTAX (FETCH_BYTE (pos))])
-                 {
-                   pos++;
-                   UPDATE_SYNTAX_TABLE_FORWARD (pos);
-                 }
-             }
+           if (pos < XINT (lim))
+             while (fastmap[(int) SYNTAX (FETCH_CHAR (pos_byte))])
+               {
+                 /* Since we already checked for multibyteness,
+                    avoid using INC_BOTH which checks again.  */
+                 INC_POS (pos_byte);
+                 pos++;
+                 if (pos >= XINT (lim))
+                   break;
+                 UPDATE_SYNTAX_TABLE_FORWARD (pos);
+               }
          }
        else
          {
-           if (multibyte)
-             {
-               while (pos > XINT (lim))
-                 {
-                   int savepos = pos_byte;
-                   /* Since we already checked for multibyteness,
-                      avoid using DEC_BOTH which checks again.  */
-                   pos--;
-                   DEC_POS (pos_byte);
-                   UPDATE_SYNTAX_TABLE_BACKWARD (pos);
-                   if (!fastmap[(int) SYNTAX (FETCH_CHAR (pos_byte))])
-                     {
-                       pos++;
-                       pos_byte = savepos;
-                       break;
-                     }
-                 }
-             }
-           else
+           while (pos < XINT (lim))
              {
-               if (pos > XINT (lim))
-                 while (fastmap[(int) SYNTAX (FETCH_BYTE (pos - 1))])
-                   {
-                     pos--;
-                     if (pos <= XINT (lim))
-                       break;
-                     UPDATE_SYNTAX_TABLE_BACKWARD (pos - 1);
-                   }
+               c = FETCH_BYTE (pos);
+               MAKE_CHAR_MULTIBYTE (c);
+               if (fastmap[(int) SYNTAX (c)])
+                 break;
+               pos++;
+               UPDATE_SYNTAX_TABLE_FORWARD (pos);
              }
+           pos_byte = pos;
          }
       }
     else
       {
-       if (forwardp)
+       if (multibyte)
          {
-           if (multibyte)
-             while (pos < XINT (lim))
-               {
-                 c = FETCH_MULTIBYTE_CHAR (pos_byte);
-                 if (ASCII_CHAR_P (c))
-                   {
-                     if (!fastmap[c])
-                       break;
-                   }
-                 else
-                   {
-                     /* If we are looking at a multibyte character,
-                        we must look up the character in the table
-                        CHAR_RANGES.  If there's no data in the
-                        table, that character is not what we want to
-                        skip.  */
-
-                     /* The following code do the right thing even if
-                        n_char_ranges is zero (i.e. no data in
-                        CHAR_RANGES).  */
-                     for (i = 0; i < n_char_ranges; i += 2)
-                       if (c >= char_ranges[i] && c <= char_ranges[i + 1])
-                         break;
-                     if (!(negate ^ (i < n_char_ranges)))
-                       break;
-                   }
-                 INC_BOTH (pos, pos_byte);
-               }
-           else
-             while (pos < XINT (lim) && fastmap[FETCH_BYTE (pos)])
-               pos++;
+           while (pos > XINT (lim))
+             {
+               int savepos = pos_byte;
+               /* Since we already checked for multibyteness,
+                  avoid using DEC_BOTH which checks again.  */
+               pos--;
+               DEC_POS (pos_byte);
+               UPDATE_SYNTAX_TABLE_BACKWARD (pos);
+               if (!fastmap[(int) SYNTAX (FETCH_CHAR (pos_byte))])
+                 {
+                   pos++;
+                   pos_byte = savepos;
+                   break;
+                 }
+             }
          }
        else
          {
-           if (multibyte)
-             while (pos > XINT (lim))
+           if (pos > XINT (lim))
+             while (1)
                {
-                 int prev_pos_byte = pos_byte;
-
-                 DEC_POS (prev_pos_byte);
-                 c = FETCH_MULTIBYTE_CHAR (prev_pos_byte);
-                 if (SINGLE_BYTE_CHAR_P (c))
-                   {
-                     if (!fastmap[c])
-                       break;
-                   }
-                 else
-                   {
-                     /* See the comment in the previous similar code.  */
-                     for (i = 0; i < n_char_ranges; i += 2)
-                       if (c >= char_ranges[i] && c <= char_ranges[i + 1])
-                         break;
-                     if (!(negate ^ (i < n_char_ranges)))
-                       break;
-                   }
+                 c = FETCH_BYTE (pos - 1);
+                 MAKE_CHAR_MULTIBYTE (c);
+                 if (! fastmap[(int) SYNTAX (c)])
+                   break;
                  pos--;
-                 pos_byte = prev_pos_byte;
+                 if (pos <= XINT (lim))
+                   break;
+                 UPDATE_SYNTAX_TABLE_BACKWARD (pos - 1);
                }
-           else
-             while (pos > XINT (lim) && fastmap[FETCH_BYTE (pos - 1)])
-               pos--;
+           pos_byte = pos;
          }
       }
 
-    if (! multibyte)
-      pos_byte = pos;
-
     SET_PT_BOTH (pos, pos_byte);
     immediate_quit = 0;
 
@@ -1851,7 +2009,7 @@ between them, return t; otherwise return nil.  */)
              immediate_quit = 0;
              return Qnil;
            }
-         c = FETCH_CHAR (from_byte);
+         c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
          code = SYNTAX (c);
          comstart_first = SYNTAX_COMSTART_FIRST (c);
          comnested = SYNTAX_COMMENT_NESTED (c);
@@ -1859,7 +2017,7 @@ between them, return t; otherwise return nil.  */)
          INC_BOTH (from, from_byte);
          UPDATE_SYNTAX_TABLE_FORWARD (from);
          if (from < stop && comstart_first
-             && (c1 = FETCH_CHAR (from_byte),
+             && (c1 = FETCH_CHAR_AS_MULTIBYTE (from_byte),
                  SYNTAX_COMSTART_SECOND (c1)))
            {
              /* We have encountered a comment start sequence and we 
@@ -1917,7 +2075,7 @@ between them, return t; otherwise return nil.  */)
          DEC_BOTH (from, from_byte);
          /* char_quoted does UPDATE_SYNTAX_TABLE_BACKWARD (from).  */
          quoted = char_quoted (from, from_byte);
-         c = FETCH_CHAR (from_byte);
+         c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
          code = SYNTAX (c);
          comstyle = 0;
          comnested = SYNTAX_COMMENT_NESTED (c);
@@ -1934,7 +2092,7 @@ between them, return t; otherwise return nil.  */)
              code = Sendcomment;
              /* Calling char_quoted, above, set up global syntax position
                 at the new value of FROM.  */
-             c1 = FETCH_CHAR (from_byte);
+             c1 = FETCH_CHAR_AS_MULTIBYTE (from_byte);
              comstyle = SYNTAX_COMMENT_STYLE (c1);
              comnested = comnested || SYNTAX_COMMENT_NESTED (c1);
            }
@@ -1950,7 +2108,7 @@ between them, return t; otherwise return nil.  */)
                  if (from == stop)
                    break;
                  UPDATE_SYNTAX_TABLE_BACKWARD (from);
-                 c = FETCH_CHAR (from_byte);
+                 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
                  if (SYNTAX (c) == Scomment_fence
                      && !char_quoted (from, from_byte)) 
                    {
@@ -2011,11 +2169,11 @@ between them, return t; otherwise return nil.  */)
   return Qt;
 }
 \f
-/* Return syntax code of character C if C is a single byte character
+/* Return syntax code of character C if C is an ASCII character
    or `multibyte_symbol_p' is zero.  Otherwise, return Ssymbol.  */
 
-#define SYNTAX_WITH_MULTIBYTE_CHECK(c)                 \
-  ((SINGLE_BYTE_CHAR_P (c) || !multibyte_symbol_p)     \
+#define SYNTAX_WITH_MULTIBYTE_CHECK(c)         \
+  ((ASCII_CHAR_P (c) || !multibyte_symbol_p)   \
    ? SYNTAX (c) : Ssymbol)
 
 static Lisp_Object
@@ -2058,7 +2216,7 @@ scan_lists (from, count, depth, sexpflag)
        {
          int comstart_first, prefix;
          UPDATE_SYNTAX_TABLE_FORWARD (from);
-         c = FETCH_CHAR (from_byte);
+         c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
          code = SYNTAX_WITH_MULTIBYTE_CHECK (c);
          comstart_first = SYNTAX_COMSTART_FIRST (c);
          comnested = SYNTAX_COMMENT_NESTED (c);
@@ -2069,7 +2227,7 @@ scan_lists (from, count, depth, sexpflag)
          INC_BOTH (from, from_byte);
          UPDATE_SYNTAX_TABLE_FORWARD (from);
          if (from < stop && comstart_first
-             && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from_byte))
+             && SYNTAX_COMSTART_SECOND (FETCH_CHAR_AS_MULTIBYTE (from_byte))
              && parse_sexp_ignore_comments)
            {
              /* we have encountered a comment start sequence and we 
@@ -2078,7 +2236,7 @@ scan_lists (from, count, depth, sexpflag)
                 only a comment end of the same style actually ends
                 the comment section */
              code = Scomment;
-             c1 = FETCH_CHAR (from_byte);
+             c1 = FETCH_CHAR_AS_MULTIBYTE (from_byte);
              comstyle = SYNTAX_COMMENT_STYLE (c1);
              comnested = comnested || SYNTAX_COMMENT_NESTED (c1);
              INC_BOTH (from, from_byte);
@@ -2104,7 +2262,7 @@ scan_lists (from, count, depth, sexpflag)
                  UPDATE_SYNTAX_TABLE_FORWARD (from);
 
                  /* Some compilers can't handle this inside the switch.  */
-                 c = FETCH_CHAR (from_byte);
+                 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
                  temp = SYNTAX_WITH_MULTIBYTE_CHECK (c);
                  switch (temp)
                    {
@@ -2147,7 +2305,7 @@ scan_lists (from, count, depth, sexpflag)
            case Smath:
              if (!sexpflag)
                break;
-             if (from != stop && c == FETCH_CHAR (from_byte))
+             if (from != stop && c == FETCH_CHAR_AS_MULTIBYTE (from_byte))
                {
                  INC_BOTH (from, from_byte);
                }
@@ -2175,12 +2333,12 @@ scan_lists (from, count, depth, sexpflag)
            case Sstring:
            case Sstring_fence:
              temp_pos = dec_bytepos (from_byte);
-             stringterm = FETCH_CHAR (temp_pos);
+             stringterm = FETCH_CHAR_AS_MULTIBYTE (temp_pos);
              while (1)
                {
                  if (from >= stop) goto lose;
                  UPDATE_SYNTAX_TABLE_FORWARD (from);
-                 c = FETCH_CHAR (from_byte);
+                 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
                  if (code == Sstring
                      ? (c == stringterm
                         && SYNTAX_WITH_MULTIBYTE_CHECK (c) == Sstring)
@@ -2220,7 +2378,7 @@ scan_lists (from, count, depth, sexpflag)
        {
          DEC_BOTH (from, from_byte);
          UPDATE_SYNTAX_TABLE_BACKWARD (from);
-         c = FETCH_CHAR (from_byte);
+         c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
          code = SYNTAX_WITH_MULTIBYTE_CHECK (c);
          if (depth == min_depth)
            last_good = from;
@@ -2238,7 +2396,7 @@ scan_lists (from, count, depth, sexpflag)
              DEC_BOTH (from, from_byte);
              UPDATE_SYNTAX_TABLE_BACKWARD (from);
              code = Sendcomment;
-             c1 = FETCH_CHAR (from_byte);
+             c1 = FETCH_CHAR_AS_MULTIBYTE (from_byte);
              comstyle = SYNTAX_COMMENT_STYLE (c1);
              comnested = comnested || SYNTAX_COMMENT_NESTED (c1);
            }
@@ -2268,7 +2426,7 @@ scan_lists (from, count, depth, sexpflag)
                  else
                    temp_pos--;
                  UPDATE_SYNTAX_TABLE_BACKWARD (from - 1);
-                 c1 = FETCH_CHAR (temp_pos);
+                 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)
@@ -2280,7 +2438,7 @@ scan_lists (from, count, depth, sexpflag)
                      temp_pos = dec_bytepos (temp_pos);
                      UPDATE_SYNTAX_TABLE_BACKWARD (from - 1);
                    }
-                 c1 = FETCH_CHAR (temp_pos);
+                 c1 = FETCH_CHAR_AS_MULTIBYTE (temp_pos);
                  temp_code = SYNTAX_WITH_MULTIBYTE_CHECK (c1);
                  if (! (quoted || temp_code == Sword
                         || temp_code == Ssymbol
@@ -2295,7 +2453,7 @@ scan_lists (from, count, depth, sexpflag)
                break;
              temp_pos = dec_bytepos (from_byte);
              UPDATE_SYNTAX_TABLE_BACKWARD (from - 1);
-             if (from != stop && c == FETCH_CHAR (temp_pos))
+             if (from != stop && c == FETCH_CHAR_AS_MULTIBYTE (temp_pos))
                DEC_BOTH (from, from_byte);
              if (mathexit)
                {
@@ -2341,7 +2499,7 @@ scan_lists (from, count, depth, sexpflag)
                  if (from == stop) goto lose;
                  UPDATE_SYNTAX_TABLE_BACKWARD (from);
                  if (!char_quoted (from, from_byte) 
-                     && (c = FETCH_CHAR (from_byte),
+                     && (c = FETCH_CHAR_AS_MULTIBYTE (from_byte),
                          SYNTAX_WITH_MULTIBYTE_CHECK (c) == code))
                    break;
                }
@@ -2349,7 +2507,7 @@ scan_lists (from, count, depth, sexpflag)
              break;
              
            case Sstring:
-             stringterm = FETCH_CHAR (from_byte);
+             stringterm = FETCH_CHAR_AS_MULTIBYTE (from_byte);
              while (1)
                {
                  if (from == stop) goto lose;
@@ -2360,7 +2518,7 @@ scan_lists (from, count, depth, sexpflag)
                    temp_pos--;
                  UPDATE_SYNTAX_TABLE_BACKWARD (from - 1);
                  if (!char_quoted (from - 1, temp_pos)
-                     && stringterm == (c = FETCH_CHAR (temp_pos))
+                     && stringterm == (c = FETCH_CHAR_AS_MULTIBYTE (temp_pos))
                      && SYNTAX_WITH_MULTIBYTE_CHECK (c) == Sstring)
                    break;
                  DEC_BOTH (from, from_byte);
@@ -2465,7 +2623,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 (pos_byte), SYNTAX (c) == Squote)
+        && ((c = FETCH_CHAR_AS_MULTIBYTE (pos_byte), SYNTAX (c) == Squote)
             || SYNTAX_PREFIX (c)))
     {
       opoint = pos;
@@ -2691,7 +2849,7 @@ do { prev_from = from;                            \
          while (from < end)
            {
              /* Some compilers can't handle this inside the switch.  */
-             temp = SYNTAX (FETCH_CHAR (from_byte));
+             temp = SYNTAX (FETCH_CHAR_AS_MULTIBYTE (from_byte));
              switch (temp)
                {
                case Scharquote:
@@ -2763,7 +2921,7 @@ do { prev_from = from;                            \
          if (stopbefore) goto stop;  /* this arg means stop at sexp start */
          curlevel->last = prev_from;
          state.instring = (code == Sstring 
-                           ? (FETCH_CHAR (prev_from_byte))
+                           ? (FETCH_CHAR_AS_MULTIBYTE (prev_from_byte))
                            : ST_STRING_STYLE);
          if (boundary_stop) goto done;
        startinstring:
@@ -2775,7 +2933,7 @@ do { prev_from = from;                            \
                int c;
 
                if (from >= end) goto done;
-               c = FETCH_CHAR (from_byte);
+               c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
                /* Some compilers can't handle this inside the switch.  */
                temp = SYNTAX (c);