comparison src/print.c @ 5560:58b38d5b32d0

Implement print-circle, allowing recursive and circular structures to be read. src/ChangeLog addition: 2011-09-04 Aidan Kehoe <kehoea@parhasard.net> * alloc.c: * alloc.c (ALLOC_FROB_BLOCK_LISP_OBJECT_1): * alloc.c (ALLOC_FROB_BLOCK_LISP_OBJECT): * alloc.c (cons_print_preprocess): * alloc.c (vector_print_preprocess): * alloc.c (vector_nsubst_structures_descend): * alloc.c (Fmake_symbol): * alloc.c (UNMARK_symbol): * alloc.c (sweep_symbols): * alloc.c (reinit_alloc_objects_early): * alloc.c (reinit_alloc_early): * bytecode.c: * bytecode.c (compiled_function_print_preprocess): * bytecode.c (compiled_function_nsubst_structures_descend): * bytecode.c (set_compiled_function_arglist): * bytecode.c (set_compiled_function_interactive): * bytecode.c (bytecode_objects_create): * chartab.c: * chartab.c (print_preprocess_mapper): * chartab.c (nsubst_structures_mapper): * chartab.c (char_table_nsubst_structures_descend): * chartab.c (chartab_objects_create): * elhash.c: * elhash.c (nsubst_structures_map_hash_table): * elhash.c (hash_table_nsubst_structures_descend): * elhash.c (print_preprocess_mapper): * elhash.c (hash_table_print_preprocess): * elhash.c (inchash_eq): * elhash.c (hash_table_objects_create): * elhash.c (syms_of_elhash): * elhash.h: * emacs.c (main_1): * fns.c: * fns.c (check_eq_nokey): * fns.c (Fnsubst): * fns.c (syms_of_fns): * lisp.h: * lisp.h (struct Lisp_Symbol): * lisp.h (IN_OBARRAY): * lisp.h (struct): * lisp.h (PRINT_PREPROCESS): * lread.c (read1): * lrecord.h: * lrecord.h (struct lrecord_implementation): * lrecord.h (DEFINE_DUMPABLE_MODULE_LISP_OBJECT): * print.c: * print.c (PRINT_CIRCLE_LIMIT): * print.c (print_continuous_numbering_changed): * print.c (print_prepare): * print.c (print_finish): * print.c (Fprin1_to_string): * print.c (print_cons): * print.c (print_preprocess_inchash_eq): * print.c (print_preprocess): * print.c (print_sort_get_numbers): * print.c (print_sort_compare_ordinals): * print.c (print_gensym_or_circle): * print.c (nsubst_structures_descend): * print.c (nsubst_structures): * print.c (print_internal): * print.c (print_symbol): * print.c (vars_of_print): * rangetab.c: * rangetab.c (range_table_print_preprocess): * rangetab.c (range_table_nsubst_structures_descend): * rangetab.c (rangetab_objects_create): * rangetab.c (syms_of_rangetab): * symbols.c: * symbols.c (symbol_print_preprocess): * symbols.c (Fintern): * symbols.c (Funintern): * symbols.c (reinit_symbol_objects_early): * symbols.c (init_symbols_once_early): * symsinit.h: Implement print-circle, printing circular structures in a readable fashion, and treating them appropriately on read. This is by means of two new object methods, print_preprocess (detecting circularities), and nsubst_structures_descend (replacing placeholders with the read objects). Expose the substitution to Lisp via #'nsubst and its new :descend-structures keyword. Store information as to whether symbols are interned in obarray or not in their header, making checking for keywords and uninterned symbols (and thus printing) cheaper. Default print_gensym to t, as Common Lisp does, and as a more-than-decade old comment suggests. lisp/ChangeLog addition: 2011-09-04 Aidan Kehoe <kehoea@parhasard.net> * bytecomp.el (byte-compile-output-file-form): * bytecomp.el (byte-compile-output-docform): Bind print-circle, print-continuous-numbering in these functions, now those variables are available. * lisp.el (forward-sexp): * lisp.el (backward-sexp): Recognise leading #N= as being part of an expression. tests/ChangeLog addition: 2011-09-04 Aidan Kehoe <kehoea@parhasard.net> * automated/lisp-reader-tests.el: * automated/lisp-tests.el (literal-with-uninterned): * automated/symbol-tests.el (foo): Test print-circle, for printing (mutually-)recursive and circular structures. Bind print-continuous-numbering where appropriate.
author Aidan Kehoe <kehoea@parhasard.net>
date Sun, 04 Sep 2011 19:51:35 +0100
parents b9167d522a9a
children 56144c8593a8
comparison
equal deleted inserted replaced
5559:f3ab0c29c246 5560:58b38d5b32d0
48 #ifdef WIN32_NATIVE 48 #ifdef WIN32_NATIVE
49 #include "console-msw.h" 49 #include "console-msw.h"
50 #endif 50 #endif
51 51
52 #include "sysfile.h" 52 #include "sysfile.h"
53 #include "elhash.h"
53 54
54 #include <float.h> 55 #include <float.h>
55 /* Define if not in float.h */ 56 /* Define if not in float.h */
56 #ifndef DBL_DIG 57 #ifndef DBL_DIG
57 #define DBL_DIG 16 58 #define DBL_DIG 16
69 70
70 /* Avoid actual stack overflow in print. */ 71 /* Avoid actual stack overflow in print. */
71 static int print_depth; 72 static int print_depth;
72 73
73 /* Detect most circularities to print finite output. */ 74 /* Detect most circularities to print finite output. */
74 #define PRINT_CIRCLE 200 75 #define PRINT_CIRCLE_LIMIT 200
75 static Lisp_Object being_printed[PRINT_CIRCLE]; 76 static Lisp_Object being_printed[PRINT_CIRCLE_LIMIT];
76 77
77 /* Maximum length of list or vector to print in full; noninteger means 78 /* Maximum length of list or vector to print in full; noninteger means
78 effectively infinity */ 79 effectively infinity */
79 80
80 Lisp_Object Vprint_length; 81 Lisp_Object Vprint_length;
94 /* Label to use when making echo-area messages. */ 95 /* Label to use when making echo-area messages. */
95 96
96 Lisp_Object Vprint_message_label; 97 Lisp_Object Vprint_message_label;
97 98
98 /* Nonzero means print newlines in strings as \n. */ 99 /* Nonzero means print newlines in strings as \n. */
99 100 Boolint print_escape_newlines;
100 int print_escape_newlines; 101
101 int print_readably; 102 Boolint print_readably;
102 103
103 /* Non-nil means print #: before uninterned symbols. 104 /* Non-zero means print #: before uninterned symbols, and use the #n= and
104 Neither t nor nil means so that and don't clear Vprint_gensym_alist 105 #n# syntax for them. */
105 on entry to and exit from print functions. */ 106 Boolint print_gensym;
106 Lisp_Object Vprint_gensym; 107
107 Lisp_Object Vprint_gensym_alist; 108 /* Non-zero means print recursive structures using #n= and #n# syntax. */
109 Boolint print_circle;
110
111 /* Non-zero means keep continuous numbers for #n= and #n# syntax between
112 several print functions. Setting or binding the corresponding Lisp
113 variable to a non-nil value silently *clears* Vprint_number_table. */
114 Boolint print_continuous_numbering;
115
116 /* Vprint_number_table is a hash table mapping objects to their statuses for
117 this print operation. The statuses are represented by integers. */
118 Lisp_Object Vprint_number_table;
119
120 /* These describe the bit fields of the integers in Vprint_number_table. */
121 enum PRINT_NUMBER_FIELDS {
122 /* Lowest four bits describe the number of times a given object has
123 been seen, allowing entries to be manipulated cheaply by
124 inchash_eq() when encountered. */
125 PRINT_NUMBER_SEEN_MASK = 0xF,
126
127 /* The next twenty-five bits give the sequence number for the object,
128 corresponding to the order in which print_preprocess encountered the
129 objects; as such, it's related to print_number_index. */
130 PRINT_NUMBER_ORDINAL_MASK = 0x1FFFFFF0,
131 PRINT_NUMBER_ORDINAL_SHIFT = 4,
132
133 /* And the next bit describes whether the object has already been printed
134 in this print operation (or in these print operations, if
135 print-continuous-numbering is relevant). */
136 PRINT_NUMBER_PRINTED_MASK = 0x20000000,
137 };
138
139 /* Reflects the number of repeated or possibly-repeated objects encountered
140 by print_preprocess(); reset whenever Vprint_number_table is cleared. */
141 Elemcount print_number_index;
108 142
109 Lisp_Object Qdisplay_error; 143 Lisp_Object Qdisplay_error;
110 Lisp_Object Qprint_message_label; 144 Lisp_Object Qprint_message_label;
111 145
112 /* Force immediate output of all printed data. Used for debugging. */ 146 /* Force immediate output of all printed data. Used for debugging. */
538 } 572 }
539 573
540 UNGCPRO; 574 UNGCPRO;
541 } 575 }
542 576
543 #define RESET_PRINT_GENSYM do { \ 577 static int
544 if (!CONSP (Vprint_gensym)) \ 578 print_continuous_numbering_changed (Lisp_Object UNUSED (sym),
545 Vprint_gensym_alist = Qnil; \ 579 Lisp_Object *val,
546 } while (0) 580 Lisp_Object UNUSED (in_object),
547 581 int UNUSED (flags))
582 {
583 if (!NILP (*val) && !print_continuous_numbering)
584 {
585 Fclrhash (Vprint_number_table);
586 print_number_index = 0;
587 }
588
589 return 0;
590 }
591
592 #define RESET_PRINT_NUMBER_TABLE do { \
593 if (!print_continuous_numbering) \
594 { \
595 Fclrhash (Vprint_number_table); \
596 print_number_index = 0; \
597 } \
598 } while (0)
599
548 Lisp_Object 600 Lisp_Object
549 canonicalize_printcharfun (Lisp_Object printcharfun) 601 canonicalize_printcharfun (Lisp_Object printcharfun)
550 { 602 {
551 if (NILP (printcharfun)) 603 if (NILP (printcharfun))
552 printcharfun = Vstandard_output; 604 printcharfun = Vstandard_output;
563 /* Emacs won't print while GCing, but an external debugger might */ 615 /* Emacs won't print while GCing, but an external debugger might */
564 #ifdef NO_PRINT_DURING_GC 616 #ifdef NO_PRINT_DURING_GC
565 if (gc_in_progress) 617 if (gc_in_progress)
566 return Qnil; 618 return Qnil;
567 #endif 619 #endif
568 620
569 RESET_PRINT_GENSYM; 621 RESET_PRINT_NUMBER_TABLE;
570 622
571 printcharfun = canonicalize_printcharfun (printcharfun); 623 printcharfun = canonicalize_printcharfun (printcharfun);
572 624
573 /* Here we could safely return the canonicalized PRINTCHARFUN. 625 /* Here we could safely return the canonicalized PRINTCHARFUN.
574 However, if PRINTCHARFUN is a frame, printing of complex 626 However, if PRINTCHARFUN is a frame, printing of complex
610 /* Emacs won't print while GCing, but an external debugger might */ 662 /* Emacs won't print while GCing, but an external debugger might */
611 #ifdef NO_PRINT_DURING_GC 663 #ifdef NO_PRINT_DURING_GC
612 if (gc_in_progress) 664 if (gc_in_progress)
613 return; 665 return;
614 #endif 666 #endif
615 667
616 RESET_PRINT_GENSYM; 668 RESET_PRINT_NUMBER_TABLE;
617 669
618 /* See the comment in print_prepare(). */ 670 /* See the comment in print_prepare(). */
619 if (FRAMEP (frame_kludge)) 671 if (FRAMEP (frame_kludge))
620 { 672 {
621 struct frame *f = XFRAME (frame_kludge); 673 struct frame *f = XFRAME (frame_kludge);
933 (object, noescape)) 985 (object, noescape))
934 { 986 {
935 /* This function can GC */ 987 /* This function can GC */
936 Lisp_Object result = Qnil; 988 Lisp_Object result = Qnil;
937 989
938 RESET_PRINT_GENSYM; 990 RESET_PRINT_NUMBER_TABLE;
939 result = prin1_to_string (object, !(EQ(noescape, Qnil))); 991 result = prin1_to_string (object, !(EQ(noescape, Qnil)));
940 RESET_PRINT_GENSYM; 992 RESET_PRINT_NUMBER_TABLE;
941 993
942 return result; 994 return result;
943 } 995 }
944 996
945 DEFUN ("princ", Fprinc, 1, 2, 0, /* 997 DEFUN ("princ", Fprinc, 1, 2, 0, /*
1413 for (tortoise = obj, len = 0; 1465 for (tortoise = obj, len = 0;
1414 CONSP (obj); 1466 CONSP (obj);
1415 obj = XCDR (obj), len++) 1467 obj = XCDR (obj), len++)
1416 { 1468 {
1417 if (len > 0) 1469 if (len > 0)
1418 write_ascstring (printcharfun, " "); 1470 {
1419 if (EQ (obj, tortoise) && len > 0) 1471 write_ascstring (printcharfun, " ");
1420 { 1472
1421 if (print_readably) 1473 /* Note that print_cons is the only object method that does any
1422 printing_unreadable_object_fmt ("circular list"); 1474 circularity checking itself, because a cons that is the cdr
1423 else 1475 of OBJ is not handed to print_internal in the ordinary course
1424 write_ascstring (printcharfun, "... <circular list>"); 1476 of events. All the other possibly-repeated structures always
1425 break; 1477 hand sub-objects to print_internal(). */
1426 } 1478 if (print_circle &&
1427 if (len & 1) 1479 INTP (Fgethash (obj, Vprint_number_table, Qnil)))
1428 tortoise = XCDR (tortoise); 1480 {
1429 if (len > max) 1481 write_ascstring (printcharfun, ". ");
1430 { 1482 print_internal (obj, printcharfun, escapeflag);
1431 write_ascstring (printcharfun, "..."); 1483 /* We have printed the list's tail, print_cons() is done. */
1432 break; 1484 break;
1433 } 1485 }
1486
1487 if (EQ (obj, tortoise))
1488 {
1489 if (print_readably)
1490 {
1491 printing_unreadable_object_fmt ("circular list");
1492 }
1493
1494 write_ascstring (printcharfun, "... <circular list>");
1495 break;
1496 }
1497
1498 if (len & 1)
1499 {
1500 tortoise = XCDR (tortoise);
1501 }
1502
1503 if (len > max)
1504 {
1505 write_ascstring (printcharfun, "...");
1506 break;
1507 }
1508 }
1509
1434 print_internal (XCAR (obj), printcharfun, escapeflag); 1510 print_internal (XCAR (obj), printcharfun, escapeflag);
1435 } 1511 }
1436 } 1512 }
1513
1437 if (!LISTP (obj)) 1514 if (!LISTP (obj))
1438 { 1515 {
1439 write_ascstring (printcharfun, " . "); 1516 write_ascstring (printcharfun, " . ");
1440 print_internal (obj, printcharfun, escapeflag); 1517 print_internal (obj, printcharfun, escapeflag);
1441 } 1518 }
1519
1442 UNGCPRO; 1520 UNGCPRO;
1443 1521
1444 write_ascstring (printcharfun, ")"); 1522 write_ascstring (printcharfun, ")");
1445 return; 1523 return;
1446 } 1524 }
1636 } 1714 }
1637 write_fmt_string (printcharfun, 1715 write_fmt_string (printcharfun,
1638 "#<SERIOUS XEMACS BUG: %s Save your buffers immediately " 1716 "#<SERIOUS XEMACS BUG: %s Save your buffers immediately "
1639 "and please report this bug>", buf); 1717 "and please report this bug>", buf);
1640 } 1718 }
1641 1719
1720 /* Not static only because of print_preprocess_cons. */
1721 Elemcount print_preprocess_inchash_eq (Lisp_Object, Lisp_Object, Elemcount *);
1722
1723 Elemcount
1724 print_preprocess_inchash_eq (Lisp_Object obj, Lisp_Object table,
1725 Elemcount *seen_object_count)
1726 {
1727 htentry *hte = inchash_eq (obj, table, 1);
1728 Elemcount extracted;
1729
1730 /* If the hash table had to be resized, hte is NULL. */
1731 if (hte == NULL)
1732 {
1733 hte = find_htentry (obj, XHASH_TABLE (table));
1734 }
1735
1736 extracted = XINT (hte->value);
1737 if (1 == extracted)
1738 {
1739 *seen_object_count += 1;
1740 hte->value
1741 = make_int (1 | (*seen_object_count << PRINT_NUMBER_ORDINAL_SHIFT));
1742 }
1743 else if ((extracted & PRINT_NUMBER_SEEN_MASK) == PRINT_NUMBER_SEEN_MASK)
1744 {
1745 /* Avoid the number overflowing the bit field. */
1746 extracted = (extracted & ~PRINT_NUMBER_SEEN_MASK) | 2;
1747 hte->value = make_int (extracted);
1748 }
1749
1750 return extracted & PRINT_NUMBER_SEEN_MASK;
1751 }
1752
1753 /* Fill in Vprint_number_table according to the structure of OBJ. OBJ itself
1754 and all its elements will be added to Vprint_number_table recursively if
1755 its type has the print_preprocess method implemented. Objects with the
1756 print_preprocess method implemented include cons, vector, compiled
1757 function, hash table, char table, range table, and symbol. Symbol is an
1758 exceptional type in that it is impossible to construct a recursive symbol
1759 structure, but is here for the print-gensym feature. */
1760
1761 void
1762 print_preprocess (Lisp_Object object, Lisp_Object print_number_table,
1763 Elemcount *seen_object_count)
1764 {
1765 if (!LRECORDP (object) || !HAS_OBJECT_METH_P (object, print_preprocess))
1766 {
1767 return;
1768 }
1769
1770 if (SYMBOLP (object) && IN_OBARRAY (object))
1771 {
1772 /* Handle symbols specially. We do this here rather than in symbols.c
1773 because we don't want to have all the other print_preprocess methods
1774 worry about print_preprocess_inchash_eq. */
1775 return;
1776 }
1777
1778 if (print_preprocess_inchash_eq (object, print_number_table,
1779 seen_object_count) > 1)
1780 {
1781 return;
1782 }
1783
1784 OBJECT_METH (object, print_preprocess, (object, print_number_table,
1785 seen_object_count));
1786 }
1787
1788 typedef struct { Lisp_Object key; Elemcount count; } preprocess_sort_t;
1789
1790 static int
1791 print_seen_once (Lisp_Object UNUSED (key), Lisp_Object value,
1792 void * UNUSED (extra_arg))
1793 {
1794 return 1 == ((XINT (value) & PRINT_NUMBER_SEEN_MASK));
1795 }
1796
1797 static int
1798 print_nonsymbol_seen_once (Lisp_Object key, Lisp_Object value,
1799 void * UNUSED (extra_arg))
1800 {
1801 /* print_continuous_numbering is used for symbols, so we don't delete them
1802 from the print info hash table. It's less useful for other objects at
1803 the moment, though. */
1804 return !SYMBOLP (key) && (1 == ((XINT (value) & PRINT_NUMBER_SEEN_MASK)));
1805 }
1806
1807 static int
1808 print_sort_get_numbers (Lisp_Object key, Lisp_Object value, void *extra_arg)
1809 {
1810 preprocess_sort_t **preprocess_sort_ptr = (preprocess_sort_t **) extra_arg;
1811 preprocess_sort_t *preprocess_sort = *preprocess_sort_ptr;
1812
1813 *preprocess_sort_ptr += 1;
1814 preprocess_sort->key = key;
1815 preprocess_sort->count = XINT (value);
1816
1817 return 0;
1818 }
1819
1820 static int
1821 print_sort_compare_ordinals (const void *object1, const void *object2)
1822 {
1823 Elemcount a = ((preprocess_sort_t *) object1)->count
1824 & PRINT_NUMBER_ORDINAL_MASK;
1825 Elemcount b = ((preprocess_sort_t *) object2)->count
1826 & PRINT_NUMBER_ORDINAL_MASK;
1827
1828 return a - b;
1829 }
1830
1831 enum print_gensym_status
1832 {
1833 PRINT_GENSYM_DONE,
1834 PRINT_GENSYM_PRINT,
1835 PRINT_GENSYM_PRINT_AND_CLEANUP_TABLE,
1836 };
1837
1838 /* Check for any circular objects or repeated uninterned symbols.
1839
1840 If OBJ is a repeated structure (or symbol) and it has been printed
1841 already, print it now in the #%d# format, and return 1, to indicate
1842 print_internal is done.
1843
1844 If OBJ is a repeated structure and it has not yet been printed, print
1845 #%d= before the object, mark it as printed, and return zero, to indicate
1846 print_internal should continue as usual.
1847
1848 If OBJ is not a repeated structure, do nothing, and return zero, to
1849 indicate print_internal should continue as usual. */
1850 static enum print_gensym_status
1851 print_gensym_or_circle (Lisp_Object obj, Lisp_Object printcharfun)
1852 {
1853 Lisp_Object seen = Fgethash (obj, Vprint_number_table, Qnil);
1854 if (NILP (seen))
1855 {
1856 Elemcount old_print_number_index = print_number_index;
1857
1858 print_preprocess (obj, Vprint_number_table, &print_number_index);
1859
1860 if (old_print_number_index != print_number_index)
1861 {
1862 Elemcount new_print_number_index, ii;
1863
1864 /* We support up to 25 bits' worth of repeated objects, which is
1865 33 million or so, far more than we support in, say, a
1866 compiled-function constants vector. */
1867 assert (print_number_index <=
1868 (PRINT_NUMBER_ORDINAL_MASK >> PRINT_NUMBER_ORDINAL_SHIFT));
1869
1870 /* If any objects have been seen once and once only, remove them
1871 from Vprint_number_table. This is a bit of an arbitrary
1872 decision; we could keep them around for the sake of
1873 print_continuous_numbering, but there's the reasonable worry
1874 about Vprint_number_table getting awkwardly large. */
1875 elisp_map_remhash (print_continuous_numbering ?
1876 print_nonsymbol_seen_once : print_seen_once,
1877 Vprint_number_table, NULL);
1878
1879 new_print_number_index
1880 = XINT (Fhash_table_count (Vprint_number_table));
1881
1882 if (new_print_number_index != print_number_index
1883 && new_print_number_index != old_print_number_index)
1884 {
1885 preprocess_sort_t *preprocess_sort
1886 = alloca_array (preprocess_sort_t, new_print_number_index);
1887 preprocess_sort_t *preprocess_sort_ptr = preprocess_sort;
1888
1889 /* There are new objects in Vprint_number_table, but their
1890 ordinal values don't necessarily represent the order they
1891 were seen in, there will be gaps corresponding to the
1892 non-symbols that were seen only once. Correct this. */
1893 elisp_maphash_unsafe (print_sort_get_numbers, Vprint_number_table,
1894 &preprocess_sort_ptr);
1895
1896 qsort (preprocess_sort, new_print_number_index,
1897 sizeof (preprocess_sort_t), print_sort_compare_ordinals);
1898
1899 for (ii = old_print_number_index;
1900 ii < new_print_number_index;
1901 ii++)
1902 {
1903 Fputhash (preprocess_sort[ii].key,
1904 make_int ((preprocess_sort[ii].count
1905 & ~PRINT_NUMBER_ORDINAL_MASK)
1906 | ((ii + 1)
1907 << PRINT_NUMBER_ORDINAL_SHIFT)),
1908 Vprint_number_table);
1909 }
1910 }
1911
1912 print_number_index = new_print_number_index;
1913
1914 /* The new objects may include OBJ; update SEEN to reflect
1915 this. */
1916 seen = Fgethash (obj, Vprint_number_table, Qnil);
1917 if (INTP (seen))
1918 {
1919 goto prefix_this;
1920 }
1921 }
1922 }
1923 else
1924 {
1925 prefix_this:
1926 if ((XINT (seen) & PRINT_NUMBER_SEEN_MASK) == 1
1927 && !(print_continuous_numbering && SYMBOLP (obj)))
1928 {
1929 return PRINT_GENSYM_PRINT_AND_CLEANUP_TABLE;
1930 }
1931 else if (XINT (seen) & PRINT_NUMBER_PRINTED_MASK)
1932 {
1933 write_fmt_string (printcharfun, "#%d#",
1934 (XINT (seen) & PRINT_NUMBER_ORDINAL_MASK)
1935 >> PRINT_NUMBER_ORDINAL_SHIFT);
1936
1937 /* We're finished printing this object. */
1938 return PRINT_GENSYM_DONE;
1939 }
1940 else
1941 {
1942 write_fmt_string (printcharfun, "#%d=",
1943 (XINT (seen) & PRINT_NUMBER_ORDINAL_MASK)
1944 >> PRINT_NUMBER_ORDINAL_SHIFT);
1945
1946 /* We set PRINT_NUMBER_PRINTED_MASK immediately here, so the
1947 object itself is written as #%d# when printing its contents. */
1948 Fputhash (obj, make_int (XINT (seen) | PRINT_NUMBER_PRINTED_MASK),
1949 Vprint_number_table);
1950
1951 /* This is the first time the object has been seen while
1952 printing the recursive object; we still have to go ahead
1953 and do the actual print. */
1954 }
1955 }
1956
1957 return PRINT_GENSYM_PRINT;
1958 }
1959
1960 Lisp_Object
1961 nsubst_structures_descend (Lisp_Object new_, Lisp_Object old,
1962 Lisp_Object tree,
1963 Lisp_Object number_table, Boolint test_not_unboundp)
1964 {
1965 Lisp_Object seen;
1966
1967 if (!LRECORDP (tree) || !HAS_OBJECT_METH_P (tree, nsubst_structures_descend))
1968 {
1969 return tree;
1970 }
1971
1972 seen = Fgethash (tree, number_table, Qnil);
1973
1974 if (INTP (seen))
1975 {
1976 if (XINT (seen) & PRINT_NUMBER_PRINTED_MASK)
1977 {
1978 return tree;
1979 }
1980
1981 Fputhash (tree, make_int (XINT (seen) | PRINT_NUMBER_PRINTED_MASK),
1982 number_table);
1983 }
1984
1985 OBJECT_METH (tree, nsubst_structures_descend,
1986 (new_, old, tree, number_table, test_not_unboundp));
1987
1988 return tree;
1989 }
1990
1991 /* Descend TREE, replacing the Lisp object OLD each time it is encountered
1992 with the Lisp object NEW_. TREE can be recursive or circular, and this is
1993 handled correctly. */
1994 Lisp_Object
1995 nsubst_structures (Lisp_Object new_, Lisp_Object old, Lisp_Object tree,
1996 check_test_func_t check_test, Boolint test_not_unboundp,
1997 Lisp_Object UNUSED (test), Lisp_Object UNUSED (key))
1998 {
1999 Lisp_Object number_table, result;
2000 Elemcount ordinal = 0;
2001 struct gcpro gcpro1;
2002
2003 if (check_test != check_eq_nokey || !LRECORDP (old))
2004 {
2005 signal_error (Qunimplemented,
2006 ":descend-structures not yet finished, nsubst",
2007 Qunbound);
2008 }
2009
2010 if (!LRECORDP (tree) || !HAS_OBJECT_METH_P (tree, nsubst_structures_descend))
2011 {
2012 return tree;
2013 }
2014
2015 number_table = make_lisp_hash_table (16, HASH_TABLE_NON_WEAK, Qeq);
2016 GCPRO1 (number_table);
2017
2018 print_preprocess (tree, number_table, &ordinal);
2019
2020 /* This function can GC by means of the hash table test functions, when
2021 replacing hash table entries. */
2022 result = nsubst_structures_descend (new_, old, tree, number_table,
2023 test_not_unboundp);
2024 Fclrhash (number_table);
2025
2026 RETURN_UNGCPRO (result);
2027 }
2028
1642 void 2029 void
1643 print_internal (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) 2030 print_internal (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
1644 { 2031 {
1645 /* This function can GC */ 2032 /* This function can GC */
1646 int specdepth = 0; 2033 int specdepth = 0;
1647 struct gcpro gcpro1, gcpro2; 2034 struct gcpro gcpro1, gcpro2;
2035 Boolint cleanup_table = 0;
1648 2036
1649 QUIT; 2037 QUIT;
1650 2038
1651 #ifdef NO_PRINT_DURING_GC 2039 #ifdef NO_PRINT_DURING_GC
1652 /* Emacs won't print while GCing, but an external debugger might */ 2040 /* Emacs won't print while GCing, but an external debugger might */
1681 debug_prin1. In that case, we have bound print_depth to 0 anyway. */ 2069 debug_prin1. In that case, we have bound print_depth to 0 anyway. */
1682 if (!inhibit_non_essential_conversion_operations) 2070 if (!inhibit_non_essential_conversion_operations)
1683 { 2071 {
1684 specdepth = internal_bind_int (&print_depth, print_depth + 1); 2072 specdepth = internal_bind_int (&print_depth, print_depth + 1);
1685 2073
1686 if (print_depth > PRINT_CIRCLE) 2074 if (print_depth > PRINT_CIRCLE_LIMIT)
1687 signal_error (Qstack_overflow, 2075 {
1688 "Apparently circular structure being printed", Qunbound); 2076 signal_error (Qstack_overflow,
2077 "Apparently circular structure being printed",
2078 Qunbound);
2079 }
1689 } 2080 }
1690 2081
1691 switch (XTYPE (obj)) 2082 switch (XTYPE (obj))
1692 { 2083 {
1693 case Lisp_Type_Int_Even: 2084 case Lisp_Type_Int_Even:
1886 } 2277 }
1887 #endif /* not NEW_GC */ 2278 #endif /* not NEW_GC */
1888 } 2279 }
1889 } 2280 }
1890 2281
1891 /* Detect circularities and truncate them. 2282 if (LRECORDP (obj) &&
1892 No need to offer any alternative--this is better than an error. */ 2283 ((print_circle && HAS_OBJECT_METH_P (obj, print_preprocess)) ||
1893 if (CONSP (obj) || VECTORP (obj) || COMPILED_FUNCTIONP (obj)) 2284 (print_gensym && SYMBOLP (obj) && !IN_OBARRAY (obj))))
1894 { 2285 {
2286 enum print_gensym_status status
2287 = print_gensym_or_circle (obj, printcharfun);
2288
2289 cleanup_table = (PRINT_GENSYM_PRINT_AND_CLEANUP_TABLE == status);
2290
2291 if (PRINT_GENSYM_DONE == status)
2292 {
2293 break;
2294 }
2295 }
2296 else if (!print_circle &&
2297 /* Could this structure be recursive? */
2298 LRECORDP (obj)
2299 && HAS_OBJECT_METH_P (obj, nsubst_structures_descend))
2300 {
1895 int i; 2301 int i;
1896 for (i = 0; i < print_depth - 1; i++) 2302 for (i = 0; i < print_depth - 1; i++)
1897 if (EQ (obj, being_printed[i])) 2303 if (EQ (obj, being_printed[i]))
1898 { 2304 {
1899 Ascbyte buf[DECIMAL_PRINT_SIZE (long) + 1]; 2305 Ascbyte buf[DECIMAL_PRINT_SIZE (long) + 1];
1935 BADNESS_INTEGER_OBJECT); 2341 BADNESS_INTEGER_OBJECT);
1936 break; 2342 break;
1937 } 2343 }
1938 } 2344 }
1939 2345
2346 if (cleanup_table)
2347 {
2348 /* If any objects have been seen once and once only, remove them from
2349 Vprint_number_table. This is a bit of an arbitrary decision; we
2350 could keep them around for the sake of print_continuous_numbering,
2351 but there's the reasonable worry about Vprint_number_table getting
2352 awkwardly large. */
2353 elisp_map_remhash (print_continuous_numbering ?
2354 print_nonsymbol_seen_once : print_seen_once,
2355 Vprint_number_table, NULL);
2356
2357 }
2358
1940 if (!inhibit_non_essential_conversion_operations) 2359 if (!inhibit_non_essential_conversion_operations)
1941 unbind_to (specdepth); 2360 unbind_to (specdepth);
1942 UNGCPRO; 2361 UNGCPRO;
1943 } 2362 }
1944 2363
1966 { 2385 {
1967 /* This deals with GC-relocation */ 2386 /* This deals with GC-relocation */
1968 output_string (printcharfun, 0, name, 0, size); 2387 output_string (printcharfun, 0, name, 0, size);
1969 return; 2388 return;
1970 } 2389 }
2390
1971 GCPRO2 (obj, printcharfun); 2391 GCPRO2 (obj, printcharfun);
1972 2392
1973 /* If we print an uninterned symbol as part of a complex object and 2393 if (print_gensym)
1974 the flag print-gensym is non-nil, prefix it with #n= to read the 2394 {
1975 object back with the #n# reader syntax later if needed. */ 2395 if (!IN_OBARRAY (obj))
1976 if (!NILP (Vprint_gensym) 2396 {
1977 /* #### Test whether this produces a noticeable slow-down for 2397 write_ascstring (printcharfun, "#:");
1978 printing when print-gensym is non-nil. */ 2398 }
1979 && !EQ (obj, oblookup (Vobarray,
1980 XSTRING_DATA (symbol_name (XSYMBOL (obj))),
1981 XSTRING_LENGTH (symbol_name (XSYMBOL (obj))))))
1982 {
1983 if (print_depth > 1)
1984 {
1985 Lisp_Object tem = Fassq (obj, Vprint_gensym_alist);
1986 if (CONSP (tem))
1987 {
1988 write_ascstring (printcharfun, "#");
1989 print_internal (XCDR (tem), printcharfun, escapeflag);
1990 write_ascstring (printcharfun, "#");
1991 UNGCPRO;
1992 return;
1993 }
1994 else
1995 {
1996 if (CONSP (Vprint_gensym_alist))
1997 {
1998 /* Vprint_gensym_alist is exposed to Lisp, so we
1999 have to be careful. */
2000 CHECK_CONS (XCAR (Vprint_gensym_alist));
2001 CHECK_INT (XCDR (XCAR (Vprint_gensym_alist)));
2002 tem = make_int (XINT (XCDR (XCAR (Vprint_gensym_alist))) + 1);
2003 }
2004 else
2005 tem = make_int (1);
2006 Vprint_gensym_alist = Fcons (Fcons (obj, tem), Vprint_gensym_alist);
2007
2008 write_ascstring (printcharfun, "#");
2009 print_internal (tem, printcharfun, escapeflag);
2010 write_ascstring (printcharfun, "=");
2011 }
2012 }
2013 write_ascstring (printcharfun, "#:");
2014 } 2399 }
2015 2400
2016 /* Does it look like an integer or a float? */ 2401 /* Does it look like an integer or a float? */
2017 { 2402 {
2018 Ibyte *data = XSTRING_DATA (name); 2403 Ibyte *data = XSTRING_DATA (name);
2686 lists of the form (quote object) will be written as the equivalent 'object. 3071 lists of the form (quote object) will be written as the equivalent 'object.
2687 Do not SET this variable; bind it instead. 3072 Do not SET this variable; bind it instead.
2688 */ ); 3073 */ );
2689 print_readably = 0; 3074 print_readably = 0;
2690 3075
2691 /* #### I think this should default to t. But we'd better wait 3076 DEFVAR_BOOL ("print-gensym", &print_gensym /*
2692 until we see that it works out. */
2693 DEFVAR_LISP ("print-gensym", &Vprint_gensym /*
2694 If non-nil, then uninterned symbols will be printed specially. 3077 If non-nil, then uninterned symbols will be printed specially.
2695 Uninterned symbols are those which are not present in `obarray', that is, 3078 Uninterned symbols are those which are not present in `obarray', that is,
2696 those which were made with `make-symbol' or by calling `intern' with a 3079 those which were made with `make-symbol' or by calling `intern' with a
2697 second argument. 3080 second argument.
2698 3081
2701 and returning an existing one. Beware: the #: syntax creates a new 3084 and returning an existing one. Beware: the #: syntax creates a new
2702 symbol each time it is seen, so if you print an object which contains 3085 symbol each time it is seen, so if you print an object which contains
2703 two pointers to the same uninterned symbol, `read' will not duplicate 3086 two pointers to the same uninterned symbol, `read' will not duplicate
2704 that structure. 3087 that structure.
2705 3088
2706 If the value of `print-gensym' is a cons cell, then in addition 3089 If the value of `print-continuous-numbering' is non-nil, the table used by
2707 refrain from clearing `print-gensym-alist' on entry to and exit from 3090 `print-gensym' and `print-circle' (which see) will not be reset on entry to
2708 printing functions, so that the use of #...# and #...= can carry over 3091 and exit from printing functions, so that the use of #...# and #...= can
2709 for several separately printed objects. 3092 carry over for several separately printed objects.
2710 */ ); 3093 */ );
2711 Vprint_gensym = Qnil; 3094 print_gensym = 1;
2712 3095
2713 DEFVAR_LISP ("print-gensym-alist", &Vprint_gensym_alist /* 3096 DEFVAR_BOOL ("print-circle", &print_circle /*
2714 Association list of elements (GENSYM . N) to guide use of #N# and #N=. 3097 Non-nil means print recursive structures using #N= and #N# syntax.
2715 In each element, GENSYM is an uninterned symbol that has been associated 3098
2716 with #N= for the specified value of N. 3099 If nil, XEmacs detects recursive structures and truncates them in an
2717 */ ); 3100 unreadable fashion.
2718 Vprint_gensym_alist = Qnil; 3101
3102 If non-nil, shared substructures anywhere in the structure are printed
3103 with `#N=' before the first occurrence (in the order of the print
3104 representation) and `#N#' in place of each subsequent occurrence,
3105 where N is a positive decimal integer.
3106
3107 If the value of `print-continuous-numbering' is non-nil, the table used by
3108 `print-gensym' (which see) and `print-circle' will not be reset on entry to
3109 and exit from printing functions, so that the use of #...# and #...= can
3110 carry over for several separately printed objects.
3111 */);
3112 print_circle = 0;
3113
3114 DEFVAR_BOOL_MAGIC ("print-continuous-numbering",
3115 &print_continuous_numbering /*
3116 Non-nil means number continuously across print calls, mostly for symbols.
3117 This affects the numbers printed for #N= labels and #M# references.
3118 See also `print-circle' and `print-gensym'.
3119 This variable should not be set with `setq'; bind it with a `let' instead.
3120 */ ,
3121 print_continuous_numbering_changed);
3122 print_continuous_numbering = 0;
3123
3124 staticpro (&Vprint_number_table);
3125 Vprint_number_table = make_lisp_hash_table (16, HASH_TABLE_KEY_WEAK, Qeq);
2719 3126
2720 DEFVAR_LISP ("print-message-label", &Vprint_message_label /* 3127 DEFVAR_LISP ("print-message-label", &Vprint_message_label /*
2721 Label for minibuffer messages created with `print'. This should 3128 Label for minibuffer messages created with `print'. This should
2722 generally be bound with `let' rather than set. (See `display-message'.) 3129 generally be bound with `let' rather than set. (See `display-message'.)
2723 */ ); 3130 */ );