1 |
edhill |
1.1 |
/* $XConsortium: parse.c,v 1.30 94/04/17 20:10:38 gildea Exp $ */ |
2 |
|
|
/* |
3 |
|
|
* Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. |
4 |
|
|
* |
5 |
|
|
* Redistribution and use in source and binary forms, with or without |
6 |
|
|
* modification, are permitted provided that the following conditions |
7 |
|
|
* are met: |
8 |
|
|
* |
9 |
|
|
* 1. Redistributions of source code must retain the above copyright |
10 |
|
|
* notice, this list of conditions and the following disclaimer. |
11 |
|
|
* |
12 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
13 |
|
|
* notice, this list of conditions and the following disclaimer in |
14 |
|
|
* the documentation and/or other materials provided with the |
15 |
|
|
* distribution. |
16 |
|
|
* |
17 |
|
|
* 3. The name "Carnegie Mellon University" must not be used to |
18 |
|
|
* endorse or promote products derived from this software without |
19 |
|
|
* prior written permission. For permission or any other legal |
20 |
|
|
* details, please contact |
21 |
|
|
* Office of Technology Transfer |
22 |
|
|
* Carnegie Mellon University |
23 |
|
|
* 5000 Forbes Avenue |
24 |
|
|
* Pittsburgh, PA 15213-3890 |
25 |
|
|
* (412) 268-4387, fax: (412) 268-7395 |
26 |
|
|
* tech-transfer@andrew.cmu.edu |
27 |
|
|
* |
28 |
|
|
* 4. Redistributions of any form whatsoever must retain the following |
29 |
|
|
* acknowledgment: |
30 |
|
|
* "This product includes software developed by Computing Services |
31 |
|
|
* at Carnegie Mellon University (http://www.cmu.edu/computing/)." |
32 |
|
|
* |
33 |
|
|
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO |
34 |
|
|
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY |
35 |
|
|
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE |
36 |
|
|
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
37 |
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN |
38 |
|
|
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING |
39 |
|
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
40 |
|
|
* |
41 |
|
|
*/ |
42 |
|
|
|
43 |
|
|
/* |
44 |
|
|
|
45 |
|
|
Copyright (c) 1993, 1994 X Consortium |
46 |
|
|
|
47 |
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy |
48 |
|
|
of this software and associated documentation files (the "Software"), to deal |
49 |
|
|
in the Software without restriction, including without limitation the rights |
50 |
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
51 |
|
|
copies of the Software, and to permit persons to whom the Software is |
52 |
|
|
furnished to do so, subject to the following conditions: |
53 |
|
|
|
54 |
|
|
The above copyright notice and this permission notice shall be included in |
55 |
|
|
all copies or substantial portions of the Software. |
56 |
|
|
|
57 |
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
58 |
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
59 |
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
60 |
|
|
X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
61 |
|
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
62 |
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
63 |
|
|
|
64 |
|
|
Except as contained in this notice, the name of the X Consortium shall not be |
65 |
|
|
used in advertising or otherwise to promote the sale, use or other dealings |
66 |
|
|
in this Software without prior written authorization from the X Consortium. |
67 |
|
|
|
68 |
|
|
*/ |
69 |
|
|
|
70 |
|
|
#include "def.h" |
71 |
|
|
|
72 |
|
|
extern char *directives[]; |
73 |
|
|
extern struct inclist maininclist; |
74 |
|
|
|
75 |
|
|
find_includes(filep, file, file_red, recursion, failOK) |
76 |
|
|
struct filepointer *filep; |
77 |
|
|
struct inclist *file, *file_red; |
78 |
|
|
int recursion; |
79 |
|
|
boolean failOK; |
80 |
|
|
{ |
81 |
|
|
register char *line; |
82 |
|
|
register int type; |
83 |
|
|
boolean recfailOK; |
84 |
|
|
|
85 |
jahn |
1.2 |
while (line = getppline(filep)) { |
86 |
edhill |
1.1 |
switch(type = deftype(line, filep, file_red, file, TRUE)) { |
87 |
|
|
case IF: |
88 |
|
|
doif: |
89 |
|
|
type = find_includes(filep, file, |
90 |
|
|
file_red, recursion+1, failOK); |
91 |
|
|
while ((type == ELIF) || (type == ELIFFALSE) || |
92 |
|
|
(type == ELIFGUESSFALSE)) |
93 |
|
|
type = gobble(filep, file, file_red); |
94 |
|
|
if (type == ELSE) |
95 |
|
|
gobble(filep, file, file_red); |
96 |
|
|
break; |
97 |
|
|
case IFFALSE: |
98 |
|
|
case IFGUESSFALSE: |
99 |
|
|
doiffalse: |
100 |
|
|
if (type == IFGUESSFALSE || type == ELIFGUESSFALSE) |
101 |
|
|
recfailOK = TRUE; |
102 |
|
|
else |
103 |
|
|
recfailOK = failOK; |
104 |
|
|
type = gobble(filep, file, file_red); |
105 |
|
|
if (type == ELSE) |
106 |
|
|
find_includes(filep, file, |
107 |
|
|
file_red, recursion+1, recfailOK); |
108 |
|
|
else |
109 |
|
|
if (type == ELIF) |
110 |
|
|
goto doif; |
111 |
|
|
else |
112 |
|
|
if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE)) |
113 |
|
|
goto doiffalse; |
114 |
|
|
break; |
115 |
|
|
case IFDEF: |
116 |
|
|
case IFNDEF: |
117 |
|
|
if ((type == IFDEF && isdefined(line, file_red, NULL)) |
118 |
|
|
|| (type == IFNDEF && !isdefined(line, file_red, NULL))) { |
119 |
|
|
debug(1,(type == IFNDEF ? |
120 |
|
|
"line %d: %s !def'd in %s via %s%s\n" : "", |
121 |
|
|
filep->f_line, line, |
122 |
|
|
file->i_file, file_red->i_file, ": doit")); |
123 |
|
|
type = find_includes(filep, file, |
124 |
|
|
file_red, recursion+1, failOK); |
125 |
|
|
while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE) |
126 |
|
|
type = gobble(filep, file, file_red); |
127 |
|
|
if (type == ELSE) |
128 |
|
|
gobble(filep, file, file_red); |
129 |
|
|
} |
130 |
|
|
else { |
131 |
|
|
debug(1,(type == IFDEF ? |
132 |
|
|
"line %d: %s !def'd in %s via %s%s\n" : "", |
133 |
|
|
filep->f_line, line, |
134 |
|
|
file->i_file, file_red->i_file, ": gobble")); |
135 |
|
|
type = gobble(filep, file, file_red); |
136 |
|
|
if (type == ELSE) |
137 |
|
|
find_includes(filep, file, |
138 |
|
|
file_red, recursion+1, failOK); |
139 |
|
|
else if (type == ELIF) |
140 |
|
|
goto doif; |
141 |
|
|
else if (type == ELIFFALSE || type == ELIFGUESSFALSE) |
142 |
|
|
goto doiffalse; |
143 |
|
|
} |
144 |
|
|
break; |
145 |
|
|
case ELSE: |
146 |
|
|
case ELIFFALSE: |
147 |
|
|
case ELIFGUESSFALSE: |
148 |
|
|
case ELIF: |
149 |
|
|
if (!recursion) |
150 |
|
|
gobble(filep, file, file_red); |
151 |
|
|
case ENDIF: |
152 |
|
|
if (recursion) |
153 |
|
|
return(type); |
154 |
|
|
case DEFINE: |
155 |
|
|
define(line, file); |
156 |
|
|
break; |
157 |
|
|
case UNDEF: |
158 |
|
|
if (!*line) { |
159 |
|
|
warning("%s, line %d: incomplete undef == \"%s\"\n", |
160 |
|
|
file_red->i_file, filep->f_line, line); |
161 |
|
|
break; |
162 |
|
|
} |
163 |
|
|
undefine(line, file_red); |
164 |
|
|
break; |
165 |
|
|
case INCLUDE: |
166 |
|
|
add_include(filep, file, file_red, line, FALSE, failOK); |
167 |
|
|
break; |
168 |
|
|
case INCLUDEDOT: |
169 |
|
|
add_include(filep, file, file_red, line, TRUE, failOK); |
170 |
|
|
break; |
171 |
|
|
case ERROR: |
172 |
|
|
warning("%s: %d: %s\n", file_red->i_file, |
173 |
|
|
filep->f_line, line); |
174 |
|
|
break; |
175 |
|
|
|
176 |
|
|
case PRAGMA: |
177 |
|
|
case IDENT: |
178 |
|
|
case SCCS: |
179 |
|
|
case EJECT: |
180 |
|
|
break; |
181 |
|
|
case -1: |
182 |
|
|
warning("%s", file_red->i_file); |
183 |
|
|
if (file_red != file) |
184 |
|
|
warning1(" (reading %s)", file->i_file); |
185 |
|
|
warning1(", line %d: unknown directive == \"%s\"\n", |
186 |
|
|
filep->f_line, line); |
187 |
|
|
break; |
188 |
|
|
case -2: |
189 |
|
|
warning("%s", file_red->i_file); |
190 |
|
|
if (file_red != file) |
191 |
|
|
warning1(" (reading %s)", file->i_file); |
192 |
|
|
warning1(", line %d: incomplete include == \"%s\"\n", |
193 |
|
|
filep->f_line, line); |
194 |
|
|
break; |
195 |
|
|
} |
196 |
|
|
} |
197 |
|
|
return(-1); |
198 |
|
|
} |
199 |
|
|
|
200 |
|
|
gobble(filep, file, file_red) |
201 |
|
|
register struct filepointer *filep; |
202 |
|
|
struct inclist *file, *file_red; |
203 |
|
|
{ |
204 |
|
|
register char *line; |
205 |
|
|
register int type; |
206 |
|
|
|
207 |
jahn |
1.2 |
while (line = getppline(filep)) { |
208 |
edhill |
1.1 |
switch(type = deftype(line, filep, file_red, file, FALSE)) { |
209 |
|
|
case IF: |
210 |
|
|
case IFFALSE: |
211 |
|
|
case IFGUESSFALSE: |
212 |
|
|
case IFDEF: |
213 |
|
|
case IFNDEF: |
214 |
|
|
type = gobble(filep, file, file_red); |
215 |
|
|
while ((type == ELIF) || (type == ELIFFALSE) || |
216 |
|
|
(type == ELIFGUESSFALSE)) |
217 |
|
|
type = gobble(filep, file, file_red); |
218 |
|
|
if (type == ELSE) |
219 |
|
|
(void)gobble(filep, file, file_red); |
220 |
|
|
break; |
221 |
|
|
case ELSE: |
222 |
|
|
case ENDIF: |
223 |
|
|
debug(0,("%s, line %d: #%s\n", |
224 |
|
|
file->i_file, filep->f_line, |
225 |
|
|
directives[type])); |
226 |
|
|
return(type); |
227 |
|
|
case DEFINE: |
228 |
|
|
case UNDEF: |
229 |
|
|
case INCLUDE: |
230 |
|
|
case INCLUDEDOT: |
231 |
|
|
case PRAGMA: |
232 |
|
|
case ERROR: |
233 |
|
|
case IDENT: |
234 |
|
|
case SCCS: |
235 |
|
|
case EJECT: |
236 |
|
|
break; |
237 |
|
|
case ELIF: |
238 |
|
|
case ELIFFALSE: |
239 |
|
|
case ELIFGUESSFALSE: |
240 |
|
|
return(type); |
241 |
|
|
case -1: |
242 |
|
|
warning("%s, line %d: unknown directive == \"%s\"\n", |
243 |
|
|
file_red->i_file, filep->f_line, line); |
244 |
|
|
break; |
245 |
|
|
} |
246 |
|
|
} |
247 |
|
|
return(-1); |
248 |
|
|
} |
249 |
|
|
|
250 |
|
|
/* |
251 |
|
|
* Decide what type of # directive this line is. |
252 |
|
|
*/ |
253 |
|
|
int deftype (line, filep, file_red, file, parse_it) |
254 |
|
|
register char *line; |
255 |
|
|
register struct filepointer *filep; |
256 |
|
|
register struct inclist *file_red, *file; |
257 |
|
|
int parse_it; |
258 |
|
|
{ |
259 |
|
|
register char *p; |
260 |
|
|
char *directive, savechar; |
261 |
|
|
register int ret; |
262 |
|
|
|
263 |
|
|
/* |
264 |
|
|
* Parse the directive... |
265 |
|
|
*/ |
266 |
|
|
directive=line+1; |
267 |
|
|
while (*directive == ' ' || *directive == '\t') |
268 |
|
|
directive++; |
269 |
|
|
|
270 |
|
|
p = directive; |
271 |
|
|
while (*p >= 'a' && *p <= 'z') |
272 |
|
|
p++; |
273 |
|
|
savechar = *p; |
274 |
|
|
*p = '\0'; |
275 |
|
|
ret = match(directive, directives); |
276 |
|
|
*p = savechar; |
277 |
|
|
|
278 |
|
|
/* If we don't recognize this compiler directive or we happen to just |
279 |
|
|
* be gobbling up text while waiting for an #endif or #elif or #else |
280 |
|
|
* in the case of an #elif we must check the zero_value and return an |
281 |
|
|
* ELIF or an ELIFFALSE. |
282 |
|
|
*/ |
283 |
|
|
|
284 |
|
|
if (ret == ELIF && !parse_it) |
285 |
|
|
{ |
286 |
|
|
while (*p == ' ' || *p == '\t') |
287 |
|
|
p++; |
288 |
|
|
/* |
289 |
|
|
* parse an expression. |
290 |
|
|
*/ |
291 |
|
|
debug(0,("%s, line %d: #elif %s ", |
292 |
|
|
file->i_file, filep->f_line, p)); |
293 |
|
|
ret = zero_value(p, filep, file_red); |
294 |
|
|
if (ret != IF) |
295 |
|
|
{ |
296 |
|
|
debug(0,("false...\n")); |
297 |
|
|
if (ret == IFFALSE) |
298 |
|
|
return(ELIFFALSE); |
299 |
|
|
else |
300 |
|
|
return(ELIFGUESSFALSE); |
301 |
|
|
} |
302 |
|
|
else |
303 |
|
|
{ |
304 |
|
|
debug(0,("true...\n")); |
305 |
|
|
return(ELIF); |
306 |
|
|
} |
307 |
|
|
} |
308 |
|
|
|
309 |
|
|
if (ret < 0 || ! parse_it) |
310 |
|
|
return(ret); |
311 |
|
|
|
312 |
|
|
/* |
313 |
|
|
* now decide how to parse the directive, and do it. |
314 |
|
|
*/ |
315 |
|
|
while (*p == ' ' || *p == '\t') |
316 |
|
|
p++; |
317 |
|
|
switch (ret) { |
318 |
|
|
case IF: |
319 |
|
|
/* |
320 |
|
|
* parse an expression. |
321 |
|
|
*/ |
322 |
|
|
ret = zero_value(p, filep, file_red); |
323 |
|
|
debug(0,("%s, line %d: %s #if %s\n", |
324 |
|
|
file->i_file, filep->f_line, ret?"false":"true", p)); |
325 |
|
|
break; |
326 |
|
|
case IFDEF: |
327 |
|
|
case IFNDEF: |
328 |
|
|
debug(0,("%s, line %d: #%s %s\n", |
329 |
|
|
file->i_file, filep->f_line, directives[ret], p)); |
330 |
|
|
case UNDEF: |
331 |
|
|
/* |
332 |
|
|
* separate the name of a single symbol. |
333 |
|
|
*/ |
334 |
|
|
while (isalnum(*p) || *p == '_') |
335 |
|
|
*line++ = *p++; |
336 |
|
|
*line = '\0'; |
337 |
|
|
break; |
338 |
|
|
case INCLUDE: |
339 |
|
|
debug(2,("%s, line %d: #include %s\n", |
340 |
|
|
file->i_file, filep->f_line, p)); |
341 |
|
|
|
342 |
|
|
/* Support ANSI macro substitution */ |
343 |
|
|
{ |
344 |
|
|
struct symtab *sym = isdefined(p, file_red, NULL); |
345 |
|
|
while (sym) { |
346 |
|
|
p = sym->s_value; |
347 |
|
|
debug(3,("%s : #includes SYMBOL %s = %s\n", |
348 |
|
|
file->i_incstring, |
349 |
|
|
sym -> s_name, |
350 |
|
|
sym -> s_value)); |
351 |
|
|
/* mark file as having included a 'soft include' */ |
352 |
|
|
file->i_included_sym = TRUE; |
353 |
|
|
sym = isdefined(p, file_red, NULL); |
354 |
|
|
} |
355 |
|
|
} |
356 |
|
|
|
357 |
|
|
/* |
358 |
|
|
* Separate the name of the include file. |
359 |
|
|
*/ |
360 |
|
|
while (*p && *p != '"' && *p != '<') |
361 |
|
|
p++; |
362 |
|
|
if (! *p) |
363 |
|
|
return(-2); |
364 |
|
|
if (*p++ == '"') { |
365 |
|
|
ret = INCLUDEDOT; |
366 |
|
|
while (*p && *p != '"') |
367 |
|
|
*line++ = *p++; |
368 |
|
|
} else |
369 |
|
|
while (*p && *p != '>') |
370 |
|
|
*line++ = *p++; |
371 |
|
|
*line = '\0'; |
372 |
|
|
break; |
373 |
|
|
case DEFINE: |
374 |
|
|
/* |
375 |
|
|
* copy the definition back to the beginning of the line. |
376 |
|
|
*/ |
377 |
|
|
strcpy (line, p); |
378 |
|
|
break; |
379 |
|
|
case ELSE: |
380 |
|
|
case ENDIF: |
381 |
|
|
case ELIF: |
382 |
|
|
case PRAGMA: |
383 |
|
|
case ERROR: |
384 |
|
|
case IDENT: |
385 |
|
|
case SCCS: |
386 |
|
|
case EJECT: |
387 |
|
|
debug(0,("%s, line %d: #%s\n", |
388 |
|
|
file->i_file, filep->f_line, directives[ret])); |
389 |
|
|
/* |
390 |
|
|
* nothing to do. |
391 |
|
|
*/ |
392 |
|
|
break; |
393 |
|
|
} |
394 |
|
|
return(ret); |
395 |
|
|
} |
396 |
|
|
|
397 |
|
|
struct symtab *isdefined(symbol, file, srcfile) |
398 |
|
|
register char *symbol; |
399 |
|
|
struct inclist *file; |
400 |
|
|
struct inclist **srcfile; |
401 |
|
|
{ |
402 |
|
|
register struct symtab *val; |
403 |
|
|
|
404 |
|
|
if (val = slookup(symbol, &maininclist)) { |
405 |
|
|
debug(1,("%s defined on command line\n", symbol)); |
406 |
|
|
if (srcfile != NULL) *srcfile = &maininclist; |
407 |
|
|
return(val); |
408 |
|
|
} |
409 |
|
|
if (val = fdefined(symbol, file, srcfile)) |
410 |
|
|
return(val); |
411 |
|
|
debug(1,("%s not defined in %s\n", symbol, file->i_file)); |
412 |
|
|
return(NULL); |
413 |
|
|
} |
414 |
|
|
|
415 |
|
|
struct symtab *fdefined(symbol, file, srcfile) |
416 |
|
|
register char *symbol; |
417 |
|
|
struct inclist *file; |
418 |
|
|
struct inclist **srcfile; |
419 |
|
|
{ |
420 |
|
|
register struct inclist **ip; |
421 |
|
|
register struct symtab *val; |
422 |
|
|
register int i; |
423 |
|
|
static int recurse_lvl = 0; |
424 |
|
|
|
425 |
|
|
if (file->i_defchecked) |
426 |
|
|
return(NULL); |
427 |
|
|
file->i_defchecked = TRUE; |
428 |
|
|
if (val = slookup(symbol, file)) |
429 |
|
|
debug(1,("%s defined in %s as %s\n", symbol, file->i_file, val->s_value)); |
430 |
|
|
if (val == NULL && file->i_list) |
431 |
|
|
{ |
432 |
|
|
for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++) |
433 |
|
|
if (val = fdefined(symbol, *ip, srcfile)) { |
434 |
|
|
break; |
435 |
|
|
} |
436 |
|
|
} |
437 |
|
|
else if (val != NULL && srcfile != NULL) *srcfile = file; |
438 |
|
|
recurse_lvl--; |
439 |
|
|
file->i_defchecked = FALSE; |
440 |
|
|
|
441 |
|
|
return(val); |
442 |
|
|
} |
443 |
|
|
|
444 |
|
|
/* |
445 |
|
|
* Return type based on if the #if expression evaluates to 0 |
446 |
|
|
*/ |
447 |
|
|
zero_value(exp, filep, file_red) |
448 |
|
|
register char *exp; |
449 |
|
|
register struct filepointer *filep; |
450 |
|
|
register struct inclist *file_red; |
451 |
|
|
{ |
452 |
|
|
if (cppsetup(exp, filep, file_red)) |
453 |
|
|
return(IFFALSE); |
454 |
|
|
else |
455 |
|
|
return(IF); |
456 |
|
|
} |
457 |
|
|
|
458 |
|
|
define(def, file) |
459 |
|
|
char *def; |
460 |
|
|
struct inclist *file; |
461 |
|
|
{ |
462 |
|
|
char *val; |
463 |
|
|
|
464 |
|
|
/* Separate symbol name and its value */ |
465 |
|
|
val = def; |
466 |
|
|
while (isalnum(*val) || *val == '_') |
467 |
|
|
val++; |
468 |
|
|
if (*val) |
469 |
|
|
*val++ = '\0'; |
470 |
|
|
while (*val == ' ' || *val == '\t') |
471 |
|
|
val++; |
472 |
|
|
|
473 |
|
|
if (!*val) |
474 |
|
|
val = "1"; |
475 |
|
|
define2(def, val, file); |
476 |
|
|
} |
477 |
|
|
|
478 |
|
|
define2(name, val, file) |
479 |
|
|
char *name, *val; |
480 |
|
|
struct inclist *file; |
481 |
|
|
{ |
482 |
|
|
int first, last, below; |
483 |
|
|
register struct symtab *sp = NULL, *dest; |
484 |
|
|
|
485 |
|
|
/* Make space if it's needed */ |
486 |
|
|
if (file->i_defs == NULL) |
487 |
|
|
{ |
488 |
|
|
file->i_defs = (struct symtab *) |
489 |
|
|
malloc(sizeof (struct symtab) * SYMTABINC); |
490 |
|
|
file->i_deflen = SYMTABINC; |
491 |
|
|
file->i_ndefs = 0; |
492 |
|
|
} |
493 |
|
|
else if (file->i_ndefs == file->i_deflen) |
494 |
|
|
file->i_defs = (struct symtab *) |
495 |
|
|
realloc(file->i_defs, |
496 |
|
|
sizeof(struct symtab)*(file->i_deflen+=SYMTABINC)); |
497 |
|
|
|
498 |
|
|
if (file->i_defs == NULL) |
499 |
|
|
fatalerr("malloc()/realloc() failure in insert_defn()\n"); |
500 |
|
|
|
501 |
|
|
below = first = 0; |
502 |
|
|
last = file->i_ndefs - 1; |
503 |
|
|
while (last >= first) |
504 |
|
|
{ |
505 |
|
|
/* Fast inline binary search */ |
506 |
|
|
register char *s1; |
507 |
|
|
register char *s2; |
508 |
|
|
register int middle = (first + last) / 2; |
509 |
|
|
|
510 |
|
|
/* Fast inline strchr() */ |
511 |
|
|
s1 = name; |
512 |
|
|
s2 = file->i_defs[middle].s_name; |
513 |
|
|
while (*s1++ == *s2++) |
514 |
|
|
if (s2[-1] == '\0') break; |
515 |
|
|
|
516 |
|
|
/* If exact match, set sp and break */ |
517 |
|
|
if (*--s1 == *--s2) |
518 |
|
|
{ |
519 |
|
|
sp = file->i_defs + middle; |
520 |
|
|
break; |
521 |
|
|
} |
522 |
|
|
|
523 |
|
|
/* If name > i_defs[middle] ... */ |
524 |
|
|
if (*s1 > *s2) |
525 |
|
|
{ |
526 |
|
|
below = first; |
527 |
|
|
first = middle + 1; |
528 |
|
|
} |
529 |
|
|
/* else ... */ |
530 |
|
|
else |
531 |
|
|
{ |
532 |
|
|
below = last = middle - 1; |
533 |
|
|
} |
534 |
|
|
} |
535 |
|
|
|
536 |
|
|
/* Search is done. If we found an exact match to the symbol name, |
537 |
|
|
just replace its s_value */ |
538 |
|
|
if (sp != NULL) |
539 |
|
|
{ |
540 |
|
|
free(sp->s_value); |
541 |
|
|
sp->s_value = copy(val); |
542 |
|
|
return; |
543 |
|
|
} |
544 |
|
|
|
545 |
|
|
sp = file->i_defs + file->i_ndefs++; |
546 |
|
|
dest = file->i_defs + below + 1; |
547 |
|
|
while (sp > dest) |
548 |
|
|
{ |
549 |
|
|
*sp = sp[-1]; |
550 |
|
|
sp--; |
551 |
|
|
} |
552 |
|
|
sp->s_name = copy(name); |
553 |
|
|
sp->s_value = copy(val); |
554 |
|
|
} |
555 |
|
|
|
556 |
|
|
struct symtab *slookup(symbol, file) |
557 |
|
|
register char *symbol; |
558 |
|
|
register struct inclist *file; |
559 |
|
|
{ |
560 |
|
|
register int first = 0; |
561 |
|
|
register int last = file->i_ndefs - 1; |
562 |
|
|
|
563 |
|
|
if (file) while (last >= first) |
564 |
|
|
{ |
565 |
|
|
/* Fast inline binary search */ |
566 |
|
|
register char *s1; |
567 |
|
|
register char *s2; |
568 |
|
|
register int middle = (first + last) / 2; |
569 |
|
|
|
570 |
|
|
/* Fast inline strchr() */ |
571 |
|
|
s1 = symbol; |
572 |
|
|
s2 = file->i_defs[middle].s_name; |
573 |
|
|
while (*s1++ == *s2++) |
574 |
|
|
if (s2[-1] == '\0') break; |
575 |
|
|
|
576 |
|
|
/* If exact match, we're done */ |
577 |
|
|
if (*--s1 == *--s2) |
578 |
|
|
{ |
579 |
|
|
return file->i_defs + middle; |
580 |
|
|
} |
581 |
|
|
|
582 |
|
|
/* If symbol > i_defs[middle] ... */ |
583 |
|
|
if (*s1 > *s2) |
584 |
|
|
{ |
585 |
|
|
first = middle + 1; |
586 |
|
|
} |
587 |
|
|
/* else ... */ |
588 |
|
|
else |
589 |
|
|
{ |
590 |
|
|
last = middle - 1; |
591 |
|
|
} |
592 |
|
|
} |
593 |
|
|
return(NULL); |
594 |
|
|
} |
595 |
|
|
|
596 |
|
|
undefine(symbol, file) |
597 |
|
|
char *symbol; |
598 |
|
|
register struct inclist *file; |
599 |
|
|
{ |
600 |
|
|
register struct symtab *ptr; |
601 |
|
|
struct inclist *srcfile; |
602 |
|
|
while ((ptr = isdefined(symbol, file, &srcfile)) != NULL) |
603 |
|
|
{ |
604 |
|
|
srcfile->i_ndefs--; |
605 |
|
|
for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++) |
606 |
|
|
*ptr = ptr[1]; |
607 |
|
|
} |
608 |
|
|
} |