blob: 4a7e8132bc551b8ac6d926debadb78c11da29f86 [file] [log] [blame]
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001/* hashlib.c -- functions to manage and access hash tables for bash. */
Jari Aalto726f6381996-08-26 18:22:31 +00002
Jari Aalto31859422009-01-12 13:36:28 +00003/* Copyright (C) 1987,1989,1991,1995,1998,2001,2003,2005,2006,2008,2009 Free Software Foundation, Inc.
Jari Aalto726f6381996-08-26 18:22:31 +00004
Jari Aalto31859422009-01-12 13:36:28 +00005 This file is part of GNU Bash, the Bourne Again SHell.
Jari Aalto726f6381996-08-26 18:22:31 +00006
Jari Aalto31859422009-01-12 13:36:28 +00007 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
Jari Aalto726f6381996-08-26 18:22:31 +000011
Jari Aalto31859422009-01-12 13:36:28 +000012 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
Jari Aalto726f6381996-08-26 18:22:31 +000016
Jari Aalto31859422009-01-12 13:36:28 +000017 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19*/
Jari Aalto726f6381996-08-26 18:22:31 +000020
Jari Aaltobb706242000-03-17 21:46:59 +000021#include <config.h>
Jari Aalto726f6381996-08-26 18:22:31 +000022
Jari Aaltod166f041997-06-05 14:59:13 +000023#include "bashansi.h"
Jari Aalto726f6381996-08-26 18:22:31 +000024
Jari Aaltoccc6cda1996-12-23 17:02:34 +000025#if defined (HAVE_UNISTD_H)
Jari Aaltocce855b1998-04-17 19:52:44 +000026# ifdef _MINIX
27# include <sys/types.h>
28# endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +000029# include <unistd.h>
30#endif
31
Jari Aaltod166f041997-06-05 14:59:13 +000032#include <stdio.h>
33
Jari Aalto726f6381996-08-26 18:22:31 +000034#include "shell.h"
Jari Aaltoccc6cda1996-12-23 17:02:34 +000035#include "hashlib.h"
Jari Aalto726f6381996-08-26 18:22:31 +000036
Chet Ramey8868eda2020-12-06 15:51:17 -050037/* tunable constants for rehashing */
38#define HASH_REHASH_MULTIPLIER 4
39#define HASH_REHASH_FACTOR 2
40
41#define HASH_SHOULDGROW(table) \
42 ((table)->nentries >= (table)->nbuckets * HASH_REHASH_FACTOR)
43
44/* an initial approximation */
45#define HASH_SHOULDSHRINK(table) \
46 (((table)->nbuckets > DEFAULT_HASH_BUCKETS) && \
47 ((table)->nentries < (table)->nbuckets / HASH_REHASH_MULTIPLIER))
48
Jari Aalto7117c2d2002-07-17 14:10:11 +000049/* Rely on properties of unsigned division (unsigned/int -> unsigned) and
50 don't discard the upper 32 bits of the value, if present. */
51#define HASH_BUCKET(s, t, h) (((h) = hash_string (s)) & ((t)->nbuckets - 1))
Jari Aaltof73dda02001-11-13 17:56:06 +000052
Chet Ramey8868eda2020-12-06 15:51:17 -050053static BUCKET_CONTENTS *copy_bucket_array PARAMS((BUCKET_CONTENTS *, sh_string_func_t *));
54
55static void hash_rehash PARAMS((HASH_TABLE *, int));
56static void hash_grow PARAMS((HASH_TABLE *));
57static void hash_shrink PARAMS((HASH_TABLE *));
Jari Aalto726f6381996-08-26 18:22:31 +000058
59/* Make a new hash table with BUCKETS number of buckets. Initialize
60 each slot in the table to NULL. */
61HASH_TABLE *
Jari Aalto7117c2d2002-07-17 14:10:11 +000062hash_create (buckets)
Jari Aalto726f6381996-08-26 18:22:31 +000063 int buckets;
64{
Jari Aaltoccc6cda1996-12-23 17:02:34 +000065 HASH_TABLE *new_table;
Jari Aalto7117c2d2002-07-17 14:10:11 +000066 register int i;
Jari Aalto726f6381996-08-26 18:22:31 +000067
Jari Aaltoccc6cda1996-12-23 17:02:34 +000068 new_table = (HASH_TABLE *)xmalloc (sizeof (HASH_TABLE));
Jari Aalto726f6381996-08-26 18:22:31 +000069 if (buckets == 0)
70 buckets = DEFAULT_HASH_BUCKETS;
71
72 new_table->bucket_array =
73 (BUCKET_CONTENTS **)xmalloc (buckets * sizeof (BUCKET_CONTENTS *));
74 new_table->nbuckets = buckets;
75 new_table->nentries = 0;
Jari Aalto7117c2d2002-07-17 14:10:11 +000076
77 for (i = 0; i < buckets; i++)
78 new_table->bucket_array[i] = (BUCKET_CONTENTS *)NULL;
79
Jari Aalto726f6381996-08-26 18:22:31 +000080 return (new_table);
81}
82
Jari Aaltof73dda02001-11-13 17:56:06 +000083int
Jari Aalto7117c2d2002-07-17 14:10:11 +000084hash_size (table)
Jari Aaltof73dda02001-11-13 17:56:06 +000085 HASH_TABLE *table;
86{
87 return (HASH_ENTRIES(table));
88}
89
90static BUCKET_CONTENTS *
91copy_bucket_array (ba, cpdata)
92 BUCKET_CONTENTS *ba;
93 sh_string_func_t *cpdata; /* data copy function */
94{
95 BUCKET_CONTENTS *new_bucket, *n, *e;
96
97 if (ba == 0)
98 return ((BUCKET_CONTENTS *)0);
99
100 for (n = (BUCKET_CONTENTS *)0, e = ba; e; e = e->next)
101 {
102 if (n == 0)
103 {
104 new_bucket = (BUCKET_CONTENTS *)xmalloc (sizeof (BUCKET_CONTENTS));
105 n = new_bucket;
106 }
107 else
108 {
109 n->next = (BUCKET_CONTENTS *)xmalloc (sizeof (BUCKET_CONTENTS));
110 n = n->next;
111 }
112
113 n->key = savestring (e->key);
114 n->data = e->data ? (cpdata ? (*cpdata) (e->data) : savestring (e->data))
Jari Aalto7117c2d2002-07-17 14:10:11 +0000115 : NULL;
116 n->khash = e->khash;
Jari Aaltof73dda02001-11-13 17:56:06 +0000117 n->times_found = e->times_found;
118 n->next = (BUCKET_CONTENTS *)NULL;
119 }
120
121 return new_bucket;
122}
123
Chet Ramey8868eda2020-12-06 15:51:17 -0500124static void
125hash_rehash (table, nsize)
126 HASH_TABLE *table;
127 int nsize;
128{
129 int osize, i, j;
130 BUCKET_CONTENTS **old_bucket_array, *item, *next;
131
132 if (table == NULL || nsize == table->nbuckets)
133 return;
134
135 osize = table->nbuckets;
136 old_bucket_array = table->bucket_array;
137
138 table->nbuckets = nsize;
139 table->bucket_array = (BUCKET_CONTENTS **)xmalloc (table->nbuckets * sizeof (BUCKET_CONTENTS *));
140 for (i = 0; i < table->nbuckets; i++)
141 table->bucket_array[i] = (BUCKET_CONTENTS *)NULL;
142
143 for (j = 0; j < osize; j++)
144 {
145 for (item = old_bucket_array[j]; item; item = next)
146 {
147 next = item->next;
148 i = item->khash & (table->nbuckets - 1);
149 item->next = table->bucket_array[i];
150 table->bucket_array[i] = item;
151 }
152 }
153
154 free (old_bucket_array);
155}
156
157static void
158hash_grow (table)
159 HASH_TABLE *table;
160{
161 int nsize;
162
163 nsize = table->nbuckets * HASH_REHASH_MULTIPLIER;
164 if (nsize > 0) /* overflow */
165 hash_rehash (table, nsize);
166}
167
168static void
169hash_shrink (table)
170 HASH_TABLE *table;
171{
172 int nsize;
173
174 nsize = table->nbuckets / HASH_REHASH_MULTIPLIER;
175 hash_rehash (table, nsize);
176}
177
Jari Aaltof73dda02001-11-13 17:56:06 +0000178HASH_TABLE *
Jari Aalto7117c2d2002-07-17 14:10:11 +0000179hash_copy (table, cpdata)
Jari Aaltof73dda02001-11-13 17:56:06 +0000180 HASH_TABLE *table;
181 sh_string_func_t *cpdata;
182{
183 HASH_TABLE *new_table;
184 int i;
185
186 if (table == 0)
187 return ((HASH_TABLE *)NULL);
188
Jari Aalto7117c2d2002-07-17 14:10:11 +0000189 new_table = hash_create (table->nbuckets);
Jari Aaltof73dda02001-11-13 17:56:06 +0000190
191 for (i = 0; i < table->nbuckets; i++)
192 new_table->bucket_array[i] = copy_bucket_array (table->bucket_array[i], cpdata);
193
194 new_table->nentries = table->nentries;
195 return new_table;
196}
197
Chet Rameyd233b482019-01-07 09:27:52 -0500198/* This is the best 32-bit string hash function I found. It's one of the
199 Fowler-Noll-Vo family (FNV-1).
200
201 The magic is in the interesting relationship between the special prime
202 16777619 (2^24 + 403) and 2^32 and 2^8. */
203
204#define FNV_OFFSET 2166136261
205#define FNV_PRIME 16777619
206
207/* If you want to use 64 bits, use
208FNV_OFFSET 14695981039346656037
Chet Ramey8868eda2020-12-06 15:51:17 -0500209FNV_PRIME 1099511628211
Chet Rameyd233b482019-01-07 09:27:52 -0500210*/
211
Jari Aalto7117c2d2002-07-17 14:10:11 +0000212/* The `khash' check below requires that strings that compare equally with
213 strcmp hash to the same value. */
214unsigned int
215hash_string (s)
216 const char *s;
217{
218 register unsigned int i;
219
Chet Rameyd233b482019-01-07 09:27:52 -0500220 for (i = FNV_OFFSET; *s; s++)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000221 {
Chet Ramey8868eda2020-12-06 15:51:17 -0500222 /* FNV-1a has the XOR first, traditional FNV-1 has the multiply first */
223
224 /* was i *= FNV_PRIME */
225 i += (i<<1) + (i<<4) + (i<<7) + (i<<8) + (i<<24);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000226 i ^= *s;
227 }
228
229 return i;
230}
231
Jari Aalto726f6381996-08-26 18:22:31 +0000232/* Return the location of the bucket which should contain the data
233 for STRING. TABLE is a pointer to a HASH_TABLE. */
234
Jari Aalto726f6381996-08-26 18:22:31 +0000235int
Jari Aalto7117c2d2002-07-17 14:10:11 +0000236hash_bucket (string, table)
Jari Aaltof73dda02001-11-13 17:56:06 +0000237 const char *string;
Jari Aalto726f6381996-08-26 18:22:31 +0000238 HASH_TABLE *table;
239{
Jari Aalto7117c2d2002-07-17 14:10:11 +0000240 unsigned int h;
Jari Aalto726f6381996-08-26 18:22:31 +0000241
Jari Aalto7117c2d2002-07-17 14:10:11 +0000242 return (HASH_BUCKET (string, table, h));
Jari Aalto726f6381996-08-26 18:22:31 +0000243}
244
Jari Aalto7117c2d2002-07-17 14:10:11 +0000245/* Return a pointer to the hashed item. If the HASH_CREATE flag is passed,
246 create a new hash table entry for STRING, otherwise return NULL. */
Jari Aalto726f6381996-08-26 18:22:31 +0000247BUCKET_CONTENTS *
Jari Aalto7117c2d2002-07-17 14:10:11 +0000248hash_search (string, table, flags)
Jari Aaltof73dda02001-11-13 17:56:06 +0000249 const char *string;
Jari Aalto726f6381996-08-26 18:22:31 +0000250 HASH_TABLE *table;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000251 int flags;
Jari Aalto726f6381996-08-26 18:22:31 +0000252{
253 BUCKET_CONTENTS *list;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000254 int bucket;
255 unsigned int hv;
Jari Aalto726f6381996-08-26 18:22:31 +0000256
Jari Aalto7117c2d2002-07-17 14:10:11 +0000257 if (table == 0 || ((flags & HASH_CREATE) == 0 && HASH_ENTRIES (table) == 0))
Jari Aalto726f6381996-08-26 18:22:31 +0000258 return (BUCKET_CONTENTS *)NULL;
259
Jari Aalto7117c2d2002-07-17 14:10:11 +0000260 bucket = HASH_BUCKET (string, table, hv);
Jari Aalto726f6381996-08-26 18:22:31 +0000261
Chet Ramey00018032011-11-21 20:51:19 -0500262 for (list = table->bucket_array ? table->bucket_array[bucket] : 0; list; list = list->next)
Jari Aalto726f6381996-08-26 18:22:31 +0000263 {
Chet Rameya0c0a002016-09-15 16:59:08 -0400264 /* This is the comparison function */
Jari Aalto7117c2d2002-07-17 14:10:11 +0000265 if (hv == list->khash && STREQ (list->key, string))
Jari Aalto726f6381996-08-26 18:22:31 +0000266 {
267 list->times_found++;
268 return (list);
269 }
Jari Aalto726f6381996-08-26 18:22:31 +0000270 }
Jari Aalto7117c2d2002-07-17 14:10:11 +0000271
272 if (flags & HASH_CREATE)
273 {
Chet Ramey8868eda2020-12-06 15:51:17 -0500274 if (HASH_SHOULDGROW (table))
275 {
276 hash_grow (table);
277 bucket = HASH_BUCKET (string, table, hv);
278 }
279
Jari Aalto7117c2d2002-07-17 14:10:11 +0000280 list = (BUCKET_CONTENTS *)xmalloc (sizeof (BUCKET_CONTENTS));
281 list->next = table->bucket_array[bucket];
282 table->bucket_array[bucket] = list;
283
284 list->data = NULL;
285 list->key = (char *)string; /* XXX fix later */
286 list->khash = hv;
287 list->times_found = 0;
288
289 table->nentries++;
290 return (list);
291 }
292
Jari Aalto726f6381996-08-26 18:22:31 +0000293 return (BUCKET_CONTENTS *)NULL;
294}
295
296/* Remove the item specified by STRING from the hash table TABLE.
297 The item removed is returned, so you can free its contents. If
298 the item isn't in this table NULL is returned. */
299BUCKET_CONTENTS *
Jari Aalto7117c2d2002-07-17 14:10:11 +0000300hash_remove (string, table, flags)
Jari Aaltof73dda02001-11-13 17:56:06 +0000301 const char *string;
Jari Aalto726f6381996-08-26 18:22:31 +0000302 HASH_TABLE *table;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000303 int flags;
Jari Aalto726f6381996-08-26 18:22:31 +0000304{
Jari Aalto7117c2d2002-07-17 14:10:11 +0000305 int bucket;
Jari Aalto726f6381996-08-26 18:22:31 +0000306 BUCKET_CONTENTS *prev, *temp;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000307 unsigned int hv;
Jari Aalto726f6381996-08-26 18:22:31 +0000308
Jari Aalto7117c2d2002-07-17 14:10:11 +0000309 if (table == 0 || HASH_ENTRIES (table) == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000310 return (BUCKET_CONTENTS *)NULL;
311
Jari Aalto7117c2d2002-07-17 14:10:11 +0000312 bucket = HASH_BUCKET (string, table, hv);
Jari Aalto726f6381996-08-26 18:22:31 +0000313 prev = (BUCKET_CONTENTS *)NULL;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000314 for (temp = table->bucket_array[bucket]; temp; temp = temp->next)
Jari Aalto726f6381996-08-26 18:22:31 +0000315 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000316 if (hv == temp->khash && STREQ (temp->key, string))
Jari Aalto726f6381996-08-26 18:22:31 +0000317 {
318 if (prev)
319 prev->next = temp->next;
320 else
Jari Aalto7117c2d2002-07-17 14:10:11 +0000321 table->bucket_array[bucket] = temp->next;
Jari Aalto726f6381996-08-26 18:22:31 +0000322
323 table->nentries--;
324 return (temp);
325 }
326 prev = temp;
Jari Aalto726f6381996-08-26 18:22:31 +0000327 }
328 return ((BUCKET_CONTENTS *) NULL);
329}
330
331/* Create an entry for STRING, in TABLE. If the entry already
Jari Aalto7117c2d2002-07-17 14:10:11 +0000332 exists, then return it (unless the HASH_NOSRCH flag is set). */
Jari Aalto726f6381996-08-26 18:22:31 +0000333BUCKET_CONTENTS *
Jari Aalto7117c2d2002-07-17 14:10:11 +0000334hash_insert (string, table, flags)
Jari Aalto726f6381996-08-26 18:22:31 +0000335 char *string;
336 HASH_TABLE *table;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000337 int flags;
Jari Aalto726f6381996-08-26 18:22:31 +0000338{
339 BUCKET_CONTENTS *item;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000340 int bucket;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000341 unsigned int hv;
Jari Aalto726f6381996-08-26 18:22:31 +0000342
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000343 if (table == 0)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000344 table = hash_create (0);
Jari Aalto726f6381996-08-26 18:22:31 +0000345
Jari Aalto7117c2d2002-07-17 14:10:11 +0000346 item = (flags & HASH_NOSRCH) ? (BUCKET_CONTENTS *)NULL
347 : hash_search (string, table, 0);
348
349 if (item == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000350 {
Chet Ramey8868eda2020-12-06 15:51:17 -0500351 if (HASH_SHOULDGROW (table))
352 hash_grow (table);
353
Jari Aalto7117c2d2002-07-17 14:10:11 +0000354 bucket = HASH_BUCKET (string, table, hv);
Jari Aalto726f6381996-08-26 18:22:31 +0000355
Jari Aalto7117c2d2002-07-17 14:10:11 +0000356 item = (BUCKET_CONTENTS *)xmalloc (sizeof (BUCKET_CONTENTS));
357 item->next = table->bucket_array[bucket];
358 table->bucket_array[bucket] = item;
Jari Aalto726f6381996-08-26 18:22:31 +0000359
Jari Aalto7117c2d2002-07-17 14:10:11 +0000360 item->data = NULL;
Jari Aalto726f6381996-08-26 18:22:31 +0000361 item->key = string;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000362 item->khash = hv;
Jari Aalto726f6381996-08-26 18:22:31 +0000363 item->times_found = 0;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000364
365 table->nentries++;
Jari Aalto726f6381996-08-26 18:22:31 +0000366 }
367
368 return (item);
369}
370
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000371/* Remove and discard all entries in TABLE. If FREE_DATA is non-null, it
372 is a function to call to dispose of a hash item's data. Otherwise,
373 free() is called. */
374void
Jari Aalto7117c2d2002-07-17 14:10:11 +0000375hash_flush (table, free_data)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000376 HASH_TABLE *table;
Jari Aaltof73dda02001-11-13 17:56:06 +0000377 sh_free_func_t *free_data;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000378{
379 int i;
380 register BUCKET_CONTENTS *bucket, *item;
381
Jari Aalto7117c2d2002-07-17 14:10:11 +0000382 if (table == 0 || HASH_ENTRIES (table) == 0)
Jari Aaltod166f041997-06-05 14:59:13 +0000383 return;
384
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000385 for (i = 0; i < table->nbuckets; i++)
386 {
387 bucket = table->bucket_array[i];
388
389 while (bucket)
390 {
391 item = bucket;
392 bucket = bucket->next;
393
394 if (free_data)
395 (*free_data) (item->data);
396 else
397 free (item->data);
398 free (item->key);
399 free (item);
400 }
401 table->bucket_array[i] = (BUCKET_CONTENTS *)NULL;
402 }
Jari Aalto7117c2d2002-07-17 14:10:11 +0000403
404 table->nentries = 0;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000405}
406
Jari Aaltod166f041997-06-05 14:59:13 +0000407/* Free the hash table pointed to by TABLE. */
408void
Jari Aalto7117c2d2002-07-17 14:10:11 +0000409hash_dispose (table)
Jari Aaltod166f041997-06-05 14:59:13 +0000410 HASH_TABLE *table;
411{
412 free (table->bucket_array);
413 free (table);
414}
415
Jari Aaltocce855b1998-04-17 19:52:44 +0000416void
Jari Aalto7117c2d2002-07-17 14:10:11 +0000417hash_walk (table, func)
418 HASH_TABLE *table;
419 hash_wfunc *func;
420{
421 register int i;
422 BUCKET_CONTENTS *item;
423
424 if (table == 0 || HASH_ENTRIES (table) == 0)
425 return;
426
427 for (i = 0; i < table->nbuckets; i++)
428 {
429 for (item = hash_items (i, table); item; item = item->next)
430 if ((*func) (item) < 0)
431 return;
432 }
433}
434
435#if defined (DEBUG) || defined (TEST_HASHING)
436void
437hash_pstats (table, name)
Jari Aaltod166f041997-06-05 14:59:13 +0000438 HASH_TABLE *table;
439 char *name;
440{
441 register int slot, bcount;
442 register BUCKET_CONTENTS *bc;
443
444 if (name == 0)
445 name = "unknown hash table";
446
447 fprintf (stderr, "%s: %d buckets; %d items\n", name, table->nbuckets, table->nentries);
448
449 /* Print out a count of how many strings hashed to each bucket, so we can
450 see how even the distribution is. */
451 for (slot = 0; slot < table->nbuckets; slot++)
452 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000453 bc = hash_items (slot, table);
Jari Aaltod166f041997-06-05 14:59:13 +0000454
455 fprintf (stderr, "\tslot %3d: ", slot);
456 for (bcount = 0; bc; bc = bc->next)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000457 bcount++;
Jari Aaltod166f041997-06-05 14:59:13 +0000458
459 fprintf (stderr, "%d\n", bcount);
460 }
461}
Jari Aaltocce855b1998-04-17 19:52:44 +0000462#endif
Jari Aaltod166f041997-06-05 14:59:13 +0000463
Jari Aalto726f6381996-08-26 18:22:31 +0000464#ifdef TEST_HASHING
465
Jari Aalto7117c2d2002-07-17 14:10:11 +0000466/* link with xmalloc.o and lib/malloc/libmalloc.a */
Jari Aalto726f6381996-08-26 18:22:31 +0000467#undef NULL
468#include <stdio.h>
469
Jari Aaltof73dda02001-11-13 17:56:06 +0000470#ifndef NULL
471#define NULL 0
472#endif
473
474HASH_TABLE *table, *ntable;
Jari Aalto726f6381996-08-26 18:22:31 +0000475
Jari Aalto7117c2d2002-07-17 14:10:11 +0000476int interrupt_immediately = 0;
Chet Ramey8868eda2020-12-06 15:51:17 -0500477int running_trap = 0;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000478
479int
480signal_is_trapped (s)
481 int s;
Jari Aalto726f6381996-08-26 18:22:31 +0000482{
Jari Aalto7117c2d2002-07-17 14:10:11 +0000483 return (0);
484}
485
486void
487programming_error (const char *format, ...)
488{
489 abort();
490}
491
492void
493fatal_error (const char *format, ...)
494{
495 abort();
Jari Aalto726f6381996-08-26 18:22:31 +0000496}
497
Chet Rameya0c0a002016-09-15 16:59:08 -0400498void
499internal_warning (const char *format, ...)
500{
501}
502
Chet Ramey8868eda2020-12-06 15:51:17 -0500503int
Jari Aalto726f6381996-08-26 18:22:31 +0000504main ()
505{
506 char string[256];
507 int count = 0;
508 BUCKET_CONTENTS *tt;
509
Chet Rameya0c0a002016-09-15 16:59:08 -0400510#if defined (TEST_NBUCKETS)
511 table = hash_create (TEST_NBUCKETS);
512#else
Jari Aalto7117c2d2002-07-17 14:10:11 +0000513 table = hash_create (0);
Chet Rameya0c0a002016-09-15 16:59:08 -0400514#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000515
Jari Aalto726f6381996-08-26 18:22:31 +0000516 for (;;)
517 {
518 char *temp_string;
519 if (fgets (string, sizeof (string), stdin) == 0)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000520 break;
Jari Aalto726f6381996-08-26 18:22:31 +0000521 if (!*string)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000522 break;
Jari Aalto726f6381996-08-26 18:22:31 +0000523 temp_string = savestring (string);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000524 tt = hash_insert (temp_string, table, 0);
Jari Aalto726f6381996-08-26 18:22:31 +0000525 if (tt->times_found)
526 {
527 fprintf (stderr, "You have already added item `%s'\n", string);
528 free (temp_string);
529 }
530 else
531 {
532 count++;
533 }
534 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000535
Jari Aalto7117c2d2002-07-17 14:10:11 +0000536 hash_pstats (table, "hash test");
Jari Aaltof73dda02001-11-13 17:56:06 +0000537
Jari Aalto7117c2d2002-07-17 14:10:11 +0000538 ntable = hash_copy (table, (sh_string_func_t *)NULL);
539 hash_flush (table, (sh_free_func_t *)NULL);
540 hash_pstats (ntable, "hash copy test");
Jari Aaltof73dda02001-11-13 17:56:06 +0000541
Jari Aaltod166f041997-06-05 14:59:13 +0000542 exit (0);
Jari Aalto726f6381996-08-26 18:22:31 +0000543}
544
545#endif /* TEST_HASHING */