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 $ */
5 Copyright (c) 1993, 1994 X Consortium
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:
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
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.
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.
31 char *hash_lookup( char *symbol
, struct symhash
*symbols
);
32 void hash_undefine( char *symbol
, struct symhash
*symbols
);
33 int gobble( struct filepointer
*filep
, struct inclist
*file
,
34 struct inclist
*file_red
, struct symhash
*symbols
);
35 int deftype ( char *line
, struct filepointer
*filep
,
36 struct inclist
*file_red
, struct inclist
*file
,
37 int parse_it
, struct symhash
*symbols
);
38 int zero_value(char *exp
, struct filepointer
*filep
,
39 struct inclist
*file_red
, struct symhash
*symbols
);
41 extern char *directives
[];
42 extern struct symhash
*maininclist
;
44 int find_includes(struct filepointer
*filep
, struct inclist
*file
, struct inclist
*file_red
, int recursion
, boolean failOK
, struct IncludesCollection
* incCollection
, struct symhash
*symbols
)
50 while ((line
= get_line(filep
))) {
51 switch(type
= deftype(line
, filep
, file_red
, file
, TRUE
, symbols
)) {
54 type
= find_includes(filep
, file
,
55 file_red
, recursion
+1, failOK
, incCollection
, symbols
);
56 while ((type
== ELIF
) || (type
== ELIFFALSE
) ||
57 (type
== ELIFGUESSFALSE
))
58 type
= gobble(filep
, file
, file_red
, symbols
);
60 gobble(filep
, file
, file_red
, symbols
);
65 if (type
== IFGUESSFALSE
|| type
== ELIFGUESSFALSE
)
69 type
= gobble(filep
, file
, file_red
, symbols
);
71 find_includes(filep
, file
,
72 file_red
, recursion
+1, recfailOK
, incCollection
, symbols
);
73 else if (type
== ELIF
)
75 else 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
);
120 define(line
, &symbols
);
124 warning("%s, line %d: incomplete undef == \"%s\"\n",
125 file_red
->i_file
, filep
->f_line
, line
);
128 hash_undefine(line
, symbols
);
131 add_include(filep
, file
, file_red
, line
, FALSE
, failOK
, incCollection
, symbols
);
134 add_include(filep
, file
, file_red
, line
, TRUE
, failOK
, incCollection
, symbols
);
137 warning("%s: %d: %s\n", file_red
->i_file
,
138 filep
->f_line
, line
);
147 warning("%s", file_red
->i_file
);
148 if (file_red
!= file
)
149 warning1(" (reading %s)", file
->i_file
);
150 warning1(", line %d: unknown directive == \"%s\"\n",
151 filep
->f_line
, line
);
154 warning("%s", file_red
->i_file
);
155 if (file_red
!= file
)
156 warning1(" (reading %s)", file
->i_file
);
157 warning1(", line %d: incomplete include == \"%s\"\n",
158 filep
->f_line
, line
);
165 int gobble(struct filepointer
*filep
,
166 struct inclist
*file
,
167 struct inclist
*file_red
,
168 struct symhash
*symbols
)
173 while ((line
= get_line(filep
))) {
174 switch(type
= deftype(line
, filep
, file_red
, file
, FALSE
, symbols
)) {
180 type
= gobble(filep
, file
, file_red
, symbols
);
181 while ((type
== ELIF
) || (type
== ELIFFALSE
) ||
182 (type
== ELIFGUESSFALSE
))
183 type
= gobble(filep
, file
, file_red
, symbols
);
185 (void)gobble(filep
, file
, file_red
, symbols
);
189 debug(0,("%s, line %d: #%s\n",
190 file
->i_file
, filep
->f_line
,
208 warning("%s, line %d: unknown directive == \"%s\"\n",
209 file_red
->i_file
, filep
->f_line
, line
);
217 * Decide what type of # directive this line is.
219 int deftype (char *line
, struct filepointer
*filep
, struct inclist
*file_red
, struct inclist
*file
, int parse_it
, struct symhash
*symbols
)
222 char *directive
, savechar
;
226 * Parse the directive...
229 while (*directive
== ' ' || *directive
== '\t')
233 while (*p
>= 'a' && *p
<= 'z')
237 ret
= match(directive
, directives
);
240 /* If we don't recognize this compiler directive or we happen to just
241 * be gobbling up text while waiting for an #endif or #elif or #else
242 * in the case of an #elif we must check the zero_value and return an
243 * ELIF or an ELIFFALSE.
246 if (ret
== ELIF
&& !parse_it
)
248 while (*p
== ' ' || *p
== '\t')
251 * parse an expression.
253 debug(0,("%s, line %d: #elif %s ",
254 file
->i_file
, filep
->f_line
, p
));
255 ret
= zero_value(p
, filep
, file_red
, symbols
);
258 debug(0,("false...\n"));
262 return ELIFGUESSFALSE
;
266 debug(0,("true...\n"));
271 if (ret
< 0 || ! parse_it
)
275 * now decide how to parse the directive, and do it.
277 while (*p
== ' ' || *p
== '\t')
282 * parse an expression.
284 ret
= zero_value(p
, filep
, file_red
, symbols
);
285 debug(0,("%s, line %d: %s #if %s\n",
286 file
->i_file
, filep
->f_line
, ret
?"false":"true", p
));
290 debug(0,("%s, line %d: #%s %s\n",
291 file
->i_file
, filep
->f_line
, directives
[ret
], p
));
295 * separate the name of a single symbol.
297 while (isalnum(*p
) || *p
== '_')
302 debug(2,("%s, line %d: #include %s\n",
303 file
->i_file
, filep
->f_line
, p
));
305 /* Support ANSI macro substitution */
307 char *sym
= hash_lookup(p
, symbols
);
311 debug(3,("%s : #includes SYMBOL %s\n",
314 /* mark file as having included a 'soft include' */
315 file
->i_included_sym
= TRUE
;
316 sym
= hash_lookup(p
, symbols
);
321 * Separate the name of the include file.
323 while (*p
&& *p
!= '"' && *p
!= '<')
329 while (*p
&& *p
!= '"')
332 while (*p
&& *p
!= '>')
338 * copy the definition back to the beginning of the line.
340 memmove (line
, p
, strlen(p
));
350 debug(0,("%s, line %d: #%s\n",
351 file
->i_file
, filep
->f_line
, directives
[ret
]));
361 * HACK! - so that we do not have to introduce 'symbols' in each cppsetup.c
362 * function... It's safe, functions from cppsetup.c don't return here.
364 struct symhash
*global_symbols
= NULL
;
366 char * isdefined( char *symbol
)
368 return hash_lookup( symbol
, global_symbols
);
372 * Return type based on if the #if expression evaluates to 0
374 int zero_value(char *exp
, struct filepointer
*filep
, struct inclist
*file_red
, struct symhash
*symbols
)
376 global_symbols
= symbols
; /* HACK! see above */
377 if (cppsetup(exp
, filep
, file_red
))
383 void define( char *def
, struct symhash
**symbols
)
387 /* Separate symbol name and its value */
389 while (isalnum(*val
) || *val
== '_')
393 while (*val
== ' ' || *val
== '\t')
398 hash_define( def
, val
, symbols
);
401 static int hash( char *str
)
403 /* Hash (Kernighan and Ritchie) */
404 unsigned int hashval
= 0;
406 for ( ; *str
; str
++ )
408 hashval
= ( hashval
* SYMHASHSEED
) + ( *str
);
411 return hashval
& ( SYMHASHMEMBERS
- 1 );
414 struct symhash
*hash_copy( struct symhash
*symbols
)
417 struct symhash
*newsym
;
421 newsym
= (struct symhash
*) malloc( sizeof( struct symhash
) );
423 for ( i
= 0; i
< SYMHASHMEMBERS
; ++i
)
425 if ( !symbols
->s_pairs
[ i
] )
426 newsym
->s_pairs
[ i
] = NULL
;
429 struct pair
*it
= symbols
->s_pairs
[ i
];
430 struct pair
*nw
= newsym
->s_pairs
[ i
] = (struct pair
*) malloc( sizeof( struct pair
) );
431 nw
->p_name
= it
->p_name
;
432 nw
->p_value
= it
->p_value
;
437 nw
->p_next
= (struct pair
*) malloc( sizeof( struct pair
) );
440 nw
->p_name
= it
->p_name
;
441 nw
->p_value
= it
->p_value
;
449 void hash_free( struct symhash
*symbols
)
456 for ( i
= 0; i
< SYMHASHMEMBERS
; ++i
)
458 struct pair
*it
= symbols
->s_pairs
[ i
];
467 free( symbols
->s_pairs
);
470 void hash_define( char *name
, char *val
, struct symhash
**symbols
)
478 /* Make space if it's needed */
479 if ( *symbols
== NULL
)
483 *symbols
= (struct symhash
*) malloc( sizeof( struct symhash
) );
484 if ( *symbols
== NULL
)
485 fatalerr( "malloc()/realloc() failure in insert_defn()\n" );
487 for ( i
= 0; i
< SYMHASHMEMBERS
; ++i
)
488 (*symbols
)->s_pairs
[i
] = NULL
;
491 hashval
= hash( name
);
492 it
= (*symbols
)->s_pairs
[ hashval
];
494 /* Replace/insert the symbol */
497 it
= (*symbols
)->s_pairs
[ hashval
] = (struct pair
*) malloc( sizeof( struct pair
) );
498 it
->p_name
= copy( name
);
499 it
->p_value
= copy( val
);
502 else if ( strcmp( it
->p_name
, name
) == 0 )
504 it
->p_value
= copy( val
);
508 while ( it
->p_next
&& ( strcmp( it
->p_next
->p_name
, name
) != 0 ) )
513 it
->p_next
->p_name
= copy( name
);
516 it
->p_next
= (struct pair
*) malloc( sizeof( struct pair
) );
517 it
->p_next
->p_name
= copy( name
);
518 it
->p_next
->p_value
= copy( val
);
519 it
->p_next
->p_next
= NULL
;
524 char *hash_lookup( char *symbol
, struct symhash
*symbols
)
531 it
= symbols
->s_pairs
[ hash( symbol
) ];
533 while ( it
&& ( strcmp( it
->p_name
, symbol
) != 0 ) )
543 void hash_undefine( char *symbol
, struct symhash
*symbols
)
551 hashval
= hash( symbol
);
552 it
= symbols
->s_pairs
[ hashval
];
554 /* Replace/insert the symbol */
557 else if ( strcmp( it
->p_name
, symbol
) == 0 )
562 it
->p_name
= it
->p_next
->p_name
;
563 it
->p_value
= it
->p_next
->p_value
;
564 tmp
= it
->p_next
->p_next
;
571 symbols
->s_pairs
[ hashval
] = NULL
;
576 while ( it
->p_next
&& ( strcmp( it
->p_next
->p_name
, symbol
) != 0 ) )
582 struct pair
*tmp
= it
->p_next
;
583 it
->p_next
= it
->p_next
->p_next
;
589 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */