back out new hash routine
[external/binutils.git] / gas / hash.c
1 /* hash.c - hash table lookup strings -
2    Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
3
4    This file is part of GAS, the GNU Assembler.
5
6    GAS is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    GAS is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with GAS; see the file COPYING.  If not, write to
18    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 /*
21  * BUGS, GRIPES, APOLOGIA etc.
22  *
23  * A typical user doesn't need ALL this: I intend to make a library out
24  * of it one day - Dean Elsner.
25  * Also, I want to change the definition of a symbol to (address,length)
26  * so I can put arbitrary binary in the names stored. [see hsh.c for that]
27  *
28  * This slime is common coupled inside the module. Com-coupling (and other
29  * vandalism) was done to speed running time. The interfaces at the
30  * module's edges are adequately clean.
31  *
32  * There is no way to (a) run a test script through this heap and (b)
33  * compare results with previous scripts, to see if we have broken any
34  * code. Use GNU (f)utilities to do this. A few commands assist test.
35  * The testing is awkward: it tries to be both batch & interactive.
36  * For now, interactive rules!
37  */
38 \f
39 /*
40  *  The idea is to implement a symbol table. A test jig is here.
41  *  Symbols are arbitrary strings; they can't contain '\0'.
42  *      [See hsh.c for a more general symbol flavour.]
43  *  Each symbol is associated with a char*, which can point to anything
44  *  you want, allowing an arbitrary property list for each symbol.
45  *
46  *  The basic operations are:
47  *
48  *    new                     creates symbol table, returns handle
49  *    find (symbol)           returns char*
50  *    insert (symbol,char*)   error if symbol already in table
51  *    delete (symbol)         returns char* if symbol was in table
52  *    apply                   so you can delete all symbols before die()
53  *    die                     destroy symbol table (free up memory)
54  *
55  *  Supplementary functions include:
56  *
57  *    say                     how big? what % full?
58  *    replace (symbol,newval) report previous value
59  *    jam (symbol,value)      assert symbol:=value
60  *
61  *  You, the caller, have control over errors: this just reports them.
62  *
63  *  This package requires malloc(), free().
64  *  Malloc(size) returns NULL or address of char[size].
65  *  Free(address) frees same.
66  */
67 \f
68 /*
69  *  The code and its structures are re-enterent.
70  *
71  *  Before you do anything else, you must call hash_new() which will
72  *  return the address of a hash-table-control-block.  You then use
73  *  this address as a handle of the symbol table by passing it to all
74  *  the other hash_...() functions.  The only approved way to recover
75  *  the memory used by the symbol table is to call hash_die() with the
76  *  handle of the symbol table.
77  *
78  *  Before you call hash_die() you normally delete anything pointed to
79  *  by individual symbols. After hash_die() you can't use that symbol
80  *  table again.
81  *
82  *  The char* you associate with a symbol may not be NULL (0) because
83  *  NULL is returned whenever a symbol is not in the table. Any other
84  *  value is OK, except DELETED, #defined below.
85  *
86  *  When you supply a symbol string for insertion, YOU MUST PRESERVE THE
87  *  STRING until that symbol is deleted from the table. The reason is that
88  *  only the address you supply, NOT the symbol string itself, is stored
89  *  in the symbol table.
90  *
91  *  You may delete and add symbols arbitrarily.
92  *  Any or all symbols may have the same 'value' (char *). In fact, these
93  *  routines don't do anything with your symbol values.
94  *
95  *  You have no right to know where the symbol:char* mapping is stored,
96  *  because it moves around in memory; also because we may change how it
97  *  works and we don't want to break your code do we? However the handle
98  *  (address of struct hash_control) is never changed in
99  *  the life of the symbol table.
100  *
101  *  What you CAN find out about a symbol table is:
102  *    how many slots are in the hash table?
103  *    how many slots are filled with symbols?
104  *    (total hashes,collisions) for (reads,writes) (*)
105  *  All of the above values vary in time.
106  *  (*) some of these numbers will not be meaningful if we change the
107  *  internals. */
108 \f
109 /*
110  *  I N T E R N A L
111  *
112  *  Hash table is an array of hash_entries; each entry is a pointer to a
113  *  a string and a user-supplied value 1 char* wide.
114  *
115  *  The array always has 2 ** n elements, n>0, n integer.
116  *  There is also a 'wall' entry after the array, which is always empty
117  *  and acts as a sentinel to stop running off the end of the array.
118  *  When the array gets too full, we create a new array twice as large
119  *  and re-hash the symbols into the new array, then forget the old array.
120  *  (Of course, we copy the values into the new array before we junk the
121  *  old array!)
122  *
123  */
124
125 #include <stdio.h>
126
127 #ifndef FALSE
128 #define FALSE   (0)
129 #define TRUE    (!FALSE)
130 #endif /* no FALSE yet */
131
132 #include <ctype.h>
133 #define min(a, b)       ((a) < (b) ? (a) : (b))
134
135 #include "as.h"
136
137 #define error   as_fatal
138
139 #define DELETED     ((PTR)1)    /* guarenteed invalid address */
140 #define START_POWER    (11)     /* power of two: size of new hash table */
141
142 /* TRUE if a symbol is in entry @ ptr.  */
143 #define islive(ptr) (ptr->hash_string && ptr->hash_string!=DELETED)
144
145 /* Number of slots in hash table.  The wall does not count here.
146    We expect this is always a power of 2.  */
147 #define STAT_SIZE      (0)
148 #define STAT_ACCESS    (1)      /* number of hash_ask()s */
149 #define STAT__READ     (0)      /* reading */
150 #define STAT__WRITE    (1)      /* writing */
151 /* Number of collisions (total).  This may exceed STAT_ACCESS if we
152    have lots of collisions/access.  */
153 #define STAT_COLLIDE   (3)
154 #define STAT_USED      (5)      /* slots used right now */
155 #define STATLENGTH     (6)      /* size of statistics block */
156 #if STATLENGTH != HASH_STATLENGTH
157 Panic! Please make #include "stat.h" agree with previous definitions!
158 #endif
159
160 /* #define SUSPECT to do runtime checks */
161 /* #define TEST to be a test jig for hash...() */
162
163 #ifdef TEST
164 /* TEST: use smaller hash table */
165 #undef  START_POWER
166 #define START_POWER (3)
167 #undef  START_SIZE
168 #define START_SIZE  (8)
169 #undef  START_FULL
170 #define START_FULL  (4)
171 #endif
172 \f
173 /*------------------ plan ---------------------------------- i = internal
174
175   struct hash_control * c;
176   struct hash_entry   * e;                                                    i
177   int                   b[z];     buffer for statistics
178   z         size of b
179   char                * s;        symbol string (address) [ key ]
180   char                * v;        value string (address)  [datum]
181   boolean               f;        TRUE if we found s in hash table            i
182   char                * t;        error string; 0 means OK
183   int                   a;        access type [0...n)                         i
184
185   c=hash_new       ()             create new hash_control
186
187   hash_die         (c)            destroy hash_control (and hash table)
188   table should be empty.
189   doesn't check if table is empty.
190   c has no meaning after this.
191
192   hash_say         (c,b,z)        report statistics of hash_control.
193   also report number of available statistics.
194
195   v=hash_delete    (c,s)          delete symbol, return old value if any.
196   ask()                       NULL means no old value.
197   f
198
199   v=hash_replace   (c,s,v)        replace old value of s with v.
200   ask()                       NULL means no old value: no table change.
201   f
202
203   t=hash_insert    (c,s,v)        insert (s,v) in c.
204   ask()                       return error string.
205   f                           it is an error to insert if s is already
206   in table.
207   if any error, c is unchanged.
208
209   t=hash_jam       (c,s,v)        assert that new value of s will be v.       i
210   ask()                       it may decide to GROW the table.            i
211   f                                                                       i
212   grow()                                                                  i
213   t=hash_grow      (c)            grow the hash table.                        i
214   jam()                       will invoke JAM.                            i
215
216   ?=hash_apply     (c,y)          apply y() to every symbol in c.
217   y                           evtries visited in 'unspecified' order.
218
219   v=hash_find      (c,s)          return value of s, or NULL if s not in c.
220   ask()
221   f
222
223   f,e=hash_ask()   (c,s,a)        return slot where s SHOULD live.            i
224   code()                      maintain collision stats in c.              i
225
226   .=hash_code      (c,s)          compute hash-code for s,                    i
227   from parameters of c.                       i
228
229   */
230 \f
231 /* Returned by hash_ask() to stop extra testing. hash_ask() wants to
232    return both a slot and a status. This is the status.  TRUE: found
233    symbol FALSE: absent: empty or deleted slot Also returned by
234    hash_jam().  TRUE: we replaced a value FALSE: we inserted a value.  */
235 static char hash_found;
236
237 static struct hash_entry *hash_ask PARAMS ((struct hash_control *,
238                                             const char *, int));
239 static int hash_code PARAMS ((struct hash_control *, const char *));
240 static const char *hash_grow PARAMS ((struct hash_control *));
241 \f
242 /* Create a new hash table.  Return NULL if failed; otherwise return handle
243    (address of struct hash).  */
244 struct hash_control *
245 hash_new ()
246 {
247   struct hash_control *retval;
248   struct hash_entry *room;      /* points to hash table */
249   struct hash_entry *wall;
250   struct hash_entry *entry;
251   int *ip;              /* scan stats block of struct hash_control */
252   int *nd;              /* limit of stats block */
253
254   room = (struct hash_entry *) xmalloc (sizeof (struct hash_entry)
255                                         /* +1 for the wall entry */
256                                         * ((1 << START_POWER) + 1));
257   retval = (struct hash_control *) xmalloc (sizeof (struct hash_control));
258
259   nd = retval->hash_stat + STATLENGTH;
260   for (ip = retval->hash_stat; ip < nd; ip++)
261     *ip = 0;
262
263   retval->hash_stat[STAT_SIZE] = 1 << START_POWER;
264   retval->hash_mask = (1 << START_POWER) - 1;
265   retval->hash_sizelog = START_POWER;
266   /* works for 1's compl ok */
267   retval->hash_where = room;
268   retval->hash_wall =
269     wall = room + (1 << START_POWER);
270   retval->hash_full = (1 << START_POWER) / 2;
271   for (entry = room; entry <= wall; entry++)
272     entry->hash_string = NULL;
273   return retval;
274 }
275
276 /*
277  *           h a s h _ d i e ( )
278  *
279  * Table should be empty, but this is not checked.
280  * To empty the table, try hash_apply()ing a symbol deleter.
281  * Return to free memory both the hash table and it's control
282  * block.
283  * 'handle' has no meaning after this function.
284  * No errors are recoverable.
285  */
286 void
287 hash_die (handle)
288      struct hash_control *handle;
289 {
290   free ((char *) handle->hash_where);
291   free ((char *) handle);
292 }
293 \f
294 /*
295  *           h a s h _ s a y ( )
296  *
297  * Return the size of the statistics table, and as many statistics as
298  * we can until either (a) we have run out of statistics or (b) caller
299  * has run out of buffer.
300  * NOTE: hash_say treats all statistics alike.
301  * These numbers may change with time, due to insertions, deletions
302  * and expansions of the table.
303  * The first "statistic" returned is the length of hash_stat[].
304  * Then contents of hash_stat[] are read out (in ascending order)
305  * until your buffer or hash_stat[] is exausted.
306  */
307 void
308 hash_say (handle, buffer, bufsiz)
309      struct hash_control *handle;
310      int buffer[ /*bufsiz*/ ];
311      int bufsiz;
312 {
313   int *nd;              /* limit of statistics block */
314   int *ip;              /* scan statistics */
315
316   ip = handle->hash_stat;
317   nd = ip + min (bufsiz - 1, STATLENGTH);
318   if (bufsiz > 0)               /* trust nothing! bufsiz<=0 is dangerous */
319     {
320       *buffer++ = STATLENGTH;
321       for (; ip < nd; ip++, buffer++)
322         {
323           *buffer = *ip;
324         }
325     }
326 }
327 \f
328 /*
329  *           h a s h _ d e l e t e ( )
330  *
331  * Try to delete a symbol from the table.
332  * If it was there, return its value (and adjust STAT_USED).
333  * Otherwise, return NULL.
334  * Anyway, the symbol is not present after this function.
335  *
336  */
337 PTR                             /* NULL if string not in table, else */
338 /* returns value of deleted symbol */
339 hash_delete (handle, string)
340      struct hash_control *handle;
341      const char *string;
342 {
343   PTR retval;
344   struct hash_entry *entry;
345
346   entry = hash_ask (handle, string, STAT__WRITE);
347   if (hash_found)
348     {
349       retval = entry->hash_value;
350       entry->hash_string = DELETED;
351       handle->hash_stat[STAT_USED] -= 1;
352 #ifdef SUSPECT
353       if (handle->hash_stat[STAT_USED] < 0)
354         {
355           error ("hash_delete");
356         }
357 #endif /* def SUSPECT */
358     }
359   else
360     {
361       retval = NULL;
362     }
363   return (retval);
364 }
365 \f
366 /*
367  *                   h a s h _ r e p l a c e ( )
368  *
369  * Try to replace the old value of a symbol with a new value.
370  * Normally return the old value.
371  * Return NULL and don't change the table if the symbol is not already
372  * in the table.
373  */
374 PTR
375 hash_replace (handle, string, value)
376      struct hash_control *handle;
377      const char *string;
378      PTR value;
379 {
380   struct hash_entry *entry;
381   char *retval;
382
383   entry = hash_ask (handle, string, STAT__WRITE);
384   if (hash_found)
385     {
386       retval = entry->hash_value;
387       entry->hash_value = value;
388     }
389   else
390     {
391       retval = NULL;
392     }
393   ;
394   return retval;
395 }
396 \f
397 /*
398  *                   h a s h _ i n s e r t ( )
399  *
400  * Insert a (symbol-string, value) into the hash table.
401  * Return an error string, 0 means OK.
402  * It is an 'error' to insert an existing symbol.
403  */
404
405 const char *                    /* return error string */
406 hash_insert (handle, string, value)
407      struct hash_control *handle;
408      const char *string;
409      PTR value;
410 {
411   struct hash_entry *entry;
412   const char *retval;
413
414   retval = 0;
415   if (handle->hash_stat[STAT_USED] > handle->hash_full)
416     {
417       retval = hash_grow (handle);
418     }
419   if (!retval)
420     {
421       entry = hash_ask (handle, string, STAT__WRITE);
422       if (hash_found)
423         {
424           retval = "exists";
425         }
426       else
427         {
428           entry->hash_value = value;
429           entry->hash_string = string;
430           handle->hash_stat[STAT_USED] += 1;
431         }
432     }
433   return retval;
434 }
435 \f
436 /*
437  *               h a s h _ j a m ( )
438  *
439  * Regardless of what was in the symbol table before, after hash_jam()
440  * the named symbol has the given value. The symbol is either inserted or
441  * (its value is) relpaced.
442  * An error message string is returned, 0 means OK.
443  *
444  * WARNING: this may decide to grow the hashed symbol table.
445  * To do this, we call hash_grow(), WHICH WILL recursively CALL US.
446  *
447  * We report status internally: hash_found is TRUE if we replaced, but
448  * false if we inserted.
449  */
450 const char *
451 hash_jam (handle, string, value)
452      struct hash_control *handle;
453      const char *string;
454      PTR value;
455 {
456   const char *retval;
457   struct hash_entry *entry;
458
459   retval = 0;
460   if (handle->hash_stat[STAT_USED] > handle->hash_full)
461     {
462       retval = hash_grow (handle);
463     }
464   if (!retval)
465     {
466       entry = hash_ask (handle, string, STAT__WRITE);
467       if (!hash_found)
468         {
469           entry->hash_string = string;
470           handle->hash_stat[STAT_USED] += 1;
471         }
472       entry->hash_value = value;
473     }
474   return retval;
475 }
476
477 /*
478  *               h a s h _ g r o w ( )
479  *
480  * Grow a new (bigger) hash table from the old one.
481  * We choose to double the hash table's size.
482  * Return a human-scrutible error string: 0 if OK.
483  * Warning! This uses hash_jam(), which had better not recurse
484  * back here! Hash_jam() conditionally calls us, but we ALWAYS
485  * call hash_jam()!
486  * Internal.
487  */
488 static const char *
489 hash_grow (handle)              /* make a hash table grow */
490      struct hash_control *handle;
491 {
492   struct hash_entry *newwall;
493   struct hash_entry *newwhere;
494   struct hash_entry *newtrack;
495   struct hash_entry *oldtrack;
496   struct hash_entry *oldwhere;
497   struct hash_entry *oldwall;
498   int temp;
499   int newsize;
500   const char *string;
501   const char *retval;
502 #ifdef SUSPECT
503   int oldused;
504 #endif
505
506   /*
507    * capture info about old hash table
508    */
509   oldwhere = handle->hash_where;
510   oldwall = handle->hash_wall;
511 #ifdef SUSPECT
512   oldused = handle->hash_stat[STAT_USED];
513 #endif
514   /*
515    * attempt to get enough room for a hash table twice as big
516    */
517   temp = handle->hash_stat[STAT_SIZE];
518   if ((newwhere = ((struct hash_entry *)
519                    xmalloc ((unsigned long) ((temp + temp + 1)
520                                              * sizeof (struct hash_entry)))))
521       != NULL)
522     /* +1 for wall slot */
523     {
524       retval = 0;               /* assume success until proven otherwise */
525       /*
526        * have enough room: now we do all the work.
527        * double the size of everything in handle,
528        * note: hash_mask frob works for 1's & for 2's complement machines
529        */
530       handle->hash_mask = handle->hash_mask + handle->hash_mask + 1;
531       handle->hash_stat[STAT_SIZE] <<= 1;
532       newsize = handle->hash_stat[STAT_SIZE];
533       handle->hash_where = newwhere;
534       handle->hash_full <<= 1;
535       handle->hash_sizelog += 1;
536       handle->hash_stat[STAT_USED] = 0;
537       handle->hash_wall =
538         newwall = newwhere + newsize;
539       /*
540        * set all those pesky new slots to vacant.
541        */
542       for (newtrack = newwhere; newtrack <= newwall; newtrack++)
543         {
544           newtrack->hash_string = NULL;
545         }
546       /*
547        * we will do a scan of the old table, the hard way, using the
548        * new control block to re-insert the data into new hash table.
549        */
550       handle->hash_stat[STAT_USED] = 0; /* inserts will bump it up to correct */
551       for (oldtrack = oldwhere; oldtrack < oldwall; oldtrack++)
552         if (((string = oldtrack->hash_string) != NULL) && string != DELETED)
553           if ((retval = hash_jam (handle, string, oldtrack->hash_value)))
554             break;
555
556 #ifdef SUSPECT
557       if (!retval && handle->hash_stat[STAT_USED] != oldused)
558         {
559           retval = "hash_used";
560         }
561 #endif
562       if (!retval)
563         {
564           /*
565            * we have a completely faked up control block.
566            * return the old hash table.
567            */
568           free ((char *) oldwhere);
569           /*
570            * Here with success. retval is already 0.
571            */
572         }
573     }
574   else
575     {
576       retval = "no room";
577     }
578   return retval;
579 }
580 \f
581 /*
582  *          h a s h _ a p p l y ( )
583  *
584  * Use this to scan each entry in symbol table.
585  * For each symbol, this calls (applys) a nominated function supplying the
586  * symbol's value (and the symbol's name).
587  * The idea is you use this to destroy whatever is associted with
588  * any values in the table BEFORE you destroy the table with hash_die.
589  * Of course, you can use it for other jobs; whenever you need to
590  * visit all extant symbols in the table.
591  *
592  * We choose to have a call-you-back idea for two reasons:
593  *  asthetic: it is a neater idea to use apply than an explicit loop
594  *  sensible: if we ever had to grow the symbol table (due to insertions)
595  *            then we would lose our place in the table when we re-hashed
596  *            symbols into the new table in a different order.
597  *
598  * The order symbols are visited depends entirely on the hashing function.
599  * Whenever you insert a (symbol, value) you risk expanding the table. If
600  * you do expand the table, then the hashing function WILL change, so you
601  * MIGHT get a different order of symbols visited. In other words, if you
602  * want the same order of visiting symbols as the last time you used
603  * hash_apply() then you better not have done any hash_insert()s or
604  * hash_jam()s since the last time you used hash_apply().
605  *
606  * In future we may use the value returned by your nominated function.
607  * One idea is to abort the scan if, after applying the function to a
608  * certain node, the function returns a certain code.
609  * To be safe, please make your functions of type char *. If you always
610  * return NULL, then the scan will complete, visiting every symbol in
611  * the table exactly once. ALL OTHER RETURNED VALUES have no meaning yet!
612  * Caveat Actor!
613  *
614  * The function you supply should be of the form:
615  *      char * myfunct(string,value)
616  *              char * string;        |* the symbol's name *|
617  *              char * value;         |* the symbol's value *|
618  *      {
619  *        |* ... *|
620  *        return(NULL);
621  *      }
622  *
623  * The returned value of hash_apply() is (char*)NULL. In future it may return
624  * other values. NULL means "completed scan OK". Other values have no meaning
625  * yet. (The function has no graceful failures.)
626  */
627 char *
628 hash_apply (handle, function)
629      struct hash_control *handle;
630      char *(*function) ();
631 {
632   struct hash_entry *entry;
633   struct hash_entry *wall;
634
635   wall = handle->hash_wall;
636   for (entry = handle->hash_where; entry < wall; entry++)
637     {
638       if (islive (entry))       /* silly code: tests entry->string twice! */
639         {
640           (*function) (entry->hash_string, entry->hash_value);
641         }
642     }
643   return (NULL);
644 }
645 \f
646 /*
647  *          h a s h _ f i n d ( )
648  *
649  * Given symbol string, find value (if any).
650  * Return found value or NULL.
651  */
652 PTR
653 hash_find (handle, string)
654      struct hash_control *handle;
655      const char *string;
656 {
657   struct hash_entry *entry;
658
659   entry = hash_ask (handle, string, STAT__READ);
660   if (hash_found)
661     return entry->hash_value;
662   else
663     return NULL;
664 }
665 \f
666 /*
667  *          h a s h _ a s k ( )
668  *
669  * Searches for given symbol string.
670  * Return the slot where it OUGHT to live. It may be there.
671  * Return hash_found: TRUE only if symbol is in that slot.
672  * Access argument is to help keep statistics in control block.
673  * Internal.
674  */
675 static struct hash_entry *      /* string slot, may be empty or deleted */
676 hash_ask (handle, string, access)
677      struct hash_control *handle;
678      const char *string;
679      int access;                /* access type */
680 {
681   const char *s;
682   struct hash_entry *slot;
683   int collision;        /* count collisions */
684
685   /* start looking here */
686   slot = handle->hash_where + hash_code (handle, string);
687
688   handle->hash_stat[STAT_ACCESS + access] += 1;
689   collision = 0;
690   hash_found = FALSE;
691   while (((s = slot->hash_string) != NULL) && s != DELETED)
692     {
693       if (string == s || !strcmp (string, s))
694         hash_found = TRUE;
695       if (hash_found)
696         break;
697       collision++;
698       slot++;
699     }
700   /*
701    * slot:                                                      return:
702    *       in use:     we found string                           slot
703    *       at empty:
704    *                   at wall:        we fell off: wrap round   ????
705    *                   in table:       dig here                  slot
706    *       at DELETED: dig here                                  slot
707    */
708   if (slot == handle->hash_wall)
709     {
710       slot = handle->hash_where;/* now look again */
711       while (((s = slot->hash_string) != NULL) && s != DELETED)
712         {
713           if (string == s || !strcmp (string, s))
714             hash_found = TRUE;
715           collision++;
716           slot++;
717         }
718       /*
719        * slot:                                                   return:
720        *       in use: we found it                                slot
721        *       empty:  wall:         ERROR IMPOSSIBLE             !!!!
722        *               in table:     dig here                     slot
723        *       DELETED:dig here                                   slot
724        */
725     }
726   handle->hash_stat[STAT_COLLIDE + access] += collision;
727   return (slot);                /* also return hash_found */
728 }
729 \f
730 /*
731  *           h a s h _ c o d e
732  *
733  * Does hashing of symbol string to hash number.
734  * Internal.
735  */
736 static int
737 hash_code (handle, string)
738      struct hash_control *handle;
739      const char *string;
740 {
741 #if 1 /* There seems to be some interesting property of this function
742          that prevents the bfd version below from being an adequate
743          substitute.  @@ Figure out what this property is!  */
744   long h;               /* hash code built here */
745   long c;               /* each character lands here */
746   int n;                /* Amount to shift h by */
747
748   n = (handle->hash_sizelog - 3);
749   h = 0;
750   while ((c = *string++) != 0)
751     {
752       h += c;
753       h = (h << 3) + (h >> n) + c;
754     }
755   return (h & handle->hash_mask);
756 #else
757   /* from bfd */
758   unsigned long h = 0;
759   unsigned int len = 0;
760   unsigned int c;
761
762   while ((c = *string++) != 0)
763     {
764       h += c + (c << 17);
765       h ^= h >> 2;
766       ++len;
767     }
768   h += len + (len << 17);
769   h ^= h >> 2;
770   return h & handle->hash_mask;
771 #endif
772 }
773 \f
774 /*
775  * Here is a test program to exercise above.
776  */
777 #ifdef TEST
778
779 #define TABLES (6)              /* number of hash tables to maintain */
780 /* (at once) in any testing */
781 #define STATBUFSIZE (12)        /* we can have 12 statistics */
782
783 int statbuf[STATBUFSIZE];       /* display statistics here */
784 char answer[100];               /* human farts here */
785 char *hashtable[TABLES];        /* we test many hash tables at once */
786 char *h;                        /* points to curent hash_control */
787 char **pp;
788 char *p;
789 char *name;
790 char *value;
791 int size;
792 int used;
793 char command;
794 int number;                     /* number 0:TABLES-1 of current hashed */
795 /* symbol table */
796
797 main ()
798 {
799   char (*applicatee ());
800   char *destroy ();
801   char *what ();
802   int *ip;
803
804   number = 0;
805   h = 0;
806   printf ("type h <RETURN> for help\n");
807   for (;;)
808     {
809       printf ("hash_test command: ");
810       gets (answer);
811       command = answer[0];
812       if (isupper (command))
813         command = tolower (command);    /* ecch! */
814       switch (command)
815         {
816         case '#':
817           printf ("old hash table #=%d.\n", number);
818           whattable ();
819           break;
820         case '?':
821           for (pp = hashtable; pp < hashtable + TABLES; pp++)
822             {
823               printf ("address of hash table #%d control block is %xx\n"
824                       ,pp - hashtable, *pp);
825             }
826           break;
827         case 'a':
828           hash_apply (h, applicatee);
829           break;
830         case 'd':
831           hash_apply (h, destroy);
832           hash_die (h);
833           break;
834         case 'f':
835           p = hash_find (h, name = what ("symbol"));
836           printf ("value of \"%s\" is \"%s\"\n", name, p ? p : "NOT-PRESENT");
837           break;
838         case 'h':
839           printf ("# show old, select new default hash table number\n");
840           printf ("? display all hashtable control block addresses\n");
841           printf ("a apply a simple display-er to each symbol in table\n");
842           printf ("d die: destroy hashtable\n");
843           printf ("f find value of nominated symbol\n");
844           printf ("h this help\n");
845           printf ("i insert value into symbol\n");
846           printf ("j jam value into symbol\n");
847           printf ("n new hashtable\n");
848           printf ("r replace a value with another\n");
849           printf ("s say what %% of table is used\n");
850           printf ("q exit this program\n");
851           printf ("x delete a symbol from table, report its value\n");
852           break;
853         case 'i':
854           p = hash_insert (h, name = what ("symbol"), value = what ("value"));
855           if (p)
856             {
857               printf ("symbol=\"%s\"  value=\"%s\"  error=%s\n", name, value,
858                       p);
859             }
860           break;
861         case 'j':
862           p = hash_jam (h, name = what ("symbol"), value = what ("value"));
863           if (p)
864             {
865               printf ("symbol=\"%s\"  value=\"%s\"  error=%s\n", name, value, p);
866             }
867           break;
868         case 'n':
869           h = hashtable[number] = (char *) hash_new ();
870           break;
871         case 'q':
872           exit (EXIT_SUCCESS);
873         case 'r':
874           p = hash_replace (h, name = what ("symbol"), value = what ("value"));
875           printf ("old value was \"%s\"\n", p ? p : "{}");
876           break;
877         case 's':
878           hash_say (h, statbuf, STATBUFSIZE);
879           for (ip = statbuf; ip < statbuf + STATBUFSIZE; ip++)
880             {
881               printf ("%d ", *ip);
882             }
883           printf ("\n");
884           break;
885         case 'x':
886           p = hash_delete (h, name = what ("symbol"));
887           printf ("old value was \"%s\"\n", p ? p : "{}");
888           break;
889         default:
890           printf ("I can't understand command \"%c\"\n", command);
891           break;
892         }
893     }
894 }
895
896 char *
897 what (description)
898      char *description;
899 {
900   char *retval;
901   char *malloc ();
902
903   printf ("   %s : ", description);
904   gets (answer);
905   /* will one day clean up answer here */
906   retval = malloc (strlen (answer) + 1);
907   if (!retval)
908     {
909       error ("room");
910     }
911   (void) strcpy (retval, answer);
912   return (retval);
913 }
914
915 char *
916 destroy (string, value)
917      char *string;
918      char *value;
919 {
920   free (string);
921   free (value);
922   return (NULL);
923 }
924
925
926 char *
927 applicatee (string, value)
928      char *string;
929      char *value;
930 {
931   printf ("%.20s-%.20s\n", string, value);
932   return (NULL);
933 }
934
935 whattable ()                    /* determine number: what hash table to use */
936      /* also determine h: points to hash_control */
937 {
938
939   for (;;)
940     {
941       printf ("   what hash table (%d:%d) ?  ", 0, TABLES - 1);
942       gets (answer);
943       sscanf (answer, "%d", &number);
944       if (number >= 0 && number < TABLES)
945         {
946           h = hashtable[number];
947           if (!h)
948             {
949               printf ("warning: current hash-table-#%d. has no hash-control\n", number);
950             }
951           return;
952         }
953       else
954         {
955           printf ("invalid hash table number: %d\n", number);
956         }
957     }
958 }
959
960
961
962 #endif /* #ifdef TEST */
963
964 /* end of hash.c */