Home | History | Annotate | Download | only in antlr
      1 /*
      2  * hash.c
      3  *
      4  * Manage hash tables.
      5  *
      6  * The following functions are visible:
      7  *
      8  *		char	*mystrdup(char *);		Make space and copy string
      9  *		Entry 	**newHashTable();		Create and return initialized hash table
     10  *		Entry	*hash_add(Entry **, char *, Entry *)
     11  *		Entry	*hash_get(Entry **, char *)
     12  *
     13  * SOFTWARE RIGHTS
     14  *
     15  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
     16  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
     17  * company may do whatever they wish with source code distributed with
     18  * PCCTS or the code generated by PCCTS, including the incorporation of
     19  * PCCTS, or its output, into commerical software.
     20  *
     21  * We encourage users to develop software with PCCTS.  However, we do ask
     22  * that credit is given to us for developing PCCTS.  By "credit",
     23  * we mean that if you incorporate our source code into one of your
     24  * programs (commercial product, research project, or otherwise) that you
     25  * acknowledge this fact somewhere in the documentation, research report,
     26  * etc...  If you like PCCTS and have developed a nice tool with the
     27  * output, please mention that you developed it using PCCTS.  In
     28  * addition, we ask that this header remain intact in our source code.
     29  * As long as these guidelines are kept, we expect to continue enhancing
     30  * this system and expect to make other tools available as they are
     31  * completed.
     32  *
     33  * ANTLR 1.33
     34  * Terence Parr
     35  * Parr Research Corporation
     36  * with Purdue University and AHPCRC, University of Minnesota
     37  * 1989-2001
     38  */
     39 
     40 #include <stdio.h>
     41 #include "pcctscfg.h"
     42 #include "hash.h"
     43 
     44 #ifdef __USE_PROTOS
     45 #include <stdlib.h>
     46 #else
     47 #ifdef VAXC
     48 #include <stdlib.h>
     49 #else
     50 #include <malloc.h>
     51 #endif
     52 #endif
     53 #include <string.h>
     54 
     55 #define StrSame		0
     56 
     57 #define fatal(err)															\
     58 			{fprintf(stderr, "%s(%d):", __FILE__, __LINE__);				\
     59 			fprintf(stderr, " %s\n", err); exit(PCCTS_EXIT_FAILURE);}
     60 #define require(expr, err) {if ( !(expr) ) fatal(err);}
     61 
     62 static unsigned size = HashTableSize;
     63 static char *strings = NULL;
     64 static char *strp;
     65 static unsigned strsize = StrTableSize;
     66 
     67 /* create the hash table and string table for terminals (string table only once) */
     68 Entry **
     69 #ifdef __USE_PROTOS
     70 newHashTable( void )
     71 #else
     72 newHashTable( )
     73 #endif
     74 {
     75 	Entry **table;
     76 
     77 	table = (Entry **) calloc(size, sizeof(Entry *));
     78 	require( table != NULL, "cannot allocate hash table");
     79 	if ( strings == NULL )
     80 	{
     81 		strings = (char *) calloc(strsize, sizeof(char));
     82 		require( strings != NULL, "cannot allocate string table");
     83 		strp = strings;
     84 	}
     85 	return table;
     86 }
     87 
     88 void
     89 #ifdef __USE_PROTOS
     90 killHashTable( Entry **table )
     91 #else
     92 killHashTable( table )
     93 Entry **table;
     94 #endif
     95 {
     96 	/* for now, just free table, forget entries */
     97 	free( (char *) table );     /* MR10 cast */
     98 }
     99 
    100 /* Given a table, add 'rec' with key 'key' (add to front of list). return ptr to entry */
    101 Entry *
    102 #ifdef __USE_PROTOS
    103 hash_add( Entry **table, char *key, Entry *rec )
    104 #else
    105 hash_add( table, key, rec )
    106 Entry **table;
    107 char *key;
    108 Entry *rec;
    109 #endif
    110 {
    111 	unsigned h=0;
    112 	char *p=key;
    113 	require(table!=NULL && key!=NULL && rec!=NULL, "add: invalid addition");
    114 
    115 	Hash(p,h,size);
    116 	rec->next = table[h];			/* Add to singly-linked list */
    117 	table[h] = rec;
    118 	return rec;
    119 }
    120 
    121 /* Return ptr to 1st entry found in table under key (return NULL if none found) */
    122 Entry *
    123 #ifdef __USE_PROTOS
    124 hash_get( Entry **table, char *key )
    125 #else
    126 hash_get( table, key )
    127 Entry **table;
    128 char *key;
    129 #endif
    130 {
    131 	unsigned h=0;
    132 	char *p=key;
    133 	Entry *q;
    134 /*	require(table!=NULL && key!=NULL, "get: invalid table and/or key");*/
    135 	if ( !(table!=NULL && key!=NULL) ) *((char *) 34) = 3;
    136 
    137 	Hash(p,h,size);
    138 	for (q = table[h]; q != NULL; q = q->next)
    139 	{
    140 		if ( strcmp(key, q->str) == StrSame ) return( q );
    141 	}
    142 	return( NULL );
    143 }
    144 
    145 #ifdef DEBUG_HASH
    146 void
    147 #ifdef __USE_PROTOS
    148 hashStat( Entry **table )
    149 #else
    150 hashStat( table )
    151 Entry **table;
    152 #endif
    153 {
    154 	static unsigned short count[20];
    155 	int i,n=0,low=0, hi=0;
    156 	Entry **p;
    157 	float avg=0.0;
    158 
    159 	for (i=0; i<20; i++) count[i] = 0;
    160 	for (p=table; p<&(table[size]); p++)
    161 	{
    162 		Entry *q = *p;
    163 		int len;
    164 
    165 		if ( q != NULL && low==0 ) low = p-table;
    166 		len = 0;
    167 		if ( q != NULL ) fprintf(stderr, "[%d]", p-table);
    168 		while ( q != NULL )
    169 		{
    170 			len++;
    171 			n++;
    172 			fprintf(stderr, " %s", q->str);
    173 			q = q->next;
    174 			if ( q == NULL ) fprintf(stderr, "\n");
    175 		}
    176 		count[len]++;
    177 		if ( *p != NULL ) hi = p-table;
    178 	}
    179 
    180 	fprintf(stderr, "Storing %d recs used %d hash positions out of %d\n",
    181 					n, size-count[0], size);
    182 	fprintf(stderr, "%f %% utilization\n",
    183 					((float)(size-count[0]))/((float)size));
    184 	for (i=0; i<20; i++)
    185 	{
    186 		if ( count[i] != 0 )
    187 		{
    188 			avg += (((float)(i*count[i]))/((float)n)) * i;
    189 			fprintf(stderr, "Bucket len %d == %d (%f %% of recs)\n",
    190 							i, count[i], ((float)(i*count[i]))/((float)n));
    191 		}
    192 	}
    193 	fprintf(stderr, "Avg bucket length %f\n", avg);
    194 	fprintf(stderr, "Range of hash function: %d..%d\n", low, hi);
    195 }
    196 #endif
    197 
    198 /* Add a string to the string table and return a pointer to it.
    199  * Bump the pointer into the string table to next avail position.
    200  */
    201 char *
    202 #ifdef __USE_PROTOS
    203 mystrdup( char *s )
    204 #else
    205 mystrdup( s )
    206 char *s;
    207 #endif
    208 {
    209 	char *start=strp;
    210 	require(s!=NULL, "mystrdup: NULL string");
    211 
    212 	while ( *s != '\0' )
    213 	{
    214 		require( strp <= &(strings[strsize-2]),
    215 				 "string table overflow\nIncrease StrTableSize in hash.h and recompile hash.c\n");
    216 		*strp++ = *s++;
    217 	}
    218 	*strp++ = '\0';
    219 
    220 	return( start );
    221 }
    222