xref: /aoo4110/main/soltools/mkdepend/parse.c (revision b1cdbd2c)
1 /* $XConsortium: parse.c,v 1.30 94/04/17 20:10:38 gildea Exp $ */
2 /*
3 
4 Copyright (c) 1993, 1994  X Consortium
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
19 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 
23 Except as contained in this notice, the name of the X Consortium shall not be
24 used in advertising or otherwise to promote the sale, use or other dealings
25 in this Software without prior written authorization from the X Consortium.
26 
27 */
28 
29 #include "def.h"
30 char *hash_lookup( char *symbol, struct symhash *symbols );
31 void hash_undefine( char *symbol, struct symhash *symbols );
32 int gobble( register struct filepointer *filep, struct inclist *file,
33     struct inclist *file_red, struct symhash *symbols );
34 int deftype ( register char *line, register struct filepointer *filep,
35     register struct inclist *file_red, register struct inclist *file,
36     int parse_it, struct symhash *symbols);
37 int zero_value(register char *exp, register struct filepointer *filep,
38     register struct inclist *file_red, register struct symhash *symbols);
39 
40 extern char	*directives[];
41 extern struct symhash *maininclist;
42 
find_includes(filep,file,file_red,recursion,failOK,incCollection,symbols)43 int find_includes(filep, file, file_red, recursion, failOK, incCollection, symbols)
44 	struct filepointer	*filep;
45 	struct inclist		*file, *file_red;
46 	int			recursion;
47 	boolean			failOK;
48     struct IncludesCollection* incCollection;
49 	struct symhash		*symbols;
50 {
51 	register char	*line;
52 	register int	type;
53 	boolean recfailOK;
54 
55 	while ((line = get_line(filep))) {
56 		switch(type = deftype(line, filep, file_red, file, TRUE, symbols)) {
57 		case IF:
58 		doif:
59 			type = find_includes(filep, file,
60 				file_red, recursion+1, failOK, incCollection, symbols);
61 			while ((type == ELIF) || (type == ELIFFALSE) ||
62 			       (type == ELIFGUESSFALSE))
63 				type = gobble(filep, file, file_red, symbols);
64 			if (type == ELSE)
65 				gobble(filep, file, file_red, symbols);
66 			break;
67 		case IFFALSE:
68 		case IFGUESSFALSE:
69 		    doiffalse:
70 			if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
71 			    recfailOK = TRUE;
72 			else
73 			    recfailOK = failOK;
74 			type = gobble(filep, file, file_red, symbols);
75 			if (type == ELSE)
76 			    find_includes(filep, file,
77 					  file_red, recursion+1, recfailOK, incCollection, symbols);
78 			else
79 			if (type == ELIF)
80 			    goto doif;
81 			else
82 			if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
83 			    goto doiffalse;
84 			break;
85 		case IFDEF:
86 		case IFNDEF:
87 			if ((type == IFDEF && hash_lookup(line, symbols))
88 			 || (type == IFNDEF && !hash_lookup(line, symbols))) {
89 				debug(1,(type == IFNDEF ?
90 				    "line %d: %s !def'd in %s via %s%s\n" : "",
91 				    filep->f_line, line,
92 				    file->i_file, file_red->i_file, ": doit"));
93 				type = find_includes(filep, file,
94 					file_red, recursion+1, failOK, incCollection, symbols);
95 				while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
96 					type = gobble(filep, file, file_red, symbols);
97 				if (type == ELSE)
98 					gobble(filep, file, file_red, symbols);
99 			}
100 			else {
101 				debug(1,(type == IFDEF ?
102 				    "line %d: %s !def'd in %s via %s%s\n" : "",
103 				    filep->f_line, line,
104 				    file->i_file, file_red->i_file, ": gobble"));
105 				type = gobble(filep, file, file_red, symbols);
106 				if (type == ELSE)
107 					find_includes(filep, file,
108 						file_red, recursion + 1, failOK, incCollection, symbols);
109 				else if (type == ELIF)
110 				    	goto doif;
111 				else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
112 				    	goto doiffalse;
113 			}
114 			break;
115 		case ELSE:
116 		case ELIFFALSE:
117 		case ELIFGUESSFALSE:
118 		case ELIF:
119 			if (!recursion)
120 				gobble(filep, file, file_red, symbols);
121 		case ENDIF:
122 			if (recursion)
123 				return(type);
124 		case DEFINE:
125 			define(line, &symbols);
126 			break;
127 		case UNDEF:
128 			if (!*line) {
129 			    warning("%s, line %d: incomplete undef == \"%s\"\n",
130 				file_red->i_file, filep->f_line, line);
131 			    break;
132 			}
133 			hash_undefine(line, symbols);
134 			break;
135 		case INCLUDE:
136 			add_include(filep, file, file_red, line, FALSE, failOK, incCollection, symbols);
137 			break;
138 		case INCLUDEDOT:
139 			add_include(filep, file, file_red, line, TRUE, failOK, incCollection, symbols);
140 			break;
141 		case ERROR:
142 		    	warning("%s: %d: %s\n", file_red->i_file,
143 				 filep->f_line, line);
144 		    	break;
145 
146 		case PRAGMA:
147 		case IDENT:
148 		case SCCS:
149 		case EJECT:
150 			break;
151 		case -1:
152 			warning("%s", file_red->i_file);
153 			if (file_red != file)
154 			    warning1(" (reading %s)", file->i_file);
155 			warning1(", line %d: unknown directive == \"%s\"\n",
156 				 filep->f_line, line);
157 			break;
158 		case -2:
159 			warning("%s", file_red->i_file);
160 			if (file_red != file)
161 			    warning1(" (reading %s)", file->i_file);
162 			warning1(", line %d: incomplete include == \"%s\"\n",
163 				 filep->f_line, line);
164 			break;
165 		}
166 	}
167 	return(-1);
168 }
169 
gobble(filep,file,file_red,symbols)170 int gobble(filep, file, file_red, symbols)
171 	register struct filepointer *filep;
172 	struct inclist		*file, *file_red;
173 	struct symhash		*symbols;
174 {
175 	register char	*line;
176 	register int	type;
177 
178 	while ((line = get_line(filep))) {
179 		switch(type = deftype(line, filep, file_red, file, FALSE, symbols)) {
180 		case IF:
181 		case IFFALSE:
182 		case IFGUESSFALSE:
183 		case IFDEF:
184 		case IFNDEF:
185 			type = gobble(filep, file, file_red, symbols);
186 			while ((type == ELIF) || (type == ELIFFALSE) ||
187 			       (type == ELIFGUESSFALSE))
188 			    type = gobble(filep, file, file_red, symbols);
189 			if (type == ELSE)
190 			        (void)gobble(filep, file, file_red, symbols);
191 			break;
192 		case ELSE:
193 		case ENDIF:
194 			debug(0,("%s, line %d: #%s\n",
195 				file->i_file, filep->f_line,
196 				directives[type]));
197 			return(type);
198 		case DEFINE:
199 		case UNDEF:
200 		case INCLUDE:
201 		case INCLUDEDOT:
202 		case PRAGMA:
203 		case ERROR:
204 		case IDENT:
205 		case SCCS:
206 		case EJECT:
207 			break;
208 		case ELIF:
209 		case ELIFFALSE:
210 		case ELIFGUESSFALSE:
211 			return(type);
212 		case -1:
213 			warning("%s, line %d: unknown directive == \"%s\"\n",
214 				file_red->i_file, filep->f_line, line);
215 			break;
216 		}
217 	}
218 	return(-1);
219 }
220 
221 /*
222  * Decide what type of # directive this line is.
223  */
deftype(line,filep,file_red,file,parse_it,symbols)224 int deftype (line, filep, file_red, file, parse_it, symbols)
225 	register char	*line;
226 	register struct filepointer *filep;
227 	register struct inclist *file_red, *file;
228 	int	parse_it;
229 	struct symhash	*symbols;
230 {
231 	register char	*p;
232 	char	*directive, savechar;
233 	register int	ret;
234 
235 	/*
236 	 * Parse the directive...
237 	 */
238 	directive=line+1;
239 	while (*directive == ' ' || *directive == '\t')
240 		directive++;
241 
242 	p = directive;
243 	while (*p >= 'a' && *p <= 'z')
244 		p++;
245 	savechar = *p;
246 	*p = '\0';
247 	ret = match(directive, directives);
248 	*p = savechar;
249 
250 	/* If we don't recognize this compiler directive or we happen to just
251 	 * be gobbling up text while waiting for an #endif or #elif or #else
252 	 * in the case of an #elif we must check the zero_value and return an
253 	 * ELIF or an ELIFFALSE.
254 	 */
255 
256 	if (ret == ELIF && !parse_it)
257 	{
258 	    while (*p == ' ' || *p == '\t')
259 		p++;
260 	    /*
261 	     * parse an expression.
262 	     */
263 	    debug(0,("%s, line %d: #elif %s ",
264 		   file->i_file, filep->f_line, p));
265 	    ret = zero_value(p, filep, file_red, symbols);
266 	    if (ret != IF)
267 	    {
268 		debug(0,("false...\n"));
269 		if (ret == IFFALSE)
270 		    return(ELIFFALSE);
271 		else
272 		    return(ELIFGUESSFALSE);
273 	    }
274 	    else
275 	    {
276 		debug(0,("true...\n"));
277 		return(ELIF);
278 	    }
279 	}
280 
281 	if (ret < 0 || ! parse_it)
282 		return(ret);
283 
284 	/*
285 	 * now decide how to parse the directive, and do it.
286 	 */
287 	while (*p == ' ' || *p == '\t')
288 		p++;
289 	switch (ret) {
290 	case IF:
291 		/*
292 		 * parse an expression.
293 		 */
294 		ret = zero_value(p, filep, file_red, symbols);
295 		debug(0,("%s, line %d: %s #if %s\n",
296 			 file->i_file, filep->f_line, ret?"false":"true", p));
297 		break;
298 	case IFDEF:
299 	case IFNDEF:
300 		debug(0,("%s, line %d: #%s %s\n",
301 			file->i_file, filep->f_line, directives[ret], p));
302 	case UNDEF:
303 		/*
304 		 * separate the name of a single symbol.
305 		 */
306 		while (isalnum(*p) || *p == '_')
307 			*line++ = *p++;
308 		*line = '\0';
309 		break;
310 	case INCLUDE:
311 		debug(2,("%s, line %d: #include %s\n",
312 			file->i_file, filep->f_line, p));
313 
314 		/* Support ANSI macro substitution */
315 		{
316 			char *sym = hash_lookup(p, symbols);
317 			while (sym)
318 			{
319 				p = sym;
320 				debug(3,("%s : #includes SYMBOL %s\n",
321 							file->i_incstring,
322 							sym));
323 				/* mark file as having included a 'soft include' */
324 				file->i_included_sym = TRUE;
325 				sym = hash_lookup(p, symbols);
326 			}
327 		}
328 
329 		/*
330 		 * Separate the name of the include file.
331 		 */
332 		while (*p && *p != '"' && *p != '<')
333 			p++;
334 		if (! *p)
335 			return(-2);
336 		if (*p++ == '"') {
337 			ret = INCLUDEDOT;
338 			while (*p && *p != '"')
339 				*line++ = *p++;
340 		} else
341 			while (*p && *p != '>')
342 				*line++ = *p++;
343 		*line = '\0';
344 		break;
345 	case DEFINE:
346 		/*
347 		 * copy the definition back to the beginning of the line.
348 		 */
349 		strcpy (line, p);
350 		break;
351 	case ELSE:
352 	case ENDIF:
353 	case ELIF:
354 	case PRAGMA:
355 	case ERROR:
356 	case IDENT:
357 	case SCCS:
358 	case EJECT:
359 		debug(0,("%s, line %d: #%s\n",
360 			file->i_file, filep->f_line, directives[ret]));
361 		/*
362 		 * nothing to do.
363 		 */
364 		break;
365 	}
366 	return(ret);
367 }
368 
369 /*
370  * HACK! - so that we do not have to introduce 'symbols' in each cppsetup.c
371  * function...  It's safe, functions from cppsetup.c don't return here.
372  */
373 struct symhash *global_symbols = NULL;
374 
isdefined(symbol)375 char * isdefined( symbol )
376 	register char *symbol;
377 {
378 	return hash_lookup( symbol, global_symbols );
379 }
380 
381 /*
382  * Return type based on if the #if expression evaluates to 0
383  */
zero_value(exp,filep,file_red,symbols)384 int zero_value(exp, filep, file_red, symbols)
385 	register char	*exp;
386 	register struct filepointer *filep;
387 	register struct inclist *file_red;
388 	register struct symhash *symbols;
389 {
390 	global_symbols = symbols; /* HACK! see above */
391 	if (cppsetup(exp, filep, file_red))
392 	    return(IFFALSE);
393 	else
394 	    return(IF);
395 }
396 
define(def,symbols)397 void define( def, symbols )
398     char	        *def;
399     struct symhash **symbols;
400 {
401     char *val;
402 
403     /* Separate symbol name and its value */
404     val = def;
405     while (isalnum(*val) || *val == '_')
406 	val++;
407     if (*val)
408 	*val++ = '\0';
409     while (*val == ' ' || *val == '\t')
410 	val++;
411 
412     if (!*val)
413 	val = "1";
414     hash_define( def, val, symbols );
415 }
416 
hash(str)417 static int hash( str )
418     register char *str;
419 {
420     /* Hash (Kernighan and Ritchie) */
421     register unsigned int hashval = 0;
422     //char *s = str;
423 
424     for ( ; *str; str++ )
425     {
426         hashval = ( hashval * SYMHASHSEED ) + ( *str );
427     }
428 
429     //fprintf( stderr, "hash: %s, %d\n", s, hashval & ( SYMHASHMEMBERS - 1 ) );
430     return hashval & ( SYMHASHMEMBERS - 1 );
431 }
432 
hash_copy(symbols)433 struct symhash *hash_copy( symbols )
434     struct symhash *symbols;
435 {
436     int i;
437     struct symhash *newsym;
438     if ( !symbols )
439         return NULL;
440 
441     newsym = (struct symhash *) malloc( sizeof( struct symhash ) );
442 
443     for ( i = 0; i < SYMHASHMEMBERS; ++i )
444     {
445         if ( !symbols->s_pairs[ i ] )
446             newsym->s_pairs[ i ] = NULL;
447         else
448         {
449             struct pair *it = symbols->s_pairs[ i ];
450             struct pair *nw = newsym->s_pairs[ i ] = (struct pair*) malloc( sizeof( struct pair ) );
451             nw->p_name = it->p_name;
452             nw->p_value = it->p_value;
453             nw->p_next = NULL;
454 
455             while ( it->p_next )
456             {
457                 nw->p_next = (struct pair*) malloc( sizeof( struct pair ) );
458                 it = it->p_next;
459                 nw = nw->p_next;
460                 nw->p_name = it->p_name;
461                 nw->p_value = it->p_value;
462                 nw->p_next = NULL;
463             }
464         }
465     }
466     return newsym;
467 }
468 
hash_free(symbols)469 void hash_free( symbols )
470     struct symhash *symbols;
471 {
472     int i;
473 
474     if ( !symbols )
475         return;
476 
477     for ( i = 0; i < SYMHASHMEMBERS; ++i )
478     {
479         struct pair *it = symbols->s_pairs[ i ];
480         struct pair *next;
481         while ( it )
482         {
483             next = it->p_next;
484             free( it );
485             it = next;
486         }
487     }
488     free( symbols->s_pairs );
489 }
490 
hash_define(name,val,symbols)491 void hash_define( name, val, symbols )
492     char            *name, *val;
493     struct symhash **symbols;
494 {
495     int hashval;
496     struct pair *it;
497 
498     if ( !symbols )
499         return;
500 
501     /* Make space if it's needed */
502     if ( *symbols == NULL )
503     {
504         int i;
505 
506         *symbols = (struct symhash *) malloc( sizeof( struct symhash ) );
507         if ( *symbols == NULL )
508             fatalerr( "malloc()/realloc() failure in insert_defn()\n" );
509 
510         for ( i = 0; i < SYMHASHMEMBERS; ++i )
511             (*symbols)->s_pairs[i] = NULL;
512     }
513 
514     hashval = hash( name );
515     it = (*symbols)->s_pairs[ hashval ];
516 
517     /* Replace/insert the symbol */
518     if ( it == NULL )
519     {
520         it = (*symbols)->s_pairs[ hashval ] = (struct pair*) malloc( sizeof( struct pair ) );
521         it->p_name = copy( name );
522         it->p_value = copy( val );
523         it->p_next = NULL;
524     }
525     else if ( strcmp( it->p_name, name ) == 0 )
526     {
527         it->p_value = copy( val );
528     }
529     else
530     {
531         while ( it->p_next && ( strcmp( it->p_next->p_name, name ) != 0 ) )
532         {
533             it = it->p_next;
534         }
535         if ( it->p_next )
536             it->p_next->p_name = copy( name );
537         else
538         {
539             it->p_next = (struct pair*) malloc( sizeof( struct pair ) );
540             it->p_next->p_name = copy( name );
541             it->p_next->p_value = copy( val );
542             it->p_next->p_next = NULL;
543         }
544     }
545 }
546 
hash_lookup(symbol,symbols)547 char *hash_lookup( symbol, symbols )
548     char           *symbol;
549     struct symhash *symbols;
550 {
551     struct pair *it;
552 
553     if ( !symbols )
554         return NULL;
555 
556     it = symbols->s_pairs[ hash( symbol ) ];
557 
558     while ( it && ( strcmp( it->p_name, symbol ) != 0 ) )
559     {
560         it = it->p_next;
561     }
562     if ( it )
563         return it->p_value;
564 
565     return NULL;
566 }
567 
hash_undefine(symbol,symbols)568 void hash_undefine( symbol, symbols )
569     char           *symbol;
570     struct symhash *symbols;
571 {
572     int hashval;
573     struct pair *it;
574 
575     if ( !symbols )
576         return;
577 
578     hashval = hash( symbol );
579     it = symbols->s_pairs[ hashval ];
580 
581     /* Replace/insert the symbol */
582     if ( it == NULL )
583         return;
584     else if ( strcmp( it->p_name, symbol ) == 0 )
585     {
586         if ( it->p_next )
587         {
588             struct pair *tmp;
589             it->p_name = it->p_next->p_name;
590             it->p_value = it->p_next->p_value;
591             tmp = it->p_next->p_next;
592             free( it->p_next );
593             it->p_next = tmp;
594         }
595         else
596         {
597             free( it );
598             symbols->s_pairs[ hashval ] = NULL;
599         }
600     }
601     else
602     {
603         while ( it->p_next && ( strcmp( it->p_next->p_name, symbol ) != 0 ) )
604         {
605             it = it->p_next;
606         }
607         if ( it->p_next )
608         {
609             struct pair *tmp = it->p_next;
610             it->p_next = it->p_next->p_next;
611             free( tmp );
612         }
613     }
614 }
615