comparison src/lread.c @ 20548:e9733cb049d9

(readchar_backlog): New variable. (readchar): When fetching from buffer or marker, use readchar_backlog to fetch bytes from a character. (unreadchar): Increment readchar_backlog. (readevalloop, Fread): Init readchar_backlog.
author Richard M. Stallman <rms@gnu.org>
date Thu, 01 Jan 1998 06:38:45 +0000
parents 0f0a48a69b88
children 0877f6e6fc15
comparison
equal deleted inserted replaced
20547:07053199a368 20548:e9733cb049d9
127 static int read_pure; 127 static int read_pure;
128 128
129 /* For use within read-from-string (this reader is non-reentrant!!) */ 129 /* For use within read-from-string (this reader is non-reentrant!!) */
130 static int read_from_string_index; 130 static int read_from_string_index;
131 static int read_from_string_limit; 131 static int read_from_string_limit;
132
133 /* Number of bytes left to read in the buffer character
134 that `readchar' has already advanced over. */
135 static int readchar_backlog;
132 136
133 /* This contains the last string skipped with #@, but only on some systems. 137 /* This contains the last string skipped with #@, but only on some systems.
134 On other systems we can't put the string here. */ 138 On other systems we can't put the string here. */
135 static char *saved_doc_string; 139 static char *saved_doc_string;
136 /* Length of buffer allocated in saved_doc_string. */ 140 /* Length of buffer allocated in saved_doc_string. */
167 171
168 if (BUFFERP (readcharfun)) 172 if (BUFFERP (readcharfun))
169 { 173 {
170 inbuffer = XBUFFER (readcharfun); 174 inbuffer = XBUFFER (readcharfun);
171 175
172 if (BUF_PT (inbuffer) >= BUF_ZV (inbuffer)) 176 if (readchar_backlog == 0)
173 return -1; 177 {
174 c = *(unsigned char *) BUF_CHAR_ADDRESS (inbuffer, BUF_PT (inbuffer)); 178 int pt_byte = BUF_PT_BYTE (inbuffer);
175 SET_BUF_PT (inbuffer, BUF_PT (inbuffer) + 1); 179 int orig_pt_byte = pt_byte;
176 180
177 return c; 181 if (pt_byte >= BUF_ZV_BYTE (inbuffer))
182 return -1;
183
184 if (! NILP (inbuffer->enable_multibyte_characters))
185 BUF_INC_POS (inbuffer, pt_byte);
186 else
187 pt_byte++;
188 SET_BUF_PT_BOTH (inbuffer, BUF_PT (inbuffer) + 1, pt_byte);
189 readchar_backlog = pt_byte - orig_pt_byte;
190 }
191
192 /* We get the address of the byte just passed,
193 which is the last byte of the character.
194 The other bytes in this character are consecutive with it,
195 because the gap can't be in the middle of a character. */
196 return *(BUF_BYTE_ADDRESS (inbuffer, BUF_PT_BYTE (inbuffer) - 1)
197 - --readchar_backlog);
178 } 198 }
179 if (MARKERP (readcharfun)) 199 if (MARKERP (readcharfun))
180 { 200 {
181 inbuffer = XMARKER (readcharfun)->buffer; 201 inbuffer = XMARKER (readcharfun)->buffer;
182 202
183 mpos = marker_position (readcharfun); 203 if (readchar_backlog == 0)
184 204 {
185 if (mpos > BUF_ZV (inbuffer) - 1) 205 int bytepos = marker_byte_position (readcharfun);
186 return -1; 206 int orig_bytepos = bytepos;
187 c = *(unsigned char *) BUF_CHAR_ADDRESS (inbuffer, mpos); 207
188 if (mpos != BUF_GPT (inbuffer)) 208 if (bytepos >= BUF_ZV_BYTE (inbuffer))
189 XMARKER (readcharfun)->bufpos++; 209 return -1;
190 else 210
191 Fset_marker (readcharfun, make_number (mpos + 1), 211 if (XMARKER (readcharfun)->bufpos == BUF_GPT_BYTE (inbuffer))
192 Fmarker_buffer (readcharfun)); 212 XMARKER (readcharfun)->bufpos += BUF_GAP_SIZE (inbuffer);
193 return c; 213
214 if (! NILP (inbuffer->enable_multibyte_characters))
215 INC_POS (bytepos);
216 else
217 bytepos++;
218 XMARKER (readcharfun)->bufpos += bytepos - orig_bytepos;
219 XMARKER (readcharfun)->charpos++;
220
221 readchar_backlog = bytepos - orig_bytepos;
222 }
223
224 /* Because we move ->bufpos across the gap before we advance it,
225 the gap never comes between the previous character and ->bufpos. */
226 return *(BUF_BEG_ADDR (inbuffer) + XMARKER (readcharfun)->bufpos
227 - readchar_backlog--);
194 } 228 }
195 if (EQ (readcharfun, Qget_file_char)) 229 if (EQ (readcharfun, Qget_file_char))
196 { 230 {
197 c = getc (instream); 231 c = getc (instream);
198 #ifdef EINTR 232 #ifdef EINTR
213 but that truncated -1 to a char on VMS. */ 247 but that truncated -1 to a char on VMS. */
214 if (read_from_string_index < read_from_string_limit) 248 if (read_from_string_index < read_from_string_limit)
215 c = XSTRING (readcharfun)->data[read_from_string_index++]; 249 c = XSTRING (readcharfun)->data[read_from_string_index++];
216 else 250 else
217 c = -1; 251 c = -1;
252
218 return c; 253 return c;
219 } 254 }
220 255
221 tem = call0 (readcharfun); 256 tem = call0 (readcharfun);
222 257
236 if (c == -1) 271 if (c == -1)
237 /* Don't back up the pointer if we're unreading the end-of-input mark, 272 /* Don't back up the pointer if we're unreading the end-of-input mark,
238 since readchar didn't advance it when we read it. */ 273 since readchar didn't advance it when we read it. */
239 ; 274 ;
240 else if (BUFFERP (readcharfun)) 275 else if (BUFFERP (readcharfun))
241 { 276 readchar_backlog++;
242 if (XBUFFER (readcharfun) == current_buffer)
243 SET_PT (PT - 1);
244 else
245 SET_BUF_PT (XBUFFER (readcharfun), BUF_PT (XBUFFER (readcharfun)) - 1);
246 }
247 else if (MARKERP (readcharfun)) 277 else if (MARKERP (readcharfun))
248 XMARKER (readcharfun)->bufpos--; 278 readchar_backlog++;
249 else if (STRINGP (readcharfun)) 279 else if (STRINGP (readcharfun))
250 read_from_string_index--; 280 read_from_string_index--;
251 else if (EQ (readcharfun, Qget_file_char)) 281 else if (EQ (readcharfun, Qget_file_char))
252 ungetc (c, instream); 282 ungetc (c, instream);
253 else 283 else
254 call1 (readcharfun, make_number (c)); 284 call1 (readcharfun, make_number (c));
255 } 285 }
256 286
257 static Lisp_Object read0 (), read1 (), read_list (), read_vector (); 287 static Lisp_Object read0 (), read1 (), read_list (), read_vector ();
288 static int read_multibyte ();
258 289
259 /* get a character from the tty */ 290 /* get a character from the tty */
260 291
261 extern Lisp_Object read_char (); 292 extern Lisp_Object read_char ();
262 293
882 b = XMARKER (readcharfun)->buffer; 913 b = XMARKER (readcharfun)->buffer;
883 914
884 specbind (Qstandard_input, readcharfun); 915 specbind (Qstandard_input, readcharfun);
885 specbind (Qcurrent_load_list, Qnil); 916 specbind (Qcurrent_load_list, Qnil);
886 917
918 readchar_backlog = 0;
919
887 GCPRO1 (sourcename); 920 GCPRO1 (sourcename);
888 921
889 LOADHIST_ATTACH (sourcename); 922 LOADHIST_ATTACH (sourcename);
890 923
891 while (1) 924 while (1)
1066 if (NILP (stream)) 1099 if (NILP (stream))
1067 stream = Vstandard_input; 1100 stream = Vstandard_input;
1068 if (EQ (stream, Qt)) 1101 if (EQ (stream, Qt))
1069 stream = Qread_char; 1102 stream = Qread_char;
1070 1103
1104 readchar_backlog = 0;
1071 new_backquote_flag = 0; 1105 new_backquote_flag = 0;
1072 read_objects = Qnil; 1106 read_objects = Qnil;
1073 1107
1074 #ifndef standalone 1108 #ifndef standalone
1075 if (EQ (stream, Qread_char)) 1109 if (EQ (stream, Qread_char))
1143 static char *read_buffer; 1177 static char *read_buffer;
1144 1178
1145 /* Read multibyte form and return it as a character. C is a first 1179 /* Read multibyte form and return it as a character. C is a first
1146 byte of multibyte form, and rest of them are read from 1180 byte of multibyte form, and rest of them are read from
1147 READCHARFUN. */ 1181 READCHARFUN. */
1182
1148 static int 1183 static int
1149 read_multibyte (c, readcharfun) 1184 read_multibyte (c, readcharfun)
1150 register int c; 1185 register int c;
1151 Lisp_Object readcharfun; 1186 Lisp_Object readcharfun;
1152 { 1187 {
1160 && len < MAX_LENGTH_OF_MULTI_BYTE_FORM) 1195 && len < MAX_LENGTH_OF_MULTI_BYTE_FORM)
1161 str[len++] = c; 1196 str[len++] = c;
1162 UNREAD (c); 1197 UNREAD (c);
1163 return STRING_CHAR (str, len); 1198 return STRING_CHAR (str, len);
1164 } 1199 }
1200
1201 /* Read a \-escape sequence, assuming we already read the `\'. */
1165 1202
1166 static int 1203 static int
1167 read_escape (readcharfun) 1204 read_escape (readcharfun)
1168 Lisp_Object readcharfun; 1205 Lisp_Object readcharfun;
1169 { 1206 {
1622 1659
1623 if (c == '\\') 1660 if (c == '\\')
1624 c = read_escape (readcharfun); 1661 c = read_escape (readcharfun);
1625 else if (BASE_LEADING_CODE_P (c)) 1662 else if (BASE_LEADING_CODE_P (c))
1626 c = read_multibyte (c, readcharfun); 1663 c = read_multibyte (c, readcharfun);
1627 XSETINT (val, c); 1664
1628 1665 return make_number (c);
1629 return val;
1630 } 1666 }
1631 1667
1632 case '\"': 1668 case '\"':
1633 { 1669 {
1634 register char *p = read_buffer; 1670 register char *p = read_buffer;
1668 bcopy (str, p, length); 1704 bcopy (str, p, length);
1669 p += length; 1705 p += length;
1670 continue; 1706 continue;
1671 } 1707 }
1672 } 1708 }
1709
1673 /* c is -1 if \ newline has just been seen */ 1710 /* c is -1 if \ newline has just been seen */
1674 if (c == -1) 1711 if (c == -1)
1675 { 1712 {
1676 if (p == read_buffer) 1713 if (p == read_buffer)
1677 cancel = 1; 1714 cancel = 1;
1690 if (c & ~0xff) 1727 if (c & ~0xff)
1691 error ("Invalid modifier in string"); 1728 error ("Invalid modifier in string");
1692 *p++ = c; 1729 *p++ = c;
1693 } 1730 }
1694 } 1731 }
1695 if (c < 0) return Fsignal (Qend_of_file, Qnil); 1732 if (c < 0)
1733 return Fsignal (Qend_of_file, Qnil);
1696 1734
1697 /* If purifying, and string starts with \ newline, 1735 /* If purifying, and string starts with \ newline,
1698 return zero instead. This is for doc strings 1736 return zero instead. This is for doc strings
1699 that we are really going to find in etc/DOC.nn.nn */ 1737 that we are really going to find in etc/DOC.nn.nn */
1700 if (!NILP (Vpurify_flag) && NILP (Vdoc_file_name) && cancel) 1738 if (!NILP (Vpurify_flag) && NILP (Vdoc_file_name) && cancel)
1734 int quoted = 0; 1772 int quoted = 0;
1735 1773
1736 { 1774 {
1737 register char *end = read_buffer + read_buffer_size; 1775 register char *end = read_buffer + read_buffer_size;
1738 1776
1739 while (c > 040 && 1777 while (c > 040
1740 !(c == '\"' || c == '\'' || c == ';' || c == '?' 1778 && !(c == '\"' || c == '\'' || c == ';' || c == '?'
1741 || c == '(' || c == ')' 1779 || c == '(' || c == ')'
1742 #ifndef LISP_FLOAT_TYPE 1780 #ifndef LISP_FLOAT_TYPE
1743 /* If we have floating-point support, then we need 1781 /* If we have floating-point support, then we need
1744 to allow <digits><dot><digits>. */ 1782 to allow <digits><dot><digits>. */
1745 || c =='.' 1783 || c =='.'
1746 #endif /* not LISP_FLOAT_TYPE */ 1784 #endif /* not LISP_FLOAT_TYPE */
1747 || c == '[' || c == ']' || c == '#' 1785 || c == '[' || c == ']' || c == '#'
1748 )) 1786 ))
1749 { 1787 {
1750 if (p == end) 1788 if (p == end)
1751 { 1789 {
1752 register char *new = (char *) xrealloc (read_buffer, read_buffer_size *= 2); 1790 register char *new = (char *) xrealloc (read_buffer, read_buffer_size *= 2);
1753 p += new - read_buffer; 1791 p += new - read_buffer;
1757 if (c == '\\') 1795 if (c == '\\')
1758 { 1796 {
1759 c = READCHAR; 1797 c = READCHAR;
1760 quoted = 1; 1798 quoted = 1;
1761 } 1799 }
1800
1762 *p++ = c; 1801 *p++ = c;
1802
1763 c = READCHAR; 1803 c = READCHAR;
1764 } 1804 }
1765 1805
1766 if (p == end) 1806 if (p == end)
1767 { 1807 {
1903 free_cons (otem); 1943 free_cons (otem);
1904 } 1944 }
1905 return vector; 1945 return vector;
1906 } 1946 }
1907 1947
1908 /* flag = 1 means check for ] to terminate rather than ) and . 1948 /* FLAG = 1 means check for ] to terminate rather than ) and .
1909 flag = -1 means check for starting with defun 1949 FLAG = -1 means check for starting with defun
1910 and make structure pure. */ 1950 and make structure pure. */
1911 1951
1912 static Lisp_Object 1952 static Lisp_Object
1913 read_list (flag, readcharfun) 1953 read_list (flag, readcharfun)
1914 int flag; 1954 int flag;