Module Name: src Committed By: rillig Date: Fri Sep 11 06:47:42 UTC 2020
Modified Files: src/usr.bin/make: cond.c src/usr.bin/make/unit-tests: cond-token-plain.exp cond-token-plain.mk Log Message: make(1): add tests for really strange edge cases in conditions To generate a diff of this commit: cvs rdiff -u -r1.127 -r1.128 src/usr.bin/make/cond.c cvs rdiff -u -r1.1 -r1.2 src/usr.bin/make/unit-tests/cond-token-plain.exp cvs rdiff -u -r1.2 -r1.3 src/usr.bin/make/unit-tests/cond-token-plain.mk Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/make/cond.c diff -u src/usr.bin/make/cond.c:1.127 src/usr.bin/make/cond.c:1.128 --- src/usr.bin/make/cond.c:1.127 Fri Sep 11 06:08:10 2020 +++ src/usr.bin/make/cond.c Fri Sep 11 06:47:42 2020 @@ -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 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 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) 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 *inf 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 *inf 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; } Index: src/usr.bin/make/unit-tests/cond-token-plain.exp diff -u src/usr.bin/make/unit-tests/cond-token-plain.exp:1.1 src/usr.bin/make/unit-tests/cond-token-plain.exp:1.2 --- src/usr.bin/make/unit-tests/cond-token-plain.exp:1.1 Sun Aug 16 12:07:51 2020 +++ src/usr.bin/make/unit-tests/cond-token-plain.exp Fri Sep 11 06:47:42 2020 @@ -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 Index: src/usr.bin/make/unit-tests/cond-token-plain.mk diff -u src/usr.bin/make/unit-tests/cond-token-plain.mk:1.2 src/usr.bin/make/unit-tests/cond-token-plain.mk:1.3 --- src/usr.bin/make/unit-tests/cond-token-plain.mk:1.2 Sun Aug 16 14:25:16 2020 +++ src/usr.bin/make/unit-tests/cond-token-plain.mk Fri Sep 11 06:47:42 2020 @@ -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: @:;