]> mj.ucw.cz Git - libucw.git/blob - lib/hashtable.h
Enables the user to give non-global memory pool to hash table or KMP.
[libucw.git] / lib / hashtable.h
1 /*
2  *      UCW Library -- Universal Hash Table
3  *
4  *      (c) 2002--2004 Martin Mares <mj@ucw.cz>
5  *      (c) 2002--2005 Robert Spalek <robert@ucw.cz>
6  *
7  *      This software may be freely distributed and used according to the terms
8  *      of the GNU Lesser General Public License.
9  */
10
11 /*
12  *  This is not a normal header file, it's a generator of hash tables.
13  *  Each time you include it with parameters set in the corresponding
14  *  preprocessor macros, it generates a hash table with the parameters
15  *  given.
16  *
17  *  You need to specify:
18  *
19  *  HASH_NODE           data type where a node dwells (usually a struct).
20  *  HASH_PREFIX(x)      macro to add a name prefix (used on all global names
21  *                      defined by the hash table generator).
22  *
23  *  Then decide on type of keys:
24  *
25  *  HASH_KEY_ATOMIC=f   use node->f as a key of an atomic type (i.e.,
26  *                      a type which can be compared using `==')
27  *                      HASH_ATOMIC_TYPE (defaults to int).
28  *  | HASH_KEY_STRING=f use node->f as a string key, allocated
29  *                      separately from the rest of the node.
30  *  | HASH_KEY_ENDSTRING=f use node->f as a string key, allocated
31  *                      automatically at the end of the node struct
32  *                      (to be declared as "char f[1]" at the end).
33  *  | HASH_KEY_COMPLEX  use a multi-component key; as the name suggests,
34  *                      the passing of parameters is a bit complex then.
35  *                      The HASH_KEY_COMPLEX(x) macro should expand to
36  *                      `x k1, x k2, ... x kn' and you should also define:
37  *    HASH_KEY_DECL     declaration of function parameters in which key
38  *                      should be passed to all hash table operations.
39  *                      That is, `type1 k1, type2 k2, ... typen kn'.
40  *                      With complex keys, HASH_GIVE_HASHFN and HASH_GIVE_EQ
41  *                      are mandatory.
42  *  | HASH_KEY_MEMORY=f use node->f as a raw data key, compared using
43  *                      memcmp
44  *    HASH_KEY_SIZE     the length of the key block
45  *
46  *  Then specify what operations you request (all names are automatically
47  *  prefixed by calling HASH_PREFIX):
48  *
49  *  <always defined>    init() -- initialize the hash table.
50  *  HASH_WANT_CLEANUP   cleanup() -- deallocate the hash table.
51  *  HASH_WANT_FIND      node *find(key) -- find first node with the specified
52  *                      key, return NULL if no such node exists.
53  *  HASH_WANT_FIND_NEXT node *find(node *start) -- find next node with the
54  *                      specified key, return NULL if no such node exists.
55  *  HASH_WANT_NEW       node *new(key) -- create new node with given key.
56  *                      Doesn't check whether it already exists.
57  *  HASH_WANT_LOOKUP    node *lookup(key) -- find node with given key,
58  *                      if it doesn't exist, create it. Defining
59  *                      HASH_GIVE_INIT_DATA is strongly recommended.
60  *  HASH_WANT_DELETE    int delete(key) -- delete and deallocate node
61  *                      with given key. Returns success.
62  *  HASH_WANT_REMOVE    remove(node *) -- delete and deallocate given node.
63  *
64  *  You can also supply several functions:
65  *
66  *  HASH_GIVE_HASHFN    unsigned int hash(key) -- calculate hash value of key.
67  *                      We have sensible default hash functions for strings
68  *                      and integers.
69  *  HASH_GIVE_EQ        int eq(key1, key2) -- return whether keys are equal.
70  *                      By default, we use == for atomic types and either
71  *                      strcmp or strcasecmp for strings.
72  *  HASH_GIVE_EXTRA_SIZE int extra_size(key) -- returns how many bytes after the
73  *                      node should be allocated for dynamic data. Default=0
74  *                      or length of the string with HASH_KEY_ENDSTRING.
75  *  HASH_GIVE_INIT_KEY  void init_key(node *,key) -- initialize key in a newly
76  *                      created node. Defaults: assignment for atomic keys
77  *                      and static strings, strcpy for end-allocated strings.
78  *  HASH_GIVE_INIT_DATA void init_data(node *) -- initialize data fields in a
79  *                      newly created node. Very useful for lookup operations.
80  *  HASH_GIVE_ALLOC     void *alloc(unsigned int size) -- allocate space for
81  *                      a node. Default is xmalloc() or pooled allocation, depending
82  *                      on HASH_USE_POOL and HASH_AUTO_POOL switches.
83  *                      void free(void *) -- the converse.
84  *
85  *  ... and a couple of extra parameters:
86  *
87  *  HASH_NOCASE         String comparisons should be case-insensitive.
88  *  HASH_DEFAULT_SIZE=n Initially, use hash table of approx. `n' entries.
89  *  HASH_CONSERVE_SPACE Use as little space as possible.
90  *  HASH_FN_BITS=n      The hash function gives only `n' significant bits.
91  *  HASH_ATOMIC_TYPE=t  Atomic values are of type `t' instead of int.
92  *  HASH_USE_POOL=pool  Allocate all nodes from given mempool. Note, however, that
93  *                      deallocation is not supported by mempools, so delete/remove
94  *                      will leak pool memory.
95  *  HASH_AUTO_POOL=size Create a pool of the given block size automatically.
96  *  HASH_PARAM_POOL     Allocate all nodes from mempool given as a parameter to init().
97  *  HASH_ZERO_FILL      New entries should be initialized to all zeroes.
98  *  HASH_TABLE_ALLOC    The hash table itself will be allocated and freed using
99  *                      the same allocation functions as the nodes instead of
100  *                      the default xmalloc().
101  *  HASH_TABLE_DYNAMIC  Support multiple hash tables; the first parameter of all
102  *                      hash table operations is struct HASH_PREFIX(table) *.
103  *
104  *  You also get a iterator macro at no extra charge:
105  *
106  *  HASH_FOR_ALL(hash_prefix, variable)
107  *    {
108  *      // node *variable gets declared automatically
109  *      do_something_with_node(variable);
110  *      // use HASH_BREAK and HASH_CONTINUE instead of break and continue
111  *      // you must not alter contents of the hash table here
112  *    }
113  *  HASH_END_FOR;
114  *
115  *  (For dynamic tables, use HASH_FOR_ALL_DYNAMIC(hash_prefix, hash_table, variable) instead.)
116  *
117  *  Then include "lib/hashtable.h" and voila, you have a hash table
118  *  suiting all your needs (at least those which you've revealed :) ).
119  *
120  *  After including this file, all parameter macros are automatically
121  *  undef'd.
122  */
123
124 #ifndef _UCW_HASHFUNC_H
125 #include "lib/hashfunc.h"
126 #endif
127
128 #include <string.h>
129
130 /* Initial setup of parameters */
131
132 #if !defined(HASH_NODE) || !defined(HASH_PREFIX)
133 #error Some of the mandatory configuration macros are missing.
134 #endif
135
136 #if defined(HASH_KEY_ATOMIC) && !defined(HASH_CONSERVE_SPACE)
137 #define HASH_CONSERVE_SPACE
138 #endif
139
140 #define P(x) HASH_PREFIX(x)
141
142 /* Declare buckets and the hash table */
143
144 typedef HASH_NODE P(node);
145
146 typedef struct P(bucket) {
147   struct P(bucket) *next;
148 #ifndef HASH_CONSERVE_SPACE
149   uns hash;
150 #endif
151   P(node) n;
152 } P(bucket);
153
154 struct P(table) {
155   uns hash_size;
156   uns hash_count, hash_max, hash_min, hash_hard_max;
157   P(bucket) **ht;
158 #if defined(HASH_AUTO_POOL) || defined(HASH_PARAM_POOL)
159   struct mempool *pool;
160 #endif
161 };
162
163 #ifdef HASH_TABLE_DYNAMIC
164 #define T (*table)
165 #define TA struct P(table) *table
166 #define TAC TA,
167 #define TAU TA UNUSED
168 #define TAUC TA UNUSED,
169 #define TT table
170 #define TTC table,
171 #else
172 struct P(table) P(table);
173 #define T P(table)
174 #define TA void
175 #define TAC
176 #define TAU void
177 #define TAUC
178 #define TT
179 #define TTC
180 #endif
181
182 /* Preset parameters */
183
184 #if defined(HASH_KEY_ATOMIC)
185
186 #define HASH_KEY(x) x HASH_KEY_ATOMIC
187
188 #ifndef HASH_ATOMIC_TYPE
189 #  define HASH_ATOMIC_TYPE int
190 #endif
191 #define HASH_KEY_DECL HASH_ATOMIC_TYPE HASH_KEY( )
192
193 #ifndef HASH_GIVE_HASHFN
194 #  define HASH_GIVE_HASHFN
195    static inline int P(hash) (TAUC HASH_ATOMIC_TYPE x)
196    { return ((sizeof(x) <= 4) ? hash_u32(x) : hash_u64(x)); }
197 #endif
198
199 #ifndef HASH_GIVE_EQ
200 #  define HASH_GIVE_EQ
201    static inline int P(eq) (TAUC HASH_ATOMIC_TYPE x, HASH_ATOMIC_TYPE y)
202    { return x == y; }
203 #endif
204
205 #ifndef HASH_GIVE_INIT_KEY
206 #  define HASH_GIVE_INIT_KEY
207    static inline void P(init_key) (TAUC P(node) *n, HASH_ATOMIC_TYPE k)
208    { HASH_KEY(n->) = k; }
209 #endif
210
211 #elif defined(HASH_KEY_MEMORY)
212
213 #define HASH_KEY(x) x HASH_KEY_MEMORY
214
215 #define HASH_KEY_DECL byte HASH_KEY( )[HASH_KEY_SIZE]
216
217 #ifndef HASH_GIVE_HASHFN
218 #  define HASH_GIVE_HASHFN
219    static inline int P(hash) (TAUC byte *x)
220    { return hash_block(x, HASH_KEY_SIZE); }
221 #endif
222
223 #ifndef HASH_GIVE_EQ
224 #  define HASH_GIVE_EQ
225    static inline int P(eq) (TAUC byte *x, byte *y)
226    { return !memcmp(x, y, HASH_KEY_SIZE); }
227 #endif
228
229 #ifndef HASH_GIVE_INIT_KEY
230 #  define HASH_GIVE_INIT_KEY
231    static inline void P(init_key) (TAUC P(node) *n, byte *k)
232    { memcpy(HASH_KEY(n->), k, HASH_KEY_SIZE); }
233 #endif
234
235 #elif defined(HASH_KEY_STRING) || defined(HASH_KEY_ENDSTRING)
236
237 #ifdef HASH_KEY_STRING
238 #  define HASH_KEY(x) x HASH_KEY_STRING
239 #  ifndef HASH_GIVE_INIT_KEY
240 #    define HASH_GIVE_INIT_KEY
241      static inline void P(init_key) (TAUC P(node) *n, char *k)
242      { HASH_KEY(n->) = k; }
243 #  endif
244 #else
245 #  define HASH_KEY(x) x HASH_KEY_ENDSTRING
246 #  define HASH_GIVE_EXTRA_SIZE
247    static inline int P(extra_size) (TAUC char *k)
248    { return strlen(k); }
249 #  ifndef HASH_GIVE_INIT_KEY
250 #    define HASH_GIVE_INIT_KEY
251      static inline void P(init_key) (TAUC P(node) *n, char *k)
252      { strcpy(HASH_KEY(n->), k); }
253 #  endif
254 #endif
255 #define HASH_KEY_DECL char *HASH_KEY( )
256
257 #ifndef HASH_GIVE_HASHFN
258 #define HASH_GIVE_HASHFN
259   static inline uns P(hash) (TAUC char *k)
260    {
261 #    ifdef HASH_NOCASE
262        return hash_string_nocase(k);
263 #    else
264        return hash_string(k);
265 #    endif
266    }
267 #endif
268
269 #ifndef HASH_GIVE_EQ
270 #  define HASH_GIVE_EQ
271    static inline int P(eq) (TAUC char *x, char *y)
272    {
273 #    ifdef HASH_NOCASE
274        return !strcasecmp(x,y);
275 #    else
276        return !strcmp(x,y);
277 #    endif
278    }
279 #endif
280
281 #elif defined(HASH_KEY_COMPLEX)
282
283 #define HASH_KEY(x) HASH_KEY_COMPLEX(x)
284
285 #else
286 #error You forgot to set the hash key type.
287 #endif
288
289 /* Defaults for missing parameters */
290
291 #ifndef HASH_GIVE_HASHFN
292 #error Unable to determine which hash function to use.
293 #endif
294
295 #ifndef HASH_GIVE_EQ
296 #error Unable to determine how to compare two keys.
297 #endif
298
299 #ifdef HASH_GIVE_EXTRA_SIZE
300 /* This trickery is needed to avoid `unused parameter' warnings */
301 #define HASH_EXTRA_SIZE(x) P(extra_size)(TTC x)
302 #else
303 /*
304  *  Beware, C macros are expanded iteratively, not recursively,
305  *  hence we get only a _single_ argument, although the expansion
306  *  of HASH_KEY contains commas.
307  */
308 #define HASH_EXTRA_SIZE(x) 0
309 #endif
310
311 #ifndef HASH_GIVE_INIT_KEY
312 #error Unable to determine how to initialize keys.
313 #endif
314
315 #ifndef HASH_GIVE_INIT_DATA
316 static inline void P(init_data) (TAUC P(node) *n UNUSED)
317 {
318 }
319 #endif
320
321 #ifdef HASH_GIVE_ALLOC
322 /* If the caller has requested to use his own allocation functions, do so */
323 static inline void P(init_alloc) (TAU) { }
324 static inline void P(cleanup_alloc) (TAU) { }
325
326 #elif defined(HASH_USE_POOL)
327 /* If the caller has requested to use his mempool, do so */
328 #include "lib/mempool.h"
329 static inline void * P(alloc) (TAUC unsigned int size) { return mp_alloc_fast(HASH_USE_POOL, size); }
330 static inline void P(free) (TAUC void *x UNUSED) { }
331 static inline void P(init_alloc) (TAU) { }
332 static inline void P(cleanup_alloc) (TAU) { }
333
334 #elif defined(HASH_PARAM_POOL)
335 /* Use mempools given as a parameter to init() */
336 #include "lib/mempool.h"
337 static inline void * P(alloc) (TAUC unsigned int size) { return mp_alloc_fast(T.pool, size); }
338 static inline void P(free) (TAUC void *x UNUSED) { }
339 static inline void P(init_alloc) (TAU) { }
340 static inline void P(cleanup_alloc) (TAU) { }
341 #define HASH_USE_POOL
342
343 #elif defined(HASH_AUTO_POOL)
344 /* Use our own pools */
345 #include "lib/mempool.h"
346 static inline void * P(alloc) (TAUC unsigned int size) { return mp_alloc_fast(T.pool, size); }
347 static inline void P(free) (TAUC void *x UNUSED) { }
348 static inline void P(init_alloc) (TAU) { T.pool = mp_new(HASH_AUTO_POOL); }
349 static inline void P(cleanup_alloc) (TAU) { mp_delete(T.pool); }
350 #define HASH_USE_POOL
351
352 #else
353 /* The default allocation method */
354 static inline void * P(alloc) (TAUC unsigned int size) { return xmalloc(size); }
355 static inline void P(free) (TAUC void *x) { xfree(x); }
356 static inline void P(init_alloc) (TAU) { }
357 static inline void P(cleanup_alloc) (TAU) { }
358
359 #endif
360
361 #ifdef HASH_TABLE_ALLOC
362 static inline void * P(table_alloc) (TAUC unsigned int size) { return P(alloc)(size); }
363 static inline void P(table_free) (TAUC void *x) { P(free)(x); }
364 #else
365 static inline void * P(table_alloc) (TAUC unsigned int size) { return xmalloc(size); }
366 static inline void P(table_free) (TAUC void *x) { xfree(x); }
367 #endif
368
369 #ifndef HASH_DEFAULT_SIZE
370 #define HASH_DEFAULT_SIZE 32
371 #endif
372
373 #ifndef HASH_FN_BITS
374 #define HASH_FN_BITS 32
375 #endif
376
377 #ifdef HASH_ZERO_FILL
378 static inline void * P(new_bucket)(TAUC uns size)
379 {
380   byte *buck = P(alloc)(TTC size);
381   bzero(buck, size);
382   return buck;
383 }
384 #else
385 static inline void * P(new_bucket)(TAUC uns size) { return P(alloc)(TTC size); }
386 #endif
387
388 /* Now the operations */
389
390 static void P(alloc_table) (TAU)
391 {
392   T.hash_size = next_table_prime(T.hash_size);
393   T.ht = P(table_alloc)(TTC sizeof(void *) * T.hash_size);
394   bzero(T.ht, sizeof(void *) * T.hash_size);
395   if (2*T.hash_size < T.hash_hard_max)
396     T.hash_max = 2*T.hash_size;
397   else
398     T.hash_max = ~0U;
399   if (T.hash_size/2 > HASH_DEFAULT_SIZE)
400     T.hash_min = T.hash_size/4;
401   else
402     T.hash_min = 0;
403 }
404
405 #ifndef HASH_PARAM_POOL
406 static void P(init) (TA)
407 #else
408 static void P(init) (TAC struct mempool *pool)
409 #endif
410 {
411   T.hash_count = 0;
412   T.hash_size = HASH_DEFAULT_SIZE;
413 #if HASH_FN_BITS < 28
414   T.hash_hard_max = 1 << HASH_FN_BITS;
415 #else
416   T.hash_hard_max = 1 << 28;
417 #endif
418   P(alloc_table)(TT);
419 #ifdef HASH_PARAM_POOL
420   T.pool = pool;
421 #endif
422   P(init_alloc)(TT);
423 }
424
425 #ifdef HASH_WANT_CLEANUP
426 static void P(cleanup) (TA)
427 {
428 #ifndef HASH_USE_POOL
429   uns i;
430   P(bucket) *b, *bb;
431
432   for (i=0; i<T.hash_size; i++)
433     for (b=T.ht[i]; b; b=bb)
434       {
435         bb = b->next;
436         P(free)(TTC b);
437       }
438 #endif
439   P(cleanup_alloc)(TT);
440   P(table_free)(TTC T.ht);
441 }
442 #endif
443
444 static inline uns P(bucket_hash) (TAUC P(bucket) *b)
445 {
446 #ifdef HASH_CONSERVE_SPACE
447   return P(hash)(TTC HASH_KEY(b->n.));
448 #else
449   return b->hash;
450 #endif
451 }
452
453 static void P(rehash) (TAC uns size)
454 {
455   P(bucket) *b, *nb;
456   P(bucket) **oldt = T.ht, **newt;
457   uns oldsize = T.hash_size;
458   uns i, h;
459
460   DBG("Rehashing %d->%d at count %d", oldsize, size, T.hash_count);
461   T.hash_size = size;
462   P(alloc_table)(TT);
463   newt = T.ht;
464   for (i=0; i<oldsize; i++)
465     {
466       b = oldt[i];
467       while (b)
468         {
469           nb = b->next;
470           h = P(bucket_hash)(TTC b) % T.hash_size;
471           b->next = newt[h];
472           newt[h] = b;
473           b = nb;
474         }
475     }
476   P(table_free)(TTC oldt);
477 }
478
479 #ifdef HASH_WANT_FIND
480 static P(node) * P(find) (TAC HASH_KEY_DECL)
481 {
482   uns h0 = P(hash) (TTC HASH_KEY( ));
483   uns h = h0 % T.hash_size;
484   P(bucket) *b;
485
486   for (b=T.ht[h]; b; b=b->next)
487     {
488       if (
489 #ifndef HASH_CONSERVE_SPACE
490           b->hash == h0 &&
491 #endif
492           P(eq)(TTC HASH_KEY( ), HASH_KEY(b->n.)))
493         return &b->n;
494     }
495   return NULL;
496 }
497 #endif
498
499 #ifdef HASH_WANT_FIND_NEXT
500 static P(node) * P(find_next) (TAC P(node) *start)
501 {
502 #ifndef HASH_CONSERVE_SPACE
503   uns h0 = P(hash) (TTC HASH_KEY(start->));
504 #endif
505   P(bucket) *b = SKIP_BACK(P(bucket), n, start);
506
507   for (b=b->next; b; b=b->next)
508     {
509       if (
510 #ifndef HASH_CONSERVE_SPACE
511           b->hash == h0 &&
512 #endif
513           P(eq)(TTC HASH_KEY(start->), HASH_KEY(b->n.)))
514         return &b->n;
515     }
516   return NULL;
517 }
518 #endif
519
520 #ifdef HASH_WANT_NEW
521 static P(node) * P(new) (TAC HASH_KEY_DECL)
522 {
523   uns h0, h;
524   P(bucket) *b;
525
526   h0 = P(hash) (TTC HASH_KEY( ));
527   h = h0 % T.hash_size;
528   b = P(new_bucket) (TTC sizeof(struct P(bucket)) + HASH_EXTRA_SIZE(HASH_KEY( )));
529   b->next = T.ht[h];
530   T.ht[h] = b;
531 #ifndef HASH_CONSERVE_SPACE
532   b->hash = h0;
533 #endif
534   P(init_key)(TTC &b->n, HASH_KEY( ));
535   P(init_data)(TTC &b->n);
536   if (T.hash_count++ >= T.hash_max)
537     P(rehash)(TTC 2*T.hash_size);
538   return &b->n;
539 }
540 #endif
541
542 #ifdef HASH_WANT_LOOKUP
543 static P(node) * P(lookup) (TAC HASH_KEY_DECL)
544 {
545   uns h0 = P(hash) (TTC HASH_KEY( ));
546   uns h = h0 % T.hash_size;
547   P(bucket) *b;
548
549   for (b=T.ht[h]; b; b=b->next)
550     {
551       if (
552 #ifndef HASH_CONSERVE_SPACE
553           b->hash == h0 &&
554 #endif
555           P(eq)(TTC HASH_KEY( ), HASH_KEY(b->n.)))
556         return &b->n;
557     }
558
559   b = P(new_bucket) (TTC sizeof(struct P(bucket)) + HASH_EXTRA_SIZE(HASH_KEY( )));
560   b->next = T.ht[h];
561   T.ht[h] = b;
562 #ifndef HASH_CONSERVE_SPACE
563   b->hash = h0;
564 #endif
565   P(init_key)(TTC &b->n, HASH_KEY( ));
566   P(init_data)(TTC &b->n);
567   if (T.hash_count++ >= T.hash_max)
568     P(rehash)(TTC 2*T.hash_size);
569   return &b->n;
570 }
571 #endif
572
573 #ifdef HASH_WANT_DELETE
574 static int P(delete) (TAC HASH_KEY_DECL)
575 {
576   uns h0 = P(hash) (TTC HASH_KEY( ));
577   uns h = h0 % T.hash_size;
578   P(bucket) *b, **bb;
579
580   for (bb=&T.ht[h]; b=*bb; bb=&b->next)
581     {
582       if (
583 #ifndef HASH_CONSERVE_SPACE
584           b->hash == h0 &&
585 #endif
586           P(eq)(TTC HASH_KEY( ), HASH_KEY(b->n.)))
587         {
588           *bb = b->next;
589           P(free)(TTC b);
590           if (--T.hash_count < T.hash_min)
591             P(rehash)(TTC T.hash_size/2);
592           return 1;
593         }
594     }
595   return 0;
596 }
597 #endif
598
599 #ifdef HASH_WANT_REMOVE
600 static void P(remove) (TAC P(node) *n)
601 {
602   P(bucket) *x = SKIP_BACK(struct P(bucket), n, n);
603   uns h0 = P(bucket_hash)(TTC x);
604   uns h = h0 % T.hash_size;
605   P(bucket) *b, **bb;
606
607   for (bb=&T.ht[h]; (b=*bb) && b != x; bb=&b->next)
608     ;
609   ASSERT(b);
610   *bb = b->next;
611   P(free)(TTC b);
612   if (--T.hash_count < T.hash_min)
613     P(rehash)(TTC T.hash_size/2);
614 }
615 #endif
616
617 /* And the iterator */
618
619 #ifndef HASH_FOR_ALL
620
621 #define HASH_FOR_ALL_DYNAMIC(h_px, h_table, h_var)                                      \
622 do {                                                                                    \
623   uns h_slot;                                                                           \
624   struct GLUE_(h_px,bucket) *h_buck;                                                    \
625   for (h_slot=0; h_slot < (h_table)->hash_size; h_slot++)                               \
626     for (h_buck = (h_table)->ht[h_slot]; h_buck; h_buck = h_buck->next)                 \
627       {                                                                                 \
628         GLUE_(h_px,node) *h_var = &h_buck->n;
629 #define HASH_FOR_ALL(h_px, h_var) HASH_FOR_ALL_DYNAMIC(h_px, &GLUE_(h_px,table), h_var)
630 #define HASH_END_FOR } } while(0)
631 #define HASH_BREAK 
632 #define HASH_CONTINUE continue
633
634 #endif
635
636 /* Finally, undefine all the parameters */
637
638 #undef P
639 #undef T
640 #undef TA
641 #undef TAC
642 #undef TAU
643 #undef TAUC
644 #undef TT
645 #undef TTC
646
647 #undef HASH_ATOMIC_TYPE
648 #undef HASH_CONSERVE_SPACE
649 #undef HASH_DEFAULT_SIZE
650 #undef HASH_EXTRA_SIZE
651 #undef HASH_FN_BITS
652 #undef HASH_GIVE_ALLOC
653 #undef HASH_GIVE_EQ
654 #undef HASH_GIVE_EXTRA_SIZE
655 #undef HASH_GIVE_HASHFN
656 #undef HASH_GIVE_INIT_DATA
657 #undef HASH_GIVE_INIT_KEY
658 #undef HASH_KEY
659 #undef HASH_KEY_ATOMIC
660 #undef HASH_KEY_COMPLEX
661 #undef HASH_KEY_DECL
662 #undef HASH_KEY_ENDSTRING
663 #undef HASH_KEY_STRING
664 #undef HASH_NOCASE
665 #undef HASH_NODE
666 #undef HASH_PREFIX
667 #undef HASH_USE_POOL
668 #undef HASH_AUTO_POOL
669 #undef HASH_PARAM_POOL
670 #undef HASH_WANT_CLEANUP
671 #undef HASH_WANT_DELETE
672 #undef HASH_WANT_FIND
673 #undef HASH_WANT_FIND_NEXT
674 #undef HASH_WANT_LOOKUP
675 #undef HASH_WANT_NEW
676 #undef HASH_WANT_REMOVE
677 #undef HASH_TABLE_ALLOC
678 #undef HASH_TABLE_DYNAMIC
679 #undef HASH_ZERO_FILL