changeset 88383:0b4249d736a0

Include "character.h". (read_multibyte): New arg NBYTES. (read_escape): The meaning of returned *BYTEREP changed. (to_multibyte): Deleted. (read1): Adjuted the handling of char table and string.
author Kenichi Handa <handa@m17n.org>
date Fri, 01 Mar 2002 01:44:45 +0000
parents 5e3e1d9d514f
children 4bff91d684f4
files src/lread.c
diffstat 1 files changed, 151 insertions(+), 131 deletions(-) [+]
line wrap: on
line diff
--- a/src/lread.c	Fri Mar 01 01:44:13 2002 +0000
+++ b/src/lread.c	Fri Mar 01 01:44:45 2002 +0000
@@ -29,6 +29,7 @@
 #include "lisp.h"
 #include "intervals.h"
 #include "buffer.h"
+#include "character.h"
 #include "charset.h"
 #include <epaths.h>
 #include "commands.h"
@@ -1476,36 +1477,51 @@
 
 /* Read multibyte form and return it as a character.  C is a first
    byte of multibyte form, and rest of them are read from
-   READCHARFUN.  */
+   READCHARFUN.  Store the byte length of the form into *NBYTES.  */
 
 static int
-read_multibyte (c, readcharfun)
+read_multibyte (c, readcharfun, nbytes)
      register int c;
      Lisp_Object readcharfun;
+     int *nbytes;
 {
   /* We need the actual character code of this multibyte
      characters.  */
   unsigned char str[MAX_MULTIBYTE_LENGTH];
   int len = 0;
-  int bytes;
+  int bytes = BYTES_BY_CHAR_HEAD (c);
 
   str[len++] = c;
-  while ((c = READCHAR) >= 0xA0
-	 && len < MAX_MULTIBYTE_LENGTH)
-    str[len++] = c;
-  UNREAD (c);
-  if (UNIBYTE_STR_AS_MULTIBYTE_P (str, len, bytes))
-    return STRING_CHAR (str, len);
+  while (len < bytes)
+    {
+      c = READCHAR;
+      if (CHAR_HEAD_P (c))
+	{
+	  UNREAD (c);
+	  break;
+	}
+      str[len++] = c;
+    }
+
+  if (len == bytes && MULTIBYTE_LENGTH_NO_CHECK (str) > 0)
+    {
+      *nbytes = len;
+      return STRING_CHAR (str, len);
+    }
   /* The byte sequence is not valid as multibyte.  Unread all bytes
      but the first one, and return the first byte.  */
   while (--len > 0)
     UNREAD (str[len]);
+  *nbytes = 1;
   return str[0];
 }
 
 /* Read a \-escape sequence, assuming we already read the `\'.
    If the escape sequence forces unibyte, store 1 into *BYTEREP.
-   If the escape sequence forces multibyte, store 2 into *BYTEREP.
+   If the escape sequence forces multibyte and the returned character
+   is raw 8-bit char, store 2 into *BYTEREP.
+   If the escape sequence forces multibyte and the returned character
+   is not raw 8-bit char, store 3 into *BYTEREP.
    Otherwise store 0 into *BYTEREP.  */
 
 static int
@@ -1640,7 +1656,10 @@
 	      }
 	  }
 	
-	*byterep = 1;
+	if (c < 0x100)
+	  *byterep = 1;
+	else
+	  *byterep = 3;
 	return i;
       }
 
@@ -1648,6 +1667,7 @@
       /* A hex escape, as in ANSI C.  */
       {
 	int i = 0;
+	int count = 0;
 	while (1)
 	  {
 	    c = READCHAR;
@@ -1670,15 +1690,26 @@
 		UNREAD (c);
 		break;
 	      }
+	    count++;
 	  }
 
-	*byterep = 2;
+	if (count < 3 && i >= 0x80)
+	  *byterep = 2;
+	else
+	  *byterep = 3;
 	return i;
       }
 
     default:
-      if (BASE_LEADING_CODE_P (c))
-	c = read_multibyte (c, readcharfun);
+      if (EQ (readcharfun, Qget_file_char)
+	  && BASE_LEADING_CODE_P (c))
+	{
+	  int nbytes;
+
+	  c = read_multibyte (c, readcharfun, &nbytes);
+	  if (nbytes > 1)
+	    *byterep = 3;
+	}
       return c;
     }
 }
@@ -1750,43 +1781,6 @@
 }
 
 
-/* Convert unibyte text in read_buffer to multibyte.
-
-   Initially, *P is a pointer after the end of the unibyte text, and
-   the pointer *END points after the end of read_buffer.
-
-   If read_buffer doesn't have enough room to hold the result
-   of the conversion, reallocate it and adjust *P and *END.
-
-   At the end, make *P point after the result of the conversion, and
-   return in *NCHARS the number of characters in the converted
-   text.  */
-
-static void
-to_multibyte (p, end, nchars)
-     char **p, **end;
-     int *nchars;
-{
-  int nbytes;
-
-  parse_str_as_multibyte (read_buffer, *p - read_buffer, &nbytes, nchars);
-  if (read_buffer_size < 2 * nbytes)
-    {
-      int offset = *p - read_buffer;
-      read_buffer_size = 2 * max (read_buffer_size, nbytes);
-      read_buffer = (char *) xrealloc (read_buffer, read_buffer_size);
-      *p = read_buffer + offset;
-      *end = read_buffer + read_buffer_size;
-    }
-
-  if (nbytes != *nchars)
-    nbytes = str_as_multibyte (read_buffer, read_buffer_size,
-			       *p - read_buffer, nchars);
-  
-  *p = read_buffer + nbytes;
-}
-
-
 /* If the next token is ')' or ']' or '.', we store that character
    in *PCH and the return value is not interesting.  Else, we store
    zero in *PCH and we read and return one lisp object.
@@ -1834,11 +1828,9 @@
 	    {
 	      Lisp_Object tmp;
 	      tmp = read_vector (readcharfun, 0);
-	      if (XVECTOR (tmp)->size < CHAR_TABLE_STANDARD_SLOTS
-		  || XVECTOR (tmp)->size > CHAR_TABLE_STANDARD_SLOTS + 10)
+	      if (XVECTOR (tmp)->size != VECSIZE (struct Lisp_Char_Table))
 		error ("Invalid size char-table");
 	      XSETCHAR_TABLE (tmp, XCHAR_TABLE (tmp));
-	      XCHAR_TABLE (tmp)->top = Qt;
 	      return tmp;
 	    }
 	  else if (c == '^')
@@ -1847,11 +1839,18 @@
 	      if (c == '[')
 		{
 		  Lisp_Object tmp;
+		  int depth, size;
+		  
 		  tmp = read_vector (readcharfun, 0);
-		  if (XVECTOR (tmp)->size != SUB_CHAR_TABLE_STANDARD_SLOTS)
+		  if (!INTEGERP (AREF (tmp, 0)))
+		    error ("Invalid depth in char-table");
+		  depth = XINT (AREF (tmp, 0));
+		  if (depth < 1 || depth > 3)
+		    error ("Invalid depth in char-table");
+		  size = XVECTOR (tmp)->size + 2;
+		  if (chartab_size [depth] != size)
 		    error ("Invalid size char-table");
-		  XSETCHAR_TABLE (tmp, XCHAR_TABLE (tmp));
-		  XCHAR_TABLE (tmp)->top = Qnil;
+		  XSETSUB_CHAR_TABLE (tmp, XSUB_CHAR_TABLE (tmp));
 		  return tmp;
 		}
 	      Fsignal (Qinvalid_read_syntax,
@@ -2134,8 +2133,9 @@
 
 	if (c == '\\')
 	  c = read_escape (readcharfun, 0, &discard);
-	else if (BASE_LEADING_CODE_P (c))
-	  c = read_multibyte (c, readcharfun);
+	else if (EQ (readcharfun, Qget_file_char)
+		 && BASE_LEADING_CODE_P (c))
+	  c = read_multibyte (c, readcharfun, &discard);
 
 	return make_number (c);
       }
@@ -2145,14 +2145,12 @@
 	char *p = read_buffer;
 	char *end = read_buffer + read_buffer_size;
 	register int c;
-	/* 1 if we saw an escape sequence specifying
-	   a multibyte character, or a multibyte character.  */
+	/* Nonzero if we saw an escape sequence specifying
+	   a multibyte character.  */
 	int force_multibyte = 0;
-	/* 1 if we saw an escape sequence specifying
+	/* Nonzero if we saw an escape sequence specifying
 	   a single-byte character.  */
 	int force_singlebyte = 0;
-	/* 1 if read_buffer contains multibyte text now.  */
-	int is_multibyte = 0;
 	int cancel = 0;
 	int nchars = 0;
 
@@ -2170,6 +2168,7 @@
 
 	    if (c == '\\')
 	      {
+		int modifiers;
 		int byterep;
 
 		c = read_escape (readcharfun, 1, &byterep);
@@ -2182,53 +2181,92 @@
 		    continue;
 		  }
 
+		modifiers = c & CHAR_MODIFIER_MASK;
+		c = c & ~CHAR_MODIFIER_MASK;
+
 		if (byterep == 1)
-		  force_singlebyte = 1;
-		else if (byterep == 2)
-		  force_multibyte = 1;
-	      }
-
-	    /* A character that must be multibyte forces multibyte.  */
-	    if (! SINGLE_BYTE_CHAR_P (c & ~CHAR_MODIFIER_MASK))
-	      force_multibyte = 1;
-
-	    /* If we just discovered the need to be multibyte,
-	       convert the text accumulated thus far.  */
-	    if (force_multibyte && ! is_multibyte)
-	      {
-		is_multibyte = 1;
-		to_multibyte (&p, &end, &nchars);
+		  {
+		    force_singlebyte = 1;
+		    if (c >= 0x80)
+		      /*  Raw 8-bit code */
+		      c = BYTE8_TO_CHAR (c);
+		  }
+		else if (byterep > 1)
+		  {
+		    force_multibyte = 1;
+		    if (byterep == 2)
+		      c = BYTE8_TO_CHAR (c);
+		  }
+		else if (c >= 0x80)
+		  {
+		    force_singlebyte = 1;
+		    c = BYTE8_TO_CHAR (c);
+		  }
+
+		if (ASCII_CHAR_P (c))
+		  {
+		    /* Allow `\C- ' and `\C-?'.  */
+		    if (modifiers == CHAR_CTL)
+		      {
+			if (c == ' ')
+			  c = 0, modifiers = 0;
+			else if (c == '?')
+			  c = 127, modifiers = 0;
+		      }
+		    if (modifiers & CHAR_SHIFT)
+		      {
+			/* Shift modifier is valid only with [A-Za-z].  */
+			if (c >= 'A' && c <= 'Z')
+			  modifiers &= ~CHAR_SHIFT;
+			else if (c >= 'a' && c <= 'z')
+			  c -= ('a' - 'A'), modifiers &= ~CHAR_SHIFT;
+		      }
+
+		    if (modifiers & CHAR_META)
+		      {
+			/* Move the meta bit to the right place for a
+			   string.  */
+			modifiers &= ~CHAR_META;
+			c = BYTE8_TO_CHAR (c | 0x80);
+			force_singlebyte = 1;
+		      }
+		  }
+
+		/* Any modifiers remaining are invalid.  */
+		if (modifiers)
+		  error ("Invalid modifier in string");
+		p += CHAR_STRING (c, (unsigned char *) p);
 	      }
-
-	    /* Allow `\C- ' and `\C-?'.  */
-	    if (c == (CHAR_CTL | ' '))
-	      c = 0;
-	    else if (c == (CHAR_CTL | '?'))
-	      c = 127;
-
-	    if (c & CHAR_SHIFT)
+	    else if (c >= 0x80)
 	      {
-		/* Shift modifier is valid only with [A-Za-z].  */
-		if ((c & 0377) >= 'A' && (c & 0377) <= 'Z')
-		  c &= ~CHAR_SHIFT;
-		else if ((c & 0377) >= 'a' && (c & 0377) <= 'z')
-		  c = (c & ~CHAR_SHIFT) - ('a' - 'A');
+		if (EQ (readcharfun, Qget_file_char))
+		  {
+		    if (BASE_LEADING_CODE_P (c))
+		      {
+			int nbytes;
+			c = read_multibyte (c, readcharfun, &nbytes);
+			if (nbytes > 1)
+			  force_multibyte = 1;
+			else
+			  {
+			    force_singlebyte = 1;
+			    c = BYTE8_TO_CHAR (c);
+			  }
+		      }
+		    else
+		      {
+			force_singlebyte = 1;
+			c = BYTE8_TO_CHAR (c);
+		      }
+		  }
+		else
+		  force_multibyte = 1;
+		p += CHAR_STRING (c, (unsigned char *) p);
 	      }
-
-	    if (c & CHAR_META)
-	      /* Move the meta bit to the right place for a string.  */
-	      c = (c & ~CHAR_META) | 0x80;
-	    if (c & CHAR_MODIFIER_MASK)
-	      error ("Invalid modifier in string");
-
-	    if (is_multibyte)
-	      p += CHAR_STRING (c, p);
 	    else
 	      *p++ = c;
-
 	    nchars++;
 	  }
-
 	if (c < 0)
 	  end_of_file_error ();
 
@@ -2238,42 +2276,24 @@
 	if (!NILP (Vpurify_flag) && NILP (Vdoc_file_name) && cancel)
 	  return make_number (0);
 
-	if (is_multibyte || force_singlebyte)
+	if (force_multibyte)
+	  /* READ_BUFFER already contains valid multibyte forms.  */
 	  ;
-	else if (load_convert_to_unibyte)
+	else if (force_singlebyte)
 	  {
-	    Lisp_Object string;
-	    to_multibyte (&p, &end, &nchars);
-	    if (p - read_buffer != nchars)
-	      {
-		string = make_multibyte_string (read_buffer, nchars,
-						p - read_buffer);
-		return Fstring_make_unibyte (string);
-	      }
-	    /* We can make a unibyte string directly.  */
-	    is_multibyte = 0;
-	  }
-	else if (EQ (readcharfun, Qget_file_char)
-		 || EQ (readcharfun, Qlambda))
-	  {
-	    /* Nowadays, reading directly from a file is used only for
-	       compiled Emacs Lisp files, and those always use the
-	       Emacs internal encoding.  Meanwhile, Qlambda is used
-	       for reading dynamic byte code (compiled with
-	       byte-compile-dynamic = t).  */
-	    to_multibyte (&p, &end, &nchars);
-	    is_multibyte = 1;
+	    nchars = str_as_unibyte (read_buffer, p - read_buffer);
+	    p = read_buffer + nchars;
 	  }
 	else
-	  /* In all other cases, if we read these bytes as
-	     separate characters, treat them as separate characters now.  */
-	  ;
+	  /* Otherwise, READ_BUFFER contains only ASCII.  */
 
 	if (read_pure)
 	  return make_pure_string (read_buffer, nchars, p - read_buffer,
-				   is_multibyte);
+				   (force_multibyte
+				    || (p - read_buffer != nchars)));
 	return make_specified_string (read_buffer, nchars, p - read_buffer,
-				      is_multibyte);
+				      (force_multibyte
+				       || (p - read_buffer != nchars)));
       }
 
     case '.':