aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Monnier2010-12-22 16:25:46 -0500
committerStefan Monnier2010-12-22 16:25:46 -0500
commita65b85b5f060567a5d9dcbb7e8cbac4ddbbc0b23 (patch)
treecd54c7e3ab35e3f1bb4354c6a8709f3663194f7c /src
parent7d50c95105d8a353133deb5726e15a91bb4c96d4 (diff)
downloademacs-a65b85b5f060567a5d9dcbb7e8cbac4ddbbc0b23.tar.gz
emacs-a65b85b5f060567a5d9dcbb7e8cbac4ddbbc0b23.zip
* src/print.c (print, print_preprocess, print_object): Use a hash table
rather than a linear table for Vprint_number_table.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog5
-rw-r--r--src/print.c169
2 files changed, 76 insertions, 98 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 3dabc0703ac..2c3f8f92f83 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,8 @@
12010-12-22 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * print.c (print, print_preprocess, print_object): Use a hash table
4 rather than a linear table for Vprint_number_table.
5
12010-12-20 Chong Yidong <cyd@stupidchicken.com> 62010-12-20 Chong Yidong <cyd@stupidchicken.com>
2 7
3 * frame.c (focus_follows_mouse): Default to 0 (Bug#7269). 8 * frame.c (focus_follows_mouse): Default to 0 (Bug#7269).
diff --git a/src/print.c b/src/print.c
index a95498ae668..50a972cc94a 100644
--- a/src/print.c
+++ b/src/print.c
@@ -145,12 +145,14 @@ Lisp_Object Vprint_circle;
145 145
146Lisp_Object Vprint_continuous_numbering; 146Lisp_Object Vprint_continuous_numbering;
147 147
148/* Vprint_number_table is a vector like [OBJ1 STAT1 OBJ2 STAT2 ...], 148/* Vprint_number_table is a table, that keeps objects that are going to
149 where OBJn are objects going to be printed, and STATn are their status, 149 be printed, to allow use of #n= and #n# to express sharing.
150 which may be different meanings during process. See the comments of 150 For any given object, the table can give the following values:
151 the functions print and print_preprocess for details. 151 t the object will be printed only once.
152 print_number_index keeps the last position the next object should be added, 152 -N the object will be printed several times and will take number N.
153 twice of which is the actual vector position in Vprint_number_table. */ 153 N the object has been printed so we can refer to it as #N#.
154 print_number_index holds the largest N already used.
155 N has to be striclty larger than 0 since we need to distinguish -N. */
154int print_number_index; 156int print_number_index;
155Lisp_Object Vprint_number_table; 157Lisp_Object Vprint_number_table;
156 158
@@ -1226,33 +1228,24 @@ print (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag)
1226 /* Construct Vprint_number_table for print-gensym and print-circle. */ 1228 /* Construct Vprint_number_table for print-gensym and print-circle. */
1227 if (!NILP (Vprint_gensym) || !NILP (Vprint_circle)) 1229 if (!NILP (Vprint_gensym) || !NILP (Vprint_circle))
1228 { 1230 {
1229 int i, start, index;
1230 start = index = print_number_index;
1231 /* Construct Vprint_number_table. 1231 /* Construct Vprint_number_table.
1232 This increments print_number_index for the objects added. */ 1232 This increments print_number_index for the objects added. */
1233 print_depth = 0; 1233 print_depth = 0;
1234 print_preprocess (obj); 1234 print_preprocess (obj);
1235 1235
1236 /* Remove unnecessary objects, which appear only once in OBJ; 1236 if (HASH_TABLE_P (Vprint_number_table))
1237 that is, whose status is Qnil. Compactify the necessary objects. */ 1237 { /* Remove unnecessary objects, which appear only once in OBJ;
1238 for (i = start; i < print_number_index; i++) 1238 that is, whose status is Qt.
1239 if (!NILP (PRINT_NUMBER_STATUS (Vprint_number_table, i))) 1239 Maybe a better way to do that is to copy elements to
1240 { 1240 a new hash table. */
1241 PRINT_NUMBER_OBJECT (Vprint_number_table, index) 1241 struct Lisp_Hash_Table *h = XHASH_TABLE (Vprint_number_table);
1242 = PRINT_NUMBER_OBJECT (Vprint_number_table, i); 1242 int i;
1243 index++;
1244 }
1245
1246 /* Clear out objects outside the active part of the table. */
1247 for (i = index; i < print_number_index; i++)
1248 PRINT_NUMBER_OBJECT (Vprint_number_table, i) = Qnil;
1249
1250 /* Reset the status field for the next print step. Now this
1251 field means whether the object has already been printed. */
1252 for (i = start; i < print_number_index; i++)
1253 PRINT_NUMBER_STATUS (Vprint_number_table, i) = Qnil;
1254 1243
1255 print_number_index = index; 1244 for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
1245 if (!NILP (HASH_HASH (h, i))
1246 && EQ (HASH_VALUE (h, i), Qt))
1247 Fremhash (HASH_KEY (h, i), Vprint_number_table);
1248 }
1256 } 1249 }
1257 1250
1258 print_depth = 0; 1251 print_depth = 0;
@@ -1300,48 +1293,40 @@ print_preprocess (Lisp_Object obj)
1300 && SYMBOLP (obj) 1293 && SYMBOLP (obj)
1301 && !SYMBOL_INTERNED_P (obj))) 1294 && !SYMBOL_INTERNED_P (obj)))
1302 { 1295 {
1296 if (!HASH_TABLE_P (Vprint_number_table))
1297 {
1298 Lisp_Object args[2];
1299 args[0] = QCtest;
1300 args[1] = Qeq;
1301 Vprint_number_table = Fmake_hash_table (2, args);
1302 }
1303
1303 /* In case print-circle is nil and print-gensym is t, 1304 /* In case print-circle is nil and print-gensym is t,
1304 add OBJ to Vprint_number_table only when OBJ is a symbol. */ 1305 add OBJ to Vprint_number_table only when OBJ is a symbol. */
1305 if (! NILP (Vprint_circle) || SYMBOLP (obj)) 1306 if (! NILP (Vprint_circle) || SYMBOLP (obj))
1306 { 1307 {
1307 for (i = 0; i < print_number_index; i++) 1308 Lisp_Object num = Fgethash (obj, Vprint_number_table, Qnil);
1308 if (EQ (PRINT_NUMBER_OBJECT (Vprint_number_table, i), obj)) 1309 if (!NILP (num)
1309 { 1310 /* If Vprint_continuous_numbering is non-nil and OBJ is a gensym,
1310 /* OBJ appears more than once. Let's remember that. */ 1311 always print the gensym with a number. This is a special for
1311 PRINT_NUMBER_STATUS (Vprint_number_table, i) = Qt; 1312 the lisp function byte-compile-output-docform. */
1312 print_depth--; 1313 || (!NILP (Vprint_continuous_numbering)
1313 return; 1314 && SYMBOLP (obj)
1314 } 1315 && !SYMBOL_INTERNED_P (obj)))
1315 1316 { /* OBJ appears more than once. Let's remember that. */
1316 /* OBJ is not yet recorded. Let's add to the table. */ 1317 if (EQ (Qt, num))
1317 if (print_number_index == 0)
1318 {
1319 /* Initialize the table. */
1320 Vprint_number_table = Fmake_vector (make_number (40), Qnil);
1321 }
1322 else if (XVECTOR (Vprint_number_table)->size == print_number_index * 2)
1323 {
1324 /* Reallocate the table. */
1325 int i = print_number_index * 4;
1326 Lisp_Object old_table = Vprint_number_table;
1327 Vprint_number_table = Fmake_vector (make_number (i), Qnil);
1328 for (i = 0; i < print_number_index; i++)
1329 { 1318 {
1330 PRINT_NUMBER_OBJECT (Vprint_number_table, i) 1319 print_number_index++;
1331 = PRINT_NUMBER_OBJECT (old_table, i); 1320 /* Negative number indicates it hasn't been printed yet. */
1332 PRINT_NUMBER_STATUS (Vprint_number_table, i) 1321 Fputhash (obj, make_number (- print_number_index),
1333 = PRINT_NUMBER_STATUS (old_table, i); 1322 Vprint_number_table);
1334 } 1323 }
1324 print_depth--;
1325 return;
1335 } 1326 }
1336 PRINT_NUMBER_OBJECT (Vprint_number_table, print_number_index) = obj; 1327 else
1337 /* If Vprint_continuous_numbering is non-nil and OBJ is a gensym, 1328 /* OBJ is not yet recorded. Let's add to the table. */
1338 always print the gensym with a number. This is a special for 1329 Fputhash (obj, Qt, Vprint_number_table);
1339 the lisp function byte-compile-output-docform. */
1340 if (!NILP (Vprint_continuous_numbering)
1341 && SYMBOLP (obj)
1342 && !SYMBOL_INTERNED_P (obj))
1343 PRINT_NUMBER_STATUS (Vprint_number_table, print_number_index) = Qt;
1344 print_number_index++;
1345 } 1330 }
1346 1331
1347 switch (XTYPE (obj)) 1332 switch (XTYPE (obj))
@@ -1372,8 +1357,8 @@ print_preprocess (Lisp_Object obj)
1372 print_preprocess (XVECTOR (obj)->contents[i]); 1357 print_preprocess (XVECTOR (obj)->contents[i]);
1373 if (HASH_TABLE_P (obj)) 1358 if (HASH_TABLE_P (obj))
1374 { /* For hash tables, the key_and_value slot is past 1359 { /* For hash tables, the key_and_value slot is past
1375 `size' because it needs to be marked specially in case 1360 `size' because it needs to be marked specially in case
1376 the table is weak. */ 1361 the table is weak. */
1377 struct Lisp_Hash_Table *h = XHASH_TABLE (obj); 1362 struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
1378 print_preprocess (h->key_and_value); 1363 print_preprocess (h->key_and_value);
1379 } 1364 }
@@ -1510,28 +1495,26 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
1510 else 1495 else
1511 { 1496 {
1512 /* With the print-circle feature. */ 1497 /* With the print-circle feature. */
1513 int i; 1498 Lisp_Object num = Fgethash (obj, Vprint_number_table, Qnil);
1514 for (i = 0; i < print_number_index; i++) 1499 if (INTEGERP (num))
1515 if (EQ (PRINT_NUMBER_OBJECT (Vprint_number_table, i), obj)) 1500 {
1516 { 1501 int n = XINT (num);
1517 if (NILP (PRINT_NUMBER_STATUS (Vprint_number_table, i))) 1502 if (n < 0)
1518 { 1503 { /* Add a prefix #n= if OBJ has not yet been printed;
1519 /* Add a prefix #n= if OBJ has not yet been printed; 1504 that is, its status field is nil. */
1520 that is, its status field is nil. */ 1505 sprintf (buf, "#%d=", -n);
1521 sprintf (buf, "#%d=", i + 1); 1506 strout (buf, -1, -1, printcharfun, 0);
1522 strout (buf, -1, -1, printcharfun, 0); 1507 /* OBJ is going to be printed. Remember that fact. */
1523 /* OBJ is going to be printed. Set the status to t. */ 1508 Fputhash (obj, make_number (- n), Vprint_number_table);
1524 PRINT_NUMBER_STATUS (Vprint_number_table, i) = Qt; 1509 }
1525 break; 1510 else
1526 } 1511 {
1527 else 1512 /* Just print #n# if OBJ has already been printed. */
1528 { 1513 sprintf (buf, "#%d#", n);
1529 /* Just print #n# if OBJ has already been printed. */ 1514 strout (buf, -1, -1, printcharfun, 0);
1530 sprintf (buf, "#%d#", i + 1); 1515 return;
1531 strout (buf, -1, -1, printcharfun, 0); 1516 }
1532 return; 1517 }
1533 }
1534 }
1535 } 1518 }
1536 } 1519 }
1537 1520
@@ -1834,21 +1817,11 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
1834 /* With the print-circle feature. */ 1817 /* With the print-circle feature. */
1835 if (i != 0) 1818 if (i != 0)
1836 { 1819 {
1837 int i; 1820 Lisp_Object num = Fgethash (obj, Vprint_number_table, Qnil);
1838 for (i = 0; i < print_number_index; i++) 1821 if (INTEGERP (num))
1839 if (EQ (PRINT_NUMBER_OBJECT (Vprint_number_table, i),
1840 obj))
1841 {
1842 if (NILP (PRINT_NUMBER_STATUS (Vprint_number_table, i)))
1843 { 1822 {
1844 strout (" . ", 3, 3, printcharfun, 0); 1823 strout (" . ", 3, 3, printcharfun, 0);
1845 print_object (obj, printcharfun, escapeflag); 1824 print_object (obj, printcharfun, escapeflag);
1846 }
1847 else
1848 {
1849 sprintf (buf, " . #%d#", i + 1);
1850 strout (buf, -1, -1, printcharfun, 0);
1851 }
1852 goto end_of_list; 1825 goto end_of_list;
1853 } 1826 }
1854 } 1827 }