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