diff options
| author | Mattias EngdegÄrd | 2024-05-26 13:44:32 +0200 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2025-07-10 10:24:58 +0200 |
| commit | cd3727f7e0607a152a97b534ee09a2cb8ac6cb84 (patch) | |
| tree | 721a0f3e066b4fcafc7e7f15a21f5cee4128f59e | |
| parent | 99080d0c04931b5d45026e1ee44526bbbb8dfdef (diff) | |
| download | emacs-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.c | 807 |
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 | ||
| 238 | static Lisp_Object Vloads_in_progress; | 238 | static Lisp_Object Vloads_in_progress; |
| 239 | 239 | ||
| 240 | static int read_emacs_mule_char (int, int (*) (int, Lisp_Object), | ||
| 241 | Lisp_Object); | ||
| 242 | |||
| 243 | static void readevalloop (Lisp_Object, struct infile *, Lisp_Object, bool, | 240 | static 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 | |||
| 261 | static 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. */ |
| 279 | static int unread_char = -1; | 256 | static int unread_char = -1; |
| 280 | 257 | ||
| 281 | static int | 258 | /* Representation of a source stream. |
| 282 | readchar (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; | 261 | typedef 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)) | 276 | static int source_buffer_get (source_t *src); |
| 306 | return -1; | 277 | static void source_buffer_unget (source_t *src, int c); |
| 278 | static int source_marker_get (source_t *src); | ||
| 279 | static void source_marker_unget (source_t *src, int c); | ||
| 280 | static int source_string_get (source_t *src); | ||
| 281 | static void source_string_unget (source_t *src, int c); | ||
| 282 | static int source_function_get (source_t *src); | ||
| 283 | static void source_function_unget (source_t *src, int c); | ||
| 284 | static int source_file_get (source_t *src); | ||
| 285 | static void source_file_unget (source_t *src, int c); | ||
| 307 | 286 | ||
| 308 | if (! NILP (BVAR (inbuffer, enable_multibyte_characters))) | 287 | static void |
| 309 | { | 288 | init_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); | 331 | static int |
| 332 | source_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; | 361 | static void |
| 357 | XMARKER (readcharfun)->charpos++; | 362 | source_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; | 371 | static int |
| 360 | } | 372 | source_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)) | 400 | static void |
| 401 | source_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 | |||
| 411 | static int | ||
| 412 | source_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) | 432 | static void |
| 402 | *multibyte = 1; | 433 | source_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); | 440 | static int readbyte_from_file (void); |
| 441 | static void unreadbyte_from_file (unsigned char); | ||
| 405 | 442 | ||
| 406 | if (!FIXNUMP (tem)) | 443 | static int read_emacs_mule_char (source_t *src, int c); |
| 407 | return -1; | ||
| 408 | return XFIXNUM (tem); | ||
| 409 | 444 | ||
| 410 | read_multibyte: | 445 | static int |
| 446 | source_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) \ | 479 | static void |
| 443 | (EQ (readcharfun, Qget_file_char) \ | 480 | source_file_unget (source_t *src, int c) |
| 444 | || EQ (readcharfun, Qget_emacs_mule_file_char)) | 481 | { |
| 482 | unread_char = c; | ||
| 483 | } | ||
| 484 | |||
| 485 | static int | ||
| 486 | source_function_get (source_t *src) | ||
| 487 | { | ||
| 488 | Lisp_Object x = call0 (src->object); | ||
| 489 | return CHARACTERP (x) ? XFIXNUM (x) : -1; | ||
| 490 | } | ||
| 445 | 491 | ||
| 446 | static void | 492 | static void |
| 447 | skip_dyn_bytes (Lisp_Object readcharfun, ptrdiff_t n) | 493 | source_function_unget (source_t *src, int c) |
| 494 | { | ||
| 495 | calln (src->object, make_fixnum (c)); | ||
| 496 | } | ||
| 497 | |||
| 498 | /* Read a character from SRC. */ | ||
| 499 | static inline int | ||
| 500 | readchar (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. */ | ||
| 507 | static inline void | ||
| 508 | unreadchar (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 | |||
| 518 | static bool | ||
| 519 | from_file_p (source_t *source) | ||
| 448 | { | 520 | { |
| 449 | if (FROM_FILE_P (readcharfun)) | 521 | return source->get == source_file_get; |
| 522 | } | ||
| 523 | |||
| 524 | static void | ||
| 525 | skip_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 | ||
| 470 | static void | 548 | static void |
| 471 | skip_dyn_eof (Lisp_Object readcharfun) | 549 | skip_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 | |||
| 487 | static void | ||
| 488 | unreadchar (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. */ | ||
| 535 | static int | 563 | static int |
| 536 | readbyte_from_stdio (void) | 564 | readbyte_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 | ||
| 591 | static int | 619 | static void |
| 592 | readbyte_from_file (int c, Lisp_Object readcharfun) | 620 | unreadbyte_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 | ||
| 608 | static AVOID | 629 | static AVOID |
| 609 | invalid_syntax_lisp (Lisp_Object s, Lisp_Object readcharfun) | 630 | invalid_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 | ||
| 633 | static AVOID | 650 | static AVOID |
| 634 | invalid_syntax (const char *s, Lisp_Object readcharfun) | 651 | invalid_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 | ||
| 644 | static int | 661 | static int |
| 645 | read_emacs_mule_char (int c, int (*readbyte) (int, Lisp_Object), Lisp_Object readcharfun) | 662 | read_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 | ||
| 716 | static Lisp_Object read_internal_start (Lisp_Object, Lisp_Object, | 733 | static Lisp_Object read_internal_start (Lisp_Object, Lisp_Object, |
| 717 | Lisp_Object, bool); | 734 | Lisp_Object, bool); |
| 718 | static Lisp_Object read0 (Lisp_Object, bool); | 735 | static Lisp_Object read0 (source_t *source, bool locate_syms); |
| 719 | 736 | ||
| 720 | static Lisp_Object substitute_object_recurse (struct subst *, Lisp_Object); | 737 | static Lisp_Object substitute_object_recurse (struct subst *, Lisp_Object); |
| 721 | static void substitute_in_interval (INTERVAL, void *); | 738 | static void substitute_in_interval (INTERVAL, void *); |
| @@ -1001,20 +1018,23 @@ typedef enum { | |||
| 1001 | static lexical_cookie_t | 1018 | static lexical_cookie_t |
| 1002 | lisp_file_lexical_cookie (Lisp_Object readcharfun) | 1019 | lisp_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. */ |
| 2837 | static int | 2862 | static int |
| 2838 | character_name_to_code (char const *name, ptrdiff_t name_len, | 2863 | character_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). */ |
| 2867 | static int | 2892 | static int |
| 2868 | read_char_escape (Lisp_Object readcharfun, int next_char) | 2893 | read_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 | ||
| 3146 | static void | 3169 | static void |
| 3147 | invalid_radix_integer (EMACS_INT radix, Lisp_Object readcharfun) | 3170 | invalid_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 | ||
| 3160 | static Lisp_Object | 3183 | static Lisp_Object |
| 3161 | read_integer (Lisp_Object readcharfun, int radix) | 3184 | read_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 `?'). */ |
| 3220 | static Lisp_Object | 3243 | static Lisp_Object |
| 3221 | read_char_literal (Lisp_Object readcharfun) | 3244 | read_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 '"'). */ |
| 3265 | static Lisp_Object | 3288 | static Lisp_Object |
| 3266 | read_string_literal (Lisp_Object readcharfun) | 3289 | read_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) | |||
| 3467 | static Lisp_Object get_lazy_string (Lisp_Object val); | 3490 | static Lisp_Object get_lazy_string (Lisp_Object val); |
| 3468 | 3491 | ||
| 3469 | static Lisp_Object | 3492 | static Lisp_Object |
| 3470 | bytecode_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun) | 3493 | bytecode_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 | ||
| 3538 | static Lisp_Object | 3561 | static Lisp_Object |
| 3539 | char_table_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun) | 3562 | char_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 | ||
| 3549 | static Lisp_Object | 3572 | static Lisp_Object |
| 3550 | sub_char_table_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun) | 3573 | sub_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 | ||
| 3581 | static Lisp_Object | 3604 | static Lisp_Object |
| 3582 | string_props_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun) | 3605 | string_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 "#&"). */ |
| 3606 | static Lisp_Object | 3629 | static Lisp_Object |
| 3607 | read_bool_vector (Lisp_Object readcharfun) | 3630 | read_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). */ |
| 3648 | static bool | 3671 | static bool |
| 3649 | skip_lazy_string (Lisp_Object readcharfun) | 3672 | skip_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 | ||
| 3789 | static void | 3812 | static void |
| 3790 | skip_space_and_comments (Lisp_Object readcharfun) | 3813 | skip_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 | ||
| 3977 | static AVOID | 4000 | static AVOID |
| 3978 | invalid_syntax_with_buffer (readbuf_t *rb, Lisp_Object readcharfun) | 4001 | invalid_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 | ||
| 3984 | static inline int | 4007 | static inline int |
| 3985 | read_and_buffer (readbuf_t *rb, Lisp_Object readcharfun) | 4008 | read_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. */ |
| 3997 | static Lisp_Object | 4019 | static Lisp_Object |
| 3998 | read0 (Lisp_Object readcharfun, bool locate_syms) | 4020 | read0 (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. |