aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias EngdegÄrd2024-05-26 13:44:32 +0200
committerMattias EngdegÄrd2025-07-10 10:24:58 +0200
commitcd3727f7e0607a152a97b534ee09a2cb8ac6cb84 (patch)
tree721a0f3e066b4fcafc7e7f15a21f5cee4128f59e
parent99080d0c04931b5d45026e1ee44526bbbb8dfdef (diff)
downloademacs-cd3727f7e0607a152a97b534ee09a2cb8ac6cb84.tar.gz
emacs-cd3727f7e0607a152a97b534ee09a2cb8ac6cb84.zip
Speed up low-level parts of the reader and refactor
Inspect the given 'readcharfun' source once, before using it, instead of for each character read. This moves a bunch of branches away from the critical path, with separate functions for different source types. Replace some preprocessor macros with functions. * src/lread.c (READCHAR, UNREAD, READCHAR_REPORT_MULTIBYTE) (FROM_FILE_P): Remove; use corresponding functions instead. All callers adapted. (source_t): New struct that takes the place of the `readcharfun` and `readbyte` arguments in many places. (init_source) (source_buffer_get, source_buffer_unget) (source_marker_get, source_marker_unget) (source_string_get, source_string_unget) (source_file_get, source_file_unget) (source_function_get, source_function_unget) (from_file_p, unreadbyte_from_file): New. (readbyte_from_stdio): Replace `readbyte_from_file`. (readchar, unreadchar): Rewrite. (lisp_file_lexical_cookie, readevalloop, read_internal_start): Create a source_t for use during reading. All signatures and functions called adapted. (read_char_escape): Remove check for an error that can no longer occur.
-rw-r--r--src/lread.c807
1 files changed, 415 insertions, 392 deletions
diff --git a/src/lread.c b/src/lread.c
index 9c8adf889c0..45ce3625a64 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -237,9 +237,6 @@ static struct saved_string saved_strings[2];
237 237
238static Lisp_Object Vloads_in_progress; 238static Lisp_Object Vloads_in_progress;
239 239
240static int read_emacs_mule_char (int, int (*) (int, Lisp_Object),
241 Lisp_Object);
242
243static void readevalloop (Lisp_Object, struct infile *, Lisp_Object, bool, 240static void readevalloop (Lisp_Object, struct infile *, Lisp_Object, bool,
244 Lisp_Object, Lisp_Object, 241 Lisp_Object, Lisp_Object,
245 Lisp_Object, Lisp_Object); 242 Lisp_Object, Lisp_Object);
@@ -252,201 +249,282 @@ static Lisp_Object oblookup_considering_shorthand (Lisp_Object, const char *,
252 ptrdiff_t *); 249 ptrdiff_t *);
253 250
254 251
255/* Function that reads one byte from the current source READCHARFUN
256 or unreads one byte. If the integer argument C is -1, it returns
257 one read byte, or -1 when there's no more byte in the source. If C
258 is 0 or positive, it unreads C, and the return value is not
259 interesting. */
260
261static int readbyte_from_file (int, Lisp_Object);
262
263/* Handle unreading and rereading of characters.
264 Write READCHAR to read a character,
265 UNREAD(c) to unread c to be read again.
266
267 These macros correctly read/unread multibyte characters. */
268
269#define READCHAR readchar (readcharfun, NULL)
270#define UNREAD(c) unreadchar (readcharfun, c)
271
272/* Same as READCHAR but set *MULTIBYTE to the multibyteness of the source. */
273#define READCHAR_REPORT_MULTIBYTE(multibyte) readchar (readcharfun, multibyte)
274
275/* When READCHARFUN is Qget_file_char or Qget_emacs_mule_file_char, 252/* When READCHARFUN is Qget_file_char or Qget_emacs_mule_file_char,
276 we use this to keep an unread character because 253 we use this to keep an unread character because
277 a file stream can't handle multibyte-char unreading. The value -1 254 a file stream can't handle multibyte-char unreading. The value -1
278 means that there's no unread character. */ 255 means that there's no unread character. */
279static int unread_char = -1; 256static int unread_char = -1;
280 257
281static int 258/* Representation of a source stream.
282readchar (Lisp_Object readcharfun, bool *multibyte) 259 FIXME: This is not nearly enough; there is a lot of static state that
283{ 260 is not included. */
284 Lisp_Object tem; 261typedef struct source {
285 register int c; 262 /* Read a character, -1 if at end of stream. */
286 int (*readbyte) (int, Lisp_Object); 263 int (*get) (struct source *src);
287 unsigned char buf[MAX_MULTIBYTE_LENGTH]; 264 /* Unread character C. Only a single char can be unread at a given time. */
288 int i, len; 265 void (*unget) (struct source *src, int c);
289 bool emacs_mule_encoding = 0;
290 266
291 if (multibyte) 267 /* Object read from: buffer, marker, string, or function. */
292 *multibyte = 0; 268 Lisp_Object object;
293
294 readchar_offset++;
295
296 if (BUFFERP (readcharfun))
297 {
298 register struct buffer *inbuffer = XBUFFER (readcharfun);
299 269
300 ptrdiff_t pt_byte = BUF_PT_BYTE (inbuffer); 270 bool multibyte; /* whether `get' returns multibyte chars */
301 271
302 if (! BUFFER_LIVE_P (inbuffer)) 272 /* For file sources, whether the encoding is the old emacs-mule. */
303 return -1; 273 bool emacs_mule_encoding;
274} source_t;
304 275
305 if (pt_byte >= BUF_ZV_BYTE (inbuffer)) 276static int source_buffer_get (source_t *src);
306 return -1; 277static void source_buffer_unget (source_t *src, int c);
278static int source_marker_get (source_t *src);
279static void source_marker_unget (source_t *src, int c);
280static int source_string_get (source_t *src);
281static void source_string_unget (source_t *src, int c);
282static int source_function_get (source_t *src);
283static void source_function_unget (source_t *src, int c);
284static int source_file_get (source_t *src);
285static void source_file_unget (source_t *src, int c);
307 286
308 if (! NILP (BVAR (inbuffer, enable_multibyte_characters))) 287static void
309 { 288init_source (source_t *src, Lisp_Object readcharfun)
310 /* Fetch the character code from the buffer. */ 289{
311 unsigned char *p = BUF_BYTE_ADDRESS (inbuffer, pt_byte); 290 src->object = readcharfun;
312 int clen; 291 if (BUFFERP (readcharfun))
313 c = string_char_and_length (p, &clen); 292 {
314 pt_byte += clen; 293 src->get = source_buffer_get;
315 if (multibyte) 294 src->unget = source_buffer_unget;
316 *multibyte = 1; 295 struct buffer *buf = XBUFFER (readcharfun);
317 } 296 src->multibyte = (BUFFER_LIVE_P (buf)
318 else 297 && !NILP (BVAR (buf, enable_multibyte_characters)));
319 {
320 c = BUF_FETCH_BYTE (inbuffer, pt_byte);
321 if (! ASCII_CHAR_P (c))
322 c = BYTE8_TO_CHAR (c);
323 pt_byte++;
324 }
325 SET_BUF_PT_BOTH (inbuffer, BUF_PT (inbuffer) + 1, pt_byte);
326
327 return c;
328 } 298 }
329 if (MARKERP (readcharfun)) 299 else if (MARKERP (readcharfun))
330 { 300 {
331 register struct buffer *inbuffer = XMARKER (readcharfun)->buffer; 301 src->get = source_marker_get;
302 src->unget = source_marker_unget;
303 struct buffer *buf = XMARKER (readcharfun)->buffer;
304 src->multibyte = (BUFFER_LIVE_P (buf)
305 && !NILP (BVAR (buf, enable_multibyte_characters)));
306 }
307 else if (STRINGP (readcharfun))
308 {
309 src->get = source_string_get;
310 src->unget = source_string_unget;
311 src->multibyte = STRING_MULTIBYTE (readcharfun);
312 }
313 else if (EQ (readcharfun, Qget_file_char)
314 || EQ (readcharfun, Qget_emacs_mule_file_char))
315 {
316 src->get = source_file_get;
317 src->unget = source_file_unget;
318 src->multibyte = true;
319 src->emacs_mule_encoding = EQ (readcharfun, Qget_emacs_mule_file_char);
320 eassert (infile != NULL);
321 }
322 else
323 {
324 /* Assume callable (will signal error later if not). */
325 src->get = source_function_get;
326 src->unget = source_function_unget;
327 src->multibyte = true;
328 }
329}
332 330
333 ptrdiff_t bytepos = marker_byte_position (readcharfun); 331static int
332source_buffer_get (source_t *src)
333{
334 struct buffer *b = XBUFFER (src->object);
335 if (!BUFFER_LIVE_P (b))
336 return -1;
334 337
335 if (bytepos >= BUF_ZV_BYTE (inbuffer)) 338 ptrdiff_t pt_byte = BUF_PT_BYTE (b);
336 return -1; 339 if (pt_byte >= BUF_ZV_BYTE (b))
340 return -1;
337 341
338 if (! NILP (BVAR (inbuffer, enable_multibyte_characters))) 342 int c;
339 { 343 if (src->multibyte)
340 /* Fetch the character code from the buffer. */ 344 {
341 unsigned char *p = BUF_BYTE_ADDRESS (inbuffer, bytepos); 345 unsigned char *p = BUF_BYTE_ADDRESS (b, pt_byte);
342 int clen; 346 int clen;
343 c = string_char_and_length (p, &clen); 347 c = string_char_and_length (p, &clen);
344 bytepos += clen; 348 pt_byte += clen;
345 if (multibyte) 349 }
346 *multibyte = 1; 350 else
347 } 351 {
348 else 352 c = BUF_FETCH_BYTE (b, pt_byte);
349 { 353 if (!ASCII_CHAR_P (c))
350 c = BUF_FETCH_BYTE (inbuffer, bytepos); 354 c = BYTE8_TO_CHAR (c);
351 if (! ASCII_CHAR_P (c)) 355 pt_byte++;
352 c = BYTE8_TO_CHAR (c); 356 }
353 bytepos++; 357 SET_BUF_PT_BOTH (b, BUF_PT (b) + 1, pt_byte);
354 } 358 return c;
359}
355 360
356 XMARKER (readcharfun)->bytepos = bytepos; 361static void
357 XMARKER (readcharfun)->charpos++; 362source_buffer_unget (source_t *src, int c)
363{
364 struct buffer *b = XBUFFER (src->object);
365 ptrdiff_t charpos = BUF_PT (b);
366 ptrdiff_t bytepos = BUF_PT_BYTE (b);
367 bytepos -= src->multibyte ? buf_prev_char_len (b, bytepos) : 1;
368 SET_BUF_PT_BOTH (b, charpos - 1, bytepos);
369}
358 370
359 return c; 371static int
360 } 372source_marker_get (source_t *src)
373{
374 Lisp_Object m = src->object;
375 struct buffer *b = XMARKER (m)->buffer;
376 ptrdiff_t bytepos = marker_byte_position (m);
377 if (bytepos >= BUF_ZV_BYTE (b))
378 return -1;
361 379
362 if (EQ (readcharfun, Qget_file_char)) 380 int c;
381 if (src->multibyte)
363 { 382 {
364 eassert (infile); 383 unsigned char *p = BUF_BYTE_ADDRESS (b, bytepos);
365 readbyte = readbyte_from_file; 384 int clen;
366 goto read_multibyte; 385 c = string_char_and_length (p, &clen);
386 bytepos += clen;
367 } 387 }
368 388 else
369 if (STRINGP (readcharfun))
370 { 389 {
371 if (read_from_string_index >= read_from_string_limit) 390 c = BUF_FETCH_BYTE (b, bytepos);
372 c = -1; 391 if (!ASCII_CHAR_P (c))
373 else if (STRING_MULTIBYTE (readcharfun)) 392 c = BYTE8_TO_CHAR (c);
374 { 393 bytepos++;
375 if (multibyte)
376 *multibyte = 1;
377 c = (fetch_string_char_advance_no_check
378 (readcharfun,
379 &read_from_string_index,
380 &read_from_string_index_byte));
381 }
382 else
383 {
384 c = SREF (readcharfun, read_from_string_index_byte);
385 if (!ASCII_CHAR_P (c))
386 c = BYTE8_TO_CHAR (c);
387 read_from_string_index++;
388 read_from_string_index_byte++;
389 }
390 return c;
391 } 394 }
395 XMARKER (m)->bytepos = bytepos;
396 XMARKER (m)->charpos++;
397 return c;
398}
392 399
393 if (EQ (readcharfun, Qget_emacs_mule_file_char)) 400static void
401source_marker_unget (source_t *src, int c)
402{
403 Lisp_Object m = src->object;
404 struct buffer *b = XMARKER (m)->buffer;
405 ptrdiff_t bytepos = XMARKER (m)->bytepos;
406 XMARKER (m)->charpos--;
407 bytepos -= src->multibyte ? buf_prev_char_len (b, bytepos) : 1;
408 XMARKER (m)->bytepos = bytepos;
409}
410
411static int
412source_string_get (source_t *src)
413{
414 if (read_from_string_index >= read_from_string_limit)
415 return -1;
416 Lisp_Object s = src->object;
417 int c;
418 if (src->multibyte)
419 c = fetch_string_char_advance_no_check
420 (s, &read_from_string_index, &read_from_string_index_byte);
421 else
394 { 422 {
395 readbyte = readbyte_from_file; 423 c = SREF (s, read_from_string_index_byte);
396 eassert (infile); 424 if (!ASCII_CHAR_P (c))
397 emacs_mule_encoding = 1; 425 c = BYTE8_TO_CHAR (c);
398 goto read_multibyte; 426 read_from_string_index++;
427 read_from_string_index_byte++;
399 } 428 }
429 return c;
430}
400 431
401 if (multibyte) 432static void
402 *multibyte = 1; 433source_string_unget (source_t *src, int c)
434{
435 read_from_string_index--;
436 read_from_string_index_byte = string_char_to_byte (src->object,
437 read_from_string_index);
438}
403 439
404 tem = call0 (readcharfun); 440static int readbyte_from_file (void);
441static void unreadbyte_from_file (unsigned char);
405 442
406 if (!FIXNUMP (tem)) 443static int read_emacs_mule_char (source_t *src, int c);
407 return -1;
408 return XFIXNUM (tem);
409 444
410 read_multibyte: 445static int
446source_file_get (source_t *src)
447{
411 if (unread_char >= 0) 448 if (unread_char >= 0)
412 { 449 {
413 c = unread_char; 450 int c = unread_char;
414 unread_char = -1; 451 unread_char = -1;
415 return c; 452 return c;
416 } 453 }
417 c = (*readbyte) (-1, readcharfun); 454
455 int c = readbyte_from_file ();
418 if (c < 0) 456 if (c < 0)
419 return c; 457 return c;
420 if (multibyte)
421 *multibyte = 1;
422 if (ASCII_CHAR_P (c)) 458 if (ASCII_CHAR_P (c))
423 return c; 459 return c;
424 if (emacs_mule_encoding) 460 if (src->emacs_mule_encoding)
425 return read_emacs_mule_char (c, readbyte, readcharfun); 461 return read_emacs_mule_char (src, c);
426 i = 0; 462 int i = 0;
463 unsigned char buf[MAX_MULTIBYTE_LENGTH];
427 buf[i++] = c; 464 buf[i++] = c;
428 len = BYTES_BY_CHAR_HEAD (c); 465 int len = BYTES_BY_CHAR_HEAD (c);
429 while (i < len) 466 while (i < len)
430 { 467 {
431 buf[i++] = c = (*readbyte) (-1, readcharfun); 468 buf[i++] = c = readbyte_from_file ();
432 if (c < 0 || ! TRAILING_CODE_P (c)) 469 if (c < 0 || ! TRAILING_CODE_P (c))
433 { 470 {
434 for (i -= c < 0; 0 < --i; ) 471 for (i -= c < 0; 0 < --i; )
435 (*readbyte) (buf[i], readcharfun); 472 unreadbyte_from_file (buf[i]);
436 return BYTE8_TO_CHAR (buf[0]); 473 return BYTE8_TO_CHAR (buf[0]);
437 } 474 }
438 } 475 }
439 return STRING_CHAR (buf); 476 return STRING_CHAR (buf);
440} 477}
441 478
442#define FROM_FILE_P(readcharfun) \ 479static void
443 (EQ (readcharfun, Qget_file_char) \ 480source_file_unget (source_t *src, int c)
444 || EQ (readcharfun, Qget_emacs_mule_file_char)) 481{
482 unread_char = c;
483}
484
485static int
486source_function_get (source_t *src)
487{
488 Lisp_Object x = call0 (src->object);
489 return CHARACTERP (x) ? XFIXNUM (x) : -1;
490}
445 491
446static void 492static void
447skip_dyn_bytes (Lisp_Object readcharfun, ptrdiff_t n) 493source_function_unget (source_t *src, int c)
494{
495 calln (src->object, make_fixnum (c));
496}
497
498/* Read a character from SRC. */
499static inline int
500readchar (source_t *src)
501{
502 readchar_offset++;
503 return src->get (src);
504}
505
506/* Unread C from (to?) SRC. Only a single char can be unread at a time. */
507static inline void
508unreadchar (source_t *src, int c)
509{
510 readchar_offset--;
511 /* Don't back up the pointer if we're unreading the end-of-input mark,
512 since readchar didn't advance it when we read it. */
513 if (c == -1)
514 return;
515 src->unget (src, c);
516}
517
518static bool
519from_file_p (source_t *source)
448{ 520{
449 if (FROM_FILE_P (readcharfun)) 521 return source->get == source_file_get;
522}
523
524static void
525skip_dyn_bytes (source_t *source, ptrdiff_t n)
526{
527 if (from_file_p (source))
450 { 528 {
451 block_input (); /* FIXME: Not sure if it's needed. */ 529 block_input (); /* FIXME: Not sure if it's needed. */
452 file_seek (infile->stream, n - infile->lookahead, SEEK_CUR); 530 file_seek (infile->stream, n - infile->lookahead, SEEK_CUR);
@@ -462,15 +540,15 @@ skip_dyn_bytes (Lisp_Object readcharfun, ptrdiff_t n)
462 that \037 is the final char. */ 540 that \037 is the final char. */
463 int c; 541 int c;
464 do { 542 do {
465 c = READCHAR; 543 c = readchar (source);
466 } while (c >= 0 && c != '\037'); 544 } while (c >= 0 && c != '\037');
467 } 545 }
468} 546}
469 547
470static void 548static void
471skip_dyn_eof (Lisp_Object readcharfun) 549skip_dyn_eof (source_t *source)
472{ 550{
473 if (FROM_FILE_P (readcharfun)) 551 if (from_file_p (source))
474 { 552 {
475 block_input (); /* FIXME: Not sure if it's needed. */ 553 block_input (); /* FIXME: Not sure if it's needed. */
476 file_seek (infile->stream, 0, SEEK_END); 554 file_seek (infile->stream, 0, SEEK_END);
@@ -478,62 +556,12 @@ skip_dyn_eof (Lisp_Object readcharfun)
478 infile->lookahead = 0; 556 infile->lookahead = 0;
479 } 557 }
480 else 558 else
481 while (READCHAR >= 0); 559 while (readchar (source) >= 0);
482}
483
484/* Unread the character C in the way appropriate for the stream READCHARFUN.
485 If the stream is a user function, call it with the char as argument. */
486
487static void
488unreadchar (Lisp_Object readcharfun, int c)
489{
490 readchar_offset--;
491 if (c == -1)
492 /* Don't back up the pointer if we're unreading the end-of-input mark,
493 since readchar didn't advance it when we read it. */
494 ;
495 else if (BUFFERP (readcharfun))
496 {
497 struct buffer *b = XBUFFER (readcharfun);
498 ptrdiff_t charpos = BUF_PT (b);
499 ptrdiff_t bytepos = BUF_PT_BYTE (b);
500
501 if (! NILP (BVAR (b, enable_multibyte_characters)))
502 bytepos -= buf_prev_char_len (b, bytepos);
503 else
504 bytepos--;
505
506 SET_BUF_PT_BOTH (b, charpos - 1, bytepos);
507 }
508 else if (MARKERP (readcharfun))
509 {
510 struct buffer *b = XMARKER (readcharfun)->buffer;
511 ptrdiff_t bytepos = XMARKER (readcharfun)->bytepos;
512
513 XMARKER (readcharfun)->charpos--;
514 if (! NILP (BVAR (b, enable_multibyte_characters)))
515 bytepos -= buf_prev_char_len (b, bytepos);
516 else
517 bytepos--;
518
519 XMARKER (readcharfun)->bytepos = bytepos;
520 }
521 else if (STRINGP (readcharfun))
522 {
523 read_from_string_index--;
524 read_from_string_index_byte
525 = string_char_to_byte (readcharfun, read_from_string_index);
526 }
527 else if (FROM_FILE_P (readcharfun))
528 {
529 unread_char = c;
530 }
531 else
532 calln (readcharfun, make_fixnum (c));
533} 560}
534 561
562/* Read a byte from the current input file. Return -1 at end of file. */
535static int 563static int
536readbyte_from_stdio (void) 564readbyte_from_file (void)
537{ 565{
538 if (infile->lookahead) 566 if (infile->lookahead)
539 return infile->buf[--infile->lookahead]; 567 return infile->buf[--infile->lookahead];
@@ -588,40 +616,29 @@ readbyte_from_stdio (void)
588 return (c == EOF ? -1 : c); 616 return (c == EOF ? -1 : c);
589} 617}
590 618
591static int 619static void
592readbyte_from_file (int c, Lisp_Object readcharfun) 620unreadbyte_from_file (unsigned char c)
593{ 621{
594 eassert (infile); 622 eassert (infile->lookahead < sizeof infile->buf);
595 if (c >= 0) 623 infile->buf[infile->lookahead++] = c;
596 {
597 eassert (infile->lookahead < sizeof infile->buf);
598 infile->buf[infile->lookahead++] = c;
599 return 0;
600 }
601
602 return readbyte_from_stdio ();
603} 624}
604 625
605/* Signal Qinvalid_read_syntax error. 626/* Signal Qinvalid_read_syntax error.
606 S is error string of length N (if > 0) */ 627 S is error string of length N (if > 0) */
607 628
608static AVOID 629static AVOID
609invalid_syntax_lisp (Lisp_Object s, Lisp_Object readcharfun) 630invalid_syntax_lisp (Lisp_Object s, source_t *source)
610{ 631{
611 if (BUFFERP (readcharfun)) 632 if (source->get == source_buffer_get)
612 { 633 {
613 ptrdiff_t line, column; 634 Lisp_Object buffer = source->object;
614 635 /* Get the line/column in the buffer. */
615 /* Get the line/column in the readcharfun buffer. */ 636 specpdl_ref count = SPECPDL_INDEX ();
616 { 637 record_unwind_protect_excursion ();
617 specpdl_ref count = SPECPDL_INDEX (); 638 set_buffer_internal (XBUFFER (buffer));
618 639 ptrdiff_t line = count_lines (BEGV_BYTE, PT_BYTE) + 1;
619 record_unwind_protect_excursion (); 640 ptrdiff_t column = current_column ();
620 set_buffer_internal (XBUFFER (readcharfun)); 641 unbind_to (count, Qnil);
621 line = count_lines (BEGV_BYTE, PT_BYTE) + 1;
622 column = current_column ();
623 unbind_to (count, Qnil);
624 }
625 642
626 xsignal (Qinvalid_read_syntax, 643 xsignal (Qinvalid_read_syntax,
627 list3 (s, make_fixnum (line), make_fixnum (column))); 644 list3 (s, make_fixnum (line), make_fixnum (column)));
@@ -631,9 +648,9 @@ invalid_syntax_lisp (Lisp_Object s, Lisp_Object readcharfun)
631} 648}
632 649
633static AVOID 650static AVOID
634invalid_syntax (const char *s, Lisp_Object readcharfun) 651invalid_syntax (const char *s, source_t *source)
635{ 652{
636 invalid_syntax_lisp (build_string (s), readcharfun); 653 invalid_syntax_lisp (build_string (s), source);
637} 654}
638 655
639 656
@@ -642,7 +659,7 @@ invalid_syntax (const char *s, Lisp_Object readcharfun)
642 C. */ 659 C. */
643 660
644static int 661static int
645read_emacs_mule_char (int c, int (*readbyte) (int, Lisp_Object), Lisp_Object readcharfun) 662read_emacs_mule_char (source_t *src, int c)
646{ 663{
647 /* Emacs-mule coding uses at most 4-byte for one character. */ 664 /* Emacs-mule coding uses at most 4-byte for one character. */
648 unsigned char buf[4]; 665 unsigned char buf[4];
@@ -659,11 +676,11 @@ read_emacs_mule_char (int c, int (*readbyte) (int, Lisp_Object), Lisp_Object rea
659 buf[i++] = c; 676 buf[i++] = c;
660 while (i < len) 677 while (i < len)
661 { 678 {
662 buf[i++] = c = (*readbyte) (-1, readcharfun); 679 buf[i++] = c = readbyte_from_file ();
663 if (c < 0xA0) 680 if (c < 0xA0)
664 { 681 {
665 for (i -= c < 0; 0 < --i; ) 682 for (i -= c < 0; 0 < --i; )
666 (*readbyte) (buf[i], readcharfun); 683 unreadbyte_from_file (buf[i]);
667 return BYTE8_TO_CHAR (buf[0]); 684 return BYTE8_TO_CHAR (buf[0]);
668 } 685 }
669 } 686 }
@@ -694,7 +711,7 @@ read_emacs_mule_char (int c, int (*readbyte) (int, Lisp_Object), Lisp_Object rea
694 } 711 }
695 c = DECODE_CHAR (charset, code); 712 c = DECODE_CHAR (charset, code);
696 if (c < 0) 713 if (c < 0)
697 invalid_syntax ("invalid multibyte form", readcharfun); 714 invalid_syntax ("invalid multibyte form", src);
698 return c; 715 return c;
699} 716}
700 717
@@ -715,7 +732,7 @@ struct subst
715 732
716static Lisp_Object read_internal_start (Lisp_Object, Lisp_Object, 733static Lisp_Object read_internal_start (Lisp_Object, Lisp_Object,
717 Lisp_Object, bool); 734 Lisp_Object, bool);
718static Lisp_Object read0 (Lisp_Object, bool); 735static Lisp_Object read0 (source_t *source, bool locate_syms);
719 736
720static Lisp_Object substitute_object_recurse (struct subst *, Lisp_Object); 737static Lisp_Object substitute_object_recurse (struct subst *, Lisp_Object);
721static void substitute_in_interval (INTERVAL, void *); 738static void substitute_in_interval (INTERVAL, void *);
@@ -1001,20 +1018,23 @@ typedef enum {
1001static lexical_cookie_t 1018static lexical_cookie_t
1002lisp_file_lexical_cookie (Lisp_Object readcharfun) 1019lisp_file_lexical_cookie (Lisp_Object readcharfun)
1003{ 1020{
1004 int ch = READCHAR; 1021 source_t source;
1022 init_source (&source, readcharfun);
1023
1024 int ch = readchar (&source);
1005 1025
1006 if (ch == '#') 1026 if (ch == '#')
1007 { 1027 {
1008 ch = READCHAR; 1028 ch = readchar (&source);
1009 if (ch != '!') 1029 if (ch != '!')
1010 { 1030 {
1011 UNREAD (ch); 1031 unreadchar (&source, ch);
1012 UNREAD ('#'); 1032 unreadchar (&source, '#');
1013 return Cookie_None; 1033 return Cookie_None;
1014 } 1034 }
1015 while (ch != '\n' && ch != EOF) 1035 while (ch != '\n' && ch != EOF)
1016 ch = READCHAR; 1036 ch = readchar (&source);
1017 if (ch == '\n') ch = READCHAR; 1037 if (ch == '\n') ch = readchar (&source);
1018 /* It is OK to leave the position after a #! line, since 1038 /* It is OK to leave the position after a #! line, since
1019 that is what read0 does. */ 1039 that is what read0 does. */
1020 } 1040 }
@@ -1022,7 +1042,7 @@ lisp_file_lexical_cookie (Lisp_Object readcharfun)
1022 if (ch != ';') 1042 if (ch != ';')
1023 /* The first line isn't a comment, just give up. */ 1043 /* The first line isn't a comment, just give up. */
1024 { 1044 {
1025 UNREAD (ch); 1045 unreadchar (&source, ch);
1026 return Cookie_None; 1046 return Cookie_None;
1027 } 1047 }
1028 else 1048 else
@@ -1049,7 +1069,7 @@ lisp_file_lexical_cookie (Lisp_Object readcharfun)
1049 /* Skip until we get to the file vars, if any. */ 1069 /* Skip until we get to the file vars, if any. */
1050 do 1070 do
1051 { 1071 {
1052 ch = READCHAR; 1072 ch = readchar (&source);
1053 UPDATE_BEG_END_STATE (ch); 1073 UPDATE_BEG_END_STATE (ch);
1054 } 1074 }
1055 while (!in_file_vars && ch != '\n' && ch != EOF); 1075 while (!in_file_vars && ch != '\n' && ch != EOF);
@@ -1059,11 +1079,11 @@ lisp_file_lexical_cookie (Lisp_Object readcharfun)
1059 char var[100], val[100]; 1079 char var[100], val[100];
1060 unsigned i; 1080 unsigned i;
1061 1081
1062 ch = READCHAR; 1082 ch = readchar (&source);
1063 1083
1064 /* Read a variable name. */ 1084 /* Read a variable name. */
1065 while (ch == ' ' || ch == '\t') 1085 while (ch == ' ' || ch == '\t')
1066 ch = READCHAR; 1086 ch = readchar (&source);
1067 1087
1068 i = 0; 1088 i = 0;
1069 beg_end_state = NOMINAL; 1089 beg_end_state = NOMINAL;
@@ -1072,7 +1092,7 @@ lisp_file_lexical_cookie (Lisp_Object readcharfun)
1072 if (i < sizeof var - 1) 1092 if (i < sizeof var - 1)
1073 var[i++] = ch; 1093 var[i++] = ch;
1074 UPDATE_BEG_END_STATE (ch); 1094 UPDATE_BEG_END_STATE (ch);
1075 ch = READCHAR; 1095 ch = readchar (&source);
1076 } 1096 }
1077 1097
1078 /* Stop scanning if no colon was found before end marker. */ 1098 /* Stop scanning if no colon was found before end marker. */
@@ -1086,10 +1106,10 @@ lisp_file_lexical_cookie (Lisp_Object readcharfun)
1086 if (ch == ':') 1106 if (ch == ':')
1087 { 1107 {
1088 /* Read a variable value. */ 1108 /* Read a variable value. */
1089 ch = READCHAR; 1109 ch = readchar (&source);
1090 1110
1091 while (ch == ' ' || ch == '\t') 1111 while (ch == ' ' || ch == '\t')
1092 ch = READCHAR; 1112 ch = readchar (&source);
1093 1113
1094 i = 0; 1114 i = 0;
1095 beg_end_state = NOMINAL; 1115 beg_end_state = NOMINAL;
@@ -1098,7 +1118,7 @@ lisp_file_lexical_cookie (Lisp_Object readcharfun)
1098 if (i < sizeof val - 1) 1118 if (i < sizeof val - 1)
1099 val[i++] = ch; 1119 val[i++] = ch;
1100 UPDATE_BEG_END_STATE (ch); 1120 UPDATE_BEG_END_STATE (ch);
1101 ch = READCHAR; 1121 ch = readchar (&source);
1102 } 1122 }
1103 if (! in_file_vars) 1123 if (! in_file_vars)
1104 /* The value was terminated by an end-marker, which remove. */ 1124 /* The value was terminated by an end-marker, which remove. */
@@ -1117,7 +1137,7 @@ lisp_file_lexical_cookie (Lisp_Object readcharfun)
1117 } 1137 }
1118 1138
1119 while (ch != '\n' && ch != EOF) 1139 while (ch != '\n' && ch != EOF)
1120 ch = READCHAR; 1140 ch = readchar (&source);
1121 1141
1122 return rv; 1142 return rv;
1123 } 1143 }
@@ -2468,6 +2488,9 @@ readevalloop (Lisp_Object readcharfun,
2468 2488
2469 loadhist_initialize (sourcename); 2489 loadhist_initialize (sourcename);
2470 2490
2491 source_t source;
2492 init_source (&source, readcharfun);
2493
2471 continue_reading_p = 1; 2494 continue_reading_p = 1;
2472 while (continue_reading_p) 2495 while (continue_reading_p)
2473 { 2496 {
@@ -2507,10 +2530,10 @@ readevalloop (Lisp_Object readcharfun,
2507 2530
2508 eassert (!infile0 || infile == infile0); 2531 eassert (!infile0 || infile == infile0);
2509 read_next: 2532 read_next:
2510 c = READCHAR; 2533 c = readchar (&source);
2511 if (c == ';') 2534 if (c == ';')
2512 { 2535 {
2513 while ((c = READCHAR) != '\n' && c != -1); 2536 while ((c = readchar (&source)) != '\n' && c != -1);
2514 goto read_next; 2537 goto read_next;
2515 } 2538 }
2516 if (c < 0) 2539 if (c < 0)
@@ -2523,7 +2546,7 @@ readevalloop (Lisp_Object readcharfun,
2523 if (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r' 2546 if (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r'
2524 || c == NO_BREAK_SPACE) 2547 || c == NO_BREAK_SPACE)
2525 goto read_next; 2548 goto read_next;
2526 UNREAD (c); 2549 unreadchar (&source, c);
2527 2550
2528 if (! HASH_TABLE_P (read_objects_map) 2551 if (! HASH_TABLE_P (read_objects_map)
2529 || XHASH_TABLE (read_objects_map)->count) 2552 || XHASH_TABLE (read_objects_map)->count)
@@ -2534,7 +2557,7 @@ readevalloop (Lisp_Object readcharfun,
2534 read_objects_completed 2557 read_objects_completed
2535 = make_hash_table (&hashtest_eq, DEFAULT_HASH_SIZE, Weak_None); 2558 = make_hash_table (&hashtest_eq, DEFAULT_HASH_SIZE, Weak_None);
2536 if (!NILP (Vpurify_flag) && c == '(') 2559 if (!NILP (Vpurify_flag) && c == '(')
2537 val = read0 (readcharfun, false); 2560 val = read0 (&source, false);
2538 else 2561 else
2539 { 2562 {
2540 if (!NILP (readfun)) 2563 if (!NILP (readfun))
@@ -2798,7 +2821,9 @@ read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end,
2798 read_from_string_limit = endval; 2821 read_from_string_limit = endval;
2799 } 2822 }
2800 2823
2801 retval = read0 (stream, locate_syms); 2824 source_t source;
2825 init_source (&source, stream);
2826 retval = read0 (&source, locate_syms);
2802 if (HASH_TABLE_P (read_objects_map) 2827 if (HASH_TABLE_P (read_objects_map)
2803 && XHASH_TABLE (read_objects_map)->count > 0) 2828 && XHASH_TABLE (read_objects_map)->count > 0)
2804 read_objects_map = Qnil; 2829 read_objects_map = Qnil;
@@ -2836,7 +2861,7 @@ grow_read_buffer (char *buf, ptrdiff_t offset,
2836 Raise 'invalid-read-syntax' if there is no such character. */ 2861 Raise 'invalid-read-syntax' if there is no such character. */
2837static int 2862static int
2838character_name_to_code (char const *name, ptrdiff_t name_len, 2863character_name_to_code (char const *name, ptrdiff_t name_len,
2839 Lisp_Object readcharfun) 2864 source_t *source)
2840{ 2865{
2841 /* For "U+XXXX", pass the leading '+' to string_to_number to reject 2866 /* For "U+XXXX", pass the leading '+' to string_to_number to reject
2842 monstrosities like "U+-0000". */ 2867 monstrosities like "U+-0000". */
@@ -2852,7 +2877,7 @@ character_name_to_code (char const *name, ptrdiff_t name_len,
2852 { 2877 {
2853 AUTO_STRING (format, "\\N{%s}"); 2878 AUTO_STRING (format, "\\N{%s}");
2854 AUTO_STRING_WITH_LEN (namestr, name, name_len); 2879 AUTO_STRING_WITH_LEN (namestr, name, name_len);
2855 invalid_syntax_lisp (CALLN (Fformat, format, namestr), readcharfun); 2880 invalid_syntax_lisp (CALLN (Fformat, format, namestr), source);
2856 } 2881 }
2857 2882
2858 return FIXNUMP (code) ? XFIXNUM (code) : -1; 2883 return FIXNUMP (code) ? XFIXNUM (code) : -1;
@@ -2865,7 +2890,7 @@ enum { UNICODE_CHARACTER_NAME_LENGTH_BOUND = 200 };
2865/* Read a character escape sequence, assuming we just read a backslash 2890/* Read a character escape sequence, assuming we just read a backslash
2866 and one more character (next_char). */ 2891 and one more character (next_char). */
2867static int 2892static int
2868read_char_escape (Lisp_Object readcharfun, int next_char) 2893read_char_escape (source_t *source, int next_char)
2869{ 2894{
2870 int modifiers = 0; 2895 int modifiers = 0;
2871 ptrdiff_t ncontrol = 0; 2896 ptrdiff_t ncontrol = 0;
@@ -2905,13 +2930,13 @@ read_char_escape (Lisp_Object readcharfun, int next_char)
2905 2930
2906 mod_key: 2931 mod_key:
2907 { 2932 {
2908 int c1 = READCHAR; 2933 int c1 = readchar (source);
2909 if (c1 != '-') 2934 if (c1 != '-')
2910 { 2935 {
2911 if (c == 's') 2936 if (c == 's')
2912 { 2937 {
2913 /* \s not followed by a hyphen is SPC. */ 2938 /* \s not followed by a hyphen is SPC. */
2914 UNREAD (c1); 2939 unreadchar (source, c1);
2915 chr = ' '; 2940 chr = ' ';
2916 break; 2941 break;
2917 } 2942 }
@@ -2920,10 +2945,10 @@ read_char_escape (Lisp_Object readcharfun, int next_char)
2920 error ("Invalid escape char syntax: \\%c not followed by -", c); 2945 error ("Invalid escape char syntax: \\%c not followed by -", c);
2921 } 2946 }
2922 modifiers |= mod; 2947 modifiers |= mod;
2923 c1 = READCHAR; 2948 c1 = readchar (source);
2924 if (c1 == '\\') 2949 if (c1 == '\\')
2925 { 2950 {
2926 next_char = READCHAR; 2951 next_char = readchar (source);
2927 goto again; 2952 goto again;
2928 } 2953 }
2929 chr = c1; 2954 chr = c1;
@@ -2935,7 +2960,7 @@ read_char_escape (Lisp_Object readcharfun, int next_char)
2935 Keep a count of them and apply them separately. */ 2960 Keep a count of them and apply them separately. */
2936 case 'C': 2961 case 'C':
2937 { 2962 {
2938 int c1 = READCHAR; 2963 int c1 = readchar (source);
2939 if (c1 != '-') 2964 if (c1 != '-')
2940 error ("Invalid escape char syntax: \\%c not followed by -", c); 2965 error ("Invalid escape char syntax: \\%c not followed by -", c);
2941 } 2966 }
@@ -2944,10 +2969,10 @@ read_char_escape (Lisp_Object readcharfun, int next_char)
2944 case '^': 2969 case '^':
2945 { 2970 {
2946 ncontrol++; 2971 ncontrol++;
2947 int c1 = READCHAR; 2972 int c1 = readchar (source);
2948 if (c1 == '\\') 2973 if (c1 == '\\')
2949 { 2974 {
2950 next_char = READCHAR; 2975 next_char = readchar (source);
2951 goto again; 2976 goto again;
2952 } 2977 }
2953 chr = c1; 2978 chr = c1;
@@ -2962,10 +2987,10 @@ read_char_escape (Lisp_Object readcharfun, int next_char)
2962 int count = 0; 2987 int count = 0;
2963 while (count < 2) 2988 while (count < 2)
2964 { 2989 {
2965 int c = READCHAR; 2990 int c = readchar (source);
2966 if (c < '0' || c > '7') 2991 if (c < '0' || c > '7')
2967 { 2992 {
2968 UNREAD (c); 2993 unreadchar (source, c);
2969 break; 2994 break;
2970 } 2995 }
2971 i = (i << 3) + (c - '0'); 2996 i = (i << 3) + (c - '0');
@@ -2986,11 +3011,11 @@ read_char_escape (Lisp_Object readcharfun, int next_char)
2986 int count = 0; 3011 int count = 0;
2987 while (1) 3012 while (1)
2988 { 3013 {
2989 int c = READCHAR; 3014 int c = readchar (source);
2990 int digit = char_hexdigit (c); 3015 int digit = char_hexdigit (c);
2991 if (digit < 0) 3016 if (digit < 0)
2992 { 3017 {
2993 UNREAD (c); 3018 unreadchar (source, c);
2994 break; 3019 break;
2995 } 3020 }
2996 i = (i << 4) + digit; 3021 i = (i << 4) + digit;
@@ -3023,7 +3048,7 @@ read_char_escape (Lisp_Object readcharfun, int next_char)
3023 unsigned int i = 0; 3048 unsigned int i = 0;
3024 for (int count = 0; count < unicode_hex_count; count++) 3049 for (int count = 0; count < unicode_hex_count; count++)
3025 { 3050 {
3026 int c = READCHAR; 3051 int c = readchar (source);
3027 if (c < 0) 3052 if (c < 0)
3028 error ("Malformed Unicode escape: \\%c%x", 3053 error ("Malformed Unicode escape: \\%c%x",
3029 unicode_hex_count == 4 ? 'u' : 'U', i); 3054 unicode_hex_count == 4 ? 'u' : 'U', i);
@@ -3042,15 +3067,15 @@ read_char_escape (Lisp_Object readcharfun, int next_char)
3042 /* Named character: \N{name} */ 3067 /* Named character: \N{name} */
3043 case 'N': 3068 case 'N':
3044 { 3069 {
3045 int c = READCHAR; 3070 int c = readchar (source);
3046 if (c != '{') 3071 if (c != '{')
3047 invalid_syntax ("Expected opening brace after \\N", readcharfun); 3072 invalid_syntax ("Expected opening brace after \\N", source);
3048 char name[UNICODE_CHARACTER_NAME_LENGTH_BOUND + 1]; 3073 char name[UNICODE_CHARACTER_NAME_LENGTH_BOUND + 1];
3049 bool whitespace = false; 3074 bool whitespace = false;
3050 ptrdiff_t length = 0; 3075 ptrdiff_t length = 0;
3051 while (true) 3076 while (true)
3052 { 3077 {
3053 int c = READCHAR; 3078 int c = readchar (source);
3054 if (c < 0) 3079 if (c < 0)
3055 end_of_file_error (); 3080 end_of_file_error ();
3056 if (c == '}') 3081 if (c == '}')
@@ -3061,7 +3086,7 @@ read_char_escape (Lisp_Object readcharfun, int next_char)
3061 "Invalid character U+%04X in character name"); 3086 "Invalid character U+%04X in character name");
3062 invalid_syntax_lisp (CALLN (Fformat, format, 3087 invalid_syntax_lisp (CALLN (Fformat, format,
3063 make_fixed_natnum (c)), 3088 make_fixed_natnum (c)),
3064 readcharfun); 3089 source);
3065 } 3090 }
3066 /* Treat multiple adjacent whitespace characters as a 3091 /* Treat multiple adjacent whitespace characters as a
3067 single space character. This makes it easier to use 3092 single space character. This makes it easier to use
@@ -3077,15 +3102,15 @@ read_char_escape (Lisp_Object readcharfun, int next_char)
3077 whitespace = false; 3102 whitespace = false;
3078 name[length++] = c; 3103 name[length++] = c;
3079 if (length >= sizeof name) 3104 if (length >= sizeof name)
3080 invalid_syntax ("Character name too long", readcharfun); 3105 invalid_syntax ("Character name too long", source);
3081 } 3106 }
3082 if (length == 0) 3107 if (length == 0)
3083 invalid_syntax ("Empty character name", readcharfun); 3108 invalid_syntax ("Empty character name", source);
3084 name[length] = '\0'; 3109 name[length] = '\0';
3085 3110
3086 /* character_name_to_code can invoke read0, recursively. 3111 /* character_name_to_code can invoke read0, recursively.
3087 This is why read0 needs to be re-entrant. */ 3112 This is why read0 needs to be re-entrant. */
3088 chr = character_name_to_code (name, length, readcharfun); 3113 chr = character_name_to_code (name, length, source);
3089 break; 3114 break;
3090 } 3115 }
3091 3116
@@ -3094,8 +3119,6 @@ read_char_escape (Lisp_Object readcharfun, int next_char)
3094 break; 3119 break;
3095 } 3120 }
3096 eassert (chr >= 0 && chr < (1 << CHARACTERBITS)); 3121 eassert (chr >= 0 && chr < (1 << CHARACTERBITS));
3097 if (chr < 0 || chr >= (1 << CHARACTERBITS))
3098 invalid_syntax ("Invalid character", readcharfun);
3099 3122
3100 /* Apply Control modifiers, using the rules: 3123 /* Apply Control modifiers, using the rules:
3101 \C-X = ascii_ctrl(nomod(X)) | mods(X) if nomod(X) is one of: 3124 \C-X = ascii_ctrl(nomod(X)) | mods(X) if nomod(X) is one of:
@@ -3144,12 +3167,12 @@ digit_to_number (int character, int base)
3144} 3167}
3145 3168
3146static void 3169static void
3147invalid_radix_integer (EMACS_INT radix, Lisp_Object readcharfun) 3170invalid_radix_integer (EMACS_INT radix, source_t *source)
3148{ 3171{
3149 static char const format[] = "integer, radix %"pI"d"; 3172 static char const format[] = "integer, radix %"pI"d";
3150 char buf[sizeof format - sizeof "%"pI"d" + INT_BUFSIZE_BOUND (radix)]; 3173 char buf[sizeof format - sizeof "%"pI"d" + INT_BUFSIZE_BOUND (radix)];
3151 sprintf (buf, format, radix); 3174 sprintf (buf, format, radix);
3152 invalid_syntax (buf, readcharfun); 3175 invalid_syntax (buf, source);
3153} 3176}
3154 3177
3155/* Read an integer in radix RADIX using READCHARFUN to read 3178/* Read an integer in radix RADIX using READCHARFUN to read
@@ -3158,7 +3181,7 @@ invalid_radix_integer (EMACS_INT radix, Lisp_Object readcharfun)
3158 Signal an error if encountering invalid read syntax. */ 3181 Signal an error if encountering invalid read syntax. */
3159 3182
3160static Lisp_Object 3183static Lisp_Object
3161read_integer (Lisp_Object readcharfun, int radix) 3184read_integer (source_t *source, int radix)
3162{ 3185{
3163 char stackbuf[20]; 3186 char stackbuf[20];
3164 char *read_buffer = stackbuf; 3187 char *read_buffer = stackbuf;
@@ -3168,11 +3191,11 @@ read_integer (Lisp_Object readcharfun, int radix)
3168 int valid = -1; /* 1 if valid, 0 if not, -1 if incomplete. */ 3191 int valid = -1; /* 1 if valid, 0 if not, -1 if incomplete. */
3169 specpdl_ref count = SPECPDL_INDEX (); 3192 specpdl_ref count = SPECPDL_INDEX ();
3170 3193
3171 int c = READCHAR; 3194 int c = readchar (source);
3172 if (c == '-' || c == '+') 3195 if (c == '-' || c == '+')
3173 { 3196 {
3174 *p++ = c; 3197 *p++ = c;
3175 c = READCHAR; 3198 c = readchar (source);
3176 } 3199 }
3177 3200
3178 if (c == '0') 3201 if (c == '0')
@@ -3183,7 +3206,7 @@ read_integer (Lisp_Object readcharfun, int radix)
3183 /* Ignore redundant leading zeros, so the buffer doesn't 3206 /* Ignore redundant leading zeros, so the buffer doesn't
3184 fill up with them. */ 3207 fill up with them. */
3185 do 3208 do
3186 c = READCHAR; 3209 c = readchar (source);
3187 while (c == '0'); 3210 while (c == '0');
3188 } 3211 }
3189 3212
@@ -3203,13 +3226,13 @@ read_integer (Lisp_Object readcharfun, int radix)
3203 p = read_buffer + offset; 3226 p = read_buffer + offset;
3204 } 3227 }
3205 *p++ = c; 3228 *p++ = c;
3206 c = READCHAR; 3229 c = readchar (source);
3207 } 3230 }
3208 3231
3209 UNREAD (c); 3232 unreadchar (source, c);
3210 3233
3211 if (valid != 1) 3234 if (valid != 1)
3212 invalid_radix_integer (radix, readcharfun); 3235 invalid_radix_integer (radix, source);
3213 3236
3214 *p = '\0'; 3237 *p = '\0';
3215 return unbind_to (count, string_to_number (read_buffer, radix, NULL)); 3238 return unbind_to (count, string_to_number (read_buffer, radix, NULL));
@@ -3218,9 +3241,9 @@ read_integer (Lisp_Object readcharfun, int radix)
3218 3241
3219/* Read a character literal (preceded by `?'). */ 3242/* Read a character literal (preceded by `?'). */
3220static Lisp_Object 3243static Lisp_Object
3221read_char_literal (Lisp_Object readcharfun) 3244read_char_literal (source_t *source)
3222{ 3245{
3223 int ch = READCHAR; 3246 int ch = readchar (source);
3224 if (ch < 0) 3247 if (ch < 0)
3225 end_of_file_error (); 3248 end_of_file_error ();
3226 3249
@@ -3242,7 +3265,7 @@ read_char_literal (Lisp_Object readcharfun)
3242 } 3265 }
3243 3266
3244 if (ch == '\\') 3267 if (ch == '\\')
3245 ch = read_char_escape (readcharfun, READCHAR); 3268 ch = read_char_escape (source, readchar (source));
3246 3269
3247 int modifiers = ch & CHAR_MODIFIER_MASK; 3270 int modifiers = ch & CHAR_MODIFIER_MASK;
3248 ch &= ~CHAR_MODIFIER_MASK; 3271 ch &= ~CHAR_MODIFIER_MASK;
@@ -3250,20 +3273,20 @@ read_char_literal (Lisp_Object readcharfun)
3250 ch = CHAR_TO_BYTE8 (ch); 3273 ch = CHAR_TO_BYTE8 (ch);
3251 ch |= modifiers; 3274 ch |= modifiers;
3252 3275
3253 int nch = READCHAR; 3276 int nch = readchar (source);
3254 UNREAD (nch); 3277 unreadchar (source, nch);
3255 if (nch <= 32 3278 if (nch <= 32
3256 || nch == '"' || nch == '\'' || nch == ';' || nch == '(' 3279 || nch == '"' || nch == '\'' || nch == ';' || nch == '('
3257 || nch == ')' || nch == '[' || nch == ']' || nch == '#' 3280 || nch == ')' || nch == '[' || nch == ']' || nch == '#'
3258 || nch == '?' || nch == '`' || nch == ',' || nch == '.') 3281 || nch == '?' || nch == '`' || nch == ',' || nch == '.')
3259 return make_fixnum (ch); 3282 return make_fixnum (ch);
3260 3283
3261 invalid_syntax ("?", readcharfun); 3284 invalid_syntax ("?", source);
3262} 3285}
3263 3286
3264/* Read a string literal (preceded by '"'). */ 3287/* Read a string literal (preceded by '"'). */
3265static Lisp_Object 3288static Lisp_Object
3266read_string_literal (Lisp_Object readcharfun) 3289read_string_literal (source_t *source)
3267{ 3290{
3268 char stackbuf[1024]; 3291 char stackbuf[1024];
3269 char *read_buffer = stackbuf; 3292 char *read_buffer = stackbuf;
@@ -3281,7 +3304,7 @@ read_string_literal (Lisp_Object readcharfun)
3281 ptrdiff_t nchars = 0; 3304 ptrdiff_t nchars = 0;
3282 3305
3283 int ch; 3306 int ch;
3284 while ((ch = READCHAR) >= 0 && ch != '\"') 3307 while ((ch = readchar (source)) >= 0 && ch != '\"')
3285 { 3308 {
3286 if (end - p < MAX_MULTIBYTE_LENGTH) 3309 if (end - p < MAX_MULTIBYTE_LENGTH)
3287 { 3310 {
@@ -3296,7 +3319,7 @@ read_string_literal (Lisp_Object readcharfun)
3296 if (ch == '\\') 3319 if (ch == '\\')
3297 { 3320 {
3298 /* First apply string-specific escape rules: */ 3321 /* First apply string-specific escape rules: */
3299 ch = READCHAR; 3322 ch = readchar (source);
3300 switch (ch) 3323 switch (ch)
3301 { 3324 {
3302 case 's': 3325 case 's':
@@ -3308,7 +3331,7 @@ read_string_literal (Lisp_Object readcharfun)
3308 /* `\SPC' and `\LF' generate no characters at all. */ 3331 /* `\SPC' and `\LF' generate no characters at all. */
3309 continue; 3332 continue;
3310 default: 3333 default:
3311 ch = read_char_escape (readcharfun, ch); 3334 ch = read_char_escape (source, ch);
3312 break; 3335 break;
3313 } 3336 }
3314 3337
@@ -3353,7 +3376,7 @@ read_string_literal (Lisp_Object readcharfun)
3353 3376
3354 /* Any modifiers remaining are invalid. */ 3377 /* Any modifiers remaining are invalid. */
3355 if (modifiers) 3378 if (modifiers)
3356 invalid_syntax ("Invalid modifier in string", readcharfun); 3379 invalid_syntax ("Invalid modifier in string", source);
3357 p += CHAR_STRING (ch, (unsigned char *) p); 3380 p += CHAR_STRING (ch, (unsigned char *) p);
3358 } 3381 }
3359 else 3382 else
@@ -3467,7 +3490,7 @@ vector_from_rev_list (Lisp_Object elems)
3467static Lisp_Object get_lazy_string (Lisp_Object val); 3490static Lisp_Object get_lazy_string (Lisp_Object val);
3468 3491
3469static Lisp_Object 3492static Lisp_Object
3470bytecode_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun) 3493bytecode_from_rev_list (Lisp_Object elems, source_t *source)
3471{ 3494{
3472 Lisp_Object obj = vector_from_rev_list (elems); 3495 Lisp_Object obj = vector_from_rev_list (elems);
3473 Lisp_Object *vec = XVECTOR (obj)->contents; 3496 Lisp_Object *vec = XVECTOR (obj)->contents;
@@ -3490,14 +3513,14 @@ bytecode_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun)
3490 Lisp_Object enc = vec[CLOSURE_CODE]; 3513 Lisp_Object enc = vec[CLOSURE_CODE];
3491 eassert (!STRING_MULTIBYTE (enc)); 3514 eassert (!STRING_MULTIBYTE (enc));
3492 /* The string (always unibyte) must be decoded to be parsed. */ 3515 /* The string (always unibyte) must be decoded to be parsed. */
3516 eassert (from_file_p (source));
3493 enc = Fdecode_coding_string (enc, 3517 enc = Fdecode_coding_string (enc,
3494 EQ (readcharfun, 3518 source->emacs_mule_encoding
3495 Qget_emacs_mule_file_char)
3496 ? Qemacs_mule : Qutf_8_emacs, 3519 ? Qemacs_mule : Qutf_8_emacs,
3497 Qt, Qnil); 3520 Qt, Qnil);
3498 Lisp_Object pair = Fread (enc); 3521 Lisp_Object pair = Fread (enc);
3499 if (!CONSP (pair)) 3522 if (!CONSP (pair))
3500 invalid_syntax ("Invalid byte-code object", readcharfun); 3523 invalid_syntax ("Invalid byte-code object", source);
3501 3524
3502 vec[CLOSURE_CODE] = XCAR (pair); 3525 vec[CLOSURE_CODE] = XCAR (pair);
3503 vec[CLOSURE_CONSTANTS] = XCDR (pair); 3526 vec[CLOSURE_CONSTANTS] = XCDR (pair);
@@ -3515,7 +3538,7 @@ bytecode_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun)
3515 || (CONSP (vec[CLOSURE_CODE]) /* Interpreted function. */ 3538 || (CONSP (vec[CLOSURE_CODE]) /* Interpreted function. */
3516 && (CONSP (vec[CLOSURE_CONSTANTS]) 3539 && (CONSP (vec[CLOSURE_CONSTANTS])
3517 || NILP (vec[CLOSURE_CONSTANTS])))))) 3540 || NILP (vec[CLOSURE_CONSTANTS]))))))
3518 invalid_syntax ("Invalid byte-code object", readcharfun); 3541 invalid_syntax ("Invalid byte-code object", source);
3519 3542
3520 if (STRINGP (vec[CLOSURE_CODE])) 3543 if (STRINGP (vec[CLOSURE_CODE]))
3521 { 3544 {
@@ -3536,18 +3559,18 @@ bytecode_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun)
3536} 3559}
3537 3560
3538static Lisp_Object 3561static Lisp_Object
3539char_table_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun) 3562char_table_from_rev_list (Lisp_Object elems, source_t *source)
3540{ 3563{
3541 Lisp_Object obj = vector_from_rev_list (elems); 3564 Lisp_Object obj = vector_from_rev_list (elems);
3542 if (ASIZE (obj) < CHAR_TABLE_STANDARD_SLOTS) 3565 if (ASIZE (obj) < CHAR_TABLE_STANDARD_SLOTS)
3543 invalid_syntax ("Invalid size char-table", readcharfun); 3566 invalid_syntax ("Invalid size char-table", source);
3544 XSETPVECTYPE (XVECTOR (obj), PVEC_CHAR_TABLE); 3567 XSETPVECTYPE (XVECTOR (obj), PVEC_CHAR_TABLE);
3545 return obj; 3568 return obj;
3546 3569
3547} 3570}
3548 3571
3549static Lisp_Object 3572static Lisp_Object
3550sub_char_table_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun) 3573sub_char_table_from_rev_list (Lisp_Object elems, source_t *source)
3551{ 3574{
3552 /* A sub-char-table can't be read as a regular vector because of two 3575 /* A sub-char-table can't be read as a regular vector because of two
3553 C integer fields. */ 3576 C integer fields. */
@@ -3579,22 +3602,22 @@ sub_char_table_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun)
3579} 3602}
3580 3603
3581static Lisp_Object 3604static Lisp_Object
3582string_props_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun) 3605string_props_from_rev_list (Lisp_Object elems, source_t *source)
3583{ 3606{
3584 elems = Fnreverse (elems); 3607 elems = Fnreverse (elems);
3585 if (NILP (elems) || !STRINGP (XCAR (elems))) 3608 if (NILP (elems) || !STRINGP (XCAR (elems)))
3586 invalid_syntax ("#", readcharfun); 3609 invalid_syntax ("#", source);
3587 Lisp_Object obj = XCAR (elems); 3610 Lisp_Object obj = XCAR (elems);
3588 for (Lisp_Object tl = XCDR (elems); !NILP (tl);) 3611 for (Lisp_Object tl = XCDR (elems); !NILP (tl);)
3589 { 3612 {
3590 Lisp_Object beg = XCAR (tl); 3613 Lisp_Object beg = XCAR (tl);
3591 tl = XCDR (tl); 3614 tl = XCDR (tl);
3592 if (NILP (tl)) 3615 if (NILP (tl))
3593 invalid_syntax ("Invalid string property list", readcharfun); 3616 invalid_syntax ("Invalid string property list", source);
3594 Lisp_Object end = XCAR (tl); 3617 Lisp_Object end = XCAR (tl);
3595 tl = XCDR (tl); 3618 tl = XCDR (tl);
3596 if (NILP (tl)) 3619 if (NILP (tl))
3597 invalid_syntax ("Invalid string property list", readcharfun); 3620 invalid_syntax ("Invalid string property list", source);
3598 Lisp_Object plist = XCAR (tl); 3621 Lisp_Object plist = XCAR (tl);
3599 tl = XCDR (tl); 3622 tl = XCDR (tl);
3600 Fset_text_properties (beg, end, plist, obj); 3623 Fset_text_properties (beg, end, plist, obj);
@@ -3604,34 +3627,34 @@ string_props_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun)
3604 3627
3605/* Read a bool vector (preceded by "#&"). */ 3628/* Read a bool vector (preceded by "#&"). */
3606static Lisp_Object 3629static Lisp_Object
3607read_bool_vector (Lisp_Object readcharfun) 3630read_bool_vector (source_t *source)
3608{ 3631{
3609 EMACS_INT length = 0; 3632 EMACS_INT length = 0;
3610 for (;;) 3633 for (;;)
3611 { 3634 {
3612 int c = READCHAR; 3635 int c = readchar (source);
3613 if (c < '0' || c > '9') 3636 if (c < '0' || c > '9')
3614 { 3637 {
3615 if (c != '"') 3638 if (c != '"')
3616 invalid_syntax ("#&", readcharfun); 3639 invalid_syntax ("#&", source);
3617 break; 3640 break;
3618 } 3641 }
3619 if (ckd_mul (&length, length, 10) 3642 if (ckd_mul (&length, length, 10)
3620 || ckd_add (&length, length, c - '0')) 3643 || ckd_add (&length, length, c - '0'))
3621 invalid_syntax ("#&", readcharfun); 3644 invalid_syntax ("#&", source);
3622 } 3645 }
3623 if (BOOL_VECTOR_LENGTH_MAX < length) 3646 if (BOOL_VECTOR_LENGTH_MAX < length)
3624 invalid_syntax ("#&", readcharfun); 3647 invalid_syntax ("#&", source);
3625 3648
3626 ptrdiff_t size_in_chars = bool_vector_bytes (length); 3649 ptrdiff_t size_in_chars = bool_vector_bytes (length);
3627 Lisp_Object str = read_string_literal (readcharfun); 3650 Lisp_Object str = read_string_literal (source);
3628 if (STRING_MULTIBYTE (str) 3651 if (STRING_MULTIBYTE (str)
3629 || !(size_in_chars == SCHARS (str) 3652 || !(size_in_chars == SCHARS (str)
3630 /* Emacs 19 printed 1 char too many when the number of bits 3653 /* Emacs 19 printed 1 char too many when the number of bits
3631 was a multiple of 8. Accept such input in case it came 3654 was a multiple of 8. Accept such input in case it came
3632 from that old version. */ 3655 from that old version. */
3633 || length == (SCHARS (str) - 1) * BOOL_VECTOR_BITS_PER_CHAR)) 3656 || length == (SCHARS (str) - 1) * BOOL_VECTOR_BITS_PER_CHAR))
3634 invalid_syntax ("#&...", readcharfun); 3657 invalid_syntax ("#&...", source);
3635 3658
3636 Lisp_Object obj = make_uninit_bool_vector (length); 3659 Lisp_Object obj = make_uninit_bool_vector (length);
3637 unsigned char *data = bool_vector_uchar_data (obj); 3660 unsigned char *data = bool_vector_uchar_data (obj);
@@ -3646,13 +3669,13 @@ read_bool_vector (Lisp_Object readcharfun)
3646 preceded by "#@". Return true if this was a normal skip, 3669 preceded by "#@". Return true if this was a normal skip,
3647 false if we read #@00 (which skips to EOB/EOF). */ 3670 false if we read #@00 (which skips to EOB/EOF). */
3648static bool 3671static bool
3649skip_lazy_string (Lisp_Object readcharfun) 3672skip_lazy_string (source_t *source)
3650{ 3673{
3651 ptrdiff_t nskip = 0; 3674 ptrdiff_t nskip = 0;
3652 ptrdiff_t digits = 0; 3675 ptrdiff_t digits = 0;
3653 for (;;) 3676 for (;;)
3654 { 3677 {
3655 int c = READCHAR; 3678 int c = readchar (source);
3656 if (c < '0' || c > '9') 3679 if (c < '0' || c > '9')
3657 { 3680 {
3658 if (nskip > 0) 3681 if (nskip > 0)
@@ -3662,22 +3685,22 @@ skip_lazy_string (Lisp_Object readcharfun)
3662 a space. */ 3685 a space. */
3663 nskip--; 3686 nskip--;
3664 else 3687 else
3665 UNREAD (c); 3688 unreadchar (source, c);
3666 break; 3689 break;
3667 } 3690 }
3668 if (ckd_mul (&nskip, nskip, 10) 3691 if (ckd_mul (&nskip, nskip, 10)
3669 || ckd_add (&nskip, nskip, c - '0')) 3692 || ckd_add (&nskip, nskip, c - '0'))
3670 invalid_syntax ("#@", readcharfun); 3693 invalid_syntax ("#@", source);
3671 digits++; 3694 digits++;
3672 if (digits == 2 && nskip == 0) 3695 if (digits == 2 && nskip == 0)
3673 { 3696 {
3674 /* #@00 means "read nil and skip to end" */ 3697 /* #@00 means "read nil and skip to end" */
3675 skip_dyn_eof (readcharfun); 3698 skip_dyn_eof (source);
3676 return false; 3699 return false;
3677 } 3700 }
3678 } 3701 }
3679 3702
3680 if (load_force_doc_strings && FROM_FILE_P (readcharfun)) 3703 if (load_force_doc_strings && from_file_p (source))
3681 { 3704 {
3682 /* If we are supposed to force doc strings into core right now, 3705 /* If we are supposed to force doc strings into core right now,
3683 record the last string that we skipped, 3706 record the last string that we skipped,
@@ -3719,7 +3742,7 @@ skip_lazy_string (Lisp_Object readcharfun)
3719 } 3742 }
3720 else 3743 else
3721 /* Skip that many bytes. */ 3744 /* Skip that many bytes. */
3722 skip_dyn_bytes (readcharfun, nskip); 3745 skip_dyn_bytes (source, nskip);
3723 3746
3724 return true; 3747 return true;
3725} 3748}
@@ -3787,21 +3810,21 @@ symbol_char_span (const char *s)
3787} 3810}
3788 3811
3789static void 3812static void
3790skip_space_and_comments (Lisp_Object readcharfun) 3813skip_space_and_comments (source_t *source)
3791{ 3814{
3792 int c; 3815 int c;
3793 do 3816 do
3794 { 3817 {
3795 c = READCHAR; 3818 c = readchar (source);
3796 if (c == ';') 3819 if (c == ';')
3797 do 3820 do
3798 c = READCHAR; 3821 c = readchar (source);
3799 while (c >= 0 && c != '\n'); 3822 while (c >= 0 && c != '\n');
3800 if (c < 0) 3823 if (c < 0)
3801 end_of_file_error (); 3824 end_of_file_error ();
3802 } 3825 }
3803 while (c <= 32 || c == NO_BREAK_SPACE); 3826 while (c <= 32 || c == NO_BREAK_SPACE);
3804 UNREAD (c); 3827 unreadchar (source, c);
3805} 3828}
3806 3829
3807/* When an object is read, the type of the top read stack entry indicates 3830/* When an object is read, the type of the top read stack entry indicates
@@ -3975,27 +3998,26 @@ add_char_to_buffer (readbuf_t *rb, int c, bool multibyte)
3975} 3998}
3976 3999
3977static AVOID 4000static AVOID
3978invalid_syntax_with_buffer (readbuf_t *rb, Lisp_Object readcharfun) 4001invalid_syntax_with_buffer (readbuf_t *rb, source_t *source)
3979{ 4002{
3980 *rb->cur = '\0'; 4003 *rb->cur = '\0';
3981 invalid_syntax (rb->start, readcharfun); 4004 invalid_syntax (rb->start, source);
3982} 4005}
3983 4006
3984static inline int 4007static inline int
3985read_and_buffer (readbuf_t *rb, Lisp_Object readcharfun) 4008read_and_buffer (readbuf_t *rb, source_t *source)
3986{ 4009{
3987 bool multibyte; 4010 int c = readchar (source);
3988 int c = READCHAR_REPORT_MULTIBYTE (&multibyte);
3989 if (c < 0) 4011 if (c < 0)
3990 invalid_syntax_with_buffer (rb, readcharfun); 4012 invalid_syntax_with_buffer (rb, source);
3991 add_char_to_buffer (rb, c, multibyte); 4013 add_char_to_buffer (rb, c, source->multibyte);
3992 return c; 4014 return c;
3993} 4015}
3994 4016
3995/* Read a Lisp object. 4017/* Read a Lisp object.
3996 If LOCATE_SYMS is true, symbols are read with position. */ 4018 If LOCATE_SYMS is true, symbols are read with position. */
3997static Lisp_Object 4019static Lisp_Object
3998read0 (Lisp_Object readcharfun, bool locate_syms) 4020read0 (source_t *source, bool locate_syms)
3999{ 4021{
4000 char stackbuf[64]; 4022 char stackbuf[64];
4001 4023
@@ -4014,8 +4036,7 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4014 /* Read an object into `obj'. */ 4036 /* Read an object into `obj'. */
4015 read_obj: ; 4037 read_obj: ;
4016 Lisp_Object obj; 4038 Lisp_Object obj;
4017 bool multibyte; 4039 int c = readchar (source);
4018 int c = READCHAR_REPORT_MULTIBYTE (&multibyte);
4019 if (c < 0) 4040 if (c < 0)
4020 end_of_file_error (); 4041 end_of_file_error ();
4021 4042
@@ -4027,7 +4048,7 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4027 4048
4028 case ')': 4049 case ')':
4029 if (read_stack_empty_p (base_sp)) 4050 if (read_stack_empty_p (base_sp))
4030 invalid_syntax (")", readcharfun); 4051 invalid_syntax (")", source);
4031 switch (read_stack_top ()->type) 4052 switch (read_stack_top ()->type)
4032 { 4053 {
4033 case RE_list_start: 4054 case RE_list_start:
@@ -4042,7 +4063,7 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4042 locate_syms = read_stack_top ()->u.vector.old_locate_syms; 4063 locate_syms = read_stack_top ()->u.vector.old_locate_syms;
4043 Lisp_Object elems = Fnreverse (read_stack_pop ()->u.vector.elems); 4064 Lisp_Object elems = Fnreverse (read_stack_pop ()->u.vector.elems);
4044 if (NILP (elems)) 4065 if (NILP (elems))
4045 invalid_syntax ("#s", readcharfun); 4066 invalid_syntax ("#s", source);
4046 4067
4047 if (BASE_EQ (XCAR (elems), Qhash_table)) 4068 if (BASE_EQ (XCAR (elems), Qhash_table))
4048 obj = hash_table_from_plist (XCDR (elems)); 4069 obj = hash_table_from_plist (XCDR (elems));
@@ -4053,10 +4074,10 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4053 case RE_string_props: 4074 case RE_string_props:
4054 locate_syms = read_stack_top ()->u.vector.old_locate_syms; 4075 locate_syms = read_stack_top ()->u.vector.old_locate_syms;
4055 obj = string_props_from_rev_list (read_stack_pop () ->u.vector.elems, 4076 obj = string_props_from_rev_list (read_stack_pop () ->u.vector.elems,
4056 readcharfun); 4077 source);
4057 break; 4078 break;
4058 default: 4079 default:
4059 invalid_syntax (")", readcharfun); 4080 invalid_syntax (")", source);
4060 } 4081 }
4061 break; 4082 break;
4062 4083
@@ -4071,7 +4092,7 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4071 4092
4072 case ']': 4093 case ']':
4073 if (read_stack_empty_p (base_sp)) 4094 if (read_stack_empty_p (base_sp))
4074 invalid_syntax ("]", readcharfun); 4095 invalid_syntax ("]", source);
4075 switch (read_stack_top ()->type) 4096 switch (read_stack_top ()->type)
4076 { 4097 {
4077 case RE_vector: 4098 case RE_vector:
@@ -4081,20 +4102,20 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4081 case RE_byte_code: 4102 case RE_byte_code:
4082 locate_syms = read_stack_top ()->u.vector.old_locate_syms; 4103 locate_syms = read_stack_top ()->u.vector.old_locate_syms;
4083 obj = bytecode_from_rev_list (read_stack_pop ()->u.vector.elems, 4104 obj = bytecode_from_rev_list (read_stack_pop ()->u.vector.elems,
4084 readcharfun); 4105 source);
4085 break; 4106 break;
4086 case RE_char_table: 4107 case RE_char_table:
4087 locate_syms = read_stack_top ()->u.vector.old_locate_syms; 4108 locate_syms = read_stack_top ()->u.vector.old_locate_syms;
4088 obj = char_table_from_rev_list (read_stack_pop ()->u.vector.elems, 4109 obj = char_table_from_rev_list (read_stack_pop ()->u.vector.elems,
4089 readcharfun); 4110 source);
4090 break; 4111 break;
4091 case RE_sub_char_table: 4112 case RE_sub_char_table:
4092 locate_syms = read_stack_top ()->u.vector.old_locate_syms; 4113 locate_syms = read_stack_top ()->u.vector.old_locate_syms;
4093 obj = sub_char_table_from_rev_list (read_stack_pop ()->u.vector.elems, 4114 obj = sub_char_table_from_rev_list (read_stack_pop ()->u.vector.elems,
4094 readcharfun); 4115 source);
4095 break; 4116 break;
4096 default: 4117 default:
4097 invalid_syntax ("]", readcharfun); 4118 invalid_syntax ("]", source);
4098 break; 4119 break;
4099 } 4120 }
4100 break; 4121 break;
@@ -4103,7 +4124,7 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4103 { 4124 {
4104 rb.cur = rb.start; 4125 rb.cur = rb.start;
4105 *rb.cur++ = '#'; 4126 *rb.cur++ = '#';
4106 int ch = read_and_buffer (&rb, readcharfun); 4127 int ch = read_and_buffer (&rb, source);
4107 switch (ch) 4128 switch (ch)
4108 { 4129 {
4109 case '\'': 4130 case '\'':
@@ -4121,11 +4142,11 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4121 4142
4122 case 's': 4143 case 's':
4123 /* #s(...) -- a record or hash-table */ 4144 /* #s(...) -- a record or hash-table */
4124 ch = read_and_buffer (&rb, readcharfun); 4145 ch = read_and_buffer (&rb, source);
4125 if (ch != '(') 4146 if (ch != '(')
4126 { 4147 {
4127 UNREAD (ch); 4148 unreadchar (source, ch);
4128 invalid_syntax_with_buffer (&rb, readcharfun); 4149 invalid_syntax_with_buffer (&rb, source);
4129 } 4150 }
4130 read_stack_push ((struct read_stack_entry) { 4151 read_stack_push ((struct read_stack_entry) {
4131 .type = RE_record, 4152 .type = RE_record,
@@ -4138,10 +4159,10 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4138 case '^': 4159 case '^':
4139 /* #^[...] -- char-table 4160 /* #^[...] -- char-table
4140 #^^[...] -- sub-char-table */ 4161 #^^[...] -- sub-char-table */
4141 ch = read_and_buffer (&rb, readcharfun); 4162 ch = read_and_buffer (&rb, source);
4142 if (ch == '^') 4163 if (ch == '^')
4143 { 4164 {
4144 ch = read_and_buffer (&rb, readcharfun); 4165 ch = read_and_buffer (&rb, source);
4145 if (ch == '[') 4166 if (ch == '[')
4146 { 4167 {
4147 read_stack_push ((struct read_stack_entry) { 4168 read_stack_push ((struct read_stack_entry) {
@@ -4154,8 +4175,8 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4154 } 4175 }
4155 else 4176 else
4156 { 4177 {
4157 UNREAD (ch); 4178 unreadchar (source, ch);
4158 invalid_syntax_with_buffer (&rb, readcharfun); 4179 invalid_syntax_with_buffer (&rb, source);
4159 } 4180 }
4160 } 4181 }
4161 else if (ch == '[') 4182 else if (ch == '[')
@@ -4170,8 +4191,8 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4170 } 4191 }
4171 else 4192 else
4172 { 4193 {
4173 UNREAD (ch); 4194 unreadchar (source, ch);
4174 invalid_syntax_with_buffer (&rb, readcharfun); 4195 invalid_syntax_with_buffer (&rb, source);
4175 } 4196 }
4176 4197
4177 case '(': 4198 case '(':
@@ -4196,7 +4217,7 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4196 4217
4197 case '&': 4218 case '&':
4198 /* #&N"..." -- bool-vector */ 4219 /* #&N"..." -- bool-vector */
4199 obj = read_bool_vector (readcharfun); 4220 obj = read_bool_vector (source);
4200 break; 4221 break;
4201 4222
4202 case '!': 4223 case '!':
@@ -4205,31 +4226,31 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4205 { 4226 {
4206 int c; 4227 int c;
4207 do 4228 do
4208 c = READCHAR; 4229 c = readchar (source);
4209 while (c >= 0 && c != '\n'); 4230 while (c >= 0 && c != '\n');
4210 goto read_obj; 4231 goto read_obj;
4211 } 4232 }
4212 4233
4213 case 'x': 4234 case 'x':
4214 case 'X': 4235 case 'X':
4215 obj = read_integer (readcharfun, 16); 4236 obj = read_integer (source, 16);
4216 break; 4237 break;
4217 4238
4218 case 'o': 4239 case 'o':
4219 case 'O': 4240 case 'O':
4220 obj = read_integer (readcharfun, 8); 4241 obj = read_integer (source, 8);
4221 break; 4242 break;
4222 4243
4223 case 'b': 4244 case 'b':
4224 case 'B': 4245 case 'B':
4225 obj = read_integer (readcharfun, 2); 4246 obj = read_integer (source, 2);
4226 break; 4247 break;
4227 4248
4228 case '@': 4249 case '@':
4229 /* #@NUMBER is used to skip NUMBER following bytes. 4250 /* #@NUMBER is used to skip NUMBER following bytes.
4230 That's used in .elc files to skip over doc strings 4251 That's used in .elc files to skip over doc strings
4231 and function definitions that can be loaded lazily. */ 4252 and function definitions that can be loaded lazily. */
4232 if (skip_lazy_string (readcharfun)) 4253 if (skip_lazy_string (source))
4233 goto read_obj; 4254 goto read_obj;
4234 obj = Qnil; /* #@00 skips to EOB/EOF and yields nil. */ 4255 obj = Qnil; /* #@00 skips to EOB/EOF and yields nil. */
4235 break; 4256 break;
@@ -4241,14 +4262,14 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4241 4262
4242 case ':': 4263 case ':':
4243 /* #:X -- uninterned symbol */ 4264 /* #:X -- uninterned symbol */
4244 c = READCHAR; 4265 c = readchar (source);
4245 if (c <= 32 || c == NO_BREAK_SPACE 4266 if (c <= 32 || c == NO_BREAK_SPACE
4246 || c == '"' || c == '\'' || c == ';' || c == '#' 4267 || c == '"' || c == '\'' || c == ';' || c == '#'
4247 || c == '(' || c == ')' || c == '[' || c == ']' 4268 || c == '(' || c == ')' || c == '[' || c == ']'
4248 || c == '`' || c == ',') 4269 || c == '`' || c == ',')
4249 { 4270 {
4250 /* No symbol character follows: this is the empty symbol. */ 4271 /* No symbol character follows: this is the empty symbol. */
4251 UNREAD (c); 4272 unreadchar (source, c);
4252 obj = Fmake_symbol (empty_unibyte_string); 4273 obj = Fmake_symbol (empty_unibyte_string);
4253 break; 4274 break;
4254 } 4275 }
@@ -4258,14 +4279,14 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4258 4279
4259 case '_': 4280 case '_':
4260 /* #_X -- symbol without shorthand */ 4281 /* #_X -- symbol without shorthand */
4261 c = READCHAR; 4282 c = readchar (source);
4262 if (c <= 32 || c == NO_BREAK_SPACE 4283 if (c <= 32 || c == NO_BREAK_SPACE
4263 || c == '"' || c == '\'' || c == ';' || c == '#' 4284 || c == '"' || c == '\'' || c == ';' || c == '#'
4264 || c == '(' || c == ')' || c == '[' || c == ']' 4285 || c == '(' || c == ')' || c == '[' || c == ']'
4265 || c == '`' || c == ',') 4286 || c == '`' || c == ',')
4266 { 4287 {
4267 /* No symbol character follows: this is the empty symbol. */ 4288 /* No symbol character follows: this is the empty symbol. */
4268 UNREAD (c); 4289 unreadchar (source, c);
4269 obj = Fintern (empty_unibyte_string, Qnil); 4290 obj = Fintern (empty_unibyte_string, Qnil);
4270 break; 4291 break;
4271 } 4292 }
@@ -4281,19 +4302,19 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4281 int c; 4302 int c;
4282 for (;;) 4303 for (;;)
4283 { 4304 {
4284 c = read_and_buffer (&rb, readcharfun); 4305 c = read_and_buffer (&rb, source);
4285 if (c < '0' || c > '9') 4306 if (c < '0' || c > '9')
4286 break; 4307 break;
4287 if (ckd_mul (&n, n, 10) 4308 if (ckd_mul (&n, n, 10)
4288 || ckd_add (&n, n, c - '0')) 4309 || ckd_add (&n, n, c - '0'))
4289 invalid_syntax_with_buffer (&rb, readcharfun); 4310 invalid_syntax_with_buffer (&rb, source);
4290 } 4311 }
4291 if (c == 'r' || c == 'R') 4312 if (c == 'r' || c == 'R')
4292 { 4313 {
4293 /* #NrDIGITS -- radix-N number */ 4314 /* #NrDIGITS -- radix-N number */
4294 if (n < 2 || n > 36) 4315 if (n < 2 || n > 36)
4295 invalid_radix_integer (n, readcharfun); 4316 invalid_radix_integer (n, source);
4296 obj = read_integer (readcharfun, n); 4317 obj = read_integer (source, n);
4297 break; 4318 break;
4298 } 4319 }
4299 else if (n <= MOST_POSITIVE_FIXNUM && !NILP (Vread_circle)) 4320 else if (n <= MOST_POSITIVE_FIXNUM && !NILP (Vread_circle))
@@ -4327,28 +4348,28 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4327 = XHASH_TABLE (read_objects_map); 4348 = XHASH_TABLE (read_objects_map);
4328 ptrdiff_t i = hash_find (h, make_fixnum (n)); 4349 ptrdiff_t i = hash_find (h, make_fixnum (n));
4329 if (i < 0) 4350 if (i < 0)
4330 invalid_syntax_with_buffer (&rb, readcharfun); 4351 invalid_syntax_with_buffer (&rb, source);
4331 obj = HASH_VALUE (h, i); 4352 obj = HASH_VALUE (h, i);
4332 break; 4353 break;
4333 } 4354 }
4334 else 4355 else
4335 invalid_syntax_with_buffer (&rb, readcharfun); 4356 invalid_syntax_with_buffer (&rb, source);
4336 } 4357 }
4337 else 4358 else
4338 invalid_syntax_with_buffer (&rb, readcharfun); 4359 invalid_syntax_with_buffer (&rb, source);
4339 } 4360 }
4340 else 4361 else
4341 invalid_syntax_with_buffer (&rb, readcharfun); 4362 invalid_syntax_with_buffer (&rb, source);
4342 } 4363 }
4343 break; 4364 break;
4344 } 4365 }
4345 4366
4346 case '?': 4367 case '?':
4347 obj = read_char_literal (readcharfun); 4368 obj = read_char_literal (source);
4348 break; 4369 break;
4349 4370
4350 case '"': 4371 case '"':
4351 obj = read_string_literal (readcharfun); 4372 obj = read_string_literal (source);
4352 break; 4373 break;
4353 4374
4354 case '\'': 4375 case '\'':
@@ -4367,14 +4388,14 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4367 4388
4368 case ',': 4389 case ',':
4369 { 4390 {
4370 int ch = READCHAR; 4391 int ch = readchar (source);
4371 Lisp_Object sym; 4392 Lisp_Object sym;
4372 if (ch == '@') 4393 if (ch == '@')
4373 sym = Qcomma_at; 4394 sym = Qcomma_at;
4374 else 4395 else
4375 { 4396 {
4376 if (ch >= 0) 4397 if (ch >= 0)
4377 UNREAD (ch); 4398 unreadchar (source, ch);
4378 sym = Qcomma; 4399 sym = Qcomma;
4379 } 4400 }
4380 read_stack_push ((struct read_stack_entry) { 4401 read_stack_push ((struct read_stack_entry) {
@@ -4388,15 +4409,15 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4388 { 4409 {
4389 int c; 4410 int c;
4390 do 4411 do
4391 c = READCHAR; 4412 c = readchar (source);
4392 while (c >= 0 && c != '\n'); 4413 while (c >= 0 && c != '\n');
4393 goto read_obj; 4414 goto read_obj;
4394 } 4415 }
4395 4416
4396 case '.': 4417 case '.':
4397 { 4418 {
4398 int nch = READCHAR; 4419 int nch = readchar (source);
4399 UNREAD (nch); 4420 unreadchar (source, nch);
4400 if (nch <= 32 || nch == NO_BREAK_SPACE 4421 if (nch <= 32 || nch == NO_BREAK_SPACE
4401 || nch == '"' || nch == '\'' || nch == ';' 4422 || nch == '"' || nch == '\'' || nch == ';'
4402 || nch == '(' || nch == '[' || nch == '#' 4423 || nch == '(' || nch == '[' || nch == '#'
@@ -4408,7 +4429,7 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4408 read_stack_top ()->type = RE_list_dot; 4429 read_stack_top ()->type = RE_list_dot;
4409 goto read_obj; 4430 goto read_obj;
4410 } 4431 }
4411 invalid_syntax (".", readcharfun); 4432 invalid_syntax (".", source);
4412 } 4433 }
4413 } 4434 }
4414 /* may be a number or symbol starting with a dot */ 4435 /* may be a number or symbol starting with a dot */
@@ -4432,15 +4453,15 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4432 { 4453 {
4433 if (c == '\\') 4454 if (c == '\\')
4434 { 4455 {
4435 c = READCHAR; 4456 c = readchar (source);
4436 if (c < 0) 4457 if (c < 0)
4437 end_of_file_error (); 4458 end_of_file_error ();
4438 quoted = true; 4459 quoted = true;
4439 } 4460 }
4440 4461
4441 add_char_to_buffer (&rb, c, multibyte); 4462 add_char_to_buffer (&rb, c, source->multibyte);
4442 nchars++; 4463 nchars++;
4443 c = READCHAR; 4464 c = readchar (source);
4444 } 4465 }
4445 while (c > 32 4466 while (c > 32
4446 && c != NO_BREAK_SPACE 4467 && c != NO_BREAK_SPACE
@@ -4451,7 +4472,7 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4451 4472
4452 *rb.cur = '\0'; 4473 *rb.cur = '\0';
4453 ptrdiff_t nbytes = rb.cur - rb.start; 4474 ptrdiff_t nbytes = rb.cur - rb.start;
4454 UNREAD (c); 4475 unreadchar (source, c);
4455 4476
4456 /* Only attempt to parse the token as a number if it starts as one. */ 4477 /* Only attempt to parse the token as a number if it starts as one. */
4457 char c0 = rb.start[0]; 4478 char c0 = rb.start[0];
@@ -4472,7 +4493,8 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4472 if (uninterned_symbol) 4493 if (uninterned_symbol)
4473 { 4494 {
4474 Lisp_Object name 4495 Lisp_Object name
4475 = make_specified_string (rb.start, nchars, nbytes, multibyte); 4496 = make_specified_string (rb.start, nchars, nbytes,
4497 source->multibyte);
4476 result = Fmake_symbol (name); 4498 result = Fmake_symbol (name);
4477 } 4499 }
4478 else 4500 else
@@ -4508,14 +4530,15 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4508 Lisp_Object name = make_specified_string (longhand, 4530 Lisp_Object name = make_specified_string (longhand,
4509 longhand_chars, 4531 longhand_chars,
4510 longhand_bytes, 4532 longhand_bytes,
4511 multibyte); 4533 source->multibyte);
4512 xfree (longhand); 4534 xfree (longhand);
4513 result = intern_driver (name, obarray, found); 4535 result = intern_driver (name, obarray, found);
4514 } 4536 }
4515 else 4537 else
4516 { 4538 {
4517 Lisp_Object name = make_specified_string (rb.start, nchars, 4539 Lisp_Object name = make_specified_string (rb.start, nchars,
4518 nbytes, multibyte); 4540 nbytes,
4541 source->multibyte);
4519 result = intern_driver (name, obarray, found); 4542 result = intern_driver (name, obarray, found);
4520 } 4543 }
4521 } 4544 }
@@ -4550,10 +4573,10 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4550 4573
4551 case RE_list_dot: 4574 case RE_list_dot:
4552 { 4575 {
4553 skip_space_and_comments (readcharfun); 4576 skip_space_and_comments (source);
4554 int ch = READCHAR; 4577 int ch = readchar (source);
4555 if (ch != ')') 4578 if (ch != ')')
4556 invalid_syntax ("expected )", readcharfun); 4579 invalid_syntax ("expected )", source);
4557 XSETCDR (e->u.list.tail, obj); 4580 XSETCDR (e->u.list.tail, obj);
4558 read_stack_pop (); 4581 read_stack_pop ();
4559 obj = e->u.list.head; 4582 obj = e->u.list.head;
@@ -4591,7 +4614,7 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4591 { 4614 {
4592 if (BASE_EQ (obj, placeholder)) 4615 if (BASE_EQ (obj, placeholder))
4593 /* Catch silly games like #1=#1# */ 4616 /* Catch silly games like #1=#1# */
4594 invalid_syntax ("nonsensical self-reference", readcharfun); 4617 invalid_syntax ("nonsensical self-reference", source);
4595 4618
4596 /* Optimization: since the placeholder is already 4619 /* Optimization: since the placeholder is already
4597 a cons, repurpose it as the actual value. 4620 a cons, repurpose it as the actual value.