diff options
| author | Stefan Monnier | 2010-12-22 16:25:46 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2010-12-22 16:25:46 -0500 |
| commit | a65b85b5f060567a5d9dcbb7e8cbac4ddbbc0b23 (patch) | |
| tree | cd54c7e3ab35e3f1bb4354c6a8709f3663194f7c /src | |
| parent | 7d50c95105d8a353133deb5726e15a91bb4c96d4 (diff) | |
| download | emacs-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/ChangeLog | 5 | ||||
| -rw-r--r-- | src/print.c | 169 |
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 @@ | |||
| 1 | 2010-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 | |||
| 1 | 2010-12-20 Chong Yidong <cyd@stupidchicken.com> | 6 | 2010-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 | ||
| 146 | Lisp_Object Vprint_continuous_numbering; | 146 | Lisp_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. */ | ||
| 154 | int print_number_index; | 156 | int print_number_index; |
| 155 | Lisp_Object Vprint_number_table; | 157 | Lisp_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 | } |