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"
32 #define DEFAULT_HTAB_SIZE 128
34 /*-----------------------------------------------------------------*/
35 /* newHashtItem - creates a new hashtable Item */
36 /*-----------------------------------------------------------------*/
37 static hashtItem *_newHashtItem (int key, void *pkey, void *item)
41 ALLOC(htip,sizeof(hashtItem));
50 /*-----------------------------------------------------------------*/
51 /* newHashTable - allocates a new hashtable of size */
52 /*-----------------------------------------------------------------*/
53 hTab *newHashTable (int size)
57 ALLOC(htab,sizeof(hTab));
59 if (!(htab->table = GC_malloc((size +1)* sizeof(hashtItem *)))) {
60 fprintf(stderr,"out of virtual memory %s %d\n",
61 __FILE__,(size +1)* sizeof(hashtItem *));
64 htab->minKey = htab->size = size ;
69 void hTabAddItemLong(hTab **htab, int key, void *pkey, void *item)
75 *htab = newHashTable ( DEFAULT_HTAB_SIZE );
77 if (key > (*htab)->size ) {
79 (*htab)->table = GC_realloc ((*htab)->table,
80 (key*2 + 2)*sizeof(hashtItem *));
81 for ( i = (*htab)->size +1; i <= (key*2 + 1); i++ )
82 (*htab)->table[i] = NULL ;
83 (*htab)->size = key*2 + 1;
87 if ((*htab)->maxKey < key )
88 (*htab)->maxKey = key ;
90 if ((*htab)->minKey > key )
91 (*htab)->minKey = key ;
94 htip = _newHashtItem(key, pkey, item);
96 /* if there is a clash then goto end of chain */
97 if ((last = (*htab)->table[key])) {
102 /* else just add it */
103 (*htab)->table[key] = htip ;
107 /*-----------------------------------------------------------------*/
108 /* hTabAddItem - adds an item to the hash table */
109 /*-----------------------------------------------------------------*/
110 void hTabAddItem (hTab **htab, int key, void *item )
112 hTabAddItemLong(htab, key, NULL, item);
115 /*-----------------------------------------------------------------*/
116 /* hTabDeleteItem - either delete an item */
117 /*-----------------------------------------------------------------*/
118 void hTabDeleteItem (hTab **htab, int key ,
119 const void *item, DELETE_ACTION action,
120 int (*compareFunc)(const void *, const void *))
122 hashtItem *htip, **htipp ;
127 /* first check if anything exists in the slot */
128 if (! (*htab)->table[key] )
131 /* if delete chain */
132 if ( action == DELETE_CHAIN )
133 (*htab)->table[key] = NULL ;
136 /* delete specific item */
137 /* if a compare function is given then use the compare */
138 /* function to find the item, else just compare the items */
140 htipp = &((*htab)->table[key]);
141 htip = (*htab)->table[key];
142 for (; htip; htip = htip->next) {
144 if (compareFunc ? compareFunc(item,htip->item) :
145 (item == htip->item) ) {
157 if (!(*htab)->nItems) {
162 /*-----------------------------------------------------------------*/
163 /* hTabDeleteAll - deletes all items in a hash table to reduce mem */
164 /* leaks written by */
165 /* "BESSIERE Jerome" <BESSIERE_Jerome@stna.dgac.fr> */
166 /*-----------------------------------------------------------------*/
167 void hTabDeleteAll(hTab * p)
171 register hashtItem *jc,*jn;
172 for (i=0;i<p->size;i++) {
174 if (!(jc = p->table[i])) continue;
178 if((jc=jn)) jn = jc->next;
186 /*-----------------------------------------------------------------*/
187 /* hTabClearAll - clear all entries in the table (does not free) */
188 /*-----------------------------------------------------------------*/
189 void hTabClearAll (hTab *htab)
192 if (!htab || !htab->table) {
193 printf("null table\n");
196 memset(htab->table, 0, htab->size*sizeof(hashtItem *));
198 htab->minKey = htab->size;
199 htab->currKey = htab->nItems = htab->maxKey = 0;
202 static const hashtItem *_findItem(hTab *htab, int key, void *item, int (*compareFunc)(void *, void *))
206 for (htip = htab->table[key] ; htip ; htip = htip->next ) {
207 /* if a compare function is given use it */
208 if (compareFunc && compareFunc(item,htip->item))
211 if (item == htip->item)
217 static const hashtItem *_findByKey(hTab *htab, int key, const void *pkey, int (*compare)(const void *, const void *))
226 for (htip = htab->table[key] ; htip ; htip = htip->next ) {
227 /* if a compare function is given use it */
228 if (compare && compare(pkey, htip->pkey))
231 if (pkey == htip->pkey)
237 void *hTabFindByKey(hTab *h, int key, const void *pkey, int (*compare)(const void *, const void *))
239 const hashtItem *item;
241 if ((item = _findByKey(h, key, pkey, compare)))
246 int hTabDeleteByKey(hTab **h, int key, const void *pkey, int (*compare)(const void *, const void *))
248 hashtItem *htip, **htipp ;
253 /* first check if anything exists in the slot */
254 if (! (*h)->table[key] )
257 /* delete specific item */
258 /* if a compare function is given then use the compare */
259 /* function to find the item, else just compare the items */
261 htipp = &((*h)->table[key]);
262 htip = (*h)->table[key];
263 for (; htip; htip = htip->next) {
265 (compare && compare(pkey, htip->pkey)) ||
266 pkey == htip->pkey) {
280 /*-----------------------------------------------------------------*/
281 /* hTabIsInTable - will determine if an Item is in the hasht */
282 /*-----------------------------------------------------------------*/
283 int hTabIsInTable (hTab *htab, int key,
284 void *item , int (*compareFunc)(void *,void *))
286 if (_findItem(htab, key, item, compareFunc))
291 /*-----------------------------------------------------------------*/
292 /* hTabFirstItem - returns the first Item in the hTab */
293 /*-----------------------------------------------------------------*/
294 void *hTabFirstItem (hTab *htab, int *k)
301 for ( key = htab->minKey ; key <= htab->maxKey ; key++ ) {
302 if (htab->table[key]) {
303 htab->currItem = htab->table[key];
304 htab->currKey = key ;
306 return htab->table[key]->item;
312 /*-----------------------------------------------------------------*/
313 /* hTabNextItem - returns the next item in the hTab */
314 /*-----------------------------------------------------------------*/
315 void *hTabNextItem (hTab *htab, int *k)
322 /* if this chain not ended then */
323 if (htab->currItem->next) {
324 *k = htab->currItem->key ;
325 return (htab->currItem = htab->currItem->next)->item ;
328 /* find the next chain which has something */
329 for ( key = htab->currKey + 1; key <= htab->maxKey ; key++ ) {
330 if (htab->table[key]) {
331 htab->currItem = htab->table[key];
332 *k = htab->currKey = key ;
333 return htab->table[key]->item;
340 /*-----------------------------------------------------------------*/
341 /* hTabFirstItemWK - returns the first Item in the hTab for a key */
342 /*-----------------------------------------------------------------*/
343 void *hTabFirstItemWK (hTab *htab, int wk)
349 if (wk < htab->minKey || wk > htab->maxKey )
352 htab->currItem = htab->table[wk] ;
355 return (htab->table[wk] ? htab->table[wk]->item : NULL);
358 /*-----------------------------------------------------------------*/
359 /* hTabNextItem - returns the next item in the hTab for a key */
360 /*-----------------------------------------------------------------*/
361 void *hTabNextItemWK (hTab *htab )
367 /* if this chain not ended then */
368 if (htab->currItem->next) {
369 return (htab->currItem = htab->currItem->next)->item ;
375 /*-----------------------------------------------------------------*/
376 /* hTabFromTable - hash Table from a hash table */
377 /*-----------------------------------------------------------------*/
378 hTab *hTabFromTable (hTab *htab)
387 nhtab = newHashTable(htab->size);
389 for (key = htab->minKey; key <= htab->maxKey ; key++ ) {
391 for (htip = htab->table[key] ; htip ; htip = htip->next)
392 hTabAddItem (&nhtab, htip->key, htip->item);
398 /*-----------------------------------------------------------------*/
399 /* isHtabsEqual - returns 1 if all items in htab1 is found in htab2*/
400 /*-----------------------------------------------------------------*/
401 int isHtabsEqual (hTab *htab1, hTab *htab2,
402 int (*compareFunc)(void *,void *))
407 if ( htab1 == htab2 )
410 if (htab1 == NULL || htab2 == NULL )
413 /* if they are different sizes then */
414 if ( htab1->nItems != htab2->nItems)
417 /* now do an item by item check */
418 for ( item = hTabFirstItem (htab1,&key) ;item;
419 item = hTabNextItem (htab1,&key))
420 if (!hTabIsInTable (htab2, key, item, compareFunc))
427 /*-----------------------------------------------------------------*/
428 /* hTabSearch - returns the first Item with the specified key */
429 /*-----------------------------------------------------------------*/
430 hashtItem *hTabSearch (hTab *htab, int key )
435 if ((key < htab->minKey)||(key>htab->maxKey))
438 if (!htab->table[key])
441 return htab->table[key] ;
444 /*-----------------------------------------------------------------*/
445 /* hTabItemWithKey - returns the first item with the given key */
446 /*-----------------------------------------------------------------*/
447 void *hTabItemWithKey (hTab *htab, int key )
451 if (!(htip = hTabSearch(htab,key)))
457 /*-----------------------------------------------------------------*/
458 /*hTabAddItemIfNotP - adds an item with nothing found with key */
459 /*-----------------------------------------------------------------*/
460 void hTabAddItemIfNotP (hTab **htab, int key, void *item)
463 hTabAddItem (htab,key,item);
467 if (hTabItemWithKey(*htab,key))
470 hTabAddItem(htab,key,item);
473 /** Simple implementation of a hash table which uses
474 string (key, value) pairs. If a key already exists in the
475 table, the newly added value will replace it.
476 This is used for the assembler token table. The replace existing
477 condition is used to implement inheritance.
479 static int _compare(const void *s1, const void *s2)
481 return !strcmp(s1, s2);
484 static int _hash(const char *sz)
490 void shash_add(hTab **h, const char *szKey, const char *szValue)
492 int key = _hash(szKey);
493 /* First, delete any that currently exist */
494 hTabDeleteByKey(h, key, szKey, _compare);
495 /* Now add in ours */
496 hTabAddItemLong(h, key, gc_strdup(szKey), gc_strdup(szValue));
499 const char *shash_find(hTab *h, const char *szKey)
501 int key = _hash(szKey);
502 return (char *)hTabFindByKey(h, key, szKey, _compare);