gbdk-releases/sdcc/src/SDCChasht.c

569 lines
14 KiB
C
Raw Permalink Normal View History

2015-01-10 16:25:06 +01:00
/*-----------------------------------------------------------------
SDCChast.c - contains support routines for hashtables
2015-01-10 16:25:09 +01:00
2015-01-10 16:25:06 +01:00
Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
2015-01-10 16:25:09 +01:00
2015-01-10 16:25:06 +01:00
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
2015-01-10 16:25:09 +01:00
2015-01-10 16:25:06 +01:00
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
2015-01-10 16:25:09 +01:00
2015-01-10 16:25:06 +01:00
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
2015-01-10 16:25:09 +01:00
what you give them. Help stamp out software-hoarding!
2015-01-10 16:25:06 +01:00
-------------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <limits.h>
2015-01-10 16:25:07 +01:00
#include <assert.h>
#include "SDCCglobl.h"
2015-01-10 16:25:06 +01:00
#include "SDCChasht.h"
2015-01-10 16:25:09 +01:00
#include "newalloc.h"
2015-01-10 16:25:06 +01:00
#define DEFAULT_HTAB_SIZE 128
/*-----------------------------------------------------------------*/
/* newHashtItem - creates a new hashtable Item */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
static hashtItem *
_newHashtItem (int key, void *pkey, void *item)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
hashtItem *htip;
htip = Safe_alloc ( sizeof (hashtItem));
htip->key = key;
htip->pkey = pkey;
htip->item = item;
htip->next = NULL;
return htip;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* newHashTable - allocates a new hashtable of size */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
hTab *
newHashTable (int size)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
hTab *htab;
htab = Safe_alloc ( sizeof (hTab));
if (!(htab->table = Safe_alloc ((size + 1) * sizeof (hashtItem *))))
{
fprintf (stderr, "out of virtual memory %s %d\n",
__FILE__, (size + 1) * sizeof (hashtItem *));
exit (1);
}
htab->minKey = htab->size = size;
return htab;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
void
hTabAddItemLong (hTab ** htab, int key, void *pkey, void *item)
2015-01-10 16:25:07 +01:00
{
2015-01-10 16:25:09 +01:00
hashtItem *htip;
hashtItem *last;
if (!(*htab))
*htab = newHashTable (DEFAULT_HTAB_SIZE);
if (key > (*htab)->size)
{
int i;
(*htab)->table = Safe_realloc ((*htab)->table,
(key * 2 + 2) * sizeof (hashtItem *));
for (i = (*htab)->size + 1; i <= (key * 2 + 1); i++)
(*htab)->table[i] = NULL;
(*htab)->size = key * 2 + 1;
}
/* update the key */
if ((*htab)->maxKey < key)
(*htab)->maxKey = key;
if ((*htab)->minKey > key)
(*htab)->minKey = key;
/* create the item */
htip = _newHashtItem (key, pkey, item);
/* if there is a clash then goto end of chain */
if ((last = (*htab)->table[key]))
{
while (last->next)
last = last->next;
last->next = htip;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
else
/* else just add it */
(*htab)->table[key] = htip;
(*htab)->nItems++;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:07 +01:00
/*-----------------------------------------------------------------*/
/* hTabAddItem - adds an item to the hash table */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
hTabAddItem (hTab ** htab, int key, void *item)
{
hTabAddItemLong (htab, key, NULL, item);
2015-01-10 16:25:07 +01:00
}
2015-01-10 16:25:06 +01:00
/*-----------------------------------------------------------------*/
/* hTabDeleteItem - either delete an item */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
hTabDeleteItem (hTab ** htab, int key,
const void *item, DELETE_ACTION action,
int (*compareFunc) (const void *, const void *))
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
hashtItem *htip, **htipp;
if (!(*htab))
return;
/* first check if anything exists in the slot */
if (!(*htab)->table[key])
return;
/* if delete chain */
if (action == DELETE_CHAIN)
(*htab)->table[key] = NULL;
else
{
/* delete specific item */
/* if a compare function is given then use the compare */
/* function to find the item, else just compare the items */
htipp = &((*htab)->table[key]);
htip = (*htab)->table[key];
for (; htip; htip = htip->next)
{
if (compareFunc ? compareFunc (item, htip->item) :
(item == htip->item))
{
*htipp = htip->next;
break;
}
htipp = &(htip->next);
}
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
(*htab)->nItems--;
if (!(*htab)->nItems)
{
*htab = NULL;
2015-01-10 16:25:06 +01:00
}
}
/*-----------------------------------------------------------------*/
/* hTabDeleteAll - deletes all items in a hash table to reduce mem */
/* leaks written by */
/* "BESSIERE Jerome" <BESSIERE_Jerome@stna.dgac.fr> */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
hTabDeleteAll (hTab * p)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
if (p && p->table)
{
register int i;
register hashtItem *jc, *jn;
for (i = 0; i < p->size; i++)
{
if (!(jc = p->table[i]))
continue;
jn = jc->next;
while (jc)
{
Safe_free (jc);
if ((jc = jn))
jn = jc->next;
}
p->table[i] = NULL;
}
Safe_free (p->table);
2015-01-10 16:25:06 +01:00
}
}
/*-----------------------------------------------------------------*/
2015-01-10 16:25:07 +01:00
/* hTabClearAll - clear all entries in the table (does not free) */
2015-01-10 16:25:06 +01:00
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
hTabClearAll (hTab * htab)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
if (!htab || !htab->table)
{
printf ("null table\n");
return;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
memset (htab->table, 0, htab->size * sizeof (hashtItem *));
htab->minKey = htab->size;
htab->currKey = htab->nItems = htab->maxKey = 0;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
static const hashtItem *
_findItem (hTab * htab, int key, void *item, int (*compareFunc) (void *, void *))
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
hashtItem *htip;
for (htip = htab->table[key]; htip; htip = htip->next)
{
/* if a compare function is given use it */
if (compareFunc && compareFunc (item, htip->item))
break;
else if (item == htip->item)
break;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
return htip;
2015-01-10 16:25:07 +01:00
}
2015-01-10 16:25:09 +01:00
static const hashtItem *
_findByKey (hTab * htab, int key, const void *pkey, int (*compare) (const void *, const void *))
2015-01-10 16:25:07 +01:00
{
2015-01-10 16:25:09 +01:00
hashtItem *htip;
assert (compare);
if (!htab)
return NULL;
for (htip = htab->table[key]; htip; htip = htip->next)
{
/* if a compare function is given use it */
if (compare && compare (pkey, htip->pkey))
{
break;
}
else
{
if (pkey == htip->pkey)
{
break;
}
}
2015-01-10 16:25:07 +01:00
}
2015-01-10 16:25:09 +01:00
return htip;
2015-01-10 16:25:07 +01:00
}
2015-01-10 16:25:09 +01:00
void *
hTabFindByKey (hTab * h, int key, const void *pkey, int (*compare) (const void *, const void *))
2015-01-10 16:25:07 +01:00
{
2015-01-10 16:25:09 +01:00
const hashtItem *item;
2015-01-10 16:25:07 +01:00
2015-01-10 16:25:09 +01:00
if ((item = _findByKey (h, key, pkey, compare)))
return item->item;
return NULL;
2015-01-10 16:25:07 +01:00
}
2015-01-10 16:25:09 +01:00
int
hTabDeleteByKey (hTab ** h, int key, const void *pkey, int (*compare) (const void *, const void *))
2015-01-10 16:25:07 +01:00
{
2015-01-10 16:25:09 +01:00
hashtItem *htip, **htipp;
bool found = FALSE;
if (!(*h))
return 0;
/* first check if anything exists in the slot */
if (!(*h)->table[key])
return 0;
/* delete specific item */
/* if a compare function is given then use the compare */
/* function to find the item, else just compare the items */
htipp = &((*h)->table[key]);
htip = (*h)->table[key];
for (; htip; htip = htip->next)
{
if (
(compare && compare (pkey, htip->pkey)) ||
pkey == htip->pkey)
{
*htipp = htip->next;
found = TRUE;
break;
2015-01-10 16:25:07 +01:00
}
2015-01-10 16:25:09 +01:00
htipp = &(htip->next);
2015-01-10 16:25:07 +01:00
}
2015-01-10 16:25:09 +01:00
if (found == TRUE)
{
(*h)->nItems--;
if (!(*h)->nItems)
{
*h = NULL;
}
2015-01-10 16:25:07 +01:00
}
2015-01-10 16:25:09 +01:00
return 1;
2015-01-10 16:25:07 +01:00
}
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:07 +01:00
/*-----------------------------------------------------------------*/
/* hTabIsInTable - will determine if an Item is in the hasht */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
int
hTabIsInTable (hTab * htab, int key,
void *item, int (*compareFunc) (void *, void *))
2015-01-10 16:25:07 +01:00
{
2015-01-10 16:25:09 +01:00
if (_findItem (htab, key, item, compareFunc))
return 1;
return 0;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* hTabFirstItem - returns the first Item in the hTab */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void *
hTabFirstItem (hTab * htab, int *k)
{
int key;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (!htab)
return NULL;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
for (key = htab->minKey; key <= htab->maxKey; key++)
{
if (htab->table[key])
{
htab->currItem = htab->table[key];
htab->currKey = key;
*k = key;
return htab->table[key]->item;
2015-01-10 16:25:06 +01:00
}
}
2015-01-10 16:25:09 +01:00
return NULL;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* hTabNextItem - returns the next item in the hTab */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void *
hTabNextItem (hTab * htab, int *k)
{
int key;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (!htab)
return NULL;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* if this chain not ended then */
if (htab->currItem->next)
{
*k = htab->currItem->key;
return (htab->currItem = htab->currItem->next)->item;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
/* find the next chain which has something */
for (key = htab->currKey + 1; key <= htab->maxKey; key++)
{
if (htab->table[key])
{
htab->currItem = htab->table[key];
*k = htab->currKey = key;
return htab->table[key]->item;
2015-01-10 16:25:06 +01:00
}
}
2015-01-10 16:25:09 +01:00
return NULL;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* hTabFirstItemWK - returns the first Item in the hTab for a key */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void *
hTabFirstItemWK (hTab * htab, int wk)
{
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (!htab)
return NULL;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (wk < htab->minKey || wk > htab->maxKey)
return NULL;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
htab->currItem = htab->table[wk];
htab->currKey = wk;
return (htab->table[wk] ? htab->table[wk]->item : NULL);
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* hTabNextItem - returns the next item in the hTab for a key */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void *
hTabNextItemWK (hTab * htab)
{
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (!htab)
return NULL;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
/* if this chain not ended then */
if (htab->currItem->next)
{
return (htab->currItem = htab->currItem->next)->item;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
return NULL;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* hTabFromTable - hash Table from a hash table */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
hTab *
hTabFromTable (hTab * htab)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
hTab *nhtab;
hashtItem *htip;
int key;
if (!htab)
return NULL;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
nhtab = newHashTable (htab->size);
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
for (key = htab->minKey; key <= htab->maxKey; key++)
{
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
for (htip = htab->table[key]; htip; htip = htip->next)
hTabAddItem (&nhtab, htip->key, htip->item);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
return nhtab;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
/* isHtabsEqual - returns 1 if all items in htab1 is found in htab2 */
2015-01-10 16:25:06 +01:00
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
int
isHtabsEqual (hTab * htab1, hTab * htab2,
int (*compareFunc) (void *, void *))
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
void *item;
int key;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (htab1 == htab2)
2015-01-10 16:25:06 +01:00
return 1;
2015-01-10 16:25:09 +01:00
if (htab1 == NULL || htab2 == NULL)
return 0;
/* if they are different sizes then */
if (htab1->nItems != htab2->nItems)
return 0;
/* now do an item by item check */
for (item = hTabFirstItem (htab1, &key); item;
item = hTabNextItem (htab1, &key))
if (!hTabIsInTable (htab2, key, item, compareFunc))
return 0;
return 1;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/* hTabSearch - returns the first Item with the specified key */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
hashtItem *
hTabSearch (hTab * htab, int key)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
if (!htab)
return NULL;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if ((key < htab->minKey) || (key > htab->maxKey))
return NULL;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (!htab->table[key])
return NULL;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
return htab->table[key];
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
2015-01-10 16:25:07 +01:00
/* hTabItemWithKey - returns the first item with the given key */
2015-01-10 16:25:06 +01:00
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void *
hTabItemWithKey (hTab * htab, int key)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
hashtItem *htip;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
if (!(htip = hTabSearch (htab, key)))
return NULL;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
return htip->item;
2015-01-10 16:25:06 +01:00
}
/*-----------------------------------------------------------------*/
/*hTabAddItemIfNotP - adds an item with nothing found with key */
/*-----------------------------------------------------------------*/
2015-01-10 16:25:09 +01:00
void
hTabAddItemIfNotP (hTab ** htab, int key, void *item)
2015-01-10 16:25:06 +01:00
{
2015-01-10 16:25:09 +01:00
if (!*htab)
{
hTabAddItem (htab, key, item);
return;
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:09 +01:00
if (hTabItemWithKey (*htab, key))
return;
2015-01-10 16:25:06 +01:00
2015-01-10 16:25:09 +01:00
hTabAddItem (htab, key, item);
2015-01-10 16:25:06 +01:00
}
2015-01-10 16:25:07 +01:00
/** Simple implementation of a hash table which uses
string (key, value) pairs. If a key already exists in the
table, the newly added value will replace it.
This is used for the assembler token table. The replace existing
condition is used to implement inheritance.
*/
2015-01-10 16:25:09 +01:00
static int
_compare (const void *s1, const void *s2)
2015-01-10 16:25:07 +01:00
{
2015-01-10 16:25:09 +01:00
return !strcmp (s1, s2);
2015-01-10 16:25:07 +01:00
}
2015-01-10 16:25:09 +01:00
static int
_hash (const char *sz)
2015-01-10 16:25:07 +01:00
{
2015-01-10 16:25:09 +01:00
/* Dumb for now */
return *sz;
2015-01-10 16:25:07 +01:00
}
2015-01-10 16:25:09 +01:00
void
shash_add (hTab ** h, const char *szKey, const char *szValue)
2015-01-10 16:25:07 +01:00
{
2015-01-10 16:25:09 +01:00
int key = _hash (szKey);
/* First, delete any that currently exist */
hTabDeleteByKey (h, key, szKey, _compare);
/* Now add in ours */
hTabAddItemLong (h, key, Safe_strdup (szKey), Safe_strdup (szValue));
2015-01-10 16:25:07 +01:00
}
2015-01-10 16:25:09 +01:00
const char *
shash_find (hTab * h, const char *szKey)
2015-01-10 16:25:07 +01:00
{
2015-01-10 16:25:09 +01:00
int key = _hash (szKey);
return (char *) hTabFindByKey (h, key, szKey, _compare);
2015-01-10 16:25:07 +01:00
}