changeset 89063:2054397a36be

(char_quoted): Use FETCH_CHAR_AS_MULTIBYTE to convert 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.
author Kenichi Handa <handa@m17n.org>
date Tue, 03 Sep 2002 04:10:19 +0000
parents be059fb97bac
children 2ac5108292b2
files src/syntax.c
diffstat 1 files changed, 410 insertions(+), 252 deletions(-) [+]
line wrap: on
line diff
--- a/src/syntax.c	Tue Sep 03 04:09:59 2002 +0000
+++ b/src/syntax.c	Tue Sep 03 04:10:19 2002 +0000
@@ -97,7 +97,8 @@
 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 @@
   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 @@
 	{
 	  /* 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 @@
       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 @@
 	  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 @@
 	      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 @@
 	    {
 	      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 @@
 	    }
 	  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 @@
 		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 @@
      (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 @@
      (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 @@
      (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 @@
      (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 @@
   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 @@
     }
 
   /* Find the characters specified and set their elements of fastmap.
-     If syntaxp, each character counts as itself.
-     Otherwise, handle backslashes and ranges specially.  */
-
-  if (size_byte == XSTRING (string)->size)
-    while (i_byte < size_byte)
-      {
-	c = str[i_byte++];
-
-	if (syntaxp)
-	  fastmap[syntax_spec_code[c]] = 1;	  
-	else
-	  {
-	    if (c == '\\')
-	      {
+     Handle backslashes and ranges specially.
+
+     If STRING contains non-ASCII characters, setup char_ranges for
+     them and use fastmap only for their leading codes.  */
+
+  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,68 +1465,300 @@
 
 	      /* 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)
+    {
+      while (i_byte < size_byte)
+	{
+	  unsigned char leading_code;
+
+	  leading_code = str[i_byte];
+	  c = STRING_CHAR_AND_LENGTH (str + i_byte, size_byte-i_byte, len);
+	  i_byte += len;
+
+	  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++;
+
+	      if (i_byte == size_byte)
+		break;
+
+	      /* 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 (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;
+		  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)
       {
-	c = STRING_CHAR_AND_LENGTH (str + i_byte, size_byte-i_byte, len);
-	i_byte += len;
-
-	if (syntaxp)
-	  fastmap[syntax_spec_code[c & 0377]] = 1;
+	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
 	  {
-	    if (c == '\\')
-	      {
-		if (i_byte == size_byte)
-		  break;
-
-		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;
-
-		/* Skip over the dash.  */
-		i_byte++;
-
-		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;
-
-		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;
-		  }
-	      }
+	    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)
     for (i = 0; i < sizeof fastmap; i++)
@@ -1548,138 +1770,74 @@
     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))
 	      {
-		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);
-		    }
+		c = FETCH_BYTE (pos);
+		MAKE_CHAR_MULTIBYTE (c);
+		if (fastmap[(int) SYNTAX (c)])
+		  break;
+		pos++;
+		UPDATE_SYNTAX_TABLE_FORWARD (pos);
 	      }
-	    else
+	    pos_byte = pos;
+	  }
+      }
+    else
+      {
+	if (multibyte)
+	  {
+	    while (pos > XINT (lim))
 	      {
-		while (pos < XINT (lim)
-		       && fastmap[(int) SYNTAX (FETCH_BYTE (pos))])
+		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++;
-		    UPDATE_SYNTAX_TABLE_FORWARD (pos);
+		    pos_byte = savepos;
+		    break;
 		  }
 	      }
 	  }
 	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
-	      {
-		if (pos > XINT (lim))
-		  while (fastmap[(int) SYNTAX (FETCH_BYTE (pos - 1))])
-		    {
-		      pos--;
-		      if (pos <= XINT (lim))
-			break;
-		      UPDATE_SYNTAX_TABLE_BACKWARD (pos - 1);
-		    }
-	      }
+	    if (pos > XINT (lim))
+	      while (1)
+		{
+		  c = FETCH_BYTE (pos - 1);
+		  MAKE_CHAR_MULTIBYTE (c);
+		  if (! fastmap[(int) SYNTAX (c)])
+		    break;
+		  pos--;
+		  if (pos <= XINT (lim))
+		    break;
+		  UPDATE_SYNTAX_TABLE_BACKWARD (pos - 1);
+		}
+	    pos_byte = pos;
 	  }
       }
-    else
-      {
-	if (forwardp)
-	  {
-	    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++;
-	  }
-	else
-	  {
-	    if (multibyte)
-	      while (pos > XINT (lim))
-		{
-		  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;
-		    }
-		  pos--;
-		  pos_byte = prev_pos_byte;
-		}
-	    else
-	      while (pos > XINT (lim) && fastmap[FETCH_BYTE (pos - 1)])
-		pos--;
-	  }
-      }
-
-    if (! multibyte)
-      pos_byte = pos;
 
     SET_PT_BOTH (pos, pos_byte);
     immediate_quit = 0;
@@ -1851,7 +2009,7 @@
 	      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 @@
 	  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 @@
 	  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 @@
 	      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 @@
 		  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 @@
   return Qt;
 }
 
-/* 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 @@
 	{
 	  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 @@
 	  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 @@
 		 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 @@
 		  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 @@
 	    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 @@
 	    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 @@
 	{
 	  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 @@
 	      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 @@
 		  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 @@
 		      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 @@
 		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 @@
 		  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 @@
 	      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 @@
 		    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 @@
 
   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 @@
 	  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 @@
 	  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 @@
 		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);