(file) Return to parse.c CVS log (file) (dir) Up to [XFree86 CVS] / xc / config / makedepend

  1 dawes 1.1.1.2 /* $XConsortium: parse.c /main/31 1995/12/08 18:26:41 gildea $ */
  2 dawes 1.1     /*
  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 dawes 1.1     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               
 31               extern char	*directives[];
 32               extern struct inclist	maininclist;
 33               
 34               find_includes(filep, file, file_red, recursion, failOK)
 35               	struct filepointer	*filep;
 36               	struct inclist		*file, *file_red;
 37               	int			recursion;
 38               	boolean			failOK;
 39               {
 40               	register char	*line;
 41               	register int	type;
 42               	boolean recfailOK;
 43               
 44 dawes 1.1     	while (line = getline(filep)) {
 45               		switch(type = deftype(line, filep, file_red, file, TRUE)) {
 46               		case IF:
 47               		doif:
 48               			type = find_includes(filep, file,
 49               				file_red, recursion+1, failOK);
 50               			while ((type == ELIF) || (type == ELIFFALSE) ||
 51               			       (type == ELIFGUESSFALSE))
 52               				type = gobble(filep, file, file_red);
 53               			if (type == ELSE)
 54               				gobble(filep, file, file_red);
 55               			break;
 56               		case IFFALSE:
 57               		case IFGUESSFALSE:
 58               		    doiffalse:
 59               			if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
 60               			    recfailOK = TRUE;
 61               			else
 62               			    recfailOK = failOK;
 63               			type = gobble(filep, file, file_red);
 64               			if (type == ELSE)
 65 dawes 1.1     			    find_includes(filep, file,
 66               					  file_red, recursion+1, recfailOK);
 67               			else
 68               			if (type == ELIF)
 69               			    goto doif;
 70               			else
 71               			if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
 72               			    goto doiffalse;
 73               			break;
 74               		case IFDEF:
 75               		case IFNDEF:
 76               			if ((type == IFDEF && isdefined(line, file_red, NULL))
 77               			 || (type == IFNDEF && !isdefined(line, file_red, NULL))) {
 78               				debug(1,(type == IFNDEF ?
 79               				    "line %d: %s !def'd in %s via %s%s\n" : "",
 80               				    filep->f_line, line,
 81               				    file->i_file, file_red->i_file, ": doit"));
 82               				type = find_includes(filep, file,
 83               					file_red, recursion+1, failOK);
 84               				while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
 85               					type = gobble(filep, file, file_red);
 86 dawes 1.1     				if (type == ELSE)
 87               					gobble(filep, file, file_red);
 88               			}
 89               			else {
 90               				debug(1,(type == IFDEF ?
 91               				    "line %d: %s !def'd in %s via %s%s\n" : "",
 92               				    filep->f_line, line,
 93               				    file->i_file, file_red->i_file, ": gobble"));
 94               				type = gobble(filep, file, file_red);
 95               				if (type == ELSE)
 96               					find_includes(filep, file,
 97               						file_red, recursion+1, failOK);
 98               				else if (type == ELIF)
 99               				    	goto doif;
100               				else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
101               				    	goto doiffalse;
102               			}
103               			break;
104               		case ELSE:
105               		case ELIFFALSE:
106               		case ELIFGUESSFALSE:
107 dawes 1.1     		case ELIF:
108               			if (!recursion)
109               				gobble(filep, file, file_red);
110               		case ENDIF:
111               			if (recursion)
112               				return(type);
113               		case DEFINE:
114               			define(line, file);
115               			break;
116               		case UNDEF:
117               			if (!*line) {
118               			    warning("%s, line %d: incomplete undef == \"%s\"\n",
119               				file_red->i_file, filep->f_line, line);
120               			    break;
121               			}
122               			undefine(line, file_red);
123               			break;
124               		case INCLUDE:
125               			add_include(filep, file, file_red, line, FALSE, failOK);
126               			break;
127               		case INCLUDEDOT:
128 dawes 1.1     			add_include(filep, file, file_red, line, TRUE, failOK);
129               			break;
130               		case ERROR:
131               		    	warning("%s: %d: %s\n", file_red->i_file,
132               				 filep->f_line, line);
133               		    	break;
134               		    
135               		case PRAGMA:
136               		case IDENT:
137               		case SCCS:
138               		case EJECT:
139               			break;
140               		case -1:
141               			warning("%s", file_red->i_file);
142               			if (file_red != file)
143               			    warning1(" (reading %s)", file->i_file);
144               			warning1(", line %d: unknown directive == \"%s\"\n",
145               				 filep->f_line, line);
146               			break;
147               		case -2:
148               			warning("%s", file_red->i_file);
149 dawes 1.1     			if (file_red != file)
150               			    warning1(" (reading %s)", file->i_file);
151               			warning1(", line %d: incomplete include == \"%s\"\n",
152               				 filep->f_line, line);
153               			break;
154               		}
155               	}
156 dawes 1.1.1.2 	file->i_flags |= FINISHED;
157 dawes 1.1     	return(-1);
158               }
159               
160               gobble(filep, file, file_red)
161               	register struct filepointer *filep;
162               	struct inclist		*file, *file_red;
163               {
164               	register char	*line;
165               	register int	type;
166               
167               	while (line = getline(filep)) {
168               		switch(type = deftype(line, filep, file_red, file, FALSE)) {
169               		case IF:
170               		case IFFALSE:
171               		case IFGUESSFALSE:
172               		case IFDEF:
173               		case IFNDEF:
174               			type = gobble(filep, file, file_red);
175               			while ((type == ELIF) || (type == ELIFFALSE) ||
176               			       (type == ELIFGUESSFALSE))
177               			    type = gobble(filep, file, file_red);
178 dawes 1.1     			if (type == ELSE)
179               			        (void)gobble(filep, file, file_red);
180               			break;
181               		case ELSE:
182               		case ENDIF:
183               			debug(0,("%s, line %d: #%s\n",
184               				file->i_file, filep->f_line,
185               				directives[type]));
186               			return(type);
187               		case DEFINE:
188               		case UNDEF:
189               		case INCLUDE:
190               		case INCLUDEDOT:
191               		case PRAGMA:
192               		case ERROR:
193               		case IDENT:
194               		case SCCS:
195               		case EJECT:
196               			break;
197               		case ELIF:
198               		case ELIFFALSE:
199 dawes 1.1     		case ELIFGUESSFALSE:
200               			return(type);
201               		case -1:
202               			warning("%s, line %d: unknown directive == \"%s\"\n",
203               				file_red->i_file, filep->f_line, line);
204               			break;
205               		}
206               	}
207               	return(-1);
208               }
209               
210               /*
211                * Decide what type of # directive this line is.
212                */
213               int deftype (line, filep, file_red, file, parse_it)
214               	register char	*line;
215               	register struct filepointer *filep;
216               	register struct inclist *file_red, *file;
217               	int	parse_it;
218               {
219               	register char	*p;
220 dawes 1.1     	char	*directive, savechar;
221               	register int	ret;
222               
223               	/*
224               	 * Parse the directive...
225               	 */
226               	directive=line+1;
227               	while (*directive == ' ' || *directive == '\t')
228               		directive++;
229               
230               	p = directive;
231               	while (*p >= 'a' && *p <= 'z')
232               		p++;
233               	savechar = *p;
234               	*p = '\0';
235               	ret = match(directive, directives);
236               	*p = savechar;
237               
238               	/* If we don't recognize this compiler directive or we happen to just
239               	 * be gobbling up text while waiting for an #endif or #elif or #else
240               	 * in the case of an #elif we must check the zero_value and return an
241 dawes 1.1     	 * ELIF or an ELIFFALSE.
242               	 */
243               
244               	if (ret == ELIF && !parse_it)
245               	{
246               	    while (*p == ' ' || *p == '\t')
247               		p++;
248               	    /*
249               	     * parse an expression.
250               	     */
251               	    debug(0,("%s, line %d: #elif %s ",
252               		   file->i_file, filep->f_line, p));
253               	    ret = zero_value(p, filep, file_red);
254               	    if (ret != IF)
255               	    {
256               		debug(0,("false...\n"));
257               		if (ret == IFFALSE)
258               		    return(ELIFFALSE);
259               		else
260               		    return(ELIFGUESSFALSE);
261               	    }
262 dawes 1.1     	    else
263               	    {
264               		debug(0,("true...\n"));
265               		return(ELIF);
266               	    }
267               	}
268               
269               	if (ret < 0 || ! parse_it)
270               		return(ret);
271               
272               	/*
273               	 * now decide how to parse the directive, and do it.
274               	 */
275               	while (*p == ' ' || *p == '\t')
276               		p++;
277               	switch (ret) {
278               	case IF:
279               		/*
280               		 * parse an expression.
281               		 */
282               		ret = zero_value(p, filep, file_red);
283 dawes 1.1     		debug(0,("%s, line %d: %s #if %s\n",
284               			 file->i_file, filep->f_line, ret?"false":"true", p));
285               		break;
286               	case IFDEF:
287               	case IFNDEF:
288               		debug(0,("%s, line %d: #%s %s\n",
289               			file->i_file, filep->f_line, directives[ret], p));
290               	case UNDEF:
291               		/*
292               		 * separate the name of a single symbol.
293               		 */
294               		while (isalnum(*p) || *p == '_')
295               			*line++ = *p++;
296               		*line = '\0';
297               		break;
298               	case INCLUDE:
299               		debug(2,("%s, line %d: #include %s\n",
300               			file->i_file, filep->f_line, p));
301               
302               		/* Support ANSI macro substitution */
303               		{
304 dawes 1.1.1.2 		    struct symtab **sym = isdefined(p, file_red, NULL);
305 dawes 1.1     		    while (sym) {
306 dawes 1.1.1.2 			p = (*sym)->s_value;
307 dawes 1.1     			debug(3,("%s : #includes SYMBOL %s = %s\n",
308               			       file->i_incstring,
309 dawes 1.1.1.2 			       (*sym) -> s_name,
310               			       (*sym) -> s_value));
311 dawes 1.1     			/* mark file as having included a 'soft include' */
312 dawes 1.1.1.2 			file->i_flags |= INCLUDED_SYM; 
313 dawes 1.1     			sym = isdefined(p, file_red, NULL);
314               		    }
315               		}
316               
317               		/*
318               		 * Separate the name of the include file.
319               		 */
320               		while (*p && *p != '"' && *p != '<')
321               			p++;
322               		if (! *p)
323               			return(-2);
324               		if (*p++ == '"') {
325               			ret = INCLUDEDOT;
326               			while (*p && *p != '"')
327               				*line++ = *p++;
328               		} else
329               			while (*p && *p != '>')
330               				*line++ = *p++;
331               		*line = '\0';
332               		break;
333               	case DEFINE:
334 dawes 1.1     		/*
335               		 * copy the definition back to the beginning of the line.
336               		 */
337               		strcpy (line, p);
338               		break;
339               	case ELSE:
340               	case ENDIF:
341               	case ELIF:
342               	case PRAGMA:
343               	case ERROR:
344               	case IDENT:
345               	case SCCS:
346               	case EJECT:
347               		debug(0,("%s, line %d: #%s\n",
348               			file->i_file, filep->f_line, directives[ret]));
349               		/*
350               		 * nothing to do.
351               		 */
352               		break;
353               	}
354               	return(ret);
355 dawes 1.1     }
356               
357 dawes 1.1.1.2 struct symtab **isdefined(symbol, file, srcfile)
358 dawes 1.1     	register char	*symbol;
359               	struct inclist	*file;
360               	struct inclist	**srcfile;
361               {
362 dawes 1.1.1.2 	register struct symtab	**val;
363 dawes 1.1     
364               	if (val = slookup(symbol, &maininclist)) {
365               		debug(1,("%s defined on command line\n", symbol));
366               		if (srcfile != NULL) *srcfile = &maininclist;
367               		return(val);
368               	}
369               	if (val = fdefined(symbol, file, srcfile))
370               		return(val);
371               	debug(1,("%s not defined in %s\n", symbol, file->i_file));
372               	return(NULL);
373               }
374               
375 dawes 1.1.1.2 struct symtab **fdefined(symbol, file, srcfile)
376 dawes 1.1     	register char	*symbol;
377               	struct inclist	*file;
378               	struct inclist	**srcfile;
379               {
380               	register struct inclist	**ip;
381 dawes 1.1.1.2 	register struct symtab	**val;
382 dawes 1.1     	register int	i;
383               	static int	recurse_lvl = 0;
384               
385 dawes 1.1.1.2 	if (file->i_flags & DEFCHECKED)
386 dawes 1.1     		return(NULL);
387 dawes 1.1.1.2 	file->i_flags |= DEFCHECKED;
388 dawes 1.1     	if (val = slookup(symbol, file))
389 dawes 1.1.1.2 		debug(1,("%s defined in %s as %s\n",
390               			 symbol, file->i_file, (*val)->s_value));
391 dawes 1.1     	if (val == NULL && file->i_list)
392               		{
393               		for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
394 dawes 1.1.1.2 			if (file->i_merged[i]==FALSE) {
395               				val = fdefined(symbol, *ip, srcfile);
396               				if ((*ip)->i_flags & FINISHED) {
397               					merge2defines(file,*ip);
398               					file->i_merged[i]=TRUE;
399               				    }
400               				if (val!=NULL) break;
401 dawes 1.1     			}
402               		}
403               	else if (val != NULL && srcfile != NULL) *srcfile = file;
404               	recurse_lvl--;
405 dawes 1.1.1.2 	file->i_flags &= ~DEFCHECKED;
406 dawes 1.1     
407               	return(val);
408               }
409               
410               /*
411                * Return type based on if the #if expression evaluates to 0
412                */
413               zero_value(exp, filep, file_red)
414               	register char	*exp;
415               	register struct filepointer *filep;
416               	register struct inclist *file_red;
417               {
418               	if (cppsetup(exp, filep, file_red))
419               	    return(IFFALSE);
420               	else
421               	    return(IF);
422               }
423               
424               define(def, file)
425               	char	*def;
426               	struct inclist	*file;
427 dawes 1.1     {
428                   char *val;
429               
430                   /* Separate symbol name and its value */
431                   val = def;
432                   while (isalnum(*val) || *val == '_')
433               	val++;
434                   if (*val)
435               	*val++ = '\0';
436                   while (*val == ' ' || *val == '\t')
437               	val++;
438               
439                   if (!*val)
440               	val = "1";
441                   define2(def, val, file);
442               }
443               
444               define2(name, val, file)
445               	char	*name, *val;
446               	struct inclist	*file;
447               {
448 dawes 1.1         int first, last, below;
449 dawes 1.1.1.2     register struct symtab **sp = NULL, **dest;
450                   struct symtab *stab;
451 dawes 1.1     
452                   /* Make space if it's needed */
453                   if (file->i_defs == NULL)
454                   {
455 dawes 1.1.1.2 	file->i_defs = (struct symtab **)
456               			malloc(sizeof (struct symtab*) * SYMTABINC);
457 dawes 1.1     	file->i_ndefs = 0;
458                   }
459 dawes 1.1.1.2     else if (!(file->i_ndefs % SYMTABINC))
460               	file->i_defs = (struct symtab **)
461 dawes 1.1     			realloc(file->i_defs,
462 dawes 1.1.1.2 			   sizeof(struct symtab*)*(file->i_ndefs+SYMTABINC));
463 dawes 1.1     
464                   if (file->i_defs == NULL)
465               	fatalerr("malloc()/realloc() failure in insert_defn()\n");
466               
467                   below = first = 0;
468                   last = file->i_ndefs - 1;
469                   while (last >= first)
470                   {
471               	/* Fast inline binary search */
472               	register char *s1;
473               	register char *s2;
474               	register int middle = (first + last) / 2;
475               
476               	/* Fast inline strchr() */
477               	s1 = name;
478 dawes 1.1.1.2 	s2 = file->i_defs[middle]->s_name;
479 dawes 1.1     	while (*s1++ == *s2++)
480               	    if (s2[-1] == '\0') break;
481               
482               	/* If exact match, set sp and break */
483               	if (*--s1 == *--s2) 
484               	{
485               	    sp = file->i_defs + middle;
486               	    break;
487               	}
488               
489               	/* If name > i_defs[middle] ... */
490               	if (*s1 > *s2) 
491               	{
492               	    below = first;
493               	    first = middle + 1;
494               	}
495               	/* else ... */
496               	else
497               	{
498               	    below = last = middle - 1;
499               	}
500 dawes 1.1         }
501               
502                   /* Search is done.  If we found an exact match to the symbol name,
503                      just replace its s_value */
504                   if (sp != NULL)
505                   {
506 dawes 1.1.1.2 	free((*sp)->s_value);
507               	(*sp)->s_value = copy(val);
508 dawes 1.1     	return;
509                   }
510               
511                   sp = file->i_defs + file->i_ndefs++;
512                   dest = file->i_defs + below + 1;
513                   while (sp > dest)
514                   {
515               	*sp = sp[-1];
516               	sp--;
517                   }
518 dawes 1.1.1.2     stab = (struct symtab *) malloc(sizeof (struct symtab));
519                   if (stab == NULL)
520               	fatalerr("malloc()/realloc() failure in insert_defn()\n");
521               
522                   stab->s_name = copy(name);
523                   stab->s_value = copy(val);
524                   *sp = stab;
525 dawes 1.1     }
526               
527 dawes 1.1.1.2 struct symtab **slookup(symbol, file)
528 dawes 1.1     	register char	*symbol;
529               	register struct inclist	*file;
530               {
531               	register int first = 0;
532               	register int last = file->i_ndefs - 1;
533               
534               	if (file) while (last >= first)
535               	{
536               	    /* Fast inline binary search */
537               	    register char *s1;
538               	    register char *s2;
539               	    register int middle = (first + last) / 2;
540               
541               	    /* Fast inline strchr() */
542               	    s1 = symbol;
543 dawes 1.1.1.2 	    s2 = file->i_defs[middle]->s_name;
544 dawes 1.1     	    while (*s1++ == *s2++)
545               	        if (s2[-1] == '\0') break;
546               
547               	    /* If exact match, we're done */
548               	    if (*--s1 == *--s2) 
549               	    {
550               	        return file->i_defs + middle;
551               	    }
552               
553               	    /* If symbol > i_defs[middle] ... */
554               	    if (*s1 > *s2) 
555               	    {
556               	        first = middle + 1;
557               	    }
558               	    /* else ... */
559               	    else
560               	    {
561               	        last = middle - 1;
562               	    }
563               	}
564               	return(NULL);
565 dawes 1.1     }
566               
567 dawes 1.1.1.2 int merge2defines(file1, file2)
568               	struct inclist	*file1;
569               	struct inclist	*file2;
570               {
571               	if ((file1!=NULL) && (file2!=NULL)) 
572                       {
573               		int first1 = 0;
574               		int last1 = file1->i_ndefs - 1;
575               
576               		int first2 = 0;
577               		int last2 = file2->i_ndefs - 1;
578               
579                               int first=0;
580                               struct symtab** i_defs = NULL;
581               		int deflen=file1->i_ndefs+file2->i_ndefs;
582               
583                               if (deflen>0)
584                               { 
585                               	/* make sure deflen % SYMTABINC == 0 is still true */
586                               	deflen += (SYMTABINC - deflen % SYMTABINC) % SYMTABINC;
587                               	i_defs=(struct symtab**)
588 dawes 1.1.1.2 			    malloc(deflen*sizeof(struct symtab*));
589                               	if (i_defs==NULL) return 0;
590                       	}
591               
592                       	while ((last1 >= first1) && (last2 >= first2))
593                       	{
594               	    		char *s1=file1->i_defs[first1]->s_name;
595               	    		char *s2=file2->i_defs[first2]->s_name;
596               
597                    			if (strcmp(s1,s2) < 0)
598                                       	i_defs[first++]=file1->i_defs[first1++];
599                    			else if (strcmp(s1,s2) > 0)
600                                       	i_defs[first++]=file2->i_defs[first2++];
601                                       else /* equal */
602                                       {
603                                       	i_defs[first++]=file2->i_defs[first2++];
604                                               first1++;
605                                       }
606                       	}
607                       	while (last1 >= first1)
608                       	{
609 dawes 1.1.1.2                         i_defs[first++]=file1->i_defs[first1++];
610                       	}
611                       	while (last2 >= first2)
612                       	{
613                                       i_defs[first++]=file2->i_defs[first2++];
614                       	}
615               
616                               if (file1->i_defs) free(file1->i_defs);
617                               file1->i_defs=i_defs;
618                               file1->i_ndefs=first;
619                               
620               		return 1;
621                 	}
622               	return 0;
623               }
624               
625 dawes 1.1     undefine(symbol, file)
626               	char	*symbol;
627               	register struct inclist	*file;
628               {
629 dawes 1.1.1.2 	register struct symtab **ptr;
630 dawes 1.1     	struct inclist *srcfile;
631               	while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
632               	{
633               	    srcfile->i_ndefs--;
634               	    for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
635               		*ptr = ptr[1];
636               	}
637               }
638 dawes 1.1.1.2 

Powered by
ViewCVS 0.9.2