|
|
1.1 root 1: /* Part of CPP library. (Macro hash table support.)
2: Copyright (C) 1986, 87, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
3: Written by Per Bothner, 1994.
4: Based on CCCP program by by Paul Rubin, June 1986
5: Adapted to ANSI C, Richard Stallman, Jan 1987
6:
7: This program is free software; you can redistribute it and/or modify it
8: under the terms of the GNU General Public License as published by the
9: Free Software Foundation; either version 2, or (at your option) any
10: later version.
11:
12: This program is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU General Public License for more details.
16:
17: You should have received a copy of the GNU General Public License
18: along with this program; if not, write to the Free Software
19: Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20:
21: In other words, you are welcome to use, share and improve this program.
22: You are forbidden to forbid anyone else to use, share and improve
23: what you give them. Help stamp out software-hoarding! */
24:
25: #include "cpplib.h"
26: #include "cpphash.h"
27:
28: extern char *xmalloc PARAMS ((unsigned));
29:
30: /* Define a generic NULL if one hasn't already been defined. */
31:
32: #ifndef NULL
33: #define NULL 0
34: #endif
35:
36: #ifndef __STDC__
37: #define const
38: #define volatile
39: #endif
40:
41: /*
42: * return hash function on name. must be compatible with the one
43: * computed a step at a time, elsewhere
44: */
45: int
46: hashf (name, len, hashsize)
47: register const U_CHAR *name;
48: register int len;
49: int hashsize;
50: {
51: register int r = 0;
52:
53: while (len--)
54: r = HASHSTEP (r, *name++);
55:
56: return MAKE_POS (r) % hashsize;
57: }
58:
59: /*
60: * find the most recent hash node for name name (ending with first
61: * non-identifier char) installed by install
62: *
63: * If LEN is >= 0, it is the length of the name.
64: * Otherwise, compute the length by scanning the entire name.
65: *
66: * If HASH is >= 0, it is the precomputed hash code.
67: * Otherwise, compute the hash code.
68: */
69: HASHNODE *
70: cpp_lookup (pfile, name, len, hash)
71: struct parse_file *pfile;
72: const U_CHAR *name;
73: int len;
74: int hash;
75: {
76: register const U_CHAR *bp;
77: register HASHNODE *bucket;
78:
79: if (len < 0)
80: {
81: for (bp = name; is_idchar[*bp]; bp++) ;
82: len = bp - name;
83: }
84:
85: if (hash < 0)
86: hash = hashf (name, len, HASHSIZE);
87:
88: bucket = hashtab[hash];
89: while (bucket) {
90: if (bucket->length == len && strncmp (bucket->name, name, len) == 0)
91: return bucket;
92: bucket = bucket->next;
93: }
94: return (HASHNODE*) 0;
95: }
96:
97: /*
98: * Delete a hash node. Some weirdness to free junk from macros.
99: * More such weirdness will have to be added if you define more hash
100: * types that need it.
101: */
102:
103: /* Note that the DEFINITION of a macro is removed from the hash table
104: but its storage is not freed. This would be a storage leak
105: except that it is not reasonable to keep undefining and redefining
106: large numbers of macros many times.
107: In any case, this is necessary, because a macro can be #undef'd
108: in the middle of reading the arguments to a call to it.
109: If #undef freed the DEFINITION, that would crash. */
110:
111: void
112: delete_macro (hp)
113: HASHNODE *hp;
114: {
115:
116: if (hp->prev != NULL)
117: hp->prev->next = hp->next;
118: if (hp->next != NULL)
119: hp->next->prev = hp->prev;
120:
121: /* make sure that the bucket chain header that
122: the deleted guy was on points to the right thing afterwards. */
123: if (hp == *hp->bucket_hdr)
124: *hp->bucket_hdr = hp->next;
125:
126: if (hp->type == T_MACRO)
127: {
128: DEFINITION *d = hp->value.defn;
129: struct reflist *ap, *nextap;
130:
131: for (ap = d->pattern; ap != NULL; ap = nextap)
132: {
133: nextap = ap->next;
134: free (ap);
135: }
136: if (d->nargs >= 0)
137: free (d->args.argnames);
138: free (d);
139: }
140:
141: free (hp);
142: }
143: /*
144: * install a name in the main hash table, even if it is already there.
145: * name stops with first non alphanumeric, except leading '#'.
146: * caller must check against redefinition if that is desired.
147: * delete_macro () removes things installed by install () in fifo order.
148: * this is important because of the `defined' special symbol used
149: * in #if, and also if pushdef/popdef directives are ever implemented.
150: *
151: * If LEN is >= 0, it is the length of the name.
152: * Otherwise, compute the length by scanning the entire name.
153: *
154: * If HASH is >= 0, it is the precomputed hash code.
155: * Otherwise, compute the hash code.
156: */
157: HASHNODE *
158: install (name, len, type, ivalue, value, hash)
159: U_CHAR *name;
160: int len;
161: enum node_type type;
162: int ivalue;
163: char *value;
164: int hash;
165: {
166: register HASHNODE *hp;
167: register int i, bucket;
168: register U_CHAR *p, *q;
169:
170: if (len < 0) {
171: p = name;
172: while (is_idchar[*p])
173: p++;
174: len = p - name;
175: }
176:
177: if (hash < 0)
178: hash = hashf (name, len, HASHSIZE);
179:
180: i = sizeof (HASHNODE) + len + 1;
181: hp = (HASHNODE *) xmalloc (i);
182: bucket = hash;
183: hp->bucket_hdr = &hashtab[bucket];
184: hp->next = hashtab[bucket];
185: hashtab[bucket] = hp;
186: hp->prev = NULL;
187: if (hp->next != NULL)
188: hp->next->prev = hp;
189: hp->type = type;
190: hp->length = len;
191: if (hp->type == T_CONST)
192: hp->value.ival = ivalue;
193: else
194: hp->value.cpval = value;
195: hp->name = ((U_CHAR *) hp) + sizeof (HASHNODE);
196: p = hp->name;
197: q = name;
198: for (i = 0; i < len; i++)
199: *p++ = *q++;
200: hp->name[len] = 0;
201: return hp;
202: }
203:
204: void
205: cpp_hash_cleanup (pfile)
206: cpp_reader *pfile;
207: {
208: register int i;
209: for (i = HASHSIZE; --i >= 0; )
210: {
211: while (hashtab[i])
212: delete_macro (hashtab[i]);
213: }
214: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.