aboutsummaryrefslogtreecommitdiffstats
path: root/src/lread.c
diff options
context:
space:
mode:
authorMichael R. Mauger2017-07-24 22:15:04 -0400
committerMichael R. Mauger2017-07-24 22:15:04 -0400
commitdf1a71272e5cdd10b511e2ffd702ca50ddd8a773 (patch)
tree9b9ac725394ee80891e2bff57b6407d0e491e71a /src/lread.c
parenteb27fc4d49e8c914cd0e6a8a2d02159601542141 (diff)
parent32daa3cb54523006c88717cbeac87964cd687a1b (diff)
downloademacs-df1a71272e5cdd10b511e2ffd702ca50ddd8a773.tar.gz
emacs-df1a71272e5cdd10b511e2ffd702ca50ddd8a773.zip
Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs
Diffstat (limited to 'src/lread.c')
-rw-r--r--src/lread.c239
1 files changed, 139 insertions, 100 deletions
diff --git a/src/lread.c b/src/lread.c
index 7c554ba8536..dbaadce4b40 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -103,8 +103,20 @@ static Lisp_Object read_objects_map;
103 (to reduce allocations), or nil. */ 103 (to reduce allocations), or nil. */
104static Lisp_Object read_objects_completed; 104static Lisp_Object read_objects_completed;
105 105
106/* File for get_file_char to read from. Use by load. */ 106/* File and lookahead for get-file-char and get-emacs-mule-file-char
107static FILE *instream; 107 to read from. Used by Fload. */
108static struct infile
109{
110 /* The input stream. */
111 FILE *stream;
112
113 /* Lookahead byte count. */
114 signed char lookahead;
115
116 /* Lookahead bytes, in reverse order. Keep these here because it is
117 not portable to ungetc more than one byte at a time. */
118 unsigned char buf[MAX_MULTIBYTE_LENGTH - 1];
119} *infile;
108 120
109/* For use within read-from-string (this reader is non-reentrant!!) */ 121/* For use within read-from-string (this reader is non-reentrant!!) */
110static ptrdiff_t read_from_string_index; 122static ptrdiff_t read_from_string_index;
@@ -149,7 +161,7 @@ static Lisp_Object Vloads_in_progress;
149static int read_emacs_mule_char (int, int (*) (int, Lisp_Object), 161static int read_emacs_mule_char (int, int (*) (int, Lisp_Object),
150 Lisp_Object); 162 Lisp_Object);
151 163
152static void readevalloop (Lisp_Object, FILE *, Lisp_Object, bool, 164static void readevalloop (Lisp_Object, struct infile *, Lisp_Object, bool,
153 Lisp_Object, Lisp_Object, 165 Lisp_Object, Lisp_Object,
154 Lisp_Object, Lisp_Object); 166 Lisp_Object, Lisp_Object);
155 167
@@ -340,14 +352,13 @@ readchar (Lisp_Object readcharfun, bool *multibyte)
340 len = BYTES_BY_CHAR_HEAD (c); 352 len = BYTES_BY_CHAR_HEAD (c);
341 while (i < len) 353 while (i < len)
342 { 354 {
343 c = (*readbyte) (-1, readcharfun); 355 buf[i++] = c = (*readbyte) (-1, readcharfun);
344 if (c < 0 || ! TRAILING_CODE_P (c)) 356 if (c < 0 || ! TRAILING_CODE_P (c))
345 { 357 {
346 while (--i > 1) 358 for (i -= c < 0; 0 < --i; )
347 (*readbyte) (buf[i], readcharfun); 359 (*readbyte) (buf[i], readcharfun);
348 return BYTE8_TO_CHAR (buf[0]); 360 return BYTE8_TO_CHAR (buf[0]);
349 } 361 }
350 buf[i++] = c;
351 } 362 }
352 return STRING_CHAR (buf); 363 return STRING_CHAR (buf);
353} 364}
@@ -362,8 +373,9 @@ skip_dyn_bytes (Lisp_Object readcharfun, ptrdiff_t n)
362 if (FROM_FILE_P (readcharfun)) 373 if (FROM_FILE_P (readcharfun))
363 { 374 {
364 block_input (); /* FIXME: Not sure if it's needed. */ 375 block_input (); /* FIXME: Not sure if it's needed. */
365 fseek (instream, n, SEEK_CUR); 376 fseek (infile->stream, n - infile->lookahead, SEEK_CUR);
366 unblock_input (); 377 unblock_input ();
378 infile->lookahead = 0;
367 } 379 }
368 else 380 else
369 { /* We're not reading directly from a file. In that case, it's difficult 381 { /* We're not reading directly from a file. In that case, it's difficult
@@ -385,8 +397,9 @@ skip_dyn_eof (Lisp_Object readcharfun)
385 if (FROM_FILE_P (readcharfun)) 397 if (FROM_FILE_P (readcharfun))
386 { 398 {
387 block_input (); /* FIXME: Not sure if it's needed. */ 399 block_input (); /* FIXME: Not sure if it's needed. */
388 fseek (instream, 0, SEEK_END); 400 fseek (infile->stream, 0, SEEK_END);
389 unblock_input (); 401 unblock_input ();
402 infile->lookahead = 0;
390 } 403 }
391 else 404 else
392 while (READCHAR >= 0); 405 while (READCHAR >= 0);
@@ -459,15 +472,13 @@ readbyte_for_lambda (int c, Lisp_Object readcharfun)
459 472
460 473
461static int 474static int
462readbyte_from_file (int c, Lisp_Object readcharfun) 475readbyte_from_stdio (void)
463{ 476{
464 if (c >= 0) 477 if (infile->lookahead)
465 { 478 return infile->buf[--infile->lookahead];
466 block_input (); 479
467 ungetc (c, instream); 480 int c;
468 unblock_input (); 481 FILE *instream = infile->stream;
469 return 0;
470 }
471 482
472 block_input (); 483 block_input ();
473 484
@@ -487,6 +498,19 @@ readbyte_from_file (int c, Lisp_Object readcharfun)
487} 498}
488 499
489static int 500static int
501readbyte_from_file (int c, Lisp_Object readcharfun)
502{
503 if (c >= 0)
504 {
505 eassert (infile->lookahead < sizeof infile->buf);
506 infile->buf[infile->lookahead++] = c;
507 return 0;
508 }
509
510 return readbyte_from_stdio ();
511}
512
513static int
490readbyte_from_string (int c, Lisp_Object readcharfun) 514readbyte_from_string (int c, Lisp_Object readcharfun)
491{ 515{
492 Lisp_Object string = XCAR (readcharfun); 516 Lisp_Object string = XCAR (readcharfun);
@@ -508,7 +532,7 @@ readbyte_from_string (int c, Lisp_Object readcharfun)
508} 532}
509 533
510 534
511/* Read one non-ASCII character from INSTREAM. The character is 535/* Read one non-ASCII character from INFILE. The character is
512 encoded in `emacs-mule' and the first byte is already read in 536 encoded in `emacs-mule' and the first byte is already read in
513 C. */ 537 C. */
514 538
@@ -530,14 +554,13 @@ read_emacs_mule_char (int c, int (*readbyte) (int, Lisp_Object), Lisp_Object rea
530 buf[i++] = c; 554 buf[i++] = c;
531 while (i < len) 555 while (i < len)
532 { 556 {
533 c = (*readbyte) (-1, readcharfun); 557 buf[i++] = c = (*readbyte) (-1, readcharfun);
534 if (c < 0xA0) 558 if (c < 0xA0)
535 { 559 {
536 while (--i > 1) 560 for (i -= c < 0; 0 < --i; )
537 (*readbyte) (buf[i], readcharfun); 561 (*readbyte) (buf[i], readcharfun);
538 return BYTE8_TO_CHAR (buf[0]); 562 return BYTE8_TO_CHAR (buf[0]);
539 } 563 }
540 buf[i++] = c;
541 } 564 }
542 565
543 if (len == 2) 566 if (len == 2)
@@ -572,6 +595,20 @@ read_emacs_mule_char (int c, int (*readbyte) (int, Lisp_Object), Lisp_Object rea
572} 595}
573 596
574 597
598/* An in-progress substitution of OBJECT for PLACEHOLDER. */
599struct subst
600{
601 Lisp_Object object;
602 Lisp_Object placeholder;
603
604 /* Hash table of subobjects of OBJECT that might be circular. If
605 Qt, all such objects might be circular. */
606 Lisp_Object completed;
607
608 /* List of subobjects of OBJECT that have already been visited. */
609 Lisp_Object seen;
610};
611
575static Lisp_Object read_internal_start (Lisp_Object, Lisp_Object, 612static Lisp_Object read_internal_start (Lisp_Object, Lisp_Object,
576 Lisp_Object); 613 Lisp_Object);
577static Lisp_Object read0 (Lisp_Object); 614static Lisp_Object read0 (Lisp_Object);
@@ -580,9 +617,8 @@ static Lisp_Object read1 (Lisp_Object, int *, bool);
580static Lisp_Object read_list (bool, Lisp_Object); 617static Lisp_Object read_list (bool, Lisp_Object);
581static Lisp_Object read_vector (Lisp_Object, bool); 618static Lisp_Object read_vector (Lisp_Object, bool);
582 619
583static Lisp_Object substitute_object_recurse (Lisp_Object, Lisp_Object, 620static Lisp_Object substitute_object_recurse (struct subst *, Lisp_Object);
584 Lisp_Object); 621static void substitute_in_interval (INTERVAL, void *);
585static void substitute_in_interval (INTERVAL, Lisp_Object);
586 622
587 623
588/* Get a character from the tty. */ 624/* Get a character from the tty. */
@@ -779,11 +815,9 @@ DEFUN ("get-file-char", Fget_file_char, Sget_file_char, 0, 0, 0,
779 doc: /* Don't use this yourself. */) 815 doc: /* Don't use this yourself. */)
780 (void) 816 (void)
781{ 817{
782 register Lisp_Object val; 818 if (!infile)
783 block_input (); 819 error ("get-file-char misused");
784 XSETINT (val, getc_unlocked (instream)); 820 return make_number (readbyte_from_stdio ());
785 unblock_input ();
786 return val;
787} 821}
788 822
789 823
@@ -1028,6 +1062,15 @@ suffix_p (Lisp_Object string, const char *suffix)
1028 return string_len >= suffix_len && !strcmp (SSDATA (string) + string_len - suffix_len, suffix); 1062 return string_len >= suffix_len && !strcmp (SSDATA (string) + string_len - suffix_len, suffix);
1029} 1063}
1030 1064
1065static void
1066close_infile_unwind (void *arg)
1067{
1068 FILE *stream = arg;
1069 eassert (infile == NULL || infile->stream == stream);
1070 infile = NULL;
1071 fclose (stream);
1072}
1073
1031DEFUN ("load", Fload, Sload, 1, 5, 0, 1074DEFUN ("load", Fload, Sload, 1, 5, 0,
1032 doc: /* Execute a file of Lisp code named FILE. 1075 doc: /* Execute a file of Lisp code named FILE.
1033First try FILE with `.elc' appended, then try with `.el', then try 1076First try FILE with `.elc' appended, then try with `.el', then try
@@ -1347,7 +1390,7 @@ Return t if the file exists and loads successfully. */)
1347 } 1390 }
1348 if (! stream) 1391 if (! stream)
1349 report_file_error ("Opening stdio stream", file); 1392 report_file_error ("Opening stdio stream", file);
1350 set_unwind_protect_ptr (fd_index, fclose_unwind, stream); 1393 set_unwind_protect_ptr (fd_index, close_infile_unwind, stream);
1351 1394
1352 if (! NILP (Vpurify_flag)) 1395 if (! NILP (Vpurify_flag))
1353 Vpreloaded_file_list = Fcons (Fpurecopy (file), Vpreloaded_file_list); 1396 Vpreloaded_file_list = Fcons (Fpurecopy (file), Vpreloaded_file_list);
@@ -1370,19 +1413,23 @@ Return t if the file exists and loads successfully. */)
1370 specbind (Qinhibit_file_name_operation, Qnil); 1413 specbind (Qinhibit_file_name_operation, Qnil);
1371 specbind (Qload_in_progress, Qt); 1414 specbind (Qload_in_progress, Qt);
1372 1415
1373 instream = stream; 1416 struct infile input;
1417 input.stream = stream;
1418 input.lookahead = 0;
1419 infile = &input;
1420
1374 if (lisp_file_lexically_bound_p (Qget_file_char)) 1421 if (lisp_file_lexically_bound_p (Qget_file_char))
1375 Fset (Qlexical_binding, Qt); 1422 Fset (Qlexical_binding, Qt);
1376 1423
1377 if (! version || version >= 22) 1424 if (! version || version >= 22)
1378 readevalloop (Qget_file_char, stream, hist_file_name, 1425 readevalloop (Qget_file_char, &input, hist_file_name,
1379 0, Qnil, Qnil, Qnil, Qnil); 1426 0, Qnil, Qnil, Qnil, Qnil);
1380 else 1427 else
1381 { 1428 {
1382 /* We can't handle a file which was compiled with 1429 /* We can't handle a file which was compiled with
1383 byte-compile-dynamic by older version of Emacs. */ 1430 byte-compile-dynamic by older version of Emacs. */
1384 specbind (Qload_force_doc_strings, Qt); 1431 specbind (Qload_force_doc_strings, Qt);
1385 readevalloop (Qget_emacs_mule_file_char, stream, hist_file_name, 1432 readevalloop (Qget_emacs_mule_file_char, &input, hist_file_name,
1386 0, Qnil, Qnil, Qnil, Qnil); 1433 0, Qnil, Qnil, Qnil, Qnil);
1387 } 1434 }
1388 unbind_to (count, Qnil); 1435 unbind_to (count, Qnil);
@@ -1813,7 +1860,7 @@ readevalloop_eager_expand_eval (Lisp_Object val, Lisp_Object macroexpand)
1813 1860
1814static void 1861static void
1815readevalloop (Lisp_Object readcharfun, 1862readevalloop (Lisp_Object readcharfun,
1816 FILE *stream, 1863 struct infile *infile0,
1817 Lisp_Object sourcename, 1864 Lisp_Object sourcename,
1818 bool printflag, 1865 bool printflag,
1819 Lisp_Object unibyte, Lisp_Object readfun, 1866 Lisp_Object unibyte, Lisp_Object readfun,
@@ -1913,7 +1960,7 @@ readevalloop (Lisp_Object readcharfun,
1913 if (b && first_sexp) 1960 if (b && first_sexp)
1914 whole_buffer = (BUF_PT (b) == BUF_BEG (b) && BUF_ZV (b) == BUF_Z (b)); 1961 whole_buffer = (BUF_PT (b) == BUF_BEG (b) && BUF_ZV (b) == BUF_Z (b));
1915 1962
1916 instream = stream; 1963 infile = infile0;
1917 read_next: 1964 read_next:
1918 c = READCHAR; 1965 c = READCHAR;
1919 if (c == ';') 1966 if (c == ';')
@@ -2003,7 +2050,7 @@ readevalloop (Lisp_Object readcharfun,
2003 } 2050 }
2004 2051
2005 build_load_history (sourcename, 2052 build_load_history (sourcename,
2006 stream || whole_buffer); 2053 infile0 || whole_buffer);
2007 2054
2008 unbind_to (count, Qnil); 2055 unbind_to (count, Qnil);
2009} 2056}
@@ -2629,6 +2676,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
2629 bool uninterned_symbol = false; 2676 bool uninterned_symbol = false;
2630 bool multibyte; 2677 bool multibyte;
2631 char stackbuf[MAX_ALLOCA]; 2678 char stackbuf[MAX_ALLOCA];
2679 current_thread->stack_top = stackbuf;
2632 2680
2633 *pch = 0; 2681 *pch = 0;
2634 2682
@@ -2943,11 +2991,17 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
2943 saved_doc_string_size = nskip + extra; 2991 saved_doc_string_size = nskip + extra;
2944 } 2992 }
2945 2993
2946 saved_doc_string_position = file_tell (instream); 2994 FILE *instream = infile->stream;
2995 saved_doc_string_position = (file_tell (instream)
2996 - infile->lookahead);
2947 2997
2948 /* Copy that many characters into saved_doc_string. */ 2998 /* Copy that many bytes into saved_doc_string. */
2999 i = 0;
3000 for (int n = min (nskip, infile->lookahead); 0 < n; n--)
3001 saved_doc_string[i++]
3002 = c = infile->buf[--infile->lookahead];
2949 block_input (); 3003 block_input ();
2950 for (i = 0; i < nskip && c >= 0; i++) 3004 for (; i < nskip && 0 <= c; i++)
2951 saved_doc_string[i] = c = getc_unlocked (instream); 3005 saved_doc_string[i] = c = getc_unlocked (instream);
2952 unblock_input (); 3006 unblock_input ();
2953 3007
@@ -3067,7 +3121,8 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3067 } 3121 }
3068 else 3122 else
3069 { 3123 {
3070 Fsubstitute_object_in_subtree (tem, placeholder); 3124 Flread__substitute_object_in_subtree
3125 (tem, placeholder, read_objects_completed);
3071 3126
3072 /* ...and #n# will use the real value from now on. */ 3127 /* ...and #n# will use the real value from now on. */
3073 i = hash_lookup (h, number, &hash); 3128 i = hash_lookup (h, number, &hash);
@@ -3424,6 +3479,24 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3424 if (! NILP (result)) 3479 if (! NILP (result))
3425 return unbind_to (count, result); 3480 return unbind_to (count, result);
3426 } 3481 }
3482 if (!quoted && multibyte)
3483 {
3484 int ch = STRING_CHAR ((unsigned char *) read_buffer);
3485 switch (ch)
3486 {
3487 case 0x2018: /* LEFT SINGLE QUOTATION MARK */
3488 case 0x2019: /* RIGHT SINGLE QUOTATION MARK */
3489 case 0x201B: /* SINGLE HIGH-REVERSED-9 QUOTATION MARK */
3490 case 0x201C: /* LEFT DOUBLE QUOTATION MARK */
3491 case 0x201D: /* RIGHT DOUBLE QUOTATION MARK */
3492 case 0x201F: /* DOUBLE HIGH-REVERSED-9 QUOTATION MARK */
3493 case 0x301E: /* DOUBLE PRIME QUOTATION MARK */
3494 case 0xFF02: /* FULLWIDTH QUOTATION MARK */
3495 case 0xFF07: /* FULLWIDTH APOSTROPHE */
3496 xsignal2 (Qinvalid_read_syntax, build_string ("strange quote"),
3497 CALLN (Fstring, make_number (ch)));
3498 }
3499 }
3427 { 3500 {
3428 Lisp_Object result; 3501 Lisp_Object result;
3429 ptrdiff_t nbytes = p - read_buffer; 3502 ptrdiff_t nbytes = p - read_buffer;
@@ -3473,26 +3546,16 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3473 } 3546 }
3474} 3547}
3475 3548
3476 3549DEFUN ("lread--substitute-object-in-subtree",
3477/* List of nodes we've seen during substitute_object_in_subtree. */ 3550 Flread__substitute_object_in_subtree,
3478static Lisp_Object seen_list; 3551 Slread__substitute_object_in_subtree, 3, 3, 0,
3479 3552 doc: /* In OBJECT, replace every occurrence of PLACEHOLDER with OBJECT.
3480DEFUN ("substitute-object-in-subtree", Fsubstitute_object_in_subtree, 3553COMPLETED is a hash table of objects that might be circular, or is t
3481 Ssubstitute_object_in_subtree, 2, 2, 0, 3554if any object might be circular. */)
3482 doc: /* Replace every reference to PLACEHOLDER in OBJECT with OBJECT. */) 3555 (Lisp_Object object, Lisp_Object placeholder, Lisp_Object completed)
3483 (Lisp_Object object, Lisp_Object placeholder)
3484{ 3556{
3485 Lisp_Object check_object; 3557 struct subst subst = { object, placeholder, completed, Qnil };
3486 3558 Lisp_Object check_object = substitute_object_recurse (&subst, object);
3487 /* We haven't seen any objects when we start. */
3488 seen_list = Qnil;
3489
3490 /* Make all the substitutions. */
3491 check_object
3492 = substitute_object_recurse (object, placeholder, object);
3493
3494 /* Clear seen_list because we're done with it. */
3495 seen_list = Qnil;
3496 3559
3497 /* The returned object here is expected to always eq the 3560 /* The returned object here is expected to always eq the
3498 original. */ 3561 original. */
@@ -3501,26 +3564,12 @@ DEFUN ("substitute-object-in-subtree", Fsubstitute_object_in_subtree,
3501 return Qnil; 3564 return Qnil;
3502} 3565}
3503 3566
3504/* Feval doesn't get called from here, so no gc protection is needed. */
3505#define SUBSTITUTE(get_val, set_val) \
3506 do { \
3507 Lisp_Object old_value = get_val; \
3508 Lisp_Object true_value \
3509 = substitute_object_recurse (object, placeholder, \
3510 old_value); \
3511 \
3512 if (!EQ (old_value, true_value)) \
3513 { \
3514 set_val; \
3515 } \
3516 } while (0)
3517
3518static Lisp_Object 3567static Lisp_Object
3519substitute_object_recurse (Lisp_Object object, Lisp_Object placeholder, Lisp_Object subtree) 3568substitute_object_recurse (struct subst *subst, Lisp_Object subtree)
3520{ 3569{
3521 /* If we find the placeholder, return the target object. */ 3570 /* If we find the placeholder, return the target object. */
3522 if (EQ (placeholder, subtree)) 3571 if (EQ (subst->placeholder, subtree))
3523 return object; 3572 return subst->object;
3524 3573
3525 /* For common object types that can't contain other objects, don't 3574 /* For common object types that can't contain other objects, don't
3526 bother looking them up; we're done. */ 3575 bother looking them up; we're done. */
@@ -3530,15 +3579,16 @@ substitute_object_recurse (Lisp_Object object, Lisp_Object placeholder, Lisp_Obj
3530 return subtree; 3579 return subtree;
3531 3580
3532 /* If we've been to this node before, don't explore it again. */ 3581 /* If we've been to this node before, don't explore it again. */
3533 if (!EQ (Qnil, Fmemq (subtree, seen_list))) 3582 if (!EQ (Qnil, Fmemq (subtree, subst->seen)))
3534 return subtree; 3583 return subtree;
3535 3584
3536 /* If this node can be the entry point to a cycle, remember that 3585 /* If this node can be the entry point to a cycle, remember that
3537 we've seen it. It can only be such an entry point if it was made 3586 we've seen it. It can only be such an entry point if it was made
3538 by #n=, which means that we can find it as a value in 3587 by #n=, which means that we can find it as a value in
3539 read_objects_completed. */ 3588 COMPLETED. */
3540 if (hash_lookup (XHASH_TABLE (read_objects_completed), subtree, NULL) >= 0) 3589 if (EQ (subst->completed, Qt)
3541 seen_list = Fcons (subtree, seen_list); 3590 || hash_lookup (XHASH_TABLE (subst->completed), subtree, NULL) >= 0)
3591 subst->seen = Fcons (subtree, subst->seen);
3542 3592
3543 /* Recurse according to subtree's type. 3593 /* Recurse according to subtree's type.
3544 Every branch must return a Lisp_Object. */ 3594 Every branch must return a Lisp_Object. */
@@ -3565,19 +3615,15 @@ substitute_object_recurse (Lisp_Object object, Lisp_Object placeholder, Lisp_Obj
3565 if (SUB_CHAR_TABLE_P (subtree)) 3615 if (SUB_CHAR_TABLE_P (subtree))
3566 i = 2; 3616 i = 2;
3567 for ( ; i < length; i++) 3617 for ( ; i < length; i++)
3568 SUBSTITUTE (AREF (subtree, i), 3618 ASET (subtree, i,
3569 ASET (subtree, i, true_value)); 3619 substitute_object_recurse (subst, AREF (subtree, i)));
3570 return subtree; 3620 return subtree;
3571 } 3621 }
3572 3622
3573 case Lisp_Cons: 3623 case Lisp_Cons:
3574 { 3624 XSETCAR (subtree, substitute_object_recurse (subst, XCAR (subtree)));
3575 SUBSTITUTE (XCAR (subtree), 3625 XSETCDR (subtree, substitute_object_recurse (subst, XCDR (subtree)));
3576 XSETCAR (subtree, true_value)); 3626 return subtree;
3577 SUBSTITUTE (XCDR (subtree),
3578 XSETCDR (subtree, true_value));
3579 return subtree;
3580 }
3581 3627
3582 case Lisp_String: 3628 case Lisp_String:
3583 { 3629 {
@@ -3585,11 +3631,8 @@ substitute_object_recurse (Lisp_Object object, Lisp_Object placeholder, Lisp_Obj
3585 substitute_in_interval contains part of the logic. */ 3631 substitute_in_interval contains part of the logic. */
3586 3632
3587 INTERVAL root_interval = string_intervals (subtree); 3633 INTERVAL root_interval = string_intervals (subtree);
3588 AUTO_CONS (arg, object, placeholder);
3589
3590 traverse_intervals_noorder (root_interval, 3634 traverse_intervals_noorder (root_interval,
3591 &substitute_in_interval, arg); 3635 substitute_in_interval, subst);
3592
3593 return subtree; 3636 return subtree;
3594 } 3637 }
3595 3638
@@ -3601,12 +3644,10 @@ substitute_object_recurse (Lisp_Object object, Lisp_Object placeholder, Lisp_Obj
3601 3644
3602/* Helper function for substitute_object_recurse. */ 3645/* Helper function for substitute_object_recurse. */
3603static void 3646static void
3604substitute_in_interval (INTERVAL interval, Lisp_Object arg) 3647substitute_in_interval (INTERVAL interval, void *arg)
3605{ 3648{
3606 Lisp_Object object = Fcar (arg); 3649 set_interval_plist (interval,
3607 Lisp_Object placeholder = Fcdr (arg); 3650 substitute_object_recurse (arg, interval->plist));
3608
3609 SUBSTITUTE (interval->plist, set_interval_plist (interval, true_value));
3610} 3651}
3611 3652
3612 3653
@@ -4704,7 +4745,7 @@ syms_of_lread (void)
4704{ 4745{
4705 defsubr (&Sread); 4746 defsubr (&Sread);
4706 defsubr (&Sread_from_string); 4747 defsubr (&Sread_from_string);
4707 defsubr (&Ssubstitute_object_in_subtree); 4748 defsubr (&Slread__substitute_object_in_subtree);
4708 defsubr (&Sintern); 4749 defsubr (&Sintern);
4709 defsubr (&Sintern_soft); 4750 defsubr (&Sintern_soft);
4710 defsubr (&Sunintern); 4751 defsubr (&Sunintern);
@@ -5017,8 +5058,6 @@ that are loaded before your customizations are read! */);
5017 read_objects_map = Qnil; 5058 read_objects_map = Qnil;
5018 staticpro (&read_objects_completed); 5059 staticpro (&read_objects_completed);
5019 read_objects_completed = Qnil; 5060 read_objects_completed = Qnil;
5020 staticpro (&seen_list);
5021 seen_list = Qnil;
5022 5061
5023 Vloads_in_progress = Qnil; 5062 Vloads_in_progress = Qnil;
5024 staticpro (&Vloads_in_progress); 5063 staticpro (&Vloads_in_progress);