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