home *** CD-ROM | disk | FTP | other *** search
- /* Part of CPP library. (Macro hash table support.)
- Copyright (C) 1986, 87, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
- Written by Per Bothner, 1994.
- Based on CCCP program by by Paul Rubin, June 1986
- Adapted to ANSI C, Richard Stallman, Jan 1987
-
- 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.
-
- 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.
-
- 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.
-
- 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
- what you give them. Help stamp out software-hoarding! */
-
- #include "cpplib.h"
- #include "cpphash.h"
-
- extern char *xmalloc PARAMS ((unsigned));
-
- /* Define a generic NULL if one hasn't already been defined. */
-
- #ifndef NULL
- #define NULL 0
- #endif
-
- #ifndef __STDC__
- #define const
- #define volatile
- #endif
-
- /*
- * return hash function on name. must be compatible with the one
- * computed a step at a time, elsewhere
- */
- int
- hashf (name, len, hashsize)
- register const U_CHAR *name;
- register int len;
- int hashsize;
- {
- register int r = 0;
-
- while (len--)
- r = HASHSTEP (r, *name++);
-
- return MAKE_POS (r) % hashsize;
- }
-
- /*
- * find the most recent hash node for name name (ending with first
- * non-identifier char) installed by install
- *
- * If LEN is >= 0, it is the length of the name.
- * Otherwise, compute the length by scanning the entire name.
- *
- * If HASH is >= 0, it is the precomputed hash code.
- * Otherwise, compute the hash code.
- */
- HASHNODE *
- cpp_lookup (pfile, name, len, hash)
- struct parse_file *pfile;
- const U_CHAR *name;
- int len;
- int hash;
- {
- register const U_CHAR *bp;
- register HASHNODE *bucket;
-
- if (len < 0)
- {
- for (bp = name; is_idchar[*bp]; bp++) ;
- len = bp - name;
- }
-
- if (hash < 0)
- hash = hashf (name, len, HASHSIZE);
-
- bucket = hashtab[hash];
- while (bucket) {
- if (bucket->length == len && strncmp (bucket->name, name, len) == 0)
- return bucket;
- bucket = bucket->next;
- }
- return (HASHNODE*) 0;
- }
-
- /*
- * Delete a hash node. Some weirdness to free junk from macros.
- * More such weirdness will have to be added if you define more hash
- * types that need it.
- */
-
- /* Note that the DEFINITION of a macro is removed from the hash table
- but its storage is not freed. This would be a storage leak
- except that it is not reasonable to keep undefining and redefining
- large numbers of macros many times.
- In any case, this is necessary, because a macro can be #undef'd
- in the middle of reading the arguments to a call to it.
- If #undef freed the DEFINITION, that would crash. */
-
- void
- delete_macro (hp)
- HASHNODE *hp;
- {
-
- if (hp->prev != NULL)
- hp->prev->next = hp->next;
- if (hp->next != NULL)
- hp->next->prev = hp->prev;
-
- /* make sure that the bucket chain header that
- the deleted guy was on points to the right thing afterwards. */
- if (hp == *hp->bucket_hdr)
- *hp->bucket_hdr = hp->next;
-
- if (hp->type == T_MACRO)
- {
- DEFINITION *d = hp->value.defn;
- struct reflist *ap, *nextap;
-
- for (ap = d->pattern; ap != NULL; ap = nextap)
- {
- nextap = ap->next;
- free (ap);
- }
- if (d->nargs >= 0)
- free (d->args.argnames);
- free (d);
- }
-
- free (hp);
- }
- /*
- * install a name in the main hash table, even if it is already there.
- * name stops with first non alphanumeric, except leading '#'.
- * caller must check against redefinition if that is desired.
- * delete_macro () removes things installed by install () in fifo order.
- * this is important because of the `defined' special symbol used
- * in #if, and also if pushdef/popdef directives are ever implemented.
- *
- * If LEN is >= 0, it is the length of the name.
- * Otherwise, compute the length by scanning the entire name.
- *
- * If HASH is >= 0, it is the precomputed hash code.
- * Otherwise, compute the hash code.
- */
- HASHNODE *
- install (name, len, type, ivalue, value, hash)
- U_CHAR *name;
- int len;
- enum node_type type;
- int ivalue;
- char *value;
- int hash;
- {
- register HASHNODE *hp;
- register int i, bucket;
- register U_CHAR *p, *q;
-
- if (len < 0) {
- p = name;
- while (is_idchar[*p])
- p++;
- len = p - name;
- }
-
- if (hash < 0)
- hash = hashf (name, len, HASHSIZE);
-
- i = sizeof (HASHNODE) + len + 1;
- hp = (HASHNODE *) xmalloc (i);
- bucket = hash;
- hp->bucket_hdr = &hashtab[bucket];
- hp->next = hashtab[bucket];
- hashtab[bucket] = hp;
- hp->prev = NULL;
- if (hp->next != NULL)
- hp->next->prev = hp;
- hp->type = type;
- hp->length = len;
- if (hp->type == T_CONST)
- hp->value.ival = ivalue;
- else
- hp->value.cpval = value;
- hp->name = ((U_CHAR *) hp) + sizeof (HASHNODE);
- p = hp->name;
- q = name;
- for (i = 0; i < len; i++)
- *p++ = *q++;
- hp->name[len] = 0;
- return hp;
- }
-
- void
- cpp_hash_cleanup (pfile)
- cpp_reader *pfile;
- {
- register int i;
- for (i = HASHSIZE; --i >= 0; )
- {
- while (hashtab[i])
- delete_macro (hashtab[i]);
- }
- }
-