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