mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-25 07:28:20 +00:00
* src/print.c (print, print_preprocess, print_object): Use a hash table
rather than a linear table for Vprint_number_table.
This commit is contained in:
parent
7d50c95105
commit
a65b85b5f0
@ -1,3 +1,8 @@
|
||||
2010-12-22 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* print.c (print, print_preprocess, print_object): Use a hash table
|
||||
rather than a linear table for Vprint_number_table.
|
||||
|
||||
2010-12-20 Chong Yidong <cyd@stupidchicken.com>
|
||||
|
||||
* frame.c (focus_follows_mouse): Default to 0 (Bug#7269).
|
||||
|
169
src/print.c
169
src/print.c
@ -145,12 +145,14 @@ Lisp_Object Vprint_circle;
|
||||
|
||||
Lisp_Object Vprint_continuous_numbering;
|
||||
|
||||
/* Vprint_number_table is a vector like [OBJ1 STAT1 OBJ2 STAT2 ...],
|
||||
where OBJn are objects going to be printed, and STATn are their status,
|
||||
which may be different meanings during process. See the comments of
|
||||
the functions print and print_preprocess for details.
|
||||
print_number_index keeps the last position the next object should be added,
|
||||
twice of which is the actual vector position in Vprint_number_table. */
|
||||
/* Vprint_number_table is a table, that keeps objects that are going to
|
||||
be printed, to allow use of #n= and #n# to express sharing.
|
||||
For any given object, the table can give the following values:
|
||||
t the object will be printed only once.
|
||||
-N the object will be printed several times and will take number N.
|
||||
N the object has been printed so we can refer to it as #N#.
|
||||
print_number_index holds the largest N already used.
|
||||
N has to be striclty larger than 0 since we need to distinguish -N. */
|
||||
int print_number_index;
|
||||
Lisp_Object Vprint_number_table;
|
||||
|
||||
@ -1226,33 +1228,24 @@ print (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag)
|
||||
/* Construct Vprint_number_table for print-gensym and print-circle. */
|
||||
if (!NILP (Vprint_gensym) || !NILP (Vprint_circle))
|
||||
{
|
||||
int i, start, index;
|
||||
start = index = print_number_index;
|
||||
/* Construct Vprint_number_table.
|
||||
This increments print_number_index for the objects added. */
|
||||
print_depth = 0;
|
||||
print_preprocess (obj);
|
||||
|
||||
/* Remove unnecessary objects, which appear only once in OBJ;
|
||||
that is, whose status is Qnil. Compactify the necessary objects. */
|
||||
for (i = start; i < print_number_index; i++)
|
||||
if (!NILP (PRINT_NUMBER_STATUS (Vprint_number_table, i)))
|
||||
{
|
||||
PRINT_NUMBER_OBJECT (Vprint_number_table, index)
|
||||
= PRINT_NUMBER_OBJECT (Vprint_number_table, i);
|
||||
index++;
|
||||
}
|
||||
if (HASH_TABLE_P (Vprint_number_table))
|
||||
{ /* Remove unnecessary objects, which appear only once in OBJ;
|
||||
that is, whose status is Qt.
|
||||
Maybe a better way to do that is to copy elements to
|
||||
a new hash table. */
|
||||
struct Lisp_Hash_Table *h = XHASH_TABLE (Vprint_number_table);
|
||||
int i;
|
||||
|
||||
/* Clear out objects outside the active part of the table. */
|
||||
for (i = index; i < print_number_index; i++)
|
||||
PRINT_NUMBER_OBJECT (Vprint_number_table, i) = Qnil;
|
||||
|
||||
/* Reset the status field for the next print step. Now this
|
||||
field means whether the object has already been printed. */
|
||||
for (i = start; i < print_number_index; i++)
|
||||
PRINT_NUMBER_STATUS (Vprint_number_table, i) = Qnil;
|
||||
|
||||
print_number_index = index;
|
||||
for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
|
||||
if (!NILP (HASH_HASH (h, i))
|
||||
&& EQ (HASH_VALUE (h, i), Qt))
|
||||
Fremhash (HASH_KEY (h, i), Vprint_number_table);
|
||||
}
|
||||
}
|
||||
|
||||
print_depth = 0;
|
||||
@ -1300,48 +1293,40 @@ print_preprocess (Lisp_Object obj)
|
||||
&& SYMBOLP (obj)
|
||||
&& !SYMBOL_INTERNED_P (obj)))
|
||||
{
|
||||
if (!HASH_TABLE_P (Vprint_number_table))
|
||||
{
|
||||
Lisp_Object args[2];
|
||||
args[0] = QCtest;
|
||||
args[1] = Qeq;
|
||||
Vprint_number_table = Fmake_hash_table (2, args);
|
||||
}
|
||||
|
||||
/* In case print-circle is nil and print-gensym is t,
|
||||
add OBJ to Vprint_number_table only when OBJ is a symbol. */
|
||||
if (! NILP (Vprint_circle) || SYMBOLP (obj))
|
||||
{
|
||||
for (i = 0; i < print_number_index; i++)
|
||||
if (EQ (PRINT_NUMBER_OBJECT (Vprint_number_table, i), obj))
|
||||
{
|
||||
/* OBJ appears more than once. Let's remember that. */
|
||||
PRINT_NUMBER_STATUS (Vprint_number_table, i) = Qt;
|
||||
print_depth--;
|
||||
return;
|
||||
}
|
||||
|
||||
/* OBJ is not yet recorded. Let's add to the table. */
|
||||
if (print_number_index == 0)
|
||||
{
|
||||
/* Initialize the table. */
|
||||
Vprint_number_table = Fmake_vector (make_number (40), Qnil);
|
||||
}
|
||||
else if (XVECTOR (Vprint_number_table)->size == print_number_index * 2)
|
||||
{
|
||||
/* Reallocate the table. */
|
||||
int i = print_number_index * 4;
|
||||
Lisp_Object old_table = Vprint_number_table;
|
||||
Vprint_number_table = Fmake_vector (make_number (i), Qnil);
|
||||
for (i = 0; i < print_number_index; i++)
|
||||
Lisp_Object num = Fgethash (obj, Vprint_number_table, Qnil);
|
||||
if (!NILP (num)
|
||||
/* If Vprint_continuous_numbering is non-nil and OBJ is a gensym,
|
||||
always print the gensym with a number. This is a special for
|
||||
the lisp function byte-compile-output-docform. */
|
||||
|| (!NILP (Vprint_continuous_numbering)
|
||||
&& SYMBOLP (obj)
|
||||
&& !SYMBOL_INTERNED_P (obj)))
|
||||
{ /* OBJ appears more than once. Let's remember that. */
|
||||
if (EQ (Qt, num))
|
||||
{
|
||||
PRINT_NUMBER_OBJECT (Vprint_number_table, i)
|
||||
= PRINT_NUMBER_OBJECT (old_table, i);
|
||||
PRINT_NUMBER_STATUS (Vprint_number_table, i)
|
||||
= PRINT_NUMBER_STATUS (old_table, i);
|
||||
print_number_index++;
|
||||
/* Negative number indicates it hasn't been printed yet. */
|
||||
Fputhash (obj, make_number (- print_number_index),
|
||||
Vprint_number_table);
|
||||
}
|
||||
print_depth--;
|
||||
return;
|
||||
}
|
||||
PRINT_NUMBER_OBJECT (Vprint_number_table, print_number_index) = obj;
|
||||
/* If Vprint_continuous_numbering is non-nil and OBJ is a gensym,
|
||||
always print the gensym with a number. This is a special for
|
||||
the lisp function byte-compile-output-docform. */
|
||||
if (!NILP (Vprint_continuous_numbering)
|
||||
&& SYMBOLP (obj)
|
||||
&& !SYMBOL_INTERNED_P (obj))
|
||||
PRINT_NUMBER_STATUS (Vprint_number_table, print_number_index) = Qt;
|
||||
print_number_index++;
|
||||
else
|
||||
/* OBJ is not yet recorded. Let's add to the table. */
|
||||
Fputhash (obj, Qt, Vprint_number_table);
|
||||
}
|
||||
|
||||
switch (XTYPE (obj))
|
||||
@ -1372,8 +1357,8 @@ print_preprocess (Lisp_Object obj)
|
||||
print_preprocess (XVECTOR (obj)->contents[i]);
|
||||
if (HASH_TABLE_P (obj))
|
||||
{ /* For hash tables, the key_and_value slot is past
|
||||
`size' because it needs to be marked specially in case
|
||||
the table is weak. */
|
||||
`size' because it needs to be marked specially in case
|
||||
the table is weak. */
|
||||
struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
|
||||
print_preprocess (h->key_and_value);
|
||||
}
|
||||
@ -1510,28 +1495,26 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
|
||||
else
|
||||
{
|
||||
/* With the print-circle feature. */
|
||||
int i;
|
||||
for (i = 0; i < print_number_index; i++)
|
||||
if (EQ (PRINT_NUMBER_OBJECT (Vprint_number_table, i), obj))
|
||||
{
|
||||
if (NILP (PRINT_NUMBER_STATUS (Vprint_number_table, i)))
|
||||
{
|
||||
/* Add a prefix #n= if OBJ has not yet been printed;
|
||||
that is, its status field is nil. */
|
||||
sprintf (buf, "#%d=", i + 1);
|
||||
strout (buf, -1, -1, printcharfun, 0);
|
||||
/* OBJ is going to be printed. Set the status to t. */
|
||||
PRINT_NUMBER_STATUS (Vprint_number_table, i) = Qt;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just print #n# if OBJ has already been printed. */
|
||||
sprintf (buf, "#%d#", i + 1);
|
||||
strout (buf, -1, -1, printcharfun, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Lisp_Object num = Fgethash (obj, Vprint_number_table, Qnil);
|
||||
if (INTEGERP (num))
|
||||
{
|
||||
int n = XINT (num);
|
||||
if (n < 0)
|
||||
{ /* Add a prefix #n= if OBJ has not yet been printed;
|
||||
that is, its status field is nil. */
|
||||
sprintf (buf, "#%d=", -n);
|
||||
strout (buf, -1, -1, printcharfun, 0);
|
||||
/* OBJ is going to be printed. Remember that fact. */
|
||||
Fputhash (obj, make_number (- n), Vprint_number_table);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just print #n# if OBJ has already been printed. */
|
||||
sprintf (buf, "#%d#", n);
|
||||
strout (buf, -1, -1, printcharfun, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1834,21 +1817,11 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
|
||||
/* With the print-circle feature. */
|
||||
if (i != 0)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < print_number_index; i++)
|
||||
if (EQ (PRINT_NUMBER_OBJECT (Vprint_number_table, i),
|
||||
obj))
|
||||
{
|
||||
if (NILP (PRINT_NUMBER_STATUS (Vprint_number_table, i)))
|
||||
Lisp_Object num = Fgethash (obj, Vprint_number_table, Qnil);
|
||||
if (INTEGERP (num))
|
||||
{
|
||||
strout (" . ", 3, 3, printcharfun, 0);
|
||||
print_object (obj, printcharfun, escapeflag);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf (buf, " . #%d#", i + 1);
|
||||
strout (buf, -1, -1, printcharfun, 0);
|
||||
}
|
||||
goto end_of_list;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user