parse.c revision d43532a6
10eb10989Smrg/*
20eb10989Smrg
30eb10989SmrgCopyright (c) 1993, 1994, 1998 The Open Group
40eb10989Smrg
50eb10989SmrgPermission to use, copy, modify, distribute, and sell this software and its
60eb10989Smrgdocumentation for any purpose is hereby granted without fee, provided that
70eb10989Smrgthe above copyright notice appear in all copies and that both that
80eb10989Smrgcopyright notice and this permission notice appear in supporting
90eb10989Smrgdocumentation.
100eb10989Smrg
110eb10989SmrgThe above copyright notice and this permission notice shall be included in
120eb10989Smrgall copies or substantial portions of the Software.
130eb10989Smrg
140eb10989SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
150eb10989SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
160eb10989SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
170eb10989SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
180eb10989SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
190eb10989SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
200eb10989Smrg
210eb10989SmrgExcept as contained in this notice, the name of The Open Group shall not be
220eb10989Smrgused in advertising or otherwise to promote the sale, use or other dealings
230eb10989Smrgin this Software without prior written authorization from The Open Group.
240eb10989Smrg
250eb10989Smrg*/
260eb10989Smrg
270eb10989Smrg#include "def.h"
280eb10989Smrg
290eb10989Smrgstatic int deftype (char *line, struct filepointer *filep,
300eb10989Smrg		    struct inclist *file_red, struct inclist *file,
310eb10989Smrg		    int parse_it);
320eb10989Smrgstatic int zero_value(char *filename, char *exp, struct filepointer *filep,
330eb10989Smrg		    struct inclist *file_red);
340eb10989Smrgstatic int merge2defines(struct inclist *file1, struct inclist *file2);
350eb10989Smrg
360eb10989Smrgstatic int
370eb10989Smrggobble(struct filepointer *filep, struct inclist *file,
380eb10989Smrg       struct inclist *file_red)
390eb10989Smrg{
400eb10989Smrg	char	*line;
410eb10989Smrg	int	type;
420eb10989Smrg
430eb10989Smrg	while ((line = getnextline(filep))) {
440eb10989Smrg		switch(type = deftype(line, filep, file_red, file, FALSE)) {
450eb10989Smrg		case IF:
460eb10989Smrg		case IFFALSE:
470eb10989Smrg		case IFGUESSFALSE:
480eb10989Smrg		case IFDEF:
490eb10989Smrg		case IFNDEF:
500eb10989Smrg			type = gobble(filep, file, file_red);
510eb10989Smrg			while ((type == ELIF) || (type == ELIFFALSE) ||
520eb10989Smrg			       (type == ELIFGUESSFALSE))
530eb10989Smrg			    type = gobble(filep, file, file_red);
540eb10989Smrg			if (type == ELSE)
550eb10989Smrg			        (void)gobble(filep, file, file_red);
560eb10989Smrg			break;
570eb10989Smrg		case ELSE:
580eb10989Smrg		case ENDIF:
590eb10989Smrg			debug(0,("%s, line %d: #%s\n",
600eb10989Smrg				file->i_file, filep->f_line,
610eb10989Smrg				directives[type]));
620eb10989Smrg			return(type);
630eb10989Smrg		case DEFINE:
640eb10989Smrg		case UNDEF:
650eb10989Smrg		case INCLUDE:
660eb10989Smrg		case INCLUDEDOT:
670eb10989Smrg		case PRAGMA:
680eb10989Smrg		case ERROR:
690eb10989Smrg		case IDENT:
700eb10989Smrg		case SCCS:
710eb10989Smrg		case EJECT:
720eb10989Smrg		case WARNING:
730eb10989Smrg		case INCLUDENEXT:
740eb10989Smrg		case INCLUDENEXTDOT:
750eb10989Smrg			break;
760eb10989Smrg		case ELIF:
770eb10989Smrg		case ELIFFALSE:
780eb10989Smrg		case ELIFGUESSFALSE:
790eb10989Smrg			return(type);
800eb10989Smrg		case -1:
810eb10989Smrg			warning("%s", file_red->i_file);
820eb10989Smrg			if (file_red != file)
830eb10989Smrg				warning1(" (reading %s)", file->i_file);
8463165362Smrg			warning1(", line %ld: unknown directive == \"%s\"\n",
850eb10989Smrg				filep->f_line, line);
860eb10989Smrg			break;
870eb10989Smrg		}
880eb10989Smrg	}
890eb10989Smrg	return(-1);
900eb10989Smrg}
910eb10989Smrg
920eb10989Smrg/*
930eb10989Smrg * Decide what type of # directive this line is.
940eb10989Smrg */
95d43532a6Smrgstatic int
96d43532a6Smrgdeftype (char *line, struct filepointer *filep,
970eb10989Smrg	     struct inclist *file_red, struct inclist *file, int parse_it)
980eb10989Smrg{
990eb10989Smrg	register char	*p;
1000eb10989Smrg	char	*directive, savechar, *q;
1010eb10989Smrg	register int	ret;
1020eb10989Smrg
1030eb10989Smrg	/*
1040eb10989Smrg	 * Parse the directive...
1050eb10989Smrg	 */
1060eb10989Smrg	directive=line+1;
1070eb10989Smrg	while (*directive == ' ' || *directive == '\t')
1080eb10989Smrg		directive++;
1090eb10989Smrg
1100eb10989Smrg	p = directive;
1110eb10989Smrg	while ((*p == '_') || (*p >= 'a' && *p <= 'z'))
1120eb10989Smrg		p++;
1130eb10989Smrg	savechar = *p;
1140eb10989Smrg	*p = '\0';
1150eb10989Smrg	ret = match(directive, directives);
1160eb10989Smrg	*p = savechar;
1170eb10989Smrg
1180eb10989Smrg	/* If we don't recognize this compiler directive or we happen to just
1190eb10989Smrg	 * be gobbling up text while waiting for an #endif or #elif or #else
1200eb10989Smrg	 * in the case of an #elif we must check the zero_value and return an
1210eb10989Smrg	 * ELIF or an ELIFFALSE.
1220eb10989Smrg	 */
1230eb10989Smrg
1240eb10989Smrg	if (ret == ELIF && !parse_it)
1250eb10989Smrg	{
1260eb10989Smrg	    while (*p == ' ' || *p == '\t')
1270eb10989Smrg		p++;
1280eb10989Smrg	    /*
1290eb10989Smrg	     * parse an expression.
1300eb10989Smrg	     */
1310eb10989Smrg	    debug(0,("%s, line %d: #elif %s ",
1320eb10989Smrg		   file->i_file, filep->f_line, p));
1330eb10989Smrg	    ret = zero_value(file->i_file, p, filep, file_red);
1340eb10989Smrg	    if (ret != IF)
1350eb10989Smrg	    {
1360eb10989Smrg		debug(0,("false...\n"));
1370eb10989Smrg		if (ret == IFFALSE)
1380eb10989Smrg		    return(ELIFFALSE);
1390eb10989Smrg		else
1400eb10989Smrg		    return(ELIFGUESSFALSE);
1410eb10989Smrg	    }
1420eb10989Smrg	    else
1430eb10989Smrg	    {
1440eb10989Smrg		debug(0,("true...\n"));
1450eb10989Smrg		return(ELIF);
1460eb10989Smrg	    }
1470eb10989Smrg	}
1480eb10989Smrg
1490eb10989Smrg	if (ret < 0 || ! parse_it)
1500eb10989Smrg		return(ret);
1510eb10989Smrg
1520eb10989Smrg	/*
1530eb10989Smrg	 * now decide how to parse the directive, and do it.
1540eb10989Smrg	 */
1550eb10989Smrg	while (*p == ' ' || *p == '\t')
1560eb10989Smrg		p++;
1570eb10989Smrg	q = p + strlen(p);
1580eb10989Smrg	do {
1590eb10989Smrg		q--;
1600eb10989Smrg	} while (*q == ' ' || *q == '\t');
1610eb10989Smrg	q[1] = '\0';
1620eb10989Smrg	switch (ret) {
1630eb10989Smrg	case IF:
1640eb10989Smrg		/*
1650eb10989Smrg		 * parse an expression.
1660eb10989Smrg		 */
1670eb10989Smrg		ret = zero_value(file->i_file, p, filep, file_red);
1680eb10989Smrg		debug(0,("%s, line %d: %s #if %s\n",
1690eb10989Smrg			 file->i_file, filep->f_line, ret?"false":"true", p));
1700eb10989Smrg		break;
1710eb10989Smrg	case IFDEF:
1720eb10989Smrg	case IFNDEF:
1730eb10989Smrg		debug(0,("%s, line %d: #%s %s\n",
1740eb10989Smrg			file->i_file, filep->f_line, directives[ret], p));
1750eb10989Smrg	case UNDEF:
1760eb10989Smrg		/*
1770eb10989Smrg		 * separate the name of a single symbol.
1780eb10989Smrg		 */
1790eb10989Smrg		while (isalnum(*p) || *p == '_')
1800eb10989Smrg			*line++ = *p++;
1810eb10989Smrg		*line = '\0';
1820eb10989Smrg		break;
1830eb10989Smrg	case INCLUDE:
1840eb10989Smrg	case INCLUDENEXT:
1850eb10989Smrg		debug(2,("%s, line %d: #include%s %s\n",
1860eb10989Smrg			file->i_file, filep->f_line,
1870eb10989Smrg			(ret == INCLUDE) ? "" : "_next", p));
1880eb10989Smrg
1890eb10989Smrg		/* Support ANSI macro substitution */
1900eb10989Smrg		while (1) {
1910eb10989Smrg			struct symtab **sym;
1920eb10989Smrg
1930eb10989Smrg			if (!*p || *p == '"' || *p == '<')
1940eb10989Smrg				break;
1950eb10989Smrg
1960eb10989Smrg		    	sym = isdefined(p, file_red, NULL);
1970eb10989Smrg			if (!sym)
1980eb10989Smrg				break;
1990eb10989Smrg
2000eb10989Smrg			p = (*sym)->s_value;
2010eb10989Smrg			debug(3,("%s : #includes SYMBOL %s = %s\n",
2020eb10989Smrg			       file->i_incstring,
2030eb10989Smrg			       (*sym) -> s_name,
2040eb10989Smrg			       (*sym) -> s_value));
2050eb10989Smrg			/* mark file as having included a 'soft include' */
206d43532a6Smrg			file->i_flags |= INCLUDED_SYM;
2070eb10989Smrg		}
2080eb10989Smrg
2090eb10989Smrg		/*
2100eb10989Smrg		 * Separate the name of the include file.
2110eb10989Smrg		 */
2120eb10989Smrg		while (*p && *p != '"' && *p != '<')
2130eb10989Smrg			p++;
2140eb10989Smrg		if (! *p)
2150eb10989Smrg			return(-2);
2160eb10989Smrg		if (*p++ == '"') {
2170eb10989Smrg			if (ret == INCLUDE)
2180eb10989Smrg				ret = INCLUDEDOT;
2190eb10989Smrg			else
2200eb10989Smrg				ret = INCLUDENEXTDOT;
2210eb10989Smrg			while (*p && *p != '"')
2220eb10989Smrg				*line++ = *p++;
2230eb10989Smrg		} else
2240eb10989Smrg			while (*p && *p != '>')
2250eb10989Smrg				*line++ = *p++;
2260eb10989Smrg		*line = '\0';
2270eb10989Smrg		break;
2280eb10989Smrg	case DEFINE:
2290eb10989Smrg		/*
2300eb10989Smrg		 * copy the definition back to the beginning of the line.
2310eb10989Smrg		 */
2320eb10989Smrg		strcpy (line, p);
2330eb10989Smrg		break;
2340eb10989Smrg	case ELSE:
2350eb10989Smrg	case ENDIF:
2360eb10989Smrg	case ELIF:
2370eb10989Smrg	case PRAGMA:
2380eb10989Smrg	case ERROR:
2390eb10989Smrg	case IDENT:
2400eb10989Smrg	case SCCS:
2410eb10989Smrg	case EJECT:
2420eb10989Smrg	case WARNING:
2430eb10989Smrg		debug(0,("%s, line %d: #%s\n",
2440eb10989Smrg			file->i_file, filep->f_line, directives[ret]));
2450eb10989Smrg		/*
2460eb10989Smrg		 * nothing to do.
2470eb10989Smrg		 */
2480eb10989Smrg		break;
2490eb10989Smrg	}
2500eb10989Smrg	return(ret);
2510eb10989Smrg}
2520eb10989Smrg
2530eb10989Smrgstruct symtab **
254d43532a6Smrgfdefined(const char *symbol, struct inclist *file, struct inclist **srcfile)
2550eb10989Smrg{
2560eb10989Smrg	struct inclist	**ip;
2570eb10989Smrg	struct symtab	**val;
2580eb10989Smrg	int	i;
2590eb10989Smrg	static int	recurse_lvl = 0;
2600eb10989Smrg
2610eb10989Smrg	if (file->i_flags & DEFCHECKED)
2620eb10989Smrg		return(NULL);
2630eb10989Smrg	debug(2,("Looking for %s in %s\n", symbol, file->i_file));
2640eb10989Smrg	file->i_flags |= DEFCHECKED;
2650eb10989Smrg	if ((val = slookup(symbol, file)))
2660eb10989Smrg		debug(1,("%s defined in %s as %s\n",
2670eb10989Smrg			 symbol, file->i_file, (*val)->s_value));
2680eb10989Smrg	if (val == NULL && file->i_list)
2690eb10989Smrg	{
2700eb10989Smrg		for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
2710eb10989Smrg			if (file->i_merged[i]==FALSE) {
2720eb10989Smrg				val = fdefined(symbol, *ip, srcfile);
2730eb10989Smrg				file->i_merged[i]=merge2defines(file,*ip);
2740eb10989Smrg				if (val!=NULL) break;
2750eb10989Smrg			}
2760eb10989Smrg	}
2770eb10989Smrg	else if (val != NULL && srcfile != NULL) *srcfile = file;
2780eb10989Smrg	recurse_lvl--;
2790eb10989Smrg	file->i_flags &= ~DEFCHECKED;
2800eb10989Smrg
2810eb10989Smrg	return(val);
2820eb10989Smrg}
2830eb10989Smrg
2840eb10989Smrgstruct symtab **
285d43532a6Smrgisdefined(const char *symbol, struct inclist *file, struct inclist **srcfile)
2860eb10989Smrg{
2870eb10989Smrg	struct symtab	**val;
2880eb10989Smrg
2890eb10989Smrg	if ((val = slookup(symbol, &maininclist))) {
2900eb10989Smrg		debug(1,("%s defined on command line\n", symbol));
2910eb10989Smrg		if (srcfile != NULL) *srcfile = &maininclist;
2920eb10989Smrg		return(val);
2930eb10989Smrg	}
2940eb10989Smrg	if ((val = fdefined(symbol, file, srcfile)))
2950eb10989Smrg		return(val);
2960eb10989Smrg	debug(1,("%s not defined in %s\n", symbol, file->i_file));
2970eb10989Smrg	return(NULL);
2980eb10989Smrg}
2990eb10989Smrg
3000eb10989Smrg/*
3010eb10989Smrg * Return type based on if the #if expression evaluates to 0
3020eb10989Smrg */
3030eb10989Smrgstatic int
3040eb10989Smrgzero_value(char *filename,
3050eb10989Smrg	   char *exp,
3060eb10989Smrg	   struct filepointer *filep,
3070eb10989Smrg	   struct inclist *file_red)
3080eb10989Smrg{
3090eb10989Smrg	if (cppsetup(filename, exp, filep, file_red))
3100eb10989Smrg	    return(IFFALSE);
3110eb10989Smrg	else
3120eb10989Smrg	    return(IF);
3130eb10989Smrg}
3140eb10989Smrg
3150eb10989Smrgvoid
316d43532a6Smrgdefine2(const char *name, const char *val, struct inclist *file)
3170eb10989Smrg{
3180eb10989Smrg    int first, last, below;
3190eb10989Smrg    register struct symtab **sp = NULL, **dest;
3200eb10989Smrg    struct symtab *stab;
3210eb10989Smrg
3220eb10989Smrg    /* Make space if it's needed */
3230eb10989Smrg    if (file->i_defs == NULL)
3240eb10989Smrg    {
3250eb10989Smrg	file->i_defs = (struct symtab **)
3260eb10989Smrg			malloc(sizeof (struct symtab*) * SYMTABINC);
3270eb10989Smrg	file->i_ndefs = 0;
3280eb10989Smrg    }
3290eb10989Smrg    else if (!(file->i_ndefs % SYMTABINC))
3300eb10989Smrg	file->i_defs = (struct symtab **)
3310eb10989Smrg			realloc(file->i_defs,
3320eb10989Smrg			   sizeof(struct symtab*)*(file->i_ndefs+SYMTABINC));
3330eb10989Smrg
3340eb10989Smrg    if (file->i_defs == NULL)
3350eb10989Smrg	fatalerr("malloc()/realloc() failure in insert_defn()\n");
3360eb10989Smrg
3370eb10989Smrg    below = first = 0;
3380eb10989Smrg    last = file->i_ndefs - 1;
3390eb10989Smrg    while (last >= first)
3400eb10989Smrg    {
3410eb10989Smrg	/* Fast inline binary search */
342d43532a6Smrg	register const char *s1;
343d43532a6Smrg	register const char *s2;
3440eb10989Smrg	register int middle = (first + last) / 2;
3450eb10989Smrg
3460eb10989Smrg	/* Fast inline strchr() */
3470eb10989Smrg	s1 = name;
3480eb10989Smrg	s2 = file->i_defs[middle]->s_name;
3490eb10989Smrg	while (*s1++ == *s2++)
3500eb10989Smrg	    if (s2[-1] == '\0') break;
3510eb10989Smrg
3520eb10989Smrg	/* If exact match, set sp and break */
353d43532a6Smrg	if (*--s1 == *--s2)
3540eb10989Smrg	{
3550eb10989Smrg	    sp = file->i_defs + middle;
3560eb10989Smrg	    break;
3570eb10989Smrg	}
3580eb10989Smrg
3590eb10989Smrg	/* If name > i_defs[middle] ... */
360d43532a6Smrg	if (*s1 > *s2)
3610eb10989Smrg	{
3620eb10989Smrg	    below = first;
3630eb10989Smrg	    first = middle + 1;
3640eb10989Smrg	}
3650eb10989Smrg	/* else ... */
3660eb10989Smrg	else
3670eb10989Smrg	{
3680eb10989Smrg	    below = last = middle - 1;
3690eb10989Smrg	}
3700eb10989Smrg    }
3710eb10989Smrg
3720eb10989Smrg    /* Search is done.  If we found an exact match to the symbol name,
3730eb10989Smrg       just replace its s_value */
3740eb10989Smrg    if (sp != NULL)
3750eb10989Smrg    {
3760eb10989Smrg	debug(1,("redefining %s from %s to %s in file %s\n",
3770eb10989Smrg		name, (*sp)->s_value, val, file->i_file));
3780eb10989Smrg	free((*sp)->s_value);
379d43532a6Smrg	(*sp)->s_value = strdup(val);
3800eb10989Smrg	return;
3810eb10989Smrg    }
3820eb10989Smrg
3830eb10989Smrg    sp = file->i_defs + file->i_ndefs++;
3840eb10989Smrg    dest = file->i_defs + below + 1;
3850eb10989Smrg    while (sp > dest)
3860eb10989Smrg    {
3870eb10989Smrg	*sp = sp[-1];
3880eb10989Smrg	sp--;
3890eb10989Smrg    }
3900eb10989Smrg    stab = (struct symtab *) malloc(sizeof (struct symtab));
3910eb10989Smrg    if (stab == NULL)
3920eb10989Smrg	fatalerr("malloc()/realloc() failure in insert_defn()\n");
3930eb10989Smrg
3940eb10989Smrg    debug(1,("defining %s to %s in file %s\n", name, val, file->i_file));
395d43532a6Smrg    stab->s_name = strdup(name);
396d43532a6Smrg    stab->s_value = strdup(val);
3970eb10989Smrg    *sp = stab;
3980eb10989Smrg}
3990eb10989Smrg
4000eb10989Smrgvoid
4010eb10989Smrgdefine(char *def, struct inclist *file)
4020eb10989Smrg{
4030eb10989Smrg    char *val;
4040eb10989Smrg
4050eb10989Smrg    /* Separate symbol name and its value */
4060eb10989Smrg    val = def;
4070eb10989Smrg    while (isalnum(*val) || *val == '_')
4080eb10989Smrg	val++;
4090eb10989Smrg    if (*val)
4100eb10989Smrg	*val++ = '\0';
4110eb10989Smrg    while (*val == ' ' || *val == '\t')
4120eb10989Smrg	val++;
4130eb10989Smrg
4140eb10989Smrg    if (!*val)
415d43532a6Smrg	define2(def, "1", file);
416d43532a6Smrg    else
417d43532a6Smrg	define2(def, val, file);
4180eb10989Smrg}
4190eb10989Smrg
4200eb10989Smrgstruct symtab **
421d43532a6Smrgslookup(const char *symbol, struct inclist *file)
4220eb10989Smrg{
4230eb10989Smrg	register int first = 0;
4240eb10989Smrg	register int last;
4250eb10989Smrg
4260eb10989Smrg	if (file == NULL)
4270eb10989Smrg	    return NULL;
4280eb10989Smrg
4290eb10989Smrg	last = file->i_ndefs - 1;
430d43532a6Smrg
4310eb10989Smrg	while (last >= first)
4320eb10989Smrg	{
4330eb10989Smrg	    /* Fast inline binary search */
434d43532a6Smrg	    register const char *s1;
435d43532a6Smrg	    register const char *s2;
4360eb10989Smrg	    register int middle = (first + last) / 2;
4370eb10989Smrg
4380eb10989Smrg	    /* Fast inline strchr() */
4390eb10989Smrg	    s1 = symbol;
4400eb10989Smrg	    s2 = file->i_defs[middle]->s_name;
4410eb10989Smrg	    while (*s1++ == *s2++)
4420eb10989Smrg	        if (s2[-1] == '\0') break;
4430eb10989Smrg
4440eb10989Smrg	    /* If exact match, we're done */
445d43532a6Smrg	    if (*--s1 == *--s2)
4460eb10989Smrg	    {
4470eb10989Smrg	        return file->i_defs + middle;
4480eb10989Smrg	    }
4490eb10989Smrg
4500eb10989Smrg	    /* If symbol > i_defs[middle] ... */
451d43532a6Smrg	    if (*s1 > *s2)
4520eb10989Smrg	    {
4530eb10989Smrg	        first = middle + 1;
4540eb10989Smrg	    }
4550eb10989Smrg	    /* else ... */
4560eb10989Smrg	    else
4570eb10989Smrg	    {
4580eb10989Smrg	        last = middle - 1;
4590eb10989Smrg	    }
4600eb10989Smrg	}
4610eb10989Smrg	return(NULL);
4620eb10989Smrg}
4630eb10989Smrg
464d43532a6Smrgstatic int
4650eb10989Smrgmerge2defines(struct inclist *file1, struct inclist *file2)
4660eb10989Smrg{
4670eb10989Smrg	int i;
4680eb10989Smrg
4690eb10989Smrg	if ((file1==NULL) || (file2==NULL) ||
4700eb10989Smrg	    !(file2->i_flags & FINISHED))
4710eb10989Smrg		return 0;
4720eb10989Smrg
4730eb10989Smrg	for (i=0; i < file2->i_listlen; i++)
4740eb10989Smrg		if (file2->i_merged[i]==FALSE)
4750eb10989Smrg			return 0;
4760eb10989Smrg
4770eb10989Smrg	{
4780eb10989Smrg		int first1 = 0;
4790eb10989Smrg		int last1 = file1->i_ndefs - 1;
4800eb10989Smrg
4810eb10989Smrg		int first2 = 0;
4820eb10989Smrg		int last2 = file2->i_ndefs - 1;
4830eb10989Smrg
4840eb10989Smrg                int first=0;
4850eb10989Smrg                struct symtab** i_defs = NULL;
4860eb10989Smrg		int deflen=file1->i_ndefs+file2->i_ndefs;
4870eb10989Smrg
4880eb10989Smrg		debug(2,("merging %s into %s\n",
4890eb10989Smrg			file2->i_file, file1->i_file));
4900eb10989Smrg
4910eb10989Smrg                if (deflen>0)
492d43532a6Smrg                {
4930eb10989Smrg                	/* make sure deflen % SYMTABINC == 0 is still true */
4940eb10989Smrg                	deflen += (SYMTABINC - deflen % SYMTABINC) % SYMTABINC;
4950eb10989Smrg                	i_defs=(struct symtab**)
4960eb10989Smrg			    malloc(deflen*sizeof(struct symtab*));
4970eb10989Smrg                	if (i_defs==NULL) return 0;
4980eb10989Smrg        	}
4990eb10989Smrg
5000eb10989Smrg        	while ((last1 >= first1) && (last2 >= first2))
5010eb10989Smrg        	{
5020eb10989Smrg	    		char *s1=file1->i_defs[first1]->s_name;
5030eb10989Smrg	    		char *s2=file2->i_defs[first2]->s_name;
5040eb10989Smrg
5050eb10989Smrg     			if (strcmp(s1,s2) < 0)
5060eb10989Smrg                        	i_defs[first++]=file1->i_defs[first1++];
5070eb10989Smrg     			else if (strcmp(s1,s2) > 0)
5080eb10989Smrg                        	i_defs[first++]=file2->i_defs[first2++];
5090eb10989Smrg                        else /* equal */
5100eb10989Smrg                        {
5110eb10989Smrg                        	i_defs[first++]=file2->i_defs[first2++];
5120eb10989Smrg                                first1++;
5130eb10989Smrg                        }
5140eb10989Smrg        	}
5150eb10989Smrg        	while (last1 >= first1)
5160eb10989Smrg        	{
5170eb10989Smrg                        i_defs[first++]=file1->i_defs[first1++];
5180eb10989Smrg        	}
5190eb10989Smrg        	while (last2 >= first2)
5200eb10989Smrg        	{
5210eb10989Smrg                        i_defs[first++]=file2->i_defs[first2++];
5220eb10989Smrg        	}
5230eb10989Smrg
5240eb10989Smrg                if (file1->i_defs) free(file1->i_defs);
5250eb10989Smrg                file1->i_defs=i_defs;
5260eb10989Smrg                file1->i_ndefs=first;
527d43532a6Smrg
5280eb10989Smrg		return 1;
5290eb10989Smrg  	}
5300eb10989Smrg}
5310eb10989Smrg
5320eb10989Smrgvoid
533d43532a6Smrgundefine(const char *symbol, struct inclist *file)
5340eb10989Smrg{
5350eb10989Smrg	register struct symtab **ptr;
5360eb10989Smrg	struct inclist *srcfile;
5370eb10989Smrg	while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
5380eb10989Smrg	{
5390eb10989Smrg	    srcfile->i_ndefs--;
5400eb10989Smrg	    for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
5410eb10989Smrg		*ptr = ptr[1];
5420eb10989Smrg	}
5430eb10989Smrg}
5440eb10989Smrg
5450eb10989Smrgint
546d43532a6Smrgfind_includes(struct filepointer *filep, struct inclist *file,
5470eb10989Smrg	      struct inclist *file_red, int recursion, boolean failOK)
5480eb10989Smrg{
5490eb10989Smrg	struct inclist	*inclistp;
55063165362Smrg	const char	**includedirsp;
5510eb10989Smrg	register char	*line;
5520eb10989Smrg	register int	type;
5530eb10989Smrg	boolean recfailOK;
5540eb10989Smrg
5550eb10989Smrg	while ((line = getnextline(filep))) {
5560eb10989Smrg		switch(type = deftype(line, filep, file_red, file, TRUE)) {
5570eb10989Smrg		case IF:
5580eb10989Smrg		doif:
5590eb10989Smrg			type = find_includes(filep, file,
5600eb10989Smrg				file_red, recursion+1, failOK);
5610eb10989Smrg			while ((type == ELIF) || (type == ELIFFALSE) ||
5620eb10989Smrg			       (type == ELIFGUESSFALSE))
5630eb10989Smrg				type = gobble(filep, file, file_red);
5640eb10989Smrg			if (type == ELSE)
5650eb10989Smrg				gobble(filep, file, file_red);
5660eb10989Smrg			break;
5670eb10989Smrg		case IFFALSE:
5680eb10989Smrg		case IFGUESSFALSE:
5690eb10989Smrg		    doiffalse:
5700eb10989Smrg			if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
5710eb10989Smrg			    recfailOK = TRUE;
5720eb10989Smrg			else
5730eb10989Smrg			    recfailOK = failOK;
5740eb10989Smrg			type = gobble(filep, file, file_red);
5750eb10989Smrg			if (type == ELSE)
5760eb10989Smrg			    find_includes(filep, file,
5770eb10989Smrg					  file_red, recursion+1, recfailOK);
5780eb10989Smrg			else
5790eb10989Smrg			if (type == ELIF)
5800eb10989Smrg			    goto doif;
5810eb10989Smrg			else
5820eb10989Smrg			if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
5830eb10989Smrg			    goto doiffalse;
5840eb10989Smrg			break;
5850eb10989Smrg		case IFDEF:
5860eb10989Smrg		case IFNDEF:
5870eb10989Smrg			if ((type == IFDEF && isdefined(line, file_red, NULL))
5880eb10989Smrg			 || (type == IFNDEF && !isdefined(line, file_red, NULL))) {
5890eb10989Smrg				debug(1,(type == IFNDEF ?
5900eb10989Smrg				    "line %d: %s !def'd in %s via %s%s\n" : "",
5910eb10989Smrg				    filep->f_line, line,
5920eb10989Smrg				    file->i_file, file_red->i_file, ": doit"));
5930eb10989Smrg				type = find_includes(filep, file,
5940eb10989Smrg					file_red, recursion+1, failOK);
5950eb10989Smrg				while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
5960eb10989Smrg					type = gobble(filep, file, file_red);
5970eb10989Smrg				if (type == ELSE)
5980eb10989Smrg					gobble(filep, file, file_red);
5990eb10989Smrg			}
6000eb10989Smrg			else {
6010eb10989Smrg				debug(1,(type == IFDEF ?
6020eb10989Smrg				    "line %d: %s !def'd in %s via %s%s\n" : "",
6030eb10989Smrg				    filep->f_line, line,
6040eb10989Smrg				    file->i_file, file_red->i_file, ": gobble"));
6050eb10989Smrg				type = gobble(filep, file, file_red);
6060eb10989Smrg				if (type == ELSE)
6070eb10989Smrg					find_includes(filep, file,
6080eb10989Smrg						file_red, recursion+1, failOK);
6090eb10989Smrg				else if (type == ELIF)
6100eb10989Smrg				    	goto doif;
6110eb10989Smrg				else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
6120eb10989Smrg				    	goto doiffalse;
6130eb10989Smrg			}
6140eb10989Smrg			break;
6150eb10989Smrg		case ELSE:
6160eb10989Smrg		case ELIFFALSE:
6170eb10989Smrg		case ELIFGUESSFALSE:
6180eb10989Smrg		case ELIF:
6190eb10989Smrg			if (!recursion)
6200eb10989Smrg				gobble(filep, file, file_red);
6210eb10989Smrg		case ENDIF:
6220eb10989Smrg			if (recursion)
6230eb10989Smrg				return(type);
6240eb10989Smrg		case DEFINE:
6250eb10989Smrg			define(line, file);
6260eb10989Smrg			break;
6270eb10989Smrg		case UNDEF:
6280eb10989Smrg			if (!*line) {
6290eb10989Smrg			    warning("%s", file_red->i_file);
6300eb10989Smrg			    if (file_red != file)
6310eb10989Smrg				warning1(" (reading %s)", file->i_file);
63263165362Smrg			    warning1(", line %ld: incomplete undef == \"%s\"\n",
6330eb10989Smrg				filep->f_line, line);
6340eb10989Smrg			    break;
6350eb10989Smrg			}
6360eb10989Smrg			undefine(line, file_red);
6370eb10989Smrg			break;
6380eb10989Smrg		case INCLUDE:
6390eb10989Smrg		case INCLUDEDOT:
6400eb10989Smrg		case INCLUDENEXT:
6410eb10989Smrg		case INCLUDENEXTDOT:
6420eb10989Smrg			inclistp = inclistnext;
6430eb10989Smrg			includedirsp = includedirsnext;
6440eb10989Smrg			debug(2,("%s, reading %s, includes %s\n",
6450eb10989Smrg				file_red->i_file, file->i_file, line));
6460eb10989Smrg			add_include(filep, file, file_red, line, type, failOK);
6470eb10989Smrg			inclistnext = inclistp;
6480eb10989Smrg			includedirsnext = includedirsp;
6490eb10989Smrg			break;
6500eb10989Smrg		case ERROR:
6510eb10989Smrg		case WARNING:
6520eb10989Smrg		    	warning("%s", file_red->i_file);
6530eb10989Smrg			if (file_red != file)
6540eb10989Smrg				warning1(" (reading %s)", file->i_file);
65563165362Smrg			warning1(", line %ld: %s\n",
6560eb10989Smrg				 filep->f_line, line);
6570eb10989Smrg		    	break;
658d43532a6Smrg
6590eb10989Smrg		case PRAGMA:
6600eb10989Smrg		case IDENT:
6610eb10989Smrg		case SCCS:
6620eb10989Smrg		case EJECT:
6630eb10989Smrg			break;
6640eb10989Smrg		case -1:
6650eb10989Smrg			warning("%s", file_red->i_file);
6660eb10989Smrg			if (file_red != file)
6670eb10989Smrg			    warning1(" (reading %s)", file->i_file);
66863165362Smrg			warning1(", line %ld: unknown directive == \"%s\"\n",
6690eb10989Smrg				 filep->f_line, line);
6700eb10989Smrg			break;
6710eb10989Smrg		case -2:
6720eb10989Smrg			warning("%s", file_red->i_file);
6730eb10989Smrg			if (file_red != file)
6740eb10989Smrg			    warning1(" (reading %s)", file->i_file);
67563165362Smrg			warning1(", line %ld: incomplete include == \"%s\"\n",
6760eb10989Smrg				 filep->f_line, line);
6770eb10989Smrg			break;
6780eb10989Smrg		}
6790eb10989Smrg	}
6800eb10989Smrg	file->i_flags |= FINISHED;
6810eb10989Smrg	debug(2,("finished with %s\n", file->i_file));
6820eb10989Smrg	return(-1);
6830eb10989Smrg}
684