1 /* $XConsortium: parse.c,v 1.30 94/04/17 20:10:38 gildea Exp $ */
4 Copyright (c) 1993, 1994 X Consortium
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 Except as contained in this notice, the name of the X Consortium shall not be
24 used in advertising or otherwise to promote the sale, use or other dealings
25 in this Software without prior written authorization from the X Consortium.
30 char *hash_lookup( char *symbol
, struct symhash
*symbols
);
31 void hash_undefine( char *symbol
, struct symhash
*symbols
);
33 extern char *directives
[];
34 extern struct symhash
*maininclist
;
36 int find_includes(filep
, file
, file_red
, recursion
, failOK
, incCollection
, symbols
)
37 struct filepointer
*filep
;
38 struct inclist
*file
, *file_red
;
41 struct IncludesCollection
* incCollection
;
42 struct symhash
*symbols
;
48 while ((line
= get_line(filep
))) {
49 switch(type
= deftype(line
, filep
, file_red
, file
, TRUE
, symbols
)) {
52 type
= find_includes(filep
, file
,
53 file_red
, recursion
+1, failOK
, incCollection
, symbols
);
54 while ((type
== ELIF
) || (type
== ELIFFALSE
) ||
55 (type
== ELIFGUESSFALSE
))
56 type
= gobble(filep
, file
, file_red
, symbols
);
58 gobble(filep
, file
, file_red
, symbols
);
63 if (type
== IFGUESSFALSE
|| type
== ELIFGUESSFALSE
)
67 type
= gobble(filep
, file
, file_red
, symbols
);
69 find_includes(filep
, file
,
70 file_red
, recursion
+1, recfailOK
, incCollection
, symbols
);
75 if ((type
== ELIFFALSE
) || (type
== ELIFGUESSFALSE
))
80 if ((type
== IFDEF
&& hash_lookup(line
, symbols
))
81 || (type
== IFNDEF
&& !hash_lookup(line
, symbols
))) {
82 debug(1,(type
== IFNDEF
?
83 "line %d: %s !def'd in %s via %s%s\n" : "",
85 file
->i_file
, file_red
->i_file
, ": doit"));
86 type
= find_includes(filep
, file
,
87 file_red
, recursion
+1, failOK
, incCollection
, symbols
);
88 while (type
== ELIF
|| type
== ELIFFALSE
|| type
== ELIFGUESSFALSE
)
89 type
= gobble(filep
, file
, file_red
, symbols
);
91 gobble(filep
, file
, file_red
, symbols
);
94 debug(1,(type
== IFDEF
?
95 "line %d: %s !def'd in %s via %s%s\n" : "",
97 file
->i_file
, file_red
->i_file
, ": gobble"));
98 type
= gobble(filep
, file
, file_red
, symbols
);
100 find_includes(filep
, file
,
101 file_red
, recursion
+ 1, failOK
, incCollection
, symbols
);
102 else if (type
== ELIF
)
104 else if (type
== ELIFFALSE
|| type
== ELIFGUESSFALSE
)
113 gobble(filep
, file
, file_red
, symbols
);
118 define(line
, &symbols
);
122 warning("%s, line %d: incomplete undef == \"%s\"\n",
123 file_red
->i_file
, filep
->f_line
, line
);
126 hash_undefine(line
, symbols
);
129 add_include(filep
, file
, file_red
, line
, FALSE
, failOK
, incCollection
, symbols
);
132 add_include(filep
, file
, file_red
, line
, TRUE
, failOK
, incCollection
, symbols
);
135 warning("%s: %d: %s\n", file_red
->i_file
,
136 filep
->f_line
, line
);
145 warning("%s", file_red
->i_file
);
146 if (file_red
!= file
)
147 warning1(" (reading %s)", file
->i_file
);
148 warning1(", line %d: unknown directive == \"%s\"\n",
149 filep
->f_line
, line
);
152 warning("%s", file_red
->i_file
);
153 if (file_red
!= file
)
154 warning1(" (reading %s)", file
->i_file
);
155 warning1(", line %d: incomplete include == \"%s\"\n",
156 filep
->f_line
, line
);
163 int gobble(filep
, file
, file_red
, symbols
)
164 register struct filepointer
*filep
;
165 struct inclist
*file
, *file_red
;
166 struct symhash
*symbols
;
171 while ((line
= get_line(filep
))) {
172 switch(type
= deftype(line
, filep
, file_red
, file
, FALSE
, symbols
)) {
178 type
= gobble(filep
, file
, file_red
, symbols
);
179 while ((type
== ELIF
) || (type
== ELIFFALSE
) ||
180 (type
== ELIFGUESSFALSE
))
181 type
= gobble(filep
, file
, file_red
, symbols
);
183 (void)gobble(filep
, file
, file_red
, symbols
);
187 debug(0,("%s, line %d: #%s\n",
188 file
->i_file
, filep
->f_line
,
206 warning("%s, line %d: unknown directive == \"%s\"\n",
207 file_red
->i_file
, filep
->f_line
, line
);
215 * Decide what type of # directive this line is.
217 int deftype (line
, filep
, file_red
, file
, parse_it
, symbols
)
219 register struct filepointer
*filep
;
220 register struct inclist
*file_red
, *file
;
222 struct symhash
*symbols
;
225 char *directive
, savechar
;
229 * Parse the directive...
232 while (*directive
== ' ' || *directive
== '\t')
236 while (*p
>= 'a' && *p
<= 'z')
240 ret
= match(directive
, directives
);
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.
249 if (ret
== ELIF
&& !parse_it
)
251 while (*p
== ' ' || *p
== '\t')
254 * parse an expression.
256 debug(0,("%s, line %d: #elif %s ",
257 file
->i_file
, filep
->f_line
, p
));
258 ret
= zero_value(p
, filep
, file_red
, symbols
);
261 debug(0,("false...\n"));
265 return(ELIFGUESSFALSE
);
269 debug(0,("true...\n"));
274 if (ret
< 0 || ! parse_it
)
278 * now decide how to parse the directive, and do it.
280 while (*p
== ' ' || *p
== '\t')
285 * parse an expression.
287 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
));
293 debug(0,("%s, line %d: #%s %s\n",
294 file
->i_file
, filep
->f_line
, directives
[ret
], p
));
297 * separate the name of a single symbol.
299 while (isalnum(*p
) || *p
== '_')
304 debug(2,("%s, line %d: #include %s\n",
305 file
->i_file
, filep
->f_line
, p
));
307 /* Support ANSI macro substitution */
309 char *sym
= hash_lookup(p
, symbols
);
313 debug(3,("%s : #includes SYMBOL %s\n",
316 /* mark file as having included a 'soft include' */
317 file
->i_included_sym
= TRUE
;
318 sym
= hash_lookup(p
, symbols
);
323 * Separate the name of the include file.
325 while (*p
&& *p
!= '"' && *p
!= '<')
331 while (*p
&& *p
!= '"')
334 while (*p
&& *p
!= '>')
340 * copy the definition back to the beginning of the line.
352 debug(0,("%s, line %d: #%s\n",
353 file
->i_file
, filep
->f_line
, directives
[ret
]));
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.
366 struct symhash
*global_symbols
= NULL
;
368 char * isdefined( symbol
)
369 register char *symbol
;
371 return hash_lookup( symbol
, global_symbols
);
375 * Return type based on if the #if expression evaluates to 0
377 int zero_value(exp
, filep
, file_red
, symbols
)
379 register struct filepointer
*filep
;
380 register struct inclist
*file_red
;
381 register struct symhash
*symbols
;
383 global_symbols
= symbols
; /* HACK! see above */
384 if (cppsetup(exp
, filep
, file_red
))
390 void define( def
, symbols
)
392 struct symhash
**symbols
;
396 /* Separate symbol name and its value */
398 while (isalnum(*val
) || *val
== '_')
402 while (*val
== ' ' || *val
== '\t')
407 hash_define( def
, val
, symbols
);
410 static int hash( str
)
413 /* Hash (Kernighan and Ritchie) */
414 register unsigned int hashval
= 0;
415 register unsigned int i
= 0;
418 for ( ; *str
; str
++ )
420 hashval
= ( hashval
* SYMHASHSEED
) + ( *str
);
423 //fprintf( stderr, "hash: %s, %d\n", s, hashval & ( SYMHASHMEMBERS - 1 ) );
424 return hashval
& ( SYMHASHMEMBERS
- 1 );
427 struct symhash
*hash_copy( symbols
)
428 struct symhash
*symbols
;
431 struct symhash
*newsym
;
435 newsym
= (struct symhash
*) malloc( sizeof( struct symhash
) );
437 for ( i
= 0; i
< SYMHASHMEMBERS
; ++i
)
439 if ( !symbols
->s_pairs
[ i
] )
440 newsym
->s_pairs
[ i
] = NULL
;
443 struct pair
*it
= symbols
->s_pairs
[ i
];
444 struct pair
*nw
= newsym
->s_pairs
[ i
] = (struct pair
*) malloc( sizeof( struct pair
) );
445 nw
->p_name
= it
->p_name
;
446 nw
->p_value
= it
->p_value
;
451 nw
->p_next
= (struct pair
*) malloc( sizeof( struct pair
) );
454 nw
->p_name
= it
->p_name
;
455 nw
->p_value
= it
->p_value
;
463 void hash_free( symbols
)
464 struct symhash
*symbols
;
471 for ( i
= 0; i
< SYMHASHMEMBERS
; ++i
)
473 struct pair
*it
= symbols
->s_pairs
[ i
];
482 free( symbols
->s_pairs
);
485 void hash_define( name
, val
, symbols
)
487 struct symhash
**symbols
;
495 /* Make space if it's needed */
496 if ( *symbols
== NULL
)
500 *symbols
= (struct symhash
*) malloc( sizeof( struct symhash
) );
501 if ( *symbols
== NULL
)
502 fatalerr( "malloc()/realloc() failure in insert_defn()\n" );
504 for ( i
= 0; i
< SYMHASHMEMBERS
; ++i
)
505 (*symbols
)->s_pairs
[i
] = NULL
;
508 hashval
= hash( name
);
509 it
= (*symbols
)->s_pairs
[ hashval
];
511 /* Replace/insert the symbol */
514 it
= (*symbols
)->s_pairs
[ hashval
] = (struct pair
*) malloc( sizeof( struct pair
) );
515 it
->p_name
= copy( name
);
516 it
->p_value
= copy( val
);
519 else if ( strcmp( it
->p_name
, name
) == 0 )
521 it
->p_value
= copy( val
);
525 while ( it
->p_next
&& ( strcmp( it
->p_next
->p_name
, name
) != 0 ) )
530 it
->p_next
->p_name
= copy( name
);
533 it
->p_next
= (struct pair
*) malloc( sizeof( struct pair
) );
534 it
->p_next
->p_name
= copy( name
);
535 it
->p_next
->p_value
= copy( val
);
536 it
->p_next
->p_next
= NULL
;
541 char *hash_lookup( symbol
, symbols
)
543 struct symhash
*symbols
;
550 it
= symbols
->s_pairs
[ hash( symbol
) ];
552 while ( it
&& ( strcmp( it
->p_name
, symbol
) != 0 ) )
562 void hash_undefine( symbol
, symbols
)
564 struct symhash
*symbols
;
572 hashval
= hash( symbol
);
573 it
= symbols
->s_pairs
[ hashval
];
575 /* Replace/insert the symbol */
578 else if ( strcmp( it
->p_name
, symbol
) == 0 )
583 it
->p_name
= it
->p_next
->p_name
;
584 it
->p_value
= it
->p_next
->p_value
;
585 tmp
= it
->p_next
->p_next
;
592 symbols
->s_pairs
[ hashval
] = NULL
;
597 while ( it
->p_next
&& ( strcmp( it
->p_next
->p_name
, symbol
) != 0 ) )
603 struct pair
*tmp
= it
->p_next
;
604 it
->p_next
= it
->p_next
->p_next
;