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
,
38 struct inclist
*file_red
, struct inclist
*file
,
39 int parse_it
, struct symhash
*symbols
);
40 int zero_value(char *exp
, struct filepointer
*filep
,
41 struct inclist
*file_red
, struct symhash
*symbols
);
43 extern struct symhash
*maininclist
;
45 int find_includes(struct filepointer
*filep
, struct inclist
*file
, struct inclist
*file_red
, int recursion
, boolean failOK
, struct IncludesCollection
* incCollection
, struct symhash
*symbols
)
51 while ((line
= get_line(filep
))) {
52 switch(type
= deftype(line
, filep
, file_red
, file
, TRUE
, symbols
)) {
55 type
= find_includes(filep
, file
,
56 file_red
, recursion
+1, failOK
, incCollection
, symbols
);
57 while ((type
== ELIF
) || (type
== ELIFFALSE
) ||
58 (type
== ELIFGUESSFALSE
))
59 type
= gobble(filep
, file
, file_red
, symbols
);
61 gobble(filep
, file
, file_red
, symbols
);
66 if (type
== IFGUESSFALSE
|| type
== ELIFGUESSFALSE
)
70 type
= gobble(filep
, file
, file_red
, symbols
);
72 find_includes(filep
, file
,
73 file_red
, recursion
+1, recfailOK
, incCollection
, symbols
);
74 else if (type
== ELIF
)
76 else if ((type
== ELIFFALSE
) || (type
== ELIFGUESSFALSE
))
81 if ((type
== IFDEF
&& hash_lookup(line
, symbols
))
82 || (type
== IFNDEF
&& !hash_lookup(line
, symbols
))) {
83 debug(1,(type
== IFNDEF
?
84 "line %d: %s !def'd in %s via %s%s\n" : "",
86 file
->i_file
, file_red
->i_file
, ": doit"));
87 type
= find_includes(filep
, file
,
88 file_red
, recursion
+1, failOK
, incCollection
, symbols
);
89 while (type
== ELIF
|| type
== ELIFFALSE
|| type
== ELIFGUESSFALSE
)
90 type
= gobble(filep
, file
, file_red
, symbols
);
92 gobble(filep
, file
, file_red
, symbols
);
95 debug(1,(type
== IFDEF
?
96 "line %d: %s !def'd in %s via %s%s\n" : "",
98 file
->i_file
, file_red
->i_file
, ": gobble"));
99 type
= gobble(filep
, file
, file_red
, symbols
);
101 find_includes(filep
, file
,
102 file_red
, recursion
+ 1, failOK
, incCollection
, symbols
);
103 else if (type
== ELIF
)
105 else if (type
== ELIFFALSE
|| type
== ELIFGUESSFALSE
)
114 gobble(filep
, file
, file_red
, symbols
);
121 define(line
, &symbols
);
125 warning("%s, line %d: incomplete undef == \"%s\"\n",
126 file_red
->i_file
, filep
->f_line
, line
);
129 hash_undefine(line
, symbols
);
132 add_include(filep
, file
, file_red
, line
, FALSE
, failOK
, incCollection
, symbols
);
135 add_include(filep
, file
, file_red
, line
, TRUE
, failOK
, incCollection
, symbols
);
138 warning("%s: %d: %s\n", file_red
->i_file
,
139 filep
->f_line
, line
);
148 warning("%s", file_red
->i_file
);
149 if (file_red
!= file
)
150 warning1(" (reading %s)", file
->i_file
);
151 warning1(", line %d: unknown directive == \"%s\"\n",
152 filep
->f_line
, line
);
155 warning("%s", file_red
->i_file
);
156 if (file_red
!= file
)
157 warning1(" (reading %s)", file
->i_file
);
158 warning1(", line %d: incomplete include == \"%s\"\n",
159 filep
->f_line
, line
);
166 int gobble(struct filepointer
*filep
,
167 struct inclist
*file
,
168 struct inclist
*file_red
,
169 struct symhash
*symbols
)
174 while ((line
= get_line(filep
))) {
175 switch(type
= deftype(line
, filep
, file_red
, file
, FALSE
, symbols
)) {
181 type
= gobble(filep
, file
, file_red
, symbols
);
182 while ((type
== ELIF
) || (type
== ELIFFALSE
) ||
183 (type
== ELIFGUESSFALSE
))
184 type
= gobble(filep
, file
, file_red
, symbols
);
186 (void)gobble(filep
, file
, file_red
, symbols
);
190 debug(0,("%s, line %d: #%s\n",
191 file
->i_file
, filep
->f_line
,
209 warning("%s, line %d: unknown directive == \"%s\"\n",
210 file_red
->i_file
, filep
->f_line
, line
);
218 * Decide what type of # directive this line is.
220 int deftype (char *line
, struct filepointer
*filep
, struct inclist
*file_red
, struct inclist
*file
, int parse_it
, struct symhash
*symbols
)
223 char *directive
, savechar
;
227 * Parse the directive...
230 while (*directive
== ' ' || *directive
== '\t')
234 while (*p
>= 'a' && *p
<= 'z')
238 ret
= match(directive
, directives
);
241 /* If we don't recognize this compiler directive or we happen to just
242 * be gobbling up text while waiting for an #endif or #elif or #else
243 * in the case of an #elif we must check the zero_value and return an
244 * ELIF or an ELIFFALSE.
247 if (ret
== ELIF
&& !parse_it
)
249 while (*p
== ' ' || *p
== '\t')
252 * parse an expression.
254 debug(0,("%s, line %d: #elif %s ",
255 file
->i_file
, filep
->f_line
, p
));
256 ret
= zero_value(p
, filep
, file_red
, symbols
);
259 debug(0,("false...\n"));
263 return ELIFGUESSFALSE
;
267 debug(0,("true...\n"));
272 if (ret
< 0 || ! parse_it
)
276 * now decide how to parse the directive, and do it.
278 while (*p
== ' ' || *p
== '\t')
283 * parse an expression.
285 ret
= zero_value(p
, filep
, file_red
, symbols
);
286 debug(0,("%s, line %d: %s #if %s\n",
287 file
->i_file
, filep
->f_line
, ret
?"false":"true", p
));
291 debug(0,("%s, line %d: #%s %s\n",
292 file
->i_file
, filep
->f_line
, directives
[ret
], p
));
296 * separate the name of a single symbol.
298 while (isalnum((unsigned char)*p
) || *p
== '_')
303 debug(2,("%s, line %d: #include %s\n",
304 file
->i_file
, filep
->f_line
, p
));
306 /* Support ANSI macro substitution */
308 char *sym
= hash_lookup(p
, symbols
);
312 debug(3,("%s : #includes SYMBOL %s\n",
315 /* mark file as having included a 'soft include' */
316 file
->i_included_sym
= TRUE
;
317 sym
= hash_lookup(p
, symbols
);
322 * Separate the name of the include file.
324 while (*p
&& *p
!= '"' && *p
!= '<')
330 while (*p
&& *p
!= '"')
333 while (*p
&& *p
!= '>')
339 * copy the definition back to the beginning of the line.
341 memmove (line
, p
, strlen(p
));
351 debug(0,("%s, line %d: #%s\n",
352 file
->i_file
, filep
->f_line
, directives
[ret
]));
362 * HACK! - so that we do not have to introduce 'symbols' in each cppsetup.c
363 * function... It's safe, functions from cppsetup.c don't return here.
365 static struct symhash
*global_symbols
= NULL
;
367 char * isdefined( char *symbol
)
369 return hash_lookup( symbol
, global_symbols
);
373 * Return type based on if the #if expression evaluates to 0
375 int zero_value(char *exp
, struct filepointer
*filep
, struct inclist
*file_red
, struct symhash
*symbols
)
377 global_symbols
= symbols
; /* HACK! see above */
378 if (cppsetup(exp
, filep
, file_red
))
384 void define( char *def
, struct symhash
**symbols
)
388 /* Separate symbol name and its value */
390 while (isalnum((unsigned char)*val
) || *val
== '_')
394 while (*val
== ' ' || *val
== '\t')
399 hash_define( def
, val
, symbols
);
402 static int hash( char *str
)
404 /* Hash (Kernighan and Ritchie) */
405 unsigned int hashval
= 0;
407 for ( ; *str
; str
++ )
409 hashval
= ( hashval
* SYMHASHSEED
) + ( *str
);
412 return hashval
& ( SYMHASHMEMBERS
- 1 );
415 struct symhash
*hash_copy( struct symhash
*symbols
)
418 struct symhash
*newsym
;
422 newsym
= (struct symhash
*) malloc( sizeof( struct symhash
) );
424 for ( i
= 0; i
< SYMHASHMEMBERS
; ++i
)
426 if ( !symbols
->s_pairs
[ i
] )
427 newsym
->s_pairs
[ i
] = NULL
;
430 struct pair
*it
= symbols
->s_pairs
[ i
];
431 struct pair
*nw
= newsym
->s_pairs
[ i
] = (struct pair
*) malloc( sizeof( struct pair
) );
432 nw
->p_name
= it
->p_name
;
433 nw
->p_value
= it
->p_value
;
438 nw
->p_next
= (struct pair
*) malloc( sizeof( struct pair
) );
441 nw
->p_name
= it
->p_name
;
442 nw
->p_value
= it
->p_value
;
450 void hash_free( struct symhash
*symbols
)
457 for ( i
= 0; i
< SYMHASHMEMBERS
; ++i
)
459 struct pair
*it
= symbols
->s_pairs
[ i
];
468 free( symbols
->s_pairs
);
471 void hash_define( char *name
, char *val
, struct symhash
**symbols
)
479 /* Make space if it's needed */
480 if ( *symbols
== NULL
)
484 *symbols
= (struct symhash
*) malloc( sizeof( struct symhash
) );
485 if ( *symbols
== NULL
)
486 fatalerr( "malloc()/realloc() failure in insert_defn()\n" );
488 for ( i
= 0; i
< SYMHASHMEMBERS
; ++i
)
489 (*symbols
)->s_pairs
[i
] = NULL
;
492 hashval
= hash( name
);
493 it
= (*symbols
)->s_pairs
[ hashval
];
495 /* Replace/insert the symbol */
498 it
= (*symbols
)->s_pairs
[ hashval
] = (struct pair
*) malloc( sizeof( struct pair
) );
499 it
->p_name
= copy( name
);
500 it
->p_value
= copy( val
);
503 else if ( strcmp( it
->p_name
, name
) == 0 )
505 it
->p_value
= copy( val
);
509 while ( it
->p_next
&& ( strcmp( it
->p_next
->p_name
, name
) != 0 ) )
514 it
->p_next
->p_name
= copy( name
);
517 it
->p_next
= (struct pair
*) malloc( sizeof( struct pair
) );
518 it
->p_next
->p_name
= copy( name
);
519 it
->p_next
->p_value
= copy( val
);
520 it
->p_next
->p_next
= NULL
;
525 char *hash_lookup( char *symbol
, struct symhash
*symbols
)
532 it
= symbols
->s_pairs
[ hash( symbol
) ];
534 while ( it
&& ( strcmp( it
->p_name
, symbol
) != 0 ) )
544 void hash_undefine( char *symbol
, struct symhash
*symbols
)
552 hashval
= hash( symbol
);
553 it
= symbols
->s_pairs
[ hashval
];
555 /* Replace/insert the symbol */
558 else if ( strcmp( it
->p_name
, symbol
) == 0 )
563 it
->p_name
= it
->p_next
->p_name
;
564 it
->p_value
= it
->p_next
->p_value
;
565 tmp
= it
->p_next
->p_next
;
572 symbols
->s_pairs
[ hashval
] = NULL
;
577 while ( it
->p_next
&& ( strcmp( it
->p_next
->p_name
, symbol
) != 0 ) )
583 struct pair
*tmp
= it
->p_next
;
584 it
->p_next
= it
->p_next
->p_next
;
590 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */