xref: /trunk/main/soltools/mkdepend/parse.c (revision da891659)
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 		{
350 			int lenl = strlen(line);
351 			int lenp = strlen(p);
352 			memmove ( line, p, (lenl < lenp) ? lenl : lenp );
353 			line[ (lenl < lenp) ? lenl : lenp ] = '\0';	/* belts and braces */
354 		}
355 		break;
356 	case ELSE:
357 	case ENDIF:
358 	case ELIF:
359 	case PRAGMA:
360 	case ERROR:
361 	case IDENT:
362 	case SCCS:
363 	case EJECT:
364 		debug(0,("%s, line %d: #%s\n",
365 			file->i_file, filep->f_line, directives[ret]));
366 		/*
367 		 * nothing to do.
368 		 */
369 		break;
370 	}
371 	return(ret);
372 }
373 
374 /*
375  * HACK! - so that we do not have to introduce 'symbols' in each cppsetup.c
376  * function...  It's safe, functions from cppsetup.c don't return here.
377  */
378 struct symhash *global_symbols = NULL;
379 
isdefined(symbol)380 char * isdefined( symbol )
381 	register char *symbol;
382 {
383 	return hash_lookup( symbol, global_symbols );
384 }
385 
386 /*
387  * Return type based on if the #if expression evaluates to 0
388  */
zero_value(exp,filep,file_red,symbols)389 int zero_value(exp, filep, file_red, symbols)
390 	register char	*exp;
391 	register struct filepointer *filep;
392 	register struct inclist *file_red;
393 	register struct symhash *symbols;
394 {
395 	global_symbols = symbols; /* HACK! see above */
396 	if (cppsetup(exp, filep, file_red))
397 	    return(IFFALSE);
398 	else
399 	    return(IF);
400 }
401 
define(def,symbols)402 void define( def, symbols )
403     char	        *def;
404     struct symhash **symbols;
405 {
406     char *val;
407 
408     /* Separate symbol name and its value */
409     val = def;
410     while (isalnum(*val) || *val == '_')
411 	val++;
412     if (*val)
413 	*val++ = '\0';
414     while (*val == ' ' || *val == '\t')
415 	val++;
416 
417     if (!*val)
418 	val = "1";
419     hash_define( def, val, symbols );
420 }
421 
hash(str)422 static int hash( str )
423     register char *str;
424 {
425     /* Hash (Kernighan and Ritchie) */
426     register unsigned int hashval = 0;
427     //char *s = str;
428 
429     for ( ; *str; str++ )
430     {
431         hashval = ( hashval * SYMHASHSEED ) + ( *str );
432     }
433 
434     //fprintf( stderr, "hash: %s, %d\n", s, hashval & ( SYMHASHMEMBERS - 1 ) );
435     return hashval & ( SYMHASHMEMBERS - 1 );
436 }
437 
hash_copy(symbols)438 struct symhash *hash_copy( symbols )
439     struct symhash *symbols;
440 {
441     int i;
442     struct symhash *newsym;
443     if ( !symbols )
444         return NULL;
445 
446     newsym = (struct symhash *) malloc( sizeof( struct symhash ) );
447 
448     for ( i = 0; i < SYMHASHMEMBERS; ++i )
449     {
450         if ( !symbols->s_pairs[ i ] )
451             newsym->s_pairs[ i ] = NULL;
452         else
453         {
454             struct pair *it = symbols->s_pairs[ i ];
455             struct pair *nw = newsym->s_pairs[ i ] = (struct pair*) malloc( sizeof( struct pair ) );
456             nw->p_name = it->p_name;
457             nw->p_value = it->p_value;
458             nw->p_next = NULL;
459 
460             while ( it->p_next )
461             {
462                 nw->p_next = (struct pair*) malloc( sizeof( struct pair ) );
463                 it = it->p_next;
464                 nw = nw->p_next;
465                 nw->p_name = it->p_name;
466                 nw->p_value = it->p_value;
467                 nw->p_next = NULL;
468             }
469         }
470     }
471     return newsym;
472 }
473 
hash_free(symbols)474 void hash_free( symbols )
475     struct symhash *symbols;
476 {
477     int i;
478 
479     if ( !symbols )
480         return;
481 
482     for ( i = 0; i < SYMHASHMEMBERS; ++i )
483     {
484         struct pair *it = symbols->s_pairs[ i ];
485         struct pair *next;
486         while ( it )
487         {
488             next = it->p_next;
489             free( it );
490             it = next;
491         }
492     }
493     free( symbols->s_pairs );
494 }
495 
hash_define(name,val,symbols)496 void hash_define( name, val, symbols )
497     char            *name, *val;
498     struct symhash **symbols;
499 {
500     int hashval;
501     struct pair *it;
502 
503     if ( !symbols )
504         return;
505 
506     /* Make space if it's needed */
507     if ( *symbols == NULL )
508     {
509         int i;
510 
511         *symbols = (struct symhash *) malloc( sizeof( struct symhash ) );
512         if ( *symbols == NULL )
513             fatalerr( "malloc()/realloc() failure in insert_defn()\n" );
514 
515         for ( i = 0; i < SYMHASHMEMBERS; ++i )
516             (*symbols)->s_pairs[i] = NULL;
517     }
518 
519     hashval = hash( name );
520     it = (*symbols)->s_pairs[ hashval ];
521 
522     /* Replace/insert the symbol */
523     if ( it == NULL )
524     {
525         it = (*symbols)->s_pairs[ hashval ] = (struct pair*) malloc( sizeof( struct pair ) );
526         it->p_name = copy( name );
527         it->p_value = copy( val );
528         it->p_next = NULL;
529     }
530     else if ( strcmp( it->p_name, name ) == 0 )
531     {
532         it->p_value = copy( val );
533     }
534     else
535     {
536         while ( it->p_next && ( strcmp( it->p_next->p_name, name ) != 0 ) )
537         {
538             it = it->p_next;
539         }
540         if ( it->p_next )
541             it->p_next->p_name = copy( name );
542         else
543         {
544             it->p_next = (struct pair*) malloc( sizeof( struct pair ) );
545             it->p_next->p_name = copy( name );
546             it->p_next->p_value = copy( val );
547             it->p_next->p_next = NULL;
548         }
549     }
550 }
551 
hash_lookup(symbol,symbols)552 char *hash_lookup( symbol, symbols )
553     char           *symbol;
554     struct symhash *symbols;
555 {
556     struct pair *it;
557 
558     if ( !symbols )
559         return NULL;
560 
561     it = symbols->s_pairs[ hash( symbol ) ];
562 
563     while ( it && ( strcmp( it->p_name, symbol ) != 0 ) )
564     {
565         it = it->p_next;
566     }
567     if ( it )
568         return it->p_value;
569 
570     return NULL;
571 }
572 
hash_undefine(symbol,symbols)573 void hash_undefine( symbol, symbols )
574     char           *symbol;
575     struct symhash *symbols;
576 {
577     int hashval;
578     struct pair *it;
579 
580     if ( !symbols )
581         return;
582 
583     hashval = hash( symbol );
584     it = symbols->s_pairs[ hashval ];
585 
586     /* Replace/insert the symbol */
587     if ( it == NULL )
588         return;
589     else if ( strcmp( it->p_name, symbol ) == 0 )
590     {
591         if ( it->p_next )
592         {
593             struct pair *tmp;
594             it->p_name = it->p_next->p_name;
595             it->p_value = it->p_next->p_value;
596             tmp = it->p_next->p_next;
597             free( it->p_next );
598             it->p_next = tmp;
599         }
600         else
601         {
602             free( it );
603             symbols->s_pairs[ hashval ] = NULL;
604         }
605     }
606     else
607     {
608         while ( it->p_next && ( strcmp( it->p_next->p_name, symbol ) != 0 ) )
609         {
610             it = it->p_next;
611         }
612         if ( it->p_next )
613         {
614             struct pair *tmp = it->p_next;
615             it->p_next = it->p_next->p_next;
616             free( tmp );
617         }
618     }
619 }
620