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