1 /*-----------------------------------------------------------------
2 SDCChast.c - contains support routines for hashtables
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program 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.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
29 #include "SDCCglobl.h"
30 #include "SDCChasht.h"
33 #define DEFAULT_HTAB_SIZE 128
35 /*-----------------------------------------------------------------*/
36 /* newHashtItem - creates a new hashtable Item */
37 /*-----------------------------------------------------------------*/
38 static hashtItem *_newHashtItem (int key, void *pkey, void *item)
42 htip = Safe_calloc(sizeof(hashtItem));
51 /*-----------------------------------------------------------------*/
52 /* newHashTable - allocates a new hashtable of size */
53 /*-----------------------------------------------------------------*/
54 hTab *newHashTable (int size)
58 htab = Safe_calloc(sizeof(hTab));
60 if (!(htab->table = calloc((size +1), sizeof(hashtItem *)))) {
61 fprintf(stderr,"out of virtual memory %s %d\n",
62 __FILE__,(size +1)* sizeof(hashtItem *));
65 htab->minKey = htab->size = size ;
70 void hTabAddItemLong(hTab **htab, int key, void *pkey, void *item)
76 *htab = newHashTable ( DEFAULT_HTAB_SIZE );
78 if (key > (*htab)->size ) {
80 (*htab)->table = Safe_realloc ((*htab)->table,
81 (key*2 + 2)*sizeof(hashtItem *));
82 for ( i = (*htab)->size +1; i <= (key*2 + 1); i++ )
83 (*htab)->table[i] = NULL ;
84 (*htab)->size = key*2 + 1;
88 if ((*htab)->maxKey < key )
89 (*htab)->maxKey = key ;
91 if ((*htab)->minKey > key )
92 (*htab)->minKey = key ;
95 htip = _newHashtItem(key, pkey, item);
97 /* if there is a clash then goto end of chain */
98 if ((last = (*htab)->table[key])) {
103 /* else just add it */
104 (*htab)->table[key] = htip ;
108 /*-----------------------------------------------------------------*/
109 /* hTabAddItem - adds an item to the hash table */
110 /*-----------------------------------------------------------------*/
111 void hTabAddItem (hTab **htab, int key, void *item )
113 hTabAddItemLong(htab, key, NULL, item);
116 /*-----------------------------------------------------------------*/
117 /* hTabDeleteItem - either delete an item */
118 /*-----------------------------------------------------------------*/
119 void hTabDeleteItem (hTab **htab, int key ,
120 const void *item, DELETE_ACTION action,
121 int (*compareFunc)(const void *, const void *))
123 hashtItem *htip, **htipp ;
128 /* first check if anything exists in the slot */
129 if (! (*htab)->table[key] )
132 /* if delete chain */
133 if ( action == DELETE_CHAIN )
134 (*htab)->table[key] = NULL ;
137 /* delete specific item */
138 /* if a compare function is given then use the compare */
139 /* function to find the item, else just compare the items */
141 htipp = &((*htab)->table[key]);
142 htip = (*htab)->table[key];
143 for (; htip; htip = htip->next) {
145 if (compareFunc ? compareFunc(item,htip->item) :
146 (item == htip->item) ) {
158 if (!(*htab)->nItems) {
163 /*-----------------------------------------------------------------*/
164 /* hTabDeleteAll - deletes all items in a hash table to reduce mem */
165 /* leaks written by */
166 /* "BESSIERE Jerome" <BESSIERE_Jerome@stna.dgac.fr> */
167 /*-----------------------------------------------------------------*/
168 void hTabDeleteAll(hTab * p)
172 register hashtItem *jc,*jn;
173 for (i=0;i<p->size;i++) {
175 if (!(jc = p->table[i])) continue;
179 if((jc=jn)) jn = jc->next;
187 /*-----------------------------------------------------------------*/
188 /* hTabClearAll - clear all entries in the table (does not free) */
189 /*-----------------------------------------------------------------*/
190 void hTabClearAll (hTab *htab)
193 if (!htab || !htab->table) {
194 printf("null table\n");
197 memset(htab->table, 0, htab->size*sizeof(hashtItem *));
199 htab->minKey = htab->size;
200 htab->currKey = htab->nItems = htab->maxKey = 0;
203 static const hashtItem *_findItem(hTab *htab, int key, void *item, int (*compareFunc)(void *, void *))
207 for (htip = htab->table[key] ; htip ; htip = htip->next ) {
208 /* if a compare function is given use it */
209 if (compareFunc && compareFunc(item,htip->item))
212 if (item == htip->item)
218 static const hashtItem *_findByKey(hTab *htab, int key, const void *pkey, int (*compare)(const void *, const void *))
227 for (htip = htab->table[key] ; htip ; htip = htip->next) {
228 /* if a compare function is given use it */
229 if (compare && compare(pkey, htip->pkey)) {
233 if (pkey == htip->pkey) {
241 void *hTabFindByKey(hTab *h, int key, const void *pkey, int (*compare)(const void *, const void *))
243 const hashtItem *item;
245 if ((item = _findByKey(h, key, pkey, compare)))
250 int hTabDeleteByKey(hTab **h, int key, const void *pkey, int (*compare)(const void *, const void *))
252 hashtItem *htip, **htipp ;
257 /* first check if anything exists in the slot */
258 if (! (*h)->table[key] )
261 /* delete specific item */
262 /* if a compare function is given then use the compare */
263 /* function to find the item, else just compare the items */
265 htipp = &((*h)->table[key]);
266 htip = (*h)->table[key];
267 for (; htip; htip = htip->next) {
269 (compare && compare(pkey, htip->pkey)) ||
270 pkey == htip->pkey) {
284 /*-----------------------------------------------------------------*/
285 /* hTabIsInTable - will determine if an Item is in the hasht */
286 /*-----------------------------------------------------------------*/
287 int hTabIsInTable (hTab *htab, int key,
288 void *item , int (*compareFunc)(void *,void *))
290 if (_findItem(htab, key, item, compareFunc))
295 /*-----------------------------------------------------------------*/
296 /* hTabFirstItem - returns the first Item in the hTab */
297 /*-----------------------------------------------------------------*/
298 void *hTabFirstItem (hTab *htab, int *k)
305 for ( key = htab->minKey ; key <= htab->maxKey ; key++ ) {
306 if (htab->table[key]) {
307 htab->currItem = htab->table[key];
308 htab->currKey = key ;
310 return htab->table[key]->item;
316 /*-----------------------------------------------------------------*/
317 /* hTabNextItem - returns the next item in the hTab */
318 /*-----------------------------------------------------------------*/
319 void *hTabNextItem (hTab *htab, int *k)
326 /* if this chain not ended then */
327 if (htab->currItem->next) {
328 *k = htab->currItem->key ;
329 return (htab->currItem = htab->currItem->next)->item ;
332 /* find the next chain which has something */
333 for ( key = htab->currKey + 1; key <= htab->maxKey ; key++ ) {
334 if (htab->table[key]) {
335 htab->currItem = htab->table[key];
336 *k = htab->currKey = key ;
337 return htab->table[key]->item;
344 /*-----------------------------------------------------------------*/
345 /* hTabFirstItemWK - returns the first Item in the hTab for a key */
346 /*-----------------------------------------------------------------*/
347 void *hTabFirstItemWK (hTab *htab, int wk)
353 if (wk < htab->minKey || wk > htab->maxKey )
356 htab->currItem = htab->table[wk] ;
359 return (htab->table[wk] ? htab->table[wk]->item : NULL);
362 /*-----------------------------------------------------------------*/
363 /* hTabNextItem - returns the next item in the hTab for a key */
364 /*-----------------------------------------------------------------*/
365 void *hTabNextItemWK (hTab *htab )
371 /* if this chain not ended then */
372 if (htab->currItem->next) {
373 return (htab->currItem = htab->currItem->next)->item ;
379 /*-----------------------------------------------------------------*/
380 /* hTabFromTable - hash Table from a hash table */
381 /*-----------------------------------------------------------------*/
382 hTab *hTabFromTable (hTab *htab)
391 nhtab = newHashTable(htab->size);
393 for (key = htab->minKey; key <= htab->maxKey ; key++ ) {
395 for (htip = htab->table[key] ; htip ; htip = htip->next)
396 hTabAddItem (&nhtab, htip->key, htip->item);
402 /*-----------------------------------------------------------------*/
403 /* isHtabsEqual - returns 1 if all items in htab1 is found in htab2*/
404 /*-----------------------------------------------------------------*/
405 int isHtabsEqual (hTab *htab1, hTab *htab2,
406 int (*compareFunc)(void *,void *))
411 if ( htab1 == htab2 )
414 if (htab1 == NULL || htab2 == NULL )
417 /* if they are different sizes then */
418 if ( htab1->nItems != htab2->nItems)
421 /* now do an item by item check */
422 for ( item = hTabFirstItem (htab1,&key) ;item;
423 item = hTabNextItem (htab1,&key))
424 if (!hTabIsInTable (htab2, key, item, compareFunc))
431 /*-----------------------------------------------------------------*/
432 /* hTabSearch - returns the first Item with the specified key */
433 /*-----------------------------------------------------------------*/
434 hashtItem *hTabSearch (hTab *htab, int key )
439 if ((key < htab->minKey)||(key>htab->maxKey))
442 if (!htab->table[key])
445 return htab->table[key] ;
448 /*-----------------------------------------------------------------*/
449 /* hTabItemWithKey - returns the first item with the given key */
450 /*-----------------------------------------------------------------*/
451 void *hTabItemWithKey (hTab *htab, int key )
455 if (!(htip = hTabSearch(htab,key)))
461 /*-----------------------------------------------------------------*/
462 /*hTabAddItemIfNotP - adds an item with nothing found with key */
463 /*-----------------------------------------------------------------*/
464 void hTabAddItemIfNotP (hTab **htab, int key, void *item)
467 hTabAddItem (htab,key,item);
471 if (hTabItemWithKey(*htab,key))
474 hTabAddItem(htab,key,item);
477 /** Simple implementation of a hash table which uses
478 string (key, value) pairs. If a key already exists in the
479 table, the newly added value will replace it.
480 This is used for the assembler token table. The replace existing
481 condition is used to implement inheritance.
483 static int _compare(const void *s1, const void *s2)
485 return !strcmp(s1, s2);
488 static int _hash(const char *sz)
494 void shash_add(hTab **h, const char *szKey, const char *szValue)
496 int key = _hash(szKey);
497 /* First, delete any that currently exist */
498 hTabDeleteByKey(h, key, szKey, _compare);
499 /* Now add in ours */
500 hTabAddItemLong(h, key, gc_strdup(szKey), gc_strdup(szValue));
503 const char *shash_find(hTab *h, const char *szKey)
505 int key = _hash(szKey);
506 return (char *)hTabFindByKey(h, key, szKey, _compare);