1/*-
2 * Copyright (c) 1988, 1989, 1990, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 * Copyright (c) 1988, 1989 by Adam de Boor
5 * Copyright (c) 1989 by Berkeley Softworks
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Adam de Boor.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 *    must display the following acknowledgement:
21 *	This product includes software developed by the University of
22 *	California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 *    may be used to endorse or promote products derived from this software
25 *    without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * @(#)cond.c	8.2 (Berkeley) 1/2/94
40 */
41
42#include <sys/cdefs.h>
43__FBSDID("$FreeBSD$");
44
45/*
46 * Functions to handle conditionals in a makefile.
47 *
48 * Interface:
49 *	Cond_Eval	Evaluate the conditional in the passed line.
50 */
51
52#include <ctype.h>
53#include <string.h>
54#include <stdlib.h>
55
56#include "buf.h"
57#include "cond.h"
58#include "dir.h"
59#include "globals.h"
60#include "GNode.h"
61#include "make.h"
62#include "parse.h"
63#include "str.h"
64#include "targ.h"
65#include "util.h"
66#include "var.h"
67
68/*
69 * The parsing of conditional expressions is based on this grammar:
70 *	E -> F || E
71 *	E -> F
72 *	F -> T && F
73 *	F -> T
74 *	T -> defined(variable)
75 *	T -> make(target)
76 *	T -> exists(file)
77 *	T -> empty(varspec)
78 *	T -> target(name)
79 *	T -> symbol
80 *	T -> $(varspec) op value
81 *	T -> $(varspec) == "string"
82 *	T -> $(varspec) != "string"
83 *	T -> ( E )
84 *	T -> ! T
85 *	op -> == | != | > | < | >= | <=
86 *
87 * 'symbol' is some other symbol to which the default function (condDefProc)
88 * is applied.
89 *
90 * Tokens are scanned from the 'condExpr' string. The scanner (CondToken)
91 * will return And for '&' and '&&', Or for '|' and '||', Not for '!',
92 * LParen for '(', RParen for ')' and will evaluate the other terminal
93 * symbols, using either the default function or the function given in the
94 * terminal, and return the result as either True or False.
95 *
96 * All Non-Terminal functions (CondE, CondF and CondT) return Err on error.
97 */
98typedef enum {
99	And,
100	Or,
101	Not,
102	True,
103	False,
104	LParen,
105	RParen,
106	EndOfFile,
107	None,
108	Err
109} Token;
110
111typedef Boolean CondProc(int, char *);
112
113/*-
114 * Structures to handle elegantly the different forms of #if's. The
115 * last two fields are stored in condInvert and condDefProc, respectively.
116 */
117static void CondPushBack(Token);
118static int CondGetArg(char **, char **, const char *, Boolean);
119static CondProc	CondDoDefined;
120static CondProc	CondDoMake;
121static CondProc	CondDoExists;
122static CondProc	CondDoTarget;
123static char *CondCvtArg(char *, double *);
124static Token CondToken(Boolean);
125static Token CondT(Boolean);
126static Token CondF(Boolean);
127static Token CondE(Boolean);
128
129static const struct If {
130	Boolean	doNot;		/* TRUE if default function should be negated */
131	CondProc *defProc;	/* Default function to apply */
132	Boolean	isElse;		/* actually el<XXX> */
133} ifs[] = {
134	[COND_IF] =		{ FALSE,	CondDoDefined,	FALSE },
135	[COND_IFDEF] =		{ FALSE,	CondDoDefined,	FALSE },
136	[COND_IFNDEF] =		{ TRUE,		CondDoDefined,	FALSE },
137	[COND_IFMAKE] =		{ FALSE,	CondDoMake,	FALSE },
138	[COND_IFNMAKE] =	{ TRUE,		CondDoMake,	FALSE },
139	[COND_ELIF] =		{ FALSE,	CondDoDefined,	TRUE },
140	[COND_ELIFDEF] =	{ FALSE,	CondDoDefined,	TRUE },
141	[COND_ELIFNDEF] =	{ TRUE,		CondDoDefined,	TRUE },
142	[COND_ELIFMAKE] =	{ FALSE,	CondDoMake,	TRUE },
143	[COND_ELIFNMAKE] =	{ TRUE,		CondDoMake,	TRUE },
144};
145
146static Boolean	condInvert;	/* Invert the default function */
147static CondProc	*condDefProc;	/* default function to apply */
148static char	*condExpr;	/* The expression to parse */
149static Token	condPushBack = None; /* Single push-back token in parsing */
150
151#define MAXIF	30	/* greatest depth of #if'ing */
152
153static Boolean	condStack[MAXIF];	/* Stack of conditionals's values */
154static int	condLineno[MAXIF];	/* Line numbers of the opening .if */
155static int	condTop = MAXIF;	/* Top-most conditional */
156static int	skipIfLevel = 0;	/* Depth of skipped conditionals */
157static int	skipIfLineno[MAXIF];	/* Line numbers of skipped .ifs */
158Boolean		skipLine = FALSE;	/* Whether the parse module is skipping
159					 * lines */
160
161/**
162 * CondPushBack
163 *	Push back the most recent token read. We only need one level of
164 *	this, so the thing is just stored in 'condPushback'.
165 *
166 * Side Effects:
167 *	condPushback is overwritten.
168 */
169static void
170CondPushBack(Token t)
171{
172
173	condPushBack = t;
174}
175
176/**
177 * CondGetArg
178 *	Find the argument of a built-in function.  parens is set to TRUE
179 *	if the arguments are bounded by parens.
180 *
181 * Results:
182 *	The length of the argument and the address of the argument.
183 *
184 * Side Effects:
185 *	The pointer is set to point to the closing parenthesis of the
186 *	function call.
187 */
188static int
189CondGetArg(char **linePtr, char **argPtr, const char *func, Boolean parens)
190{
191	char	*cp;
192	size_t	argLen;
193	Buffer	*buf;
194
195	cp = *linePtr;
196	if (parens) {
197		while (*cp != '(' && *cp != '\0') {
198			cp++;
199		}
200		if (*cp == '(') {
201			cp++;
202		}
203	}
204
205	if (*cp == '\0') {
206		/*
207		 * No arguments whatsoever. Because 'make' and 'defined'
208		 * aren't really "reserved words", we don't print a message.
209		 * I think this is better than hitting the user with a warning
210		 * message every time s/he uses the word 'make' or 'defined'
211		 * at the beginning of a symbol...
212		 */
213		*argPtr = cp;
214		return (0);
215	}
216
217	while (*cp == ' ' || *cp == '\t') {
218		cp++;
219	}
220
221	/*
222	 * Create a buffer for the argument and start it out at 16 characters
223	 * long. Why 16? Why not?
224	 */
225	buf = Buf_Init(16);
226
227	while ((strchr(" \t)&|", *cp) == NULL) && (*cp != '\0')) {
228		if (*cp == '$') {
229			/*
230			 * Parse the variable spec and install it as part of
231			 * the argument if it's valid. We tell Var_Parse to
232			 * complain on an undefined variable, so we don't do
233			 * it too. Nor do we return an error, though perhaps
234			 * we should...
235			 */
236			char	*cp2;
237			size_t	len = 0;
238			Boolean	doFree;
239
240			cp2 = Var_Parse(cp, VAR_CMD, TRUE, &len, &doFree);
241
242			Buf_Append(buf, cp2);
243			if (doFree) {
244				free(cp2);
245			}
246			cp += len;
247		} else {
248			Buf_AddByte(buf, (Byte)*cp);
249			cp++;
250		}
251	}
252
253	Buf_AddByte(buf, (Byte)'\0');
254	*argPtr = (char *)Buf_GetAll(buf, &argLen);
255	Buf_Destroy(buf, FALSE);
256
257	while (*cp == ' ' || *cp == '\t') {
258		cp++;
259	}
260	if (parens && *cp != ')') {
261		Parse_Error(PARSE_WARNING,
262		    "Missing closing parenthesis for %s()", func);
263		return (0);
264	} else if (parens) {
265		/*
266		 * Advance pointer past close parenthesis.
267		 */
268		cp++;
269	}
270
271	*linePtr = cp;
272	return (argLen);
273}
274
275/**
276 * CondDoDefined
277 *	Handle the 'defined' function for conditionals.
278 *
279 * Results:
280 *	TRUE if the given variable is defined.
281 */
282static Boolean
283CondDoDefined(int argLen, char *arg)
284{
285	char	savec = arg[argLen];
286	Boolean	result;
287
288	arg[argLen] = '\0';
289	if (Var_Value(arg, VAR_CMD) != NULL) {
290		result = TRUE;
291	} else {
292		result = FALSE;
293	}
294	arg[argLen] = savec;
295	return (result);
296}
297
298/**
299 * CondDoMake
300 *	Handle the 'make' function for conditionals.
301 *
302 * Results:
303 *	TRUE if the given target is being made.
304 */
305static Boolean
306CondDoMake(int argLen, char *arg)
307{
308	char	savec = arg[argLen];
309	Boolean	result;
310	const LstNode *ln;
311
312	arg[argLen] = '\0';
313	result = FALSE;
314	LST_FOREACH(ln, &create) {
315		if (Str_Match(Lst_Datum(ln), arg)) {
316			result = TRUE;
317			break;
318		}
319	}
320	arg[argLen] = savec;
321	return (result);
322}
323
324/**
325 * CondDoExists
326 *	See if the given file exists.
327 *
328 * Results:
329 *	TRUE if the file exists and FALSE if it does not.
330 */
331static Boolean
332CondDoExists(int argLen, char *arg)
333{
334	char	savec = arg[argLen];
335	Boolean	result;
336	char	*path;
337
338	arg[argLen] = '\0';
339	path = Path_FindFile(arg, &dirSearchPath);
340	if (path != NULL) {
341		result = TRUE;
342		free(path);
343	} else {
344		result = FALSE;
345	}
346	arg[argLen] = savec;
347	return (result);
348}
349
350/**
351 * CondDoTarget
352 *	See if the given node exists and is an actual target.
353 *
354 * Results:
355 *	TRUE if the node exists as a target and FALSE if it does not.
356 */
357static Boolean
358CondDoTarget(int argLen, char *arg)
359{
360	char	savec = arg[argLen];
361	Boolean	result;
362	GNode	*gn;
363
364	arg[argLen] = '\0';
365	gn = Targ_FindNode(arg, TARG_NOCREATE);
366	if ((gn != NULL) && !OP_NOP(gn->type)) {
367		result = TRUE;
368	} else {
369		result = FALSE;
370	}
371	arg[argLen] = savec;
372	return (result);
373}
374
375/**
376 * CondCvtArg
377 *	Convert the given number into a double. If the number begins
378 *	with 0x, it is interpreted as a hexadecimal integer
379 *	and converted to a double from there. All other strings just have
380 *	strtod called on them.
381 *
382 * Results:
383 *	Sets 'value' to double value of string.
384 *	Returns address of the first character after the last valid
385 *	character of the converted number.
386 *
387 * Side Effects:
388 *	Can change 'value' even if string is not a valid number.
389 */
390static char *
391CondCvtArg(char *str, double *value)
392{
393
394	if ((*str == '0') && (str[1] == 'x')) {
395		long i;
396
397		for (str += 2, i = 0; ; str++) {
398			int x;
399
400			if (isdigit((unsigned char)*str))
401				x  = *str - '0';
402			else if (isxdigit((unsigned char)*str))
403				x = 10 + *str -
404				    isupper((unsigned char)*str) ? 'A' : 'a';
405			else {
406				*value = (double)i;
407				return (str);
408			}
409			i = (i << 4) + x;
410		}
411
412	} else {
413		char *eptr;
414
415		*value = strtod(str, &eptr);
416		return (eptr);
417	}
418}
419
420/**
421 * CondToken
422 *	Return the next token from the input.
423 *
424 * Results:
425 *	A Token for the next lexical token in the stream.
426 *
427 * Side Effects:
428 *	condPushback will be set back to None if it is used.
429 */
430static Token
431CondToken(Boolean doEval)
432{
433	Token	t;
434
435	if (condPushBack != None) {
436		t = condPushBack;
437		condPushBack = None;
438		return (t);
439	}
440
441	while (*condExpr == ' ' || *condExpr == '\t') {
442		condExpr++;
443	}
444	switch (*condExpr) {
445	  case '(':
446		t = LParen;
447		condExpr++;
448		break;
449	  case ')':
450		t = RParen;
451		condExpr++;
452		break;
453	  case '|':
454		if (condExpr[1] == '|') {
455			condExpr++;
456		}
457		condExpr++;
458		t = Or;
459		break;
460	  case '&':
461		if (condExpr[1] == '&') {
462			condExpr++;
463		}
464		condExpr++;
465		t = And;
466		break;
467	  case '!':
468		t = Not;
469		condExpr++;
470		break;
471	  case '\n':
472	  case '\0':
473		t = EndOfFile;
474		break;
475	  case '$': {
476		char		*lhs;
477		const char	*op;
478		char		*rhs;
479		char		zero[] = "0";
480		size_t		varSpecLen = 0;
481		Boolean		doFree;
482
483		/*
484		 * Parse the variable spec and skip over it, saving its
485		 * value in lhs.
486		 */
487		t = Err;
488		lhs = Var_Parse(condExpr, VAR_CMD, doEval,
489		    &varSpecLen, &doFree);
490		if (lhs == var_Error) {
491			/*
492			 * Even if !doEval, we still report syntax
493			 * errors, which is what getting var_Error
494			 * back with !doEval means.
495			 */
496			return (Err);
497		}
498		condExpr += varSpecLen;
499
500		if (!isspace((unsigned char)*condExpr) &&
501		    strchr("!=><", *condExpr) == NULL) {
502			Buffer *buf;
503
504			buf = Buf_Init(0);
505
506			Buf_Append(buf, lhs);
507
508			if (doFree)
509				free(lhs);
510
511			for (;*condExpr &&
512			    !isspace((unsigned char)*condExpr);
513			    condExpr++)
514				Buf_AddByte(buf, (Byte)*condExpr);
515
516			Buf_AddByte(buf, (Byte)'\0');
517			lhs = (char *)Buf_GetAll(buf, &varSpecLen);
518			Buf_Destroy(buf, FALSE);
519
520			doFree = TRUE;
521		}
522
523		/*
524		 * Skip whitespace to get to the operator
525		 */
526		while (isspace((unsigned char)*condExpr))
527			condExpr++;
528
529		/*
530		 * Make sure the operator is a valid one. If it isn't a
531		 * known relational operator, pretend we got a
532		 * != 0 comparison.
533		 */
534		op = condExpr;
535		switch (*condExpr) {
536		  case '!':
537		  case '=':
538		  case '<':
539		  case '>':
540			if (condExpr[1] == '=') {
541				condExpr += 2;
542			} else {
543				condExpr += 1;
544			}
545			while (isspace((unsigned char)*condExpr)) {
546				condExpr++;
547			}
548			if (*condExpr == '\0') {
549				Parse_Error(PARSE_WARNING,
550				    "Missing right-hand-side of operator");
551				goto error;
552			}
553			rhs = condExpr;
554			break;
555
556		  default:
557			op = "!=";
558			rhs = zero;
559			break;
560		}
561		if (*rhs == '"') {
562			/*
563			 * Doing a string comparison. Only allow == and
564			 * != for * operators.
565			 */
566			char	*string;
567			char	*cp, *cp2;
568			int	qt;
569			Buffer	*buf;
570
571  do_string_compare:
572			if (((*op != '!') && (*op != '=')) ||
573			    (op[1] != '=')) {
574				Parse_Error(PARSE_WARNING,
575				    "String comparison operator should "
576				    "be either == or !=");
577				goto error;
578			}
579
580			buf = Buf_Init(0);
581			qt = *rhs == '"' ? 1 : 0;
582
583			for (cp = &rhs[qt];
584			    ((qt && (*cp != '"')) ||
585			    (!qt && strchr(" \t)", *cp) == NULL)) &&
586			    (*cp != '\0'); cp++) {
587				if ((*cp == '\\') && (cp[1] != '\0')) {
588					/*
589					 * Backslash escapes things --
590					 * skip over next character,							 * if it exists.
591					 */
592					cp++;
593					Buf_AddByte(buf, (Byte)*cp);
594
595				} else if (*cp == '$') {
596					size_t	len = 0;
597					Boolean	freeIt;
598
599					cp2 = Var_Parse(cp, VAR_CMD,
600					    doEval, &len, &freeIt);
601					if (cp2 != var_Error) {
602						Buf_Append(buf, cp2);
603						if (freeIt) {
604							free(cp2);
605						}
606						cp += len - 1;
607					} else {
608						Buf_AddByte(buf,
609						    (Byte)*cp);
610					}
611				} else {
612					Buf_AddByte(buf, (Byte)*cp);
613				}
614			}
615
616			string = Buf_Peel(buf);
617
618			DEBUGF(COND, ("lhs = \"%s\", rhs = \"%s\", "
619			    "op = %.2s\n", lhs, string, op));
620			/*
621			 * Null-terminate rhs and perform the
622			 * comparison. t is set to the result.
623			 */
624			if (*op == '=') {
625				t = strcmp(lhs, string) ? False : True;
626			} else {
627				t = strcmp(lhs, string) ? True : False;
628			}
629			free(string);
630			if (rhs == condExpr) {
631				if (*cp == '\0' || (!qt && *cp == ')'))
632					condExpr = cp;
633				else
634					condExpr = cp + 1;
635			}
636		} else {
637			/*
638			 * rhs is either a float or an integer.
639			 * Convert both the lhs and the rhs to a
640			 * double and compare the two.
641			 */
642			double	left, right;
643			char	*string;
644
645			if (*CondCvtArg(lhs, &left) != '\0')
646				goto do_string_compare;
647			if (*rhs == '$') {
648				size_t	len = 0;
649				Boolean	freeIt;
650
651				string = Var_Parse(rhs, VAR_CMD, doEval,
652				    &len, &freeIt);
653				if (string == var_Error) {
654					right = 0.0;
655				} else {
656					if (*CondCvtArg(string,
657					    &right) != '\0') {
658						if (freeIt)
659							free(string);
660						goto do_string_compare;
661					}
662					if (freeIt)
663						free(string);
664					if (rhs == condExpr)
665						condExpr += len;
666				}
667			} else {
668				char *c = CondCvtArg(rhs, &right);
669
670				if (c == rhs)
671					goto do_string_compare;
672				if (rhs == condExpr) {
673					/*
674					 * Skip over the right-hand side
675					 */
676					condExpr = c;
677				}
678			}
679
680			DEBUGF(COND, ("left = %f, right = %f, "
681			    "op = %.2s\n", left, right, op));
682			switch (op[0]) {
683			  case '!':
684				if (op[1] != '=') {
685					Parse_Error(PARSE_WARNING,
686					    "Unknown operator");
687					goto error;
688				}
689				t = (left != right ? True : False);
690				break;
691			  case '=':
692				if (op[1] != '=') {
693					Parse_Error(PARSE_WARNING,
694					    "Unknown operator");
695					goto error;
696				}
697				t = (left == right ? True : False);
698				break;
699			  case '<':
700				if (op[1] == '=') {
701					t = (left <= right?True:False);
702				} else {
703					t = (left < right?True:False);
704				}
705				break;
706			case '>':
707				if (op[1] == '=') {
708					t = (left >= right?True:False);
709				} else {
710					t = (left > right?True:False);
711				}
712				break;
713			default:
714				break;
715			}
716		}
717  error:
718		if (doFree)
719			free(lhs);
720		break;
721		}
722
723	  default: {
724		CondProc	*evalProc;
725		Boolean		invert = FALSE;
726		char		*arg;
727		int		arglen;
728
729		if (strncmp(condExpr, "defined", 7) == 0) {
730			/*
731			 * Use CondDoDefined to evaluate the argument
732			 * and CondGetArg to extract the argument from
733			 * the 'function call'.
734			 */
735			evalProc = CondDoDefined;
736			condExpr += 7;
737			arglen = CondGetArg(&condExpr, &arg,
738			    "defined", TRUE);
739			if (arglen == 0) {
740				condExpr -= 7;
741				goto use_default;
742			}
743
744		} else if (strncmp(condExpr, "make", 4) == 0) {
745			/*
746			 * Use CondDoMake to evaluate the argument and
747			 * CondGetArg to extract the argument from the
748			 * 'function call'.
749			 */
750			evalProc = CondDoMake;
751			condExpr += 4;
752			arglen = CondGetArg(&condExpr, &arg,
753			    "make", TRUE);
754			if (arglen == 0) {
755				condExpr -= 4;
756				goto use_default;
757			}
758
759		} else if (strncmp(condExpr, "exists", 6) == 0) {
760			/*
761			 * Use CondDoExists to evaluate the argument and
762			 * CondGetArg to extract the argument from the
763			 * 'function call'.
764			 */
765			evalProc = CondDoExists;
766			condExpr += 6;
767			arglen = CondGetArg(&condExpr, &arg,
768			    "exists", TRUE);
769			if (arglen == 0) {
770				condExpr -= 6;
771				goto use_default;
772			}
773
774		} else if (strncmp(condExpr, "empty", 5) == 0) {
775			/*
776			 * Use Var_Parse to parse the spec in parens and
777			 * return True if the resulting string is empty.
778			 */
779			size_t	length;
780			Boolean	doFree;
781			char	*val;
782
783			condExpr += 5;
784
785			for (arglen = 0;
786			    condExpr[arglen] != '(' &&
787			    condExpr[arglen] != '\0'; arglen += 1)
788				continue;
789
790			if (condExpr[arglen] != '\0') {
791				length = 0;
792				val = Var_Parse(&condExpr[arglen - 1],
793				    VAR_CMD, FALSE, &length, &doFree);
794				if (val == var_Error) {
795					t = Err;
796				} else {
797					/*
798					 * A variable is empty when it
799					 * just contains spaces...
800					 * 4/15/92, christos
801					 */
802					char *p;
803
804					for (p = val;
805					    *p &&
806					    isspace((unsigned char)*p);
807					    p++)
808						continue;
809					t = (*p == '\0') ? True : False;
810				}
811				if (doFree) {
812					free(val);
813				}
814				/*
815				 * Advance condExpr to beyond the
816				 * closing ). Note that we subtract
817				 * one from arglen + length b/c length
818				 * is calculated from
819				 * condExpr[arglen - 1].
820				 */
821				condExpr += arglen + length - 1;
822			} else {
823				condExpr -= 5;
824				goto use_default;
825			}
826			break;
827
828		} else if (strncmp(condExpr, "target", 6) == 0) {
829			/*
830			 * Use CondDoTarget to evaluate the argument and
831			 * CondGetArg to extract the argument from the
832			 * 'function call'.
833			 */
834			evalProc = CondDoTarget;
835			condExpr += 6;
836			arglen = CondGetArg(&condExpr, &arg,
837			    "target", TRUE);
838			if (arglen == 0) {
839				condExpr -= 6;
840				goto use_default;
841			}
842
843		} else {
844			/*
845			 * The symbol is itself the argument to the
846			 * default function. We advance condExpr to
847			 * the end of the symbol by hand (the next
848			 * whitespace, closing paren or binary operator)
849			 * and set to invert the evaluation
850			 * function if condInvert is TRUE.
851			 */
852  use_default:
853			invert = condInvert;
854			evalProc = condDefProc;
855			arglen = CondGetArg(&condExpr, &arg, "", FALSE);
856		}
857
858		/*
859		 * Evaluate the argument using the set function. If
860		 * invert is TRUE, we invert the sense of the function.
861		 */
862		t = (!doEval || (* evalProc) (arglen, arg) ?
863		    (invert ? False : True) :
864		    (invert ? True : False));
865		free(arg);
866		break;
867		}
868	}
869	return (t);
870}
871
872/**
873 * CondT
874 *	Parse a single term in the expression. This consists of a terminal
875 *	symbol or Not and a terminal symbol (not including the binary
876 *	operators):
877 *	    T -> defined(variable) | make(target) | exists(file) | symbol
878 *	    T -> ! T | ( E )
879 *
880 * Results:
881 *	True, False or Err.
882 *
883 * Side Effects:
884 *	Tokens are consumed.
885 */
886static Token
887CondT(Boolean doEval)
888{
889	Token	t;
890
891	t = CondToken(doEval);
892	if (t == EndOfFile) {
893		/*
894		 * If we reached the end of the expression, the expression
895		 * is malformed...
896		 */
897		t = Err;
898	} else if (t == LParen) {
899		/*
900		 * T -> ( E )
901		 */
902		t = CondE(doEval);
903		if (t != Err) {
904			if (CondToken(doEval) != RParen) {
905				t = Err;
906			}
907		}
908	} else if (t == Not) {
909		t = CondT(doEval);
910		if (t == True) {
911			t = False;
912		} else if (t == False) {
913			t = True;
914		}
915	}
916	return (t);
917}
918
919/**
920 * CondF --
921 *	Parse a conjunctive factor (nice name, wot?)
922 *	    F -> T && F | T
923 *
924 * Results:
925 *	True, False or Err
926 *
927 * Side Effects:
928 *	Tokens are consumed.
929 */
930static Token
931CondF(Boolean doEval)
932{
933	Token	l, o;
934
935	l = CondT(doEval);
936	if (l != Err) {
937		o = CondToken(doEval);
938
939		if (o == And) {
940			/*
941			 * F -> T && F
942			 *
943			 * If T is False, the whole thing will be False, but
944			 * we have to parse the r.h.s. anyway (to throw it
945			 * away). If T is True, the result is the r.h.s.,
946			 * be it an Err or no.
947			 */
948			if (l == True) {
949				l = CondF(doEval);
950			} else {
951				CondF(FALSE);
952			}
953		} else {
954			/*
955			 * F -> T
956			 */
957			CondPushBack(o);
958		}
959	}
960	return (l);
961}
962
963/**
964 * CondE --
965 *	Main expression production.
966 *	    E -> F || E | F
967 *
968 * Results:
969 *	True, False or Err.
970 *
971 * Side Effects:
972 *	Tokens are, of course, consumed.
973 */
974static Token
975CondE(Boolean doEval)
976{
977	Token   l, o;
978
979	l = CondF(doEval);
980	if (l != Err) {
981		o = CondToken(doEval);
982
983		if (o == Or) {
984			/*
985			 * E -> F || E
986			 *
987			 * A similar thing occurs for ||, except that here we
988			 * make sure the l.h.s. is False before we bother to
989			 * evaluate the r.h.s. Once again, if l is False, the
990			 * result is the r.h.s. and once again if l is True,
991			 * we parse the r.h.s. to throw it away.
992			 */
993			if (l == False) {
994				l = CondE(doEval);
995			} else {
996				CondE(FALSE);
997			}
998		} else {
999			/*
1000			 * E -> F
1001			 */
1002			CondPushBack(o);
1003		}
1004	}
1005	return (l);
1006}
1007
1008/**
1009 * Cond_If
1010 *	Handle .if<X> and .elif<X> directives.
1011 *	This function is called even when we're skipping.
1012 */
1013void
1014Cond_If(char *line, int code, int lineno)
1015{
1016	const struct If	*ifp;
1017	Boolean value;
1018
1019	ifp = &ifs[code];
1020
1021	if (ifp->isElse) {
1022		if (condTop == MAXIF) {
1023			Parse_Error(PARSE_FATAL, "if-less elif");
1024			return;
1025		}
1026		if (skipIfLevel != 0) {
1027			/*
1028			 * If skipping this conditional, just ignore
1029			 * the whole thing. If we don't, the user
1030			 * might be employing a variable that's
1031			 * undefined, for which there's an enclosing
1032			 * ifdef that we're skipping...
1033			 */
1034			skipIfLineno[skipIfLevel - 1] = lineno;
1035			return;
1036		}
1037
1038	} else if (skipLine) {
1039		/*
1040		 * Don't even try to evaluate a conditional that's
1041		 * not an else if we're skipping things...
1042		 */
1043		skipIfLineno[skipIfLevel] = lineno;
1044		skipIfLevel += 1;
1045		return;
1046	}
1047
1048	/*
1049	 * Initialize file-global variables for parsing
1050	 */
1051	condDefProc = ifp->defProc;
1052	condInvert = ifp->doNot;
1053
1054	while (*line == ' ' || *line == '\t') {
1055		line++;
1056	}
1057
1058	condExpr = line;
1059	condPushBack = None;
1060
1061	switch (CondE(TRUE)) {
1062	  case True:
1063		if (CondToken(TRUE) != EndOfFile)
1064			goto err;
1065		value = TRUE;
1066		break;
1067
1068	  case False:
1069		if (CondToken(TRUE) != EndOfFile)
1070			goto err;
1071		value = FALSE;
1072		break;
1073
1074	  case Err:
1075  err:		Parse_Error(PARSE_FATAL, "Malformed conditional (%s)", line);
1076		return;
1077
1078	  default:
1079		abort();
1080	}
1081
1082	if (!ifp->isElse) {
1083		/* push this value */
1084		condTop -= 1;
1085
1086	} else if (skipIfLevel != 0 || condStack[condTop]) {
1087		/*
1088		 * If this is an else-type conditional, it should only take
1089		 * effect if its corresponding if was evaluated and FALSE.
1090		 * If its if was TRUE or skipped, we return COND_SKIP (and
1091		 * start skipping in case we weren't already), leaving the
1092		 * stack unmolested so later elif's don't screw up...
1093		 */
1094		skipLine = TRUE;
1095		return;
1096	}
1097
1098	if (condTop < 0) {
1099		/*
1100		 * This is the one case where we can definitely proclaim a fatal
1101		 * error. If we don't, we're hosed.
1102		 */
1103		Parse_Error(PARSE_FATAL, "Too many nested if's. %d max.",MAXIF);
1104		return;
1105	}
1106
1107	/* push */
1108	condStack[condTop] = value;
1109	condLineno[condTop] = lineno;
1110	skipLine = !value;
1111}
1112
1113/**
1114 * Cond_Else
1115 *	Handle .else statement.
1116 */
1117void
1118Cond_Else(char *line __unused, int code __unused, int lineno __unused)
1119{
1120
1121	while (isspace((u_char)*line))
1122		line++;
1123
1124	if (*line != '\0' && (warn_flags & WARN_DIRSYNTAX)) {
1125		Parse_Error(PARSE_WARNING, "junk after .else ignored '%s'",
1126		    line);
1127	}
1128
1129	if (condTop == MAXIF) {
1130		Parse_Error(PARSE_FATAL, "if-less else");
1131		return;
1132	}
1133	if (skipIfLevel != 0)
1134		return;
1135
1136	if (skipIfLevel != 0 || condStack[condTop]) {
1137		/*
1138		 * An else should only take effect if its corresponding if was
1139		 * evaluated and FALSE.
1140		 * If its if was TRUE or skipped, we return COND_SKIP (and
1141		 * start skipping in case we weren't already), leaving the
1142		 * stack unmolested so later elif's don't screw up...
1143		 * XXX How does this work with two .else's?
1144		 */
1145		skipLine = TRUE;
1146		return;
1147	}
1148
1149	/* inverse value */
1150	condStack[condTop] = !condStack[condTop];
1151	skipLine = !condStack[condTop];
1152}
1153
1154/**
1155 * Cond_Endif
1156 *	Handle .endif statement.
1157 */
1158void
1159Cond_Endif(char *line __unused, int code __unused, int lineno __unused)
1160{
1161
1162	while (isspace((u_char)*line))
1163		line++;
1164
1165	if (*line != '\0' && (warn_flags & WARN_DIRSYNTAX)) {
1166		Parse_Error(PARSE_WARNING, "junk after .endif ignored '%s'",
1167		    line);
1168	}
1169
1170	/*
1171	 * End of a conditional section. If skipIfLevel is non-zero,
1172	 * that conditional was skipped, so lines following it should
1173	 * also be skipped. Hence, we return COND_SKIP. Otherwise,
1174	 * the conditional was read so succeeding lines should be
1175	 * parsed (think about it...) so we return COND_PARSE, unless
1176	 * this endif isn't paired with a decent if.
1177	 */
1178	if (skipIfLevel != 0) {
1179		skipIfLevel -= 1;
1180		return;
1181	}
1182
1183	if (condTop == MAXIF) {
1184		Parse_Error(PARSE_FATAL, "if-less endif");
1185		return;
1186	}
1187
1188	/* pop */
1189	skipLine = FALSE;
1190	condTop += 1;
1191}
1192
1193/**
1194 * Cond_End
1195 *	Make sure everything's clean at the end of a makefile.
1196 *
1197 * Side Effects:
1198 *	Parse_Error will be called if open conditionals are around.
1199 */
1200void
1201Cond_End(void)
1202{
1203	int level;
1204
1205	if (condTop != MAXIF) {
1206		Parse_Error(PARSE_FATAL, "%d open conditional%s:",
1207		    MAXIF - condTop + skipIfLevel,
1208		    MAXIF - condTop + skipIfLevel== 1 ? "" : "s");
1209
1210		for (level = skipIfLevel; level > 0; level--)
1211			Parse_Error(PARSE_FATAL, "\t%*sat line %d (skipped)",
1212			    MAXIF - condTop + level + 1, "",
1213			    skipIfLineno[level - 1]);
1214		for (level = condTop; level < MAXIF; level++)
1215			Parse_Error(PARSE_FATAL, "\t%*sat line %d "
1216			    "(evaluated to %s)", MAXIF - level + skipIfLevel,
1217			    "", condLineno[level],
1218			    condStack[level] ? "true" : "false");
1219	}
1220	condTop = MAXIF;
1221}
1222