annotate src/elhash.c @ 617:af57a77cbc92

[xemacs-hg @ 2001-06-18 07:09:50 by ben] --------------------------------------------------------------- DOCUMENTATION FIXES: --------------------------------------------------------------- eval.c: Correct documentation. elhash.c: Doc correction. --------------------------------------------------------------- LISP OBJECT CLEANUP: --------------------------------------------------------------- bytecode.h, buffer.h, casetab.h, chartab.h, console-msw.h, console.h, database.c, device.h, eldap.h, elhash.h, events.h, extents.h, faces.h, file-coding.h, frame.h, glyphs.h, gui-x.h, gui.h, keymap.h, lisp-disunion.h, lisp-union.h, lisp.h, lrecord.h, lstream.h, mule-charset.h, objects.h, opaque.h, postgresql.h, process.h, rangetab.h, specifier.h, toolbar.h, tooltalk.h, ui-gtk.h: Add wrap_* to all objects (it was already there for a few of them) -- an expression to encapsulate a pointer into a Lisp object, rather than the inconvenient XSET*. "wrap" was chosen because "make" as in make_int(), make_char() is not appropriate. (It implies allocation. The issue does not exist for ints and chars because they are not allocated.) Full error checking has been added to these expressions. When used without error checking, non-union build, use of these expressions will incur no loss of efficiency. (In fact, XSET* is now defined in terms of wrap_* in a non-union build.) In a union build, you will also get no loss of efficiency provided that you have a decent optimizing compiler, and a compiler that either understands inlines or automatically inlines those particular functions. (And since people don't normally do their production builds on union, it doesn't matter.) Update the sample Lisp object definition in lrecord.h accordingly. dumper.c: Fix places in dumper that referenced wrap_object to reference its new name, wrap_pointer_1. buffer.c, bufslots.h, conslots.h, console.c, console.h, devslots.h, device.c, device.h, frame.c, frame.h, frameslots.h, window.c, window.h, winslots.h: -- Extract out the Lisp objects of `struct device' into devslots.h, just like for the other structures. -- Extract out the remaining (not copied into the window config) Lisp objects in `struct window' into winslots.h; use different macros (WINDOW_SLOT vs. WINDOW_SAVED_SLOT) to differentiate them. -- Eliminate the `dead' flag of `struct frame', since it duplicates information already available in `framemeths', and fix FRAME_LIVE_P accordingly. (Devices and consoles already work this way.) -- In *slots.h, switch to system where MARKED_SLOT is automatically undef'd at the end of the file. (Follows what winslots.h already does.) -- Update the comments at the beginning of *slots.h to be accurate. -- When making any of the above objects dead, zero it out entirely and reset all Lisp object slots to Qnil. (We were already doing this somewhat, but not consistently.) This (1) Eliminates the possibility of extra objects hanging around that ought to be GC'd, (2) Causes an immediate crash if anyone tries to access a structure in one of these objects, (3) Ensures consistent behavior wrt dead objects. dialog-msw.c: Use internal_object_printer, since this object should not escape. --------------------------------------------------------------- FIXING A CRASH THAT I HIT ONCE (AND A RELATED BAD BEHAVIOR): --------------------------------------------------------------- eval.c: Fix up some comments about the FSF implementation. Fix two nasty bugs: (1) condition_case_unwind frees the conses sitting in the catch->tag slot too quickly, resulting in a crash that I hit. (2) catches need to be unwound one at a time when calling unwind-protect code, rather than all at once at the end; otherwise, incorrect behavior can result. (A comment shows exactly how.) backtrace.h: Improve comment about FSF differences in the handler stack. --------------------------------------------------------------- FIXING A CRASH THAT I REPEATEDLY HIT WHEN USING THE MOUSE WHEEL UNDER MSWINDOWS: --------------------------------------------------------------- Basic idea: My crash is due either to a dead, non-marked, GC-collected frame inside of a window mirror, or a prematurely freed window mirror. We need to mark the Lisp objects inside of window mirrors. Tracking the lifespan of window mirrors and scrollbar instances is extremely hard, and there may well be lurking bugs where such objects are freed too soon. The only safe way to fix these problems (and it fixes both problems at once) is to make both of these structures Lisp objects. lrecord.h, emacs.c, inline.c, scrollbar-gtk.c, scrollbar-msw.c, scrollbar-x.c, scrollbar.c, scrollbar.h, symsinit.h: Make scrollbar instances actual Lisp objects. Mark the window mirrors in them. inline.c needs to know about scrollbar.h now. Record the new type in lrecord.h. Fix up scrollbar-*.c appropriately. Create a hash table in scrollbar-msw.c so that the scrollbar instances stored in scrollbar HWND's are properly GC-protected. Create complex_vars_of_scrollbar_mswindows() to create the hash table at startup, and call it from emacs.c. Don't store the scrollbar instance as a property of the GTK scrollbar, as it's not used and if we did this, we'd have to separately GC-protect it in a hash table, like in MS Windows. lrecord.h, frame.h, frame.c, frameslots.h, redisplay.c, window.c, window.h: Move mark_window_mirror from redisplay.c to window.c. Make window mirrors actual Lisp objects. Tell lrecord.h about them. Change the window mirror member of struct frame from a pointer to a Lisp object, and add XWINDOW_MIRROR in appropriate places. Mark the scrollbar instances in the window mirror. redisplay.c, redisplay.h, alloc.c: Delete mark_redisplay. Don't call mark_redisplay. We now mark frame-specific structures in mark_frame. NOTE: I also deleted an extremely questionable call to update_frame_window_mirrors(). It was extremely questionable before, and now totally impossible, since it will create Lisp objects during redisplay. frame.c: Mark the scrollbar instances, which are now Lisp objects. Call mark_gutter() here, not in mark_redisplay(). gutter.c: Update comments about correct marking. --------------------------------------------------------------- ISSUES BROUGHT UP BY MARTIN: --------------------------------------------------------------- buffer.h: Put back these macros the way Steve T and I think they ought to be. I already explained in a previous changelog entry why I think these macros should be the way I'd defined them. Once again: We fix these macros so they don't care about the type of their lvalues. The non-C-string equivalents of these already function in the same way, and it's correct because it should be OK to pass in a CBufbyte *, a BufByte *, a Char_Binary *, an UChar_Binary *, etc. The whole reason for these different types is to work around errors caused by signed-vs-unsigned non-matching types. Any possible error that might be caught in a DFC macro would also be caught wherever the argument is used elsewhere. So creating multiple macro versions would add no useful error-checking and just further complicate an already complicated area. As for Martin's "ANSI aliasing" bug, XEmacs is not ANSI-aliasing clean and probably never will be. Unless the board agrees to change XEmacs in this way (and we really don't want to go down that road), this is not a bug. sound.h: Undo Martin's type change. signal.c: Fix problem identified by Martin with Linux and g++ due to non-standard declaration of setitimer(). systime.h: Update the docs for "qxe_" to point out why making the encapsulation explicit is always the right way to go. (setitimer() itself serves as an example.) For 21.4: update-elc-2.el: Correct misplaced parentheses, making lisp/mule not get recompiled.
author ben
date Mon, 18 Jun 2001 07:10:32 +0000
parents 190b164ddcac
children b39c14581166
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1 /* Implementation of the hash table lisp object type.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
2 Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
3 Copyright (C) 1995, 1996 Ben Wing.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
4 Copyright (C) 1997 Free Software Foundation, Inc.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
5
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
6 This file is part of XEmacs.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
7
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
8 XEmacs is free software; you can redistribute it and/or modify it
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
9 under the terms of the GNU General Public License as published by the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
10 Free Software Foundation; either version 2, or (at your option) any
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
11 later version.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
12
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
14 ANY WARRANTY; without even the implied warranty of MERCNTABILITY or
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
16 for more details.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
17
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
18 You should have received a copy of the GNU General Public License
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
19 along with XEmacs; see the file COPYING. If not, write to
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
21 Boston, MA 02111-1307, USA. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
22
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
23 /* Synched up with: Not in FSF. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
24
489
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
25 /* This file implements the hash table lisp object type.
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
26
504
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
27 This implementation was mostly written by Martin Buchholz in 1997.
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
28
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
29 The Lisp-level API (derived from Common Lisp) is almost completely
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
30 compatible with GNU Emacs 21, even though the implementations are
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
31 totally independent.
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
32
489
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
33 The hash table technique used is "linear probing". Collisions are
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
34 resolved by putting the item in the next empty place in the array
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
35 following the collision. Finding a hash entry performs a linear
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
36 search in the cluster starting at the hash value.
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
37
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
38 On deletions from the hash table, the entries immediately following
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
39 the deleted entry are re-entered in the hash table. We do not have
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
40 a special way to mark deleted entries (known as "tombstones").
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
41
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
42 At the end of the hash entries ("hentries"), we leave room for an
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
43 entry that is always empty (the "sentinel").
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
44
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
45 The traditional literature on hash table implementation
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
46 (e.g. Knuth) suggests that too much "primary clustering" occurs
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
47 with linear probing. However, this literature was written when
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
48 locality of reference was not a factor. The discrepancy between
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
49 CPU speeds and memory speeds is increasing, and the speed of access
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
50 to memory is highly dependent on memory caches which work best when
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
51 there is high locality of data reference. Random access to memory
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
52 is up to 20 times as expensive as access to the nearest address
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
53 (and getting worse). So linear probing makes sense.
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
54
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
55 But the representation doesn't actually matter that much with the
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
56 current elisp engine. Funcall is sufficiently slow that the choice
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
57 of hash table implementation is noise. */
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
58
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
59 #include <config.h>
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
60 #include "lisp.h"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
61 #include "bytecode.h"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
62 #include "elhash.h"
489
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
63 #include "opaque.h"
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
64
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
65 Lisp_Object Qhash_tablep;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
66 static Lisp_Object Qhashtable, Qhash_table;
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
67 static Lisp_Object Qweakness, Qvalue, Qkey_or_value, Qkey_and_value;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
68 static Lisp_Object Vall_weak_hash_tables;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
69 static Lisp_Object Qrehash_size, Qrehash_threshold;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
70 static Lisp_Object Q_size, Q_test, Q_weakness, Q_rehash_size, Q_rehash_threshold;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
71
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
72 /* obsolete as of 19990901 in xemacs-21.2 */
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
73 static Lisp_Object Qweak, Qkey_weak, Qvalue_weak, Qkey_or_value_weak;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
74 static Lisp_Object Qnon_weak, Q_type;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
75
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
76 typedef struct hentry
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
77 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
78 Lisp_Object key;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
79 Lisp_Object value;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
80 } hentry;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
81
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
82 struct Lisp_Hash_Table
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
83 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
84 struct lcrecord_header header;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
85 size_t size;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
86 size_t count;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
87 size_t rehash_count;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
88 double rehash_size;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
89 double rehash_threshold;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
90 size_t golden_ratio;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
91 hash_table_hash_function_t hash_function;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
92 hash_table_test_function_t test_function;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
93 hentry *hentries;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
94 enum hash_table_weakness weakness;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
95 Lisp_Object next_weak; /* Used to chain together all of the weak
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
96 hash tables. Don't mark through this. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
97 };
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
98
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
99 #define HENTRY_CLEAR_P(hentry) ((*(EMACS_UINT*)(&((hentry)->key))) == 0)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
100 #define CLEAR_HENTRY(hentry) \
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
101 ((*(EMACS_UINT*)(&((hentry)->key))) = 0, \
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
102 (*(EMACS_UINT*)(&((hentry)->value))) = 0)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
103
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
104 #define HASH_TABLE_DEFAULT_SIZE 16
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
105 #define HASH_TABLE_DEFAULT_REHASH_SIZE 1.3
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
106 #define HASH_TABLE_MIN_SIZE 10
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
107
434
9d177e8d4150 Import from CVS: tag r21-2-25
cvs
parents: 432
diff changeset
108 #define HASH_CODE(key, ht) \
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 442
diff changeset
109 ((((ht)->hash_function ? (ht)->hash_function (key) : LISP_HASH (key)) \
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 442
diff changeset
110 * (ht)->golden_ratio) \
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 442
diff changeset
111 % (ht)->size)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
112
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
113 #define KEYS_EQUAL_P(key1, key2, testfun) \
434
9d177e8d4150 Import from CVS: tag r21-2-25
cvs
parents: 432
diff changeset
114 (EQ (key1, key2) || ((testfun) && (testfun) (key1, key2)))
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
115
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
116 #define LINEAR_PROBING_LOOP(probe, entries, size) \
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
117 for (; \
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
118 !HENTRY_CLEAR_P (probe) || \
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
119 (probe == entries + size ? \
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
120 (probe = entries, !HENTRY_CLEAR_P (probe)) : 0); \
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
121 probe++)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
122
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
123 #ifndef ERROR_CHECK_HASH_TABLE
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
124 # ifdef ERROR_CHECK_TYPECHECK
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
125 # define ERROR_CHECK_HASH_TABLE 1
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
126 # else
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
127 # define ERROR_CHECK_HASH_TABLE 0
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
128 # endif
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
129 #endif
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
130
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
131 #if ERROR_CHECK_HASH_TABLE
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
132 static void
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
133 check_hash_table_invariants (Lisp_Hash_Table *ht)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
134 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
135 assert (ht->count < ht->size);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
136 assert (ht->count <= ht->rehash_count);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
137 assert (ht->rehash_count < ht->size);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
138 assert ((double) ht->count * ht->rehash_threshold - 1 <= (double) ht->rehash_count);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
139 assert (HENTRY_CLEAR_P (ht->hentries + ht->size));
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
140 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
141 #else
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
142 #define check_hash_table_invariants(ht)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
143 #endif
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
144
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
145 /* Return a suitable size for a hash table, with at least SIZE slots. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
146 static size_t
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
147 hash_table_size (size_t requested_size)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
148 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
149 /* Return some prime near, but greater than or equal to, SIZE.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
150 Decades from the time of writing, someone will have a system large
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
151 enough that the list below will be too short... */
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
152 static const size_t primes [] =
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
153 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
154 19, 29, 41, 59, 79, 107, 149, 197, 263, 347, 457, 599, 787, 1031,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
155 1361, 1777, 2333, 3037, 3967, 5167, 6719, 8737, 11369, 14783,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
156 19219, 24989, 32491, 42257, 54941, 71429, 92861, 120721, 156941,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
157 204047, 265271, 344857, 448321, 582821, 757693, 985003, 1280519,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
158 1664681, 2164111, 2813353, 3657361, 4754591, 6180989, 8035301,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
159 10445899, 13579681, 17653589, 22949669, 29834603, 38784989,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
160 50420551, 65546729, 85210757, 110774011, 144006217, 187208107,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
161 243370577, 316381771, 411296309, 534685237, 695090819, 903618083,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
162 1174703521, 1527114613, 1985248999, 2580823717UL, 3355070839UL
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
163 };
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
164 /* We've heard of binary search. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
165 int low, high;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
166 for (low = 0, high = countof (primes) - 1; high - low > 1;)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
167 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
168 /* Loop Invariant: size < primes [high] */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
169 int mid = (low + high) / 2;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
170 if (primes [mid] < requested_size)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
171 low = mid;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
172 else
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
173 high = mid;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
174 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
175 return primes [high];
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
176 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
177
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
178
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
179 #if 0 /* I don't think these are needed any more.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
180 If using the general lisp_object_equal_*() functions
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
181 causes efficiency problems, these can be resurrected. --ben */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
182 /* equality and hash functions for Lisp strings */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
183 int
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
184 lisp_string_equal (Lisp_Object str1, Lisp_Object str2)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
185 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
186 /* This is wrong anyway. You can't use strcmp() on Lisp strings,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
187 because they can contain zero characters. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
188 return !strcmp ((char *) XSTRING_DATA (str1), (char *) XSTRING_DATA (str2));
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
189 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
190
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
191 static hashcode_t
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
192 lisp_string_hash (Lisp_Object obj)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
193 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
194 return hash_string (XSTRING_DATA (str), XSTRING_LENGTH (str));
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
195 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
196
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
197 #endif /* 0 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
198
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
199 static int
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
200 lisp_object_eql_equal (Lisp_Object obj1, Lisp_Object obj2)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
201 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
202 return EQ (obj1, obj2) || (FLOATP (obj1) && internal_equal (obj1, obj2, 0));
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
203 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
204
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
205 static hashcode_t
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
206 lisp_object_eql_hash (Lisp_Object obj)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
207 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
208 return FLOATP (obj) ? internal_hash (obj, 0) : LISP_HASH (obj);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
209 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
210
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
211 static int
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
212 lisp_object_equal_equal (Lisp_Object obj1, Lisp_Object obj2)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
213 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
214 return internal_equal (obj1, obj2, 0);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
215 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
216
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
217 static hashcode_t
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
218 lisp_object_equal_hash (Lisp_Object obj)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
219 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
220 return internal_hash (obj, 0);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
221 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
222
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
223
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
224 static Lisp_Object
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
225 mark_hash_table (Lisp_Object obj)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
226 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
227 Lisp_Hash_Table *ht = XHASH_TABLE (obj);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
228
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
229 /* If the hash table is weak, we don't want to mark the keys and
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
230 values (we scan over them after everything else has been marked,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
231 and mark or remove them as necessary). */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
232 if (ht->weakness == HASH_TABLE_NON_WEAK)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
233 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
234 hentry *e, *sentinel;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
235
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
236 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
237 if (!HENTRY_CLEAR_P (e))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
238 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
239 mark_object (e->key);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
240 mark_object (e->value);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
241 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
242 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
243 return Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
244 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
245
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
246 /* Equality of hash tables. Two hash tables are equal when they are of
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
247 the same weakness and test function, they have the same number of
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
248 elements, and for each key in the hash table, the values are `equal'.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
249
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
250 This is similar to Common Lisp `equalp' of hash tables, with the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
251 difference that CL requires the keys to be compared with the test
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
252 function, which we don't do. Doing that would require consing, and
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
253 consing is a bad idea in `equal'. Anyway, our method should provide
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
254 the same result -- if the keys are not equal according to the test
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
255 function, then Fgethash() in hash_table_equal_mapper() will fail. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
256 static int
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
257 hash_table_equal (Lisp_Object hash_table1, Lisp_Object hash_table2, int depth)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
258 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
259 Lisp_Hash_Table *ht1 = XHASH_TABLE (hash_table1);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
260 Lisp_Hash_Table *ht2 = XHASH_TABLE (hash_table2);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
261 hentry *e, *sentinel;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
262
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
263 if ((ht1->test_function != ht2->test_function) ||
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
264 (ht1->weakness != ht2->weakness) ||
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
265 (ht1->count != ht2->count))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
266 return 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
267
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
268 depth++;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
269
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
270 for (e = ht1->hentries, sentinel = e + ht1->size; e < sentinel; e++)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
271 if (!HENTRY_CLEAR_P (e))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
272 /* Look up the key in the other hash table, and compare the values. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
273 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
274 Lisp_Object value_in_other = Fgethash (e->key, hash_table2, Qunbound);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
275 if (UNBOUNDP (value_in_other) ||
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
276 !internal_equal (e->value, value_in_other, depth))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
277 return 0; /* Give up */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
278 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
279
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
280 return 1;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
281 }
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
282
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
283 /* This is not a great hash function, but it _is_ correct and fast.
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
284 Examining all entries is too expensive, and examining a random
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
285 subset does not yield a correct hash function. */
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
286 static hashcode_t
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
287 hash_table_hash (Lisp_Object hash_table, int depth)
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
288 {
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
289 return XHASH_TABLE (hash_table)->count;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
290 }
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
291
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
292
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
293 /* Printing hash tables.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
294
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
295 This is non-trivial, because we use a readable structure-style
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
296 syntax for hash tables. This means that a typical hash table will be
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
297 readably printed in the form of:
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
298
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
299 #s(hash-table size 2 data (key1 value1 key2 value2))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
300
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
301 The supported hash table structure keywords and their values are:
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
302 `test' (eql (or nil), eq or equal)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
303 `size' (a natnum or nil)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
304 `rehash-size' (a float)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
305 `rehash-threshold' (a float)
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
306 `weakness' (nil, key, value, key-and-value, or key-or-value)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
307 `data' (a list)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
308
430
a5df635868b2 Import from CVS: tag r21-2-23
cvs
parents: 428
diff changeset
309 If `print-readably' is nil, then a simpler syntax is used, for example
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
310
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
311 #<hash-table size 2/13 data (key1 value1 key2 value2) 0x874d>
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
312
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
313 The data is truncated to four pairs, and the rest is shown with
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
314 `...'. This printer does not cons. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
315
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
316
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
317 /* Print the data of the hash table. This maps through a Lisp
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
318 hash table and prints key/value pairs using PRINTCHARFUN. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
319 static void
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
320 print_hash_table_data (Lisp_Hash_Table *ht, Lisp_Object printcharfun)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
321 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
322 int count = 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
323 hentry *e, *sentinel;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
324
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
325 write_c_string (" data (", printcharfun);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
326
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
327 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
328 if (!HENTRY_CLEAR_P (e))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
329 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
330 if (count > 0)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
331 write_c_string (" ", printcharfun);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
332 if (!print_readably && count > 3)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
333 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
334 write_c_string ("...", printcharfun);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
335 break;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
336 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
337 print_internal (e->key, printcharfun, 1);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
338 write_c_string (" ", printcharfun);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
339 print_internal (e->value, printcharfun, 1);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
340 count++;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
341 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
342
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
343 write_c_string (")", printcharfun);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
344 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
345
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
346 static void
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
347 print_hash_table (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
348 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
349 Lisp_Hash_Table *ht = XHASH_TABLE (obj);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
350 char buf[128];
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
351
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
352 write_c_string (print_readably ? "#s(hash-table" : "#<hash-table",
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
353 printcharfun);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
354
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
355 /* These checks have a kludgy look to them, but they are safe.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
356 Due to nature of hashing, you cannot use arbitrary
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
357 test functions anyway. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
358 if (!ht->test_function)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
359 write_c_string (" test eq", printcharfun);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
360 else if (ht->test_function == lisp_object_equal_equal)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
361 write_c_string (" test equal", printcharfun);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
362 else if (ht->test_function == lisp_object_eql_equal)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
363 DO_NOTHING;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
364 else
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
365 abort ();
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
366
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
367 if (ht->count || !print_readably)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
368 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
369 if (print_readably)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
370 sprintf (buf, " size %lu", (unsigned long) ht->count);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
371 else
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
372 sprintf (buf, " size %lu/%lu",
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
373 (unsigned long) ht->count,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
374 (unsigned long) ht->size);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
375 write_c_string (buf, printcharfun);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
376 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
377
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
378 if (ht->weakness != HASH_TABLE_NON_WEAK)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
379 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
380 sprintf (buf, " weakness %s",
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
381 (ht->weakness == HASH_TABLE_WEAK ? "key-and-value" :
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
382 ht->weakness == HASH_TABLE_KEY_WEAK ? "key" :
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
383 ht->weakness == HASH_TABLE_VALUE_WEAK ? "value" :
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
384 ht->weakness == HASH_TABLE_KEY_VALUE_WEAK ? "key-or-value" :
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
385 "you-d-better-not-see-this"));
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
386 write_c_string (buf, printcharfun);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
387 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
388
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
389 if (ht->count)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
390 print_hash_table_data (ht, printcharfun);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
391
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
392 if (print_readably)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
393 write_c_string (")", printcharfun);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
394 else
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
395 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
396 sprintf (buf, " 0x%x>", ht->header.uid);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
397 write_c_string (buf, printcharfun);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
398 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
399 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
400
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
401 static void
489
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
402 free_hentries (hentry *hentries, size_t size)
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
403 {
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
404 #if ERROR_CHECK_HASH_TABLE
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
405 /* Ensure a crash if other code uses the discarded entries afterwards. */
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
406 hentry *e, *sentinel;
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
407
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
408 for (e = hentries, sentinel = e + size; e < sentinel; e++)
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
409 * (unsigned long *) e = 0xdeadbeef;
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
410 #endif
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
411
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
412 if (!DUMPEDP (hentries))
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
413 xfree (hentries);
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
414 }
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
415
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
416 static void
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
417 finalize_hash_table (void *header, int for_disksave)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
418 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
419 if (!for_disksave)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
420 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
421 Lisp_Hash_Table *ht = (Lisp_Hash_Table *) header;
489
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
422 free_hentries (ht->hentries, ht->size);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
423 ht->hentries = 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
424 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
425 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
426
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
427 static const struct lrecord_description hentry_description_1[] = {
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
428 { XD_LISP_OBJECT, offsetof (hentry, key) },
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
429 { XD_LISP_OBJECT, offsetof (hentry, value) },
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
430 { XD_END }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
431 };
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
432
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
433 static const struct struct_description hentry_description = {
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
434 sizeof (hentry),
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
435 hentry_description_1
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
436 };
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
437
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
438 const struct lrecord_description hash_table_description[] = {
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
439 { XD_SIZE_T, offsetof (Lisp_Hash_Table, size) },
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
440 { XD_STRUCT_PTR, offsetof (Lisp_Hash_Table, hentries), XD_INDIRECT(0, 1), &hentry_description },
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
441 { XD_LO_LINK, offsetof (Lisp_Hash_Table, next_weak) },
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
442 { XD_END }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
443 };
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
444
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
445 DEFINE_LRECORD_IMPLEMENTATION ("hash-table", hash_table,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
446 mark_hash_table, print_hash_table,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
447 finalize_hash_table,
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
448 hash_table_equal, hash_table_hash,
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
449 hash_table_description,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
450 Lisp_Hash_Table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
451
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
452 static Lisp_Hash_Table *
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
453 xhash_table (Lisp_Object hash_table)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
454 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
455 if (!gc_in_progress)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
456 CHECK_HASH_TABLE (hash_table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
457 check_hash_table_invariants (XHASH_TABLE (hash_table));
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
458 return XHASH_TABLE (hash_table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
459 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
460
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
461
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
462 /************************************************************************/
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
463 /* Creation of Hash Tables */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
464 /************************************************************************/
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
465
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
466 /* Creation of hash tables, without error-checking. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
467 static void
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
468 compute_hash_table_derived_values (Lisp_Hash_Table *ht)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
469 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
470 ht->rehash_count = (size_t)
438
84b14dcb0985 Import from CVS: tag r21-2-27
cvs
parents: 434
diff changeset
471 ((double) ht->size * ht->rehash_threshold);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
472 ht->golden_ratio = (size_t)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
473 ((double) ht->size * (.6180339887 / (double) sizeof (Lisp_Object)));
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
474 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
475
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
476 Lisp_Object
450
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
477 make_standard_lisp_hash_table (enum hash_table_test test,
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
478 size_t size,
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
479 double rehash_size,
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
480 double rehash_threshold,
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
481 enum hash_table_weakness weakness)
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
482 {
462
0784d089fdc9 Import from CVS: tag r21-2-46
cvs
parents: 458
diff changeset
483 hash_table_hash_function_t hash_function = 0;
450
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
484 hash_table_test_function_t test_function = 0;
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
485
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
486 switch (test)
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
487 {
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
488 case HASH_TABLE_EQ:
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
489 test_function = 0;
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
490 hash_function = 0;
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
491 break;
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
492
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
493 case HASH_TABLE_EQL:
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
494 test_function = lisp_object_eql_equal;
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
495 hash_function = lisp_object_eql_hash;
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
496 break;
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
497
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
498 case HASH_TABLE_EQUAL:
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
499 test_function = lisp_object_equal_equal;
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
500 hash_function = lisp_object_equal_hash;
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
501 break;
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
502
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
503 default:
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
504 abort ();
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
505 }
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
506
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
507 return make_general_lisp_hash_table (hash_function, test_function,
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
508 size, rehash_size, rehash_threshold,
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
509 weakness);
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
510 }
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
511
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
512 Lisp_Object
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
513 make_general_lisp_hash_table (hash_table_hash_function_t hash_function,
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
514 hash_table_test_function_t test_function,
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
515 size_t size,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
516 double rehash_size,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
517 double rehash_threshold,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
518 enum hash_table_weakness weakness)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
519 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
520 Lisp_Object hash_table;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
521 Lisp_Hash_Table *ht = alloc_lcrecord_type (Lisp_Hash_Table, &lrecord_hash_table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
522
450
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
523 ht->test_function = test_function;
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
524 ht->hash_function = hash_function;
438
84b14dcb0985 Import from CVS: tag r21-2-27
cvs
parents: 434
diff changeset
525 ht->weakness = weakness;
84b14dcb0985 Import from CVS: tag r21-2-27
cvs
parents: 434
diff changeset
526
84b14dcb0985 Import from CVS: tag r21-2-27
cvs
parents: 434
diff changeset
527 ht->rehash_size =
84b14dcb0985 Import from CVS: tag r21-2-27
cvs
parents: 434
diff changeset
528 rehash_size > 1.0 ? rehash_size : HASH_TABLE_DEFAULT_REHASH_SIZE;
84b14dcb0985 Import from CVS: tag r21-2-27
cvs
parents: 434
diff changeset
529
84b14dcb0985 Import from CVS: tag r21-2-27
cvs
parents: 434
diff changeset
530 ht->rehash_threshold =
84b14dcb0985 Import from CVS: tag r21-2-27
cvs
parents: 434
diff changeset
531 rehash_threshold > 0.0 ? rehash_threshold :
84b14dcb0985 Import from CVS: tag r21-2-27
cvs
parents: 434
diff changeset
532 size > 4096 && !ht->test_function ? 0.7 : 0.6;
84b14dcb0985 Import from CVS: tag r21-2-27
cvs
parents: 434
diff changeset
533
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
534 if (size < HASH_TABLE_MIN_SIZE)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
535 size = HASH_TABLE_MIN_SIZE;
438
84b14dcb0985 Import from CVS: tag r21-2-27
cvs
parents: 434
diff changeset
536 ht->size = hash_table_size ((size_t) (((double) size / ht->rehash_threshold)
84b14dcb0985 Import from CVS: tag r21-2-27
cvs
parents: 434
diff changeset
537 + 1.0));
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
538 ht->count = 0;
438
84b14dcb0985 Import from CVS: tag r21-2-27
cvs
parents: 434
diff changeset
539
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
540 compute_hash_table_derived_values (ht);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
541
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
542 /* We leave room for one never-occupied sentinel hentry at the end. */
458
c33ae14dd6d0 Import from CVS: tag r21-2-44
cvs
parents: 452
diff changeset
543 ht->hentries = xnew_array_and_zero (hentry, ht->size + 1);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
544
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
545 XSETHASH_TABLE (hash_table, ht);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
546
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
547 if (weakness == HASH_TABLE_NON_WEAK)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
548 ht->next_weak = Qunbound;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
549 else
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
550 ht->next_weak = Vall_weak_hash_tables, Vall_weak_hash_tables = hash_table;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
551
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
552 return hash_table;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
553 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
554
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
555 Lisp_Object
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
556 make_lisp_hash_table (size_t size,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
557 enum hash_table_weakness weakness,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
558 enum hash_table_test test)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
559 {
450
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
560 return make_standard_lisp_hash_table (test, size, -1.0, -1.0, weakness);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
561 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
562
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
563 /* Pretty reading of hash tables.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
564
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
565 Here we use the existing structures mechanism (which is,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
566 unfortunately, pretty cumbersome) for validating and instantiating
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
567 the hash tables. The idea is that the side-effect of reading a
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
568 #s(hash-table PLIST) object is creation of a hash table with desired
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
569 properties, and that the hash table is returned. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
570
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
571 /* Validation functions: each keyword provides its own validation
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
572 function. The errors should maybe be continuable, but it is
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
573 unclear how this would cope with ERRB. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
574 static int
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
575 hash_table_size_validate (Lisp_Object keyword, Lisp_Object value,
578
190b164ddcac [xemacs-hg @ 2001-05-25 11:26:50 by ben]
ben
parents: 563
diff changeset
576 Error_Behavior errb)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
577 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
578 if (NATNUMP (value))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
579 return 1;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
580
563
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
581 maybe_signal_error_1 (Qwrong_type_argument, list2 (Qnatnump, value),
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
582 Qhash_table, errb);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
583 return 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
584 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
585
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
586 static size_t
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
587 decode_hash_table_size (Lisp_Object obj)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
588 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
589 return NILP (obj) ? HASH_TABLE_DEFAULT_SIZE : XINT (obj);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
590 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
591
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
592 static int
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
593 hash_table_weakness_validate (Lisp_Object keyword, Lisp_Object value,
578
190b164ddcac [xemacs-hg @ 2001-05-25 11:26:50 by ben]
ben
parents: 563
diff changeset
594 Error_Behavior errb)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
595 {
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
596 if (EQ (value, Qnil)) return 1;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
597 if (EQ (value, Qt)) return 1;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
598 if (EQ (value, Qkey)) return 1;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
599 if (EQ (value, Qkey_and_value)) return 1;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
600 if (EQ (value, Qkey_or_value)) return 1;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
601 if (EQ (value, Qvalue)) return 1;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
602
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
603 /* Following values are obsolete as of 19990901 in xemacs-21.2 */
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
604 if (EQ (value, Qnon_weak)) return 1;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
605 if (EQ (value, Qweak)) return 1;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
606 if (EQ (value, Qkey_weak)) return 1;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
607 if (EQ (value, Qkey_or_value_weak)) return 1;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
608 if (EQ (value, Qvalue_weak)) return 1;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
609
563
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
610 maybe_invalid_constant ("Invalid hash table weakness",
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
611 value, Qhash_table, errb);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
612 return 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
613 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
614
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
615 static enum hash_table_weakness
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
616 decode_hash_table_weakness (Lisp_Object obj)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
617 {
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
618 if (EQ (obj, Qnil)) return HASH_TABLE_NON_WEAK;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
619 if (EQ (obj, Qt)) return HASH_TABLE_WEAK;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
620 if (EQ (obj, Qkey_and_value)) return HASH_TABLE_WEAK;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
621 if (EQ (obj, Qkey)) return HASH_TABLE_KEY_WEAK;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
622 if (EQ (obj, Qkey_or_value)) return HASH_TABLE_KEY_VALUE_WEAK;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
623 if (EQ (obj, Qvalue)) return HASH_TABLE_VALUE_WEAK;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
624
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
625 /* Following values are obsolete as of 19990901 in xemacs-21.2 */
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
626 if (EQ (obj, Qnon_weak)) return HASH_TABLE_NON_WEAK;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
627 if (EQ (obj, Qweak)) return HASH_TABLE_WEAK;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
628 if (EQ (obj, Qkey_weak)) return HASH_TABLE_KEY_WEAK;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
629 if (EQ (obj, Qkey_or_value_weak)) return HASH_TABLE_KEY_VALUE_WEAK;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
630 if (EQ (obj, Qvalue_weak)) return HASH_TABLE_VALUE_WEAK;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
631
563
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
632 invalid_constant ("Invalid hash table weakness", obj);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
633 return HASH_TABLE_NON_WEAK; /* not reached */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
634 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
635
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
636 static int
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
637 hash_table_test_validate (Lisp_Object keyword, Lisp_Object value,
578
190b164ddcac [xemacs-hg @ 2001-05-25 11:26:50 by ben]
ben
parents: 563
diff changeset
638 Error_Behavior errb)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
639 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
640 if (EQ (value, Qnil)) return 1;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
641 if (EQ (value, Qeq)) return 1;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
642 if (EQ (value, Qequal)) return 1;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
643 if (EQ (value, Qeql)) return 1;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
644
563
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
645 maybe_invalid_constant ("Invalid hash table test",
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
646 value, Qhash_table, errb);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
647 return 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
648 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
649
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
650 static enum hash_table_test
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
651 decode_hash_table_test (Lisp_Object obj)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
652 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
653 if (EQ (obj, Qnil)) return HASH_TABLE_EQL;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
654 if (EQ (obj, Qeq)) return HASH_TABLE_EQ;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
655 if (EQ (obj, Qequal)) return HASH_TABLE_EQUAL;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
656 if (EQ (obj, Qeql)) return HASH_TABLE_EQL;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
657
563
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
658 invalid_constant ("Invalid hash table test", obj);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
659 return HASH_TABLE_EQ; /* not reached */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
660 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
661
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
662 static int
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
663 hash_table_rehash_size_validate (Lisp_Object keyword, Lisp_Object value,
578
190b164ddcac [xemacs-hg @ 2001-05-25 11:26:50 by ben]
ben
parents: 563
diff changeset
664 Error_Behavior errb)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
665 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
666 if (!FLOATP (value))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
667 {
563
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
668 maybe_signal_error_1 (Qwrong_type_argument, list2 (Qfloatp, value),
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
669 Qhash_table, errb);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
670 return 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
671 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
672
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
673 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
674 double rehash_size = XFLOAT_DATA (value);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
675 if (rehash_size <= 1.0)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
676 {
563
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
677 maybe_invalid_argument
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
678 ("Hash table rehash size must be greater than 1.0",
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
679 value, Qhash_table, errb);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
680 return 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
681 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
682 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
683
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
684 return 1;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
685 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
686
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
687 static double
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
688 decode_hash_table_rehash_size (Lisp_Object rehash_size)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
689 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
690 return NILP (rehash_size) ? -1.0 : XFLOAT_DATA (rehash_size);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
691 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
692
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
693 static int
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
694 hash_table_rehash_threshold_validate (Lisp_Object keyword, Lisp_Object value,
578
190b164ddcac [xemacs-hg @ 2001-05-25 11:26:50 by ben]
ben
parents: 563
diff changeset
695 Error_Behavior errb)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
696 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
697 if (!FLOATP (value))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
698 {
563
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
699 maybe_signal_error_1 (Qwrong_type_argument, list2 (Qfloatp, value),
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
700 Qhash_table, errb);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
701 return 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
702 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
703
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
704 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
705 double rehash_threshold = XFLOAT_DATA (value);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
706 if (rehash_threshold <= 0.0 || rehash_threshold >= 1.0)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
707 {
563
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
708 maybe_invalid_argument
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
709 ("Hash table rehash threshold must be between 0.0 and 1.0",
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
710 value, Qhash_table, errb);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
711 return 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
712 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
713 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
714
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
715 return 1;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
716 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
717
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
718 static double
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
719 decode_hash_table_rehash_threshold (Lisp_Object rehash_threshold)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
720 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
721 return NILP (rehash_threshold) ? -1.0 : XFLOAT_DATA (rehash_threshold);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
722 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
723
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
724 static int
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
725 hash_table_data_validate (Lisp_Object keyword, Lisp_Object value,
578
190b164ddcac [xemacs-hg @ 2001-05-25 11:26:50 by ben]
ben
parents: 563
diff changeset
726 Error_Behavior errb)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
727 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
728 int len;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
729
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
730 GET_EXTERNAL_LIST_LENGTH (value, len);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
731
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
732 if (len & 1)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
733 {
563
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
734 maybe_sferror
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
735 ("Hash table data must have alternating key/value pairs",
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
736 value, Qhash_table, errb);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
737 return 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
738 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
739 return 1;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
740 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
741
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
742 /* The actual instantiation of a hash table. This does practically no
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
743 error checking, because it relies on the fact that the paranoid
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
744 functions above have error-checked everything to the last details.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
745 If this assumption is wrong, we will get a crash immediately (with
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
746 error-checking compiled in), and we'll know if there is a bug in
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
747 the structure mechanism. So there. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
748 static Lisp_Object
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
749 hash_table_instantiate (Lisp_Object plist)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
750 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
751 Lisp_Object hash_table;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
752 Lisp_Object test = Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
753 Lisp_Object size = Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
754 Lisp_Object rehash_size = Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
755 Lisp_Object rehash_threshold = Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
756 Lisp_Object weakness = Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
757 Lisp_Object data = Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
758
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
759 while (!NILP (plist))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
760 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
761 Lisp_Object key, value;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
762 key = XCAR (plist); plist = XCDR (plist);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
763 value = XCAR (plist); plist = XCDR (plist);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
764
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
765 if (EQ (key, Qtest)) test = value;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
766 else if (EQ (key, Qsize)) size = value;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
767 else if (EQ (key, Qrehash_size)) rehash_size = value;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
768 else if (EQ (key, Qrehash_threshold)) rehash_threshold = value;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
769 else if (EQ (key, Qweakness)) weakness = value;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
770 else if (EQ (key, Qdata)) data = value;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
771 else if (EQ (key, Qtype))/*obsolete*/ weakness = value;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
772 else
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
773 abort ();
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
774 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
775
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
776 /* Create the hash table. */
450
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
777 hash_table = make_standard_lisp_hash_table
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
778 (decode_hash_table_test (test),
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
779 decode_hash_table_size (size),
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
780 decode_hash_table_rehash_size (rehash_size),
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
781 decode_hash_table_rehash_threshold (rehash_threshold),
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
782 decode_hash_table_weakness (weakness));
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
783
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
784 /* I'm not sure whether this can GC, but better safe than sorry. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
785 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
786 struct gcpro gcpro1;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
787 GCPRO1 (hash_table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
788
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
789 /* And fill it with data. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
790 while (!NILP (data))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
791 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
792 Lisp_Object key, value;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
793 key = XCAR (data); data = XCDR (data);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
794 value = XCAR (data); data = XCDR (data);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
795 Fputhash (key, value, hash_table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
796 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
797 UNGCPRO;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
798 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
799
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
800 return hash_table;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
801 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
802
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
803 static void
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
804 structure_type_create_hash_table_structure_name (Lisp_Object structure_name)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
805 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
806 struct structure_type *st;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
807
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
808 st = define_structure_type (structure_name, 0, hash_table_instantiate);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
809 define_structure_type_keyword (st, Qtest, hash_table_test_validate);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
810 define_structure_type_keyword (st, Qsize, hash_table_size_validate);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
811 define_structure_type_keyword (st, Qrehash_size, hash_table_rehash_size_validate);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
812 define_structure_type_keyword (st, Qrehash_threshold, hash_table_rehash_threshold_validate);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
813 define_structure_type_keyword (st, Qweakness, hash_table_weakness_validate);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
814 define_structure_type_keyword (st, Qdata, hash_table_data_validate);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
815
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
816 /* obsolete as of 19990901 in xemacs-21.2 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
817 define_structure_type_keyword (st, Qtype, hash_table_weakness_validate);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
818 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
819
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
820 /* Create a built-in Lisp structure type named `hash-table'.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
821 We make #s(hashtable ...) equivalent to #s(hash-table ...),
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
822 for backward compatibility.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
823 This is called from emacs.c. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
824 void
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
825 structure_type_create_hash_table (void)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
826 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
827 structure_type_create_hash_table_structure_name (Qhash_table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
828 structure_type_create_hash_table_structure_name (Qhashtable); /* compat */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
829 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
830
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
831
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
832 /************************************************************************/
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
833 /* Definition of Lisp-visible methods */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
834 /************************************************************************/
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
835
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
836 DEFUN ("hash-table-p", Fhash_table_p, 1, 1, 0, /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
837 Return t if OBJECT is a hash table, else nil.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
838 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
839 (object))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
840 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
841 return HASH_TABLEP (object) ? Qt : Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
842 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
843
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
844 DEFUN ("make-hash-table", Fmake_hash_table, 0, MANY, 0, /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
845 Return a new empty hash table object.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
846 Use Common Lisp style keywords to specify hash table properties.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
847 (make-hash-table &key test size rehash-size rehash-threshold weakness)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
848
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
849 Keyword :test can be `eq', `eql' (default) or `equal'.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
850 Comparison between keys is done using this function.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
851 If speed is important, consider using `eq'.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
852 When storing strings in the hash table, you will likely need to use `equal'.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
853
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
854 Keyword :size specifies the number of keys likely to be inserted.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
855 This number of entries can be inserted without enlarging the hash table.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
856
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
857 Keyword :rehash-size must be a float greater than 1.0, and specifies
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
858 the factor by which to increase the size of the hash table when enlarging.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
859
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
860 Keyword :rehash-threshold must be a float between 0.0 and 1.0,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
861 and specifies the load factor of the hash table which triggers enlarging.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
862
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
863 Non-standard keyword :weakness can be `nil' (default), `t', `key-and-value',
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
864 `key', `value' or `key-or-value'. `t' is an alias for `key-and-value'.
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
865
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
866 A key-and-value-weak hash table, also known as a fully-weak or simply
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
867 as a weak hash table, is one whose pointers do not count as GC
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
868 referents: for any key-value pair in the hash table, if the only
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
869 remaining pointer to either the key or the value is in a weak hash
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
870 table, then the pair will be removed from the hash table, and the key
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
871 and value collected. A non-weak hash table (or any other pointer)
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
872 would prevent the object from being collected.
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
873
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
874 A key-weak hash table is similar to a fully-weak hash table except that
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
875 a key-value pair will be removed only if the key remains unmarked
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
876 outside of weak hash tables. The pair will remain in the hash table if
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
877 the key is pointed to by something other than a weak hash table, even
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
878 if the value is not.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
879
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
880 A value-weak hash table is similar to a fully-weak hash table except
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
881 that a key-value pair will be removed only if the value remains
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
882 unmarked outside of weak hash tables. The pair will remain in the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
883 hash table if the value is pointed to by something other than a weak
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
884 hash table, even if the key is not.
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
885
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
886 A key-or-value-weak hash table is similar to a fully-weak hash table except
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
887 that a key-value pair will be removed only if the value and the key remain
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
888 unmarked outside of weak hash tables. The pair will remain in the
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
889 hash table if the value or key are pointed to by something other than a weak
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
890 hash table, even if the other is not.
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
891 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
892 (int nargs, Lisp_Object *args))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
893 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
894 int i = 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
895 Lisp_Object test = Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
896 Lisp_Object size = Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
897 Lisp_Object rehash_size = Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
898 Lisp_Object rehash_threshold = Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
899 Lisp_Object weakness = Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
900
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
901 while (i + 1 < nargs)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
902 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
903 Lisp_Object keyword = args[i++];
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
904 Lisp_Object value = args[i++];
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
905
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
906 if (EQ (keyword, Q_test)) test = value;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
907 else if (EQ (keyword, Q_size)) size = value;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
908 else if (EQ (keyword, Q_rehash_size)) rehash_size = value;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
909 else if (EQ (keyword, Q_rehash_threshold)) rehash_threshold = value;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
910 else if (EQ (keyword, Q_weakness)) weakness = value;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
911 else if (EQ (keyword, Q_type))/*obsolete*/ weakness = value;
563
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
912 else invalid_constant ("Invalid hash table property keyword", keyword);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
913 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
914
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
915 if (i < nargs)
563
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
916 sferror ("Hash table property requires a value", args[i]);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
917
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
918 #define VALIDATE_VAR(var) \
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
919 if (!NILP (var)) hash_table_##var##_validate (Q##var, var, ERROR_ME);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
920
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
921 VALIDATE_VAR (test);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
922 VALIDATE_VAR (size);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
923 VALIDATE_VAR (rehash_size);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
924 VALIDATE_VAR (rehash_threshold);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
925 VALIDATE_VAR (weakness);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
926
450
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
927 return make_standard_lisp_hash_table
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
928 (decode_hash_table_test (test),
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
929 decode_hash_table_size (size),
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
930 decode_hash_table_rehash_size (rehash_size),
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
931 decode_hash_table_rehash_threshold (rehash_threshold),
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
932 decode_hash_table_weakness (weakness));
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
933 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
934
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
935 DEFUN ("copy-hash-table", Fcopy_hash_table, 1, 1, 0, /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
936 Return a new hash table containing the same keys and values as HASH-TABLE.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
937 The keys and values will not themselves be copied.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
938 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
939 (hash_table))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
940 {
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
941 const Lisp_Hash_Table *ht_old = xhash_table (hash_table);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
942 Lisp_Hash_Table *ht = alloc_lcrecord_type (Lisp_Hash_Table, &lrecord_hash_table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
943
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
944 copy_lcrecord (ht, ht_old);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
945
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
946 ht->hentries = xnew_array (hentry, ht_old->size + 1);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
947 memcpy (ht->hentries, ht_old->hentries, (ht_old->size + 1) * sizeof (hentry));
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
948
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
949 XSETHASH_TABLE (hash_table, ht);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
950
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
951 if (! EQ (ht->next_weak, Qunbound))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
952 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
953 ht->next_weak = Vall_weak_hash_tables;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
954 Vall_weak_hash_tables = hash_table;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
955 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
956
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
957 return hash_table;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
958 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
959
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
960 static void
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
961 resize_hash_table (Lisp_Hash_Table *ht, size_t new_size)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
962 {
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
963 hentry *old_entries, *new_entries, *sentinel, *e;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
964 size_t old_size;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
965
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
966 old_size = ht->size;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
967 ht->size = new_size;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
968
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
969 old_entries = ht->hentries;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
970
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
971 ht->hentries = xnew_array_and_zero (hentry, new_size + 1);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
972 new_entries = ht->hentries;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
973
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
974 compute_hash_table_derived_values (ht);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
975
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
976 for (e = old_entries, sentinel = e + old_size; e < sentinel; e++)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
977 if (!HENTRY_CLEAR_P (e))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
978 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
979 hentry *probe = new_entries + HASH_CODE (e->key, ht);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
980 LINEAR_PROBING_LOOP (probe, new_entries, new_size)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
981 ;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
982 *probe = *e;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
983 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
984
489
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
985 free_hentries (old_entries, old_size);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
986 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
987
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
988 /* After a hash table has been saved to disk and later restored by the
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
989 portable dumper, it contains the same objects, but their addresses
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
990 and thus their HASH_CODEs have changed. */
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
991 void
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
992 pdump_reorganize_hash_table (Lisp_Object hash_table)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
993 {
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
994 const Lisp_Hash_Table *ht = xhash_table (hash_table);
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
995 hentry *new_entries = xnew_array_and_zero (hentry, ht->size + 1);
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
996 hentry *e, *sentinel;
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
997
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
998 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++)
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
999 if (!HENTRY_CLEAR_P (e))
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
1000 {
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
1001 hentry *probe = new_entries + HASH_CODE (e->key, ht);
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
1002 LINEAR_PROBING_LOOP (probe, new_entries, ht->size)
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
1003 ;
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
1004 *probe = *e;
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
1005 }
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
1006
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
1007 memcpy (ht->hentries, new_entries, ht->size * sizeof (hentry));
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
1008
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 438
diff changeset
1009 xfree (new_entries);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1010 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1011
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1012 static void
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1013 enlarge_hash_table (Lisp_Hash_Table *ht)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1014 {
432
3a7e78e1142d Import from CVS: tag r21-2-24
cvs
parents: 430
diff changeset
1015 size_t new_size =
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1016 hash_table_size ((size_t) ((double) ht->size * ht->rehash_size));
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1017 resize_hash_table (ht, new_size);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1018 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1019
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1020 static hentry *
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1021 find_hentry (Lisp_Object key, const Lisp_Hash_Table *ht)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1022 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1023 hash_table_test_function_t test_function = ht->test_function;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1024 hentry *entries = ht->hentries;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1025 hentry *probe = entries + HASH_CODE (key, ht);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1026
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1027 LINEAR_PROBING_LOOP (probe, entries, ht->size)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1028 if (KEYS_EQUAL_P (probe->key, key, test_function))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1029 break;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1030
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1031 return probe;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1032 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1033
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1034 DEFUN ("gethash", Fgethash, 2, 3, 0, /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1035 Find hash value for KEY in HASH-TABLE.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1036 If there is no corresponding value, return DEFAULT (which defaults to nil).
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1037 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1038 (key, hash_table, default_))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1039 {
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1040 const Lisp_Hash_Table *ht = xhash_table (hash_table);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1041 hentry *e = find_hentry (key, ht);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1042
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1043 return HENTRY_CLEAR_P (e) ? default_ : e->value;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1044 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1045
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1046 DEFUN ("puthash", Fputhash, 3, 3, 0, /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1047 Hash KEY to VALUE in HASH-TABLE.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1048 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1049 (key, value, hash_table))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1050 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1051 Lisp_Hash_Table *ht = xhash_table (hash_table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1052 hentry *e = find_hentry (key, ht);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1053
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1054 if (!HENTRY_CLEAR_P (e))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1055 return e->value = value;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1056
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1057 e->key = key;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1058 e->value = value;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1059
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1060 if (++ht->count >= ht->rehash_count)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1061 enlarge_hash_table (ht);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1062
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1063 return value;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1064 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1065
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1066 /* Remove hentry pointed at by PROBE.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1067 Subsequent entries are removed and reinserted.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1068 We don't use tombstones - too wasteful. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1069 static void
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1070 remhash_1 (Lisp_Hash_Table *ht, hentry *entries, hentry *probe)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1071 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1072 size_t size = ht->size;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1073 CLEAR_HENTRY (probe);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1074 probe++;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1075 ht->count--;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1076
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1077 LINEAR_PROBING_LOOP (probe, entries, size)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1078 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1079 Lisp_Object key = probe->key;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1080 hentry *probe2 = entries + HASH_CODE (key, ht);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1081 LINEAR_PROBING_LOOP (probe2, entries, size)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1082 if (EQ (probe2->key, key))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1083 /* hentry at probe doesn't need to move. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1084 goto continue_outer_loop;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1085 /* Move hentry from probe to new home at probe2. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1086 *probe2 = *probe;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1087 CLEAR_HENTRY (probe);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1088 continue_outer_loop: continue;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1089 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1090 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1091
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1092 DEFUN ("remhash", Fremhash, 2, 2, 0, /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1093 Remove the entry for KEY from HASH-TABLE.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1094 Do nothing if there is no entry for KEY in HASH-TABLE.
617
af57a77cbc92 [xemacs-hg @ 2001-06-18 07:09:50 by ben]
ben
parents: 578
diff changeset
1095 Return non-nil if an entry was removed.
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1096 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1097 (key, hash_table))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1098 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1099 Lisp_Hash_Table *ht = xhash_table (hash_table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1100 hentry *e = find_hentry (key, ht);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1101
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1102 if (HENTRY_CLEAR_P (e))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1103 return Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1104
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1105 remhash_1 (ht, ht->hentries, e);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1106 return Qt;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1107 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1108
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1109 DEFUN ("clrhash", Fclrhash, 1, 1, 0, /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1110 Remove all entries from HASH-TABLE, leaving it empty.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1111 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1112 (hash_table))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1113 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1114 Lisp_Hash_Table *ht = xhash_table (hash_table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1115 hentry *e, *sentinel;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1116
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1117 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1118 CLEAR_HENTRY (e);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1119 ht->count = 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1120
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1121 return hash_table;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1122 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1123
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1124 /************************************************************************/
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1125 /* Accessor Functions */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1126 /************************************************************************/
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1127
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1128 DEFUN ("hash-table-count", Fhash_table_count, 1, 1, 0, /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1129 Return the number of entries in HASH-TABLE.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1130 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1131 (hash_table))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1132 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1133 return make_int (xhash_table (hash_table)->count);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1134 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1135
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1136 DEFUN ("hash-table-test", Fhash_table_test, 1, 1, 0, /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1137 Return the test function of HASH-TABLE.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1138 This can be one of `eq', `eql' or `equal'.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1139 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1140 (hash_table))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1141 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1142 hash_table_test_function_t fun = xhash_table (hash_table)->test_function;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1143
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1144 return (fun == lisp_object_eql_equal ? Qeql :
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1145 fun == lisp_object_equal_equal ? Qequal :
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1146 Qeq);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1147 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1148
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1149 DEFUN ("hash-table-size", Fhash_table_size, 1, 1, 0, /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1150 Return the size of HASH-TABLE.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1151 This is the current number of slots in HASH-TABLE, whether occupied or not.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1152 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1153 (hash_table))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1154 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1155 return make_int (xhash_table (hash_table)->size);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1156 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1157
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1158 DEFUN ("hash-table-rehash-size", Fhash_table_rehash_size, 1, 1, 0, /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1159 Return the current rehash size of HASH-TABLE.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1160 This is a float greater than 1.0; the factor by which HASH-TABLE
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1161 is enlarged when the rehash threshold is exceeded.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1162 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1163 (hash_table))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1164 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1165 return make_float (xhash_table (hash_table)->rehash_size);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1166 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1167
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1168 DEFUN ("hash-table-rehash-threshold", Fhash_table_rehash_threshold, 1, 1, 0, /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1169 Return the current rehash threshold of HASH-TABLE.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1170 This is a float between 0.0 and 1.0; the maximum `load factor' of HASH-TABLE,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1171 beyond which the HASH-TABLE is enlarged by rehashing.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1172 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1173 (hash_table))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1174 {
438
84b14dcb0985 Import from CVS: tag r21-2-27
cvs
parents: 434
diff changeset
1175 return make_float (xhash_table (hash_table)->rehash_threshold);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1176 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1177
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1178 DEFUN ("hash-table-weakness", Fhash_table_weakness, 1, 1, 0, /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1179 Return the weakness of HASH-TABLE.
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1180 This can be one of `nil', `key-and-value', `key-or-value', `key' or `value'.
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1181 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1182 (hash_table))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1183 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1184 switch (xhash_table (hash_table)->weakness)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1185 {
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1186 case HASH_TABLE_WEAK: return Qkey_and_value;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1187 case HASH_TABLE_KEY_WEAK: return Qkey;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1188 case HASH_TABLE_KEY_VALUE_WEAK: return Qkey_or_value;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1189 case HASH_TABLE_VALUE_WEAK: return Qvalue;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1190 default: return Qnil;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1191 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1192 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1193
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1194 /* obsolete as of 19990901 in xemacs-21.2 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1195 DEFUN ("hash-table-type", Fhash_table_type, 1, 1, 0, /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1196 Return the type of HASH-TABLE.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1197 This can be one of `non-weak', `weak', `key-weak' or `value-weak'.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1198 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1199 (hash_table))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1200 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1201 switch (xhash_table (hash_table)->weakness)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1202 {
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1203 case HASH_TABLE_WEAK: return Qweak;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1204 case HASH_TABLE_KEY_WEAK: return Qkey_weak;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1205 case HASH_TABLE_KEY_VALUE_WEAK: return Qkey_or_value_weak;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1206 case HASH_TABLE_VALUE_WEAK: return Qvalue_weak;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1207 default: return Qnon_weak;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1208 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1209 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1210
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1211 /************************************************************************/
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1212 /* Mapping Functions */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1213 /************************************************************************/
489
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1214
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1215 /* We need to be careful when mapping over hash tables because the
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1216 hash table might be modified during the mapping operation:
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1217 - by the mapping function
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1218 - by gc (if the hash table is weak)
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1219
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1220 So we make a copy of the hentries at the beginning of the mapping
497
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1221 operation, and iterate over the copy. Naturally, this is
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1222 expensive, but not as expensive as you might think, because no
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1223 actual memory has to be collected by our notoriously inefficient
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1224 GC; we use an unwind-protect instead to free the memory directly.
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1225
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1226 We could avoid the copying by having the hash table modifiers
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1227 puthash and remhash check for currently active mapping functions.
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1228 Disadvantages: it's hard to get right, and IMO hash mapping
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1229 functions are basically rare, and no extra space in the hash table
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1230 object and no extra cpu in puthash or remhash should be wasted to
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1231 make maphash 3% faster. From a design point of view, the basic
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1232 functions gethash, puthash and remhash should be implementable
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1233 without having to think about maphash.
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1234
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1235 Note: We don't (yet) have Common Lisp's with-hash-table-iterator.
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1236 If you implement this naively, you cannot have more than one
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1237 concurrently active iterator over the same hash table. The `each'
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1238 function in perl has this limitation.
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1239
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1240 Note: We GCPRO memory on the heap, not on the stack. There is no
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1241 obvious reason why this is bad, but as of this writing this is the
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1242 only known occurrence of this technique in the code.
504
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1243
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1244 -- Martin
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1245 */
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1246
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1247 /* Ben disagrees with the "copying hentries" design, and says:
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1248
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1249 Another solution is the same as I've already proposed -- when
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1250 mapping, mark the table as "change-unsafe", and in this case, use a
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1251 secondary table to maintain changes. this could be basically a
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1252 standard hash table, but with entries only for added or deleted
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1253 entries in the primary table, and a marker like Qunbound to
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1254 indicate a deleted entry. puthash, gethash and remhash need a
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1255 single extra check for this secondary table -- totally
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1256 insignificant speedwise. if you really cared about making
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1257 recursive maphashes completely correct, you'd have to do a bit of
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1258 extra work here -- when maphashing, if the secondary table exists,
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1259 make a copy of it, and use the copy in conjunction with the primary
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1260 table when mapping. the advantages of this are
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1261
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1262 [a] easy to demonstrate correct, even with weak hashtables.
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1263
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1264 [b] no extra overhead in the general maphash case -- only when you
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1265 modify the table while maphashing, and even then the overhead is
bcda0b3445a6 [xemacs-hg @ 2001-05-05 08:19:18 by martinb]
martinb
parents: 497
diff changeset
1266 very small.
497
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1267 */
11b53bb7daf5 [xemacs-hg @ 2001-05-02 10:22:58 by martinb]
martinb
parents: 489
diff changeset
1268
489
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1269 static Lisp_Object
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1270 maphash_unwind (Lisp_Object unwind_obj)
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1271 {
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1272 void *ptr = (void *) get_opaque_ptr (unwind_obj);
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1273 xfree (ptr);
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1274 free_opaque_ptr (unwind_obj);
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1275 return Qnil;
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1276 }
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1277
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1278 /* Return a malloced array of alternating key/value pairs from HT. */
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1279 static Lisp_Object *
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1280 copy_compress_hentries (const Lisp_Hash_Table *ht)
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1281 {
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1282 Lisp_Object * const objs =
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1283 /* If the hash table is empty, ht->count could be 0. */
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1284 xnew_array (Lisp_Object, 2 * (ht->count > 0 ? ht->count : 1));
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1285 const hentry *e, *sentinel;
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1286 Lisp_Object *pobj;
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1287
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1288 for (e = ht->hentries, sentinel = e + ht->size, pobj = objs; e < sentinel; e++)
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1289 if (!HENTRY_CLEAR_P (e))
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1290 {
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1291 *(pobj++) = e->key;
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1292 *(pobj++) = e->value;
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1293 }
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1294
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1295 type_checking_assert (pobj == objs + 2 * ht->count);
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1296
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1297 return objs;
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1298 }
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1299
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1300 DEFUN ("maphash", Fmaphash, 2, 2, 0, /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1301 Map FUNCTION over entries in HASH-TABLE, calling it with two args,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1302 each key and value in HASH-TABLE.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1303
489
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1304 FUNCTION must not modify HASH-TABLE, with the one exception that FUNCTION
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1305 may remhash or puthash the entry currently being processed by FUNCTION.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1306 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1307 (function, hash_table))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1308 {
489
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1309 const Lisp_Hash_Table * const ht = xhash_table (hash_table);
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1310 Lisp_Object * const objs = copy_compress_hentries (ht);
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1311 Lisp_Object args[3];
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1312 const Lisp_Object *pobj, *end;
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1313 int speccount = specpdl_depth ();
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1314 struct gcpro gcpro1;
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1315
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1316 record_unwind_protect (maphash_unwind, make_opaque_ptr ((void *)objs));
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1317 GCPRO1 (objs[0]);
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1318 gcpro1.nvars = 2 * ht->count;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1319
489
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1320 args[0] = function;
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1321
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1322 for (pobj = objs, end = pobj + 2 * ht->count; pobj < end; pobj += 2)
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1323 {
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1324 args[1] = pobj[0];
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1325 args[2] = pobj[1];
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1326 Ffuncall (countof (args), args);
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1327 }
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1328
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1329 unbind_to (speccount, Qnil);
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1330 UNGCPRO;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1331
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1332 return Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1333 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1334
489
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1335 /* Map *C* function FUNCTION over the elements of a non-weak lisp hash table.
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1336 FUNCTION must not modify HASH-TABLE, with the one exception that FUNCTION
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1337 may puthash the entry currently being processed by FUNCTION.
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1338 Mapping terminates if FUNCTION returns something other than 0. */
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1339 void
489
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1340 elisp_maphash_unsafe (maphash_function_t function,
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1341 Lisp_Object hash_table, void *extra_arg)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1342 {
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1343 const Lisp_Hash_Table *ht = XHASH_TABLE (hash_table);
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1344 const hentry *e, *sentinel;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1345
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1346 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1347 if (!HENTRY_CLEAR_P (e))
489
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1348 if (function (e->key, e->value, extra_arg))
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1349 return;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1350 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1351
489
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1352 /* Map *C* function FUNCTION over the elements of a lisp hash table.
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1353 It is safe for FUNCTION to modify HASH-TABLE.
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1354 Mapping terminates if FUNCTION returns something other than 0. */
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1355 void
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1356 elisp_maphash (maphash_function_t function,
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1357 Lisp_Object hash_table, void *extra_arg)
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1358 {
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1359 const Lisp_Hash_Table * const ht = xhash_table (hash_table);
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1360 Lisp_Object * const objs = copy_compress_hentries (ht);
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1361 const Lisp_Object *pobj, *end;
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1362 int speccount = specpdl_depth ();
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1363 struct gcpro gcpro1;
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1364
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1365 record_unwind_protect (maphash_unwind, make_opaque_ptr ((void *)objs));
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1366 GCPRO1 (objs[0]);
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1367 gcpro1.nvars = 2 * ht->count;
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1368
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1369 for (pobj = objs, end = pobj + 2 * ht->count; pobj < end; pobj += 2)
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1370 if (function (pobj[0], pobj[1], extra_arg))
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1371 break;
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1372
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1373 unbind_to (speccount, Qnil);
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1374 UNGCPRO;
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1375 }
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1376
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1377 /* Remove all elements of a lisp hash table satisfying *C* predicate PREDICATE.
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1378 PREDICATE must not modify HASH-TABLE. */
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1379 void
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1380 elisp_map_remhash (maphash_function_t predicate,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1381 Lisp_Object hash_table, void *extra_arg)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1382 {
489
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1383 const Lisp_Hash_Table * const ht = xhash_table (hash_table);
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1384 Lisp_Object * const objs = copy_compress_hentries (ht);
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1385 const Lisp_Object *pobj, *end;
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1386 int speccount = specpdl_depth ();
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1387 struct gcpro gcpro1;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1388
489
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1389 record_unwind_protect (maphash_unwind, make_opaque_ptr ((void *)objs));
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1390 GCPRO1 (objs[0]);
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1391 gcpro1.nvars = 2 * ht->count;
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1392
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1393 for (pobj = objs, end = pobj + 2 * ht->count; pobj < end; pobj += 2)
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1394 if (predicate (pobj[0], pobj[1], extra_arg))
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1395 Fremhash (pobj[0], hash_table);
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1396
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1397 unbind_to (speccount, Qnil);
4a8bb4aa9740 [xemacs-hg @ 2001-04-30 08:49:24 by martinb]
martinb
parents: 464
diff changeset
1398 UNGCPRO;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1399 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1400
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1401
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1402 /************************************************************************/
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1403 /* garbage collecting weak hash tables */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1404 /************************************************************************/
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1405 #define MARK_OBJ(obj) do { \
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1406 Lisp_Object mo_obj = (obj); \
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1407 if (!marked_p (mo_obj)) \
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1408 { \
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1409 mark_object (mo_obj); \
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1410 did_mark = 1; \
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1411 } \
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1412 } while (0)
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1413
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1414
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1415 /* Complete the marking for semi-weak hash tables. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1416 int
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1417 finish_marking_weak_hash_tables (void)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1418 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1419 Lisp_Object hash_table;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1420 int did_mark = 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1421
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1422 for (hash_table = Vall_weak_hash_tables;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1423 !NILP (hash_table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1424 hash_table = XHASH_TABLE (hash_table)->next_weak)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1425 {
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1426 const Lisp_Hash_Table *ht = XHASH_TABLE (hash_table);
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1427 const hentry *e = ht->hentries;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1428 const hentry *sentinel = e + ht->size;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1429
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1430 if (! marked_p (hash_table))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1431 /* The hash table is probably garbage. Ignore it. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1432 continue;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1433
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1434 /* Now, scan over all the pairs. For all pairs that are
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1435 half-marked, we may need to mark the other half if we're
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1436 keeping this pair. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1437 switch (ht->weakness)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1438 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1439 case HASH_TABLE_KEY_WEAK:
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1440 for (; e < sentinel; e++)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1441 if (!HENTRY_CLEAR_P (e))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1442 if (marked_p (e->key))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1443 MARK_OBJ (e->value);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1444 break;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1445
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1446 case HASH_TABLE_VALUE_WEAK:
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1447 for (; e < sentinel; e++)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1448 if (!HENTRY_CLEAR_P (e))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1449 if (marked_p (e->value))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1450 MARK_OBJ (e->key);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1451 break;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1452
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1453 case HASH_TABLE_KEY_VALUE_WEAK:
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1454 for (; e < sentinel; e++)
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1455 if (!HENTRY_CLEAR_P (e))
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1456 {
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1457 if (marked_p (e->value))
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1458 MARK_OBJ (e->key);
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1459 else if (marked_p (e->key))
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1460 MARK_OBJ (e->value);
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1461 }
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1462 break;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1463
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1464 case HASH_TABLE_KEY_CAR_WEAK:
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1465 for (; e < sentinel; e++)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1466 if (!HENTRY_CLEAR_P (e))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1467 if (!CONSP (e->key) || marked_p (XCAR (e->key)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1468 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1469 MARK_OBJ (e->key);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1470 MARK_OBJ (e->value);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1471 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1472 break;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1473
450
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
1474 /* We seem to be sprouting new weakness types at an alarming
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
1475 rate. At least this is not externally visible - and in
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
1476 fact all of these KEY_CAR_* types are only used by the
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
1477 glyph code. */
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
1478 case HASH_TABLE_KEY_CAR_VALUE_WEAK:
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
1479 for (; e < sentinel; e++)
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
1480 if (!HENTRY_CLEAR_P (e))
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
1481 {
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
1482 if (!CONSP (e->key) || marked_p (XCAR (e->key)))
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
1483 {
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
1484 MARK_OBJ (e->key);
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
1485 MARK_OBJ (e->value);
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
1486 }
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
1487 else if (marked_p (e->value))
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
1488 MARK_OBJ (e->key);
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
1489 }
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
1490 break;
98528da0b7fc Import from CVS: tag r21-2-40
cvs
parents: 444
diff changeset
1491
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1492 case HASH_TABLE_VALUE_CAR_WEAK:
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1493 for (; e < sentinel; e++)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1494 if (!HENTRY_CLEAR_P (e))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1495 if (!CONSP (e->value) || marked_p (XCAR (e->value)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1496 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1497 MARK_OBJ (e->key);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1498 MARK_OBJ (e->value);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1499 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1500 break;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1501
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1502 default:
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1503 break;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1504 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1505 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1506
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1507 return did_mark;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1508 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1509
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1510 void
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1511 prune_weak_hash_tables (void)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1512 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1513 Lisp_Object hash_table, prev = Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1514 for (hash_table = Vall_weak_hash_tables;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1515 !NILP (hash_table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1516 hash_table = XHASH_TABLE (hash_table)->next_weak)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1517 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1518 if (! marked_p (hash_table))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1519 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1520 /* This hash table itself is garbage. Remove it from the list. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1521 if (NILP (prev))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1522 Vall_weak_hash_tables = XHASH_TABLE (hash_table)->next_weak;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1523 else
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1524 XHASH_TABLE (prev)->next_weak = XHASH_TABLE (hash_table)->next_weak;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1525 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1526 else
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1527 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1528 /* Now, scan over all the pairs. Remove all of the pairs
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1529 in which the key or value, or both, is unmarked
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1530 (depending on the weakness of the hash table). */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1531 Lisp_Hash_Table *ht = XHASH_TABLE (hash_table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1532 hentry *entries = ht->hentries;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1533 hentry *sentinel = entries + ht->size;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1534 hentry *e;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1535
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1536 for (e = entries; e < sentinel; e++)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1537 if (!HENTRY_CLEAR_P (e))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1538 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1539 again:
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1540 if (!marked_p (e->key) || !marked_p (e->value))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1541 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1542 remhash_1 (ht, entries, e);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1543 if (!HENTRY_CLEAR_P (e))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1544 goto again;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1545 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1546 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1547
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1548 prev = hash_table;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1549 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1550 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1551 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1552
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1553 /* Return a hash value for an array of Lisp_Objects of size SIZE. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1554
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1555 hashcode_t
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1556 internal_array_hash (Lisp_Object *arr, int size, int depth)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1557 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1558 int i;
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1559 hashcode_t hash = 0;
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1560 depth++;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1561
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1562 if (size <= 5)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1563 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1564 for (i = 0; i < size; i++)
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1565 hash = HASH2 (hash, internal_hash (arr[i], depth));
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1566 return hash;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1567 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1568
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1569 /* just pick five elements scattered throughout the array.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1570 A slightly better approach would be to offset by some
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1571 noise factor from the points chosen below. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1572 for (i = 0; i < 5; i++)
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1573 hash = HASH2 (hash, internal_hash (arr[i*size/5], depth));
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1574
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1575 return hash;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1576 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1577
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1578 /* Return a hash value for a Lisp_Object. This is for use when hashing
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1579 objects with the comparison being `equal' (for `eq', you can just
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1580 use the Lisp_Object itself as the hash value). You need to make a
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1581 tradeoff between the speed of the hash function and how good the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1582 hashing is. In particular, the hash function needs to be FAST,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1583 so you can't just traipse down the whole tree hashing everything
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1584 together. Most of the time, objects will differ in the first
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1585 few elements you hash. Thus, we only go to a short depth (5)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1586 and only hash at most 5 elements out of a vector. Theoretically
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1587 we could still take 5^5 time (a big big number) to compute a
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1588 hash, but practically this won't ever happen. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1589
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1590 hashcode_t
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1591 internal_hash (Lisp_Object obj, int depth)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1592 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1593 if (depth > 5)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1594 return 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1595 if (CONSP (obj))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1596 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1597 /* no point in worrying about tail recursion, since we're not
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1598 going very deep */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1599 return HASH2 (internal_hash (XCAR (obj), depth + 1),
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1600 internal_hash (XCDR (obj), depth + 1));
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1601 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1602 if (STRINGP (obj))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1603 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1604 return hash_string (XSTRING_DATA (obj), XSTRING_LENGTH (obj));
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1605 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1606 if (LRECORDP (obj))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1607 {
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1608 const struct lrecord_implementation
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1609 *imp = XRECORD_LHEADER_IMPLEMENTATION (obj);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1610 if (imp->hash)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1611 return imp->hash (obj, depth);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1612 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1613
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1614 return LISP_HASH (obj);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1615 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1616
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1617 DEFUN ("sxhash", Fsxhash, 1, 1, 0, /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1618 Return a hash value for OBJECT.
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 442
diff changeset
1619 \(equal obj1 obj2) implies (= (sxhash obj1) (sxhash obj2)).
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1620 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1621 (object))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1622 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1623 return make_int (internal_hash (object, 0));
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1624 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1625
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1626 #if 0
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1627 xxDEFUN ("internal-hash-value", Finternal_hash_value, 1, 1, 0, /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1628 Hash value of OBJECT. For debugging.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1629 The value is returned as (HIGH . LOW).
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1630 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1631 (object))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1632 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1633 /* This function is pretty 32bit-centric. */
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1634 hashcode_t hash = internal_hash (object, 0);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1635 return Fcons (hash >> 16, hash & 0xffff);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1636 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1637 #endif
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1638
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1639
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1640 /************************************************************************/
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1641 /* initialization */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1642 /************************************************************************/
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1643
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1644 void
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1645 syms_of_elhash (void)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1646 {
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1647 INIT_LRECORD_IMPLEMENTATION (hash_table);
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
1648
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1649 DEFSUBR (Fhash_table_p);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1650 DEFSUBR (Fmake_hash_table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1651 DEFSUBR (Fcopy_hash_table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1652 DEFSUBR (Fgethash);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1653 DEFSUBR (Fremhash);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1654 DEFSUBR (Fputhash);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1655 DEFSUBR (Fclrhash);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1656 DEFSUBR (Fmaphash);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1657 DEFSUBR (Fhash_table_count);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1658 DEFSUBR (Fhash_table_test);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1659 DEFSUBR (Fhash_table_size);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1660 DEFSUBR (Fhash_table_rehash_size);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1661 DEFSUBR (Fhash_table_rehash_threshold);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1662 DEFSUBR (Fhash_table_weakness);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1663 DEFSUBR (Fhash_table_type); /* obsolete */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1664 DEFSUBR (Fsxhash);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1665 #if 0
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1666 DEFSUBR (Finternal_hash_value);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1667 #endif
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1668
563
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
1669 DEFSYMBOL_MULTIWORD_PREDICATE (Qhash_tablep);
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
1670 DEFSYMBOL (Qhash_table);
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
1671 DEFSYMBOL (Qhashtable);
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
1672 DEFSYMBOL (Qweakness);
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
1673 DEFSYMBOL (Qvalue);
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
1674 DEFSYMBOL (Qkey_or_value);
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
1675 DEFSYMBOL (Qkey_and_value);
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
1676 DEFSYMBOL (Qrehash_size);
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
1677 DEFSYMBOL (Qrehash_threshold);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1678
563
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
1679 DEFSYMBOL (Qweak); /* obsolete */
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
1680 DEFSYMBOL (Qkey_weak); /* obsolete */
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
1681 DEFSYMBOL (Qkey_or_value_weak); /* obsolete */
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
1682 DEFSYMBOL (Qvalue_weak); /* obsolete */
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
1683 DEFSYMBOL (Qnon_weak); /* obsolete */
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1684
563
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
1685 DEFKEYWORD (Q_test);
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
1686 DEFKEYWORD (Q_size);
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
1687 DEFKEYWORD (Q_rehash_size);
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
1688 DEFKEYWORD (Q_rehash_threshold);
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
1689 DEFKEYWORD (Q_weakness);
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 504
diff changeset
1690 DEFKEYWORD (Q_type); /* obsolete */
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1691 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1692
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1693 void
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1694 vars_of_elhash (void)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1695 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1696 /* This must NOT be staticpro'd */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1697 Vall_weak_hash_tables = Qnil;
452
3d3049ae1304 Import from CVS: tag r21-2-41
cvs
parents: 450
diff changeset
1698 dump_add_weak_object_chain (&Vall_weak_hash_tables);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1699 }