* environments.c (DEFAULT_OBARRAY_SIZE): Changed from 137 to 31
[bpt/guile.git] / libguile / hashtab.c
CommitLineData
f59a096e 1/* Copyright (C) 1995,1996,1998,1999,2000,2001, 2003 Free Software Foundation, Inc.
0f2d19dd
JB
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
82892bed
JB
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
0f2d19dd
JB
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
82892bed 40 * If you do not wish that, delete this exception notice. */
1bbd0b84 41
1bbd0b84 42
0f2d19dd
JB
43\f
44
a0599745
MD
45#include "libguile/_scm.h"
46#include "libguile/alist.h"
47#include "libguile/hash.h"
48#include "libguile/eval.h"
fdc28395 49#include "libguile/root.h"
a0599745 50#include "libguile/vectors.h"
f59a096e 51#include "libguile/ports.h"
a0599745
MD
52
53#include "libguile/validate.h"
54#include "libguile/hashtab.h"
0f2d19dd
JB
55\f
56
c35738c1
MD
57/* NOTES
58 *
59 * 1. The current hash table implementation uses weak alist vectors
60 * (implementation in weaks.c) internally, but we do the scanning
61 * ourselves (in scan_weak_hashtables) because we need to update the
62 * hash table structure when items are dropped during GC.
63 *
64 * 2. All hash table operations still work on alist vectors.
65 *
f59a096e
MD
66 */
67
c35738c1
MD
68/* Hash tables are either vectors of association lists or smobs
69 * containing such vectors. Currently, the vector version represents
70 * constant size tables while those wrapped in a smob represents
71 * resizing tables.
72 *
73 * Growing or shrinking, with following rehashing, is triggered when
74 * the load factor
75 *
76 * L = N / S (N: number of items in table, S: bucket vector length)
77 *
78 * passes an upper limit of 0.9 or a lower limit of 0.25.
79 *
80 * The implementation stores the upper and lower number of items which
81 * trigger a resize in the hashtable object.
82 *
83 * Possible hash table sizes (primes) are stored in the array
84 * hashtable_size.
f59a096e
MD
85 */
86
f59a096e
MD
87scm_t_bits scm_tc16_hashtable;
88
0a4c1355 89#define HASHTABLE_SIZE_N 25
f59a096e 90
0a4c1355
MD
91static unsigned long hashtable_size[] = {
92 31, 61, 113, 223, 443, 883, 1759, 3517, 7027, 14051, 28099, 56197, 112363,
93 224717, 449419, 898823, 1797641, 3595271, 7190537, 14381041, 28762081,
94 57524111, 115048217, 230096423, 460192829 /* larger values can't be
95 represented as INUMs */
f59a096e
MD
96};
97
f59a096e
MD
98/* Turn an empty vector hash table into an opaque resizable one. */
99
100static char *s_hashtable = "hashtable";
101
c35738c1
MD
102SCM weak_hashtables = SCM_EOL;
103
104static SCM
105make_hash_table (int flags, unsigned long k, const char *func_name) {
106 SCM table, vector;
110beb83
MD
107 int i = 0, n = k ? k : 31;
108 while (i < HASHTABLE_SIZE_N && n > hashtable_size[i])
109 ++i;
110 n = hashtable_size[i];
c35738c1
MD
111 if (flags)
112 /* The SCM_WVECTF_NOSCAN flag informs the weak vector code not to
113 perform the final scan for broken references. Instead we do
114 that ourselves in scan_weak_hashtables. */
115 vector = scm_i_allocate_weak_vector (flags | SCM_WVECTF_NOSCAN,
116 SCM_MAKINUM (n),
117 SCM_EOL,
118 func_name);
119 else
120 vector = scm_c_make_vector (n, SCM_EOL);
f59a096e 121 scm_t_hashtable *t = scm_gc_malloc (sizeof (*t), s_hashtable);
c35738c1 122 t->min_size_index = t->size_index = i;
f59a096e 123 t->n_items = 0;
c35738c1 124 t->lower = 0;
110beb83 125 t->upper = 9 * n / 10;
c35738c1
MD
126 t->flags = flags;
127 if (flags)
128 {
129 SCM_NEWSMOB3 (table, scm_tc16_hashtable, vector, t, weak_hashtables);
130 weak_hashtables = table;
131 }
132 else
133 SCM_NEWSMOB3 (table, scm_tc16_hashtable, vector, t, SCM_EOL);
f59a096e
MD
134 return table;
135}
136
c35738c1
MD
137
138void
139scm_i_rehash (SCM table,
140 unsigned long (*hash_fn)(),
141 void *closure,
142 const char* func_name)
143{
144 SCM buckets, new_buckets;
145 int i;
146 unsigned long old_size;
147 unsigned long new_size;
148
149 if (SCM_HASHTABLE_N_ITEMS (table) < SCM_HASHTABLE_LOWER (table))
150 {
151 /* rehashing is not triggered when i <= min_size */
152 i = SCM_HASHTABLE (table)->size_index;
153 do
154 --i;
155 while (i > SCM_HASHTABLE (table)->min_size_index
156 && SCM_HASHTABLE_N_ITEMS (table) < hashtable_size[i] / 4);
157 }
158 else
159 {
160 i = SCM_HASHTABLE (table)->size_index + 1;
161 if (i >= HASHTABLE_SIZE_N)
162 /* don't rehash */
163 return;
164 /* store for use in rehash_after_gc */
165 SCM_HASHTABLE (table)->hash_fn = hash_fn;
166 SCM_HASHTABLE (table)->closure = closure;
167 }
168 SCM_HASHTABLE (table)->size_index = i;
169
170 new_size = hashtable_size[i];
171 if (i <= SCM_HASHTABLE (table)->min_size_index)
172 SCM_HASHTABLE (table)->lower = 0;
173 else
174 SCM_HASHTABLE (table)->lower = new_size / 4;
175 SCM_HASHTABLE (table)->upper = 9 * new_size / 10;
176 buckets = SCM_HASHTABLE_VECTOR (table);
177
178 if (SCM_HASHTABLE_WEAK_P (table))
179 new_buckets = scm_i_allocate_weak_vector (SCM_HASHTABLE_FLAGS (table)
180 | SCM_WVECTF_NOSCAN,
181 SCM_MAKINUM (new_size),
182 SCM_EOL,
183 func_name);
184 else
185 new_buckets = scm_c_make_vector (new_size, SCM_EOL);
186
187 old_size = SCM_VECTOR_LENGTH (buckets);
188 for (i = 0; i < old_size; ++i)
189 {
190 SCM ls = SCM_VELTS (buckets)[i], handle;
191 while (!SCM_NULLP (ls))
192 {
193 unsigned long h;
194 handle = SCM_CAR (ls);
195 h = hash_fn (SCM_CAR (handle), new_size, closure);
196 if (h >= new_size)
197 scm_out_of_range (func_name, scm_ulong2num (h));
198 SCM_VECTOR_SET (new_buckets, h,
199 scm_cons (handle, SCM_VELTS (new_buckets)[h]));
200 ls = SCM_CDR (ls);
201 }
202 }
203 SCM_SET_HASHTABLE_VECTOR (table, new_buckets);
204}
205
206
f59a096e
MD
207static int
208hashtable_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
209{
210 scm_t_hashtable *t = SCM_HASHTABLE (exp);
c35738c1
MD
211 scm_puts ("#<", port);
212 if (SCM_HASHTABLE_WEAK_KEY_P (exp))
213 scm_puts ("weak-key-", port);
214 else if (SCM_HASHTABLE_WEAK_VALUE_P (exp))
215 scm_puts ("weak-value-", port);
216 else if (SCM_HASHTABLE_DOUBLY_WEAK_P (exp))
217 scm_puts ("doubly-weak-", port);
218 scm_puts ("hash-table ", port);
219 scm_intprint ((unsigned long) t->n_items, 10, port);
f59a096e
MD
220 scm_putc ('/', port);
221 scm_intprint ((unsigned long) SCM_VECTOR_LENGTH (SCM_HASHTABLE_VECTOR (exp)),
222 10, port);
223 scm_puts (">", port);
224 return 1;
225}
226
c35738c1
MD
227#define UNMARKED_CELL_P(x) (SCM_NIMP(x) && !SCM_GC_MARK_P (x))
228
229/* keep track of hash tables that need to shrink after scan */
230static SCM to_rehash = SCM_EOL;
231
232/* scan hash tables for broken references, remove them, and update
233 hash tables item count */
234static void *
235scan_weak_hashtables (void *dummy1 SCM_UNUSED,
236 void *dummy2 SCM_UNUSED,
237 void *dummy3 SCM_UNUSED)
238{
239 SCM *next = &weak_hashtables;
240 SCM h = *next;
241 while (!SCM_NULLP (h))
242 {
243 if (!SCM_GC_MARK_P (h))
244 *next = h = SCM_HASHTABLE_NEXT (h);
245 else
246 {
247 SCM alist;
248 int i, n = SCM_HASHTABLE_N_BUCKETS (h);
249 int weak_car = SCM_HASHTABLE_FLAGS (h) & SCM_HASHTABLEF_WEAK_CAR;
250 int weak_cdr = SCM_HASHTABLE_FLAGS (h) & SCM_HASHTABLEF_WEAK_CDR;
251 int check_size_p = 0;
252 for (i = 0; i < n; ++i)
253 {
254 SCM *next_spine = (SCM *) &SCM_HASHTABLE_BUCKETS (h)[i];
255 for (alist = *next_spine;
256 !SCM_NULLP (alist);
257 alist = SCM_CDR (alist))
258 if ((weak_car && UNMARKED_CELL_P (SCM_CAAR (alist)))
259 || (weak_cdr && UNMARKED_CELL_P (SCM_CDAR (alist))))
260 {
261 *next_spine = SCM_CDR (alist);
262 SCM_HASHTABLE_DECREMENT (h);
263 check_size_p = 1;
264 }
265 else
266 next_spine = SCM_CDRLOC (alist);
267 }
268 if (check_size_p
269 && SCM_HASHTABLE_N_ITEMS (h) < SCM_HASHTABLE_LOWER (h))
270 {
271 SCM tmp = SCM_HASHTABLE_NEXT (h);
272 /* temporarily move table from weak_hashtables to to_rehash */
273 SCM_SET_HASHTABLE_NEXT (h, to_rehash);
274 to_rehash = h;
275 *next = h = tmp;
276 }
277 else
278 {
279 next = SCM_HASHTABLE_NEXTLOC (h);
280 h = SCM_HASHTABLE_NEXT (h);
281 }
282 }
283 }
284 return 0;
285}
286
287static void *
288rehash_after_gc (void *dummy1 SCM_UNUSED,
289 void *dummy2 SCM_UNUSED,
290 void *dummy3 SCM_UNUSED)
291{
292 if (!SCM_NULLP (to_rehash))
293 {
294 SCM h = to_rehash, last;
295 do
296 {
297 scm_i_rehash (h,
298 /* use same hash_fn and closure as last time */
299 SCM_HASHTABLE (h)->hash_fn,
300 SCM_HASHTABLE (h)->closure,
301 "rehash_after_gc");
302 last = h;
303 h = SCM_HASHTABLE_NEXT (h);
304 } while (!SCM_NULLP (h));
305 /* move tables back to weak_hashtables */
306 SCM_SET_HASHTABLE_NEXT (last, weak_hashtables);
307 weak_hashtables = to_rehash;
308 to_rehash = SCM_EOL;
309 }
310 return 0;
311}
312
f59a096e
MD
313static size_t
314hashtable_free (SCM obj)
315{
316 scm_gc_free (SCM_HASHTABLE (obj), sizeof (scm_t_hashtable), s_hashtable);
317 return 0;
318}
319
320
00ffa0e7 321SCM
c014a02e 322scm_c_make_hash_table (unsigned long k)
00ffa0e7 323{
c35738c1 324 return make_hash_table (0, k, "scm_c_make_hash_table");
f59a096e
MD
325}
326
327SCM_DEFINE (scm_make_hash_table, "make-hash-table", 0, 1, 0,
328 (SCM n),
c35738c1 329 "Make a hash table with optional minimum number of buckets @var{n}\n")
f59a096e
MD
330#define FUNC_NAME s_scm_make_hash_table
331{
332 if (SCM_UNBNDP (n))
c35738c1 333 return make_hash_table (0, 0, FUNC_NAME);
f59a096e
MD
334 else
335 {
336 int k;
337 SCM_VALIDATE_INUM_COPY (1, n, k);
c35738c1 338 return make_hash_table (0, k, FUNC_NAME);
f59a096e
MD
339 }
340}
341#undef FUNC_NAME
342
c35738c1
MD
343SCM_DEFINE (scm_make_weak_key_hash_table, "make-weak-key-hash-table", 0, 1, 0,
344 (SCM n),
345 "@deffnx {Scheme Procedure} make-weak-value-hash-table size\n"
346 "@deffnx {Scheme Procedure} make-doubly-weak-hash-table size\n"
347 "Return a weak hash table with @var{size} buckets. As with any\n"
348 "hash table, choosing a good size for the table requires some\n"
349 "caution.\n"
350 "\n"
351 "You can modify weak hash tables in exactly the same way you\n"
352 "would modify regular hash tables. (@pxref{Hash Tables})")
353#define FUNC_NAME s_scm_make_weak_key_hash_table
f59a096e 354{
c35738c1
MD
355 if (SCM_UNBNDP (n))
356 return make_hash_table (SCM_HASHTABLEF_WEAK_CAR, 0, FUNC_NAME);
f59a096e 357 else
0a4c1355 358 {
c35738c1
MD
359 int k;
360 SCM_VALIDATE_INUM_COPY (1, n, k);
361 return make_hash_table (SCM_HASHTABLEF_WEAK_CAR, k, FUNC_NAME);
0a4c1355 362 }
c35738c1
MD
363}
364#undef FUNC_NAME
365
366
367SCM_DEFINE (scm_make_weak_value_hash_table, "make-weak-value-hash-table", 0, 1, 0,
368 (SCM n),
369 "Return a hash table with weak values with @var{size} buckets.\n"
370 "(@pxref{Hash Tables})")
371#define FUNC_NAME s_scm_make_weak_value_hash_table
372{
373 if (SCM_UNBNDP (n))
374 return make_hash_table (SCM_HASHTABLEF_WEAK_CDR, 0, FUNC_NAME);
f59a096e 375 else
c35738c1
MD
376 {
377 int k;
378 SCM_VALIDATE_INUM_COPY (1, n, k);
379 return make_hash_table (SCM_HASHTABLEF_WEAK_CDR, k, FUNC_NAME);
f59a096e 380 }
c35738c1
MD
381}
382#undef FUNC_NAME
f59a096e 383
c35738c1
MD
384
385SCM_DEFINE (scm_make_doubly_weak_hash_table, "make-doubly-weak-hash-table", 1, 0, 0,
386 (SCM n),
387 "Return a hash table with weak keys and values with @var{size}\n"
388 "buckets. (@pxref{Hash Tables})")
389#define FUNC_NAME s_scm_make_doubly_weak_hash_table
390{
391 if (SCM_UNBNDP (n))
392 return make_hash_table (SCM_HASHTABLEF_WEAK_CAR | SCM_HASHTABLEF_WEAK_CDR,
393 0,
394 FUNC_NAME);
395 else
f59a096e 396 {
c35738c1
MD
397 int k;
398 SCM_VALIDATE_INUM_COPY (1, n, k);
399 return make_hash_table (SCM_HASHTABLEF_WEAK_CAR | SCM_HASHTABLEF_WEAK_CDR,
400 k,
401 FUNC_NAME);
f59a096e 402 }
f59a096e 403}
c35738c1
MD
404#undef FUNC_NAME
405
406
407SCM_DEFINE (scm_hash_table_p, "hash-table?", 1, 0, 0,
408 (SCM obj),
409 "Return @code{#t} if @var{obj} is a hash table.")
410#define FUNC_NAME s_scm_hash_table_p
411{
412 return SCM_BOOL (SCM_HASHTABLE_P (obj));
413}
414#undef FUNC_NAME
415
416
417SCM_DEFINE (scm_weak_key_hash_table_p, "weak-key-hash-table?", 1, 0, 0,
418 (SCM obj),
419 "@deffnx {Scheme Procedure} weak-value-hash-table? obj\n"
420 "@deffnx {Scheme Procedure} doubly-weak-hash-table? obj\n"
421 "Return @code{#t} if @var{obj} is the specified weak hash\n"
422 "table. Note that a doubly weak hash table is neither a weak key\n"
423 "nor a weak value hash table.")
424#define FUNC_NAME s_scm_weak_key_hash_table_p
425{
426 return SCM_BOOL (SCM_HASHTABLE_P (obj) && SCM_HASHTABLE_WEAK_KEY_P (obj));
427}
428#undef FUNC_NAME
429
430
431SCM_DEFINE (scm_weak_value_hash_table_p, "weak-value-hash-table?", 1, 0, 0,
432 (SCM obj),
433 "Return @code{#t} if @var{obj} is a weak value hash table.")
434#define FUNC_NAME s_scm_weak_value_hash_table_p
435{
436 return SCM_BOOL (SCM_HASHTABLE_P (obj) && SCM_HASHTABLE_WEAK_VALUE_P (obj));
437}
438#undef FUNC_NAME
439
440
441SCM_DEFINE (scm_doubly_weak_hash_table_p, "doubly-weak-hash-table?", 1, 0, 0,
442 (SCM obj),
443 "Return @code{#t} if @var{obj} is a doubly weak hash table.")
444#define FUNC_NAME s_scm_doubly_weak_hash_table_p
445{
446 return SCM_BOOL (SCM_HASHTABLE_P (obj) && SCM_HASHTABLE_DOUBLY_WEAK_P (obj));
447}
448#undef FUNC_NAME
449
22a52da1 450
0f2d19dd 451SCM
34d19ef6 452scm_hash_fn_get_handle (SCM table, SCM obj, unsigned long (*hash_fn)(), SCM (*assoc_fn)(), void * closure)
22a52da1 453#define FUNC_NAME "scm_hash_fn_get_handle"
0f2d19dd 454{
c014a02e 455 unsigned long k;
0f2d19dd
JB
456 SCM h;
457
f59a096e 458 if (SCM_HASHTABLE_P (table))
0a4c1355 459 table = SCM_HASHTABLE_VECTOR (table);
f59a096e 460 else
0a4c1355 461 SCM_VALIDATE_VECTOR (1, table);
bfa974f0 462 if (SCM_VECTOR_LENGTH (table) == 0)
22a52da1 463 return SCM_BOOL_F;
bfa974f0
DH
464 k = hash_fn (obj, SCM_VECTOR_LENGTH (table), closure);
465 if (k >= SCM_VECTOR_LENGTH (table))
0a4c1355 466 scm_out_of_range ("hash_fn_get_handle", scm_ulong2num (k));
0f2d19dd
JB
467 h = assoc_fn (obj, SCM_VELTS (table)[k], closure);
468 return h;
469}
22a52da1 470#undef FUNC_NAME
0f2d19dd
JB
471
472
0f2d19dd 473SCM
34d19ef6
HWN
474scm_hash_fn_create_handle_x (SCM table, SCM obj, SCM init, unsigned long (*hash_fn)(),
475 SCM (*assoc_fn)(), void * closure)
cbaadf02 476#define FUNC_NAME "scm_hash_fn_create_handle_x"
0f2d19dd 477{
c014a02e 478 unsigned long k;
f59a096e 479 SCM buckets, it;
0f2d19dd 480
f59a096e 481 if (SCM_HASHTABLE_P (table))
0a4c1355 482 buckets = SCM_HASHTABLE_VECTOR (table);
f59a096e
MD
483 else
484 {
485 SCM_ASSERT (SCM_VECTORP (table),
486 table, SCM_ARG1, "hash_fn_create_handle_x");
487 buckets = table;
f59a096e
MD
488 }
489 if (SCM_VECTOR_LENGTH (buckets) == 0)
cbaadf02
DH
490 SCM_MISC_ERROR ("void hashtable", SCM_EOL);
491
f59a096e
MD
492 k = hash_fn (obj, SCM_VECTOR_LENGTH (buckets), closure);
493 if (k >= SCM_VECTOR_LENGTH (buckets))
0a4c1355 494 scm_out_of_range ("hash_fn_create_handle_x", scm_ulong2num (k));
f59a096e 495 it = assoc_fn (obj, SCM_VELTS (buckets)[k], closure);
ee083ac2 496 if (!SCM_FALSEP (it))
0a4c1355 497 return it;
ee083ac2
DH
498 else
499 {
0a4c1355
MD
500 SCM old_bucket = SCM_VELTS (buckets)[k];
501 SCM new_bucket = scm_acons (obj, init, old_bucket);
502 SCM_VECTOR_SET (buckets, k, new_bucket);
f59a096e
MD
503 if (table != buckets)
504 {
505 SCM_HASHTABLE_INCREMENT (table);
506 if (SCM_HASHTABLE_N_ITEMS (table) > SCM_HASHTABLE_UPPER (table))
c35738c1 507 scm_i_rehash (table, hash_fn, closure, FUNC_NAME);
f59a096e 508 }
ee083ac2
DH
509 return SCM_CAR (new_bucket);
510 }
0f2d19dd 511}
cbaadf02 512#undef FUNC_NAME
0f2d19dd 513
1cc91f1b 514
0f2d19dd 515SCM
34d19ef6
HWN
516scm_hash_fn_ref (SCM table, SCM obj, SCM dflt, unsigned long (*hash_fn)(),
517 SCM (*assoc_fn)(), void * closure)
0f2d19dd 518{
22a52da1
DH
519 SCM it = scm_hash_fn_get_handle (table, obj, hash_fn, assoc_fn, closure);
520 if (SCM_CONSP (it))
0f2d19dd 521 return SCM_CDR (it);
22a52da1
DH
522 else
523 return dflt;
0f2d19dd
JB
524}
525
526
527
1cc91f1b 528
0f2d19dd 529SCM
34d19ef6
HWN
530scm_hash_fn_set_x (SCM table, SCM obj, SCM val, unsigned long (*hash_fn)(),
531 SCM (*assoc_fn)(), void * closure)
0f2d19dd
JB
532{
533 SCM it;
534
535 it = scm_hash_fn_create_handle_x (table, obj, SCM_BOOL_F, hash_fn, assoc_fn, closure);
536 SCM_SETCDR (it, val);
537 return val;
538}
539
540
541
542
1cc91f1b 543
0f2d19dd 544SCM
34d19ef6
HWN
545scm_hash_fn_remove_x (SCM table, SCM obj, unsigned long (*hash_fn)(), SCM (*assoc_fn)(),
546 SCM (*delete_fn)(), void * closure)
0f2d19dd 547{
c014a02e 548 unsigned long k;
87ca11ff 549 SCM buckets, h;
0f2d19dd 550
87ca11ff 551 if (SCM_HASHTABLE_P (table))
0a4c1355 552 buckets = SCM_HASHTABLE_VECTOR (table);
87ca11ff
MD
553 else
554 {
555 SCM_ASSERT (SCM_VECTORP (table), table, SCM_ARG1, "hash_fn_remove_x");
556 buckets = table;
87ca11ff 557 }
bfa974f0 558 if (SCM_VECTOR_LENGTH (table) == 0)
0f2d19dd 559 return SCM_EOL;
87ca11ff 560
87ca11ff
MD
561 k = hash_fn (obj, SCM_VECTOR_LENGTH (buckets), closure);
562 if (k >= SCM_VECTOR_LENGTH (buckets))
0a4c1355 563 scm_out_of_range ("hash_fn_remove_x", scm_ulong2num (k));
87ca11ff
MD
564 h = assoc_fn (obj, SCM_VELTS (buckets)[k], closure);
565 if (!SCM_FALSEP (h))
566 {
567 SCM_VECTOR_SET (buckets, k, delete_fn (h, SCM_VELTS (buckets)[k]));
568 if (table != buckets)
569 {
570 SCM_HASHTABLE_DECREMENT (table);
571 if (SCM_HASHTABLE_N_ITEMS (table) < SCM_HASHTABLE_LOWER (table))
c35738c1 572 scm_i_rehash (table, hash_fn, closure, "scm_hash_fn_remove_x");
87ca11ff
MD
573 }
574 }
0f2d19dd
JB
575 return h;
576}
577
c35738c1
MD
578SCM_DEFINE (scm_hash_clear_x, "hash-clear!", 1, 0, 0,
579 (SCM table),
580 "Remove all items from TABLE (without triggering a resize).")
581#define FUNC_NAME s_scm_hash_clear_x
582{
583 SCM_VALIDATE_HASHTABLE (1, table);
584 scm_vector_fill_x (SCM_HASHTABLE_VECTOR (table), SCM_EOL);
585 SCM_SET_HASHTABLE_N_ITEMS (table, 0);
586 return SCM_UNSPECIFIED;
587}
588#undef FUNC_NAME
0f2d19dd
JB
589
590\f
591
a1ec6916 592SCM_DEFINE (scm_hashq_get_handle, "hashq-get-handle", 2, 0, 0,
22a52da1
DH
593 (SCM table, SCM key),
594 "This procedure returns the @code{(key . value)} pair from the\n"
595 "hash table @var{table}. If @var{table} does not hold an\n"
596 "associated value for @var{key}, @code{#f} is returned.\n"
597 "Uses @code{eq?} for equality testing.")
1bbd0b84 598#define FUNC_NAME s_scm_hashq_get_handle
0f2d19dd 599{
22a52da1 600 return scm_hash_fn_get_handle (table, key, scm_ihashq, scm_sloppy_assq, 0);
0f2d19dd 601}
1bbd0b84 602#undef FUNC_NAME
0f2d19dd
JB
603
604
a1ec6916 605SCM_DEFINE (scm_hashq_create_handle_x, "hashq-create-handle!", 3, 0, 0,
d550d22a
GB
606 (SCM table, SCM key, SCM init),
607 "This function looks up @var{key} in @var{table} and returns its handle.\n"
b380b885
MD
608 "If @var{key} is not already present, a new handle is created which\n"
609 "associates @var{key} with @var{init}.")
1bbd0b84 610#define FUNC_NAME s_scm_hashq_create_handle_x
0f2d19dd 611{
d550d22a 612 return scm_hash_fn_create_handle_x (table, key, init, scm_ihashq, scm_sloppy_assq, 0);
0f2d19dd 613}
1bbd0b84 614#undef FUNC_NAME
0f2d19dd
JB
615
616
a1ec6916 617SCM_DEFINE (scm_hashq_ref, "hashq-ref", 2, 1, 0,
1e6808ea 618 (SCM table, SCM key, SCM dflt),
b380b885
MD
619 "Look up @var{key} in the hash table @var{table}, and return the\n"
620 "value (if any) associated with it. If @var{key} is not found,\n"
5352393c
MG
621 "return @var{default} (or @code{#f} if no @var{default} argument\n"
622 "is supplied). Uses @code{eq?} for equality testing.")
1bbd0b84 623#define FUNC_NAME s_scm_hashq_ref
0f2d19dd 624{
54778cd3 625 if (SCM_UNBNDP (dflt))
0f2d19dd 626 dflt = SCM_BOOL_F;
1e6808ea 627 return scm_hash_fn_ref (table, key, dflt, scm_ihashq, scm_sloppy_assq, 0);
0f2d19dd 628}
1bbd0b84 629#undef FUNC_NAME
0f2d19dd
JB
630
631
632
a1ec6916 633SCM_DEFINE (scm_hashq_set_x, "hashq-set!", 3, 0, 0,
1e6808ea 634 (SCM table, SCM key, SCM val),
5352393c
MG
635 "Find the entry in @var{table} associated with @var{key}, and\n"
636 "store @var{value} there. Uses @code{eq?} for equality testing.")
1bbd0b84 637#define FUNC_NAME s_scm_hashq_set_x
0f2d19dd 638{
1e6808ea 639 return scm_hash_fn_set_x (table, key, val, scm_ihashq, scm_sloppy_assq, 0);
0f2d19dd 640}
1bbd0b84 641#undef FUNC_NAME
0f2d19dd
JB
642
643
644
a1ec6916 645SCM_DEFINE (scm_hashq_remove_x, "hashq-remove!", 2, 0, 0,
1e6808ea 646 (SCM table, SCM key),
5352393c
MG
647 "Remove @var{key} (and any value associated with it) from\n"
648 "@var{table}. Uses @code{eq?} for equality tests.")
1bbd0b84 649#define FUNC_NAME s_scm_hashq_remove_x
0f2d19dd 650{
1e6808ea
MG
651 return scm_hash_fn_remove_x (table, key, scm_ihashq, scm_sloppy_assq,
652 scm_delq_x, 0);
0f2d19dd 653}
1bbd0b84 654#undef FUNC_NAME
0f2d19dd
JB
655
656
657\f
658
a1ec6916 659SCM_DEFINE (scm_hashv_get_handle, "hashv-get-handle", 2, 0, 0,
22a52da1
DH
660 (SCM table, SCM key),
661 "This procedure returns the @code{(key . value)} pair from the\n"
662 "hash table @var{table}. If @var{table} does not hold an\n"
663 "associated value for @var{key}, @code{#f} is returned.\n"
664 "Uses @code{eqv?} for equality testing.")
1bbd0b84 665#define FUNC_NAME s_scm_hashv_get_handle
0f2d19dd 666{
22a52da1 667 return scm_hash_fn_get_handle (table, key, scm_ihashv, scm_sloppy_assv, 0);
0f2d19dd 668}
1bbd0b84 669#undef FUNC_NAME
0f2d19dd
JB
670
671
a1ec6916 672SCM_DEFINE (scm_hashv_create_handle_x, "hashv-create-handle!", 3, 0, 0,
d550d22a
GB
673 (SCM table, SCM key, SCM init),
674 "This function looks up @var{key} in @var{table} and returns its handle.\n"
675 "If @var{key} is not already present, a new handle is created which\n"
676 "associates @var{key} with @var{init}.")
1bbd0b84 677#define FUNC_NAME s_scm_hashv_create_handle_x
0f2d19dd 678{
1e6808ea
MG
679 return scm_hash_fn_create_handle_x (table, key, init, scm_ihashv,
680 scm_sloppy_assv, 0);
0f2d19dd 681}
1bbd0b84 682#undef FUNC_NAME
0f2d19dd
JB
683
684
a1ec6916 685SCM_DEFINE (scm_hashv_ref, "hashv-ref", 2, 1, 0,
1e6808ea 686 (SCM table, SCM key, SCM dflt),
d550d22a
GB
687 "Look up @var{key} in the hash table @var{table}, and return the\n"
688 "value (if any) associated with it. If @var{key} is not found,\n"
5352393c
MG
689 "return @var{default} (or @code{#f} if no @var{default} argument\n"
690 "is supplied). Uses @code{eqv?} for equality testing.")
1bbd0b84 691#define FUNC_NAME s_scm_hashv_ref
0f2d19dd 692{
54778cd3 693 if (SCM_UNBNDP (dflt))
0f2d19dd 694 dflt = SCM_BOOL_F;
1e6808ea 695 return scm_hash_fn_ref (table, key, dflt, scm_ihashv, scm_sloppy_assv, 0);
0f2d19dd 696}
1bbd0b84 697#undef FUNC_NAME
0f2d19dd
JB
698
699
700
a1ec6916 701SCM_DEFINE (scm_hashv_set_x, "hashv-set!", 3, 0, 0,
1e6808ea 702 (SCM table, SCM key, SCM val),
5352393c
MG
703 "Find the entry in @var{table} associated with @var{key}, and\n"
704 "store @var{value} there. Uses @code{eqv?} for equality testing.")
1bbd0b84 705#define FUNC_NAME s_scm_hashv_set_x
0f2d19dd 706{
1e6808ea 707 return scm_hash_fn_set_x (table, key, val, scm_ihashv, scm_sloppy_assv, 0);
0f2d19dd 708}
1bbd0b84 709#undef FUNC_NAME
0f2d19dd
JB
710
711
a1ec6916 712SCM_DEFINE (scm_hashv_remove_x, "hashv-remove!", 2, 0, 0,
1e6808ea 713 (SCM table, SCM key),
5352393c
MG
714 "Remove @var{key} (and any value associated with it) from\n"
715 "@var{table}. Uses @code{eqv?} for equality tests.")
1bbd0b84 716#define FUNC_NAME s_scm_hashv_remove_x
0f2d19dd 717{
1e6808ea
MG
718 return scm_hash_fn_remove_x (table, key, scm_ihashv, scm_sloppy_assv,
719 scm_delv_x, 0);
0f2d19dd 720}
1bbd0b84 721#undef FUNC_NAME
0f2d19dd
JB
722
723\f
724
a1ec6916 725SCM_DEFINE (scm_hash_get_handle, "hash-get-handle", 2, 0, 0,
22a52da1
DH
726 (SCM table, SCM key),
727 "This procedure returns the @code{(key . value)} pair from the\n"
728 "hash table @var{table}. If @var{table} does not hold an\n"
729 "associated value for @var{key}, @code{#f} is returned.\n"
730 "Uses @code{equal?} for equality testing.")
1bbd0b84 731#define FUNC_NAME s_scm_hash_get_handle
0f2d19dd 732{
22a52da1 733 return scm_hash_fn_get_handle (table, key, scm_ihash, scm_sloppy_assoc, 0);
0f2d19dd 734}
1bbd0b84 735#undef FUNC_NAME
0f2d19dd
JB
736
737
a1ec6916 738SCM_DEFINE (scm_hash_create_handle_x, "hash-create-handle!", 3, 0, 0,
d550d22a
GB
739 (SCM table, SCM key, SCM init),
740 "This function looks up @var{key} in @var{table} and returns its handle.\n"
741 "If @var{key} is not already present, a new handle is created which\n"
742 "associates @var{key} with @var{init}.")
1bbd0b84 743#define FUNC_NAME s_scm_hash_create_handle_x
0f2d19dd 744{
d550d22a 745 return scm_hash_fn_create_handle_x (table, key, init, scm_ihash, scm_sloppy_assoc, 0);
0f2d19dd 746}
1bbd0b84 747#undef FUNC_NAME
0f2d19dd
JB
748
749
a1ec6916 750SCM_DEFINE (scm_hash_ref, "hash-ref", 2, 1, 0,
1e6808ea 751 (SCM table, SCM key, SCM dflt),
d550d22a
GB
752 "Look up @var{key} in the hash table @var{table}, and return the\n"
753 "value (if any) associated with it. If @var{key} is not found,\n"
5352393c
MG
754 "return @var{default} (or @code{#f} if no @var{default} argument\n"
755 "is supplied). Uses @code{equal?} for equality testing.")
1bbd0b84 756#define FUNC_NAME s_scm_hash_ref
0f2d19dd 757{
54778cd3 758 if (SCM_UNBNDP (dflt))
0f2d19dd 759 dflt = SCM_BOOL_F;
1e6808ea 760 return scm_hash_fn_ref (table, key, dflt, scm_ihash, scm_sloppy_assoc, 0);
0f2d19dd 761}
1bbd0b84 762#undef FUNC_NAME
0f2d19dd
JB
763
764
765
a1ec6916 766SCM_DEFINE (scm_hash_set_x, "hash-set!", 3, 0, 0,
1e6808ea 767 (SCM table, SCM key, SCM val),
5352393c
MG
768 "Find the entry in @var{table} associated with @var{key}, and\n"
769 "store @var{value} there. Uses @code{equal?} for equality\n"
770 "testing.")
1bbd0b84 771#define FUNC_NAME s_scm_hash_set_x
0f2d19dd 772{
1e6808ea 773 return scm_hash_fn_set_x (table, key, val, scm_ihash, scm_sloppy_assoc, 0);
0f2d19dd 774}
1bbd0b84 775#undef FUNC_NAME
0f2d19dd
JB
776
777
778
a1ec6916 779SCM_DEFINE (scm_hash_remove_x, "hash-remove!", 2, 0, 0,
1e6808ea 780 (SCM table, SCM key),
5352393c
MG
781 "Remove @var{key} (and any value associated with it) from\n"
782 "@var{table}. Uses @code{equal?} for equality tests.")
1bbd0b84 783#define FUNC_NAME s_scm_hash_remove_x
0f2d19dd 784{
1e6808ea
MG
785 return scm_hash_fn_remove_x (table, key, scm_ihash, scm_sloppy_assoc,
786 scm_delete_x, 0);
0f2d19dd 787}
1bbd0b84 788#undef FUNC_NAME
0f2d19dd
JB
789
790\f
791
792
92c2555f 793typedef struct scm_t_ihashx_closure
0f2d19dd
JB
794{
795 SCM hash;
796 SCM assoc;
797 SCM delete;
92c2555f 798} scm_t_ihashx_closure;
0f2d19dd
JB
799
800
1cc91f1b 801
c014a02e 802static unsigned long
92c2555f 803scm_ihashx (SCM obj, unsigned long n, scm_t_ihashx_closure *closure)
0f2d19dd 804{
87ca11ff
MD
805 SCM answer = scm_call_2 (closure->hash,
806 obj,
807 scm_ulong2num ((unsigned long) n));
0f2d19dd
JB
808 return SCM_INUM (answer);
809}
810
811
1cc91f1b 812
0f2d19dd 813static SCM
92c2555f 814scm_sloppy_assx (SCM obj, SCM alist, scm_t_ihashx_closure *closure)
0f2d19dd 815{
87ca11ff 816 return scm_call_2 (closure->assoc, obj, alist);
0f2d19dd
JB
817}
818
819
820
1cc91f1b 821
0f2d19dd 822static SCM
92c2555f 823scm_delx_x (SCM obj, SCM alist, scm_t_ihashx_closure *closure)
0f2d19dd 824{
87ca11ff 825 return scm_call_2 (closure->delete, obj, alist);
0f2d19dd
JB
826}
827
828
829
a1ec6916 830SCM_DEFINE (scm_hashx_get_handle, "hashx-get-handle", 4, 0, 0,
1e6808ea
MG
831 (SCM hash, SCM assoc, SCM table, SCM key),
832 "This behaves the same way as the corresponding\n"
833 "@code{-get-handle} function, but uses @var{hash} as a hash\n"
834 "function and @var{assoc} to compare keys. @code{hash} must be\n"
835 "a function that takes two arguments, a key to be hashed and a\n"
d550d22a
GB
836 "table size. @code{assoc} must be an associator function, like\n"
837 "@code{assoc}, @code{assq} or @code{assv}.")
1bbd0b84 838#define FUNC_NAME s_scm_hashx_get_handle
0f2d19dd 839{
92c2555f 840 scm_t_ihashx_closure closure;
0f2d19dd
JB
841 closure.hash = hash;
842 closure.assoc = assoc;
1e6808ea 843 return scm_hash_fn_get_handle (table, key, scm_ihashx, scm_sloppy_assx,
87ca11ff 844 (void *) &closure);
0f2d19dd 845}
1bbd0b84 846#undef FUNC_NAME
0f2d19dd
JB
847
848
a1ec6916 849SCM_DEFINE (scm_hashx_create_handle_x, "hashx-create-handle!", 5, 0, 0,
1e6808ea
MG
850 (SCM hash, SCM assoc, SCM table, SCM key, SCM init),
851 "This behaves the same way as the corresponding\n"
852 "@code{-create-handle} function, but uses @var{hash} as a hash\n"
853 "function and @var{assoc} to compare keys. @code{hash} must be\n"
854 "a function that takes two arguments, a key to be hashed and a\n"
d550d22a
GB
855 "table size. @code{assoc} must be an associator function, like\n"
856 "@code{assoc}, @code{assq} or @code{assv}.")
1bbd0b84 857#define FUNC_NAME s_scm_hashx_create_handle_x
0f2d19dd 858{
92c2555f 859 scm_t_ihashx_closure closure;
0f2d19dd
JB
860 closure.hash = hash;
861 closure.assoc = assoc;
1e6808ea
MG
862 return scm_hash_fn_create_handle_x (table, key, init, scm_ihashx,
863 scm_sloppy_assx, (void *)&closure);
0f2d19dd 864}
1bbd0b84 865#undef FUNC_NAME
0f2d19dd
JB
866
867
868
a1ec6916 869SCM_DEFINE (scm_hashx_ref, "hashx-ref", 4, 1, 0,
1e6808ea 870 (SCM hash, SCM assoc, SCM table, SCM key, SCM dflt),
d550d22a 871 "This behaves the same way as the corresponding @code{ref}\n"
1e6808ea
MG
872 "function, but uses @var{hash} as a hash function and\n"
873 "@var{assoc} to compare keys. @code{hash} must be a function\n"
874 "that takes two arguments, a key to be hashed and a table size.\n"
875 "@code{assoc} must be an associator function, like @code{assoc},\n"
876 "@code{assq} or @code{assv}.\n"
877 "\n"
878 "By way of illustration, @code{hashq-ref table key} is\n"
879 "equivalent to @code{hashx-ref hashq assq table key}.")
1bbd0b84 880#define FUNC_NAME s_scm_hashx_ref
0f2d19dd 881{
92c2555f 882 scm_t_ihashx_closure closure;
54778cd3 883 if (SCM_UNBNDP (dflt))
0f2d19dd
JB
884 dflt = SCM_BOOL_F;
885 closure.hash = hash;
886 closure.assoc = assoc;
1e6808ea
MG
887 return scm_hash_fn_ref (table, key, dflt, scm_ihashx, scm_sloppy_assx,
888 (void *)&closure);
0f2d19dd 889}
1bbd0b84 890#undef FUNC_NAME
0f2d19dd
JB
891
892
893
894
a1ec6916 895SCM_DEFINE (scm_hashx_set_x, "hashx-set!", 5, 0, 0,
1e6808ea 896 (SCM hash, SCM assoc, SCM table, SCM key, SCM val),
d550d22a 897 "This behaves the same way as the corresponding @code{set!}\n"
1e6808ea
MG
898 "function, but uses @var{hash} as a hash function and\n"
899 "@var{assoc} to compare keys. @code{hash} must be a function\n"
900 "that takes two arguments, a key to be hashed and a table size.\n"
901 "@code{assoc} must be an associator function, like @code{assoc},\n"
902 "@code{assq} or @code{assv}.\n"
903 "\n"
904 " By way of illustration, @code{hashq-set! table key} is\n"
905 "equivalent to @code{hashx-set! hashq assq table key}.")
1bbd0b84 906#define FUNC_NAME s_scm_hashx_set_x
0f2d19dd 907{
92c2555f 908 scm_t_ihashx_closure closure;
0f2d19dd
JB
909 closure.hash = hash;
910 closure.assoc = assoc;
1e6808ea
MG
911 return scm_hash_fn_set_x (table, key, val, scm_ihashx, scm_sloppy_assx,
912 (void *)&closure);
0f2d19dd 913}
1bbd0b84 914#undef FUNC_NAME
0f2d19dd
JB
915
916
1cc91f1b 917
0f2d19dd 918SCM
1be6b49c 919scm_hashx_remove_x (SCM hash, SCM assoc, SCM delete, SCM table, SCM obj)
0f2d19dd 920{
92c2555f 921 scm_t_ihashx_closure closure;
0f2d19dd
JB
922 closure.hash = hash;
923 closure.assoc = assoc;
924 closure.delete = delete;
925 return scm_hash_fn_remove_x (table, obj, scm_ihashx, scm_sloppy_assx, scm_delx_x, 0);
926}
927
b94903c2
MD
928static SCM
929fold_proc (void *proc, SCM key, SCM data, SCM value)
930{
fdc28395 931 return scm_call_3 (SCM_PACK (proc), key, data, value);
b94903c2
MD
932}
933
a1ec6916 934SCM_DEFINE (scm_hash_fold, "hash-fold", 3, 0, 0,
1bbd0b84 935 (SCM proc, SCM init, SCM table),
d550d22a
GB
936 "An iterator over hash-table elements.\n"
937 "Accumulates and returns a result by applying PROC successively.\n"
938 "The arguments to PROC are \"(key value prior-result)\" where key\n"
939 "and value are successive pairs from the hash table TABLE, and\n"
940 "prior-result is either INIT (for the first application of PROC)\n"
941 "or the return value of the previous application of PROC.\n"
72dd0a03 942 "For example, @code{(hash-fold acons '() tab)} will convert a hash\n"
9401323e 943 "table into an a-list of key-value pairs.")
1bbd0b84 944#define FUNC_NAME s_scm_hash_fold
b94903c2 945{
34d19ef6 946 SCM_VALIDATE_PROC (1, proc);
87ca11ff
MD
947 if (!SCM_HASHTABLE_P (table))
948 SCM_VALIDATE_VECTOR (3, table);
54778cd3 949 return scm_internal_hash_fold (fold_proc, (void *) SCM_UNPACK (proc), init, table);
b94903c2 950}
1bbd0b84 951#undef FUNC_NAME
c7df61cd
MD
952
953SCM
8cd5191b 954scm_internal_hash_fold (SCM (*fn) (), void *closure, SCM init, SCM table)
c7df61cd 955{
87ca11ff
MD
956 long i, n;
957 SCM buckets, result = init;
87ca11ff
MD
958
959 if (SCM_HASHTABLE_P (table))
0a4c1355 960 buckets = SCM_HASHTABLE_VECTOR (table);
87ca11ff 961 else
0a4c1355
MD
962 buckets = table;
963
87ca11ff 964 n = SCM_VECTOR_LENGTH (buckets);
c7df61cd
MD
965 for (i = 0; i < n; ++i)
966 {
87ca11ff 967 SCM ls = SCM_VELTS (buckets)[i], handle;
22a52da1 968 while (!SCM_NULLP (ls))
c7df61cd 969 {
87ca11ff 970 if (!SCM_CONSP (ls))
0a4c1355 971 scm_wrong_type_arg (s_scm_hash_fold, SCM_ARG3, buckets);
c7df61cd 972 handle = SCM_CAR (ls);
87ca11ff 973 if (!SCM_CONSP (handle))
0a4c1355 974 scm_wrong_type_arg (s_scm_hash_fold, SCM_ARG3, buckets);
c7df61cd
MD
975 result = fn (closure, SCM_CAR (handle), SCM_CDR (handle), result);
976 ls = SCM_CDR (ls);
977 }
978 }
87ca11ff 979
c7df61cd
MD
980 return result;
981}
982
c35738c1
MD
983static SCM
984for_each_proc (void *proc, SCM key, SCM data, SCM value)
985{
986 return scm_call_2 (SCM_PACK (proc), key, data);
987}
988
989SCM_DEFINE (scm_hash_for_each, "hash-for-each", 2, 0, 0,
990 (SCM proc, SCM table),
991 "An iterator over hash-table elements.\n"
992 "Applies PROC successively on all hash table items.\n"
993 "The arguments to PROC are \"(key value)\" where key\n"
994 "and value are successive pairs from the hash table TABLE.")
995#define FUNC_NAME s_scm_hash_for_each
996{
997 SCM_VALIDATE_PROC (1, proc);
998 if (!SCM_HASHTABLE_P (table))
999 SCM_VALIDATE_VECTOR (2, table);
1000 scm_internal_hash_fold (for_each_proc,
1001 (void *) SCM_UNPACK (proc),
1002 SCM_BOOL_F,
1003 table);
1004 return SCM_UNSPECIFIED;
1005}
1006#undef FUNC_NAME
1007
1008static SCM
1009map_proc (void *proc, SCM key, SCM data, SCM value)
1010{
1011 return scm_cons (scm_call_2 (SCM_PACK (proc), key, data), value);
1012}
1013
1014SCM_DEFINE (scm_hash_map, "hash-map", 2, 0, 0,
1015 (SCM proc, SCM table),
1016 "An iterator over hash-table elements.\n"
1017 "Accumulates and returns as a list the results of applying PROC successively.\n"
1018 "The arguments to PROC are \"(key value)\" where key\n"
1019 "and value are successive pairs from the hash table TABLE.")
1020#define FUNC_NAME s_scm_hash_map
1021{
1022 SCM_VALIDATE_PROC (1, proc);
1023 if (!SCM_HASHTABLE_P (table))
1024 SCM_VALIDATE_VECTOR (2, table);
1025 return scm_internal_hash_fold (map_proc,
1026 (void *) SCM_UNPACK (proc),
1027 SCM_EOL,
1028 table);
1029}
1030#undef FUNC_NAME
1031
0f2d19dd
JB
1032\f
1033
1cc91f1b 1034
0f2d19dd 1035void
c35738c1 1036scm_hashtab_prehistory ()
0f2d19dd 1037{
f59a096e
MD
1038 scm_tc16_hashtable = scm_make_smob_type (s_hashtable, 0);
1039 scm_set_smob_mark (scm_tc16_hashtable, scm_markcdr);
1040 scm_set_smob_print (scm_tc16_hashtable, hashtable_print);
1041 scm_set_smob_free (scm_tc16_hashtable, hashtable_free);
c35738c1
MD
1042 scm_c_hook_add (&scm_after_sweep_c_hook, scan_weak_hashtables, 0, 0);
1043 scm_c_hook_add (&scm_after_gc_c_hook, rehash_after_gc, 0, 0);
1044}
1045
1046void
1047scm_init_hashtab ()
1048{
a0599745 1049#include "libguile/hashtab.x"
0f2d19dd 1050}
89e00824
ML
1051
1052/*
1053 Local Variables:
1054 c-file-style: "gnu"
1055 End:
1056*/