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
);
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
);
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.
342 memmove (line
, p
, strlen(p
));
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;
416 for ( ; *str
; str
++ )
418 hashval
= ( hashval
* SYMHASHSEED
) + ( *str
);
421 return hashval
& ( SYMHASHMEMBERS
- 1 );
424 struct symhash
*hash_copy( symbols
)
425 struct symhash
*symbols
;
428 struct symhash
*newsym
;
432 newsym
= (struct symhash
*) malloc( sizeof( struct symhash
) );
434 for ( i
= 0; i
< SYMHASHMEMBERS
; ++i
)
436 if ( !symbols
->s_pairs
[ i
] )
437 newsym
->s_pairs
[ i
] = NULL
;
440 struct pair
*it
= symbols
->s_pairs
[ i
];
441 struct pair
*nw
= newsym
->s_pairs
[ i
] = (struct pair
*) malloc( sizeof( struct pair
) );
442 nw
->p_name
= it
->p_name
;
443 nw
->p_value
= it
->p_value
;
448 nw
->p_next
= (struct pair
*) malloc( sizeof( struct pair
) );
451 nw
->p_name
= it
->p_name
;
452 nw
->p_value
= it
->p_value
;
460 void hash_free( symbols
)
461 struct symhash
*symbols
;
468 for ( i
= 0; i
< SYMHASHMEMBERS
; ++i
)
470 struct pair
*it
= symbols
->s_pairs
[ i
];
479 free( symbols
->s_pairs
);
482 void hash_define( name
, val
, symbols
)
484 struct symhash
**symbols
;
492 /* Make space if it's needed */
493 if ( *symbols
== NULL
)
497 *symbols
= (struct symhash
*) malloc( sizeof( struct symhash
) );
498 if ( *symbols
== NULL
)
499 fatalerr( "malloc()/realloc() failure in insert_defn()\n" );
501 for ( i
= 0; i
< SYMHASHMEMBERS
; ++i
)
502 (*symbols
)->s_pairs
[i
] = NULL
;
505 hashval
= hash( name
);
506 it
= (*symbols
)->s_pairs
[ hashval
];
508 /* Replace/insert the symbol */
511 it
= (*symbols
)->s_pairs
[ hashval
] = (struct pair
*) malloc( sizeof( struct pair
) );
512 it
->p_name
= copy( name
);
513 it
->p_value
= copy( val
);
516 else if ( strcmp( it
->p_name
, name
) == 0 )
518 it
->p_value
= copy( val
);
522 while ( it
->p_next
&& ( strcmp( it
->p_next
->p_name
, name
) != 0 ) )
527 it
->p_next
->p_name
= copy( name
);
530 it
->p_next
= (struct pair
*) malloc( sizeof( struct pair
) );
531 it
->p_next
->p_name
= copy( name
);
532 it
->p_next
->p_value
= copy( val
);
533 it
->p_next
->p_next
= NULL
;
538 char *hash_lookup( symbol
, symbols
)
540 struct symhash
*symbols
;
547 it
= symbols
->s_pairs
[ hash( symbol
) ];
549 while ( it
&& ( strcmp( it
->p_name
, symbol
) != 0 ) )
559 void hash_undefine( symbol
, symbols
)
561 struct symhash
*symbols
;
569 hashval
= hash( symbol
);
570 it
= symbols
->s_pairs
[ hashval
];
572 /* Replace/insert the symbol */
575 else if ( strcmp( it
->p_name
, symbol
) == 0 )
580 it
->p_name
= it
->p_next
->p_name
;
581 it
->p_value
= it
->p_next
->p_value
;
582 tmp
= it
->p_next
->p_next
;
589 symbols
->s_pairs
[ hashval
] = NULL
;
594 while ( it
->p_next
&& ( strcmp( it
->p_next
->p_name
, symbol
) != 0 ) )
600 struct pair
*tmp
= it
->p_next
;
601 it
->p_next
= it
->p_next
->p_next
;
607 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */