summaryrefslogtreecommitdiff
path: root/src/print.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/print.c')
-rw-r--r--src/print.c128
1 files changed, 70 insertions, 58 deletions
diff --git a/src/print.c b/src/print.c
index 26ed52b4653..76c577ec800 100644
--- a/src/print.c
+++ b/src/print.c
@@ -87,7 +87,7 @@ static struct print_buffer print_buffer;
print_number_index holds the largest N already used.
N has to be strictly larger than 0 since we need to distinguish -N. */
static ptrdiff_t print_number_index;
-static void print_interval (INTERVAL interval, Lisp_Object printcharfun);
+static void print_interval (INTERVAL interval, void *pprintcharfun);
/* GDB resets this to zero on W32 to disable OutputDebugString calls. */
bool print_output_debug_flag EXTERNALLY_VISIBLE = 1;
@@ -1285,15 +1285,9 @@ print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
{ /* Remove unnecessary objects, which appear only once in OBJ;
that is, whose status is Qt. */
struct Lisp_Hash_Table *h = XHASH_TABLE (Vprint_number_table);
- ptrdiff_t i;
-
- for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
- {
- Lisp_Object key = HASH_KEY (h, i);
- if (!BASE_EQ (key, Qunbound)
- && EQ (HASH_VALUE (h, i), Qt))
- Fremhash (key, Vprint_number_table);
- }
+ DOHASH (h, k, v)
+ if (EQ (v, Qt))
+ Fremhash (k, Vprint_number_table);
}
}
@@ -1397,6 +1391,9 @@ static void
print_preprocess (Lisp_Object obj)
{
eassert (!NILP (Vprint_circle));
+ /* The ppstack may contain HASH_UNUSED_ENTRY_KEY which is an invalid
+ Lisp value. Make sure that our filter stops us from traversing it. */
+ eassert (!PRINT_CIRCLE_CANDIDATE_P (HASH_UNUSED_ENTRY_KEY));
ptrdiff_t base_sp = ppstack.sp;
for (;;)
@@ -1415,7 +1412,7 @@ print_preprocess (Lisp_Object obj)
&& SYMBOLP (obj)
&& !SYMBOL_INTERNED_P (obj)))
{ /* OBJ appears more than once. Let's remember that. */
- if (!FIXNUMP (num))
+ if (SYMBOLP (num)) /* In practice, nil or t. */
{
print_number_index++;
/* Negative number indicates it hasn't been printed yet. */
@@ -1455,8 +1452,10 @@ print_preprocess (Lisp_Object obj)
if (HASH_TABLE_P (obj))
{
struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
- obj = h->key_and_value;
- continue;
+ /* The values pushed here may include
+ HASH_UNUSED_ENTRY_KEY; see top of this function. */
+ pp_stack_push_values (h->key_and_value,
+ 2 * h->table_size);
}
break;
}
@@ -1493,8 +1492,6 @@ print_preprocess_string (INTERVAL interval, void *arg)
print_preprocess (interval->plist);
}
-static void print_check_string_charset_prop (INTERVAL interval, Lisp_Object string);
-
#define PRINT_STRING_NON_CHARSET_FOUND 1
#define PRINT_STRING_UNSAFE_CHARSET_FOUND 2
@@ -1502,7 +1499,7 @@ static void print_check_string_charset_prop (INTERVAL interval, Lisp_Object stri
static int print_check_string_result;
static void
-print_check_string_charset_prop (INTERVAL interval, Lisp_Object string)
+print_check_string_charset_prop (INTERVAL interval, void *pstring)
{
Lisp_Object val;
@@ -1526,6 +1523,7 @@ print_check_string_charset_prop (INTERVAL interval, Lisp_Object string)
if (! (print_check_string_result & PRINT_STRING_UNSAFE_CHARSET_FOUND))
{
ptrdiff_t charpos = interval->position;
+ Lisp_Object string = *(Lisp_Object *)pstring;
ptrdiff_t bytepos = string_char_to_byte (string, charpos);
Lisp_Object charset = XCAR (XCDR (val));
@@ -1550,7 +1548,7 @@ print_prune_string_charset (Lisp_Object string)
{
print_check_string_result = 0;
traverse_intervals (string_intervals (string), 0,
- print_check_string_charset_prop, string);
+ print_check_string_charset_prop, &string);
if (NILP (Vprint_charset_text_property)
|| ! (print_check_string_result & PRINT_STRING_UNSAFE_CHARSET_FOUND))
{
@@ -2080,6 +2078,16 @@ print_vectorlike_unreadable (Lisp_Object obj, Lisp_Object printcharfun,
}
return;
+ case PVEC_OBARRAY:
+ {
+ struct Lisp_Obarray *o = XOBARRAY (obj);
+ /* FIXME: Would it make sense to print the actual symbols (up to
+ a limit)? */
+ int i = sprintf (buf, "#<obarray n=%u>", o->count);
+ strout (buf, i, i, printcharfun);
+ return;
+ }
+
/* Types handled earlier. */
case PVEC_NORMAL_VECTOR:
case PVEC_RECORD:
@@ -2267,6 +2275,11 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
goto next_obj;
}
}
+ else if (STRINGP (num))
+ {
+ strout (SSDATA (num), SCHARS (num), SBYTES (num), printcharfun);
+ goto next_obj;
+ }
}
print_depth++;
@@ -2401,8 +2414,9 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
if (string_intervals (obj))
{
+ Lisp_Object pcf = printcharfun;
traverse_intervals (string_intervals (obj),
- 0, print_interval, printcharfun);
+ 0, print_interval, &pcf);
printchar (')', printcharfun);
}
}
@@ -2555,11 +2569,6 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
goto next_obj;
case PVEC_SUB_CHAR_TABLE:
{
- /* Make each lowest sub_char_table start a new line.
- Otherwise we'll make a line extremely long, which
- results in slow redisplay. */
- if (XSUB_CHAR_TABLE (obj)->depth == 3)
- printchar ('\n', printcharfun);
print_c_string ("#^^[", printcharfun);
int n = sprintf (buf, "%d %d",
XSUB_CHAR_TABLE (obj)->depth,
@@ -2574,50 +2583,49 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
{
struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
/* Implement a readable output, e.g.:
- #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */
- /* Always print the size. */
- int len = sprintf (buf, "#s(hash-table size %"pD"d",
- HASH_TABLE_SIZE (h));
- strout (buf, len, len, printcharfun);
+ #s(hash-table test equal data (k1 v1 k2 v2)) */
+ print_c_string ("#s(hash-table", printcharfun);
- if (!NILP (h->test.name))
+ if (!BASE_EQ (h->test->name, Qeql))
{
print_c_string (" test ", printcharfun);
- print_object (h->test.name, printcharfun, escapeflag);
+ print_object (h->test->name, printcharfun, escapeflag);
}
- if (!NILP (h->weak))
+ if (h->weakness != Weak_None)
{
print_c_string (" weakness ", printcharfun);
- print_object (h->weak, printcharfun, escapeflag);
+ print_object (hash_table_weakness_symbol (h->weakness),
+ printcharfun, escapeflag);
}
- print_c_string (" rehash-size ", printcharfun);
- print_object (Fhash_table_rehash_size (obj),
- printcharfun, escapeflag);
-
- print_c_string (" rehash-threshold ", printcharfun);
- print_object (Fhash_table_rehash_threshold (obj),
- printcharfun, escapeflag);
-
if (h->purecopy)
print_c_string (" purecopy t", printcharfun);
- print_c_string (" data (", printcharfun);
-
ptrdiff_t size = h->count;
- /* Don't print more elements than the specified maximum. */
- if (FIXNATP (Vprint_length) && XFIXNAT (Vprint_length) < size)
- size = XFIXNAT (Vprint_length);
-
- print_stack_push ((struct print_stack_entry){
- .type = PE_hash,
- .u.hash.obj = obj,
- .u.hash.nobjs = size * 2,
- .u.hash.idx = 0,
- .u.hash.printed = 0,
- .u.hash.truncated = (size < h->count),
- });
+ if (size > 0)
+ {
+ print_c_string (" data (", printcharfun);
+
+ /* Don't print more elements than the specified maximum. */
+ if (FIXNATP (Vprint_length) && XFIXNAT (Vprint_length) < size)
+ size = XFIXNAT (Vprint_length);
+
+ print_stack_push ((struct print_stack_entry){
+ .type = PE_hash,
+ .u.hash.obj = obj,
+ .u.hash.nobjs = size * 2,
+ .u.hash.idx = 0,
+ .u.hash.printed = 0,
+ .u.hash.truncated = (size < h->count),
+ });
+ }
+ else
+ {
+ /* Empty table: we can omit the data entirely. */
+ printchar (')', printcharfun);
+ --print_depth; /* Done with this. */
+ }
goto next_obj;
}
@@ -2666,7 +2674,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
/* With the print-circle feature. */
Lisp_Object num = Fgethash (next, Vprint_number_table,
Qnil);
- if (FIXNUMP (num))
+ if (!(NILP (num) || EQ (num, Qt)))
{
print_c_string (" . ", printcharfun);
obj = next;
@@ -2770,7 +2778,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
{
Lisp_Object key;
ptrdiff_t idx = e->u.hash.idx;
- while (BASE_EQ ((key = HASH_KEY (h, idx)), Qunbound))
+ while (hash_unused_entry_key_p ((key = HASH_KEY (h, idx))))
idx++;
e->u.hash.idx = idx;
obj = key;
@@ -2793,10 +2801,11 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
This is part of printing a string that has text properties. */
static void
-print_interval (INTERVAL interval, Lisp_Object printcharfun)
+print_interval (INTERVAL interval, void *pprintcharfun)
{
if (NILP (interval->plist))
return;
+ Lisp_Object printcharfun = *(Lisp_Object *)pprintcharfun;
printchar (' ', printcharfun);
print_object (make_fixnum (interval->position), printcharfun, 1);
printchar (' ', printcharfun);
@@ -2929,7 +2938,10 @@ This variable should not be set with `setq'; bind it with a `let' instead. */);
DEFVAR_LISP ("print-number-table", Vprint_number_table,
doc: /* A vector used internally to produce `#N=' labels and `#N#' references.
The Lisp printer uses this vector to detect Lisp objects referenced more
-than once.
+than once. If an entry contains a number, then the corresponding key is
+referenced more than once: a positive sign indicates that it's already been
+printed, and the absolute value indicates the number to use when printing.
+If an entry contains a string, that string is printed instead.
When you bind `print-continuous-numbering' to t, you should probably
also bind `print-number-table' to nil. This ensures that the value of