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