parse.c revision 63165362
11.149Soster/*
21.1Soster
31.1SosterCopyright (c) 1993, 1994, 1998 The Open Group
41.1Soster
51.1SosterPermission to use, copy, modify, distribute, and sell this software and its
61.1Sosterdocumentation for any purpose is hereby granted without fee, provided that
71.1Sosterthe above copyright notice appear in all copies and that both that
81.1Sostercopyright notice and this permission notice appear in supporting
91.1Sosterdocumentation.
101.1Soster
111.1SosterThe above copyright notice and this permission notice shall be included in
121.1Sosterall copies or substantial portions of the Software.
131.1Soster
141.1SosterTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
151.1SosterIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
161.1SosterFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
171.1SosterOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
181.1SosterAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
191.1SosterCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
201.1Soster
211.1SosterExcept as contained in this notice, the name of The Open Group shall not be
221.1Sosterused in advertising or otherwise to promote the sale, use or other dealings
231.1Sosterin this Software without prior written authorization from The Open Group.
241.1Soster
251.1Soster*/
261.1Soster
271.1Soster#include "def.h"
281.1Soster
291.1Sosterextern const char * const directives[];
301.1Sosterextern struct inclist	inclist[ MAXFILES ],
311.1Soster			*inclistnext,
321.1Soster			maininclist;
331.1Sosterextern const char	*includedirs[ ],
341.1Soster			**includedirsnext;
351.1Soster
361.1Sosterstatic int deftype (char *line, struct filepointer *filep,
371.1Soster		    struct inclist *file_red, struct inclist *file,
381.1Soster		    int parse_it);
391.1Sosterstatic int zero_value(char *filename, char *exp, struct filepointer *filep,
401.1Soster		    struct inclist *file_red);
411.1Sosterstatic int merge2defines(struct inclist *file1, struct inclist *file2);
421.1Soster
431.1Sosterstatic int
441.1Sostergobble(struct filepointer *filep, struct inclist *file,
451.1Soster       struct inclist *file_red)
461.1Soster{
471.1Soster	char	*line;
481.1Soster	int	type;
491.1Soster
501.1Soster	while ((line = getnextline(filep))) {
511.1Soster		switch(type = deftype(line, filep, file_red, file, FALSE)) {
521.1Soster		case IF:
531.1Soster		case IFFALSE:
541.1Soster		case IFGUESSFALSE:
551.1Soster		case IFDEF:
561.1Soster		case IFNDEF:
571.1Soster			type = gobble(filep, file, file_red);
581.1Soster			while ((type == ELIF) || (type == ELIFFALSE) ||
591.1Soster			       (type == ELIFGUESSFALSE))
601.1Soster			    type = gobble(filep, file, file_red);
611.1Soster			if (type == ELSE)
621.1Soster			        (void)gobble(filep, file, file_red);
631.1Soster			break;
641.1Soster		case ELSE:
651.1Soster		case ENDIF:
661.1Soster			debug(0,("%s, line %d: #%s\n",
671.1Soster				file->i_file, filep->f_line,
681.1Soster				directives[type]));
691.1Soster			return(type);
701.1Soster		case DEFINE:
711.1Soster		case UNDEF:
721.1Soster		case INCLUDE:
731.1Soster		case INCLUDEDOT:
741.1Soster		case PRAGMA:
751.1Soster		case ERROR:
761.1Soster		case IDENT:
771.1Soster		case SCCS:
781.1Soster		case EJECT:
791.1Soster		case WARNING:
801.1Soster		case INCLUDENEXT:
811.1Soster		case INCLUDENEXTDOT:
821.1Soster			break;
831.1Soster		case ELIF:
841.1Soster		case ELIFFALSE:
851.1Soster		case ELIFGUESSFALSE:
861.1Soster			return(type);
871.1Soster		case -1:
881.1Soster			warning("%s", file_red->i_file);
891.1Soster			if (file_red != file)
901.1Soster				warning1(" (reading %s)", file->i_file);
911.1Soster			warning1(", line %ld: unknown directive == \"%s\"\n",
921.1Soster				filep->f_line, line);
931.1Soster			break;
941.1Soster		}
951.1Soster	}
961.1Soster	return(-1);
971.1Soster}
981.1Soster
991.1Soster/*
1001.1Soster * Decide what type of # directive this line is.
1011.1Soster */
1021.1Sosterstatic int
1031.1Sosterdeftype (char *line, struct filepointer *filep,
1041.1Soster	     struct inclist *file_red, struct inclist *file, int parse_it)
1051.1Soster{
1061.1Soster	register char	*p;
1071.1Soster	char	*directive, savechar, *q;
1081.1Soster	register int	ret;
1091.1Soster
1101.1Soster	/*
1111.1Soster	 * Parse the directive...
1121.1Soster	 */
1131.1Soster	directive=line+1;
1141.1Soster	while (*directive == ' ' || *directive == '\t')
1151.112Slukem		directive++;
1161.112Slukem
1171.149Soster	p = directive;
1181.1Soster	while ((*p == '_') || (*p >= 'a' && *p <= 'z'))
1191.113Slukem		p++;
1201.1Soster	savechar = *p;
1211.1Soster	*p = '\0';
1221.1Soster	ret = match(directive, directives);
1231.1Soster	*p = savechar;
1241.1Soster
1251.1Soster	/* If we don't recognize this compiler directive or we happen to just
1261.1Soster	 * be gobbling up text while waiting for an #endif or #elif or #else
1271.1Soster	 * in the case of an #elif we must check the zero_value and return an
1281.1Soster	 * ELIF or an ELIFFALSE.
1291.1Soster	 */
1301.1Soster
1311.1Soster	if (ret == ELIF && !parse_it)
1321.1Soster	{
1331.1Soster	    while (*p == ' ' || *p == '\t')
1341.1Soster		p++;
1351.1Soster	    /*
1361.65Soster	     * parse an expression.
1371.8Soster	     */
1381.110Soster	    debug(0,("%s, line %d: #elif %s ",
1391.110Soster		   file->i_file, filep->f_line, p));
1401.8Soster	    ret = zero_value(file->i_file, p, filep, file_red);
1411.62Soster	    if (ret != IF)
1421.1Soster	    {
1431.44Soster		debug(0,("false...\n"));
1441.1Soster		if (ret == IFFALSE)
1451.1Soster		    return(ELIFFALSE);
1461.99Soster		else
1471.1Soster		    return(ELIFGUESSFALSE);
1481.1Soster	    }
1491.1Soster	    else
1501.1Soster	    {
1511.1Soster		debug(0,("true...\n"));
1521.1Soster		return(ELIF);
1531.1Soster	    }
1541.1Soster	}
1551.1Soster
1561.133Soster	if (ret < 0 || ! parse_it)
1571.9Soster		return(ret);
1581.1Soster
1591.9Soster	/*
1601.1Soster	 * now decide how to parse the directive, and do it.
1611.9Soster	 */
1621.1Soster	while (*p == ' ' || *p == '\t')
1631.9Soster		p++;
1641.1Soster	q = p + strlen(p);
1651.11Soster	do {
1661.1Soster		q--;
1671.10Soster	} while (*q == ' ' || *q == '\t');
1681.10Soster	q[1] = '\0';
1691.10Soster	switch (ret) {
1701.10Soster	case IF:
1711.10Soster		/*
1721.1Soster		 * parse an expression.
1731.10Soster		 */
1741.10Soster		ret = zero_value(file->i_file, p, filep, file_red);
1751.10Soster		debug(0,("%s, line %d: %s #if %s\n",
1761.10Soster			 file->i_file, filep->f_line, ret?"false":"true", p));
1771.10Soster		break;
1781.10Soster	case IFDEF:
1791.104Soster	case IFNDEF:
1801.1Soster		debug(0,("%s, line %d: #%s %s\n",
1811.104Soster			file->i_file, filep->f_line, directives[ret], p));
1821.130Sgehenna	case UNDEF:
1831.130Sgehenna		/*
1841.130Sgehenna		 * separate the name of a single symbol.
1851.130Sgehenna		 */
1861.130Sgehenna		while (isalnum(*p) || *p == '_')
1871.130Sgehenna			*line++ = *p++;
1881.130Sgehenna		*line = '\0';
1891.130Sgehenna		break;
1901.130Sgehenna	case INCLUDE:
1911.130Sgehenna	case INCLUDENEXT:
1921.130Sgehenna		debug(2,("%s, line %d: #include%s %s\n",
1931.130Sgehenna			file->i_file, filep->f_line,
1941.130Sgehenna			(ret == INCLUDE) ? "" : "_next", p));
1951.130Sgehenna
1961.130Sgehenna		/* Support ANSI macro substitution */
1971.130Sgehenna		while (1) {
1981.130Sgehenna			struct symtab **sym;
1991.144Sjdolecek
2001.130Sgehenna			if (!*p || *p == '"' || *p == '<')
2011.1Soster				break;
2021.1Soster
2031.1Soster		    	sym = isdefined(p, file_red, NULL);
2041.1Soster			if (!sym)
2051.1Soster				break;
2061.10Soster
2071.10Soster			p = (*sym)->s_value;
2081.10Soster			debug(3,("%s : #includes SYMBOL %s = %s\n",
2091.11Soster			       file->i_incstring,
2101.10Soster			       (*sym) -> s_name,
2111.1Soster			       (*sym) -> s_value));
2121.116Sthorpej			/* mark file as having included a 'soft include' */
2131.116Sthorpej			file->i_flags |= INCLUDED_SYM;
2141.1Soster		}
2151.9Soster
2161.53Soster		/*
2171.59Soster		 * Separate the name of the include file.
2181.1Soster		 */
2191.10Soster		while (*p && *p != '"' && *p != '<')
2201.10Soster			p++;
2211.10Soster		if (! *p)
2221.11Soster			return(-2);
2231.10Soster		if (*p++ == '"') {
2241.10Soster			if (ret == INCLUDE)
2251.125Shannken				ret = INCLUDEDOT;
2261.10Soster			else
2271.1Soster				ret = INCLUDENEXTDOT;
2281.1Soster			while (*p && *p != '"')
2291.1Soster				*line++ = *p++;
2301.1Soster		} else
2311.1Soster			while (*p && *p != '>')
2321.1Soster				*line++ = *p++;
2331.1Soster		*line = '\0';
2341.1Soster		break;
2351.48Soster	case DEFINE:
2361.1Soster		/*
2371.20Soster		 * copy the definition back to the beginning of the line.
2381.20Soster		 */
2391.20Soster		strcpy (line, p);
2401.28Soster		break;
2411.28Soster	case ELSE:
2421.28Soster	case ENDIF:
2431.28Soster	case ELIF:
2441.28Soster	case PRAGMA:
2451.28Soster	case ERROR:
2461.110Soster	case IDENT:
2471.28Soster	case SCCS:
2481.28Soster	case EJECT:
2491.28Soster	case WARNING:
2501.28Soster		debug(0,("%s, line %d: #%s\n",
2511.28Soster			file->i_file, filep->f_line, directives[ret]));
2521.20Soster		/*
2531.20Soster		 * nothing to do.
2541.20Soster		 */
2551.28Soster		break;
2561.20Soster	}
2571.20Soster	return(ret);
2581.1Soster}
2591.1Soster
2601.1Sosterstruct symtab **
2611.1Sosterfdefined(char *symbol, struct inclist *file, struct inclist **srcfile)
2621.10Soster{
2631.9Soster	struct inclist	**ip;
2641.104Soster	struct symtab	**val;
2651.104Soster	int	i;
2661.104Soster	static int	recurse_lvl = 0;
2671.104Soster
2681.1Soster	if (file->i_flags & DEFCHECKED)
2691.104Soster		return(NULL);
2701.104Soster	debug(2,("Looking for %s in %s\n", symbol, file->i_file));
2711.1Soster	file->i_flags |= DEFCHECKED;
2721.104Soster	if ((val = slookup(symbol, file)))
2731.48Soster		debug(1,("%s defined in %s as %s\n",
2741.48Soster			 symbol, file->i_file, (*val)->s_value));
2751.1Soster	if (val == NULL && file->i_list)
2761.104Soster	{
2771.37Soster		for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
2781.104Soster			if (file->i_merged[i]==FALSE) {
2791.104Soster				val = fdefined(symbol, *ip, srcfile);
2801.104Soster				file->i_merged[i]=merge2defines(file,*ip);
2811.104Soster				if (val!=NULL) break;
2821.142Sthorpej			}
2831.142Sthorpej	}
2841.104Soster	else if (val != NULL && srcfile != NULL) *srcfile = file;
2851.104Soster	recurse_lvl--;
2861.104Soster	file->i_flags &= ~DEFCHECKED;
2871.104Soster
2881.104Soster	return(val);
2891.104Soster}
2901.104Soster
2911.104Sosterstruct symtab **
2921.104Sosterisdefined(char *symbol, struct inclist *file, struct inclist **srcfile)
2931.104Soster{
2941.104Soster	struct symtab	**val;
2951.104Soster
2961.48Soster	if ((val = slookup(symbol, &maininclist))) {
2971.48Soster		debug(1,("%s defined on command line\n", symbol));
2981.62Soster		if (srcfile != NULL) *srcfile = &maininclist;
2991.62Soster		return(val);
3001.62Soster	}
3011.62Soster	if ((val = fdefined(symbol, file, srcfile)))
3021.37Soster		return(val);
3031.10Soster	debug(1,("%s not defined in %s\n", symbol, file->i_file));
3041.10Soster	return(NULL);
3051.9Soster}
3061.1Soster
3071.14Soster/*
3081.14Soster * Return type based on if the #if expression evaluates to 0
3091.1Soster */
3101.1Sosterstatic int
3111.9Sosterzero_value(char *filename,
3121.1Soster	   char *exp,
3131.1Soster	   struct filepointer *filep,
3141.1Soster	   struct inclist *file_red)
3151.1Soster{
3161.1Soster	if (cppsetup(filename, exp, filep, file_red))
3171.1Soster	    return(IFFALSE);
3181.1Soster	else
3191.1Soster	    return(IF);
3201.9Soster}
3211.1Soster
3221.50Sostervoid
3231.50Sosterdefine2(char *name, char *val, struct inclist *file)
3241.1Soster{
3251.1Soster    int first, last, below;
3261.1Soster    register struct symtab **sp = NULL, **dest;
3271.1Soster    struct symtab *stab;
3281.141Sprovos
3291.1Soster    /* Make space if it's needed */
3301.116Sthorpej    if (file->i_defs == NULL)
3311.116Sthorpej    {
3321.116Sthorpej	file->i_defs = (struct symtab **)
3331.117Sthorpej			malloc(sizeof (struct symtab*) * SYMTABINC);
3341.116Sthorpej	file->i_ndefs = 0;
3351.14Soster    }
3361.14Soster    else if (!(file->i_ndefs % SYMTABINC))
3371.14Soster	file->i_defs = (struct symtab **)
3381.14Soster			realloc(file->i_defs,
3391.14Soster			   sizeof(struct symtab*)*(file->i_ndefs+SYMTABINC));
3401.14Soster
3411.14Soster    if (file->i_defs == NULL)
3421.58Soster	fatalerr("malloc()/realloc() failure in insert_defn()\n");
3431.14Soster
3441.14Soster    below = first = 0;
3451.14Soster    last = file->i_ndefs - 1;
3461.14Soster    while (last >= first)
3471.14Soster    {
3481.141Sprovos	/* Fast inline binary search */
3491.14Soster	register char *s1;
3501.9Soster	register char *s2;
3511.9Soster	register int middle = (first + last) / 2;
3521.1Soster
3531.1Soster	/* Fast inline strchr() */
3541.48Soster	s1 = name;
3551.48Soster	s2 = file->i_defs[middle]->s_name;
3561.1Soster	while (*s1++ == *s2++)
3571.1Soster	    if (s2[-1] == '\0') break;
3581.1Soster
3591.1Soster	/* If exact match, set sp and break */
3601.50Soster	if (*--s1 == *--s2)
3611.108Sthorpej	{
3621.34Soster	    sp = file->i_defs + middle;
3631.48Soster	    break;
3641.48Soster	}
3651.48Soster
3661.141Sprovos	/* If name > i_defs[middle] ... */
3671.48Soster	if (*s1 > *s2)
3681.48Soster	{
3691.9Soster	    below = first;
3701.126Shannken	    first = middle + 1;
3711.48Soster	}
3721.48Soster	/* else ... */
3731.48Soster	else
3741.48Soster	{
3751.48Soster	    below = last = middle - 1;
3761.48Soster	}
3771.48Soster    }
3781.48Soster
3791.9Soster    /* Search is done.  If we found an exact match to the symbol name,
3801.11Soster       just replace its s_value */
3811.9Soster    if (sp != NULL)
3821.39Soster    {
3831.39Soster	debug(1,("redefining %s from %s to %s in file %s\n",
3841.39Soster		name, (*sp)->s_value, val, file->i_file));
3851.1Soster	free((*sp)->s_value);
3861.1Soster	(*sp)->s_value = copy(val);
3871.48Soster	return;
3881.114Slukem    }
3891.62Soster
3901.62Soster    sp = file->i_defs + file->i_ndefs++;
3911.62Soster    dest = file->i_defs + below + 1;
3921.142Sthorpej    while (sp > dest)
3931.142Sthorpej    {
3941.142Sthorpej	*sp = sp[-1];
3951.142Sthorpej	sp--;
3961.142Sthorpej    }
3971.142Sthorpej    stab = (struct symtab *) malloc(sizeof (struct symtab));
3981.142Sthorpej    if (stab == NULL)
3991.142Sthorpej	fatalerr("malloc()/realloc() failure in insert_defn()\n");
4001.142Sthorpej
4011.142Sthorpej    debug(1,("defining %s to %s in file %s\n", name, val, file->i_file));
4021.142Sthorpej    stab->s_name = copy(name);
4031.142Sthorpej    stab->s_value = copy(val);
4041.142Sthorpej    *sp = stab;
4051.142Sthorpej}
4061.142Sthorpej
4071.142Sthorpejvoid
4081.142Sthorpejdefine(char *def, struct inclist *file)
4091.142Sthorpej{
4101.142Sthorpej    char *val;
4111.142Sthorpej
4121.48Soster    /* Separate symbol name and its value */
4131.142Sthorpej    val = def;
4141.142Sthorpej    while (isalnum(*val) || *val == '_')
4151.48Soster	val++;
4161.48Soster    if (*val)
4171.48Soster	*val++ = '\0';
4181.142Sthorpej    while (*val == ' ' || *val == '\t')
4191.48Soster	val++;
4201.48Soster
4211.142Sthorpej    if (!*val)
4221.142Sthorpej	val = "1";
4231.142Sthorpej    define2(def, val, file);
4241.142Sthorpej}
4251.142Sthorpej
4261.48Sosterstruct symtab **
4271.142Sthorpejslookup(char *symbol, struct inclist *file)
4281.48Soster{
4291.48Soster	register int first = 0;
4301.48Soster	register int last;
4311.142Sthorpej
4321.48Soster	if (file == NULL)
4331.48Soster	    return NULL;
4341.48Soster
4351.51Soster	last = file->i_ndefs - 1;
4361.48Soster
4371.51Soster	while (last >= first)
4381.51Soster	{
4391.48Soster	    /* Fast inline binary search */
4401.101Soster	    register char *s1;
4411.51Soster	    register char *s2;
4421.48Soster	    register int middle = (first + last) / 2;
4431.48Soster
4441.48Soster	    /* Fast inline strchr() */
4451.51Soster	    s1 = symbol;
4461.51Soster	    s2 = file->i_defs[middle]->s_name;
4471.51Soster	    while (*s1++ == *s2++)
4481.51Soster	        if (s2[-1] == '\0') break;
4491.51Soster
4501.51Soster	    /* If exact match, we're done */
4511.51Soster	    if (*--s1 == *--s2)
4521.51Soster	    {
4531.51Soster	        return file->i_defs + middle;
4541.51Soster	    }
4551.51Soster
4561.51Soster	    /* If symbol > i_defs[middle] ... */
4571.51Soster	    if (*s1 > *s2)
4581.51Soster	    {
4591.48Soster	        first = middle + 1;
4601.48Soster	    }
4611.48Soster	    /* else ... */
4621.48Soster	    else
4631.49Soster	    {
4641.48Soster	        last = middle - 1;
4651.48Soster	    }
4661.49Soster	}
4671.48Soster	return(NULL);
4681.48Soster}
4691.122Soster
4701.122Sosterstatic int
4711.122Sostermerge2defines(struct inclist *file1, struct inclist *file2)
4721.122Soster{
4731.122Soster	int i;
4741.122Soster
4751.122Soster	if ((file1==NULL) || (file2==NULL) ||
4761.122Soster	    !(file2->i_flags & FINISHED))
4771.51Soster		return 0;
4781.1Soster
4791.1Soster	for (i=0; i < file2->i_listlen; i++)
4801.1Soster		if (file2->i_merged[i]==FALSE)
4811.1Soster			return 0;
4821.1Soster
4831.9Soster	{
4841.1Soster		int first1 = 0;
4851.1Soster		int last1 = file1->i_ndefs - 1;
4861.1Soster
4871.9Soster		int first2 = 0;
4881.1Soster		int last2 = file2->i_ndefs - 1;
4891.1Soster
4901.1Soster                int first=0;
4911.1Soster                struct symtab** i_defs = NULL;
4921.1Soster		int deflen=file1->i_ndefs+file2->i_ndefs;
4931.1Soster
4941.1Soster		debug(2,("merging %s into %s\n",
4951.1Soster			file2->i_file, file1->i_file));
4961.1Soster
4971.1Soster                if (deflen>0)
4981.1Soster                {
4991.1Soster                	/* make sure deflen % SYMTABINC == 0 is still true */
5001.1Soster                	deflen += (SYMTABINC - deflen % SYMTABINC) % SYMTABINC;
5011.1Soster                	i_defs=(struct symtab**)
5021.1Soster			    malloc(deflen*sizeof(struct symtab*));
5031.1Soster                	if (i_defs==NULL) return 0;
5041.1Soster        	}
5051.1Soster
5061.1Soster        	while ((last1 >= first1) && (last2 >= first2))
5071.1Soster        	{
5081.1Soster	    		char *s1=file1->i_defs[first1]->s_name;
5091.1Soster	    		char *s2=file2->i_defs[first2]->s_name;
5101.1Soster
5111.1Soster     			if (strcmp(s1,s2) < 0)
5121.1Soster                        	i_defs[first++]=file1->i_defs[first1++];
5131.1Soster     			else if (strcmp(s1,s2) > 0)
5141.1Soster                        	i_defs[first++]=file2->i_defs[first2++];
5151.1Soster                        else /* equal */
5161.1Soster                        {
5171.1Soster                        	i_defs[first++]=file2->i_defs[first2++];
5181.1Soster                                first1++;
5191.9Soster                        }
5201.1Soster        	}
5211.1Soster        	while (last1 >= first1)
5221.9Soster        	{
5231.1Soster                        i_defs[first++]=file1->i_defs[first1++];
5241.1Soster        	}
5251.1Soster        	while (last2 >= first2)
5261.1Soster        	{
5271.1Soster                        i_defs[first++]=file2->i_defs[first2++];
5281.1Soster        	}
5291.1Soster
5301.9Soster                if (file1->i_defs) free(file1->i_defs);
5311.9Soster                file1->i_defs=i_defs;
5321.1Soster                file1->i_ndefs=first;
5331.1Soster
5341.9Soster		return 1;
5351.1Soster  	}
5361.1Soster}
5371.9Soster
5381.9Sostervoid
5391.9Sosterundefine(char *symbol, struct inclist *file)
5401.1Soster{
5411.1Soster	register struct symtab **ptr;
5421.1Soster	struct inclist *srcfile;
5431.1Soster	while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
5441.1Soster	{
5451.9Soster	    srcfile->i_ndefs--;
5461.1Soster	    for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
5471.1Soster		*ptr = ptr[1];
5481.1Soster	}
5491.1Soster}
5501.1Soster
5511.1Sosterint
5521.1Sosterfind_includes(struct filepointer *filep, struct inclist *file,
5531.9Soster	      struct inclist *file_red, int recursion, boolean failOK)
5541.1Soster{
5551.1Soster	struct inclist	*inclistp;
5561.1Soster	const char	**includedirsp;
5571.1Soster	register char	*line;
5581.1Soster	register int	type;
5591.1Soster	boolean recfailOK;
5601.9Soster
5611.1Soster	while ((line = getnextline(filep))) {
5621.1Soster		switch(type = deftype(line, filep, file_red, file, TRUE)) {
5631.9Soster		case IF:
5641.1Soster		doif:
5651.1Soster			type = find_includes(filep, file,
5661.1Soster				file_red, recursion+1, failOK);
5671.1Soster			while ((type == ELIF) || (type == ELIFFALSE) ||
5681.1Soster			       (type == ELIFGUESSFALSE))
5691.1Soster				type = gobble(filep, file, file_red);
5701.1Soster			if (type == ELSE)
5711.1Soster				gobble(filep, file, file_red);
5721.1Soster			break;
5731.1Soster		case IFFALSE:
5741.1Soster		case IFGUESSFALSE:
5751.1Soster		    doiffalse:
5761.13Soster			if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
5771.13Soster			    recfailOK = TRUE;
5781.13Soster			else
5791.13Soster			    recfailOK = failOK;
5801.13Soster			type = gobble(filep, file, file_red);
5811.13Soster			if (type == ELSE)
5821.13Soster			    find_includes(filep, file,
5831.13Soster					  file_red, recursion+1, recfailOK);
5841.13Soster			else
5851.13Soster			if (type == ELIF)
5861.13Soster			    goto doif;
5871.13Soster			else
5881.13Soster			if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
5891.13Soster			    goto doiffalse;
5901.13Soster			break;
5911.1Soster		case IFDEF:
5921.1Soster		case IFNDEF:
5931.1Soster			if ((type == IFDEF && isdefined(line, file_red, NULL))
5941.1Soster			 || (type == IFNDEF && !isdefined(line, file_red, NULL))) {
5951.1Soster				debug(1,(type == IFNDEF ?
5961.9Soster				    "line %d: %s !def'd in %s via %s%s\n" : "",
5971.1Soster				    filep->f_line, line,
5981.1Soster				    file->i_file, file_red->i_file, ": doit"));
5991.1Soster				type = find_includes(filep, file,
6001.1Soster					file_red, recursion+1, failOK);
6011.1Soster				while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
6021.1Soster					type = gobble(filep, file, file_red);
6031.9Soster				if (type == ELSE)
6041.9Soster					gobble(filep, file, file_red);
6051.1Soster			}
6061.1Soster			else {
6071.9Soster				debug(1,(type == IFDEF ?
6081.1Soster				    "line %d: %s !def'd in %s via %s%s\n" : "",
6091.9Soster				    filep->f_line, line,
6101.9Soster				    file->i_file, file_red->i_file, ": gobble"));
6111.1Soster				type = gobble(filep, file, file_red);
6121.1Soster				if (type == ELSE)
6131.1Soster					find_includes(filep, file,
6141.1Soster						file_red, recursion+1, failOK);
6151.1Soster				else if (type == ELIF)
6161.1Soster				    	goto doif;
6171.1Soster				else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
6181.1Soster				    	goto doiffalse;
6191.1Soster			}
6201.1Soster			break;
6211.1Soster		case ELSE:
6221.1Soster		case ELIFFALSE:
6231.1Soster		case ELIFGUESSFALSE:
6241.1Soster		case ELIF:
6251.1Soster			if (!recursion)
6261.1Soster				gobble(filep, file, file_red);
6271.1Soster		case ENDIF:
6281.1Soster			if (recursion)
6291.1Soster				return(type);
6301.1Soster		case DEFINE:
6311.1Soster			define(line, file);
6321.1Soster			break;
6331.13Soster		case UNDEF:
6341.13Soster			if (!*line) {
6351.13Soster			    warning("%s", file_red->i_file);
6361.13Soster			    if (file_red != file)
6371.13Soster				warning1(" (reading %s)", file->i_file);
6381.13Soster			    warning1(", line %ld: incomplete undef == \"%s\"\n",
6391.13Soster				filep->f_line, line);
6401.147Soster			    break;
6411.91Soster			}
6421.91Soster			undefine(line, file_red);
6431.107Soster			break;
6441.107Soster		case INCLUDE:
6451.107Soster		case INCLUDEDOT:
6461.107Soster		case INCLUDENEXT:
6471.107Soster		case INCLUDENEXTDOT:
6481.107Soster			inclistp = inclistnext;
6491.107Soster			includedirsp = includedirsnext;
6501.107Soster			debug(2,("%s, reading %s, includes %s\n",
6511.107Soster				file_red->i_file, file->i_file, line));
6521.107Soster			add_include(filep, file, file_red, line, type, failOK);
6531.107Soster			inclistnext = inclistp;
6541.13Soster			includedirsnext = includedirsp;
6551.1Soster			break;
6561.1Soster		case ERROR:
6571.1Soster		case WARNING:
6581.1Soster		    	warning("%s", file_red->i_file);
6591.1Soster			if (file_red != file)
6601.1Soster				warning1(" (reading %s)", file->i_file);
6611.1Soster			warning1(", line %ld: %s\n",
6621.1Soster				 filep->f_line, line);
6631.74Saugustss		    	break;
6641.1Soster
6651.74Saugustss		case PRAGMA:
6661.1Soster		case IDENT:
6671.1Soster		case SCCS:
6681.1Soster		case EJECT:
6691.1Soster			break;
6701.1Soster		case -1:
6711.9Soster			warning("%s", file_red->i_file);
6721.1Soster			if (file_red != file)
6731.30Soster			    warning1(" (reading %s)", file->i_file);
6741.30Soster			warning1(", line %ld: unknown directive == \"%s\"\n",
6751.100Schs				 filep->f_line, line);
6761.30Soster			break;
6771.30Soster		case -2:
6781.1Soster			warning("%s", file_red->i_file);
6791.30Soster			if (file_red != file)
6801.1Soster			    warning1(" (reading %s)", file->i_file);
6811.1Soster			warning1(", line %ld: incomplete include == \"%s\"\n",
6821.1Soster				 filep->f_line, line);
6831.1Soster			break;
6841.1Soster		}
6851.1Soster	}
6861.1Soster	file->i_flags |= FINISHED;
6871.1Soster	debug(2,("finished with %s\n", file->i_file));
6881.1Soster	return(-1);
6891.1Soster}
6901.1Soster