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( 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
);
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
);
77 if ((type
== ELIFFALSE
) || (type
== ELIFGUESSFALSE
))
82 if ((type
== IFDEF
&& hash_lookup(line
, symbols
))
83 || (type
== IFNDEF
&& !hash_lookup(line
, symbols
))) {
84 debug(1,(type
== IFNDEF
?
85 "line %d: %s !def'd in %s via %s%s\n" : "",
87 file
->i_file
, file_red
->i_file
, ": doit"));
88 type
= find_includes(filep
, file
,
89 file_red
, recursion
+1, failOK
, incCollection
, symbols
);
90 while (type
== ELIF
|| type
== ELIFFALSE
|| type
== ELIFGUESSFALSE
)
91 type
= gobble(filep
, file
, file_red
, symbols
);
93 gobble(filep
, file
, file_red
, symbols
);
96 debug(1,(type
== IFDEF
?
97 "line %d: %s !def'd in %s via %s%s\n" : "",
99 file
->i_file
, file_red
->i_file
, ": gobble"));
100 type
= gobble(filep
, file
, file_red
, symbols
);
102 find_includes(filep
, file
,
103 file_red
, recursion
+ 1, failOK
, incCollection
, symbols
);
104 else if (type
== ELIF
)
106 else if (type
== ELIFFALSE
|| type
== ELIFGUESSFALSE
)
115 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(filep
, file
, file_red
, symbols
)
166 register struct filepointer
*filep
;
167 struct inclist
*file
, *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 (line
, filep
, file_red
, file
, parse_it
, symbols
)
221 register struct filepointer
*filep
;
222 register struct inclist
*file_red
, *file
;
224 struct symhash
*symbols
;
227 char *directive
, savechar
;
231 * Parse the directive...
234 while (*directive
== ' ' || *directive
== '\t')
238 while (*p
>= 'a' && *p
<= 'z')
242 ret
= match(directive
, directives
);
245 /* If we don't recognize this compiler directive or we happen to just
246 * be gobbling up text while waiting for an #endif or #elif or #else
247 * in the case of an #elif we must check the zero_value and return an
248 * ELIF or an ELIFFALSE.
251 if (ret
== ELIF
&& !parse_it
)
253 while (*p
== ' ' || *p
== '\t')
256 * parse an expression.
258 debug(0,("%s, line %d: #elif %s ",
259 file
->i_file
, filep
->f_line
, p
));
260 ret
= zero_value(p
, filep
, file_red
, symbols
);
263 debug(0,("false...\n"));
267 return(ELIFGUESSFALSE
);
271 debug(0,("true...\n"));
276 if (ret
< 0 || ! parse_it
)
280 * now decide how to parse the directive, and do it.
282 while (*p
== ' ' || *p
== '\t')
287 * parse an expression.
289 ret
= zero_value(p
, filep
, file_red
, symbols
);
290 debug(0,("%s, line %d: %s #if %s\n",
291 file
->i_file
, filep
->f_line
, ret
?"false":"true", p
));
295 debug(0,("%s, line %d: #%s %s\n",
296 file
->i_file
, filep
->f_line
, directives
[ret
], p
));
299 * separate the name of a single symbol.
301 while (isalnum(*p
) || *p
== '_')
306 debug(2,("%s, line %d: #include %s\n",
307 file
->i_file
, filep
->f_line
, p
));
309 /* Support ANSI macro substitution */
311 char *sym
= hash_lookup(p
, symbols
);
315 debug(3,("%s : #includes SYMBOL %s\n",
318 /* mark file as having included a 'soft include' */
319 file
->i_included_sym
= TRUE
;
320 sym
= hash_lookup(p
, symbols
);
325 * Separate the name of the include file.
327 while (*p
&& *p
!= '"' && *p
!= '<')
333 while (*p
&& *p
!= '"')
336 while (*p
&& *p
!= '>')
342 * copy the definition back to the beginning of the line.
344 memmove (line
, p
, strlen(p
));
354 debug(0,("%s, line %d: #%s\n",
355 file
->i_file
, filep
->f_line
, directives
[ret
]));
365 * HACK! - so that we do not have to introduce 'symbols' in each cppsetup.c
366 * function... It's safe, functions from cppsetup.c don't return here.
368 struct symhash
*global_symbols
= NULL
;
370 char * isdefined( symbol
)
371 register char *symbol
;
373 return hash_lookup( symbol
, global_symbols
);
377 * Return type based on if the #if expression evaluates to 0
379 int zero_value(exp
, filep
, file_red
, symbols
)
381 register struct filepointer
*filep
;
382 register struct inclist
*file_red
;
383 register struct symhash
*symbols
;
385 global_symbols
= symbols
; /* HACK! see above */
386 if (cppsetup(exp
, filep
, file_red
))
392 void define( def
, symbols
)
394 struct symhash
**symbols
;
398 /* Separate symbol name and its value */
400 while (isalnum(*val
) || *val
== '_')
404 while (*val
== ' ' || *val
== '\t')
409 hash_define( def
, val
, symbols
);
412 static int hash( str
)
415 /* Hash (Kernighan and Ritchie) */
416 register unsigned int hashval
= 0;
418 for ( ; *str
; str
++ )
420 hashval
= ( hashval
* SYMHASHSEED
) + ( *str
);
423 return hashval
& ( SYMHASHMEMBERS
- 1 );
426 struct symhash
*hash_copy( symbols
)
427 struct symhash
*symbols
;
430 struct symhash
*newsym
;
434 newsym
= (struct symhash
*) malloc( sizeof( struct symhash
) );
436 for ( i
= 0; i
< SYMHASHMEMBERS
; ++i
)
438 if ( !symbols
->s_pairs
[ i
] )
439 newsym
->s_pairs
[ i
] = NULL
;
442 struct pair
*it
= symbols
->s_pairs
[ i
];
443 struct pair
*nw
= newsym
->s_pairs
[ i
] = (struct pair
*) malloc( sizeof( struct pair
) );
444 nw
->p_name
= it
->p_name
;
445 nw
->p_value
= it
->p_value
;
450 nw
->p_next
= (struct pair
*) malloc( sizeof( struct pair
) );
453 nw
->p_name
= it
->p_name
;
454 nw
->p_value
= it
->p_value
;
462 void hash_free( symbols
)
463 struct symhash
*symbols
;
470 for ( i
= 0; i
< SYMHASHMEMBERS
; ++i
)
472 struct pair
*it
= symbols
->s_pairs
[ i
];
481 free( symbols
->s_pairs
);
484 void hash_define( name
, val
, symbols
)
486 struct symhash
**symbols
;
494 /* Make space if it's needed */
495 if ( *symbols
== NULL
)
499 *symbols
= (struct symhash
*) malloc( sizeof( struct symhash
) );
500 if ( *symbols
== NULL
)
501 fatalerr( "malloc()/realloc() failure in insert_defn()\n" );
503 for ( i
= 0; i
< SYMHASHMEMBERS
; ++i
)
504 (*symbols
)->s_pairs
[i
] = NULL
;
507 hashval
= hash( name
);
508 it
= (*symbols
)->s_pairs
[ hashval
];
510 /* Replace/insert the symbol */
513 it
= (*symbols
)->s_pairs
[ hashval
] = (struct pair
*) malloc( sizeof( struct pair
) );
514 it
->p_name
= copy( name
);
515 it
->p_value
= copy( val
);
518 else if ( strcmp( it
->p_name
, name
) == 0 )
520 it
->p_value
= copy( val
);
524 while ( it
->p_next
&& ( strcmp( it
->p_next
->p_name
, name
) != 0 ) )
529 it
->p_next
->p_name
= copy( name
);
532 it
->p_next
= (struct pair
*) malloc( sizeof( struct pair
) );
533 it
->p_next
->p_name
= copy( name
);
534 it
->p_next
->p_value
= copy( val
);
535 it
->p_next
->p_next
= NULL
;
540 char *hash_lookup( symbol
, symbols
)
542 struct symhash
*symbols
;
549 it
= symbols
->s_pairs
[ hash( symbol
) ];
551 while ( it
&& ( strcmp( it
->p_name
, symbol
) != 0 ) )
561 void hash_undefine( symbol
, symbols
)
563 struct symhash
*symbols
;
571 hashval
= hash( symbol
);
572 it
= symbols
->s_pairs
[ hashval
];
574 /* Replace/insert the symbol */
577 else if ( strcmp( it
->p_name
, symbol
) == 0 )
582 it
->p_name
= it
->p_next
->p_name
;
583 it
->p_value
= it
->p_next
->p_value
;
584 tmp
= it
->p_next
->p_next
;
591 symbols
->s_pairs
[ hashval
] = NULL
;
596 while ( it
->p_next
&& ( strcmp( it
->p_next
->p_name
, symbol
) != 0 ) )
602 struct pair
*tmp
= it
->p_next
;
603 it
->p_next
= it
->p_next
->p_next
;
609 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */