Home | History | Annotate | Line # | Download | only in make
cond.c revision 1.114
      1 /*	$NetBSD: cond.c,v 1.114 2020/09/08 17:55:23 rillig Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
      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. Neither the name of the University nor the names of its contributors
     19  *    may be used to endorse or promote products derived from this software
     20  *    without specific prior written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32  * SUCH DAMAGE.
     33  */
     34 
     35 /*
     36  * Copyright (c) 1988, 1989 by Adam de Boor
     37  * Copyright (c) 1989 by Berkeley Softworks
     38  * All rights reserved.
     39  *
     40  * This code is derived from software contributed to Berkeley by
     41  * Adam de Boor.
     42  *
     43  * Redistribution and use in source and binary forms, with or without
     44  * modification, are permitted provided that the following conditions
     45  * are met:
     46  * 1. Redistributions of source code must retain the above copyright
     47  *    notice, this list of conditions and the following disclaimer.
     48  * 2. Redistributions in binary form must reproduce the above copyright
     49  *    notice, this list of conditions and the following disclaimer in the
     50  *    documentation and/or other materials provided with the distribution.
     51  * 3. All advertising materials mentioning features or use of this software
     52  *    must display the following acknowledgement:
     53  *	This product includes software developed by the University of
     54  *	California, Berkeley and its contributors.
     55  * 4. Neither the name of the University nor the names of its contributors
     56  *    may be used to endorse or promote products derived from this software
     57  *    without specific prior written permission.
     58  *
     59  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     60  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     61  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     62  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     63  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     64  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     65  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     66  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     67  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     68  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     69  * SUCH DAMAGE.
     70  */
     71 
     72 #ifndef MAKE_NATIVE
     73 static char rcsid[] = "$NetBSD: cond.c,v 1.114 2020/09/08 17:55:23 rillig Exp $";
     74 #else
     75 #include <sys/cdefs.h>
     76 #ifndef lint
     77 #if 0
     78 static char sccsid[] = "@(#)cond.c	8.2 (Berkeley) 1/2/94";
     79 #else
     80 __RCSID("$NetBSD: cond.c,v 1.114 2020/09/08 17:55:23 rillig Exp $");
     81 #endif
     82 #endif /* not lint */
     83 #endif
     84 
     85 /*-
     86  * cond.c --
     87  *	Functions to handle conditionals in a makefile.
     88  *
     89  * Interface:
     90  *	Cond_Eval 	Evaluate the conditional in the passed line.
     91  *
     92  */
     93 
     94 #include <errno.h>
     95 
     96 #include "make.h"
     97 #include "dir.h"
     98 
     99 /*
    100  * The parsing of conditional expressions is based on this grammar:
    101  *	E -> F || E
    102  *	E -> F
    103  *	F -> T && F
    104  *	F -> T
    105  *	T -> defined(variable)
    106  *	T -> make(target)
    107  *	T -> exists(file)
    108  *	T -> empty(varspec)
    109  *	T -> target(name)
    110  *	T -> commands(name)
    111  *	T -> symbol
    112  *	T -> $(varspec) op value
    113  *	T -> $(varspec) == "string"
    114  *	T -> $(varspec) != "string"
    115  *	T -> "string"
    116  *	T -> ( E )
    117  *	T -> ! T
    118  *	op -> == | != | > | < | >= | <=
    119  *
    120  * 'symbol' is some other symbol to which the default function is applied.
    121  *
    122  * Tokens are scanned from the 'condExpr' string. The scanner (CondToken)
    123  * will return TOK_AND for '&' and '&&', TOK_OR for '|' and '||',
    124  * TOK_NOT for '!', TOK_LPAREN for '(', TOK_RPAREN for ')' and will evaluate
    125  * the other terminal symbols, using either the default function or the
    126  * function given in the terminal, and return the result as either TOK_TRUE
    127  * or TOK_FALSE.
    128  *
    129  * TOK_FALSE is 0 and TOK_TRUE 1 so we can directly assign C comparisons.
    130  *
    131  * All Non-Terminal functions (CondE, CondF and CondT) return TOK_ERROR on
    132  * error.
    133  */
    134 typedef enum {
    135     TOK_FALSE = 0, TOK_TRUE = 1, TOK_AND, TOK_OR, TOK_NOT,
    136     TOK_LPAREN, TOK_RPAREN, TOK_EOF, TOK_NONE, TOK_ERROR
    137 } Token;
    138 
    139 typedef struct {
    140     const struct If *if_info;	/* Info for current statement */
    141     const char *condExpr;	/* The expression to parse */
    142     Token condPushBack;		/* Single push-back token used in
    143 				 * parsing */
    144 } CondLexer;
    145 
    146 static Token CondE(CondLexer *lex, Boolean);
    147 static CondEvalResult do_Cond_EvalExpression(CondLexer *lex, Boolean *);
    148 
    149 static unsigned int cond_depth = 0;	/* current .if nesting level */
    150 static unsigned int cond_min_depth = 0;	/* depth at makefile open */
    151 
    152 /*
    153  * Indicate when we should be strict about lhs of comparisons.
    154  * TRUE when Cond_EvalExpression is called from Cond_Eval (.if etc)
    155  * FALSE when Cond_EvalExpression is called from var.c:ApplyModifiers
    156  * since lhs is already expanded and we cannot tell if
    157  * it was a variable reference or not.
    158  */
    159 static Boolean lhsStrict;
    160 
    161 static int
    162 istoken(const char *str, const char *tok, size_t len)
    163 {
    164     return strncmp(str, tok, len) == 0 && !isalpha((unsigned char)str[len]);
    165 }
    166 
    167 /* Push back the most recent token read. We only need one level of
    168  * this, so the thing is just stored in 'condPushback'. */
    169 static void
    170 CondPushBack(CondLexer *lex, Token t)
    171 {
    172     lex->condPushBack = t;
    173 }
    174 
    175 /* Parse the argument of a built-in function.
    176  *
    177  * Arguments:
    178  *	*linePtr initially points to the '(', upon successful return points
    179  *	beyond the ')'.
    180  *
    181  *	*out_arg receives the argument as string.
    182  *
    183  *	func says whether the argument belongs to an actual function, or
    184  *	whether the parsed argument is passed to the default function.
    185  *
    186  *	XXX: This is ambiguous for the empty() function since its argument is
    187  *	parsed differently.
    188  *
    189  * Return the length of the argument. */
    190 static int
    191 ParseFuncArg(Boolean doEval, const char **linePtr, char **out_arg,
    192 	     const char *func) {
    193     const char *cp;
    194     Buffer buf;
    195     int paren_depth;
    196     char ch;
    197     size_t argLen;
    198 
    199     cp = *linePtr;
    200     if (func != NULL)
    201 	/* Skip opening '(' - verified by caller */
    202 	cp++;
    203 
    204     if (*cp == '\0') {
    205 	/*
    206 	 * No arguments whatsoever. Because 'make' and 'defined' aren't really
    207 	 * "reserved words", we don't print a message. I think this is better
    208 	 * than hitting the user with a warning message every time s/he uses
    209 	 * the word 'make' or 'defined' at the beginning of a symbol...
    210 	 */
    211 	*out_arg = NULL;
    212 	return 0;
    213     }
    214 
    215     while (*cp == ' ' || *cp == '\t') {
    216 	cp++;
    217     }
    218 
    219     /*
    220      * Create a buffer for the argument and start it out at 16 characters
    221      * long. Why 16? Why not?
    222      */
    223     Buf_Init(&buf, 16);
    224 
    225     paren_depth = 0;
    226     for (;;) {
    227 	ch = *cp;
    228 	if (ch == 0 || ch == ' ' || ch == '\t')
    229 	    break;
    230 	if ((ch == '&' || ch == '|') && paren_depth == 0)
    231 	    break;
    232 	if (*cp == '$') {
    233 	    /*
    234 	     * Parse the variable spec and install it as part of the argument
    235 	     * if it's valid. We tell Var_Parse to complain on an undefined
    236 	     * variable, so we don't do it too. Nor do we return an error,
    237 	     * though perhaps we should...
    238 	     */
    239 	    void *freeIt;
    240 	    VarEvalFlags eflags = VARE_UNDEFERR | (doEval ? VARE_WANTRES : 0);
    241 	    const char *cp2 = Var_ParsePP(&cp, VAR_CMD, eflags, &freeIt);
    242 	    Buf_AddStr(&buf, cp2);
    243 	    free(freeIt);
    244 	    continue;
    245 	}
    246 	if (ch == '(')
    247 	    paren_depth++;
    248 	else if (ch == ')' && --paren_depth < 0)
    249 	    break;
    250 	Buf_AddByte(&buf, *cp);
    251 	cp++;
    252     }
    253 
    254     *out_arg = Buf_GetAll(&buf, &argLen);
    255     Buf_Destroy(&buf, FALSE);
    256 
    257     while (*cp == ' ' || *cp == '\t') {
    258 	cp++;
    259     }
    260 
    261     if (func != NULL && *cp++ != ')') {
    262 	Parse_Error(PARSE_WARNING, "Missing closing parenthesis for %s()",
    263 		    func);
    264 	return 0;
    265     }
    266 
    267     *linePtr = cp;
    268     return argLen;
    269 }
    270 
    271 /* Test whether the given variable is defined. */
    272 static Boolean
    273 CondDoDefined(int argLen MAKE_ATTR_UNUSED, const char *arg)
    274 {
    275     char *freeIt;
    276     Boolean result = Var_Value(arg, VAR_CMD, &freeIt) != NULL;
    277     bmake_free(freeIt);
    278     return result;
    279 }
    280 
    281 /* Wrapper around Str_Match, to be used by Lst_Find. */
    282 static Boolean
    283 CondFindStrMatch(const void *string, const void *pattern)
    284 {
    285     return Str_Match(string, pattern);
    286 }
    287 
    288 /* See if the given target is being made. */
    289 static Boolean
    290 CondDoMake(int argLen MAKE_ATTR_UNUSED, const char *arg)
    291 {
    292     return Lst_Find(create, CondFindStrMatch, arg) != NULL;
    293 }
    294 
    295 /* See if the given file exists. */
    296 static Boolean
    297 CondDoExists(int argLen MAKE_ATTR_UNUSED, const char *arg)
    298 {
    299     Boolean result;
    300     char *path;
    301 
    302     path = Dir_FindFile(arg, dirSearchPath);
    303     if (DEBUG(COND)) {
    304 	fprintf(debug_file, "exists(%s) result is \"%s\"\n",
    305 		arg, path ? path : "");
    306     }
    307     if (path != NULL) {
    308 	result = TRUE;
    309 	free(path);
    310     } else {
    311 	result = FALSE;
    312     }
    313     return result;
    314 }
    315 
    316 /* See if the given node exists and is an actual target. */
    317 static Boolean
    318 CondDoTarget(int argLen MAKE_ATTR_UNUSED, const char *arg)
    319 {
    320     GNode *gn;
    321 
    322     gn = Targ_FindNode(arg, TARG_NOCREATE);
    323     return gn != NULL && !OP_NOP(gn->type);
    324 }
    325 
    326 /* See if the given node exists and is an actual target with commands
    327  * associated with it. */
    328 static Boolean
    329 CondDoCommands(int argLen MAKE_ATTR_UNUSED, const char *arg)
    330 {
    331     GNode *gn;
    332 
    333     gn = Targ_FindNode(arg, TARG_NOCREATE);
    334     return gn != NULL && !OP_NOP(gn->type) && !Lst_IsEmpty(gn->commands);
    335 }
    336 
    337 /*-
    338  * Convert the given number into a double.
    339  * We try a base 10 or 16 integer conversion first, if that fails
    340  * then we try a floating point conversion instead.
    341  *
    342  * Results:
    343  *	Sets 'value' to double value of string.
    344  *	Returns TRUE if the conversion succeeded.
    345  */
    346 static Boolean
    347 CondCvtArg(const char *str, double *value)
    348 {
    349     char *eptr, ech;
    350     unsigned long l_val;
    351     double d_val;
    352 
    353     errno = 0;
    354     if (!*str) {
    355 	*value = (double)0;
    356 	return TRUE;
    357     }
    358     l_val = strtoul(str, &eptr, str[1] == 'x' ? 16 : 10);
    359     ech = *eptr;
    360     if (ech == 0 && errno != ERANGE) {
    361 	d_val = str[0] == '-' ? -(double)-l_val : (double)l_val;
    362     } else {
    363 	if (ech != 0 && ech != '.' && ech != 'e' && ech != 'E')
    364 	    return FALSE;
    365 	d_val = strtod(str, &eptr);
    366 	if (*eptr)
    367 	    return FALSE;
    368     }
    369 
    370     *value = d_val;
    371     return TRUE;
    372 }
    373 
    374 /*-
    375  * Get a string from a variable reference or an optionally quoted
    376  * string.  This is called for the lhs and rhs of string compares.
    377  *
    378  * Results:
    379  *	Returns the string, absent any quotes, or NULL on error.
    380  *	Sets quoted if the string was quoted.
    381  *	Sets freeIt if needed.
    382  *
    383  * Side Effects:
    384  *	Moves condExpr past the end of this token.
    385  */
    386 /* coverity:[+alloc : arg-*2] */
    387 static const char *
    388 CondGetString(CondLexer *lex, Boolean doEval, Boolean *quoted, void **freeIt,
    389 	      Boolean strictLHS)
    390 {
    391     Buffer buf;
    392     const char *str;
    393     int len;
    394     Boolean qt;
    395     const char *start;
    396     VarEvalFlags eflags;
    397 
    398     Buf_Init(&buf, 0);
    399     str = NULL;
    400     *freeIt = NULL;
    401     *quoted = qt = *lex->condExpr == '"' ? 1 : 0;
    402     if (qt)
    403 	lex->condExpr++;
    404     for (start = lex->condExpr;
    405 	 *lex->condExpr && str == NULL; lex->condExpr++) {
    406 	switch (*lex->condExpr) {
    407 	case '\\':
    408 	    if (lex->condExpr[1] != '\0') {
    409 		lex->condExpr++;
    410 		Buf_AddByte(&buf, *lex->condExpr);
    411 	    }
    412 	    break;
    413 	case '"':
    414 	    if (qt) {
    415 		lex->condExpr++;	/* we don't want the quotes */
    416 		goto got_str;
    417 	    } else
    418 		Buf_AddByte(&buf, *lex->condExpr); /* likely? */
    419 	    break;
    420 	case ')':
    421 	case '!':
    422 	case '=':
    423 	case '>':
    424 	case '<':
    425 	case ' ':
    426 	case '\t':
    427 	    if (!qt)
    428 		goto got_str;
    429 	    else
    430 		Buf_AddByte(&buf, *lex->condExpr);
    431 	    break;
    432 	case '$':
    433 	    /* if we are in quotes, then an undefined variable is ok */
    434 	    eflags = ((!qt && doEval) ? VARE_UNDEFERR : 0) |
    435 		     (doEval ? VARE_WANTRES : 0);
    436 	    str = Var_Parse(lex->condExpr, VAR_CMD, eflags, &len, freeIt);
    437 	    if (str == var_Error) {
    438 		if (*freeIt) {
    439 		    free(*freeIt);
    440 		    *freeIt = NULL;
    441 		}
    442 		/*
    443 		 * Even if !doEval, we still report syntax errors, which
    444 		 * is what getting var_Error back with !doEval means.
    445 		 */
    446 		str = NULL;
    447 		goto cleanup;
    448 	    }
    449 	    lex->condExpr += len;
    450 	    /*
    451 	     * If the '$' was first char (no quotes), and we are
    452 	     * followed by space, the operator or end of expression,
    453 	     * we are done.
    454 	     */
    455 	    if ((lex->condExpr == start + len) &&
    456 		(*lex->condExpr == '\0' ||
    457 		 isspace((unsigned char)*lex->condExpr) ||
    458 		 strchr("!=><)", *lex->condExpr))) {
    459 		goto cleanup;
    460 	    }
    461 
    462 	    Buf_AddStr(&buf, str);
    463 	    if (*freeIt) {
    464 		free(*freeIt);
    465 		*freeIt = NULL;
    466 	    }
    467 	    str = NULL;		/* not finished yet */
    468 	    lex->condExpr--;	/* don't skip over next char */
    469 	    break;
    470 	default:
    471 	    if (strictLHS && !qt && *start != '$' &&
    472 		!isdigit((unsigned char)*start)) {
    473 		/* lhs must be quoted, a variable reference or number */
    474 		if (*freeIt) {
    475 		    free(*freeIt);
    476 		    *freeIt = NULL;
    477 		}
    478 		str = NULL;
    479 		goto cleanup;
    480 	    }
    481 	    Buf_AddByte(&buf, *lex->condExpr);
    482 	    break;
    483 	}
    484     }
    485 got_str:
    486     *freeIt = Buf_GetAll(&buf, NULL);
    487     str = *freeIt;
    488 cleanup:
    489     Buf_Destroy(&buf, FALSE);
    490     return str;
    491 }
    492 
    493 /* The different forms of #if's. */
    494 static const struct If {
    495     const char *form;		/* Form of if */
    496     size_t formlen;		/* Length of form */
    497     Boolean doNot;		/* TRUE if default function should be negated */
    498     Boolean (*defProc)(int, const char *); /* Default function to apply */
    499 } ifs[] = {
    500     { "def",   3, FALSE, CondDoDefined },
    501     { "ndef",  4, TRUE,  CondDoDefined },
    502     { "make",  4, FALSE, CondDoMake },
    503     { "nmake", 5, TRUE,  CondDoMake },
    504     { "",      0, FALSE, CondDoDefined },
    505     { NULL,    0, FALSE, NULL }
    506 };
    507 
    508 /*-
    509  * Return the next token from the input.
    510  *
    511  * Side Effects:
    512  *	condPushback will be set back to TOK_NONE if it is used.
    513  */
    514 static Token
    515 compare_expression(CondLexer *lex, Boolean doEval)
    516 {
    517     Token t;
    518     const char *lhs;
    519     const char *rhs;
    520     const char *op;
    521     void *lhsFree;
    522     void *rhsFree;
    523     Boolean lhsQuoted;
    524     Boolean rhsQuoted;
    525     double left, right;
    526 
    527     t = TOK_ERROR;
    528     rhs = NULL;
    529     lhsFree = rhsFree = NULL;
    530     lhsQuoted = rhsQuoted = FALSE;
    531 
    532     /*
    533      * Parse the variable spec and skip over it, saving its
    534      * value in lhs.
    535      */
    536     lhs = CondGetString(lex, doEval, &lhsQuoted, &lhsFree, lhsStrict);
    537     if (!lhs)
    538 	goto done;
    539 
    540     /*
    541      * Skip whitespace to get to the operator
    542      */
    543     while (isspace((unsigned char)*lex->condExpr))
    544 	lex->condExpr++;
    545 
    546     /*
    547      * Make sure the operator is a valid one. If it isn't a
    548      * known relational operator, pretend we got a
    549      * != 0 comparison.
    550      */
    551     op = lex->condExpr;
    552     switch (*lex->condExpr) {
    553     case '!':
    554     case '=':
    555     case '<':
    556     case '>':
    557 	if (lex->condExpr[1] == '=') {
    558 	    lex->condExpr += 2;
    559 	} else {
    560 	    lex->condExpr += 1;
    561 	}
    562 	break;
    563     default:
    564 	if (!doEval) {
    565 	    t = TOK_FALSE;
    566 	    goto done;
    567 	}
    568 	/* For .ifxxx "..." check for non-empty string. */
    569 	if (lhsQuoted) {
    570 	    t = lhs[0] != 0;
    571 	    goto done;
    572 	}
    573 	/* For .ifxxx <number> compare against zero */
    574 	if (CondCvtArg(lhs, &left)) {
    575 	    t = left != 0.0;
    576 	    goto done;
    577 	}
    578 	/* For .if ${...} check for non-empty string (defProc is ifdef). */
    579 	if (lex->if_info->form[0] == 0) {
    580 	    t = lhs[0] != 0;
    581 	    goto done;
    582 	}
    583 	/* Otherwise action default test ... */
    584 	t = lex->if_info->defProc(strlen(lhs), lhs) != lex->if_info->doNot;
    585 	goto done;
    586     }
    587 
    588     while (isspace((unsigned char)*lex->condExpr))
    589 	lex->condExpr++;
    590 
    591     if (*lex->condExpr == '\0') {
    592 	Parse_Error(PARSE_WARNING,
    593 		    "Missing right-hand-side of operator");
    594 	goto done;
    595     }
    596 
    597     rhs = CondGetString(lex, doEval, &rhsQuoted, &rhsFree, FALSE);
    598     if (!rhs)
    599 	goto done;
    600 
    601     if (!doEval) {
    602 	t = TOK_FALSE;
    603 	goto done;
    604     }
    605 
    606     if (rhsQuoted || lhsQuoted) {
    607     do_string_compare:
    608 	if (((*op != '!') && (*op != '=')) || (op[1] != '=')) {
    609 	    Parse_Error(PARSE_WARNING,
    610 			"String comparison operator should be either == or !=");
    611 	    goto done;
    612 	}
    613 
    614 	if (DEBUG(COND)) {
    615 	    fprintf(debug_file, "lhs = \"%s\", rhs = \"%s\", op = %.2s\n",
    616 		    lhs, rhs, op);
    617 	}
    618 	/*
    619 	 * Null-terminate rhs and perform the comparison.
    620 	 * t is set to the result.
    621 	 */
    622 	if (*op == '=') {
    623 	    t = strcmp(lhs, rhs) == 0;
    624 	} else {
    625 	    t = strcmp(lhs, rhs) != 0;
    626 	}
    627     } else {
    628 	/*
    629 	 * rhs is either a float or an integer. Convert both the
    630 	 * lhs and the rhs to a double and compare the two.
    631 	 */
    632 
    633 	if (!CondCvtArg(lhs, &left) || !CondCvtArg(rhs, &right))
    634 	    goto do_string_compare;
    635 
    636 	if (DEBUG(COND)) {
    637 	    fprintf(debug_file, "left = %f, right = %f, op = %.2s\n", left,
    638 		    right, op);
    639 	}
    640 	switch (op[0]) {
    641 	case '!':
    642 	    if (op[1] != '=') {
    643 		Parse_Error(PARSE_WARNING,
    644 			    "Unknown operator");
    645 		goto done;
    646 	    }
    647 	    t = (left != right);
    648 	    break;
    649 	case '=':
    650 	    if (op[1] != '=') {
    651 		Parse_Error(PARSE_WARNING,
    652 			    "Unknown operator");
    653 		goto done;
    654 	    }
    655 	    t = (left == right);
    656 	    break;
    657 	case '<':
    658 	    if (op[1] == '=') {
    659 		t = (left <= right);
    660 	    } else {
    661 		t = (left < right);
    662 	    }
    663 	    break;
    664 	case '>':
    665 	    if (op[1] == '=') {
    666 		t = (left >= right);
    667 	    } else {
    668 		t = (left > right);
    669 	    }
    670 	    break;
    671 	}
    672     }
    673 
    674 done:
    675     free(lhsFree);
    676     free(rhsFree);
    677     return t;
    678 }
    679 
    680 static int
    681 ParseEmptyArg(Boolean doEval, const char **linePtr, char **argPtr,
    682 	      const char *func MAKE_ATTR_UNUSED)
    683 {
    684     void *val_freeIt;
    685     const char *val;
    686     int magic_res;
    687 
    688     /* We do all the work here and return the result as the length */
    689     *argPtr = NULL;
    690 
    691     (*linePtr)--;		/* Make (*linePtr)[1] point to the '('. */
    692     val = Var_ParsePP(linePtr, VAR_CMD, doEval ? VARE_WANTRES : 0, &val_freeIt);
    693     /* If successful, *linePtr points beyond the closing ')' now. */
    694 
    695     if (val == var_Error) {
    696 	free(val_freeIt);
    697 	return -1;
    698     }
    699 
    700     /* A variable is empty when it just contains spaces... 4/15/92, christos */
    701     while (isspace((unsigned char)val[0]))
    702 	val++;
    703 
    704     /*
    705      * For consistency with the other functions we can't generate the
    706      * true/false here.
    707      */
    708     magic_res = *val != '\0' ? 2 : 1;
    709     free(val_freeIt);
    710     return magic_res;
    711 }
    712 
    713 static Boolean
    714 CondDoEmpty(int arglen, const char *arg MAKE_ATTR_UNUSED)
    715 {
    716     /* Magic values ahead, see ParseEmptyArg. */
    717     return arglen == 1;
    718 }
    719 
    720 static Token
    721 compare_function(CondLexer *lex, Boolean doEval)
    722 {
    723     static const struct fn_def {
    724 	const char *fn_name;
    725 	size_t fn_name_len;
    726 	int (*fn_getarg)(Boolean, const char **, char **, const char *);
    727 	Boolean (*fn_proc)(int, const char *);
    728     } fn_defs[] = {
    729 	{ "defined",  7, ParseFuncArg,  CondDoDefined },
    730 	{ "make",     4, ParseFuncArg,  CondDoMake },
    731 	{ "exists",   6, ParseFuncArg,  CondDoExists },
    732 	{ "empty",    5, ParseEmptyArg, CondDoEmpty },
    733 	{ "target",   6, ParseFuncArg,  CondDoTarget },
    734 	{ "commands", 8, ParseFuncArg,  CondDoCommands },
    735 	{ NULL,       0, NULL, NULL },
    736     };
    737     const struct fn_def *fn_def;
    738     Token t;
    739     char *arg = NULL;
    740     int arglen;
    741     const char *cp = lex->condExpr;
    742     const char *cp1;
    743 
    744     for (fn_def = fn_defs; fn_def->fn_name != NULL; fn_def++) {
    745 	if (!istoken(cp, fn_def->fn_name, fn_def->fn_name_len))
    746 	    continue;
    747 	cp += fn_def->fn_name_len;
    748 	/* There can only be whitespace before the '(' */
    749 	while (isspace((unsigned char)*cp))
    750 	    cp++;
    751 	if (*cp != '(')
    752 	    break;
    753 
    754 	arglen = fn_def->fn_getarg(doEval, &cp, &arg, fn_def->fn_name);
    755 	if (arglen <= 0) {
    756 	    lex->condExpr = cp;
    757 	    return arglen < 0 ? TOK_ERROR : TOK_FALSE;
    758 	}
    759 	/* Evaluate the argument using the required function. */
    760 	t = !doEval || fn_def->fn_proc(arglen, arg);
    761 	free(arg);
    762 	lex->condExpr = cp;
    763 	return t;
    764     }
    765 
    766     /* Push anything numeric through the compare expression */
    767     cp = lex->condExpr;
    768     if (isdigit((unsigned char)cp[0]) || strchr("+-", cp[0]))
    769 	return compare_expression(lex, doEval);
    770 
    771     /*
    772      * Most likely we have a naked token to apply the default function to.
    773      * However ".if a == b" gets here when the "a" is unquoted and doesn't
    774      * start with a '$'. This surprises people.
    775      * If what follows the function argument is a '=' or '!' then the syntax
    776      * would be invalid if we did "defined(a)" - so instead treat as an
    777      * expression.
    778      */
    779     arglen = ParseFuncArg(doEval, &cp, &arg, NULL);
    780     for (cp1 = cp; isspace((unsigned char)*cp1); cp1++)
    781 	continue;
    782     if (*cp1 == '=' || *cp1 == '!')
    783 	return compare_expression(lex, doEval);
    784     lex->condExpr = cp;
    785 
    786     /*
    787      * Evaluate the argument using the default function.
    788      * This path always treats .if as .ifdef. To get here the character
    789      * after .if must have been taken literally, so the argument cannot
    790      * be empty - even if it contained a variable expansion.
    791      */
    792     t = !doEval || lex->if_info->defProc(arglen, arg) != lex->if_info->doNot;
    793     free(arg);
    794     return t;
    795 }
    796 
    797 static Token
    798 CondToken(CondLexer *lex, Boolean doEval)
    799 {
    800     Token t;
    801 
    802     t = lex->condPushBack;
    803     if (t != TOK_NONE) {
    804 	lex->condPushBack = TOK_NONE;
    805 	return t;
    806     }
    807 
    808     while (*lex->condExpr == ' ' || *lex->condExpr == '\t') {
    809 	lex->condExpr++;
    810     }
    811 
    812     switch (*lex->condExpr) {
    813 
    814     case '(':
    815 	lex->condExpr++;
    816 	return TOK_LPAREN;
    817 
    818     case ')':
    819 	lex->condExpr++;
    820 	return TOK_RPAREN;
    821 
    822     case '|':
    823 	if (lex->condExpr[1] == '|') {
    824 	    lex->condExpr++;
    825 	}
    826 	lex->condExpr++;
    827 	return TOK_OR;
    828 
    829     case '&':
    830 	if (lex->condExpr[1] == '&') {
    831 	    lex->condExpr++;
    832 	}
    833 	lex->condExpr++;
    834 	return TOK_AND;
    835 
    836     case '!':
    837 	lex->condExpr++;
    838 	return TOK_NOT;
    839 
    840     case '#':
    841     case '\n':
    842     case '\0':
    843 	return TOK_EOF;
    844 
    845     case '"':
    846     case '$':
    847 	return compare_expression(lex, doEval);
    848 
    849     default:
    850 	return compare_function(lex, doEval);
    851     }
    852 }
    853 
    854 /*-
    855  *-----------------------------------------------------------------------
    856  * CondT --
    857  *	Parse a single term in the expression. This consists of a terminal
    858  *	symbol or TOK_NOT and a terminal symbol (not including the binary
    859  *	operators):
    860  *	    T -> defined(variable) | make(target) | exists(file) | symbol
    861  *	    T -> ! T | ( E )
    862  *
    863  * Results:
    864  *	TOK_TRUE, TOK_FALSE or TOK_ERROR.
    865  *
    866  * Side Effects:
    867  *	Tokens are consumed.
    868  *
    869  *-----------------------------------------------------------------------
    870  */
    871 static Token
    872 CondT(CondLexer *lex, Boolean doEval)
    873 {
    874     Token t;
    875 
    876     t = CondToken(lex, doEval);
    877 
    878     if (t == TOK_EOF) {
    879 	/*
    880 	 * If we reached the end of the expression, the expression
    881 	 * is malformed...
    882 	 */
    883 	t = TOK_ERROR;
    884     } else if (t == TOK_LPAREN) {
    885 	/*
    886 	 * T -> ( E )
    887 	 */
    888 	t = CondE(lex, doEval);
    889 	if (t != TOK_ERROR) {
    890 	    if (CondToken(lex, doEval) != TOK_RPAREN) {
    891 		t = TOK_ERROR;
    892 	    }
    893 	}
    894     } else if (t == TOK_NOT) {
    895 	t = CondT(lex, doEval);
    896 	if (t == TOK_TRUE) {
    897 	    t = TOK_FALSE;
    898 	} else if (t == TOK_FALSE) {
    899 	    t = TOK_TRUE;
    900 	}
    901     }
    902     return t;
    903 }
    904 
    905 /*-
    906  *-----------------------------------------------------------------------
    907  * CondF --
    908  *	Parse a conjunctive factor (nice name, wot?)
    909  *	    F -> T && F | T
    910  *
    911  * Results:
    912  *	TOK_TRUE, TOK_FALSE or TOK_ERROR
    913  *
    914  * Side Effects:
    915  *	Tokens are consumed.
    916  *
    917  *-----------------------------------------------------------------------
    918  */
    919 static Token
    920 CondF(CondLexer *lex, Boolean doEval)
    921 {
    922     Token l, o;
    923 
    924     l = CondT(lex, doEval);
    925     if (l != TOK_ERROR) {
    926 	o = CondToken(lex, doEval);
    927 
    928 	if (o == TOK_AND) {
    929 	    /*
    930 	     * F -> T && F
    931 	     *
    932 	     * If T is TOK_FALSE, the whole thing will be TOK_FALSE, but we have to
    933 	     * parse the r.h.s. anyway (to throw it away).
    934 	     * If T is TOK_TRUE, the result is the r.h.s., be it an TOK_ERROR or no.
    935 	     */
    936 	    if (l == TOK_TRUE) {
    937 		l = CondF(lex, doEval);
    938 	    } else {
    939 		(void)CondF(lex, FALSE);
    940 	    }
    941 	} else {
    942 	    /*
    943 	     * F -> T
    944 	     */
    945 	    CondPushBack(lex, o);
    946 	}
    947     }
    948     return l;
    949 }
    950 
    951 /*-
    952  *-----------------------------------------------------------------------
    953  * CondE --
    954  *	Main expression production.
    955  *	    E -> F || E | F
    956  *
    957  * Results:
    958  *	TOK_TRUE, TOK_FALSE or TOK_ERROR.
    959  *
    960  * Side Effects:
    961  *	Tokens are, of course, consumed.
    962  *
    963  *-----------------------------------------------------------------------
    964  */
    965 static Token
    966 CondE(CondLexer *lex, Boolean doEval)
    967 {
    968     Token l, o;
    969 
    970     l = CondF(lex, doEval);
    971     if (l != TOK_ERROR) {
    972 	o = CondToken(lex, doEval);
    973 
    974 	if (o == TOK_OR) {
    975 	    /*
    976 	     * E -> F || E
    977 	     *
    978 	     * A similar thing occurs for ||, except that here we make sure
    979 	     * the l.h.s. is TOK_FALSE before we bother to evaluate the r.h.s.
    980 	     * Once again, if l is TOK_FALSE, the result is the r.h.s. and once
    981 	     * again if l is TOK_TRUE, we parse the r.h.s. to throw it away.
    982 	     */
    983 	    if (l == TOK_FALSE) {
    984 		l = CondE(lex, doEval);
    985 	    } else {
    986 		(void)CondE(lex, FALSE);
    987 	    }
    988 	} else {
    989 	    /*
    990 	     * E -> F
    991 	     */
    992 	    CondPushBack(lex, o);
    993 	}
    994     }
    995     return l;
    996 }
    997 
    998 static CondEvalResult
    999 do_Cond_EvalExpression(CondLexer *lex, Boolean *value)
   1000 {
   1001 
   1002     switch (CondE(lex, TRUE)) {
   1003     case TOK_TRUE:
   1004 	if (CondToken(lex, TRUE) == TOK_EOF) {
   1005 	    *value = TRUE;
   1006 	    return COND_PARSE;
   1007 	}
   1008 	break;
   1009     case TOK_FALSE:
   1010 	if (CondToken(lex, TRUE) == TOK_EOF) {
   1011 	    *value = FALSE;
   1012 	    return COND_PARSE;
   1013 	}
   1014 	break;
   1015     default:
   1016     case TOK_ERROR:
   1017 	break;
   1018     }
   1019 
   1020     return COND_INVALID;
   1021 }
   1022 
   1023 /* Evaluate the condition in the passed line, including any side effects from
   1024  * the variable expressions in the condition. The condition consists of &&,
   1025  * ||, !, function(arg), comparisons and parenthetical groupings thereof.
   1026  *
   1027  * Results:
   1028  *	COND_PARSE	if the condition was valid grammatically
   1029  *	COND_INVALID  	if not a valid conditional.
   1030  *
   1031  *	(*value) is set to the boolean value of the condition
   1032  */
   1033 CondEvalResult
   1034 Cond_EvalExpression(const struct If *info, const char *line, Boolean *value,
   1035 		    int eprint, Boolean strictLHS)
   1036 {
   1037     static const struct If *dflt_info;
   1038     CondLexer lex;
   1039     int rval;
   1040 
   1041     lhsStrict = strictLHS;
   1042 
   1043     while (*line == ' ' || *line == '\t')
   1044 	line++;
   1045 
   1046     if (info == NULL && (info = dflt_info) == NULL) {
   1047 	/* Scan for the entry for .if - it can't be first */
   1048 	for (info = ifs;; info++)
   1049 	    if (info->form[0] == 0)
   1050 		break;
   1051 	dflt_info = info;
   1052     }
   1053     assert(info != NULL);
   1054 
   1055     lex.if_info = info;
   1056     lex.condExpr = line;
   1057     lex.condPushBack = TOK_NONE;
   1058 
   1059     rval = do_Cond_EvalExpression(&lex, value);
   1060 
   1061     if (rval == COND_INVALID && eprint)
   1062 	Parse_Error(PARSE_FATAL, "Malformed conditional (%s)", line);
   1063 
   1064     return rval;
   1065 }
   1066 
   1067 
   1068 /* Evaluate the conditional in the passed line. The line looks like this:
   1069  *	.<cond-type> <expr>
   1070  * In this line, <cond-type> is any of if, ifmake, ifnmake, ifdef, ifndef,
   1071  * elif, elifmake, elifnmake, elifdef, elifndef.
   1072  * In this line, <expr> consists of &&, ||, !, function(arg), comparisons
   1073  * and parenthetical groupings thereof.
   1074  *
   1075  * Note that the states IF_ACTIVE and ELSE_ACTIVE are only different in order
   1076  * to detect spurious .else lines (as are SKIP_TO_ELSE and SKIP_TO_ENDIF),
   1077  * otherwise .else could be treated as '.elif 1'.
   1078  *
   1079  * Results:
   1080  *	COND_PARSE	to continue parsing the lines after the conditional
   1081  *			(when .if or .else returns TRUE)
   1082  *	COND_SKIP	to skip the lines after the conditional
   1083  *			(when .if or .elif returns FALSE, or when a previous
   1084  *			branch has already been taken)
   1085  *	COND_INVALID  	if the conditional was not valid, either because of
   1086  *			a syntax error or because some variable was undefined
   1087  *			or because the condition could not be evaluated
   1088  */
   1089 CondEvalResult
   1090 Cond_Eval(const char *line)
   1091 {
   1092     enum { MAXIF = 128 };	/* maximum depth of .if'ing */
   1093     enum { MAXIF_BUMP = 32 };	/* how much to grow by */
   1094     enum if_states {
   1095 	IF_ACTIVE,		/* .if or .elif part active */
   1096 	ELSE_ACTIVE,		/* .else part active */
   1097 	SEARCH_FOR_ELIF,	/* searching for .elif/else to execute */
   1098 	SKIP_TO_ELSE,		/* has been true, but not seen '.else' */
   1099 	SKIP_TO_ENDIF		/* nothing else to execute */
   1100     };
   1101     static enum if_states *cond_state = NULL;
   1102     static unsigned int max_if_depth = MAXIF;
   1103 
   1104     const struct If *ifp;
   1105     Boolean isElif;
   1106     Boolean value;
   1107     int level;			/* Level at which to report errors. */
   1108     enum if_states state;
   1109 
   1110     level = PARSE_FATAL;
   1111     if (!cond_state) {
   1112 	cond_state = bmake_malloc(max_if_depth * sizeof(*cond_state));
   1113 	cond_state[0] = IF_ACTIVE;
   1114     }
   1115     /* skip leading character (the '.') and any whitespace */
   1116     for (line++; *line == ' ' || *line == '\t'; line++)
   1117 	continue;
   1118 
   1119     /* Find what type of if we're dealing with.  */
   1120     if (line[0] == 'e') {
   1121 	if (line[1] != 'l') {
   1122 	    if (!istoken(line + 1, "ndif", 4))
   1123 		return COND_INVALID;
   1124 	    /* End of conditional section */
   1125 	    if (cond_depth == cond_min_depth) {
   1126 		Parse_Error(level, "if-less endif");
   1127 		return COND_PARSE;
   1128 	    }
   1129 	    /* Return state for previous conditional */
   1130 	    cond_depth--;
   1131 	    return cond_state[cond_depth] <= ELSE_ACTIVE
   1132 		   ? COND_PARSE : COND_SKIP;
   1133 	}
   1134 
   1135 	/* Quite likely this is 'else' or 'elif' */
   1136 	line += 2;
   1137 	if (istoken(line, "se", 2)) {
   1138 	    /* It is else... */
   1139 	    if (cond_depth == cond_min_depth) {
   1140 		Parse_Error(level, "if-less else");
   1141 		return COND_PARSE;
   1142 	    }
   1143 
   1144 	    state = cond_state[cond_depth];
   1145 	    switch (state) {
   1146 	    case SEARCH_FOR_ELIF:
   1147 		state = ELSE_ACTIVE;
   1148 		break;
   1149 	    case ELSE_ACTIVE:
   1150 	    case SKIP_TO_ENDIF:
   1151 		Parse_Error(PARSE_WARNING, "extra else");
   1152 		/* FALLTHROUGH */
   1153 	    default:
   1154 	    case IF_ACTIVE:
   1155 	    case SKIP_TO_ELSE:
   1156 		state = SKIP_TO_ENDIF;
   1157 		break;
   1158 	    }
   1159 	    cond_state[cond_depth] = state;
   1160 	    return state <= ELSE_ACTIVE ? COND_PARSE : COND_SKIP;
   1161 	}
   1162 	/* Assume for now it is an elif */
   1163 	isElif = TRUE;
   1164     } else
   1165 	isElif = FALSE;
   1166 
   1167     if (line[0] != 'i' || line[1] != 'f')
   1168 	/* Not an ifxxx or elifxxx line */
   1169 	return COND_INVALID;
   1170 
   1171     /*
   1172      * Figure out what sort of conditional it is -- what its default
   1173      * function is, etc. -- by looking in the table of valid "ifs"
   1174      */
   1175     line += 2;
   1176     for (ifp = ifs;; ifp++) {
   1177 	if (ifp->form == NULL)
   1178 	    return COND_INVALID;
   1179 	if (istoken(ifp->form, line, ifp->formlen)) {
   1180 	    line += ifp->formlen;
   1181 	    break;
   1182 	}
   1183     }
   1184 
   1185     /* Now we know what sort of 'if' it is... */
   1186 
   1187     if (isElif) {
   1188 	if (cond_depth == cond_min_depth) {
   1189 	    Parse_Error(level, "if-less elif");
   1190 	    return COND_PARSE;
   1191 	}
   1192 	state = cond_state[cond_depth];
   1193 	if (state == SKIP_TO_ENDIF || state == ELSE_ACTIVE) {
   1194 	    Parse_Error(PARSE_WARNING, "extra elif");
   1195 	    cond_state[cond_depth] = SKIP_TO_ENDIF;
   1196 	    return COND_SKIP;
   1197 	}
   1198 	if (state != SEARCH_FOR_ELIF) {
   1199 	    /* Either just finished the 'true' block, or already SKIP_TO_ELSE */
   1200 	    cond_state[cond_depth] = SKIP_TO_ELSE;
   1201 	    return COND_SKIP;
   1202 	}
   1203     } else {
   1204 	/* Normal .if */
   1205 	if (cond_depth + 1 >= max_if_depth) {
   1206 	    /*
   1207 	     * This is rare, but not impossible.
   1208 	     * In meta mode, dirdeps.mk (only runs at level 0)
   1209 	     * can need more than the default.
   1210 	     */
   1211 	    max_if_depth += MAXIF_BUMP;
   1212 	    cond_state = bmake_realloc(cond_state,
   1213 				       max_if_depth * sizeof(*cond_state));
   1214 	}
   1215 	state = cond_state[cond_depth];
   1216 	cond_depth++;
   1217 	if (state > ELSE_ACTIVE) {
   1218 	    /* If we aren't parsing the data, treat as always false */
   1219 	    cond_state[cond_depth] = SKIP_TO_ELSE;
   1220 	    return COND_SKIP;
   1221 	}
   1222     }
   1223 
   1224     /* And evaluate the conditional expression */
   1225     if (Cond_EvalExpression(ifp, line, &value, 1, TRUE) == COND_INVALID) {
   1226 	/* Syntax error in conditional, error message already output. */
   1227 	/* Skip everything to matching .endif */
   1228 	cond_state[cond_depth] = SKIP_TO_ELSE;
   1229 	return COND_SKIP;
   1230     }
   1231 
   1232     if (!value) {
   1233 	cond_state[cond_depth] = SEARCH_FOR_ELIF;
   1234 	return COND_SKIP;
   1235     }
   1236     cond_state[cond_depth] = IF_ACTIVE;
   1237     return COND_PARSE;
   1238 }
   1239 
   1240 void
   1241 Cond_restore_depth(unsigned int saved_depth)
   1242 {
   1243     int open_conds = cond_depth - cond_min_depth;
   1244 
   1245     if (open_conds != 0 || saved_depth > cond_depth) {
   1246 	Parse_Error(PARSE_FATAL, "%d open conditional%s", open_conds,
   1247 		    open_conds == 1 ? "" : "s");
   1248 	cond_depth = cond_min_depth;
   1249     }
   1250 
   1251     cond_min_depth = saved_depth;
   1252 }
   1253 
   1254 unsigned int
   1255 Cond_save_depth(void)
   1256 {
   1257     int depth = cond_min_depth;
   1258 
   1259     cond_min_depth = cond_depth;
   1260     return depth;
   1261 }
   1262