make(1): add tests for really strange edge cases in conditions
This commit is contained in:
parent
ec64646830
commit
56350d0e74
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: cond.c,v 1.127 2020/09/11 06:08:10 rillig Exp $ */
|
||||
/* $NetBSD: cond.c,v 1.128 2020/09/11 06:47:42 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
||||
|
@ -70,14 +70,14 @@
|
|||
*/
|
||||
|
||||
#ifndef MAKE_NATIVE
|
||||
static char rcsid[] = "$NetBSD: cond.c,v 1.127 2020/09/11 06:08:10 rillig Exp $";
|
||||
static char rcsid[] = "$NetBSD: cond.c,v 1.128 2020/09/11 06:47:42 rillig Exp $";
|
||||
#else
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)cond.c 8.2 (Berkeley) 1/2/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: cond.c,v 1.127 2020/09/11 06:08:10 rillig Exp $");
|
||||
__RCSID("$NetBSD: cond.c,v 1.128 2020/09/11 06:47:42 rillig Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
@ -985,7 +985,12 @@ CondParser_Expr(CondParser *par, Boolean doEval)
|
|||
static CondEvalResult
|
||||
CondParser_Eval(CondParser *par, Boolean *value)
|
||||
{
|
||||
Token res = CondParser_Expr(par, TRUE);
|
||||
Token res;
|
||||
|
||||
if (DEBUG(COND))
|
||||
fprintf(debug_file, "CondParser_Eval: %s\n", par->p);
|
||||
|
||||
res = CondParser_Expr(par, TRUE);
|
||||
if (res != TOK_FALSE && res != TOK_TRUE)
|
||||
return COND_INVALID;
|
||||
|
||||
|
@ -996,9 +1001,9 @@ CondParser_Eval(CondParser *par, Boolean *value)
|
|||
return COND_PARSE;
|
||||
}
|
||||
|
||||
/* Evaluate the condition in the passed line, including any side effects from
|
||||
* the variable expressions in the condition. The condition consists of &&,
|
||||
* ||, !, function(arg), comparisons and parenthetical groupings thereof.
|
||||
/* Evaluate the condition, including any side effects from the variable
|
||||
* expressions in the condition. The condition consists of &&, ||, !,
|
||||
* function(arg), comparisons and parenthetical groupings thereof.
|
||||
*
|
||||
* Results:
|
||||
* COND_PARSE if the condition was valid grammatically
|
||||
|
@ -1007,7 +1012,7 @@ CondParser_Eval(CondParser *par, Boolean *value)
|
|||
* (*value) is set to the boolean value of the condition
|
||||
*/
|
||||
CondEvalResult
|
||||
Cond_EvalExpression(const struct If *info, const char *line, Boolean *value,
|
||||
Cond_EvalExpression(const struct If *info, const char *cond, Boolean *value,
|
||||
int eprint, Boolean strictLHS)
|
||||
{
|
||||
static const struct If *dflt_info;
|
||||
|
@ -1016,8 +1021,8 @@ Cond_EvalExpression(const struct If *info, const char *line, Boolean *value,
|
|||
|
||||
lhsStrict = strictLHS;
|
||||
|
||||
while (*line == ' ' || *line == '\t')
|
||||
line++;
|
||||
while (*cond == ' ' || *cond == '\t')
|
||||
cond++;
|
||||
|
||||
if (info == NULL && (info = dflt_info) == NULL) {
|
||||
/* Scan for the entry for .if - it can't be first */
|
||||
|
@ -1029,13 +1034,13 @@ Cond_EvalExpression(const struct If *info, const char *line, Boolean *value,
|
|||
assert(info != NULL);
|
||||
|
||||
par.if_info = info;
|
||||
par.p = line;
|
||||
par.p = cond;
|
||||
par.curr = TOK_NONE;
|
||||
|
||||
rval = CondParser_Eval(&par, value);
|
||||
|
||||
if (rval == COND_INVALID && eprint)
|
||||
Parse_Error(PARSE_FATAL, "Malformed conditional (%s)", line);
|
||||
Parse_Error(PARSE_FATAL, "Malformed conditional (%s)", cond);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
|
|
@ -1 +1,18 @@
|
|||
CondParser_Eval: ${:Uvalue} != value
|
||||
lhs = "value", rhs = "value", op = !=
|
||||
CondParser_Eval: ${:U} != "
|
||||
lhs = "", rhs = "", op = !=
|
||||
CondParser_Eval: ${:U#hash} != "#hash"
|
||||
lhs = "#hash", rhs = "#hash", op = !=
|
||||
CondParser_Eval: ${:U\\} != "\\
|
||||
lhs = "\", rhs = "\", op = !=
|
||||
CondParser_Eval: ${:U#hash} != #hash
|
||||
lhs = "#hash", rhs = "#hash", op = !=
|
||||
CondParser_Eval: 0 # This is treated as a comment, but why?
|
||||
CondParser_Eval: ${0 # comment :?yes:no} != no
|
||||
CondParser_Eval: 0 # comment
|
||||
lhs = "no", rhs = "no", op = !=
|
||||
CondParser_Eval: ${1 # comment :?yes:no} != yes
|
||||
CondParser_Eval: 1 # comment
|
||||
lhs = "yes", rhs = "yes", op = !=
|
||||
exit status 0
|
||||
|
|
|
@ -1,9 +1,67 @@
|
|||
# $NetBSD: cond-token-plain.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $
|
||||
# $NetBSD: cond-token-plain.mk,v 1.3 2020/09/11 06:47:42 rillig Exp $
|
||||
#
|
||||
# Tests for plain tokens (that is, string literals without quotes)
|
||||
# in .if conditions.
|
||||
|
||||
# TODO: Implementation
|
||||
.MAKEFLAGS: -dc
|
||||
|
||||
.if ${:Uvalue} != value
|
||||
. error
|
||||
.endif
|
||||
|
||||
# Malformed condition since comment parsing is done in an early phase
|
||||
# and removes the '#' and everything behind it long before the condition
|
||||
# parser gets to see it.
|
||||
#
|
||||
# XXX: The error message is missing for this malformed condition.
|
||||
# The right-hand side of the comparison is just a '"'.
|
||||
.if ${:U} != "#hash"
|
||||
. error
|
||||
.endif
|
||||
|
||||
# To get a '#' into a condition, it has to be escaped using a backslash.
|
||||
# This prevents the comment parser from removing it, and in turn, it becomes
|
||||
# visible to CondParser_String.
|
||||
.if ${:U\#hash} != "\#hash"
|
||||
. error
|
||||
.endif
|
||||
|
||||
# Since 2002-12-30, and still as of 2020-09-11, CondParser_Token handles
|
||||
# the '#' specially, even though at this point, there should be no need for
|
||||
# comment handling anymore. The comments are supposed to be stripped off
|
||||
# in a very early parsing phase.
|
||||
#
|
||||
# XXX: Missing error message for the malformed condition. The right-hand
|
||||
# side is double-quotes, backslash, backslash.
|
||||
# XXX: It is unexpected that the right-hand side evaluates to a single
|
||||
# backslash.
|
||||
.if ${:U\\} != "\\#hash"
|
||||
. error
|
||||
.endif
|
||||
|
||||
# The right-hand side of a comparison is not parsed as a token, therefore
|
||||
# the code from CondParser_Token does not apply to it.
|
||||
.if ${:U\#hash} != \#hash
|
||||
. error
|
||||
.endif
|
||||
|
||||
# XXX: What is the purpose of treating an escaped '#' in the following
|
||||
# condition as a comment? And why only at the beginning of a token,
|
||||
# just as in the shell?
|
||||
.if 0 \# This is treated as a comment, but why?
|
||||
. error
|
||||
.endif
|
||||
|
||||
# Ah, ok, this can be used to add an end-of-condition comment. But does
|
||||
# anybody really use this? This is neither documented nor obvious since
|
||||
# the '#' is escaped. It's much clearer to write a comment in the line
|
||||
# above the condition.
|
||||
.if ${0 \# comment :?yes:no} != no
|
||||
. error
|
||||
.endif
|
||||
.if ${1 \# comment :?yes:no} != yes
|
||||
. error
|
||||
.endif
|
||||
|
||||
all:
|
||||
@:;
|
||||
|
|
Loading…
Reference in New Issue