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.
33 char *hash_lookup( char *symbol
, struct symhash
*symbols
);
34 void hash_undefine( char *symbol
, struct symhash
*symbols
);
35 int gobble( struct filepointer
*filep
, struct inclist
*file
,
36 struct inclist
*file_red
, struct symhash
*symbols
);
37 int deftype ( char *line
, struct filepointer
*filep
, struct inclist
*file
,
38 int parse_it
, struct symhash
*symbols
);
39 int zero_value(char const *exp
, struct symhash
*symbols
);
41 extern struct symhash
*maininclist
;
43 int find_includes(struct filepointer
*filep
, struct inclist
*file
, struct inclist
*file_red
, int recursion
, boolean failOK
, struct IncludesCollection
* incCollection
, struct symhash
*symbols
)
49 while ((line
= get_line(filep
))) {
50 switch(type
= deftype(line
, filep
, file
, TRUE
, symbols
)) {
53 type
= find_includes(filep
, file
,
54 file_red
, recursion
+1, failOK
, incCollection
, symbols
);
55 while ((type
== ELIF
) || (type
== ELIFFALSE
) ||
56 (type
== ELIFGUESSFALSE
))
57 type
= gobble(filep
, file
, file_red
, symbols
);
59 gobble(filep
, file
, file_red
, symbols
);
64 if (type
== IFGUESSFALSE
|| type
== ELIFGUESSFALSE
)
68 type
= gobble(filep
, file
, file_red
, symbols
);
70 find_includes(filep
, file
,
71 file_red
, recursion
+1, recfailOK
, incCollection
, symbols
);
72 else if (type
== ELIF
)
74 else if ((type
== ELIFFALSE
) || (type
== ELIFGUESSFALSE
))
79 if ((type
== IFDEF
&& hash_lookup(line
, symbols
))
80 || (type
== IFNDEF
&& !hash_lookup(line
, symbols
))) {
81 debug(1,(type
== IFNDEF
?
82 "line %d: %s !def'd in %s via %s%s\n" : "",
84 file
->i_file
, file_red
->i_file
, ": doit"));
85 type
= find_includes(filep
, file
,
86 file_red
, recursion
+1, failOK
, incCollection
, symbols
);
87 while (type
== ELIF
|| type
== ELIFFALSE
|| type
== ELIFGUESSFALSE
)
88 type
= gobble(filep
, file
, file_red
, symbols
);
90 gobble(filep
, file
, file_red
, symbols
);
93 debug(1,(type
== IFDEF
?
94 "line %d: %s !def'd in %s via %s%s\n" : "",
96 file
->i_file
, file_red
->i_file
, ": gobble"));
97 type
= gobble(filep
, file
, file_red
, symbols
);
99 find_includes(filep
, file
,
100 file_red
, recursion
+ 1, failOK
, incCollection
, symbols
);
101 else if (type
== ELIF
)
103 else if (type
== ELIFFALSE
|| type
== ELIFGUESSFALSE
)
112 gobble(filep
, file
, file_red
, symbols
);
119 define(line
, &symbols
);
123 warning("%s, line %d: incomplete undef == \"%s\"\n",
124 file_red
->i_file
, filep
->f_line
, line
);
127 hash_undefine(line
, symbols
);
130 add_include(filep
, file
, file_red
, line
, FALSE
, failOK
, incCollection
, symbols
);
133 add_include(filep
, file
, file_red
, line
, TRUE
, failOK
, incCollection
, symbols
);
136 warning("%s: %d: %s\n", file_red
->i_file
,
137 filep
->f_line
, line
);
146 warning("%s", file_red
->i_file
);
147 if (file_red
!= file
)
148 warning1(" (reading %s)", file
->i_file
);
149 warning1(", line %d: unknown directive == \"%s\"\n",
150 filep
->f_line
, line
);
153 warning("%s", file_red
->i_file
);
154 if (file_red
!= file
)
155 warning1(" (reading %s)", file
->i_file
);
156 warning1(", line %d: incomplete include == \"%s\"\n",
157 filep
->f_line
, line
);
164 int gobble(struct filepointer
*filep
,
165 struct inclist
*file
,
166 struct inclist
*file_red
,
167 struct symhash
*symbols
)
172 while ((line
= get_line(filep
))) {
173 switch(type
= deftype(line
, filep
, file
, FALSE
, symbols
)) {
179 type
= gobble(filep
, file
, file_red
, symbols
);
180 while ((type
== ELIF
) || (type
== ELIFFALSE
) ||
181 (type
== ELIFGUESSFALSE
))
182 type
= gobble(filep
, file
, file_red
, symbols
);
184 (void)gobble(filep
, file
, file_red
, symbols
);
188 debug(0,("%s, line %d: #%s\n",
189 file
->i_file
, filep
->f_line
,
207 warning("%s, line %d: unknown directive == \"%s\"\n",
208 file_red
->i_file
, filep
->f_line
, line
);
216 * Decide what type of # directive this line is.
218 int deftype (char *line
, struct filepointer
*filep
, struct inclist
*file
, int parse_it
, struct symhash
*symbols
)
221 char *directive
, savechar
;
225 * Parse the directive...
228 while (*directive
== ' ' || *directive
== '\t')
232 while (*p
>= 'a' && *p
<= 'z')
236 ret
= match(directive
, directives
);
239 /* If we don't recognize this compiler directive or we happen to just
240 * be gobbling up text while waiting for an #endif or #elif or #else
241 * in the case of an #elif we must check the zero_value and return an
242 * ELIF or an ELIFFALSE.
245 if (ret
== ELIF
&& !parse_it
)
247 while (*p
== ' ' || *p
== '\t')
250 * parse an expression.
252 debug(0,("%s, line %d: #elif %s ",
253 file
->i_file
, filep
->f_line
, p
));
254 ret
= zero_value(p
, symbols
);
257 debug(0,("false...\n"));
261 return ELIFGUESSFALSE
;
265 debug(0,("true...\n"));
270 if (ret
< 0 || ! parse_it
)
274 * now decide how to parse the directive, and do it.
276 while (*p
== ' ' || *p
== '\t')
281 * parse an expression.
283 ret
= zero_value(p
, symbols
);
284 debug(0,("%s, line %d: %s #if %s\n",
285 file
->i_file
, filep
->f_line
, ret
?"false":"true", p
));
289 debug(0,("%s, line %d: #%s %s\n",
290 file
->i_file
, filep
->f_line
, directives
[ret
], p
));
294 * separate the name of a single symbol.
296 while (isalnum((unsigned char)*p
) || *p
== '_')
301 debug(2,("%s, line %d: #include %s\n",
302 file
->i_file
, filep
->f_line
, p
));
304 /* Support ANSI macro substitution */
306 char *sym
= hash_lookup(p
, symbols
);
310 debug(3,("%s : #includes SYMBOL %s\n",
313 /* mark file as having included a 'soft include' */
314 file
->i_included_sym
= TRUE
;
315 sym
= hash_lookup(p
, symbols
);
320 * Separate the name of the include file.
322 while (*p
&& *p
!= '"' && *p
!= '<')
328 while (*p
&& *p
!= '"')
331 while (*p
&& *p
!= '>')
337 * copy the definition back to the beginning of the line.
339 memmove (line
, p
, strlen(p
));
349 debug(0,("%s, line %d: #%s\n",
350 file
->i_file
, filep
->f_line
, directives
[ret
]));
360 * HACK! - so that we do not have to introduce 'symbols' in each cppsetup.c
361 * function... It's safe, functions from cppsetup.c don't return here.
363 static struct symhash
*global_symbols
= NULL
;
365 char * isdefined( char *symbol
)
367 return hash_lookup( symbol
, global_symbols
);
371 * Return type based on if the #if expression evaluates to 0
373 int zero_value(char const *exp
, struct symhash
*symbols
)
375 global_symbols
= symbols
; /* HACK! see above */
382 void define( char *def
, struct symhash
**symbols
)
386 /* Separate symbol name and its value */
388 while (isalnum((unsigned char)*val
) || *val
== '_')
392 while (*val
== ' ' || *val
== '\t')
397 hash_define( def
, val
, symbols
);
400 static int hash( char *str
)
402 /* Hash (Kernighan and Ritchie) */
403 unsigned int hashval
= 0;
405 for ( ; *str
; str
++ )
407 hashval
= ( hashval
* SYMHASHSEED
) + ( *str
);
410 return hashval
& ( SYMHASHMEMBERS
- 1 );
413 struct symhash
*hash_copy( struct symhash
*symbols
)
416 struct symhash
*newsym
;
420 newsym
= (struct symhash
*) malloc( sizeof( struct symhash
) );
422 for ( i
= 0; i
< SYMHASHMEMBERS
; ++i
)
424 if ( !symbols
->s_pairs
[ i
] )
425 newsym
->s_pairs
[ i
] = NULL
;
428 struct pair
*it
= symbols
->s_pairs
[ i
];
429 struct pair
*nw
= newsym
->s_pairs
[ i
] = (struct pair
*) malloc( sizeof( struct pair
) );
430 nw
->p_name
= it
->p_name
;
431 nw
->p_value
= it
->p_value
;
436 nw
->p_next
= (struct pair
*) malloc( sizeof( struct pair
) );
439 nw
->p_name
= it
->p_name
;
440 nw
->p_value
= it
->p_value
;
448 void hash_free( struct symhash
*symbols
)
455 for ( i
= 0; i
< SYMHASHMEMBERS
; ++i
)
457 struct pair
*it
= symbols
->s_pairs
[ i
];
466 free( symbols
->s_pairs
);
469 void hash_define( char *name
, char const *val
, struct symhash
**symbols
)
477 /* Make space if it's needed */
478 if ( *symbols
== NULL
)
482 *symbols
= (struct symhash
*) malloc( sizeof( struct symhash
) );
483 if ( *symbols
== NULL
)
484 fatalerr( "malloc()/realloc() failure in insert_defn()\n" );
486 for ( i
= 0; i
< SYMHASHMEMBERS
; ++i
)
487 (*symbols
)->s_pairs
[i
] = NULL
;
490 hashval
= hash( name
);
491 it
= (*symbols
)->s_pairs
[ hashval
];
493 /* Replace/insert the symbol */
496 it
= (*symbols
)->s_pairs
[ hashval
] = (struct pair
*) malloc( sizeof( struct pair
) );
497 it
->p_name
= copy( name
);
498 it
->p_value
= copy( val
);
501 else if ( strcmp( it
->p_name
, name
) == 0 )
503 it
->p_value
= copy( val
);
507 while ( it
->p_next
&& ( strcmp( it
->p_next
->p_name
, name
) != 0 ) )
512 it
->p_next
->p_name
= copy( name
);
515 it
->p_next
= (struct pair
*) malloc( sizeof( struct pair
) );
516 it
->p_next
->p_name
= copy( name
);
517 it
->p_next
->p_value
= copy( val
);
518 it
->p_next
->p_next
= NULL
;
523 char *hash_lookup( char *symbol
, struct symhash
*symbols
)
530 it
= symbols
->s_pairs
[ hash( symbol
) ];
532 while ( it
&& ( strcmp( it
->p_name
, symbol
) != 0 ) )
542 void hash_undefine( char *symbol
, struct symhash
*symbols
)
550 hashval
= hash( symbol
);
551 it
= symbols
->s_pairs
[ hashval
];
553 /* Replace/insert the symbol */
556 else if ( strcmp( it
->p_name
, symbol
) == 0 )
561 it
->p_name
= it
->p_next
->p_name
;
562 it
->p_value
= it
->p_next
->p_value
;
563 tmp
= it
->p_next
->p_next
;
570 symbols
->s_pairs
[ hashval
] = NULL
;
575 while ( it
->p_next
&& ( strcmp( it
->p_next
->p_name
, symbol
) != 0 ) )
581 struct pair
*tmp
= it
->p_next
;
582 it
->p_next
= it
->p_next
->p_next
;
588 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */