sym.c
上传用户:itx_2006
上传日期:2007-01-06
资源大小:493k
文件大小:9k
源码类别:

编译器/解释器

开发平台:

Others

  1. /*
  2.  * Simple symbol table manager using coalesced chaining to resolve collisions
  3.  *
  4.  * Doubly-linked lists are used for fast removal of entries.
  5.  *
  6.  * 'sym.h' must have a definition for typedef "Sym".  Sym must include at
  7.  * minimum the following fields:
  8.  *
  9.  * ...
  10.  * char *symbol;
  11.  * struct ... *next, *prev, **head, *scope;
  12.  * unsigned int hash;
  13.  * ...
  14.  *
  15.  * 'template.h' can be used as a template to create a 'sym.h'.
  16.  *
  17.  * 'head' is &(table[hash(itself)]).
  18.  * The hash table is not resizable at run-time.
  19.  * The scope field is used to link all symbols of a current scope together.
  20.  * Scope() sets the current scope (linked list) to add symbols to.
  21.  * Any number of scopes can be handled.  The user passes the address of
  22.  * a pointer to a symbol table
  23.  * entry (INITIALIZED TO NULL first time).
  24.  *
  25.  * Available Functions:
  26.  *
  27.  * zzs_init(s1,s2) -- Create hash table with size s1, string table size s2.
  28.  * zzs_done() -- Free hash and string table created with zzs_init().
  29.  * zzs_add(key,rec)-- Add 'rec' with key 'key' to the symbol table.
  30.  * zzs_newadd(key) -- create entry; add using 'key' to the symbol table.
  31.  * zzs_get(key) -- Return pointer to last record entered under 'key'
  32.  * Else return NULL
  33.  * zzs_del(p) -- Unlink the entry associated with p.  This does
  34.  * NOT free 'p' and DOES NOT remove it from a scope
  35.  * list.  If it was a part of your intermediate code
  36.  * tree or another structure.  It will still be there.
  37.  *    It is only removed from further consideration
  38.  * by the symbol table.
  39.  * zzs_keydel(s) -- Unlink the entry associated with key s.
  40.  * Calls zzs_del(p) to unlink.
  41.  * zzs_scope(sc) -- Specifies that everything added to the symbol
  42.  *     table with zzs_add() is added to the list (scope)
  43.  * 'sc'.  'sc' is of 'Sym **sc' type and must be
  44.  * initialized to NULL before trying to add anything
  45.  * to it (passing it to zzs_scope()).  Scopes can be
  46.  *     switched at any time and merely links a set of
  47.  * symbol table entries.  If a NULL pointer is
  48.  * passed, the current scope is returned.
  49.  * zzs_rmscope(sc) -- Remove (zzs_del()) all elements of scope 'sc'
  50.  * from the symbol table.  The entries are NOT
  51.  * free()'d.  A pointer to the first
  52.  *     element in the "scope" is returned.  The user
  53.  *     can then manipulate the list as he/she chooses
  54.  *     (such as freeing them all). NOTE that this
  55.  *     function sets your scope pointer to NULL,
  56.  *     but returns a pointer to the list for you to use.
  57.  * zzs_stat() -- Print out the symbol table and some relevant stats.
  58.  * zzs_new(key) -- Create a new record with calloc() of type Sym.
  59.  *     Add 'key' to the string table and make the new
  60.  *     records 'symbol' pointer point to it.
  61.  * zzs_strdup(s) -- Add s to the string table and return a pointer
  62.  *     to it.  Very fast allocation routine
  63.  * and does not require strlen() nor calloc().
  64.  *
  65.  * Example:
  66.  *
  67.  * #include <stdio.h>
  68.  * #include "sym.h"
  69.  *
  70.  * main()
  71.  * {
  72.  *     Sym *scope1=NULL, *scope2=NULL, *a, *p;
  73.  *
  74.  *     zzs_init(101, 100);
  75.  *
  76.  *     a = zzs_new("Apple"); zzs_add(a->symbol, a); -- No scope
  77.  *     zzs_scope( &scope1 ); -- enter scope 1
  78.  *     a = zzs_new("Plum"); zzs_add(a->symbol, a);
  79.  *     zzs_scope( &scope2 ); -- enter scope 2
  80.  *     a = zzs_new("Truck"); zzs_add(a->symbol, a);
  81.  *
  82.  *     p = zzs_get("Plum");
  83.  *     if ( p == NULL ) fprintf(stderr, "Hmmm...Can't find 'Plum'n");
  84.  *
  85.  *     p = zzs_rmscope(&scope1)
  86.  *     for (; p!=NULL; p=p->scope) {printf("Scope1:  %sn", p->symbol);}
  87.  *     p = zzs_rmscope(&scope2)
  88.  *     for (; p!=NULL; p=p->scope) {printf("Scope2:  %sn", p->symbol);}
  89.  * }
  90.  *
  91.  * Terence Parr
  92.  * Purdue University
  93.  * February 1990
  94.  *
  95.  * CHANGES
  96.  *
  97.  * Terence Parr
  98.  * May 1991
  99.  * Renamed functions to be consistent with ANTLR
  100.  * Made HASH macro
  101.  * Added zzs_keydel()
  102.  * Added zzs_newadd()
  103.  * Fixed up zzs_stat()
  104.  *
  105.  * July 1991
  106.  * Made symbol table entry save its hash code for fast comparison
  107.  * during searching etc...
  108.  */
  109. #include <stdio.h>
  110. #if __STDC__ == 1
  111. #include <string.h>
  112. #include <stdlib.h>
  113. #else
  114. #include "malloc.h"
  115. #endif
  116. #ifdef MEMCHK
  117. #include "trax.h"
  118. #endif
  119. #include "sym.h"
  120. #define StrSame 0
  121. static Sym **CurScope = NULL;
  122. static unsigned size = 0;
  123. static Sym **table=NULL;
  124. static char *strings;
  125. static char *strp;
  126. static int strsize = 0;
  127. void
  128. zzs_init(sz, strs)
  129. int sz, strs;
  130. {
  131. if ( sz <= 0 || strs <= 0 ) return;
  132. table = (Sym **) calloc(sz, sizeof(Sym *));
  133. if ( table == NULL )
  134. {
  135. fprintf(stderr, "Cannot allocate table of size %dn", sz);
  136. exit(1);
  137. }
  138. strings = (char *) calloc(strs, sizeof(char));
  139. if ( strings == NULL )
  140. {
  141. fprintf(stderr, "Cannot allocate string table of size %dn", strs);
  142. exit(1);
  143. }
  144. size = sz;
  145. strsize = strs;
  146. strp = strings;
  147. }
  148. void
  149. zzs_done()
  150. {
  151. if ( table != NULL ) free( table );
  152. if ( strings != NULL ) free( strings );
  153. }
  154. void
  155. zzs_add(key, rec)
  156. char *key;
  157. register Sym *rec;
  158. {
  159. register unsigned int h=0;
  160. register char *p=key;
  161. extern Sym *Globals;
  162. HASH(p, h);
  163. rec->hash = h; /* save hash code for fast comp later */
  164. h %= size;
  165. if ( CurScope != NULL ) {rec->scope = *CurScope; *CurScope = rec;}
  166. rec->next = table[h]; /* Add to doubly-linked list */
  167. rec->prev = NULL;
  168. if ( rec->next != NULL ) (rec->next)->prev = rec;
  169. table[h] = rec;
  170. rec->head = &(table[h]);
  171. }
  172. Sym *
  173. zzs_get(key)
  174. char *key;
  175. {
  176. register unsigned int h=0;
  177. register char *p=key;
  178. register Sym *q;
  179. HASH(p, h);
  180. for (q = table[h%size]; q != NULL; q = q->next)
  181. {
  182. if ( q->hash == h ) /* do we even have a chance of matching? */
  183. if ( strcmp(key, q->symbol) == StrSame ) return( q );
  184. }
  185. return( NULL );
  186. }
  187. /*
  188.  * Unlink p from the symbol table.  Hopefully, it's actually in the
  189.  * symbol table.
  190.  *
  191.  * If p is not part of a bucket chain of the symbol table, bad things
  192.  * will happen.
  193.  *
  194.  * Will do nothing if all list pointers are NULL
  195.  */
  196. void
  197. zzs_del(p)
  198. register Sym *p;
  199. {
  200. if ( p == NULL ) {fprintf(stderr, "zzs_del(NULL)n"); exit(1);}
  201. if ( p->prev == NULL ) /* Head of list */
  202. {
  203. register Sym **t = p->head;
  204. if ( t == NULL ) return; /* not part of symbol table */
  205. (*t) = p->next;
  206. if ( (*t) != NULL ) (*t)->prev = NULL;
  207. }
  208. else
  209. {
  210. (p->prev)->next = p->next;
  211. if ( p->next != NULL ) (p->next)->prev = p->prev;
  212. }
  213. p->next = p->prev = NULL; /* not part of symbol table anymore */
  214. p->head = NULL;
  215. }
  216. void
  217. zzs_keydel(key)
  218. char *key;
  219. {
  220. Sym *p = zzs_get(key);
  221. if ( p != NULL ) zzs_del( p );
  222. }
  223. /* S c o p e  S t u f f */
  224. /* Set current scope to 'scope'; return current scope if 'scope' == NULL */
  225. Sym **
  226. zzs_scope(scope)
  227. Sym **scope;
  228. {
  229. if ( scope == NULL ) return( CurScope );
  230. CurScope = scope;
  231. return( scope );
  232. }
  233. /* Remove a scope described by 'scope'.  Return pointer to 1st element in scope */
  234. Sym *
  235. zzs_rmscope(scope)
  236. register Sym **scope;
  237. {
  238. register Sym *p;
  239. Sym *start;
  240. if ( scope == NULL ) return(NULL);
  241. start = p = *scope;
  242. for (; p != NULL; p=p->scope) { zzs_del( p ); }
  243. *scope = NULL;
  244. return( start );
  245. }
  246. void
  247. zzs_stat()
  248. {
  249. static unsigned short count[20];
  250. unsigned int i,n=0,low=0, hi=0;
  251. register Sym **p;
  252. float avg=0.0;
  253. for (i=0; i<20; i++) count[i] = 0;
  254. for (p=table; p<&(table[size]); p++)
  255. {
  256. register Sym *q = *p;
  257. unsigned int len;
  258. if ( q != NULL && low==0 ) low = p-table;
  259. len = 0;
  260. if ( q != NULL ) printf("[%d]", p-table);
  261. while ( q != NULL )
  262. {
  263. len++;
  264. n++;
  265. printf(" %s", q->symbol);
  266. q = q->next;
  267. if ( q == NULL ) printf("n");
  268. }
  269. if ( len>=20 ) printf("zzs_stat: count table too smalln");
  270. else count[len]++;
  271. if ( *p != NULL ) hi = p-table;
  272. }
  273. printf("Storing %d recs used %d hash positions out of %dn",
  274. n, size-count[0], size);
  275. printf("%f %% utilizationn",
  276. ((float)(size-count[0]))/((float)size));
  277. for (i=0; i<20; i++)
  278. {
  279. if ( count[i] != 0 )
  280. {
  281. avg += (((float)(i*count[i]))/((float)n)) * i;
  282. printf("Buckets of len %d == %d (%f %% of recs)n",
  283. i, count[i], 100.0*((float)(i*count[i]))/((float)n));
  284. }
  285. }
  286. printf("Avg bucket length %fn", avg);
  287. printf("Range of hash function: %d..%dn", low, hi);
  288. }
  289. /*
  290.  * Given a string, this function allocates and returns a pointer to a
  291.  * symbol table record whose "symbol" pointer is reset to a position
  292.  * in the string table.
  293.  */
  294. Sym *
  295. zzs_new(text)
  296. char *text;
  297. {
  298. Sym *p;
  299. char *zzs_strdup();
  300. if ( (p = (Sym *) calloc(1,sizeof(Sym))) == 0 )
  301. {
  302. fprintf(stderr,"Out of memoryn");
  303. exit(1);
  304. }
  305. p->symbol = zzs_strdup(text);
  306. return p;
  307. }
  308. /* create a new symbol table entry and add it to the symbol table */
  309. Sym *
  310. zzs_newadd(text)
  311. char *text;
  312. {
  313. Sym *p = zzs_new(text);
  314. if ( p != NULL ) zzs_add(text, p);
  315. return p;
  316. }
  317. /* Add a string to the string table and return a pointer to it.
  318.  * Bump the pointer into the string table to next avail position.
  319.  */
  320. char *
  321. zzs_strdup(s)
  322. register char *s;
  323. {
  324. register char *start=strp;
  325. while ( *s != '' )
  326. {
  327. if ( strp >= &(strings[strsize-2]) )
  328. {
  329. fprintf(stderr, "sym: string table overflow (%d chars)n", strsize);
  330. exit(-1);
  331. }
  332. *strp++ = *s++;
  333. }
  334. *strp++ = '';
  335. return( start );
  336. }