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