From 3e39ce563b9ba25883e5aa37d9799eda9e57c1e0 Mon Sep 17 00:00:00 2001 From: "Simon J. Gerraty" Date: Tue, 27 Jun 2023 13:29:43 -0700 Subject: [PATCH] Import bmake-20230622 Relevant/interesting changes: o optimize string matching for ':M' and ':N' o warn about malformed patterns in ':M', ':N' and '.if make(...)' o allow guards to be targets as well as variables The guard targets may include variable references like __${.PARSEDIR:tA}/${.PARSEFILE}__ o optimization for makefiles protected from multiple-inclusion skip even opening the file after first include. o var.c: do not allow delete of readOnly variable o parse.c: .break takes no args --- ChangeLog | 71 +++ FILES | 6 +- Makefile | 6 +- VERSION | 2 +- buf.c | 6 +- buf.h | 4 +- cond.c | 99 +++- dir.c | 14 +- for.c | 40 +- make.h | 19 +- mk/ChangeLog | 46 ++ mk/dirdeps.mk | 73 ++- mk/host-target.mk | 31 +- mk/install-mk | 4 +- mk/meta.autodep.mk | 5 +- mk/sys.dirdeps.mk | 48 +- mk/sys.vars.mk | 11 +- os.sh | 16 +- parse.c | 106 +++- str.c | 114 ++-- str.h | 9 +- unit-tests/Makefile | 17 +- unit-tests/cmdline-undefined.exp | 24 +- unit-tests/cmdline-undefined.mk | 14 +- unit-tests/cond-cmp-numeric-eq.exp | 4 +- unit-tests/cond-cmp-numeric-eq.mk | 4 +- unit-tests/cond-cmp-unary.exp | 2 +- unit-tests/cond-cmp-unary.mk | 11 +- unit-tests/cond-eof.exp | 6 +- unit-tests/cond-eof.mk | 10 +- unit-tests/cond-func-defined.exp | 10 +- unit-tests/cond-func-defined.mk | 8 +- unit-tests/cond-func-empty.exp | 4 +- unit-tests/cond-func-empty.mk | 7 +- unit-tests/cond-func-make.exp | 1 + unit-tests/cond-func-make.mk | 7 +- unit-tests/cond-func.exp | 18 +- unit-tests/cond-func.mk | 12 +- unit-tests/cond-op-and-lint.exp | 2 +- unit-tests/cond-op-and-lint.mk | 3 +- unit-tests/cond-op-and.exp | 8 +- unit-tests/cond-op-and.mk | 6 +- unit-tests/cond-op-not.exp | 12 +- unit-tests/cond-op-not.mk | 8 +- unit-tests/cond-op-or-lint.exp | 2 +- unit-tests/cond-op-or-lint.mk | 3 +- unit-tests/cond-op-or.exp | 8 +- unit-tests/cond-op-or.mk | 6 +- unit-tests/cond-op-parentheses.exp | 4 +- unit-tests/cond-op-parentheses.mk | 4 +- unit-tests/cond-op.exp | 37 +- unit-tests/cond-op.mk | 28 +- unit-tests/cond-token-number.exp | 8 +- unit-tests/cond-token-number.mk | 6 +- unit-tests/cond-token-plain.exp | 30 +- unit-tests/cond-token-plain.mk | 13 +- unit-tests/cond-token-string.exp | 20 +- unit-tests/cond-token-string.mk | 14 +- unit-tests/cond-token-var.exp | 8 +- unit-tests/cond-token-var.mk | 8 +- unit-tests/cond-undef-lint.exp | 14 +- unit-tests/cond-undef-lint.mk | 9 +- unit-tests/dep-colon-bug-cross-file.exp | 4 +- unit-tests/dep-colon-bug-cross-file.mk | 4 +- unit-tests/dep-wildcards.mk | 8 +- unit-tests/dep.mk | 14 +- unit-tests/deptgt-begin.exp | 4 +- unit-tests/deptgt-begin.mk | 4 +- unit-tests/deptgt-delete_on_error.mk | 2 +- unit-tests/deptgt.exp | 22 +- unit-tests/deptgt.mk | 5 +- unit-tests/directive-elif.exp | 36 +- unit-tests/directive-elif.mk | 25 +- unit-tests/directive-else.exp | 14 +- unit-tests/directive-else.mk | 12 +- unit-tests/directive-endfor.exp | 2 +- unit-tests/directive-endfor.mk | 3 +- unit-tests/directive-endif.exp | 8 +- unit-tests/directive-endif.mk | 28 +- unit-tests/directive-error.exp | 2 +- unit-tests/directive-error.mk | 3 +- unit-tests/directive-for-break.exp | 1 + unit-tests/directive-for-break.mk | 8 +- unit-tests/directive-for-empty.exp | 10 +- unit-tests/directive-for-empty.mk | 6 +- unit-tests/directive-for-errors.exp | 28 +- unit-tests/directive-for-errors.mk | 4 +- unit-tests/directive-for-escape.exp | 147 ++--- unit-tests/directive-for-escape.mk | 10 +- unit-tests/directive-for-generating-endif.exp | 8 +- unit-tests/directive-for-generating-endif.mk | 6 +- unit-tests/directive-for-if.exp | 6 +- unit-tests/directive-for-if.mk | 5 +- unit-tests/directive-for-lines.exp | 12 +- unit-tests/directive-for-lines.mk | 8 +- unit-tests/directive-for.exp | 60 +- unit-tests/directive-for.mk | 10 +- unit-tests/directive-if.exp | 28 +- unit-tests/directive-if.mk | 10 +- unit-tests/directive-ifmake.exp | 14 +- unit-tests/directive-ifmake.mk | 9 +- unit-tests/directive-ifndef.exp | 2 +- unit-tests/directive-ifndef.mk | 33 +- unit-tests/directive-include-fatal.exp | 2 +- unit-tests/directive-include-fatal.mk | 3 +- unit-tests/directive-include-guard.exp | 88 +++ unit-tests/directive-include-guard.mk | 552 ++++++++++++++++++ unit-tests/directive-include.exp | 12 +- unit-tests/directive-include.mk | 6 +- unit-tests/directive-info.exp | 24 +- unit-tests/directive-info.mk | 19 +- unit-tests/directive-misspellings.exp | 84 +-- unit-tests/directive-misspellings.mk | 46 +- unit-tests/directive-undef.exp | 6 +- unit-tests/directive-undef.mk | 5 +- unit-tests/directive-unexport-env.exp | 6 +- unit-tests/directive-unexport-env.mk | 5 +- unit-tests/directive-unexport.exp | 8 +- unit-tests/directive-unexport.mk | 5 +- unit-tests/directive-warning.exp | 14 +- unit-tests/directive-warning.mk | 9 +- unit-tests/doterror.mk | 3 +- unit-tests/error.exp | 6 +- unit-tests/error.mk | 5 +- unit-tests/export-env.mk | 6 +- unit-tests/forsubst.exp | 2 - unit-tests/forsubst.mk | 22 - unit-tests/include-main.exp | 10 +- unit-tests/include-main.mk | 6 +- unit-tests/modmatch.exp | 17 - unit-tests/modmatch.mk | 30 - unit-tests/modmisc.exp | 1 - unit-tests/modmisc.mk | 10 +- unit-tests/opt-debug-file.exp | 6 +- unit-tests/opt-debug-file.mk | 5 +- unit-tests/opt-debug-for.exp | 12 +- unit-tests/opt-debug-hash.exp | 2 +- unit-tests/opt-debug-hash.mk | 3 +- unit-tests/opt-debug-lint.exp | 14 +- unit-tests/opt-debug-lint.mk | 9 +- unit-tests/opt-debug-parse.exp | 28 +- unit-tests/opt-debug-parse.mk | 5 +- unit-tests/opt-warnings-as-errors.exp | 4 +- unit-tests/opt-warnings-as-errors.mk | 4 +- unit-tests/parse.exp | 2 +- unit-tests/parse.mk | 3 +- unit-tests/recursive.exp | 4 +- unit-tests/recursive.mk | 4 +- unit-tests/var-eval-short.exp | 8 +- unit-tests/var-eval-short.mk | 4 +- unit-tests/var-op-append.mk | 19 +- unit-tests/var-op-assign.exp | 4 +- unit-tests/var-op-assign.mk | 4 +- unit-tests/var-op-expand.exp | 6 +- unit-tests/var-op-expand.mk | 4 +- unit-tests/var-op-shell.exp | 8 +- unit-tests/var-op-shell.mk | 6 +- unit-tests/var-readonly.mk | 9 +- unit-tests/var-recursive.exp | 12 +- unit-tests/var-recursive.mk | 4 +- unit-tests/var-scope-cmdline.exp | 4 +- unit-tests/var-scope-cmdline.mk | 4 +- unit-tests/vardebug.exp | 6 +- unit-tests/vardebug.mk | 5 +- unit-tests/varmod-assign-shell.exp | 2 +- unit-tests/varmod-assign-shell.mk | 3 +- unit-tests/varmod-edge.exp | 42 +- unit-tests/varmod-edge.mk | 23 +- unit-tests/varmod-gmtime.exp | 20 +- unit-tests/varmod-gmtime.mk | 12 +- unit-tests/varmod-ifelse.exp | 24 +- unit-tests/varmod-ifelse.mk | 13 +- unit-tests/varmod-indirect.exp | 32 +- unit-tests/varmod-indirect.mk | 13 +- unit-tests/varmod-localtime.exp | 20 +- unit-tests/varmod-localtime.mk | 12 +- unit-tests/varmod-loop-delete.exp | 2 +- unit-tests/varmod-loop-delete.mk | 3 +- unit-tests/varmod-loop-varname.exp | 16 +- unit-tests/varmod-loop-varname.mk | 10 +- unit-tests/varmod-match-escape.exp | 6 +- unit-tests/varmod-match-escape.mk | 37 +- unit-tests/varmod-match.exp | 12 +- unit-tests/varmod-match.mk | 25 +- unit-tests/varmod-order.exp | 20 +- unit-tests/varmod-order.mk | 13 +- unit-tests/varmod-range.exp | 20 +- unit-tests/varmod-range.mk | 12 +- unit-tests/varmod-subst.mk | 84 ++- unit-tests/varmod-sysv.exp | 2 +- unit-tests/varmod-sysv.mk | 3 +- unit-tests/varmod-to-abs.exp | 4 +- unit-tests/varmod-to-abs.mk | 5 +- unit-tests/varmod-to-separator.exp | 28 +- unit-tests/varmod-to-separator.mk | 14 +- unit-tests/varmod.exp | 10 +- unit-tests/varmod.mk | 7 +- unit-tests/varname-dollar.exp | 8 +- unit-tests/varname-dollar.mk | 6 +- unit-tests/varname-dot-makeflags.exp | 12 +- unit-tests/varname-dot-makeflags.mk | 5 +- unit-tests/varname-dot-parsedir.exp | 6 +- unit-tests/varname-dot-parsedir.mk | 12 +- unit-tests/varname-dot-parsefile.exp | 6 +- unit-tests/varname-dot-parsefile.mk | 12 +- unit-tests/varname-makeflags.mk | 10 +- unit-tests/varname.exp | 6 +- unit-tests/varname.mk | 5 +- unit-tests/varparse-dynamic.exp | 4 +- unit-tests/varparse-dynamic.mk | 9 +- unit-tests/varparse-errors.exp | 8 +- unit-tests/varparse-errors.mk | 6 +- var.c | 115 ++-- 213 files changed, 2670 insertions(+), 1108 deletions(-) mode change 100755 => 100644 os.sh create mode 100644 unit-tests/directive-include-guard.exp create mode 100644 unit-tests/directive-include-guard.mk delete mode 100644 unit-tests/forsubst.exp delete mode 100644 unit-tests/forsubst.mk delete mode 100644 unit-tests/modmatch.exp delete mode 100644 unit-tests/modmatch.mk diff --git a/ChangeLog b/ChangeLog index fbaf247d3848..dd1fdf110ab4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,74 @@ +2023-06-22 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20230622 + Merge with NetBSD make, pick up + o optimize string matching for ':M' and ':N' + o warn about malformed patterns in ':M', ':N' and '.if make(...)' + +2023-06-21 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20230621 + Merge with NetBSD make, pick up + o more extensive tests for include guards + o parse.c: if a guard is already defined a file that uses the same + guard is still guarded by it. + +2023-06-20 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20230620 + Merge with NetBSD make, pick up + o allow guards to be targets as well as variables + The guard targets may include variable references like + __${.PARSEDIR:tA}/${.PARSEFILE}__ + +2023-06-19 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20230619 + Merge with NetBSD make, pick up + o unit test for .undef of readOnly vars + o optimization for makefiles protected from multiple-inclusion + skip even opening the file after first include. + Initially this only handles makefiles guarded by a variable + target guards are next. + +2023-06-16 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20230616 + Merge with NetBSD make, pick up + o var.c: do not allow delete of readOnly variable + +2023-06-03 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20230601 + Merge with NetBSD make, pick up + o parse.c: .break takes no args + o lots of unit test updates + +2023-05-29 Simon J Gerraty + + * unit-tests/Makefile: skip tests that require /dev/filemon + if it does not exists - issue a warning. + +2023-05-22 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20230522 + Fix building on darwin ppc + + * os.sh (MACHINE): Darwin powerpc cannot use `uname -m` + also recent NetBSD uses x86_64 for MACHINE_ARCH so conform. + +2023-05-15 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20230515 + + * Makefile (COPTS.filemon_ktrace.c): NetBSD 7 needs help to + compile filemon_ktrace.c + +2023-05-13 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20230512 + o sys.dirdeps.mk - broke after-import target + 2023-05-10 Simon J Gerraty * VERSION (_MAKE_VERSION): 20230510 diff --git a/FILES b/FILES index 5ec98a096339..e557147c85b1 100644 --- a/FILES +++ b/FILES @@ -356,6 +356,8 @@ unit-tests/directive-ifnmake.exp unit-tests/directive-ifnmake.mk unit-tests/directive-include-fatal.exp unit-tests/directive-include-fatal.mk +unit-tests/directive-include-guard.exp +unit-tests/directive-include-guard.mk unit-tests/directive-include.exp unit-tests/directive-include.mk unit-tests/directive-info.exp @@ -392,8 +394,6 @@ unit-tests/export-variants.exp unit-tests/export-variants.mk unit-tests/export.exp unit-tests/export.mk -unit-tests/forsubst.exp -unit-tests/forsubst.mk unit-tests/gnode-submake.exp unit-tests/gnode-submake.mk unit-tests/hanoi-include.exp @@ -429,8 +429,6 @@ unit-tests/meta-cmd-cmp.mk unit-tests/meta-ignore.inc unit-tests/moderrs.exp unit-tests/moderrs.mk -unit-tests/modmatch.exp -unit-tests/modmatch.mk unit-tests/modmisc.exp unit-tests/modmisc.mk unit-tests/objdir-writable.exp diff --git a/Makefile b/Makefile index 212885f7b900..22e92b4da9ac 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.124 2023/02/25 20:27:44 sjg Exp $ +# $Id: Makefile,v 1.125 2023/05/17 00:15:46 sjg Exp $ PROG= bmake @@ -68,7 +68,9 @@ FILEMON_H ?= /usr/include/dev/filemon/filemon.h .if exists(${FILEMON_H}) && ${FILEMON_H:T} == "filemon.h" COPTS.filemon_dev.c += -DHAVE_FILEMON_H -I${FILEMON_H:H} .endif -.endif # USE_FILEMON == dev +.elif ${USE_FILEMON} == "ktrace" +COPTS.filemon_ktrace.c += -Wno-error=unused-parameter +.endif .endif # USE_FILEMON diff --git a/VERSION b/VERSION index b49eb8cc7f26..f82791fcbac8 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ # keep this compatible with sh and make -_MAKE_VERSION=20230510 +_MAKE_VERSION=20230622 diff --git a/buf.c b/buf.c index 73b2eac17d4f..845a68c46330 100644 --- a/buf.c +++ b/buf.c @@ -1,4 +1,4 @@ -/* $NetBSD: buf.c,v 1.55 2022/01/08 17:25:19 rillig Exp $ */ +/* $NetBSD: buf.c,v 1.56 2023/06/01 07:44:10 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -75,7 +75,7 @@ #include "make.h" /* "@(#)buf.c 8.1 (Berkeley) 6/6/93" */ -MAKE_RCSID("$NetBSD: buf.c,v 1.55 2022/01/08 17:25:19 rillig Exp $"); +MAKE_RCSID("$NetBSD: buf.c,v 1.56 2023/06/01 07:44:10 rillig Exp $"); /* Make space in the buffer for adding at least 16 more bytes. */ void @@ -106,7 +106,7 @@ Buf_AddBytes(Buffer *buf, const char *bytes, size_t bytes_len) /* Add the bytes between start and end to the buffer. */ void -Buf_AddBytesBetween(Buffer *buf, const char *start, const char *end) +Buf_AddRange(Buffer *buf, const char *start, const char *end) { Buf_AddBytes(buf, start, (size_t)(end - start)); } diff --git a/buf.h b/buf.h index 14d048bfa514..ccd7d513b211 100644 --- a/buf.h +++ b/buf.h @@ -1,4 +1,4 @@ -/* $NetBSD: buf.h,v 1.47 2022/01/08 17:25:19 rillig Exp $ */ +/* $NetBSD: buf.h,v 1.48 2023/06/01 07:44:10 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -116,7 +116,7 @@ Buf_EndsWith(const Buffer *buf, char ch) } void Buf_AddBytes(Buffer *, const char *, size_t); -void Buf_AddBytesBetween(Buffer *, const char *, const char *); +void Buf_AddRange(Buffer *, const char *, const char *); void Buf_AddStr(Buffer *, const char *); void Buf_AddInt(Buffer *, int); void Buf_AddFlag(Buffer *, bool, const char *); diff --git a/cond.c b/cond.c index a7cd7e833f5d..9a389ae6a92d 100644 --- a/cond.c +++ b/cond.c @@ -1,4 +1,4 @@ -/* $NetBSD: cond.c,v 1.344 2023/02/14 21:08:00 rillig Exp $ */ +/* $NetBSD: cond.c,v 1.353 2023/06/23 05:21:10 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -92,7 +92,7 @@ #include "dir.h" /* "@(#)cond.c 8.2 (Berkeley) 1/2/94" */ -MAKE_RCSID("$NetBSD: cond.c,v 1.344 2023/02/14 21:08:00 rillig Exp $"); +MAKE_RCSID("$NetBSD: cond.c,v 1.353 2023/06/23 05:21:10 rillig Exp $"); /* * Conditional expressions conform to this grammar: @@ -136,10 +136,10 @@ typedef struct CondParser { /* * The plain '.if ${VAR}' evaluates to true if the value of the - * expression has length > 0. The other '.if' variants delegate - * to evalBare instead, for example '.ifdef ${VAR}' is equivalent to - * '.if defined(${VAR})', checking whether the variable named by the - * expression '${VAR}' is defined. + * expression has length > 0 and is not numerically zero. The other + * '.if' variants delegate to evalBare instead, for example '.ifdef + * ${VAR}' is equivalent to '.if defined(${VAR})', checking whether + * the variable named by the expression '${VAR}' is defined. */ bool plain; @@ -173,7 +173,7 @@ typedef struct CondParser { bool printedError; } CondParser; -static CondResult CondParser_Or(CondParser *par, bool); +static CondResult CondParser_Or(CondParser *, bool); unsigned int cond_depth = 0; /* current .if nesting level */ @@ -295,10 +295,19 @@ static bool FuncMake(const char *targetPattern) { StringListNode *ln; + bool warned = false; - for (ln = opts.create.first; ln != NULL; ln = ln->next) - if (Str_Match(ln->datum, targetPattern)) + for (ln = opts.create.first; ln != NULL; ln = ln->next) { + StrMatchResult res = Str_Match(ln->datum, targetPattern); + if (res.error != NULL && !warned) { + warned = true; + Parse_Error(PARSE_WARNING, + "%s in pattern argument '%s' to function 'make'", + res.error, targetPattern); + } + if (res.matched) return true; + } return false; } @@ -338,7 +347,7 @@ FuncCommands(const char *node) } /* - * Convert the string into a floating-point number. Accepted formats are + * Convert the string to a floating point number. Accepted formats are * base-10 integer, base-16 integer and finite floating point numbers. */ static bool @@ -507,7 +516,7 @@ CondParser_Leaf(CondParser *par, bool doEval, bool unquotedOK, * ".if 0". */ static bool -EvalNotEmpty(CondParser *par, const char *value, bool quoted) +EvalTruthy(CondParser *par, const char *value, bool quoted) { double num; @@ -631,7 +640,7 @@ CondParser_Comparison(CondParser *par, bool doEval) if (!CondParser_ComparisonOp(par, &op)) { /* Unknown operator, compare against an empty string or 0. */ - t = ToToken(doEval && EvalNotEmpty(par, lhs.str, lhsQuoted)); + t = ToToken(doEval && EvalTruthy(par, lhs.str, lhsQuoted)); goto done_lhs; } @@ -1123,6 +1132,7 @@ Cond_EvalLine(const char *line) /* Return state for previous conditional */ cond_depth--; + Parse_GuardEndif(); return cond_states[cond_depth] & IFS_ACTIVE ? CR_TRUE : CR_FALSE; } @@ -1150,6 +1160,7 @@ Cond_EvalLine(const char *line) Parse_Error(PARSE_FATAL, "if-less else"); return CR_TRUE; } + Parse_GuardElse(); state = cond_states[cond_depth]; if (state == IFS_INITIAL) { @@ -1185,6 +1196,7 @@ Cond_EvalLine(const char *line) Parse_Error(PARSE_FATAL, "if-less elif"); return CR_TRUE; } + Parse_GuardElse(); state = cond_states[cond_depth]; if (state & IFS_SEEN_ELSE) { Parse_Error(PARSE_WARNING, "extra elif"); @@ -1234,6 +1246,69 @@ Cond_EvalLine(const char *line) return res; } +static bool +ParseVarnameGuard(const char **pp, const char **varname) +{ + const char *p = *pp; + + if (ch_isalpha(*p) || *p == '_') { + while (ch_isalnum(*p) || *p == '_') + p++; + *varname = *pp; + *pp = p; + return true; + } + return false; +} + +/* Extracts the multiple-inclusion guard from a conditional, if any. */ +Guard * +Cond_ExtractGuard(const char *line) +{ + const char *p, *varname; + Substring dir; + enum GuardKind kind; + Guard *guard; + + p = line + 1; /* skip the '.' */ + cpp_skip_hspace(&p); + + dir.start = p; + while (ch_isalpha(*p)) + p++; + dir.end = p; + cpp_skip_hspace(&p); + + if (Substring_Equals(dir, "if")) { + if (skip_string(&p, "!defined(")) { + if (ParseVarnameGuard(&p, &varname) + && strcmp(p, ")") == 0) + goto found_variable; + } else if (skip_string(&p, "!target(")) { + const char *arg_p = p; + free(ParseWord(&p, false)); + if (strcmp(p, ")") == 0) { + char *target = ParseWord(&arg_p, true); + guard = bmake_malloc(sizeof(*guard)); + guard->kind = GK_TARGET; + guard->name = target; + return guard; + } + } + } else if (Substring_Equals(dir, "ifndef")) { + if (ParseVarnameGuard(&p, &varname) && *p == '\0') + goto found_variable; + } + return NULL; + +found_variable: + kind = GK_VARIABLE; + guard = bmake_malloc(sizeof(*guard)); + guard->kind = kind; + guard->name = bmake_strsedup(varname, p); + return guard; +} + void Cond_EndFile(void) { diff --git a/dir.c b/dir.c index 71c344c06dba..1da9e7d8fc13 100644 --- a/dir.c +++ b/dir.c @@ -1,4 +1,4 @@ -/* $NetBSD: dir.c,v 1.280 2023/01/24 00:24:02 sjg Exp $ */ +/* $NetBSD: dir.c,v 1.282 2023/06/23 04:56:54 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -138,7 +138,7 @@ #include "job.h" /* "@(#)dir.c 8.2 (Berkeley) 1/2/94" */ -MAKE_RCSID("$NetBSD: dir.c,v 1.280 2023/01/24 00:24:02 sjg Exp $"); +MAKE_RCSID("$NetBSD: dir.c,v 1.282 2023/06/23 04:56:54 rillig Exp $"); /* * A search path is a list of CachedDir structures. A CachedDir has in it the @@ -668,8 +668,10 @@ DirMatchFiles(const char *pattern, CachedDir *dir, StringList *expansions) HashIter_InitSet(&hi, &dir->files); while (HashIter_Next(&hi) != NULL) { const char *base = hi.entry->key; + StrMatchResult res = Str_Match(base, pattern); + /* TODO: handle errors from res.error */ - if (!Str_Match(base, pattern)) + if (!res.matched) continue; /* @@ -822,14 +824,14 @@ DirExpandCurly(const char *word, const char *brace, SearchPath *path, } -/* Expand the word in each of the directories from the path. */ +/* Expand the pattern in each of the directories from the path. */ static void -DirExpandPath(const char *word, SearchPath *path, StringList *expansions) +DirExpandPath(const char *pattern, SearchPath *path, StringList *expansions) { SearchPathNode *ln; for (ln = path->dirs.first; ln != NULL; ln = ln->next) { CachedDir *dir = ln->datum; - DirMatchFiles(word, dir, expansions); + DirMatchFiles(pattern, dir, expansions); } } diff --git a/for.c b/for.c index 7c090bab5e42..38fd1c447206 100644 --- a/for.c +++ b/for.c @@ -1,4 +1,4 @@ -/* $NetBSD: for.c,v 1.174 2023/05/09 19:43:12 rillig Exp $ */ +/* $NetBSD: for.c,v 1.176 2023/06/01 09:02:14 rillig Exp $ */ /* * Copyright (c) 1992, The Regents of the University of California. @@ -58,7 +58,7 @@ #include "make.h" /* "@(#)for.c 8.1 (Berkeley) 6/6/93" */ -MAKE_RCSID("$NetBSD: for.c,v 1.174 2023/05/09 19:43:12 rillig Exp $"); +MAKE_RCSID("$NetBSD: for.c,v 1.176 2023/06/01 09:02:14 rillig Exp $"); typedef struct ForLoop { @@ -115,7 +115,7 @@ ForLoop_Free(ForLoop *f) } char * -ForLoop_Details(ForLoop *f) +ForLoop_Details(const ForLoop *f) { size_t i, n; const char **vars; @@ -133,7 +133,7 @@ ForLoop_Details(ForLoop *f) Buf_AddStr(&buf, ", "); Buf_AddStr(&buf, vars[i]); Buf_AddStr(&buf, " = "); - Buf_AddBytesBetween(&buf, items[i].start, items[i].end); + Buf_AddRange(&buf, items[i].start, items[i].end); } return Buf_DoneData(&buf); } @@ -351,7 +351,7 @@ NeedsEscapes(Substring value, char endc) } /* - * While expanding the body of a .for loop, write the item in the ${:U...} + * While expanding the body of a .for loop, write the item as a ${:U...} * expression, escaping characters as needed. The result is later unescaped * by ApplyModifier_Defined. */ @@ -362,7 +362,7 @@ AddEscaped(Buffer *cmds, Substring item, char endc) char ch; if (!NeedsEscapes(item, endc)) { - Buf_AddBytesBetween(cmds, item.start, item.end); + Buf_AddRange(cmds, item.start, item.end); return; } @@ -392,7 +392,7 @@ AddEscaped(Buffer *cmds, Substring item, char endc) } /* - * When expanding the body of a .for loop, replace the variable name of an + * While expanding the body of a .for loop, replace the variable name of an * expression like ${i} or ${i:...} or $(i) or $(i:...) with ":Uvalue". */ static void @@ -401,12 +401,12 @@ ForLoop_SubstVarLong(ForLoop *f, unsigned int firstItem, Buffer *body, { size_t i; const char *start = *pp; - const char **vars = Vector_Get(&f->vars, 0); + const char **varnames = Vector_Get(&f->vars, 0); for (i = 0; i < f->vars.len; i++) { const char *p = start; - if (!cpp_skip_string(&p, vars[i])) + if (!cpp_skip_string(&p, varnames[i])) continue; /* XXX: why test for backslash here? */ if (*p != ':' && *p != endc && *p != '\\') @@ -416,7 +416,7 @@ ForLoop_SubstVarLong(ForLoop *f, unsigned int firstItem, Buffer *body, * Found a variable match. Skip over the variable name and * instead add ':U' to the current body. */ - Buf_AddBytesBetween(body, *inout_mark, start); + Buf_AddRange(body, *inout_mark, start); Buf_AddStr(body, ":U"); AddEscaped(body, f->items.words[firstItem + i], endc); @@ -427,7 +427,7 @@ ForLoop_SubstVarLong(ForLoop *f, unsigned int firstItem, Buffer *body, } /* - * When expanding the body of a .for loop, replace single-character + * While expanding the body of a .for loop, replace single-character * variable expressions like $i with their ${:U...} expansion. */ static void @@ -451,7 +451,7 @@ ForLoop_SubstVarShort(ForLoop *f, unsigned int firstItem, Buffer *body, return; found: - Buf_AddBytesBetween(body, *inout_mark, p); + Buf_AddRange(body, *inout_mark, p); *inout_mark = p + 1; /* Replace $ with ${:U} */ @@ -465,13 +465,14 @@ ForLoop_SubstVarShort(ForLoop *f, unsigned int firstItem, Buffer *body, * replacing the expressions for the iteration variables on the way. * * Using variable expressions ensures that the .for loop can't generate - * syntax, and that the later parsing will still see a variable. - * This code assumes that the variable with the empty name will never be - * defined, see unit-tests/varname-empty.mk for more details. + * syntax, and that the later parsing will still see an expression. + * This code assumes that the variable with the empty name is never defined, + * see unit-tests/varname-empty.mk. * * The detection of substitutions of the loop control variables is naive. * Many of the modifiers use '\$' instead of '$$' to escape '$', so it is * possible to contrive a makefile where an unwanted substitution happens. + * See unit-tests/directive-for-escape.mk. */ static void ForLoop_SubstBody(ForLoop *f, unsigned int firstItem, Buffer *body) @@ -497,7 +498,7 @@ ForLoop_SubstBody(ForLoop *f, unsigned int firstItem, Buffer *body) break; } - Buf_AddBytesBetween(body, mark, end); + Buf_AddRange(body, mark, end); } /* @@ -512,7 +513,12 @@ For_NextIteration(ForLoop *f, Buffer *body) f->nextItem += (unsigned int)f->vars.len; ForLoop_SubstBody(f, f->nextItem - (unsigned int)f->vars.len, body); - DEBUG1(FOR, "For: loop body:\n%s", body->data); + if (DEBUG(FOR)) { + char *details = ForLoop_Details(f); + debug_printf("For: loop body with %s:\n%s", + details, body->data); + free(details); + } return true; } diff --git a/make.h b/make.h index d2e6c28be1ff..50e590eb4c93 100644 --- a/make.h +++ b/make.h @@ -1,4 +1,4 @@ -/* $NetBSD: make.h,v 1.319 2023/03/28 14:39:31 rillig Exp $ */ +/* $NetBSD: make.h,v 1.323 2023/06/20 09:25:33 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -555,6 +555,14 @@ typedef enum CondResult { CR_ERROR /* Unknown directive or parse error */ } CondResult; +typedef struct { + enum GuardKind { + GK_VARIABLE, + GK_TARGET + } kind; + char *name; +} Guard; + /* Names of the variables that are "local" to a specific target. */ #define TARGET "@" /* Target of dependency */ #define OODATE "?" /* All out-of-date sources */ @@ -794,8 +802,8 @@ void Arch_End(void); bool Arch_ParseArchive(char **, GNodeList *, GNode *); void Arch_Touch(GNode *); void Arch_TouchLib(GNode *); -void Arch_UpdateMTime(GNode *gn); -void Arch_UpdateMemberMTime(GNode *gn); +void Arch_UpdateMTime(GNode *); +void Arch_UpdateMemberMTime(GNode *); void Arch_FindLib(GNode *, SearchPath *); bool Arch_LibOODate(GNode *) MAKE_ATTR_USE; bool Arch_IsLib(GNode *) MAKE_ATTR_USE; @@ -809,6 +817,7 @@ void Compat_Make(GNode *, GNode *); extern unsigned int cond_depth; CondResult Cond_EvalCondition(const char *) MAKE_ATTR_USE; CondResult Cond_EvalLine(const char *) MAKE_ATTR_USE; +Guard *Cond_ExtractGuard(const char *) MAKE_ATTR_USE; void Cond_EndFile(void); /* dir.c; see also dir.h */ @@ -836,7 +845,7 @@ int For_Eval(const char *) MAKE_ATTR_USE; bool For_Accum(const char *, int *) MAKE_ATTR_USE; void For_Run(unsigned, unsigned); bool For_NextIteration(struct ForLoop *, Buffer *); -char *ForLoop_Details(struct ForLoop *); +char *ForLoop_Details(const struct ForLoop *); void ForLoop_Free(struct ForLoop *); void For_Break(struct ForLoop *); @@ -873,6 +882,8 @@ void Parse_PushInput(const char *, unsigned, unsigned, Buffer, void Parse_MainName(GNodeList *); int Parse_NumErrors(void) MAKE_ATTR_USE; unsigned int CurFile_CondMinDepth(void) MAKE_ATTR_USE; +void Parse_GuardElse(void); +void Parse_GuardEndif(void); /* suff.c */ diff --git a/mk/ChangeLog b/mk/ChangeLog index 15c3861ea701..880b839fc860 100644 --- a/mk/ChangeLog +++ b/mk/ChangeLog @@ -1,3 +1,49 @@ +2023-05-25 Simon J Gerraty + + * meta.autodep.mk (beforegendirdeps): allow tasks to be done + at END but before gendirdeps + +2023-05-22 Simon J Gerraty + + * install-mk (MK_VERSION): 20230522 + + * host-target.mk: deal with garbage from uname -m on + Darwin ppc, also NetBSD appears to use x86_64 for MACHINE_ARCH + these days so just leave it be. + For Darwin arm and i386 use _HOST_MACHINE for _HOST_ARCH so we get + arm64 and x86_64 in HOST_TARGET. + +2023-05-15 Simon J Gerraty + + * sys.vars.mk: M_mtime use :mtime or 'stat -f %m' for older + versions of bmake. + + * dirdeps.mk (TARGET_SPEC_VARS.host): + While *most* projects need only DEP_MACHINE for host, + there is always an exception. So we allow for + TARGET_SPEC_VARS.host to be a subset of TARGET_SPEC_VARS. + The default will *just work* for most projects. + We set DEP_TARGET_SPEC_VARS and hence DEP_TARGET_SPEC + based on DEP_MACHINE. + Allow for M_dep_qual_fixes.host to be different too + and take care to apply the right set. + +2023-05-14 Simon J Gerraty + + * sys.dirdeps.mk: we *do* want to override OBJTOP + and if MAKEOBJDIR was not in env as we want it; + put it there - carefully. + Ensure OBJROOT ends in / or - (/ preferred) + Add more comments to explain what/why. + +2023-05-13 Simon J Gerraty + + * install-mk (MK_VERSION): 20230512 + + * dirdeps.mk: take care not to qualify "host" dirdeps + + * sys.dirdeps.mk (OBJTOP): must use ?= + 2023-05-10 Simon J Gerraty * meta.autodep.mk: if LOCAL_DEPENDS_GUARD is "no" diff --git a/mk/dirdeps.mk b/mk/dirdeps.mk index aafa5ab47557..2cf62bed3d9e 100644 --- a/mk/dirdeps.mk +++ b/mk/dirdeps.mk @@ -1,4 +1,4 @@ -# $Id: dirdeps.mk,v 1.160 2023/05/10 20:44:58 sjg Exp $ +# $Id: dirdeps.mk,v 1.162 2023/05/15 17:37:46 sjg Exp $ # SPDX-License-Identifier: BSD-2-Clause # @@ -212,12 +212,16 @@ _DEP_TARGET_SPEC = # it should be set by sys.mk or similar by now. # TARGET_SPEC must not contain any '.'s. TARGET_SPEC_VARS ?= MACHINE +# we allow for this to be a subset +TARGET_SPEC_VARS.host ?= MACHINE +TARGET_SPEC_VARS.host32 = ${TARGET_SPEC_VARS.host} # this is what we started with TARGET_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts,} # this is what we mostly use below -DEP_TARGET_SPEC = ${TARGET_SPEC_VARS:S,^,DEP_,:@v@${$v:U}@:ts,} +DEP_TARGET_SPEC_VARS = ${TARGET_SPEC_VARS.${DEP_MACHINE}:U${TARGET_SPEC_VARS}} +DEP_TARGET_SPEC = ${DEP_TARGET_SPEC_VARS:S,^,DEP_,:@v@${$v:U}@:ts,} # make sure we have defaults -.for v in ${TARGET_SPEC_VARS} +.for v in ${DEP_TARGET_SPEC_VARS} DEP_$v ?= ${$v} .endfor @@ -227,12 +231,7 @@ DEP_$v ?= ${$v} # we compute below are fully qualified wrt DEP_TARGET_SPEC. # The makefiles may only partially specify (eg. MACHINE only), # so we need to construct a set of modifiers to fill in the gaps. -.if ${MAKE_VERSION} >= 20170130 -_tspec_x := ${TARGET_SPEC_VARS:range} -.else -# do it the hard way -_tspec_x := ${TARGET_SPEC_VARS:[#]:@x@i=1;while [ $$i -le $x ]; do echo $$i; i=$$((i + 1)); done;@:sh} -.endif +_tspec_x := ${TARGET_SPEC_VARS:${M_RANGE:Urange}} # this handles unqualified entries M_dep_qual_fixes = C;(/[^/.,]+)$$;\1.$${DEP_TARGET_SPEC}; # there needs to be at least one item missing for these to make sense @@ -242,10 +241,27 @@ _tspec_a$i := ,${TARGET_SPEC_VARS:[$i..-1]:@v@$$$${DEP_$v}@:ts,} M_dep_qual_fixes += C;(\.${_tspec_m$i})$$;\1${_tspec_a$i}; .endfor TARGET_SPEC_VARSr := ${TARGET_SPEC_VARS:[-1..1]} +.if ${TARGET_SPEC_VARS.host} == ${TARGET_SPEC_VARS} +M_dep_qual_fixes.host = ${M_dep_qual_fixes} +.elif ${TARGET_SPEC_VARS.host:[#]} > 1 +_htspec_x := ${TARGET_SPEC_VARS.host:${M_RANGE:Urange}} +# this handles unqualified entries +M_dep_qual_fixes.host = C;(/[^/.,]+)$$;\1.$${DEP_TARGET_SPEC}; +# there needs to be at least one item missing for these to make sense +.for i in ${_htspec_x:[2..-1]} +_htspec_m$i := ${TARGET_SPEC_VARS.host:[2..$i]:@w@[^,]+@:ts,} +_htspec_a$i := ,${TARGET_SPEC_VARS.host:[$i..-1]:@v@$$$${DEP_$v}@:ts,} +M_dep_qual_fixes.host += C;(\.${_htspec_m$i})$$;\1${_htspec_a$i}; +.endfor +.else +M_dep_qual_fixes.host = U +.endif .else # A harmless? default. M_dep_qual_fixes = U .endif +M_dep_qual_fixes.host ?= ${M_dep_qual_fixes} +M_dep_qual_fixes.host32 = ${M_dep_qual_fixes.host} .if !defined(.MAKE.DEPENDFILE_PREFERENCE) # .MAKE.DEPENDFILE_PREFERENCE makes the logic below neater? @@ -328,7 +344,7 @@ _tspec := ${_DEP_TARGET_SPEC:S/,/ /g} .for i in ${_tspec_x} DEP_${TARGET_SPEC_VARS:[$i]} := ${_tspec:[$i]} .endfor -.for v in ${TARGET_SPEC_VARS:O:u} +.for v in ${DEP_TARGET_SPEC_VARS:O:u} .if empty(DEP_$v) .undef DEP_$v .endif @@ -337,14 +353,6 @@ DEP_${TARGET_SPEC_VARS:[$i]} := ${_tspec:[$i]} DEP_MACHINE := ${_DEP_TARGET_SPEC} .endif -# host is special -.if ${DEP_MACHINE:Mhost*} != "" -DEP_TARGET_SPEC = ${DEP_MACHINE} -.for v in ${TARGET_SPEC_VARS:O:u:NMACHINE} -.undef DEP_$v -.endfor -.endif - # reset each time through _build_all_dirs = _build_xtra_dirs = @@ -651,7 +659,7 @@ _machines += host _machines := ${_machines:O:u} .endif -.if ${TARGET_SPEC_VARS:[#]} > 1 +.if ${DEP_TARGET_SPEC_VARS:[#]} > 1 # we need to tweak _machines _dm := ${DEP_MACHINE} # apply the same filtering that we do when qualifying DIRDEPS. @@ -659,7 +667,7 @@ _dm := ${DEP_MACHINE} # Again we expect that any already qualified machines are fully qualified. _machines := ${_machines:M*,*} ${_machines:N*,*:@DEP_MACHINE@${DEP_TARGET_SPEC}@:S,^,.,:S,^.,,} DEP_MACHINE := ${_dm} -_machines := ${_machines:${M_dep_qual_fixes:ts:}:O:u} +_machines := ${_machines:${M_dep_qual_fixes.${DEP_MACHINE}:U${M_dep_qual_fixes}:ts:}:O:u} .endif # reset each time through @@ -717,7 +725,16 @@ _build_dirs += \ ${_machines:Nhost*:@m@${__unqual_depdirs:@d@$d.$m@}@} # qualify everything now -_build_dirs := ${_build_dirs:${M_dep_qual_fixes:ts:}:O:u} +.if ${_debug_reldir} +.info _build_dirs=${_build_dirs} +.endif +# make sure we do not mess with qualifying "host" entries +_build_dirs := ${_build_dirs:M*.host*:${M_dep_qual_fixes.host:ts:}} \ + ${_build_dirs:N*.host*:${M_dep_qual_fixes:ts:}} +_build_dirs := ${_build_dirs:O:u} +.if ${_debug_reldir} +.info _build_dirs=${_build_dirs} +.endif .endif # empty DIRDEPS @@ -767,9 +784,10 @@ _cache_script += echo; echo 'DIRDEPS.${_this_dir}.$m = \'; .endif # it would be nice to do :N${.TARGET} .if !empty(__qual_depdirs) -.for q in ${__qual_depdirs:${M_dep_qual_fixes:ts:}:E:O:u:N$m} +.for q in ${__qual_depdirs:M*.host*:${M_dep_qual_fixes.host:ts:}:E:O:u:N$m} \ + ${__qual_depdirs:N*.host*:${M_dep_qual_fixes:ts:}:E:O:u:N$m} .if ${_debug_reldir} || ${DEBUG_DIRDEPS:@x@${${DEP_RELDIR}.$m:L:M$x}${${DEP_RELDIR}.$q:L:M$x}@} != "" -.info ${DEP_RELDIR}.$m: graph: ${_build_dirs:M*.$q:S,^${SRCTOP}/,,} +.info ${DEP_RELDIR}.$m: q=$q graph: ${_build_dirs:M*.$q:S,^${SRCTOP}/,,} .endif .if ${BUILD_DIRDEPS_CACHE} == "yes" _cache_deps += ${_build_dirs:M*.$q:S,^${SRCTOP}/,,} @@ -816,14 +834,13 @@ _dr := ${d:S,^${SRCTOP}/,,} _DEP_TARGET_SPEC := ${d:E} # some makefiles may still look at this _DEP_MACHINE := ${d:E:C/,.*//} +DEP_MACHINE := ${_DEP_MACHINE} # set these too in case Makefile.depend* uses them -.if ${TARGET_SPEC_VARS:[#]} > 1 +.if ${DEP_TARGET_SPEC_VARS:[#]} > 1 _dtspec := ${_DEP_TARGET_SPEC:S/,/ /g} .for i in ${_tspec_x} -DEP_${TARGET_SPEC_VARS:[$i]} := ${_dtspec:[$i]} +DEP_${DEP_TARGET_SPEC_VARS:[$i]} := ${_dtspec:[$i]} .endfor -.else -DEP_MACHINE := ${_DEP_MACHINE} .endif # Warning: there is an assumption here that MACHINE is always # the first entry in TARGET_SPEC_VARS. @@ -831,7 +848,7 @@ DEP_MACHINE := ${_DEP_MACHINE} _m := ${.MAKE.DEPENDFILE_PREFERENCE:T:S;${TARGET_SPEC}$;${d:E};:C;${MACHINE}((,.+)?)$;${d:E:C/,.*//}\1;:@m@${exists(${d:R}/$m):?${d:R}/$m:}@:[1]} .if !empty(_m) # M_dep_qual_fixes isn't geared to Makefile.depend -_qm := ${_m:C;(\.depend)$;\1.${d:E};:${M_dep_qual_fixes:ts:}} +_qm := ${_m:C;(\.depend)$;\1.${d:E};:${M_dep_qual_fixes.${d:E}:U${M_dep_qual_fixes}:ts:}} .if ${_debug_search} .info Looking for ${_qm} .endif diff --git a/mk/host-target.mk b/mk/host-target.mk index 8d906e431779..f9f22027c00f 100644 --- a/mk/host-target.mk +++ b/mk/host-target.mk @@ -1,7 +1,10 @@ # RCSid: -# $Id: host-target.mk,v 1.14 2022/02/04 18:05:22 sjg Exp $ +# $Id: host-target.mk,v 1.18 2023/05/22 23:08:31 sjg Exp $ # Host platform information; may be overridden +.if !target(__${.PARSEFILE}__) +__${.PARSEFILE}__: .NOTMAIN + .if !defined(_HOST_OSNAME) # use .MAKE.OS if available _HOST_OSNAME := ${.MAKE.OS:U${uname -s:L:sh}} @@ -11,23 +14,27 @@ _HOST_OSNAME := ${.MAKE.OS:U${uname -s:L:sh}} _HOST_OSREL != uname -r .export _HOST_OSREL .endif -.if !defined(_HOST_MACHINE) -_HOST_MACHINE != uname -m -.export _HOST_MACHINE -.endif .if !defined(_HOST_ARCH) -# for Darwin and NetBSD prefer $MACHINE (amd64 rather than x86_64) -.if ${_HOST_OSNAME:NDarwin:NNetBSD} == "" -_HOST_ARCH := ${_HOST_MACHINE} -.else _HOST_ARCH != uname -p 2> /dev/null || uname -m # uname -p may produce garbage on linux .if ${_HOST_ARCH:[\#]} > 1 || ${_HOST_ARCH:Nunknown} == "" -_HOST_ARCH := ${_HOST_MACHINE} -.endif +_HOST_ARCH = ${_HOST_MACHINE} +.elif ${_HOST_OSNAME:NDarwin} == "" && ${_HOST_ARCH:Narm:Ni386} == "" +# _HOST_MACHINE is more explicit/useful +_HOST_ARCH = ${_HOST_MACHINE} .endif .export _HOST_ARCH .endif +.if !defined(_HOST_MACHINE) +_HOST_MACHINE != uname -m +# just in case +_HOST_ARCH := ${_HOST_ARCH} +# uname -m may produce garbage on darwin ppc +.if ${_HOST_MACHINE:[\#]} > 1 +_HOST_MACHINE := ${_HOST_ARCH} +.endif +.export _HOST_MACHINE +.endif .if !defined(HOST_MACHINE) HOST_MACHINE := ${_HOST_MACHINE} .export HOST_MACHINE @@ -48,3 +55,5 @@ HOST_TARGET32 := ${host_os:S,/,,g}${HOST_OSMAJOR}-${_HOST_ARCH32} TR ?= tr toLower = ${TR} 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' toUpper = ${TR} 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + +.endif diff --git a/mk/install-mk b/mk/install-mk index e198d52a8702..c056a39d1b1e 100644 --- a/mk/install-mk +++ b/mk/install-mk @@ -59,7 +59,7 @@ # Simon J. Gerraty # RCSid: -# $Id: install-mk,v 1.234 2023/05/13 15:52:24 sjg Exp $ +# $Id: install-mk,v 1.239 2023/05/29 18:04:48 sjg Exp $ # # @(#) Copyright (c) 1994-2023 Simon J. Gerraty # @@ -74,7 +74,7 @@ # sjg@crufty.net # -MK_VERSION=20230510 +MK_VERSION=20230601 OWNER= GROUP= MODE=444 diff --git a/mk/meta.autodep.mk b/mk/meta.autodep.mk index 5f012cdec003..851afce9f8b5 100644 --- a/mk/meta.autodep.mk +++ b/mk/meta.autodep.mk @@ -1,4 +1,4 @@ -# $Id: meta.autodep.mk,v 1.57 2023/05/13 15:52:24 sjg Exp $ +# $Id: meta.autodep.mk,v 1.58 2023/05/25 22:33:23 sjg Exp $ # # @(#) Copyright (c) 2010, Simon J. Gerraty @@ -210,7 +210,8 @@ _depend = .endif .if ${UPDATE_DEPENDFILE} == "yes" -gendirdeps: ${_DEPENDFILE} +gendirdeps: beforegendirdeps .WAIT ${_DEPENDFILE} +beforegendirdeps: .endif .if !target(${_DEPENDFILE}) diff --git a/mk/sys.dirdeps.mk b/mk/sys.dirdeps.mk index 845eda181b90..a3d22d7c2e82 100644 --- a/mk/sys.dirdeps.mk +++ b/mk/sys.dirdeps.mk @@ -1,4 +1,4 @@ -# $Id: sys.dirdeps.mk,v 1.9 2023/05/11 20:05:42 sjg Exp $ +# $Id: sys.dirdeps.mk,v 1.12 2023/05/14 16:16:03 sjg Exp $ # # @(#) Copyright (c) 2012-2023, Simon J. Gerraty # @@ -45,6 +45,7 @@ SRCTOP := ${SB_SRC:U${.PARSEDIR:tA:H:H}} .endif # fake SB if not using mk wrapper +# SB documented at http://www.crufty.net/sjg/docs/sb-tools.htm .if !defined(SB) SB := ${SRCTOP:H} .export SB @@ -54,6 +55,10 @@ SB := ${SRCTOP:H} OBJROOT := ${SB_OBJROOT:U${MAKEOBJDIRPREFIX:U${SB}/obj}/} .export OBJROOT .endif +# we expect OBJROOT to end with / (- can work too) +.if ${OBJROOT:M*[/-]} == "" +OBJROOT := ${OBJROOT}/ +.endif .if empty(STAGE_ROOT) STAGE_ROOT ?= ${OBJROOT}stage @@ -66,9 +71,6 @@ STAGE_ROOT ?= ${OBJROOT}stage # TARGET_SPEC must not contain any '.'s. TARGET_SPEC_VARS ?= MACHINE -.if !target(_tspec_env_done_) -_tspec_env_done_: .NOTMAIN - .if ${TARGET_SPEC:Uno:M*,*} != "" # deal with TARGET_SPEC from env _tspec := ${TARGET_SPEC:S/,/ /g} @@ -86,7 +88,6 @@ TARGET_SPEC= .endif .endfor .endif -.endif # Now make sure we know what TARGET_SPEC is # as we may need it to find Makefile.depend* @@ -98,6 +99,10 @@ TARGET_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts,} .endif .if ${TARGET_SPEC_VARS:[#]} > 1 +TARGET_SPEC_VARSr := ${TARGET_SPEC_VARS:[-1..1]} +# alternatives might be +# TARGET_OBJ_SPEC = ${TARGET_SPEC_VARSr:@v@${$v:U}@:ts/} +# TARGET_OBJ_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts/} TARGET_OBJ_SPEC ?= ${TARGET_SPEC_VARS:@v@${$v:U}@:ts.} .else TARGET_OBJ_SPEC ?= ${MACHINE} @@ -113,22 +118,37 @@ MACHINE0 := ${MACHINE} .export MACHINE0 .endif -.if ${MACHINE} == "host" -OBJTOP = ${HOST_OBJTOP} -.elif ${MACHINE} == "host32" -OBJTOP = ${HOST_OBJTOP32} -.endif - MACHINE_OBJ.host = ${HOST_TARGET} MACHINE_OBJ.host32 = ${HOST_TARGET32} MACHINE_OBJ.${MACHINE} ?= ${TARGET_OBJ_SPEC} MACHINE_OBJDIR = ${MACHINE_OBJ.${MACHINE}} -OBJTOP = ${OBJROOT}/${MACHINE_OBJDIR} +# we likely want to override env for OBJTOP +.if ${MACHINE} == "host" +OBJTOP = ${HOST_OBJTOP} +.elif ${MACHINE} == "host32" +OBJTOP = ${HOST_OBJTOP32} +.else +OBJTOP = ${OBJROOT}${MACHINE_OBJDIR} +.endif +.if ${.MAKE.LEVEL} > 0 +# should not change from level 1 onwards +# this only matters for cases like bmake/unit-tests +# where we do ${MAKE} -r +.export OBJTOP +.endif + +.if ${MAKEOBJDIR:U:M*/*} == "" # we do not use MAKEOBJDIRPREFIX +# though we may have used it above to initialize OBJROOT .undef MAKEOBJDIRPREFIX -# we use this -MAKEOBJDIR ?= ${.CURDIR:S,${SRCTOP},${OBJTOP},} +# this is what we expected in env +MAKEOBJDIR = $${.CURDIR:S,^$${SRCTOP},$${OBJTOP},} +# export that but do not track +.export-env MAKEOBJDIR +# this what we need here +MAKEOBJDIR = ${.CURDIR:S,${SRCTOP},${OBJTOP},} +.endif STAGE_MACHINE ?= ${MACHINE_OBJDIR} STAGE_OBJTOP ?= ${STAGE_ROOT}/${STAGE_MACHINE} diff --git a/mk/sys.vars.mk b/mk/sys.vars.mk index c3dcf6a7e7ef..974f24ca00b8 100644 --- a/mk/sys.vars.mk +++ b/mk/sys.vars.mk @@ -1,4 +1,4 @@ -# $Id: sys.vars.mk,v 1.14 2023/02/17 22:32:47 sjg Exp $ +# $Id: sys.vars.mk,v 1.15 2023/05/16 16:41:52 sjg Exp $ # # @(#) Copyright (c) 2003-2023, Simon J. Gerraty # @@ -129,3 +129,12 @@ M_Onr = Onr # index values use ${M_Index:S,K,key,}:[1] to select only the first. M_Index = _:${M_RANGE}:@i@$${"$${_:[$$i]:MK}":?$$i:}@ +# mtime of each word - assumed to be a valid pathname +.if ${.MAKE.LEVEL} < 20230510 +M_mtime = tW:S,^,${STAT:Ustat} -f %m ,:sh +.else +# M_mtime_fallback can be =error to throw an error +# or =0 to use 0, default is to use current time +M_mtime = mtime${M_mtime_fallback:U} +.endif + diff --git a/os.sh b/os.sh old mode 100755 new mode 100644 index 6bf52420c90f..78b2de95a679 --- a/os.sh +++ b/os.sh @@ -17,7 +17,7 @@ # Simon J. Gerraty # RCSid: -# $Id: os.sh,v 1.62 2023/01/17 18:30:21 sjg Exp $ +# $Id: os.sh,v 1.63 2023/05/22 20:44:47 sjg Exp $ # # @(#) Copyright (c) 1994 Simon J. Gerraty # @@ -41,12 +41,16 @@ OSMAJOR=`IFS=.; set $OSREL; echo $1` MACHINE=`uname -m` MACHINE_ARCH=`uname -p 2>/dev/null || echo $MACHINE` -# there is at least one case of `uname -p` outputting -# a bunch of usless drivel +# there is at least one case of `uname -p` +# and even `uname -m` outputting usless info +# fortunately not both together +case "$MACHINE" in +*[!A-Za-z0-9_-]*) MACHINE="$MACHINE_ARCH";; +esac case "$MACHINE_ARCH" in unknown|*[!A-Za-z0-9_-]*) MACHINE_ARCH="$MACHINE";; esac - + # we need this here, and it is not always available... Which() { case "$1" in @@ -87,7 +91,7 @@ AIX) # everyone loves to be different... PS_AXC=-e SHARE_ARCH=$OS/$OSMAJOR.X ;; -Darwin) # a bit like BSD +Darwin) # this is more explicit (arm64 vs arm) HOST_ARCH=$MACHINE ;; SunOS) @@ -140,10 +144,10 @@ SunOS) esac # NetBSD at least has good backward compatibility # so NetBSD/i386 is good enough + # recent NetBSD uses x86_64 for MACHINE_ARCH case $OS in NetBSD) LOCALBASE=/usr/pkg - HOST_ARCH=$MACHINE SHARE_ARCH=$OS/$HOST_ARCH ;; OpenBSD) diff --git a/parse.c b/parse.c index f0644ea67a14..c23e523fce58 100644 --- a/parse.c +++ b/parse.c @@ -1,4 +1,4 @@ -/* $NetBSD: parse.c,v 1.698 2023/05/10 16:10:02 rillig Exp $ */ +/* $NetBSD: parse.c,v 1.704 2023/06/23 06:08:56 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -121,7 +121,15 @@ #include "pathnames.h" /* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: parse.c,v 1.698 2023/05/10 16:10:02 rillig Exp $"); +MAKE_RCSID("$NetBSD: parse.c,v 1.704 2023/06/23 06:08:56 rillig Exp $"); + +/* Detects a multiple-inclusion guard in a makefile. */ +typedef enum { + GS_START, /* at the beginning of the file */ + GS_COND, /* after the guard condition */ + GS_DONE, /* after the closing .endif */ + GS_NO /* the file is not guarded */ +} GuardState; /* * A file being read. @@ -141,9 +149,12 @@ typedef struct IncludedFile { Buffer buf; /* the file's content or the body of the .for * loop; either empty or ends with '\n' */ - char *buf_ptr; /* next char to be read */ + char *buf_ptr; /* next char to be read from buf */ char *buf_end; /* buf_end[-1] == '\n' */ + GuardState guardState; + Guard *guard; + struct ForLoop *forLoop; } IncludedFile; @@ -315,6 +326,8 @@ static const struct { enum PosixState posix_state = PS_NOT_YET; +static HashTable /* full file name -> Guard */ guards; + static IncludedFile * GetInclude(size_t i) { @@ -429,8 +442,8 @@ IsEscaped(const char *line, const char *p) } /* - * Add the filename and lineno to the GNode so that we remember where it - * was first defined. + * Add the filename and lineno to the GNode so that we remember where its + * last command was added or where it was mentioned in a .depend file. */ static void RememberLocation(GNode *gn) @@ -1213,6 +1226,24 @@ FindInQuotPath(const char *file) return fullname; } +static bool +SkipGuarded(const char *fullname) +{ + Guard *guard = HashTable_FindValue(&guards, fullname); + if (guard != NULL && guard->kind == GK_VARIABLE + && GNode_ValueDirect(SCOPE_GLOBAL, guard->name) != NULL) + goto skip; + if (guard != NULL && guard->kind == GK_TARGET + && Targ_FindNode(guard->name) != NULL) + goto skip; + return false; + +skip: + DEBUG2(PARSE, "Skipping '%s' because '%s' is defined\n", + fullname, guard->name); + return true; +} + /* * Handle one of the .[-ds]include directives by remembering the current file * and pushing the included file on the stack. After the included file has @@ -1247,6 +1278,9 @@ IncludeFile(const char *file, bool isSystem, bool depinc, bool silent) return; } + if (SkipGuarded(fullname)) + return; + if ((fd = open(fullname, O_RDONLY)) == -1) { if (!silent) Parse_Error(PARSE_FATAL, "Cannot open %s", fullname); @@ -2190,6 +2224,8 @@ Parse_PushInput(const char *name, unsigned lineno, unsigned readLines, curFile->forBodyReadLines = readLines; curFile->buf = buf; curFile->depending = doing_depend; /* restore this on EOF */ + curFile->guardState = forLoop == NULL ? GS_START : GS_NO; + curFile->guard = NULL; curFile->forLoop = forLoop; if (forLoop != NULL && !For_NextIteration(forLoop, &curFile->buf)) @@ -2332,6 +2368,13 @@ ParseEOF(void) Cond_EndFile(); + if (curFile->guardState == GS_DONE) + HashTable_Set(&guards, curFile->name.str, curFile->guard); + else if (curFile->guard != NULL) { + free(curFile->guard->name); + free(curFile->guard); + } + FStr_Done(&curFile->name); Buf_Done(&curFile->buf); if (curFile->forLoop != NULL) @@ -2632,8 +2675,10 @@ static char * ReadHighLevelLine(void) { char *line; + CondResult condResult; for (;;) { + IncludedFile *curFile = CurFile(); line = ReadLowLevelLine(LK_NONEMPTY); if (posix_state == PS_MAYBE_NEXT_LINE) posix_state = PS_NOW_OR_NEVER; @@ -2642,10 +2687,24 @@ ReadHighLevelLine(void) if (line == NULL) return NULL; + if (curFile->guardState != GS_NO + && ((curFile->guardState == GS_START && line[0] != '.') + || curFile->guardState == GS_DONE)) + curFile->guardState = GS_NO; if (line[0] != '.') return line; - switch (Cond_EvalLine(line)) { + condResult = Cond_EvalLine(line); + if (curFile->guardState == GS_START) { + Guard *guard; + if (condResult != CR_ERROR + && (guard = Cond_ExtractGuard(line)) != NULL) { + curFile->guardState = GS_COND; + curFile->guard = guard; + } else + curFile->guardState = GS_NO; + } + switch (condResult) { case CR_FALSE: /* May also mean a syntax error. */ if (!SkipIrrelevantBranches()) return NULL; @@ -2716,10 +2775,14 @@ ParseLine_ShellCommand(const char *p) } static void -HandleBreak(void) +HandleBreak(const char *arg) { IncludedFile *curFile = CurFile(); + if (arg[0] != '\0') + Parse_Error(PARSE_FATAL, + "The .break directive does not take arguments"); + if (curFile->forLoop != NULL) { /* pretend we reached EOF */ For_Break(curFile->forLoop); @@ -2758,7 +2821,7 @@ ParseDirective(char *line) arg = cp; if (Substring_Equals(dir, "break")) - HandleBreak(); + HandleBreak(arg); else if (Substring_Equals(dir, "undef")) Var_Undef(arg); else if (Substring_Equals(dir, "export")) @@ -2796,6 +2859,23 @@ Parse_VarAssign(const char *line, bool finishDependencyGroup, GNode *scope) return true; } +void +Parse_GuardElse(void) +{ + IncludedFile *curFile = CurFile(); + if (cond_depth == curFile->condMinDepth + 1) + curFile->guardState = GS_NO; +} + +void +Parse_GuardEndif(void) +{ + IncludedFile *curFile = CurFile(); + if (cond_depth == curFile->condMinDepth + && curFile->guardState == GS_COND) + curFile->guardState = GS_DONE; +} + static char * FindSemicolon(char *p) { @@ -2986,6 +3066,7 @@ Parse_Init(void) sysIncPath = SearchPath_New(); defSysIncPath = SearchPath_New(); Vector_Init(&includes, sizeof(IncludedFile)); + HashTable_Init(&guards); } /* Clean up the parsing module. */ @@ -2993,6 +3074,8 @@ void Parse_End(void) { #ifdef CLEANUP + HashIter hi; + Lst_DoneCall(&targCmds, free); assert(targets == NULL); SearchPath_Free(defSysIncPath); @@ -3000,6 +3083,13 @@ Parse_End(void) SearchPath_Free(parseIncPath); assert(includes.len == 0); Vector_Done(&includes); + HashIter_Init(&hi, &guards); + while (HashIter_Next(&hi) != NULL) { + Guard *guard = hi.entry->value; + free(guard->name); + free(guard); + } + HashTable_Done(&guards); #endif } diff --git a/str.c b/str.c index 5bb9938296f5..2797e5567e92 100644 --- a/str.c +++ b/str.c @@ -1,4 +1,4 @@ -/* $NetBSD: str.c,v 1.94 2022/12/07 10:28:48 rillig Exp $ */ +/* $NetBSD: str.c,v 1.99 2023/06/23 05:03:04 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -71,7 +71,7 @@ #include "make.h" /* "@(#)str.c 5.8 (Berkeley) 6/1/90" */ -MAKE_RCSID("$NetBSD: str.c,v 1.94 2022/12/07 10:28:48 rillig Exp $"); +MAKE_RCSID("$NetBSD: str.c,v 1.99 2023/06/23 05:03:04 rillig Exp $"); static HashTable interned_strings; @@ -316,28 +316,26 @@ in_range(char e1, char c, char e2) * Test if a string matches a pattern like "*.[ch]". The pattern matching * characters are '*', '?' and '[]', as in fnmatch(3). * - * XXX: this function does not detect or report malformed patterns. - * * See varmod-match.mk for examples and edge cases. */ -bool +StrMatchResult Str_Match(const char *str, const char *pat) { - for (; *pat != '\0'; pat++, str++) { - if (*pat == '*') { /* match any substring */ - pat++; - while (*pat == '*') - pat++; - if (*pat == '\0') - return true; - for (; *str != '\0'; str++) - if (Str_Match(str, pat)) - return true; - return false; - } + StrMatchResult res = { NULL, false }; + const char *fixed_str, *fixed_pat; + bool asterisk, matched; + asterisk = false; + fixed_str = str; + fixed_pat = pat; + +match_fixed_length: + str = fixed_str; + pat = fixed_pat; + matched = false; + for (; *pat != '\0' && *pat != '*'; str++, pat++) { if (*str == '\0') - return false; + return res; if (*pat == '?') /* match any single character */ continue; @@ -346,25 +344,32 @@ Str_Match(const char *str, const char *pat) bool neg = pat[1] == '^'; pat += neg ? 2 : 1; - for (;;) { - if (*pat == ']' || *pat == '\0') { - if (neg) - break; - return false; - } - if (*pat == *str) - break; - if (pat[1] == '-') { - if (pat[2] == '\0') - return neg; - if (in_range(pat[0], *str, pat[2])) - break; - pat += 2; - } - pat++; + next_char_in_list: + if (*pat == '\0') + res.error = "Unfinished character list"; + if (*pat == ']' || *pat == '\0') { + if (neg) + goto end_of_char_list; + goto match_done; } + if (*pat == *str) + goto end_of_char_list; + if (pat[1] == '-' && pat[2] == '\0') { + res.error = "Unfinished character range"; + res.matched = neg; + return res; + } + if (pat[1] == '-') { + if (in_range(pat[0], *str, pat[2])) + goto end_of_char_list; + pat += 2; + } + pat++; + goto next_char_in_list; + + end_of_char_list: if (neg && *pat != ']' && *pat != '\0') - return false; + goto match_done; while (*pat != ']' && *pat != '\0') pat++; if (*pat == '\0') @@ -374,11 +379,44 @@ Str_Match(const char *str, const char *pat) if (*pat == '\\') /* match the next character exactly */ pat++; - if (*pat != *str) - return false; + goto match_done; } - return *str == '\0'; + matched = true; + +match_done: + if (!asterisk) { + if (!matched) + return res; + if (*pat == '\0') { + res.matched = *str == '\0'; + return res; + } + asterisk = true; + } else { + if (!matched) { + fixed_str++; + goto match_fixed_length; + } + if (*pat == '\0') { + if (*str == '\0') { + res.matched = true; + return res; + } + fixed_str += strlen(str); + goto match_fixed_length; + } + } + + while (*pat == '*') + pat++; + if (*pat == '\0') { + res.matched = true; + return res; + } + fixed_str = str; + fixed_pat = pat; + goto match_fixed_length; } void diff --git a/str.h b/str.h index 38fd2cf0da1a..71fd6bd15944 100644 --- a/str.h +++ b/str.h @@ -1,4 +1,4 @@ -/* $NetBSD: str.h,v 1.16 2022/12/05 23:41:24 rillig Exp $ */ +/* $NetBSD: str.h,v 1.17 2023/06/23 04:56:54 rillig Exp $ */ /* Copyright (c) 2021 Roland Illig @@ -70,6 +70,11 @@ typedef struct SubstringWords { void *freeIt; } SubstringWords; +typedef struct StrMatchResult { + const char *error; + bool matched; +} StrMatchResult; + MAKE_INLINE FStr FStr_Init(const char *str, void *freeIt) @@ -336,7 +341,7 @@ SubstringWords_Free(SubstringWords w) char *str_concat2(const char *, const char *); char *str_concat3(const char *, const char *, const char *); -bool Str_Match(const char *, const char *); +StrMatchResult Str_Match(const char *, const char *); void Str_Intern_Init(void); void Str_Intern_End(void); diff --git a/unit-tests/Makefile b/unit-tests/Makefile index a3f069133739..9bad6ff073ef 100644 --- a/unit-tests/Makefile +++ b/unit-tests/Makefile @@ -1,6 +1,6 @@ -# $Id: Makefile,v 1.195 2023/05/10 18:26:24 sjg Exp $ +# $Id: Makefile,v 1.199 2023/06/20 17:27:20 sjg Exp $ # -# $NetBSD: Makefile,v 1.335 2023/05/10 13:03:06 rillig Exp $ +# $NetBSD: Makefile,v 1.339 2023/06/20 09:25:34 rillig Exp $ # # Unit tests for make(1) # @@ -195,6 +195,7 @@ TESTS+= directive-ifndef TESTS+= directive-ifnmake TESTS+= directive-include TESTS+= directive-include-fatal +TESTS+= directive-include-guard TESTS+= directive-info TESTS+= directive-misspellings TESTS+= directive-sinclude @@ -211,7 +212,6 @@ TESTS+= export TESTS+= export-all TESTS+= export-env TESTS+= export-variants -TESTS+= forsubst TESTS+= gnode-submake TESTS+= hanoi-include TESTS+= impsrc @@ -228,7 +228,6 @@ TESTS+= lint TESTS+= make-exported TESTS+= meta-cmd-cmp TESTS+= moderrs -TESTS+= modmatch TESTS+= modmisc .if ${.MAKE.UID} > 0 TESTS+= objdir-writable @@ -424,10 +423,14 @@ TESTS+= varname-dot-make-meta-files .if ${.MAKE.PATH_FILEMON:Uno:Nktrace:N/dev*} == "" && ${TMPDIR:N/tmp*:N/var/tmp*} != "" # these tests will not work if TMPDIR is or is a subdir of # /tmp or /var/tmp +.if ${.MAKE.PATH_FILEMON:N/dev/*} != "" || exists(${.MAKE.PATH_FILEMON}) TESTS+= varname-dot-make-meta-ignore_filter TESTS+= varname-dot-make-meta-ignore_paths TESTS+= varname-dot-make-meta-ignore_patterns TESTS+= varname-dot-make-path_filemon +.else +.warning Skipping tests that require ${.MAKE.PATH_FILEMON} +.endif .endif TESTS+= varname-dot-make-meta-prefix TESTS+= varname-dot-make-mode @@ -538,6 +541,12 @@ FLAGS.varname-empty= -dv '$${:U}=cmdline-u' '=cmdline-plain' # Some tests need extra postprocessing. SED_CMDS.deptgt-phony= ${STD_SED_CMDS.dd} SED_CMDS.dir= ${STD_SED_CMDS.dd} +SED_CMDS.directive-include-guard= \ + -e '/\.MAKEFLAGS/d' \ + -e '/^Parsing line/d' \ + -e '/^SetFilenameVars:/d' \ + -e '/^ParseDependency/d' \ + -e '/^ParseEOF:/d' SED_CMDS.export= -e '/^[^=_A-Za-z0-9]*=/d' SED_CMDS.export-all= ${SED_CMDS.export} SED_CMDS.export-env= ${SED_CMDS.export} diff --git a/unit-tests/cmdline-undefined.exp b/unit-tests/cmdline-undefined.exp index 977ceee6dbf5..197f6da60131 100644 --- a/unit-tests/cmdline-undefined.exp +++ b/unit-tests/cmdline-undefined.exp @@ -1,17 +1,17 @@ The = assignment operator -make: "cmdline-undefined.mk" line 29: From the command line: Undefined is . -make: "cmdline-undefined.mk" line 30: From .MAKEFLAGS '=': Undefined is . -make: "cmdline-undefined.mk" line 31: From .MAKEFLAGS ':=': Undefined is . -make: "cmdline-undefined.mk" line 35: From the command line: Undefined is now defined. -make: "cmdline-undefined.mk" line 36: From .MAKEFLAGS '=': Undefined is now defined. -make: "cmdline-undefined.mk" line 37: From .MAKEFLAGS ':=': Undefined is now defined. +make: "cmdline-undefined.mk" line 31: From the command line: Undefined is . +make: "cmdline-undefined.mk" line 34: From .MAKEFLAGS '=': Undefined is . +make: "cmdline-undefined.mk" line 37: From .MAKEFLAGS ':=': Undefined is . +make: "cmdline-undefined.mk" line 43: From the command line: Undefined is now defined. +make: "cmdline-undefined.mk" line 46: From .MAKEFLAGS '=': Undefined is now defined. +make: "cmdline-undefined.mk" line 49: From .MAKEFLAGS ':=': Undefined is now defined. The := assignment operator -make: "cmdline-undefined.mk" line 29: From the command line: Undefined is . -make: "cmdline-undefined.mk" line 30: From .MAKEFLAGS '=': Undefined is . -make: "cmdline-undefined.mk" line 31: From .MAKEFLAGS ':=': Undefined is . -make: "cmdline-undefined.mk" line 35: From the command line: Undefined is now defined. -make: "cmdline-undefined.mk" line 36: From .MAKEFLAGS '=': Undefined is now defined. -make: "cmdline-undefined.mk" line 37: From .MAKEFLAGS ':=': Undefined is now defined. +make: "cmdline-undefined.mk" line 31: From the command line: Undefined is . +make: "cmdline-undefined.mk" line 34: From .MAKEFLAGS '=': Undefined is . +make: "cmdline-undefined.mk" line 37: From .MAKEFLAGS ':=': Undefined is . +make: "cmdline-undefined.mk" line 43: From the command line: Undefined is now defined. +make: "cmdline-undefined.mk" line 46: From .MAKEFLAGS '=': Undefined is now defined. +make: "cmdline-undefined.mk" line 49: From .MAKEFLAGS ':=': Undefined is now defined. exit status 0 diff --git a/unit-tests/cmdline-undefined.mk b/unit-tests/cmdline-undefined.mk index 5a3375cbbfb8..062449f80df2 100644 --- a/unit-tests/cmdline-undefined.mk +++ b/unit-tests/cmdline-undefined.mk @@ -1,4 +1,4 @@ -# $NetBSD: cmdline-undefined.mk,v 1.2 2020/11/04 04:49:33 rillig Exp $ +# $NetBSD: cmdline-undefined.mk,v 1.3 2023/06/01 20:56:35 rillig Exp $ # # Tests for undefined variable expressions in the command line. @@ -26,14 +26,26 @@ all: .MAKEFLAGS: MAKEFLAGS_ASSIGN='Undefined is $${UNDEFINED}.' .MAKEFLAGS: MAKEFLAGS_SUBST:='Undefined is $${UNDEFINED}.' +# expect+2: From the command line: Undefined is . +# expect+1: From the command line: Undefined is . .info From the command line: ${CMDLINE} +# expect+2: From .MAKEFLAGS '=': Undefined is . +# expect+1: From .MAKEFLAGS '=': Undefined is . .info From .MAKEFLAGS '=': ${MAKEFLAGS_ASSIGN} +# expect+2: From .MAKEFLAGS ':=': Undefined is . +# expect+1: From .MAKEFLAGS ':=': Undefined is . .info From .MAKEFLAGS ':=': ${MAKEFLAGS_SUBST} UNDEFINED?= now defined +# expect+2: From the command line: Undefined is now defined. +# expect+1: From the command line: Undefined is now defined. .info From the command line: ${CMDLINE} +# expect+2: From .MAKEFLAGS '=': Undefined is now defined. +# expect+1: From .MAKEFLAGS '=': Undefined is now defined. .info From .MAKEFLAGS '=': ${MAKEFLAGS_ASSIGN} +# expect+2: From .MAKEFLAGS ':=': Undefined is now defined. +# expect+1: From .MAKEFLAGS ':=': Undefined is now defined. .info From .MAKEFLAGS ':=': ${MAKEFLAGS_SUBST} print-undefined: diff --git a/unit-tests/cond-cmp-numeric-eq.exp b/unit-tests/cond-cmp-numeric-eq.exp index 72d3d935755b..059007f00c84 100644 --- a/unit-tests/cond-cmp-numeric-eq.exp +++ b/unit-tests/cond-cmp-numeric-eq.exp @@ -1,5 +1,5 @@ -make: "cond-cmp-numeric-eq.mk" line 67: Malformed conditional (!(12345 = 12345)) -make: "cond-cmp-numeric-eq.mk" line 74: Malformed conditional (!(12345 === 12345)) +make: "cond-cmp-numeric-eq.mk" line 68: Malformed conditional (!(12345 = 12345)) +make: "cond-cmp-numeric-eq.mk" line 76: Malformed conditional (!(12345 === 12345)) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/cond-cmp-numeric-eq.mk b/unit-tests/cond-cmp-numeric-eq.mk index c6b39876e75e..4c5f9b8aa830 100755 --- a/unit-tests/cond-cmp-numeric-eq.mk +++ b/unit-tests/cond-cmp-numeric-eq.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-cmp-numeric-eq.mk,v 1.5 2020/11/08 21:47:59 rillig Exp $ +# $NetBSD: cond-cmp-numeric-eq.mk,v 1.6 2023/06/01 20:56:35 rillig Exp $ # # Tests for numeric comparisons with the == operator in .if conditions. @@ -64,6 +64,7 @@ .endif # There is no = operator for numbers. +# expect+1: Malformed conditional (!(12345 = 12345)) .if !(12345 = 12345) . error .else @@ -71,6 +72,7 @@ .endif # There is no === operator for numbers either. +# expect+1: Malformed conditional (!(12345 === 12345)) .if !(12345 === 12345) . error .else diff --git a/unit-tests/cond-cmp-unary.exp b/unit-tests/cond-cmp-unary.exp index 89f90dc1651f..c5b800122eb9 100755 --- a/unit-tests/cond-cmp-unary.exp +++ b/unit-tests/cond-cmp-unary.exp @@ -1,2 +1,2 @@ -make: "cond-cmp-unary.mk" line 53: This is only reached because of a bug in EvalNotEmpty. +make: "cond-cmp-unary.mk" line 54: This is only reached because of a bug in EvalTruthy. exit status 0 diff --git a/unit-tests/cond-cmp-unary.mk b/unit-tests/cond-cmp-unary.mk index 90cd04e5092b..58927e3b4944 100755 --- a/unit-tests/cond-cmp-unary.mk +++ b/unit-tests/cond-cmp-unary.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-cmp-unary.mk,v 1.3 2022/09/08 05:43:20 rillig Exp $ +# $NetBSD: cond-cmp-unary.mk,v 1.5 2023/06/01 20:56:35 rillig Exp $ # # Tests for unary comparisons in .if conditions, that is, comparisons with # a single operand. If the operand is a number, it is compared to zero, @@ -26,8 +26,8 @@ # The empty string may come from a variable expression. # -# XXX: As of 2020-11-11, this empty string is interpreted "as a number" in -# EvalNotEmpty, which is plain wrong. The bug is in TryParseNumber. +# XXX: As of 2023-06-01, this empty string is interpreted "as a number" in +# EvalTruthy, which is plain wrong. The bug is in TryParseNumber. .if ${:U} . error .endif @@ -45,12 +45,13 @@ # A string of whitespace should evaluate to false. # -# XXX: As of 2020-11-11, the implementation in EvalNotEmpty does not skip +# XXX: As of 2023-06-01, the implementation in EvalTruthy does not skip # whitespace before testing for the end. This was probably an oversight in # a commit from 1992-04-15 saying "A variable is empty when it just contains # spaces". .if ${:U } -. info This is only reached because of a bug in EvalNotEmpty. +# expect+1: This is only reached because of a bug in EvalTruthy. +. info This is only reached because of a bug in EvalTruthy. .else . error .endif diff --git a/unit-tests/cond-eof.exp b/unit-tests/cond-eof.exp index 3016a9b27805..58a74d854d91 100644 --- a/unit-tests/cond-eof.exp +++ b/unit-tests/cond-eof.exp @@ -1,6 +1,6 @@ -make: "cond-eof.mk" line 15: Malformed conditional (0 ${SIDE_EFFECT} ${SIDE_EFFECT2}) -make: "cond-eof.mk" line 17: Malformed conditional (1 ${SIDE_EFFECT} ${SIDE_EFFECT2}) -make: "cond-eof.mk" line 19: Malformed conditional ((0) ${SIDE_EFFECT} ${SIDE_EFFECT2}) +make: "cond-eof.mk" line 17: Malformed conditional (0 ${SIDE_EFFECT} ${SIDE_EFFECT2}) +make: "cond-eof.mk" line 20: Malformed conditional (1 ${SIDE_EFFECT} ${SIDE_EFFECT2}) +make: "cond-eof.mk" line 23: Malformed conditional ((0) ${SIDE_EFFECT} ${SIDE_EFFECT2}) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/cond-eof.mk b/unit-tests/cond-eof.mk index ddf4a4cd20c8..25c6ec5de708 100644 --- a/unit-tests/cond-eof.mk +++ b/unit-tests/cond-eof.mk @@ -1,7 +1,8 @@ -# $NetBSD: cond-eof.mk,v 1.3 2021/12/10 23:12:44 rillig Exp $ +# $NetBSD: cond-eof.mk,v 1.5 2023/06/01 20:56:35 rillig Exp $ # -# Tests for parsing conditions, especially the end of such conditions, which -# are represented as the token TOK_EOF. +# Tests for parsing the end of '.if' conditions, which are represented as the +# token TOK_EOF. + SIDE_EFFECT= ${:!echo 'side effect' 1>&2!} SIDE_EFFECT2= ${:!echo 'side effect 2' 1>&2!} @@ -12,9 +13,12 @@ SIDE_EFFECT2= ${:!echo 'side effect 2' 1>&2!} # These syntax errors are an edge case that does not occur during normal # operation. Still, it is easy to avoid evaluating these expressions, just in # case they have side effects. +# expect+1: Malformed conditional (0 ${SIDE_EFFECT} ${SIDE_EFFECT2}) .if 0 ${SIDE_EFFECT} ${SIDE_EFFECT2} .endif +# expect+1: Malformed conditional (1 ${SIDE_EFFECT} ${SIDE_EFFECT2}) .if 1 ${SIDE_EFFECT} ${SIDE_EFFECT2} .endif +# expect+1: Malformed conditional ((0) ${SIDE_EFFECT} ${SIDE_EFFECT2}) .if (0) ${SIDE_EFFECT} ${SIDE_EFFECT2} .endif diff --git a/unit-tests/cond-func-defined.exp b/unit-tests/cond-func-defined.exp index 878f56de2ecc..c2fc78c1a35a 100644 --- a/unit-tests/cond-func-defined.exp +++ b/unit-tests/cond-func-defined.exp @@ -1,8 +1,8 @@ -make: "cond-func-defined.mk" line 23: Missing closing parenthesis for defined() -make: "cond-func-defined.mk" line 33: Missing closing parenthesis for defined() -make: "cond-func-defined.mk" line 45: In .for loops, variable expressions for the loop variables are -make: "cond-func-defined.mk" line 46: substituted at evaluation time. There is no actual variable -make: "cond-func-defined.mk" line 47: involved, even if it feels like it. +make: "cond-func-defined.mk" line 24: Missing closing parenthesis for defined() +make: "cond-func-defined.mk" line 34: Missing closing parenthesis for defined() +make: "cond-func-defined.mk" line 47: In .for loops, variable expressions for the loop variables are +make: "cond-func-defined.mk" line 49: substituted at evaluation time. There is no actual variable +make: "cond-func-defined.mk" line 51: involved, even if it feels like it. make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/cond-func-defined.mk b/unit-tests/cond-func-defined.mk index f13e2a9a1f7c..10adfde292ed 100644 --- a/unit-tests/cond-func-defined.mk +++ b/unit-tests/cond-func-defined.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-func-defined.mk,v 1.9 2022/05/08 06:51:27 rillig Exp $ +# $NetBSD: cond-func-defined.mk,v 1.10 2023/06/01 20:56:35 rillig Exp $ # # Tests for the defined() function in .if conditions. @@ -20,6 +20,7 @@ ${:UA B}= variable name with spaces .endif # The argument of a function must not directly contain whitespace. +# expect+1: Missing closing parenthesis for defined() .if !defined(A B) . error .endif @@ -29,7 +30,7 @@ ${:UA B}= variable name with spaces . error .endif -# Parse error: missing closing parenthesis; see ParseWord. +# expect+1: Missing closing parenthesis for defined() .if defined(DEF . error .else @@ -42,8 +43,11 @@ ${:UA B}= variable name with spaces . if defined(var) . error . else +# expect+1: In .for loops, variable expressions for the loop variables are . info In .for loops, variable expressions for the loop variables are +# expect+1: substituted at evaluation time. There is no actual variable . info substituted at evaluation time. There is no actual variable +# expect+1: involved, even if it feels like it. . info involved, even if it feels like it. . endif .endfor diff --git a/unit-tests/cond-func-empty.exp b/unit-tests/cond-func-empty.exp index 35d83adad5cb..5584b4062824 100644 --- a/unit-tests/cond-func-empty.exp +++ b/unit-tests/cond-func-empty.exp @@ -1,5 +1,5 @@ -make: "cond-func-empty.mk" line 153: Unclosed variable "WORD" -make: "cond-func-empty.mk" line 153: Malformed conditional (empty(WORD) +make: "cond-func-empty.mk" line 154: Unclosed variable "WORD" +make: "cond-func-empty.mk" line 154: Malformed conditional (empty(WORD) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/cond-func-empty.mk b/unit-tests/cond-func-empty.mk index 293305281298..69f489efae08 100644 --- a/unit-tests/cond-func-empty.mk +++ b/unit-tests/cond-func-empty.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-func-empty.mk,v 1.18 2023/03/04 21:15:30 rillig Exp $ +# $NetBSD: cond-func-empty.mk,v 1.20 2023/06/01 20:56:35 rillig Exp $ # # Tests for the empty() function in .if conditions, which tests a variable # expression for emptiness. @@ -25,7 +25,7 @@ WORD= word .endif # The :S modifier replaces the empty value with an actual word. After -# applying the :S modifier to the expression, it value is 'empty', so it is +# applying the :S modifier to the expression, its value is 'empty', so it is # no longer empty, but it is still based on an undefined variable. There are # a few modifiers that turn an undefined expression into a defined expression, # among them :U and :D, but not :S. Therefore, at the end of evaluating the @@ -149,7 +149,8 @@ ${:U WORD }= variable name with spaces . error .endif -# Parse error: missing closing parenthesis. +# expect+2: Unclosed variable "WORD" +# expect+1: Malformed conditional (empty(WORD) .if empty(WORD . error .else diff --git a/unit-tests/cond-func-make.exp b/unit-tests/cond-func-make.exp index 922203b72cbf..04ef6e29fee1 100644 --- a/unit-tests/cond-func-make.exp +++ b/unit-tests/cond-func-make.exp @@ -1,3 +1,4 @@ +make: "cond-func-make.mk" line 24: warning: Unfinished character list in pattern argument '[' to function 'make' : via-cmdline : via-dot-makeflags exit status 0 diff --git a/unit-tests/cond-func-make.mk b/unit-tests/cond-func-make.mk index d75b69bcf98f..15bc9f04d4e0 100644 --- a/unit-tests/cond-func-make.mk +++ b/unit-tests/cond-func-make.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-func-make.mk,v 1.3 2020/09/25 20:11:06 rillig Exp $ +# $NetBSD: cond-func-make.mk,v 1.5 2023/06/23 04:56:54 rillig Exp $ # # Tests for the make() function in .if conditions, which tests whether # the argument has been passed as a target via the command line or later @@ -20,5 +20,10 @@ . error .endif +# expect+1: warning: Unfinished character list in pattern argument '[' to function 'make' +.if make([) +. error +.endif + via-cmdline via-dot-makeflags: : $@ diff --git a/unit-tests/cond-func.exp b/unit-tests/cond-func.exp index d0663ea68647..eeaa89445887 100644 --- a/unit-tests/cond-func.exp +++ b/unit-tests/cond-func.exp @@ -1,12 +1,12 @@ -make: "cond-func.mk" line 36: Missing closing parenthesis for defined() -make: "cond-func.mk" line 51: Missing closing parenthesis for defined() -make: "cond-func.mk" line 54: Missing closing parenthesis for defined() -make: "cond-func.mk" line 94: The empty variable is never defined. -make: "cond-func.mk" line 103: A plain function name is parsed as defined(...). -make: "cond-func.mk" line 110: A plain function name is parsed as defined(...). -make: "cond-func.mk" line 120: Symbols may start with a function name. -make: "cond-func.mk" line 125: Symbols may start with a function name. -make: "cond-func.mk" line 131: Missing closing parenthesis for defined() +make: "cond-func.mk" line 37: Missing closing parenthesis for defined() +make: "cond-func.mk" line 53: Missing closing parenthesis for defined() +make: "cond-func.mk" line 57: Missing closing parenthesis for defined() +make: "cond-func.mk" line 98: The empty variable is never defined. +make: "cond-func.mk" line 108: A plain function name is parsed as defined(...). +make: "cond-func.mk" line 116: A plain function name is parsed as defined(...). +make: "cond-func.mk" line 127: Symbols may start with a function name. +make: "cond-func.mk" line 133: Symbols may start with a function name. +make: "cond-func.mk" line 139: Missing closing parenthesis for defined() make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/cond-func.mk b/unit-tests/cond-func.mk index e09b363edb64..2e8a6785b0e8 100644 --- a/unit-tests/cond-func.mk +++ b/unit-tests/cond-func.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-func.mk,v 1.12 2023/05/10 15:53:32 rillig Exp $ +# $NetBSD: cond-func.mk,v 1.13 2023/06/01 20:56:35 rillig Exp $ # # Tests for those parts of the functions in .if conditions that are common # among several functions. @@ -33,6 +33,7 @@ ${VARNAME_UNBALANCED_BRACES}= variable name with unbalanced braces .endif # The argument of a function must not directly contain whitespace. +# expect+1: Missing closing parenthesis for defined() .if !defined(A B) . error .endif @@ -48,9 +49,11 @@ ${VARNAME_UNBALANCED_BRACES}= variable name with unbalanced braces # # It's not entirely clear why these characters are forbidden. # The most plausible reason seems to be typo detection. +# expect+1: Missing closing parenthesis for defined() .if !defined(A&B) . error .endif +# expect+1: Missing closing parenthesis for defined() .if !defined(A|B) . error .endif @@ -91,6 +94,7 @@ ${VARNAME_UNBALANCED_BRACES}= variable name with unbalanced braces .if defined() . error .else +# expect+1: The empty variable is never defined. . info The empty variable is never defined. .endif @@ -100,6 +104,7 @@ ${VARNAME_UNBALANCED_BRACES}= variable name with unbalanced braces .if defined . error .else +# expect+1: A plain function name is parsed as defined(...). . info A plain function name is parsed as defined(...). .endif @@ -107,6 +112,7 @@ ${VARNAME_UNBALANCED_BRACES}= variable name with unbalanced braces # is interpreted as 'defined(defined)', and the condition evaluates to true. defined= # defined but empty .if defined +# expect+1: A plain function name is parsed as defined(...). . info A plain function name is parsed as defined(...). .else . error @@ -117,17 +123,19 @@ defined= # defined but empty .if defined-var . error .else +# expect+1: Symbols may start with a function name. . info Symbols may start with a function name. .endif defined-var= # defined but empty .if defined-var +# expect+1: Symbols may start with a function name. . info Symbols may start with a function name. .else . error .endif -# Missing closing parenthesis when parsing the function argument. +# expect+1: Missing closing parenthesis for defined() .if defined( . error .else diff --git a/unit-tests/cond-op-and-lint.exp b/unit-tests/cond-op-and-lint.exp index 8817fd0d658b..0f2cdb0028f9 100644 --- a/unit-tests/cond-op-and-lint.exp +++ b/unit-tests/cond-op-and-lint.exp @@ -1,4 +1,4 @@ -make: "cond-op-and-lint.mk" line 9: Unknown operator '&' +make: "cond-op-and-lint.mk" line 10: Unknown operator '&' make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/cond-op-and-lint.mk b/unit-tests/cond-op-and-lint.mk index 6262339016f5..bac4566314b0 100644 --- a/unit-tests/cond-op-and-lint.mk +++ b/unit-tests/cond-op-and-lint.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-op-and-lint.mk,v 1.1 2020/11/08 23:54:28 rillig Exp $ +# $NetBSD: cond-op-and-lint.mk,v 1.2 2023/06/01 20:56:35 rillig Exp $ # # Tests for the && operator in .if conditions, in lint mode. @@ -6,6 +6,7 @@ # The '&' operator is not allowed in lint mode. # It is not used in practice anyway. +# expect+1: Unknown operator '&' .if 0 & 0 . error .else diff --git a/unit-tests/cond-op-and.exp b/unit-tests/cond-op-and.exp index cd6b03a8359e..6d5a14b211cc 100644 --- a/unit-tests/cond-op-and.exp +++ b/unit-tests/cond-op-and.exp @@ -1,7 +1,7 @@ -make: "cond-op-and.mk" line 36: Malformed conditional (0 || (${DEF} && ${UNDEF})) -make: "cond-op-and.mk" line 40: Malformed conditional (0 || (${UNDEF} && ${UNDEF})) -make: "cond-op-and.mk" line 42: Malformed conditional (0 || (!${UNDEF} && ${UNDEF})) -make: "cond-op-and.mk" line 71: Malformed conditional (0 &&& 0) +make: "cond-op-and.mk" line 37: Malformed conditional (0 || (${DEF} && ${UNDEF})) +make: "cond-op-and.mk" line 42: Malformed conditional (0 || (${UNDEF} && ${UNDEF})) +make: "cond-op-and.mk" line 45: Malformed conditional (0 || (!${UNDEF} && ${UNDEF})) +make: "cond-op-and.mk" line 75: Malformed conditional (0 &&& 0) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/cond-op-and.mk b/unit-tests/cond-op-and.mk index 83386ed77de4..d12c6821f3b4 100644 --- a/unit-tests/cond-op-and.mk +++ b/unit-tests/cond-op-and.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-op-and.mk,v 1.6 2021/12/10 19:14:35 rillig Exp $ +# $NetBSD: cond-op-and.mk,v 1.7 2023/06/01 20:56:35 rillig Exp $ # # Tests for the && operator in .if conditions. @@ -33,12 +33,15 @@ # Test combinations of outer '||' with inner '&&', to ensure that the operands # of the inner '&&' are only evaluated if necessary. DEF= defined +# expect+1: Malformed conditional (0 || (${DEF} && ${UNDEF}) .if 0 || (${DEF} && ${UNDEF}) .endif .if 0 || (!${DEF} && ${UNDEF}) .endif +# expect+1: Malformed conditional (0 || (${UNDEF} && ${UNDEF}) .if 0 || (${UNDEF} && ${UNDEF}) .endif +# expect+1: Malformed conditional (0 || (!${UNDEF} && ${UNDEF}) .if 0 || (!${UNDEF} && ${UNDEF}) .endif .if 1 || (${DEF} && ${UNDEF}) @@ -68,6 +71,7 @@ DEF= defined .endif # There is no operator &&&. +# expect+1: Malformed conditional (0 &&& 0) .if 0 &&& 0 . error .endif diff --git a/unit-tests/cond-op-not.exp b/unit-tests/cond-op-not.exp index 440670ca7249..fcdceee9af21 100644 --- a/unit-tests/cond-op-not.exp +++ b/unit-tests/cond-op-not.exp @@ -1,9 +1,9 @@ -make: "cond-op-not.mk" line 29: Not empty evaluates to true. -make: "cond-op-not.mk" line 37: Not space evaluates to false. -make: "cond-op-not.mk" line 41: Not 0 evaluates to true. -make: "cond-op-not.mk" line 49: Not 1 evaluates to false. -make: "cond-op-not.mk" line 55: Not word evaluates to false. -make: "cond-op-not.mk" line 59: Malformed conditional (!) +make: "cond-op-not.mk" line 30: Not empty evaluates to true. +make: "cond-op-not.mk" line 39: Not space evaluates to false. +make: "cond-op-not.mk" line 44: Not 0 evaluates to true. +make: "cond-op-not.mk" line 53: Not 1 evaluates to false. +make: "cond-op-not.mk" line 60: Not word evaluates to false. +make: "cond-op-not.mk" line 65: Malformed conditional (!) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/cond-op-not.mk b/unit-tests/cond-op-not.mk index ffd5bc89e4bf..28f835fa3cbd 100644 --- a/unit-tests/cond-op-not.mk +++ b/unit-tests/cond-op-not.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-op-not.mk,v 1.7 2021/01/19 17:49:13 rillig Exp $ +# $NetBSD: cond-op-not.mk,v 1.8 2023/06/01 20:56:35 rillig Exp $ # # Tests for the ! operator in .if conditions, which negates its argument. @@ -26,6 +26,7 @@ .endif .if !${:U} +# expect+1: Not empty evaluates to true. . info Not empty evaluates to true. .else . info Not empty evaluates to false. @@ -34,10 +35,12 @@ .if !${:U } . info Not space evaluates to true. .else +# expect+1: Not space evaluates to false. . info Not space evaluates to false. .endif .if !${:U0} +# expect+1: Not 0 evaluates to true. . info Not 0 evaluates to true. .else . info Not 0 evaluates to false. @@ -46,16 +49,19 @@ .if !${:U1} . info Not 1 evaluates to true. .else +# expect+1: Not 1 evaluates to false. . info Not 1 evaluates to false. .endif .if !${:Uword} . info Not word evaluates to true. .else +# expect+1: Not word evaluates to false. . info Not word evaluates to false. .endif # A single exclamation mark is a parse error. +# expect+1: Malformed conditional (!) .if ! . error .else diff --git a/unit-tests/cond-op-or-lint.exp b/unit-tests/cond-op-or-lint.exp index 8abae99b6c4c..0fb1d0dae166 100644 --- a/unit-tests/cond-op-or-lint.exp +++ b/unit-tests/cond-op-or-lint.exp @@ -1,4 +1,4 @@ -make: "cond-op-or-lint.mk" line 9: Unknown operator '|' +make: "cond-op-or-lint.mk" line 10: Unknown operator '|' make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/cond-op-or-lint.mk b/unit-tests/cond-op-or-lint.mk index aa29e9a6c2f2..9ece9d5c9af6 100644 --- a/unit-tests/cond-op-or-lint.mk +++ b/unit-tests/cond-op-or-lint.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-op-or-lint.mk,v 1.1 2020/11/08 23:54:28 rillig Exp $ +# $NetBSD: cond-op-or-lint.mk,v 1.2 2023/06/01 20:56:35 rillig Exp $ # # Tests for the || operator in .if conditions, in lint mode. @@ -6,6 +6,7 @@ # The '|' operator is not allowed in lint mode. # It is not used in practice anyway. +# expect+1: Unknown operator '|' .if 0 | 0 . error .else diff --git a/unit-tests/cond-op-or.exp b/unit-tests/cond-op-or.exp index 43b9a5438a31..b10bc4bf7c52 100644 --- a/unit-tests/cond-op-or.exp +++ b/unit-tests/cond-op-or.exp @@ -1,7 +1,7 @@ -make: "cond-op-or.mk" line 46: Malformed conditional (1 && (!${DEF} || ${UNDEF})) -make: "cond-op-or.mk" line 48: Malformed conditional (1 && (${UNDEF} || ${UNDEF})) -make: "cond-op-or.mk" line 50: Malformed conditional (1 && (!${UNDEF} || ${UNDEF})) -make: "cond-op-or.mk" line 71: Malformed conditional (0 ||| 0) +make: "cond-op-or.mk" line 47: Malformed conditional (1 && (!${DEF} || ${UNDEF})) +make: "cond-op-or.mk" line 50: Malformed conditional (1 && (${UNDEF} || ${UNDEF})) +make: "cond-op-or.mk" line 53: Malformed conditional (1 && (!${UNDEF} || ${UNDEF})) +make: "cond-op-or.mk" line 75: Malformed conditional (0 ||| 0) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/cond-op-or.mk b/unit-tests/cond-op-or.mk index 0b7ac55e6c35..d0c9f3f2cd81 100644 --- a/unit-tests/cond-op-or.mk +++ b/unit-tests/cond-op-or.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-op-or.mk,v 1.8 2021/12/10 19:14:35 rillig Exp $ +# $NetBSD: cond-op-or.mk,v 1.9 2023/06/01 20:56:35 rillig Exp $ # # Tests for the || operator in .if conditions. @@ -43,10 +43,13 @@ DEF= defined .endif .if 1 && (${DEF} || ${UNDEF}) .endif +# expect+1: Malformed conditional (1 && (!${DEF} || ${UNDEF}) .if 1 && (!${DEF} || ${UNDEF}) .endif +# expect+1: Malformed conditional (1 && (${UNDEF} || ${UNDEF}) .if 1 && (${UNDEF} || ${UNDEF}) .endif +# expect+1: Malformed conditional (1 && (!${UNDEF} || ${UNDEF}) .if 1 && (!${UNDEF} || ${UNDEF}) .endif @@ -68,6 +71,7 @@ DEF= defined .endif # There is no operator |||. +# expect+1: Malformed conditional (0 ||| 0) .if 0 ||| 0 . error .endif diff --git a/unit-tests/cond-op-parentheses.exp b/unit-tests/cond-op-parentheses.exp index c2530f62de64..1daad92b2682 100644 --- a/unit-tests/cond-op-parentheses.exp +++ b/unit-tests/cond-op-parentheses.exp @@ -1,7 +1,7 @@ make: "cond-op-parentheses.mk" line 22: Comparison with '>' requires both operands '3' and '(2' to be numeric make: "cond-op-parentheses.mk" line 25: Malformed conditional ((3) > 2) -make: "cond-op-parentheses.mk" line 43: Malformed conditional (() -make: "cond-op-parentheses.mk" line 56: Malformed conditional ()) +make: "cond-op-parentheses.mk" line 44: Malformed conditional (() +make: "cond-op-parentheses.mk" line 58: Malformed conditional ()) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/cond-op-parentheses.mk b/unit-tests/cond-op-parentheses.mk index 8f8c3ee1e791..b6c9bd3c0e9d 100644 --- a/unit-tests/cond-op-parentheses.mk +++ b/unit-tests/cond-op-parentheses.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-op-parentheses.mk,v 1.6 2022/09/04 22:55:00 rillig Exp $ +# $NetBSD: cond-op-parentheses.mk,v 1.7 2023/06/01 20:56:35 rillig Exp $ # # Tests for parentheses in .if conditions, which group expressions to override # the precedence of the operators '!', '&&' and '||'. Parentheses cannot be @@ -40,6 +40,7 @@ .endif # An unbalanced opening parenthesis is a parse error. +# expect+1: Malformed conditional (() .if ( . error .else @@ -53,6 +54,7 @@ # TOK_TRUE, TOK_FALSE or TOK_ERROR. In cond.c 1.241, the return type of that # function was changed to a properly restricted enum type, to prevent this bug # from occurring again. +# expect+1: Malformed conditional ()) .if ) . error .else diff --git a/unit-tests/cond-op.exp b/unit-tests/cond-op.exp index b8f6a4301819..33bab484a6c8 100644 --- a/unit-tests/cond-op.exp +++ b/unit-tests/cond-op.exp @@ -1,22 +1,21 @@ -make: "cond-op.mk" line 50: Malformed conditional ("!word" == !word) -make: "cond-op.mk" line 76: Malformed conditional (0 ${ERR::=evaluated}) -make: "cond-op.mk" line 80: A misplaced expression after 0 is not evaluated. -make: "cond-op.mk" line 84: Malformed conditional (1 ${ERR::=evaluated}) -make: "cond-op.mk" line 88: A misplaced expression after 1 is not evaluated. -make: "cond-op.mk" line 92: Parsing continues until here. -make: "cond-op.mk" line 95: A B C => (A || B) && C A || B && C A || (B && C) -make: "cond-op.mk" line 102: 0 0 0 => 0 0 0 -make: "cond-op.mk" line 102: 0 0 1 => 0 0 0 -make: "cond-op.mk" line 102: 0 1 0 => 0 0 0 -make: "cond-op.mk" line 102: 0 1 1 => 1 1 1 -make: "cond-op.mk" line 102: 1 0 0 => 0 1 1 -make: "cond-op.mk" line 102: 1 0 1 => 1 1 1 -make: "cond-op.mk" line 102: 1 1 0 => 0 1 1 -make: "cond-op.mk" line 102: 1 1 1 => 1 1 1 -make: "cond-op.mk" line 113: Malformed conditional (1 &&) -make: "cond-op.mk" line 121: Malformed conditional (0 &&) -make: "cond-op.mk" line 129: Malformed conditional (1 ||) -make: "cond-op.mk" line 138: Malformed conditional (0 ||) +make: "cond-op.mk" line 51: Malformed conditional ("!word" == !word) +make: "cond-op.mk" line 72: Malformed conditional (0 ${ERR::=evaluated}) +make: "cond-op.mk" line 77: A misplaced expression after 0 is not evaluated. +make: "cond-op.mk" line 82: Malformed conditional (1 ${ERR::=evaluated}) +make: "cond-op.mk" line 87: A misplaced expression after 1 is not evaluated. +make: "cond-op.mk" line 93: A B C => (A || B) && C A || B && C A || (B && C) +make: "cond-op.mk" line 108: 0 0 0 => 0 0 0 +make: "cond-op.mk" line 108: 0 0 1 => 0 0 0 +make: "cond-op.mk" line 108: 0 1 0 => 0 0 0 +make: "cond-op.mk" line 108: 0 1 1 => 1 1 1 +make: "cond-op.mk" line 108: 1 0 0 => 0 1 1 +make: "cond-op.mk" line 108: 1 0 1 => 1 1 1 +make: "cond-op.mk" line 108: 1 1 0 => 0 1 1 +make: "cond-op.mk" line 108: 1 1 1 => 1 1 1 +make: "cond-op.mk" line 120: Malformed conditional (1 &&) +make: "cond-op.mk" line 129: Malformed conditional (0 &&) +make: "cond-op.mk" line 138: Malformed conditional (1 ||) +make: "cond-op.mk" line 148: Malformed conditional (0 ||) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/cond-op.mk b/unit-tests/cond-op.mk index c3ab09f7709a..6371e4db0594 100644 --- a/unit-tests/cond-op.mk +++ b/unit-tests/cond-op.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-op.mk,v 1.15 2021/12/10 23:12:44 rillig Exp $ +# $NetBSD: cond-op.mk,v 1.16 2023/06/01 20:56:35 rillig Exp $ # # Tests for operators like &&, ||, ! in .if conditions. # @@ -47,6 +47,7 @@ # appear unquoted. If any, it must be enclosed in quotes. # In any case, it is not interpreted as a negation of an unquoted string. # See CondParser_String. +# expect+1: Malformed conditional ("!word" == !word) .if "!word" == !word . error .endif @@ -66,32 +67,29 @@ # nevertheless, since CondParser_Or and CondParser_And asked for the expanded # next token, even though in this position of the condition, only comparison # operators, TOK_AND, TOK_OR or TOK_RPAREN are allowed. -# -# -# -# -# -# .undef ERR +# expect+1: Malformed conditional (0 ${ERR::=evaluated}) .if 0 ${ERR::=evaluated} . error .endif .if ${ERR:Uundefined} == undefined +# expect+1: A misplaced expression after 0 is not evaluated. . info A misplaced expression after 0 is not evaluated. .endif .undef ERR +# expect+1: Malformed conditional (1 ${ERR::=evaluated}) .if 1 ${ERR::=evaluated} . error .endif .if ${ERR:Uundefined} == undefined +# expect+1: A misplaced expression after 1 is not evaluated. . info A misplaced expression after 1 is not evaluated. .endif -# Just in case that parsing should ever stop on the first error. -.info Parsing continues until here. # Demonstration that '&&' has higher precedence than '||'. +# expect+1: A B C => (A || B) && C A || B && C A || (B && C) .info A B C => (A || B) && C A || B && C A || (B && C) .for a in 0 1 . for b in 0 1 @@ -99,6 +97,14 @@ . for r1 in ${ ($a || $b) && $c :?1:0} . for r2 in ${ $a || $b && $c :?1:0} . for r3 in ${ $a || ($b && $c) :?1:0} +# expect+8: 0 0 0 => 0 0 0 +# expect+7: 0 0 1 => 0 0 0 +# expect+6: 0 1 0 => 0 0 0 +# expect+5: 0 1 1 => 1 1 1 +# expect+4: 1 0 0 => 0 1 1 +# expect+3: 1 0 1 => 1 1 1 +# expect+2: 1 1 0 => 0 1 1 +# expect+1: 1 1 1 => 1 1 1 . info $a $b $c => ${r1} ${r2} ${r3} . endfor . endfor @@ -110,6 +116,7 @@ # This condition is obviously malformed. It is properly detected and also # was properly detected before 2021-01-19, but only because the left hand # side of the '&&' evaluated to true. +# expect+1: Malformed conditional (1 &&) .if 1 && . error .else @@ -118,6 +125,7 @@ # This obviously malformed condition was not detected as such before cond.c # 1.238 from 2021-01-19. +# expect+1: Malformed conditional (0 &&) .if 0 && . error .else @@ -126,6 +134,7 @@ # This obviously malformed condition was not detected as such before cond.c # 1.238 from 2021-01-19. +# expect+1: Malformed conditional (1 ||) .if 1 || . error .else @@ -135,6 +144,7 @@ # This condition is obviously malformed. It is properly detected and also # was properly detected before 2021-01-19, but only because the left hand # side of the '||' evaluated to false. +# expect+1: Malformed conditional (0 ||) .if 0 || . error .else diff --git a/unit-tests/cond-token-number.exp b/unit-tests/cond-token-number.exp index 1d472b63bc77..d05833b4e01b 100644 --- a/unit-tests/cond-token-number.exp +++ b/unit-tests/cond-token-number.exp @@ -1,7 +1,7 @@ -make: "cond-token-number.mk" line 15: Malformed conditional (-0) -make: "cond-token-number.mk" line 25: Malformed conditional (+0) -make: "cond-token-number.mk" line 35: Malformed conditional (!-1) -make: "cond-token-number.mk" line 45: Malformed conditional (!+1) +make: "cond-token-number.mk" line 16: Malformed conditional (-0) +make: "cond-token-number.mk" line 27: Malformed conditional (+0) +make: "cond-token-number.mk" line 38: Malformed conditional (!-1) +make: "cond-token-number.mk" line 49: Malformed conditional (!+1) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/cond-token-number.mk b/unit-tests/cond-token-number.mk index d1dd7371f447..6cec21cf6c44 100644 --- a/unit-tests/cond-token-number.mk +++ b/unit-tests/cond-token-number.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-token-number.mk,v 1.8 2023/03/04 08:07:29 rillig Exp $ +# $NetBSD: cond-token-number.mk,v 1.9 2023/06/01 20:56:35 rillig Exp $ # # Tests for number tokens in .if conditions. # @@ -12,6 +12,7 @@ # accepted by the condition parser. # # See the ch_isdigit call in CondParser_String. +# expect+1: Malformed conditional (-0) .if -0 . error .else @@ -22,6 +23,7 @@ # accepted by the condition parser. # # See the ch_isdigit call in CondParser_String. +# expect+1: Malformed conditional (+0) .if +0 . error .else @@ -32,6 +34,7 @@ # accepted by the condition parser. # # See the ch_isdigit call in CondParser_String. +# expect+1: Malformed conditional (!-1) .if !-1 . error .else @@ -42,6 +45,7 @@ # accepted by the condition parser. # # See the ch_isdigit call in CondParser_String. +# expect+1: Malformed conditional (!+1) .if !+1 . error .else diff --git a/unit-tests/cond-token-plain.exp b/unit-tests/cond-token-plain.exp index 572e8b3b2c9f..a14f69581658 100644 --- a/unit-tests/cond-token-plain.exp +++ b/unit-tests/cond-token-plain.exp @@ -27,37 +27,37 @@ Comparing "var&&name" != "var&&name" CondParser_Eval: ${:Uvar}||name != "var||name" Comparing "var||name" != "var||name" CondParser_Eval: bare -make: "cond-token-plain.mk" line 105: A bare word is treated like defined(...), and the variable 'bare' is not defined. +make: "cond-token-plain.mk" line 106: A bare word is treated like defined(...), and the variable 'bare' is not defined. CondParser_Eval: VAR -make: "cond-token-plain.mk" line 111: A bare word is treated like defined(...). +make: "cond-token-plain.mk" line 113: A bare word is treated like defined(...). CondParser_Eval: V${:UA}R -make: "cond-token-plain.mk" line 118: ok +make: "cond-token-plain.mk" line 121: ok CondParser_Eval: V${UNDEF}AR -make: "cond-token-plain.mk" line 126: Undefined variables in bare words expand to an empty string. +make: "cond-token-plain.mk" line 130: Undefined variables in bare words expand to an empty string. CondParser_Eval: 0${:Ux00} -make: "cond-token-plain.mk" line 134: Numbers can be composed from literals and variable expressions. +make: "cond-token-plain.mk" line 139: Numbers can be composed from literals and variable expressions. CondParser_Eval: 0${:Ux01} -make: "cond-token-plain.mk" line 138: Numbers can be composed from literals and variable expressions. +make: "cond-token-plain.mk" line 144: Numbers can be composed from literals and variable expressions. CondParser_Eval: "" == -make: "cond-token-plain.mk" line 144: Missing right-hand side of operator '==' +make: "cond-token-plain.mk" line 151: Missing right-hand side of operator '==' CondParser_Eval: == "" -make: "cond-token-plain.mk" line 152: Malformed conditional (== "") +make: "cond-token-plain.mk" line 160: Malformed conditional (== "") CondParser_Eval: \\ -make: "cond-token-plain.mk" line 167: The variable '\\' is not defined. +make: "cond-token-plain.mk" line 176: The variable '\\' is not defined. CondParser_Eval: \\ -make: "cond-token-plain.mk" line 172: Now the variable '\\' is defined. +make: "cond-token-plain.mk" line 182: Now the variable '\\' is defined. CondParser_Eval: "unquoted\"quoted" != unquoted"quoted Comparing "unquoted"quoted" != "unquoted"quoted" CondParser_Eval: $$$$$$$$ != "" -make: "cond-token-plain.mk" line 186: Malformed conditional ($$$$$$$$ != "") +make: "cond-token-plain.mk" line 197: Malformed conditional ($$$$$$$$ != "") CondParser_Eval: left == right -make: "cond-token-plain.mk" line 195: Malformed conditional (left == right) +make: "cond-token-plain.mk" line 206: Malformed conditional (left == right) CondParser_Eval: ${0:?:} || left == right CondParser_Eval: 0 -make: "cond-token-plain.mk" line 201: Malformed conditional (${0:?:} || left == right) +make: "cond-token-plain.mk" line 212: Malformed conditional (${0:?:} || left == right) CondParser_Eval: left == right || ${0:?:} -make: "cond-token-plain.mk" line 206: Malformed conditional (left == right || ${0:?:}) -make: "cond-token-plain.mk" line 225: Malformed conditional (VAR.${IF_COUNT::+=1} != "") +make: "cond-token-plain.mk" line 217: Malformed conditional (left == right || ${0:?:}) +make: "cond-token-plain.mk" line 236: Malformed conditional (VAR.${IF_COUNT::+=1} != "") make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/cond-token-plain.mk b/unit-tests/cond-token-plain.mk index 54bdd4fbf626..b6444e8ac1d3 100644 --- a/unit-tests/cond-token-plain.mk +++ b/unit-tests/cond-token-plain.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-token-plain.mk,v 1.17 2023/02/14 20:49:09 rillig Exp $ +# $NetBSD: cond-token-plain.mk,v 1.18 2023/06/01 20:56:35 rillig Exp $ # # Tests for plain tokens (that is, string literals without quotes) # in .if conditions. These are also called bare words. @@ -102,12 +102,14 @@ .if bare . error .else +# expect+1: A bare word is treated like defined(...), and the variable 'bare' is not defined. . info A bare word is treated like defined(...), and the variable $\ 'bare' is not defined. .endif VAR= defined .if VAR +# expect+1: A bare word is treated like defined(...). . info A bare word is treated like defined(...). .else . error @@ -115,6 +117,7 @@ VAR= defined # Bare words may be intermixed with variable expressions. .if V${:UA}R +# expect+1: ok . info ok .else . error @@ -123,6 +126,7 @@ VAR= defined # In bare words, even undefined variables are allowed. Without the bare # words, undefined variables are not allowed. That feels inconsistent. .if V${UNDEF}AR +# expect+1: Undefined variables in bare words expand to an empty string. . info Undefined variables in bare words expand to an empty string. .else . error @@ -131,16 +135,19 @@ VAR= defined .if 0${:Ux00} . error .else +# expect+1: Numbers can be composed from literals and variable expressions. . info Numbers can be composed from literals and variable expressions. .endif .if 0${:Ux01} +# expect+1: Numbers can be composed from literals and variable expressions. . info Numbers can be composed from literals and variable expressions. .else . error .endif # If the right-hand side is missing, it's a parse error. +# expect+1: Missing right-hand side of operator '==' .if "" == . error .else @@ -149,6 +156,7 @@ VAR= defined # If the left-hand side is missing, it's a parse error as well, but without # a specific error message. +# expect+1: Malformed conditional (== "") .if == "" . error .else @@ -164,11 +172,13 @@ VAR= defined .if \\ . error .else +# expect+1: The variable '\\' is not defined. . info The variable '\\' is not defined. .endif ${:U\\\\}= backslash .if \\ +# expect+1: Now the variable '\\' is defined. . info Now the variable '\\' is defined. .else . error @@ -183,6 +193,7 @@ ${:U\\\\}= backslash # FIXME: In CondParser_String, Var_Parse returns var_Error without a # corresponding error message. +# expect+1: Malformed conditional ($$$$$$$$ != "") .if $$$$$$$$ != "" . error .else diff --git a/unit-tests/cond-token-string.exp b/unit-tests/cond-token-string.exp index 854de02b7310..959effba0908 100644 --- a/unit-tests/cond-token-string.exp +++ b/unit-tests/cond-token-string.exp @@ -1,18 +1,18 @@ -make: "cond-token-string.mk" line 13: Unknown modifier "Z" -make: "cond-token-string.mk" line 13: Malformed conditional ("" != "${:Uvalue:Z}") -make: "cond-token-string.mk" line 22: xvalue is not defined. -make: "cond-token-string.mk" line 28: Malformed conditional (x${:Uvalue} == "") -make: "cond-token-string.mk" line 37: Expected. +make: "cond-token-string.mk" line 15: Unknown modifier "Z" +make: "cond-token-string.mk" line 15: Malformed conditional ("" != "${:Uvalue:Z}") +make: "cond-token-string.mk" line 25: xvalue is not defined. +make: "cond-token-string.mk" line 32: Malformed conditional (x${:Uvalue} == "") +make: "cond-token-string.mk" line 42: Expected. CondParser_Eval: "UNDEF" -make: "cond-token-string.mk" line 46: The string literal "UNDEF" is not empty. +make: "cond-token-string.mk" line 52: The string literal "UNDEF" is not empty. CondParser_Eval: " " -make: "cond-token-string.mk" line 54: The string literal " " is not empty, even though it consists of whitespace only. +make: "cond-token-string.mk" line 61: The string literal " " is not empty, even though it consists of whitespace only. CondParser_Eval: "${UNDEF}" -make: "cond-token-string.mk" line 63: An undefined variable in quotes expands to an empty string, which then evaluates to false. +make: "cond-token-string.mk" line 71: An undefined variable in quotes expands to an empty string, which then evaluates to false. CondParser_Eval: "${:Uvalue}" -make: "cond-token-string.mk" line 68: A nonempty variable expression evaluates to true. +make: "cond-token-string.mk" line 77: A nonempty variable expression evaluates to true. CondParser_Eval: "${:U}" -make: "cond-token-string.mk" line 76: An empty variable evaluates to false. +make: "cond-token-string.mk" line 86: An empty variable evaluates to false. CondParser_Eval: ("${VAR}") CondParser_Eval: "quoted" == quoted Comparing "quoted" == "quoted" diff --git a/unit-tests/cond-token-string.mk b/unit-tests/cond-token-string.mk index 4a0f175fc79f..7ecf3059e300 100644 --- a/unit-tests/cond-token-string.mk +++ b/unit-tests/cond-token-string.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-token-string.mk,v 1.6 2022/05/08 06:57:00 rillig Exp $ +# $NetBSD: cond-token-string.mk,v 1.8 2023/06/01 20:56:35 rillig Exp $ # # Tests for quoted string literals in .if conditions. # @@ -9,7 +9,9 @@ # TODO: Implementation # Cover the code in CondParser_String that frees the memory after parsing -# a variable expression based on an undefined variable. +# an expression based on an undefined variable. +# expect+2: Malformed conditional ("" != "${:Uvalue:Z}") +# expect+1: Unknown modifier "Z" .if "" != "${:Uvalue:Z}" . error .else @@ -19,12 +21,14 @@ .if x${:Uvalue} . error .else +# expect+1: xvalue is not defined. . info xvalue is not defined. .endif # The 'x' produces a "Malformed conditional" since the left-hand side of a # comparison in an .if directive must be either a variable expression, a # quoted string literal or a number that starts with a digit. +# expect+1: Malformed conditional (x${:Uvalue} == "") .if x${:Uvalue} == "" . error .else @@ -34,6 +38,7 @@ # In plain words, a '\' can be used to escape any character, just as in # double-quoted string literals. See CondParser_String. .if \x${:Uvalue} == "xvalue" +# expect+1: Expected. . info Expected. .else . error @@ -43,6 +48,7 @@ # A string in quotes is checked whether it is not empty. .if "UNDEF" +# expect+1: The string literal "UNDEF" is not empty. . info The string literal "UNDEF" is not empty. .else . error @@ -51,6 +57,7 @@ # A space is not empty as well. # This differs from many other places where whitespace is trimmed. .if " " +# expect+1: The string literal " " is not empty, even though it consists of whitespace only. . info The string literal " " is not empty, even though it consists of $\ whitespace only. .else @@ -60,11 +67,13 @@ .if "${UNDEF}" . error .else +# expect+1: An undefined variable in quotes expands to an empty string, which then evaluates to false. . info An undefined variable in quotes expands to an empty string, which $\ then evaluates to false. .endif .if "${:Uvalue}" +# expect+1: A nonempty variable expression evaluates to true. . info A nonempty variable expression evaluates to true. .else . error @@ -73,6 +82,7 @@ .if "${:U}" . error .else +# expect+1: An empty variable evaluates to false. . info An empty variable evaluates to false. .endif diff --git a/unit-tests/cond-token-var.exp b/unit-tests/cond-token-var.exp index fcd92d12a3da..d84ca56e981b 100644 --- a/unit-tests/cond-token-var.exp +++ b/unit-tests/cond-token-var.exp @@ -1,7 +1,7 @@ -make: "cond-token-var.mk" line 20: ok -make: "cond-token-var.mk" line 27: Malformed conditional (${UNDEF} == ${DEF}) -make: "cond-token-var.mk" line 33: Malformed conditional (${DEF} == ${UNDEF}) -make: "cond-token-var.mk" line 42: Malformed conditional (${UNDEF}) +make: "cond-token-var.mk" line 21: ok +make: "cond-token-var.mk" line 28: Malformed conditional (${UNDEF} == ${DEF}) +make: "cond-token-var.mk" line 34: Malformed conditional (${DEF} == ${UNDEF}) +make: "cond-token-var.mk" line 44: Malformed conditional (${UNDEF}) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/cond-token-var.mk b/unit-tests/cond-token-var.mk index 168c63c46ac1..b50c0439c127 100644 --- a/unit-tests/cond-token-var.mk +++ b/unit-tests/cond-token-var.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-token-var.mk,v 1.6 2021/04/25 21:05:38 rillig Exp $ +# $NetBSD: cond-token-var.mk,v 1.7 2023/06/01 20:56:35 rillig Exp $ # # Tests for variable expressions in .if conditions. # @@ -17,19 +17,20 @@ DEF= defined # A defined variable may appear on either side of the comparison. .if ${DEF} == ${DEF} +# expect+1: ok . info ok .else . error .endif # A variable that appears on the left-hand side must be defined. -# The following line thus generates a parse error. +# expect+1: Malformed conditional (${UNDEF} == ${DEF}) .if ${UNDEF} == ${DEF} . error .endif # A variable that appears on the right-hand side must be defined. -# The following line thus generates a parse error. +# expect+1: Malformed conditional (${DEF} == ${UNDEF}) .if ${DEF} == ${UNDEF} . error .endif @@ -39,6 +40,7 @@ DEF= defined .endif # An undefined variable on its own generates a parse error. +# expect+1: Malformed conditional (${UNDEF}) .if ${UNDEF} .endif diff --git a/unit-tests/cond-undef-lint.exp b/unit-tests/cond-undef-lint.exp index 55073b2116c6..efab46113f67 100755 --- a/unit-tests/cond-undef-lint.exp +++ b/unit-tests/cond-undef-lint.exp @@ -1,10 +1,10 @@ -make: "cond-undef-lint.mk" line 23: Variable "UNDEF" is undefined -make: "cond-undef-lint.mk" line 23: Malformed conditional (${UNDEF}) -make: "cond-undef-lint.mk" line 38: Variable "UNDEF" is undefined -make: "cond-undef-lint.mk" line 38: Variable "VAR." is undefined -make: "cond-undef-lint.mk" line 38: Malformed conditional (${VAR.${UNDEF}}) -make: "cond-undef-lint.mk" line 49: Variable "VAR.defined" is undefined -make: "cond-undef-lint.mk" line 49: Malformed conditional (${VAR.${DEF}}) +make: "cond-undef-lint.mk" line 25: Variable "UNDEF" is undefined +make: "cond-undef-lint.mk" line 25: Malformed conditional (${UNDEF}) +make: "cond-undef-lint.mk" line 43: Variable "UNDEF" is undefined +make: "cond-undef-lint.mk" line 43: Variable "VAR." is undefined +make: "cond-undef-lint.mk" line 43: Malformed conditional (${VAR.${UNDEF}}) +make: "cond-undef-lint.mk" line 56: Variable "VAR.defined" is undefined +make: "cond-undef-lint.mk" line 56: Malformed conditional (${VAR.${DEF}}) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/cond-undef-lint.mk b/unit-tests/cond-undef-lint.mk index 9dfd1bd53252..6fd353dc60e2 100755 --- a/unit-tests/cond-undef-lint.mk +++ b/unit-tests/cond-undef-lint.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-undef-lint.mk,v 1.3 2020/11/15 14:58:14 rillig Exp $ +# $NetBSD: cond-undef-lint.mk,v 1.4 2023/06/01 20:56:35 rillig Exp $ # # Tests for defined and undefined variables in .if conditions, in lint mode. # @@ -20,6 +20,8 @@ DEF= defined .endif # Since the condition fails to evaluate, neither of the branches is taken. +# expect+2: Malformed conditional (${UNDEF}) +# expect+1: Variable "UNDEF" is undefined .if ${UNDEF} . error .else @@ -35,6 +37,9 @@ DEF= defined # # TODO: Suppress the error message "Variable VAR. is undefined". That part # of the expression must not be evaluated at all. +# expect+3: Variable "UNDEF" is undefined +# expect+2: Variable "VAR." is undefined +# expect+1: Malformed conditional (${VAR.${UNDEF}}) .if ${VAR.${UNDEF}} . error .else @@ -46,6 +51,8 @@ DEF= defined # TODO: This pattern looks a lot like CFLAGS.${OPSYS}, which is at least # debatable. Or would any practical use of CFLAGS.${OPSYS} be via an indirect # expression, as in the next example? +# expect+2: Variable "VAR.defined" is undefined +# expect+1: Malformed conditional (${VAR.${DEF}}) .if ${VAR.${DEF}} . error .else diff --git a/unit-tests/dep-colon-bug-cross-file.exp b/unit-tests/dep-colon-bug-cross-file.exp index 855b575c48bc..a8ef9d0707af 100644 --- a/unit-tests/dep-colon-bug-cross-file.exp +++ b/unit-tests/dep-colon-bug-cross-file.exp @@ -1,4 +1,4 @@ -make: "dep-colon-bug-cross-file.mk" line 31: warning: duplicate script for target "all" ignored -make: "dep-colon-bug-cross-file.mk" line 40: warning: using previous script for "all" defined here +make: "dep-colon-bug-cross-file.mk" line 32: warning: duplicate script for target "all" ignored +make: "dep-colon-bug-cross-file.mk" line 42: warning: using previous script for "all" defined here : pass 1 exit status 0 diff --git a/unit-tests/dep-colon-bug-cross-file.mk b/unit-tests/dep-colon-bug-cross-file.mk index 57fbf478163c..930358af2871 100644 --- a/unit-tests/dep-colon-bug-cross-file.mk +++ b/unit-tests/dep-colon-bug-cross-file.mk @@ -1,4 +1,4 @@ -# $NetBSD: dep-colon-bug-cross-file.mk,v 1.4 2020/09/27 09:53:41 rillig Exp $ +# $NetBSD: dep-colon-bug-cross-file.mk,v 1.5 2023/06/01 20:56:35 rillig Exp $ # # Until 2020-09-25, the very last dependency group of a top-level makefile # was not finished properly. This made it possible to add further commands @@ -28,6 +28,7 @@ PASS?= 1 .if ${PASS} == 2 all: +# expect+1: warning: duplicate script for target "all" ignored : pass 2 .endif @@ -37,5 +38,6 @@ PASS= 2 .MAKEFLAGS: -f ${.PARSEDIR:q}/${.PARSEFILE:q} all: +# expect+1: warning: using previous script for "all" defined here : pass 1 .endif diff --git a/unit-tests/dep-wildcards.mk b/unit-tests/dep-wildcards.mk index 781b149f5a70..b3e2f14a07c3 100644 --- a/unit-tests/dep-wildcards.mk +++ b/unit-tests/dep-wildcards.mk @@ -1,4 +1,4 @@ -# $NetBSD: dep-wildcards.mk,v 1.3 2020/09/08 05:33:05 rillig Exp $ +# $NetBSD: dep-wildcards.mk,v 1.4 2023/06/21 12:27:50 rillig Exp $ # # Tests for wildcards such as *.c in dependency declarations. @@ -7,3 +7,9 @@ all: ${.PARSEDIR}/dep-*.mk # The :O is necessary since the result of the dependency resolution # does not order the directory entries itself. @printf '%s\n' ${.ALLSRC:T:O} + +# This is not a wildcard rule as implemented by GNU make, as those rules would +# use '%' instead of '*'. Instead, the pattern '*.target' is a file pattern +# in the current working directory. As there are no such files, the target +# list becomes empty, and the source pattern '*.source' is not even expanded. +*.target: *.source diff --git a/unit-tests/dep.mk b/unit-tests/dep.mk index 54566d43d2a1..53fadc789b13 100644 --- a/unit-tests/dep.mk +++ b/unit-tests/dep.mk @@ -1,4 +1,4 @@ -# $NetBSD: dep.mk,v 1.3 2021/12/13 23:38:54 rillig Exp $ +# $NetBSD: dep.mk,v 1.4 2023/06/01 07:27:30 rillig Exp $ # # Tests for dependency declarations, such as "target: sources". @@ -15,4 +15,16 @@ only-colon:: # would be another error message. only-colon: + +# Before parse.c 1.158 from 2009-10-07, the parser broke dependency lines at +# the first ';', without parsing expressions as such. It interpreted the +# first ';' as the separator between the dependency and its commands, and the +# '^' as a shell command. +all: for-subst +.for file in ${.PARSEFILE} +for-subst: ${file:S;^;./;g} + @echo ".for with :S;... OK" +.endfor + + all: diff --git a/unit-tests/deptgt-begin.exp b/unit-tests/deptgt-begin.exp index abc80afe9964..db4c7d7dfa13 100644 --- a/unit-tests/deptgt-begin.exp +++ b/unit-tests/deptgt-begin.exp @@ -1,5 +1,5 @@ -make: "deptgt-begin.mk" line 17: warning: duplicate script for target ".BEGIN" ignored -make: "deptgt-begin.mk" line 8: warning: using previous script for ".BEGIN" defined here +make: "deptgt-begin.mk" line 19: warning: duplicate script for target ".BEGIN" ignored +make: "deptgt-begin.mk" line 9: warning: using previous script for ".BEGIN" defined here : parse time : Making before-begin before .BEGIN. : .BEGIN diff --git a/unit-tests/deptgt-begin.mk b/unit-tests/deptgt-begin.mk index 543e377c05db..8b9842641a2d 100644 --- a/unit-tests/deptgt-begin.mk +++ b/unit-tests/deptgt-begin.mk @@ -1,9 +1,10 @@ -# $NetBSD: deptgt-begin.mk,v 1.6 2022/05/07 08:01:20 rillig Exp $ +# $NetBSD: deptgt-begin.mk,v 1.7 2023/06/01 20:56:35 rillig Exp $ # # Tests for the special target .BEGIN in dependency declarations, # which is a container for commands that are run before any other # commands from the shell lines. +# expect+2: warning: using previous script for ".BEGIN" defined here .BEGIN: : $@ @@ -13,6 +14,7 @@ # add its commands after this. # # There are several ways to resolve this situation, which are detailed below. +# expect+2: warning: duplicate script for target ".BEGIN" ignored .BEGIN: : Making another $@. diff --git a/unit-tests/deptgt-delete_on_error.mk b/unit-tests/deptgt-delete_on_error.mk index e6d0610f4672..2309e67c01a5 100644 --- a/unit-tests/deptgt-delete_on_error.mk +++ b/unit-tests/deptgt-delete_on_error.mk @@ -1,4 +1,4 @@ - # $NetBSD: deptgt-delete_on_error.mk,v 1.3 2020/10/25 21:31:00 rillig Exp $ +# $NetBSD: deptgt-delete_on_error.mk,v 1.4 2023/06/01 20:56:35 rillig Exp $ # # Tests for the special target .DELETE_ON_ERROR in dependency declarations, # which controls whether the target is deleted if a shell command fails or diff --git a/unit-tests/deptgt.exp b/unit-tests/deptgt.exp index 73d4a7f0c33f..00d312685de9 100644 --- a/unit-tests/deptgt.exp +++ b/unit-tests/deptgt.exp @@ -1,17 +1,17 @@ -make: "deptgt.mk" line 10: warning: Extra target '.PHONY' ignored -make: "deptgt.mk" line 28: Unassociated shell command ": command3 # parse error, since targets == NULL" -Parsing line 34: ${:U}: empty-source -ParseDependency(: empty-source) -Parsing line 35: : command for empty targets list -Parsing line 36: : empty-source +make: "deptgt.mk" line 11: warning: Extra target '.PHONY' ignored +make: "deptgt.mk" line 30: Unassociated shell command ": command3 # parse error, since targets == NULL" +Parsing line 36: ${:U}: empty-source ParseDependency(: empty-source) Parsing line 37: : command for empty targets list -Parsing line 38: .MAKEFLAGS: -d0 +Parsing line 38: : empty-source +ParseDependency(: empty-source) +Parsing line 39: : command for empty targets list +Parsing line 40: .MAKEFLAGS: -d0 ParseDependency(.MAKEFLAGS: -d0) -make: "deptgt.mk" line 46: Unknown modifier "Z" -make: "deptgt.mk" line 49: warning: Extra target 'ordinary' ignored -make: "deptgt.mk" line 52: warning: Extra target (ordinary) ignored -make: "deptgt.mk" line 55: warning: Special and mundane targets don't mix. Mundane ones ignored +make: "deptgt.mk" line 49: Unknown modifier "Z" +make: "deptgt.mk" line 52: warning: Extra target 'ordinary' ignored +make: "deptgt.mk" line 55: warning: Extra target (ordinary) ignored +make: "deptgt.mk" line 58: warning: Special and mundane targets don't mix. Mundane ones ignored make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/deptgt.mk b/unit-tests/deptgt.mk index 7d43220e888a..67c47e4909e6 100644 --- a/unit-tests/deptgt.mk +++ b/unit-tests/deptgt.mk @@ -1,4 +1,4 @@ -# $NetBSD: deptgt.mk,v 1.13 2023/01/03 00:00:45 rillig Exp $ +# $NetBSD: deptgt.mk,v 1.14 2023/06/01 20:56:35 rillig Exp $ # # Tests for special targets like .BEGIN or .SUFFIXES in dependency # declarations. @@ -7,6 +7,7 @@ # Just in case anyone tries to compile several special targets in a single # dependency line: That doesn't work, and make immediately rejects it. +# expect+1: warning: Extra target '.PHONY' ignored .SUFFIXES .PHONY: .c.o # The following lines demonstrate how 'targets' is set and reset during @@ -25,6 +26,7 @@ target1 target2: sources # targets := [target1, target2] : command1 # targets == [target1, target2] : command2 # targets == [target1, target2] VAR=value # targets := NULL +# expect+1: Unassociated shell command ": command3 # parse error, since targets == NULL" : command3 # parse error, since targets == NULL # In a dependency declaration, the list of targets can be empty. @@ -43,6 +45,7 @@ ${:U}: empty-source # expansion would be to use the variable modifier '::=' to modify the # targets. This in turn would be such an extreme and unreliable edge case # that nobody uses it. +# expect+1: Unknown modifier "Z" $$$$$$$${:U:Z}: # expect+1: warning: Extra target 'ordinary' ignored diff --git a/unit-tests/directive-elif.exp b/unit-tests/directive-elif.exp index 6856494023d7..15dd6bf1430b 100644 --- a/unit-tests/directive-elif.exp +++ b/unit-tests/directive-elif.exp @@ -1,21 +1,21 @@ -make: "directive-elif.mk" line 47: Unknown directive "elsif" -make: "directive-elif.mk" line 52: This branch is taken. -make: "directive-elif.mk" line 60: Unknown directive "elsif" -make: "directive-elif.mk" line 63: This branch is taken. -make: "directive-elif.mk" line 69: This branch is taken. -make: "directive-elif.mk" line 89: Unknown directive "elsif" -make: "directive-elif.mk" line 90: This misspelling is detected. -make: "directive-elif.mk" line 91: This branch is taken because of the .else. -make: "directive-elif.mk" line 109: What happens on misspelling in a skipped branch? -make: "directive-elif.mk" line 119: else -make: "directive-elif.mk" line 122: What happens on misspelling in a taken branch? -make: "directive-elif.mk" line 124: 1-then -make: "directive-elif.mk" line 125: Unknown directive "elsif" -make: "directive-elif.mk" line 126: 1-elsif -make: "directive-elif.mk" line 127: Unknown directive "elsif" -make: "directive-elif.mk" line 128: 2-elsif -make: "directive-elif.mk" line 134: if-less elif -make: "directive-elif.mk" line 139: warning: extra elif +make: "directive-elif.mk" line 48: Unknown directive "elsif" +make: "directive-elif.mk" line 54: This branch is taken. +make: "directive-elif.mk" line 62: Unknown directive "elsif" +make: "directive-elif.mk" line 66: This branch is taken. +make: "directive-elif.mk" line 73: This branch is taken. +make: "directive-elif.mk" line 94: Unknown directive "elsif" +make: "directive-elif.mk" line 96: This misspelling is detected. +make: "directive-elif.mk" line 98: This branch is taken because of the .else. +make: "directive-elif.mk" line 117: What happens on misspelling in a skipped branch? +make: "directive-elif.mk" line 128: else +make: "directive-elif.mk" line 132: What happens on misspelling in a taken branch? +make: "directive-elif.mk" line 135: 1-then +make: "directive-elif.mk" line 137: Unknown directive "elsif" +make: "directive-elif.mk" line 139: 1-elsif +make: "directive-elif.mk" line 141: Unknown directive "elsif" +make: "directive-elif.mk" line 143: 2-elsif +make: "directive-elif.mk" line 149: if-less elif +make: "directive-elif.mk" line 154: warning: extra elif make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/directive-elif.mk b/unit-tests/directive-elif.mk index e7b89beec4e9..d6500cc1e872 100644 --- a/unit-tests/directive-elif.mk +++ b/unit-tests/directive-elif.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-elif.mk,v 1.7 2020/12/19 19:49:01 rillig Exp $ +# $NetBSD: directive-elif.mk,v 1.8 2023/06/01 20:56:35 rillig Exp $ # # Tests for the .elif directive. # @@ -44,28 +44,32 @@ # Misspelling '.elsif' below an .if branch that is taken. .if 1 # This misspelling is in an active branch and is therefore detected. +# expect+1: Unknown directive "elsif" .elsif 0 # The only thing that make detects here is a misspelled directive, make # doesn't recognize that it was meant to be a conditional directive. # Therefore the branch continues here, even though the '.elsif' condition # evaluates to false. +# expect+1: This branch is taken. . info This branch is taken. .endif # Misspelling '.elsif' below an .if branch that is taken. .if 1 -# As of 2020-12-19, the misspelling is in an active branch and is therefore -# detected. +# The misspelling is in an active branch and is therefore detected. +# expect+1: Unknown directive "elsif" .elsif 1 # Since both conditions evaluate to true, this branch is taken no matter # whether make detects a misspelling or not. +# expect+1: This branch is taken. . info This branch is taken. .endif # Misspelling '.elsif' in a skipped branch below a branch that was taken. .if 1 +# expect+1: This branch is taken. . info This branch is taken. .elif 0 . info This branch is not taken. @@ -86,8 +90,11 @@ # Misspelling '.elsif' in an .else branch that is taken. .if 0 .else +# expect+1: Unknown directive "elsif" .elsif 1 +# expect+1: This misspelling is detected. . info This misspelling is detected. +# expect+1: This branch is taken because of the .else. . info This branch is taken because of the .else. .endif @@ -106,6 +113,7 @@ .endif +# expect+1: What happens on misspelling in a skipped branch? .info What happens on misspelling in a skipped branch? .if 0 . info 0-then @@ -116,26 +124,33 @@ . info XXX: This misspelling is not detected. . info 2-elsif .else +# expect+1: else . info else .endif +# expect+1: What happens on misspelling in a taken branch? .info What happens on misspelling in a taken branch? .if 1 +# expect+1: 1-then . info 1-then +# expect+1: Unknown directive "elsif" .elsif 1 +# expect+1: 1-elsif . info 1-elsif +# expect+1: Unknown directive "elsif" .elsif 2 +# expect+1: 2-elsif . info 2-elsif .else . info else .endif -# Expect: "if-less elif" +# expect+1: if-less elif .elif 0 .if 1 .else -# Expect: "warning: extra elif" +# expect+1: warning: extra elif .elif .endif diff --git a/unit-tests/directive-else.exp b/unit-tests/directive-else.exp index 17d5571ba74b..992b60e9308b 100644 --- a/unit-tests/directive-else.exp +++ b/unit-tests/directive-else.exp @@ -1,11 +1,11 @@ make: "directive-else.mk" line 14: The .else directive does not take arguments -make: "directive-else.mk" line 15: ok -make: "directive-else.mk" line 19: ok -make: "directive-else.mk" line 21: The .else directive does not take arguments -make: "directive-else.mk" line 26: if-less else -make: "directive-else.mk" line 32: ok -make: "directive-else.mk" line 33: warning: extra else -make: "directive-else.mk" line 45: The .else directive does not take arguments +make: "directive-else.mk" line 16: ok +make: "directive-else.mk" line 21: ok +make: "directive-else.mk" line 23: The .else directive does not take arguments +make: "directive-else.mk" line 29: if-less else +make: "directive-else.mk" line 36: ok +make: "directive-else.mk" line 38: warning: extra else +make: "directive-else.mk" line 51: The .else directive does not take arguments make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/directive-else.mk b/unit-tests/directive-else.mk index 794057110ef7..41b38a14a6cf 100644 --- a/unit-tests/directive-else.mk +++ b/unit-tests/directive-else.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-else.mk,v 1.7 2020/12/14 22:17:11 rillig Exp $ +# $NetBSD: directive-else.mk,v 1.8 2023/06/01 20:56:35 rillig Exp $ # # Tests for the .else directive. # @@ -10,26 +10,31 @@ .if 0 . warning must not be reached -# The .else directive does not take any arguments. +# expect+1: The .else directive does not take arguments .else 123 +# expect+1: ok . info ok .endif .if 1 +# expect+1: ok . info ok -# The .else directive does not take any arguments. +# expect+1: The .else directive does not take arguments .else 123 . warning must not be reached .endif # An .else without a corresponding .if is an error. +# expect+1: if-less else .else # Accidental extra .else directives are detected too. .if 0 . warning must not be reached .else +# expect+1: ok . info ok +# expect+1: warning: extra else .else . info After an extra .else, everything is skipped. .endif @@ -42,6 +47,7 @@ # A variable expression does count as an argument, even if it is empty. .if 0 +# expect+1: The .else directive does not take arguments .else ${:U} .endif diff --git a/unit-tests/directive-endfor.exp b/unit-tests/directive-endfor.exp index 7e243a8f67e6..8b77c0b31307 100644 --- a/unit-tests/directive-endfor.exp +++ b/unit-tests/directive-endfor.exp @@ -1,4 +1,4 @@ -make: "directive-endfor.mk" line 9: for-less endfor +make: "directive-endfor.mk" line 10: for-less endfor make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/directive-endfor.mk b/unit-tests/directive-endfor.mk index b0c37f388504..93119156fb89 100644 --- a/unit-tests/directive-endfor.mk +++ b/unit-tests/directive-endfor.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-endfor.mk,v 1.1 2020/12/30 14:50:08 rillig Exp $ +# $NetBSD: directive-endfor.mk,v 1.2 2023/06/01 20:56:35 rillig Exp $ # # Test for the directive .endfor, which ends a .for loop. # @@ -6,4 +6,5 @@ # directive-for.mk # An .endfor without a corresponding .for is a parse error. +# expect+1: for-less endfor .endfor diff --git a/unit-tests/directive-endif.exp b/unit-tests/directive-endif.exp index 0de1ecf0bf25..c88cc97c44c5 100644 --- a/unit-tests/directive-endif.exp +++ b/unit-tests/directive-endif.exp @@ -1,8 +1,8 @@ -make: "directive-endif.mk" line 18: The .endif directive does not take arguments -make: "directive-endif.mk" line 23: The .endif directive does not take arguments -make: "directive-endif.mk" line 33: The .endif directive does not take arguments +make: "directive-endif.mk" line 16: The .endif directive does not take arguments +make: "directive-endif.mk" line 21: The .endif directive does not take arguments +make: "directive-endif.mk" line 32: The .endif directive does not take arguments make: "directive-endif.mk" line 39: The .endif directive does not take arguments -make: "directive-endif.mk" line 45: Unknown directive "endifx" +make: "directive-endif.mk" line 44: Unknown directive "endifx" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/directive-endif.mk b/unit-tests/directive-endif.mk index 10dd6ce22ce8..5e01382af5f2 100644 --- a/unit-tests/directive-endif.mk +++ b/unit-tests/directive-endif.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-endif.mk,v 1.5 2020/12/14 21:56:17 rillig Exp $ +# $NetBSD: directive-endif.mk,v 1.7 2023/06/01 20:56:35 rillig Exp $ # # Tests for the .endif directive. # @@ -8,18 +8,16 @@ # See also: # Cond_EvalLine -# TODO: Implementation - .MAKEFLAGS: -dL -# Error: .endif does not take arguments .if 0 -# Since 2020-12-15, complain about the extra text after the 'endif'. +# Since 2020-12-15: +# expect+1: The .endif directive does not take arguments .endif 0 -# Error: .endif does not take arguments .if 1 -# Since 2020-12-15, complain about the extra text after the 'endif'. +# Since 2020-12-15: +# expect+1: The .endif directive does not take arguments .endif 1 # Comments are allowed after an '.endif'. @@ -29,21 +27,19 @@ # Only whitespace and comments are allowed after an '.endif', but nothing # else. .if 1 -# Since 2020-12-15, complain about the extra text after the 'endif'. +# Since 2020-12-15: +# expect+1: The .endif directive does not take arguments .endif0 # Only whitespace and comments are allowed after an '.endif', but nothing # else. .if 1 -# Since 2020-12-15, complain about the extra text after the 'endif'. +# Since 2020-12-15: +# expect+1: The .endif directive does not take arguments .endif/ -# After an '.endif', no other letter must occur. This 'endifx' is not -# parsed as an 'endif', therefore another '.endif' must follow to balance -# the directives. +# After an '.endif', no other letter must occur. .if 1 +# expect+1: Unknown directive "endifx" .endifx -.endif # to close the preceding '.if' - -all: - @:; +.endif # to close the preceding '.if' diff --git a/unit-tests/directive-error.exp b/unit-tests/directive-error.exp index bad12326a514..8ce33160e67f 100644 --- a/unit-tests/directive-error.exp +++ b/unit-tests/directive-error.exp @@ -1,4 +1,4 @@ -make: "directive-error.mk" line 13: message +make: "directive-error.mk" line 14: message make: stopped in unit-tests exit status 1 diff --git a/unit-tests/directive-error.mk b/unit-tests/directive-error.mk index 135db2159dd2..f35a9da3a018 100644 --- a/unit-tests/directive-error.mk +++ b/unit-tests/directive-error.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-error.mk,v 1.5 2021/01/27 00:02:38 rillig Exp $ +# $NetBSD: directive-error.mk,v 1.6 2023/06/01 20:56:35 rillig Exp $ # # Tests for the .error directive, which prints an error message and exits # immediately, unlike other "fatal" parse errors, which continue to parse @@ -10,4 +10,5 @@ # Before parse.c 1.532 from 2021-01-27, the ".error" issued an irrelevant # message saying "parsing warnings being treated as errors". .MAKEFLAGS: -W +# expect+1: message .error message diff --git a/unit-tests/directive-for-break.exp b/unit-tests/directive-for-break.exp index b036ebfeb661..64941448141c 100644 --- a/unit-tests/directive-for-break.exp +++ b/unit-tests/directive-for-break.exp @@ -1,4 +1,5 @@ make: "directive-for-break.mk" line 45: break outside of for loop +make: "directive-for-break.mk" line 65: The .break directive does not take arguments make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/directive-for-break.mk b/unit-tests/directive-for-break.mk index a86acfa8bde0..d9290d38c215 100644 --- a/unit-tests/directive-for-break.mk +++ b/unit-tests/directive-for-break.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-for-break.mk,v 1.3 2022/09/24 10:52:05 rillig Exp $ +# $NetBSD: directive-for-break.mk,v 1.5 2023/06/01 20:56:35 rillig Exp $ # # Tests for .break in .for loops, which immediately terminates processing of # the surrounding .for loop. @@ -58,3 +58,9 @@ COMBINED+= ${outer}-${inner} . endfor . endif .endif + + +.for i in 1 +# expect+1: The .break directive does not take arguments +. break 1 +.endfor diff --git a/unit-tests/directive-for-empty.exp b/unit-tests/directive-for-empty.exp index b9764b3196af..5cc3ac846b36 100644 --- a/unit-tests/directive-for-empty.exp +++ b/unit-tests/directive-for-empty.exp @@ -1,9 +1,9 @@ -make: "directive-for-empty.mk" line 21: 2 -make: "directive-for-empty.mk" line 34: Missing argument for ".error" -make: "directive-for-empty.mk" line 34: Missing argument for ".error" -make: "directive-for-empty.mk" line 34: Missing argument for ".error" +make: "directive-for-empty.mk" line 22: 2 +make: "directive-for-empty.mk" line 38: Missing argument for ".error" +make: "directive-for-empty.mk" line 38: Missing argument for ".error" +make: "directive-for-empty.mk" line 38: Missing argument for ".error" For: end for 1 -For: loop body: +For: loop body with i = value: # The identifier 'empty' can only be used in conditions such as .if, .ifdef or # .elif. In other lines the string 'empty(' must be preserved. CPPFLAGS+= -Dmessage="empty(i)" diff --git a/unit-tests/directive-for-empty.mk b/unit-tests/directive-for-empty.mk index 7f22a822ef77..52a65b39beeb 100644 --- a/unit-tests/directive-for-empty.mk +++ b/unit-tests/directive-for-empty.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-for-empty.mk,v 1.1 2022/05/23 22:33:56 rillig Exp $ +# $NetBSD: directive-for-empty.mk,v 1.2 2023/06/01 20:56:35 rillig Exp $ # # Tests for .for loops containing conditions of the form 'empty(var:...)'. # @@ -18,6 +18,7 @@ # when in fact they aren't. .for i in 11 12 13 . if ${i:M*2*} +# expect+1: 2 .info 2 . endif .endfor @@ -31,6 +32,9 @@ # Asking for an empty iteration variable does not make sense as the .for loop # splits the iteration items into words, and such a word cannot be empty. . if empty(i) +# expect+3: Missing argument for ".error" +# expect+2: Missing argument for ".error" +# expect+1: Missing argument for ".error" . error # due to the leaky abstraction . endif # The typical way of using 'empty' with variables from .for loops is pattern diff --git a/unit-tests/directive-for-errors.exp b/unit-tests/directive-for-errors.exp index 36ed569c7932..115a6af5b069 100644 --- a/unit-tests/directive-for-errors.exp +++ b/unit-tests/directive-for-errors.exp @@ -1,17 +1,17 @@ -make: "directive-for-errors.mk" line 11: Unknown directive "fori" -make: "directive-for-errors.mk" line 12: warning: <> -make: "directive-for-errors.mk" line 13: for-less endfor -make: "directive-for-errors.mk" line 27: Unknown directive "for" -make: "directive-for-errors.mk" line 28: warning: <> -make: "directive-for-errors.mk" line 29: for-less endfor -make: "directive-for-errors.mk" line 46: invalid character '$' in .for loop variable name -make: "directive-for-errors.mk" line 54: no iteration variables in for -make: "directive-for-errors.mk" line 66: Wrong number of words (5) in .for substitution list with 3 variables -make: "directive-for-errors.mk" line 80: missing `in' in for -make: "directive-for-errors.mk" line 91: Unknown modifier "Z" -make: "directive-for-errors.mk" line 92: warning: Should not be reached. -make: "directive-for-errors.mk" line 92: warning: Should not be reached. -make: "directive-for-errors.mk" line 92: warning: Should not be reached. +make: "directive-for-errors.mk" line 9: Unknown directive "fori" +make: "directive-for-errors.mk" line 10: warning: <> +make: "directive-for-errors.mk" line 11: for-less endfor +make: "directive-for-errors.mk" line 25: Unknown directive "for" +make: "directive-for-errors.mk" line 26: warning: <> +make: "directive-for-errors.mk" line 27: for-less endfor +make: "directive-for-errors.mk" line 44: invalid character '$' in .for loop variable name +make: "directive-for-errors.mk" line 52: no iteration variables in for +make: "directive-for-errors.mk" line 64: Wrong number of words (5) in .for substitution list with 3 variables +make: "directive-for-errors.mk" line 78: missing `in' in for +make: "directive-for-errors.mk" line 89: Unknown modifier "Z" +make: "directive-for-errors.mk" line 90: warning: Should not be reached. +make: "directive-for-errors.mk" line 90: warning: Should not be reached. +make: "directive-for-errors.mk" line 90: warning: Should not be reached. make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/directive-for-errors.mk b/unit-tests/directive-for-errors.mk index 24df5e131839..0af65350e643 100644 --- a/unit-tests/directive-for-errors.mk +++ b/unit-tests/directive-for-errors.mk @@ -1,9 +1,7 @@ -# $NetBSD: directive-for-errors.mk,v 1.5 2023/05/09 19:43:12 rillig Exp $ +# $NetBSD: directive-for-errors.mk,v 1.6 2023/06/01 20:56:35 rillig Exp $ # # Tests for error handling in .for loops. -# expect-all - # A .for directive must be followed by whitespace, everything else results # in a parse error. diff --git a/unit-tests/directive-for-escape.exp b/unit-tests/directive-for-escape.exp index 0326b62377f3..1f6c6bcc3109 100644 --- a/unit-tests/directive-for-escape.exp +++ b/unit-tests/directive-for-escape.exp @@ -1,60 +1,60 @@ For: end for 1 -For: loop body: +For: loop body with chars = !"#$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~: . info ${:U!"#$%&'()*+,-./0-9\:;<=>?@A-Z[\\]_^a-z{|\}~} make: Unclosed variable expression, expecting '}' for modifier "U!"" of variable "" with value "!"" -make: "directive-for-escape.mk" line 21: !" +make: "directive-for-escape.mk" line 19: !" For: end for 1 -For: loop body: +For: loop body with chars = !"\\#$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~: . info ${:U!"\\\\#$%&'()*+,-./0-9\:;<=>?@A-Z[\\]_^a-z{|\}~} make: Unclosed variable expression, expecting '}' for modifier "U!"\\\\" of variable "" with value "!"\\" -make: "directive-for-escape.mk" line 32: !"\\ +make: "directive-for-escape.mk" line 30: !"\\ For: end for 1 -For: loop body: +For: loop body with i = $: . info ${:U\$} -make: "directive-for-escape.mk" line 47: $ -For: loop body: +make: "directive-for-escape.mk" line 45: $ +For: loop body with i = ${V}: . info ${:U${V}} -make: "directive-for-escape.mk" line 47: value -For: loop body: +make: "directive-for-escape.mk" line 45: value +For: loop body with i = ${V:=-with-modifier}: . info ${:U${V:=-with-modifier}} -make: "directive-for-escape.mk" line 47: value-with-modifier -For: loop body: +make: "directive-for-escape.mk" line 45: value-with-modifier +For: loop body with i = $(V): . info ${:U$(V)} -make: "directive-for-escape.mk" line 47: value -For: loop body: +make: "directive-for-escape.mk" line 45: value +For: loop body with i = $(V:=-with-modifier): . info ${:U$(V:=-with-modifier)} -make: "directive-for-escape.mk" line 47: value-with-modifier +make: "directive-for-escape.mk" line 45: value-with-modifier For: end for 1 -For: loop body: +For: loop body with i = ${UNDEF:U\$\$: # ${:U\${UNDEF\:U\\$\\$} -For: loop body: +For: loop body with i = {{}}: # ${:U{{\}\}} -For: loop body: +For: loop body with i = end}: # ${:Uend\}} For: end for 1 -For: loop body: +For: loop body with i = ${UNDEF:U\$\$: . info ${:U\${UNDEF\:U\\$\\$} -make: "directive-for-escape.mk" line 101: ${UNDEF:U\backslash$ -For: loop body: +make: "directive-for-escape.mk" line 99: ${UNDEF:U\backslash$ +For: loop body with i = {{}}: . info ${:U{{\}\}} -make: "directive-for-escape.mk" line 101: {{}} -For: loop body: +make: "directive-for-escape.mk" line 99: {{}} +For: loop body with i = end}: . info ${:Uend\}} -make: "directive-for-escape.mk" line 101: end} +make: "directive-for-escape.mk" line 99: end} For: end for 1 -For: loop body: +For: loop body with i = begin<${UNDEF:Ufallback:N{{{}}}}>end: . info ${:Ubegin<${UNDEF:Ufallback:N{{{}}}}>end} -make: "directive-for-escape.mk" line 122: beginend +make: "directive-for-escape.mk" line 120: beginend For: end for 1 -For: loop body: +For: loop body with i = $: . info ${:U\$} -make: "directive-for-escape.mk" line 131: $ -make: "directive-for-escape.mk" line 140: invalid character ':' in .for loop variable name +make: "directive-for-escape.mk" line 129: $ +make: "directive-for-escape.mk" line 138: invalid character ':' in .for loop variable name For: end for 1 -make: "directive-for-escape.mk" line 150: invalid character '}' in .for loop variable name +make: "directive-for-escape.mk" line 148: invalid character '}' in .for loop variable name For: end for 1 For: end for 1 -For: loop body: +For: loop body with i = inner: . info . $$i: ${:Uinner} . info . $${i}: ${:Uinner} . info . $${i:M*}: ${:Uinner:M*} @@ -65,80 +65,83 @@ For: loop body: . info . $${i2}: ${i2} . info . $${i,}: ${i,} . info . adjacent: ${:Uinner}${:Uinner}${:Uinner:M*}${:Uinner} -make: "directive-for-escape.mk" line 159: . $i: inner -make: "directive-for-escape.mk" line 160: . ${i}: inner -make: "directive-for-escape.mk" line 161: . ${i:M*}: inner -make: "directive-for-escape.mk" line 162: . $(i): inner -make: "directive-for-escape.mk" line 163: . $(i:M*): inner -make: "directive-for-escape.mk" line 164: . ${i${:U}}: outer -make: "directive-for-escape.mk" line 165: . ${i\}}: inner} -make: "directive-for-escape.mk" line 166: . ${i2}: two -make: "directive-for-escape.mk" line 167: . ${i,}: comma -make: "directive-for-escape.mk" line 168: . adjacent: innerinnerinnerinner -make: "directive-for-escape.mk" line 187: invalid character '$' in .for loop variable name +make: "directive-for-escape.mk" line 157: . $i: inner +make: "directive-for-escape.mk" line 158: . ${i}: inner +make: "directive-for-escape.mk" line 159: . ${i:M*}: inner +make: "directive-for-escape.mk" line 160: . $(i): inner +make: "directive-for-escape.mk" line 161: . $(i:M*): inner +make: "directive-for-escape.mk" line 162: . ${i${:U}}: outer +make: "directive-for-escape.mk" line 163: . ${i\}}: inner} +make: "directive-for-escape.mk" line 164: . ${i2}: two +make: "directive-for-escape.mk" line 165: . ${i,}: comma +make: "directive-for-escape.mk" line 166: . adjacent: innerinnerinnerinner +make: "directive-for-escape.mk" line 185: invalid character '$' in .for loop variable name For: end for 1 -make: "directive-for-escape.mk" line 199: eight and no cents. +make: "directive-for-escape.mk" line 197: eight and no cents. For: end for 1 -make: "directive-for-escape.mk" line 212: newline in .for value -make: "directive-for-escape.mk" line 212: newline in .for value -For: loop body: +make: "directive-for-escape.mk" line 210: newline in .for value +make: "directive-for-escape.mk" line 210: newline in .for value +For: loop body with i = " +": . info short: ${:U" "} . info long: ${:U" "} -make: "directive-for-escape.mk" line 213: short: " " -make: "directive-for-escape.mk" line 214: long: " " +make: "directive-for-escape.mk" line 211: short: " " +make: "directive-for-escape.mk" line 212: long: " " For: end for 1 -For: loop body: +For: loop body with i = " +": For: end for 1 -Parse_PushInput: .for loop in directive-for-escape.mk, line 230 -make: "directive-for-escape.mk" line 230: newline in .for value - in .for loop from directive-for-escape.mk:230 with i = " +Parse_PushInput: .for loop in directive-for-escape.mk, line 228 +make: "directive-for-escape.mk" line 228: newline in .for value + in .for loop from directive-for-escape.mk:228 with i = " " -For: loop body: +For: loop body with i = " +": : ${:U" "} SetFilenameVars: ${.PARSEDIR} = ${.PARSEFILE} = `directive-for-escape.mk' -Parsing line 231: : ${:U" "} +Parsing line 229: : ${:U" "} ParseDependency(: " ") -ParseEOF: returning to file directive-for-escape.mk, line 233 +ParseEOF: returning to file directive-for-escape.mk, line 231 SetFilenameVars: ${.PARSEDIR} = ${.PARSEFILE} = `directive-for-escape.mk' -Parsing line 233: .MAKEFLAGS: -d0 +Parsing line 231: .MAKEFLAGS: -d0 ParseDependency(.MAKEFLAGS: -d0) For: end for 1 -For: loop body: +For: loop body with i = #: # ${:U#} -For: loop body: +For: loop body with i = \\#: # ${:U\\\\#} For: end for 1 -For: loop body: +For: loop body with i = $: # ${:U\$} -For: loop body: +For: loop body with i = $i: # ${:U$i} -For: loop body: +For: loop body with i = $(i): # ${:U$(i)} -For: loop body: +For: loop body with i = ${i}: # ${:U${i}} -For: loop body: +For: loop body with i = $$: # ${:U$$} -For: loop body: +For: loop body with i = $$$$: # ${:U$$$$} -For: loop body: +For: loop body with i = ${:U\$\$}: # ${:U${:U\$\$}} For: end for 1 -For: loop body: +For: loop body with i = ${.TARGET}: # ${:U${.TARGET}} -For: loop body: +For: loop body with i = ${.TARGET}: # ${:U${.TARGET}} -For: loop body: +For: loop body with i = $${.TARGET}: # ${:U$${.TARGET\}} -For: loop body: +For: loop body with i = $${.TARGET}: # ${:U$${.TARGET\}} For: end for 1 -For: loop body: +For: loop body with i = (((: # ${:U(((} -For: loop body: +For: loop body with i = {{{: # ${:U{{{} -For: loop body: +For: loop body with i = ))): # ${:U)))} -For: loop body: +For: loop body with i = }}}: # ${:U\}\}\}} make: Fatal errors encountered -- cannot continue make: stopped in unit-tests diff --git a/unit-tests/directive-for-escape.mk b/unit-tests/directive-for-escape.mk index 7fbd09131d2c..aa0d2504f944 100644 --- a/unit-tests/directive-for-escape.mk +++ b/unit-tests/directive-for-escape.mk @@ -1,11 +1,9 @@ -# $NetBSD: directive-for-escape.mk,v 1.18 2023/05/09 19:43:12 rillig Exp $ +# $NetBSD: directive-for-escape.mk,v 1.20 2023/06/01 20:56:35 rillig Exp $ # # Test escaping of special characters in the iteration values of a .for loop. # These values get expanded later using the :U variable modifier, and this # escaping and unescaping must pass all characters and strings unmodified. -# expect-all - .MAKEFLAGS: -df # Even though the .for loops take quotes into account when splitting the @@ -74,11 +72,11 @@ VALUES= $${UNDEF:U\$$\$$ {{}} end} # When these words are injected into the body of the .for loop, each inside a # '${:U...}' expression, the result is: # -# expect: For: loop body: +# expect: For: loop body with i = ${UNDEF:U\$\$: # expect: # ${:U\${UNDEF\:U\\$\\$} -# expect: For: loop body: +# expect: For: loop body with i = {{}}: # expect: # ${:U{{\}\}} -# expect: For: loop body: +# expect: For: loop body with i = end}: # expect: # ${:Uend\}} # expect: For: end for 1 # diff --git a/unit-tests/directive-for-generating-endif.exp b/unit-tests/directive-for-generating-endif.exp index 5f57f89c250f..ecdeb0962202 100755 --- a/unit-tests/directive-for-generating-endif.exp +++ b/unit-tests/directive-for-generating-endif.exp @@ -1,7 +1,7 @@ -make: "directive-for-generating-endif.mk" line 21: if-less endif -make: "directive-for-generating-endif.mk" line 21: if-less endif -make: "directive-for-generating-endif.mk" line 21: if-less endif -make: "directive-for-generating-endif.mk" line 26: 3 open conditionals +make: "directive-for-generating-endif.mk" line 24: if-less endif +make: "directive-for-generating-endif.mk" line 24: if-less endif +make: "directive-for-generating-endif.mk" line 24: if-less endif +make: "directive-for-generating-endif.mk" line 30: 3 open conditionals make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/directive-for-generating-endif.mk b/unit-tests/directive-for-generating-endif.mk index b4d709551003..3079ad3353c2 100755 --- a/unit-tests/directive-for-generating-endif.mk +++ b/unit-tests/directive-for-generating-endif.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-for-generating-endif.mk,v 1.1 2020/08/29 18:50:25 rillig Exp $ +# $NetBSD: directive-for-generating-endif.mk,v 1.2 2023/06/01 20:56:35 rillig Exp $ # # Test whether a .for loop can be used to generate multiple .endif # directives to close nested .if directives. Depending on the exact @@ -18,8 +18,12 @@ . if 2 . if 3 .for i in 3 2 1 +# expect+3: if-less endif +# expect+2: if-less endif +# expect+1: if-less endif .endif .endfor all: @:; +# expect+1: 3 open conditionals diff --git a/unit-tests/directive-for-if.exp b/unit-tests/directive-for-if.exp index 85bfc484856b..f30171f4db87 100644 --- a/unit-tests/directive-for-if.exp +++ b/unit-tests/directive-for-if.exp @@ -1,6 +1,6 @@ -make: "directive-for-if.mk" line 48: if-less endif -make: "directive-for-if.mk" line 48: if-less endif -make: "directive-for-if.mk" line 48: if-less endif +make: "directive-for-if.mk" line 51: if-less endif +make: "directive-for-if.mk" line 51: if-less endif +make: "directive-for-if.mk" line 51: if-less endif VAR1 VAR3 make: Fatal errors encountered -- cannot continue diff --git a/unit-tests/directive-for-if.mk b/unit-tests/directive-for-if.mk index 8d73e8ae8c4d..f2d0b550c693 100644 --- a/unit-tests/directive-for-if.mk +++ b/unit-tests/directive-for-if.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-for-if.mk,v 1.1 2021/08/30 17:08:13 rillig Exp $ +# $NetBSD: directive-for-if.mk,v 1.2 2023/06/01 20:56:35 rillig Exp $ # # Test for a .for directive that contains an .if directive. # @@ -45,6 +45,9 @@ # expanded to their bare textual value. .for directive in if ifdef ifndef . ${directive} "1" != "0" +# expect+3: if-less endif +# expect+2: if-less endif +# expect+1: if-less endif . endif .endfor # In 2021, the above code does not generate an error message, even though the diff --git a/unit-tests/directive-for-lines.exp b/unit-tests/directive-for-lines.exp index 7aeaaa4a7002..857b4829083b 100644 --- a/unit-tests/directive-for-lines.exp +++ b/unit-tests/directive-for-lines.exp @@ -1,9 +1,9 @@ -make: "directive-for-lines.mk" line 23: expect 23 -make: "directive-for-lines.mk" line 23: expect 23 -make: "directive-for-lines.mk" line 30: expect 30 -make: "directive-for-lines.mk" line 23: expect 23 -make: "directive-for-lines.mk" line 23: expect 23 -make: "directive-for-lines.mk" line 30: expect 30 +make: "directive-for-lines.mk" line 27: expect 23 +make: "directive-for-lines.mk" line 27: expect 23 +make: "directive-for-lines.mk" line 36: expect 30 +make: "directive-for-lines.mk" line 27: expect 23 +make: "directive-for-lines.mk" line 27: expect 23 +make: "directive-for-lines.mk" line 36: expect 30 make: no target to make. make: stopped in unit-tests diff --git a/unit-tests/directive-for-lines.mk b/unit-tests/directive-for-lines.mk index 648c6112daff..cae4e0a38897 100644 --- a/unit-tests/directive-for-lines.mk +++ b/unit-tests/directive-for-lines.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-for-lines.mk,v 1.4 2022/05/08 06:51:27 rillig Exp $ +# $NetBSD: directive-for-lines.mk,v 1.5 2023/06/01 20:56:35 rillig Exp $ # # Tests for the line numbers that are reported in .for loops. # @@ -20,6 +20,10 @@ VAR= \ multi-line +# expect+4: expect 23 +# expect+3: expect 23 +# expect+2: expect 23 +# expect+1: expect 23 .info expect 23 .endfor @@ -27,6 +31,8 @@ VAR= \ # comment \ # continued comment +# expect+2: expect 30 +# expect+1: expect 30 .info expect 30 .endfor diff --git a/unit-tests/directive-for.exp b/unit-tests/directive-for.exp index 97878ee49f44..7f37da4ef364 100755 --- a/unit-tests/directive-for.exp +++ b/unit-tests/directive-for.exp @@ -1,41 +1,41 @@ -make: "directive-for.mk" line 119: outer -make: "directive-for.mk" line 137: a:\ a:\file.txt -make: "directive-for.mk" line 137: d:\\ -make: "directive-for.mk" line 137: d:\\file.txt -make: "directive-for.mk" line 148: ( ( ( -make: "directive-for.mk" line 148: [ [ [ -make: "directive-for.mk" line 148: { { { -make: "directive-for.mk" line 148: ) ) ) -make: "directive-for.mk" line 148: ] ] ] -make: "directive-for.mk" line 148: } } } -make: "directive-for.mk" line 148: (()) (()) (()) -make: "directive-for.mk" line 148: [[]] [[]] [[]] -make: "directive-for.mk" line 148: {{}} {{}} {{}} -make: "directive-for.mk" line 148: )( )( )( -make: "directive-for.mk" line 148: ][ ][ ][ -make: "directive-for.mk" line 148: }{ }{ }{ -make: "directive-for.mk" line 168: invalid character ':' in .for loop variable name -make: "directive-for.mk" line 175: invalid character '$' in .for loop variable name -make: "directive-for.mk" line 187: invalid character '$' in .for loop variable name -make: "directive-for.mk" line 198: Unknown modifier "Z" -make: "directive-for.mk" line 199: XXX: Not reached word1 -make: "directive-for.mk" line 199: XXX: Not reached word3 -make: "directive-for.mk" line 206: no iteration variables in for -make: "directive-for.mk" line 232: 1 open conditional -make: "directive-for.mk" line 248: for-less endfor -make: "directive-for.mk" line 249: if-less endif -make: "directive-for.mk" line 257: if-less endif +make: "directive-for.mk" line 117: outer +make: "directive-for.mk" line 135: a:\ a:\file.txt +make: "directive-for.mk" line 135: d:\\ +make: "directive-for.mk" line 135: d:\\file.txt +make: "directive-for.mk" line 146: ( ( ( +make: "directive-for.mk" line 146: [ [ [ +make: "directive-for.mk" line 146: { { { +make: "directive-for.mk" line 146: ) ) ) +make: "directive-for.mk" line 146: ] ] ] +make: "directive-for.mk" line 146: } } } +make: "directive-for.mk" line 146: (()) (()) (()) +make: "directive-for.mk" line 146: [[]] [[]] [[]] +make: "directive-for.mk" line 146: {{}} {{}} {{}} +make: "directive-for.mk" line 146: )( )( )( +make: "directive-for.mk" line 146: ][ ][ ][ +make: "directive-for.mk" line 146: }{ }{ }{ +make: "directive-for.mk" line 166: invalid character ':' in .for loop variable name +make: "directive-for.mk" line 173: invalid character '$' in .for loop variable name +make: "directive-for.mk" line 185: invalid character '$' in .for loop variable name +make: "directive-for.mk" line 196: Unknown modifier "Z" +make: "directive-for.mk" line 197: XXX: Not reached word1 +make: "directive-for.mk" line 197: XXX: Not reached word3 +make: "directive-for.mk" line 204: no iteration variables in for +make: "directive-for.mk" line 230: 1 open conditional +make: "directive-for.mk" line 246: for-less endfor +make: "directive-for.mk" line 247: if-less endif +make: "directive-for.mk" line 255: if-less endif For: new loop 2 For: end for 2 For: end for 1 -For: loop body: +For: loop body with outer = o: .\ for inner in i .\ endfor For: end for 1 -For: loop body: -make: "directive-for.mk" line 305: newline-item=(a) +For: loop body with inner = i: +make: "directive-for.mk" line 303: newline-item=(a) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/directive-for.mk b/unit-tests/directive-for.mk index 224a466a7709..22b9f78e5fe1 100755 --- a/unit-tests/directive-for.mk +++ b/unit-tests/directive-for.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-for.mk,v 1.20 2023/05/10 13:03:06 rillig Exp $ +# $NetBSD: directive-for.mk,v 1.22 2023/06/01 20:56:35 rillig Exp $ # # Tests for the .for directive. # @@ -12,8 +12,6 @@ # See also: # varmod-loop.mk The ':@var@...@' modifier -# expect-all - # A typical use case for a .for loop is to populate a variable with a list of # values depending on other variables. In simple cases, the same effect can # be achieved using the ':@var@${var}@' modifier. @@ -87,9 +85,9 @@ var2= value before . warning After the .for loop, var2 must still have its original value. .endif -# Until 2008-12-21, the values of the iteration variables were simply -# inserted as plain text and then parsed as usual, which made it possible -# to achieve all kinds of strange effects, such as generating '.if' +# Before for.c 1.39 from 2008-12-21, the values of the iteration variables +# were simply inserted as plain text and then parsed as usual, which made it +# possible to achieve all kinds of strange effects, such as generating '.if' # directives or inserting '$' characters in random places, thereby changing # how following '$' are interpreted. # diff --git a/unit-tests/directive-if.exp b/unit-tests/directive-if.exp index 5682df501e9c..34ba63d034dd 100644 --- a/unit-tests/directive-if.exp +++ b/unit-tests/directive-if.exp @@ -1,18 +1,18 @@ -make: "directive-if.mk" line 13: 0 evaluates to false. -make: "directive-if.mk" line 17: 1 evaluates to true. -make: "directive-if.mk" line 41: Unknown directive "ifx" -make: "directive-if.mk" line 43: This is not conditional. -make: "directive-if.mk" line 45: if-less else -make: "directive-if.mk" line 47: This is not conditional. -make: "directive-if.mk" line 49: if-less endif -make: "directive-if.mk" line 53: Malformed conditional () -make: "directive-if.mk" line 63: Quotes in plain words are probably a mistake. -make: "directive-if.mk" line 72: Don't do this, always put a space after a directive. +make: "directive-if.mk" line 14: 0 evaluates to false. +make: "directive-if.mk" line 19: 1 evaluates to true. +make: "directive-if.mk" line 43: Unknown directive "ifx" +make: "directive-if.mk" line 45: This is not conditional. +make: "directive-if.mk" line 47: if-less else +make: "directive-if.mk" line 49: This is not conditional. +make: "directive-if.mk" line 51: if-less endif +make: "directive-if.mk" line 55: Malformed conditional () +make: "directive-if.mk" line 66: Quotes in plain words are probably a mistake. make: "directive-if.mk" line 76: Don't do this, always put a space after a directive. -make: "directive-if.mk" line 82: Don't do this, always put a space around comparison operators. -make: "directive-if.mk" line 88: Don't do this, always put a space after a directive. -make: "directive-if.mk" line 92: Don't do this, always put a space after a directive. -make: "directive-if.mk" line 100: Unknown directive "ifn" +make: "directive-if.mk" line 81: Don't do this, always put a space after a directive. +make: "directive-if.mk" line 88: Don't do this, always put a space around comparison operators. +make: "directive-if.mk" line 95: Don't do this, always put a space after a directive. +make: "directive-if.mk" line 100: Don't do this, always put a space after a directive. +make: "directive-if.mk" line 108: Unknown directive "ifn" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/directive-if.mk b/unit-tests/directive-if.mk index 1acd5c958008..7a68c0041415 100644 --- a/unit-tests/directive-if.mk +++ b/unit-tests/directive-if.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-if.mk,v 1.11 2022/01/23 21:48:59 rillig Exp $ +# $NetBSD: directive-if.mk,v 1.12 2023/06/01 20:56:35 rillig Exp $ # # Tests for the .if directive. # @@ -10,10 +10,12 @@ .if 0 . error .else +# expect+1: 0 evaluates to false. . info 0 evaluates to false. .endif .if 1 +# expect+1: 1 evaluates to true. . info 1 evaluates to true. .else . error @@ -60,6 +62,7 @@ # though, which are kept. The quotes need not be balanced. The next space # ends the word, and the remaining " || 1" is parsed as "or true". .if ${:Uplain"""""} == plain""""" || 1 +# expect+1: Quotes in plain words are probably a mistake. . info Quotes in plain words are probably a mistake. # XXX: Accepting quotes in plain words is probably a mistake as well. .else @@ -69,26 +72,31 @@ .if0 . error .else +# expect+1: Don't do this, always put a space after a directive. . info Don't do this, always put a space after a directive. .endif .if${:U-3} +# expect+1: Don't do this, always put a space after a directive. . info Don't do this, always put a space after a directive. .else . error .endif .if${:U-3}>-4 +# expect+1: Don't do this, always put a space around comparison operators. . info Don't do this, always put a space around comparison operators. .else . error .endif .if(1) +# expect+1: Don't do this, always put a space after a directive. . info Don't do this, always put a space after a directive. .endif .if!0 +# expect+1: Don't do this, always put a space after a directive. . info Don't do this, always put a space after a directive. .endif diff --git a/unit-tests/directive-ifmake.exp b/unit-tests/directive-ifmake.exp index bf4ded97911f..e607726fd87c 100644 --- a/unit-tests/directive-ifmake.exp +++ b/unit-tests/directive-ifmake.exp @@ -1,10 +1,10 @@ -make: "directive-ifmake.mk" line 13: ok: positive condition works -make: "directive-ifmake.mk" line 24: ok: negation works -make: "directive-ifmake.mk" line 33: ok: double negation works -make: "directive-ifmake.mk" line 40: ok: both mentioned -make: "directive-ifmake.mk" line 47: ok: only those mentioned -make: "directive-ifmake.mk" line 57: Targets can even be added at parse time. -make: "directive-ifmake.mk" line 75: ok +make: "directive-ifmake.mk" line 14: ok: positive condition works +make: "directive-ifmake.mk" line 26: ok: negation works +make: "directive-ifmake.mk" line 36: ok: double negation works +make: "directive-ifmake.mk" line 44: ok: both mentioned +make: "directive-ifmake.mk" line 52: ok: only those mentioned +make: "directive-ifmake.mk" line 63: Targets can even be added at parse time. +make: "directive-ifmake.mk" line 82: ok : first : second : late-target diff --git a/unit-tests/directive-ifmake.mk b/unit-tests/directive-ifmake.mk index a1ff3aef6825..2a0cedda463e 100644 --- a/unit-tests/directive-ifmake.mk +++ b/unit-tests/directive-ifmake.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-ifmake.mk,v 1.10 2022/02/09 21:09:24 rillig Exp $ +# $NetBSD: directive-ifmake.mk,v 1.11 2023/06/01 20:56:35 rillig Exp $ # # Tests for the .ifmake directive, which provides a shortcut for asking # whether a certain target is requested to be made from the command line. @@ -10,6 +10,7 @@ # This is the most basic form. .ifmake first +# expect+1: ok: positive condition works . info ok: positive condition works .else . warning positive condition fails @@ -21,6 +22,7 @@ .ifmake !first . warning unexpected .else +# expect+1: ok: negation works . info ok: negation works .endif @@ -30,6 +32,7 @@ # exclamation mark were part of the name instead, the name would be '!!first', # and such a target was not requested to be made. .ifmake !!first +# expect+1: ok: double negation works . info ok: double negation works .else . warning double negation fails @@ -37,6 +40,7 @@ # Multiple targets can be combined using the && and || operators. .ifmake first && second +# expect+1: ok: both mentioned . info ok: both mentioned .else . warning && does not work as expected @@ -44,6 +48,7 @@ # Negation also works in complex conditions. .ifmake first && !unmentioned +# expect+1: ok: only those mentioned . info ok: only those mentioned .else . warning && with ! does not work as expected @@ -54,6 +59,7 @@ # possible to extend the targets to be made. .MAKEFLAGS: late-target .ifmake late-target +# expect+1: Targets can even be added at parse time. . info Targets can even be added at parse time. .else . info No, targets cannot be added at parse time anymore. @@ -72,6 +78,7 @@ # A condition that consists of a variable expression only (without any # comparison operator) can be used with .if and the other .ifxxx directives. .ifmake ${:Ufirst} +# expect+1: ok . info ok .else . error diff --git a/unit-tests/directive-ifndef.exp b/unit-tests/directive-ifndef.exp index c653f6344429..d018e78616bc 100644 --- a/unit-tests/directive-ifndef.exp +++ b/unit-tests/directive-ifndef.exp @@ -1,2 +1,2 @@ -make: "directive-ifndef.mk" line 10: guarded section +make: "directive-ifndef.mk" line 14: guarded section exit status 0 diff --git a/unit-tests/directive-ifndef.mk b/unit-tests/directive-ifndef.mk index bf509ef8075e..95b8df6bcbb8 100644 --- a/unit-tests/directive-ifndef.mk +++ b/unit-tests/directive-ifndef.mk @@ -1,12 +1,16 @@ -# $NetBSD: directive-ifndef.mk,v 1.6 2020/10/24 08:46:08 rillig Exp $ +# $NetBSD: directive-ifndef.mk,v 1.8 2023/06/19 20:44:06 rillig Exp $ # # Tests for the .ifndef directive, which can be used for multiple-inclusion # guards. In contrast to C, where #ifndef and #define nicely line up the # macro name, there is no such syntax in make. Therefore, it is more # common to use .if !defined(GUARD) instead. +# +# See also: +# directive-include-guard.mk .ifndef GUARD GUARD= # defined +# expect+1: guarded section . info guarded section .endif @@ -20,5 +24,30 @@ GUARD= # defined . info guarded section .endif + +# The '.ifndef' directive can be used with multiple arguments, even negating +# them. Since these conditions are confusing for humans, they should be +# replaced with easier-to-understand plain '.if' directives. +DEFINED= +.ifndef UNDEFINED && UNDEFINED +.else +. error +.endif +.ifndef UNDEFINED && DEFINED +. error +.endif +.ifndef DEFINED && DEFINED +. error +.endif +.ifndef !UNDEFINED && !UNDEFINED +. error +.endif +.ifndef !UNDEFINED && !DEFINED +. error +.endif +.ifndef !DEFINED && !DEFINED +.else +. error +.endif + all: - @:; diff --git a/unit-tests/directive-include-fatal.exp b/unit-tests/directive-include-fatal.exp index c8ca97a0fd5f..cae0fc97a59d 100755 --- a/unit-tests/directive-include-fatal.exp +++ b/unit-tests/directive-include-fatal.exp @@ -1,4 +1,4 @@ -make: "directive-include-fatal.mk" line 13: Malformed conditional (${UNDEF}) +make: "directive-include-fatal.mk" line 14: Malformed conditional (${UNDEF}) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/directive-include-fatal.mk b/unit-tests/directive-include-fatal.mk index 6744f9e80e5c..d4ed26f2a4aa 100755 --- a/unit-tests/directive-include-fatal.mk +++ b/unit-tests/directive-include-fatal.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-include-fatal.mk,v 1.3 2021/02/01 22:16:57 rillig Exp $ +# $NetBSD: directive-include-fatal.mk,v 1.4 2023/06/01 20:56:35 rillig Exp $ # # Test for the .include directive combined with fatal errors. # @@ -10,6 +10,7 @@ # the "fatals" counter. # Using an undefined variable in a condition generates a fatal error. +# expect+1: Malformed conditional (${UNDEF}) .if ${UNDEF} .endif diff --git a/unit-tests/directive-include-guard.exp b/unit-tests/directive-include-guard.exp new file mode 100644 index 000000000000..487e67e33e77 --- /dev/null +++ b/unit-tests/directive-include-guard.exp @@ -0,0 +1,88 @@ +Parse_PushInput: file variable-ifndef.tmp, line 1 +Skipping 'variable-ifndef.tmp' because 'VARIABLE_IFNDEF' is defined +Parse_PushInput: file variable-ifndef-reuse.tmp, line 1 +Skipping 'variable-ifndef-reuse.tmp' because 'VARIABLE_IFNDEF' is defined +Parse_PushInput: file comments.tmp, line 1 +Skipping 'comments.tmp' because 'COMMENTS' is defined +Parse_PushInput: file variable-if.tmp, line 1 +Skipping 'variable-if.tmp' because 'VARIABLE_IF' is defined +Parse_PushInput: file variable-if-reuse.tmp, line 1 +Skipping 'variable-if-reuse.tmp' because 'VARIABLE_IF' is defined +Parse_PushInput: file variable-if-triple-negation.tmp, line 1 +Parse_PushInput: file variable-if-triple-negation.tmp, line 1 +Parse_PushInput: file variable-ifdef-negated.tmp, line 1 +Parse_PushInput: file variable-ifdef-negated.tmp, line 1 +Parse_PushInput: file variable-name-mismatch.tmp, line 1 +Parse_PushInput: file variable-name-mismatch.tmp, line 1 +Parse_PushInput: file variable-name-exclamation.tmp, line 1 +Parse_PushInput: file variable-name-exclamation.tmp, line 1 +Parse_PushInput: file variable-name-exclamation-middle.tmp, line 1 +Parse_PushInput: file variable-name-exclamation-middle.tmp, line 1 +Parse_PushInput: file variable-name-parentheses.tmp, line 1 +Parse_PushInput: file variable-name-parentheses.tmp, line 1 +Parse_PushInput: file variable-ifndef-plus.tmp, line 1 +Parse_PushInput: file variable-ifndef-plus.tmp, line 1 +Parse_PushInput: file variable-if-plus.tmp, line 1 +Parse_PushInput: file variable-if-plus.tmp, line 1 +Parse_PushInput: file variable-ifndef-indirect.tmp, line 1 +Parse_PushInput: file variable-ifndef-indirect.tmp, line 1 +Parse_PushInput: file variable-if-indirect.tmp, line 1 +Parse_PushInput: file variable-if-indirect.tmp, line 1 +Parse_PushInput: file variable-assign-indirect.tmp, line 1 +Skipping 'variable-assign-indirect.tmp' because 'VARIABLE_ASSIGN_INDIRECT' is defined +Parse_PushInput: file variable-assign-late.tmp, line 1 +Skipping 'variable-assign-late.tmp' because 'VARIABLE_ASSIGN_LATE' is defined +Parse_PushInput: file variable-assign-nested.tmp, line 1 +Parse_PushInput: .for loop in variable-assign-nested.tmp, line 3 +Skipping 'variable-assign-nested.tmp' because 'VARIABLE_ASSIGN_NESTED' is defined +Parse_PushInput: file variable-already-defined.tmp, line 1 +Skipping 'variable-already-defined.tmp' because 'VARIABLE_ALREADY_DEFINED' is defined +Parse_PushInput: file variable-defined-then-undefined.tmp, line 1 +Parse_PushInput: file variable-defined-then-undefined.tmp, line 1 +Parse_PushInput: file variable-two-times.tmp, line 1 +Parse_PushInput: file variable-two-times.tmp, line 1 +Parse_PushInput: file variable-clash.tmp, line 1 +Skipping 'variable-clash.tmp' because 'VARIABLE_IF' is defined +Parse_PushInput: file variable-swapped.tmp, line 1 +Parse_PushInput: file variable-swapped.tmp, line 1 +Parse_PushInput: file variable-undef-between.tmp, line 1 +Parse_PushInput: file variable-undef-between.tmp, line 1 +Parse_PushInput: file variable-undef-inside.tmp, line 1 +Parse_PushInput: file variable-undef-inside.tmp, line 1 +Parse_PushInput: file variable-not-defined.tmp, line 1 +Parse_PushInput: file variable-not-defined.tmp, line 1 +Parse_PushInput: file if-elif.tmp, line 1 +Parse_PushInput: file if-elif.tmp, line 1 +Parse_PushInput: file if-elif-reuse.tmp, line 1 +Parse_PushInput: file if-elif-reuse.tmp, line 1 +Parse_PushInput: file if-else.tmp, line 1 +Parse_PushInput: file if-else.tmp, line 1 +Parse_PushInput: file if-else-reuse.tmp, line 1 +Parse_PushInput: file if-else-reuse.tmp, line 1 +Parse_PushInput: file inner-if-elif-else.tmp, line 1 +Skipping 'inner-if-elif-else.tmp' because 'INNER_IF_ELIF_ELSE' is defined +Parse_PushInput: file target.tmp, line 1 +Skipping 'target.tmp' because '__target.tmp__' is defined +Parse_PushInput: file target-sys.tmp, line 1 +Skipping 'target-sys.tmp' because '____' is defined +Parse_PushInput: file target-indirect.tmp, line 1 +Skipping 'target-indirect.tmp' because 'target-indirect.tmp' is defined +Parse_PushInput: file target-indirect-PARSEFILE.tmp, line 1 +Skipping 'target-indirect-PARSEFILE.tmp' because '__target-indirect-PARSEFILE.tmp__' is defined +Parse_PushInput: file target-indirect-PARSEFILE2.tmp, line 1 +Skipping 'target-indirect-PARSEFILE2.tmp' because '__target-indirect-PARSEFILE2.tmp__' is defined +Parse_PushInput: file subdir/target-indirect-PARSEFILE.tmp, line 1 +Skipping 'subdir/target-indirect-PARSEFILE.tmp' because '__target-indirect-PARSEFILE.tmp__' is defined +Parse_PushInput: file target-indirect-PARSEDIR-PARSEFILE.tmp, line 1 +Skipping 'target-indirect-PARSEDIR-PARSEFILE.tmp' because '__target-indirect-PARSEDIR-PARSEFILE.tmp__' is defined +Parse_PushInput: file subdir/target-indirect-PARSEDIR-PARSEFILE.tmp, line 1 +Skipping 'subdir/target-indirect-PARSEDIR-PARSEFILE.tmp' because '__subdir/target-indirect-PARSEDIR-PARSEFILE.tmp__' is defined +Parse_PushInput: file target-unguarded.tmp, line 1 +Parse_PushInput: file target-unguarded.tmp, line 1 +Parse_PushInput: file target-plus.tmp, line 1 +Parse_PushInput: file target-plus.tmp, line 1 +Parse_PushInput: file target-already-defined.tmp, line 1 +Skipping 'target-already-defined.tmp' because 'target-already-defined' is defined +Parse_PushInput: file target-name-exclamation.tmp, line 1 +Parse_PushInput: file target-name-exclamation.tmp, line 1 +exit status 0 diff --git a/unit-tests/directive-include-guard.mk b/unit-tests/directive-include-guard.mk new file mode 100644 index 000000000000..1d19a67944e5 --- /dev/null +++ b/unit-tests/directive-include-guard.mk @@ -0,0 +1,552 @@ +# $NetBSD: directive-include-guard.mk,v 1.11 2023/06/21 21:21:52 sjg Exp $ +# +# Tests for multiple-inclusion guards in makefiles. +# +# A file that is guarded by a multiple-inclusion guard has one of the +# following forms: +# +# .ifndef GUARD_VARIABLE +# .endif +# +# .if !defined(GUARD_VARIABLE) +# .endif +# +# .if !target(guard-target) +# .endif +# +# When such a file is included for the second or later time, and the guard +# variable or the guard target is defined, including the file has no effect, +# as all its content is skipped. +# +# See also: +# https://gcc.gnu.org/onlinedocs/cppinternals/Guard-Macros.html + +# Each of the following test cases creates a temporary file named after the +# test case and writes some lines of text to that file. That file is then +# included twice, to see whether the second '.include' is skipped. + + +# This is the canonical form of a variable-based multiple-inclusion guard. +INCS+= variable-ifndef +LINES.variable-ifndef= \ + '.ifndef VARIABLE_IFNDEF' \ + 'VARIABLE_IFNDEF=' \ + '.endif' +# expect: Parse_PushInput: file variable-ifndef.tmp, line 1 +# expect: Skipping 'variable-ifndef.tmp' because 'VARIABLE_IFNDEF' is defined + +# A file that reuses a guard from a previous file (or whose guard is defined +# for any other reason) is only processed once, to see whether it is guarded. +# Its content is skipped, therefore the syntax error is not detected. +INCS+= variable-ifndef-reuse +LINES.variable-ifndef-reuse= \ + '.ifndef VARIABLE_IFNDEF' \ + 'syntax error' \ + '.endif' +# expect: Parse_PushInput: file variable-ifndef-reuse.tmp, line 1 +# expect: Skipping 'variable-ifndef-reuse.tmp' because 'VARIABLE_IFNDEF' is defined + +# Comments and empty lines do not affect the multiple-inclusion guard. +INCS+= comments +LINES.comments= \ + '\# comment' \ + '' \ + '.ifndef COMMENTS' \ + '\# comment' \ + 'COMMENTS=\#comment' \ + '.endif' \ + '\# comment' +# expect: Parse_PushInput: file comments.tmp, line 1 +# expect: Skipping 'comments.tmp' because 'COMMENTS' is defined + +# An alternative form uses the 'defined' function. It is more verbose than +# the canonical form but avoids the '.ifndef' directive, as that directive is +# not commonly used. +INCS+= variable-if +LINES.variable-if= \ + '.if !defined(VARIABLE_IF)' \ + 'VARIABLE_IF=' \ + '.endif' +# expect: Parse_PushInput: file variable-if.tmp, line 1 +# expect: Skipping 'variable-if.tmp' because 'VARIABLE_IF' is defined + +# A file that reuses a guard from a previous file (or whose guard is defined +# for any other reason) is only processed once, to see whether it is guarded. +# Its content is skipped, therefore the syntax error is not detected. +INCS+= variable-if-reuse +LINES.variable-if-reuse= \ + '.if !defined(VARIABLE_IF)' \ + 'syntax error' \ + '.endif' +# expect: Parse_PushInput: file variable-if-reuse.tmp, line 1 +# expect: Skipping 'variable-if-reuse.tmp' because 'VARIABLE_IF' is defined + +# Triple negation is so uncommon that it's not recognized, even though it has +# the same effect as a single negation. +INCS+= variable-if-triple-negation +LINES.variable-if-triple-negation= \ + '.if !!!defined(VARIABLE_IF_TRIPLE_NEGATION)' \ + 'VARIABLE_IF_TRIPLE_NEGATION=' \ + '.endif' +# expect: Parse_PushInput: file variable-if-triple-negation.tmp, line 1 +# expect: Parse_PushInput: file variable-if-triple-negation.tmp, line 1 + +# A conditional other than '.if' or '.ifndef' does not guard the file, even if +# it is otherwise equivalent to the above accepted forms. +INCS+= variable-ifdef-negated +LINES.variable-ifdef-negated= \ + '.ifdef !VARIABLE_IFDEF_NEGATED' \ + 'VARIABLE_IFDEF_NEGATED=' \ + '.endif' +# expect: Parse_PushInput: file variable-ifdef-negated.tmp, line 1 +# expect: Parse_PushInput: file variable-ifdef-negated.tmp, line 1 + +# The variable names in the '.if' and the assignment must be the same. +INCS+= variable-name-mismatch +LINES.variable-name-mismatch= \ + '.ifndef VARIABLE_NAME_MISMATCH' \ + 'VARIABLE_NAME_DIFFERENT=' \ + '.endif' +# expect: Parse_PushInput: file variable-name-mismatch.tmp, line 1 +# expect: Parse_PushInput: file variable-name-mismatch.tmp, line 1 + +# The variable name '!VARNAME' cannot be used in an '.ifndef' directive, as +# the '!' would be a negation. It is syntactically valid in a '.if !defined' +# condition, but ignored there. Furthermore, when defining the variable, the +# character '!' has to be escaped, to prevent it from being interpreted as the +# '!' dependency operator. +INCS+= variable-name-exclamation +LINES.variable-name-exclamation= \ + '.if !defined(!VARIABLE_NAME_EXCLAMATION)' \ + '${:U!}VARIABLE_NAME_EXCLAMATION=' \ + '.endif' +# expect: Parse_PushInput: file variable-name-exclamation.tmp, line 1 +# expect: Parse_PushInput: file variable-name-exclamation.tmp, line 1 + +# A variable name can contain a '!' in the middle, as that character is +# interpreted as an ordinary character in conditions as well as on the left +# side of a variable assignment. For guard variable names, the '!' is not +# supported in any place, though. +INCS+= variable-name-exclamation-middle +LINES.variable-name-exclamation-middle= \ + '.ifndef VARIABLE_NAME!MIDDLE' \ + 'VARIABLE_NAME!MIDDLE=' \ + '.endif' +# expect: Parse_PushInput: file variable-name-exclamation-middle.tmp, line 1 +# expect: Parse_PushInput: file variable-name-exclamation-middle.tmp, line 1 + +# A variable name can contain balanced parentheses, at least in conditions and +# on the left side of a variable assignment. There are enough places in make +# where parentheses or braces are handled inconsistently to make this naming +# choice a bad idea, therefore these characters are not allowed in guard +# variable names. +INCS+= variable-name-parentheses +LINES.variable-name-parentheses= \ + '.ifndef VARIABLE_NAME(&)PARENTHESES' \ + 'VARIABLE_NAME(&)PARENTHESES=' \ + '.endif' +# expect: Parse_PushInput: file variable-name-parentheses.tmp, line 1 +# expect: Parse_PushInput: file variable-name-parentheses.tmp, line 1 + +# The guard condition must consist of only the guard variable, nothing else. +INCS+= variable-ifndef-plus +LINES.variable-ifndef-plus= \ + '.ifndef VARIABLE_IFNDEF_PLUS && VARIABLE_IFNDEF_SECOND' \ + 'VARIABLE_IFNDEF_PLUS=' \ + 'VARIABLE_IFNDEF_SECOND=' \ + '.endif' +# expect: Parse_PushInput: file variable-ifndef-plus.tmp, line 1 +# expect: Parse_PushInput: file variable-ifndef-plus.tmp, line 1 + +# The guard condition must consist of only the guard variable, nothing else. +INCS+= variable-if-plus +LINES.variable-if-plus= \ + '.if !defined(VARIABLE_IF_PLUS) && !defined(VARIABLE_IF_SECOND)' \ + 'VARIABLE_IF_PLUS=' \ + 'VARIABLE_IF_SECOND=' \ + '.endif' +# expect: Parse_PushInput: file variable-if-plus.tmp, line 1 +# expect: Parse_PushInput: file variable-if-plus.tmp, line 1 + +# The variable name in an '.ifndef' guard must be given directly, it must not +# contain any '$' expression. +INCS+= variable-ifndef-indirect +LINES.variable-ifndef-indirect= \ + '.ifndef $${VARIABLE_IFNDEF_INDIRECT:L}' \ + 'VARIABLE_IFNDEF_INDIRECT=' \ + '.endif' +# expect: Parse_PushInput: file variable-ifndef-indirect.tmp, line 1 +# expect: Parse_PushInput: file variable-ifndef-indirect.tmp, line 1 + +# The variable name in an '.if' guard must be given directly, it must not +# contain any '$' expression. +INCS+= variable-if-indirect +LINES.variable-if-indirect= \ + '.if !defined($${VARIABLE_IF_INDIRECT:L})' \ + 'VARIABLE_IF_INDIRECT=' \ + '.endif' +# expect: Parse_PushInput: file variable-if-indirect.tmp, line 1 +# expect: Parse_PushInput: file variable-if-indirect.tmp, line 1 + +# The variable name in the guard condition must only contain alphanumeric +# characters and underscores. The guard variable is more flexible, it can be +# defined anywhere, as long as it is defined at the point where the file is +# included the next time. +INCS+= variable-assign-indirect +LINES.variable-assign-indirect= \ + '.ifndef VARIABLE_ASSIGN_INDIRECT' \ + '$${VARIABLE_ASSIGN_INDIRECT:L}=' \ + '.endif' +# expect: Parse_PushInput: file variable-assign-indirect.tmp, line 1 +# expect: Skipping 'variable-assign-indirect.tmp' because 'VARIABLE_ASSIGN_INDIRECT' is defined + +# The time at which the guard variable is defined doesn't matter, as long as +# it is defined at the point where the file is included the next time. +INCS+= variable-assign-late +LINES.variable-assign-late= \ + '.ifndef VARIABLE_ASSIGN_LATE' \ + 'VARIABLE_ASSIGN_LATE_OTHER=' \ + 'VARIABLE_ASSIGN_LATE=' \ + '.endif' +# expect: Parse_PushInput: file variable-assign-late.tmp, line 1 +# expect: Skipping 'variable-assign-late.tmp' because 'VARIABLE_ASSIGN_LATE' is defined + +# The time at which the guard variable is defined doesn't matter, as long as +# it is defined at the point where the file is included the next time. +INCS+= variable-assign-nested +LINES.variable-assign-nested= \ + '.ifndef VARIABLE_ASSIGN_NESTED' \ + '. if 1' \ + '. for i in once' \ + 'VARIABLE_ASSIGN_NESTED=' \ + '. endfor' \ + '. endif' \ + '.endif' +# expect: Parse_PushInput: file variable-assign-nested.tmp, line 1 +# expect: Skipping 'variable-assign-nested.tmp' because 'VARIABLE_ASSIGN_NESTED' is defined + +# If the guard variable is defined before the file is included for the first +# time, the file is considered guarded as well. In such a case, the parser +# skips almost all lines, as they are irrelevant, but the structure of the +# top-level '.if/.endif' conditional can be determined reliably enough to +# decide whether the file is guarded. +INCS+= variable-already-defined +LINES.variable-already-defined= \ + '.ifndef VARIABLE_ALREADY_DEFINED' \ + 'VARIABLE_ALREADY_DEFINED=' \ + '.endif' +VARIABLE_ALREADY_DEFINED= +# expect: Parse_PushInput: file variable-already-defined.tmp, line 1 +# expect: Skipping 'variable-already-defined.tmp' because 'VARIABLE_ALREADY_DEFINED' is defined + +# If the guard variable is defined before the file is included the first time, +# the file is processed but its content is skipped. If that same guard +# variable is undefined when the file is included the second time, the file is +# processed as usual. +INCS+= variable-defined-then-undefined +LINES.variable-defined-then-undefined= \ + '.ifndef VARIABLE_DEFINED_THEN_UNDEFINED' \ + '.endif' +VARIABLE_DEFINED_THEN_UNDEFINED= +UNDEF_BETWEEN.variable-defined-then-undefined= \ + VARIABLE_DEFINED_THEN_UNDEFINED +# expect: Parse_PushInput: file variable-defined-then-undefined.tmp, line 1 +# expect: Parse_PushInput: file variable-defined-then-undefined.tmp, line 1 + +# The whole file content must be guarded by a single '.if' conditional, not by +# several, even if they have the same effect. This case is not expected to +# occur in practice, as the two parts would rather be split into separate +# files. +INCS+= variable-two-times +LINES.variable-two-times= \ + '.ifndef VARIABLE_TWO_TIMES_1' \ + 'VARIABLE_TWO_TIMES_1=' \ + '.endif' \ + '.ifndef VARIABLE_TWO_TIMES_2' \ + 'VARIABLE_TWO_TIMES_2=' \ + '.endif' +# expect: Parse_PushInput: file variable-two-times.tmp, line 1 +# expect: Parse_PushInput: file variable-two-times.tmp, line 1 + +# When multiple files use the same guard variable name, the optimization of +# skipping the file affects each of these files. +# +# Choosing unique guard names is the responsibility of the makefile authors. +# A typical pattern of guard variable names is '${PROJECT}_${DIR}_${FILE}_MK'. +# System-provided files typically start the guard names with '_'. +INCS+= variable-clash +LINES.variable-clash= \ + ${LINES.variable-if} +# expect: Parse_PushInput: file variable-clash.tmp, line 1 +# expect: Skipping 'variable-clash.tmp' because 'VARIABLE_IF' is defined + +# The conditional must come before the assignment, otherwise the conditional +# is useless, as it always evaluates to false. +INCS+= variable-swapped +LINES.variable-swapped= \ + 'SWAPPED=' \ + '.ifndef SWAPPED' \ + '. error' \ + '.endif' +# expect: Parse_PushInput: file variable-swapped.tmp, line 1 +# expect: Parse_PushInput: file variable-swapped.tmp, line 1 + +# If the guard variable is undefined between the first and the second time the +# file is included, the guarded file is included again. +INCS+= variable-undef-between +LINES.variable-undef-between= \ + '.ifndef VARIABLE_UNDEF_BETWEEN' \ + 'VARIABLE_UNDEF_BETWEEN=' \ + '.endif' +UNDEF_BETWEEN.variable-undef-between= \ + VARIABLE_UNDEF_BETWEEN +# expect: Parse_PushInput: file variable-undef-between.tmp, line 1 +# expect: Parse_PushInput: file variable-undef-between.tmp, line 1 + +# If the guard variable is undefined while the file is included the first +# time, the guard does not have an effect, and the file is included again. +INCS+= variable-undef-inside +LINES.variable-undef-inside= \ + '.ifndef VARIABLE_UNDEF_INSIDE' \ + 'VARIABLE_UNDEF_INSIDE=' \ + '.undef VARIABLE_UNDEF_INSIDE' \ + '.endif' +# expect: Parse_PushInput: file variable-undef-inside.tmp, line 1 +# expect: Parse_PushInput: file variable-undef-inside.tmp, line 1 + +# If the file does not define the guard variable, the guard does not have an +# effect, and the file is included again. +INCS+= variable-not-defined +LINES.variable-not-defined= \ + '.ifndef VARIABLE_NOT_DEFINED' \ + '.endif' +# expect: Parse_PushInput: file variable-not-defined.tmp, line 1 +# expect: Parse_PushInput: file variable-not-defined.tmp, line 1 + +# The outermost '.if' must not have an '.elif' branch. +INCS+= if-elif +LINES.if-elif= \ + '.ifndef IF_ELIF' \ + 'IF_ELIF=' \ + '.elif 1' \ + '.endif' +# expect: Parse_PushInput: file if-elif.tmp, line 1 +# expect: Parse_PushInput: file if-elif.tmp, line 1 + +# When a file with an '.if/.elif/.endif' conditional at the top level is +# included, it is never optimized, as one of its branches is taken. +INCS+= if-elif-reuse +LINES.if-elif-reuse= \ + '.ifndef IF_ELIF' \ + 'syntax error' \ + '.elif 1' \ + '.endif' +# expect: Parse_PushInput: file if-elif-reuse.tmp, line 1 +# expect: Parse_PushInput: file if-elif-reuse.tmp, line 1 + +# The outermost '.if' must not have an '.else' branch. +INCS+= if-else +LINES.if-else= \ + '.ifndef IF_ELSE' \ + 'IF_ELSE=' \ + '.else' \ + '.endif' +# expect: Parse_PushInput: file if-else.tmp, line 1 +# expect: Parse_PushInput: file if-else.tmp, line 1 + +# When a file with an '.if/.else/.endif' conditional at the top level is +# included, it is never optimized, as one of its branches is taken. +INCS+= if-else-reuse +LINES.if-else-reuse= \ + '.ifndef IF_ELSE' \ + 'syntax error' \ + '.else' \ + '.endif' +# expect: Parse_PushInput: file if-else-reuse.tmp, line 1 +# expect: Parse_PushInput: file if-else-reuse.tmp, line 1 + +# The inner '.if' directives may have an '.elif' or '.else', and it doesn't +# matter which of their branches are taken. +INCS+= inner-if-elif-else +LINES.inner-if-elif-else= \ + '.ifndef INNER_IF_ELIF_ELSE' \ + 'INNER_IF_ELIF_ELSE=' \ + '. if 0' \ + '. elif 0' \ + '. else' \ + '. endif' \ + '. if 0' \ + '. elif 1' \ + '. else' \ + '. endif' \ + '. if 1' \ + '. elif 1' \ + '. else' \ + '. endif' \ + '.endif' +# expect: Parse_PushInput: file inner-if-elif-else.tmp, line 1 +# expect: Skipping 'inner-if-elif-else.tmp' because 'INNER_IF_ELIF_ELSE' is defined + +# The guard can also be a target instead of a variable. Using a target as a +# guard has the benefit that a target cannot be undefined once it is defined. +# The target should be declared '.NOTMAIN'. Since the target names are +# usually chosen according to a pattern that doesn't interfere with real +# target names, they don't need to be declared '.PHONY' as they don't generate +# filesystem operations. +INCS+= target +LINES.target= \ + '.if !target(__target.tmp__)' \ + '__target.tmp__: .NOTMAIN' \ + '.endif' +# expect: Parse_PushInput: file target.tmp, line 1 +# expect: Skipping 'target.tmp' because '__target.tmp__' is defined + +# When used for system files, the target name may include '<' and '>', for +# symmetry with the '.include ' directive. The characters '<' and '>' +# are ordinary characters. +INCS+= target-sys +LINES.target-sys= \ + '.if !target(____)' \ + '____: .NOTMAIN' \ + '.endif' +# expect: Parse_PushInput: file target-sys.tmp, line 1 +# expect: Skipping 'target-sys.tmp' because '____' is defined + +# The target name may include variable references. These references are +# expanded as usual. Due to the current implementation, the expressions are +# evaluated twice: Once for checking whether the condition evaluates to true, +# and once for determining the guard name. This double evaluation should not +# matter in practice, as guard expressions are expected to be simple, +# deterministic and without side effects. +INCS+= target-indirect +LINES.target-indirect= \ + '.if !target($${target-indirect.tmp:L})' \ + 'target-indirect.tmp: .NOTMAIN' \ + '.endif' +# expect: Parse_PushInput: file target-indirect.tmp, line 1 +# expect: Skipping 'target-indirect.tmp' because 'target-indirect.tmp' is defined + +# A common form of guard target is __${.PARSEFILE}__. This form can only be +# used if all files using this form have unique basenames. To get a robust +# pattern based on the same idea, use __${.PARSEDIR}/${.PARSEFILE}__ instead. +# This form does not work when the basename contains whitespace characters, as +# it is not possible to define a target with whitespace, not even by cheating. +INCS+= target-indirect-PARSEFILE +LINES.target-indirect-PARSEFILE= \ + '.if !target(__$${.PARSEFILE}__)' \ + '__$${.PARSEFILE}__: .NOTMAIN' \ + '.endif' +# expect: Parse_PushInput: file target-indirect-PARSEFILE.tmp, line 1 +# expect: Skipping 'target-indirect-PARSEFILE.tmp' because '__target-indirect-PARSEFILE.tmp__' is defined + +# Two files with different basenames can both use the same syntactic pattern +# for the target guard name, as the expressions expand to different strings. +INCS+= target-indirect-PARSEFILE2 +LINES.target-indirect-PARSEFILE2= \ + '.if !target(__$${.PARSEFILE}__)' \ + '__$${.PARSEFILE}__: .NOTMAIN' \ + '.endif' +# expect: Parse_PushInput: file target-indirect-PARSEFILE2.tmp, line 1 +# expect: Skipping 'target-indirect-PARSEFILE2.tmp' because '__target-indirect-PARSEFILE2.tmp__' is defined + +# Using plain .PARSEFILE without .PARSEDIR leads to name clashes. The include +# guard is the same as in the test case 'target-indirect-PARSEFILE', as the +# guard name only contains the basename but not the directory name. +INCS+= subdir/target-indirect-PARSEFILE +LINES.subdir/target-indirect-PARSEFILE= \ + '.if !target(__$${.PARSEFILE}__)' \ + '__$${.PARSEFILE}__: .NOTMAIN' \ + '.endif' +# expect: Parse_PushInput: file subdir/target-indirect-PARSEFILE.tmp, line 1 +# expect: Skipping 'subdir/target-indirect-PARSEFILE.tmp' because '__target-indirect-PARSEFILE.tmp__' is defined + +# Another common form of guard target is __${.PARSEDIR}/${.PARSEFILE}__ +# or __${.PARSEDIR:tA}/${.PARSEFILE}__ to be truely unique. +INCS+= target-indirect-PARSEDIR-PARSEFILE +LINES.target-indirect-PARSEDIR-PARSEFILE= \ + '.if !target(__$${.PARSEDIR}/$${.PARSEFILE}__)' \ + '__$${.PARSEDIR}/$${.PARSEFILE}__: .NOTMAIN' \ + '.endif' +# expect: Parse_PushInput: file target-indirect-PARSEDIR-PARSEFILE.tmp, line 1 +# expect: Skipping 'target-indirect-PARSEDIR-PARSEFILE.tmp' because '__target-indirect-PARSEDIR-PARSEFILE.tmp__' is defined +# The actual target starts with '__${.OBJDIR}/', see the .rawout file, but the +# string '${.OBJDIR}/' gets stripped in post processing. + +# Using the combination of '.PARSEDIR' and '.PARSEFILE', a file in a +# subdirectory gets a different guard target name than the previous one. +INCS+= subdir/target-indirect-PARSEDIR-PARSEFILE +LINES.subdir/target-indirect-PARSEDIR-PARSEFILE= \ + '.if !target(__$${.PARSEDIR}/$${.PARSEFILE}__)' \ + '__$${.PARSEDIR}/$${.PARSEFILE}__: .NOTMAIN' \ + '.endif' +# expect: Parse_PushInput: file subdir/target-indirect-PARSEDIR-PARSEFILE.tmp, line 1 +# expect: Skipping 'subdir/target-indirect-PARSEDIR-PARSEFILE.tmp' because '__subdir/target-indirect-PARSEDIR-PARSEFILE.tmp__' is defined +# The actual target starts with '__${.OBJDIR}/', see the .rawout file, but the +# string '${.OBJDIR}/' gets stripped in post processing. + +# If the guard target is not defined when including the file the next time, +# the file is processed again. +INCS+= target-unguarded +LINES.target-unguarded= \ + '.if !target(target-unguarded)' \ + '.endif' +# expect: Parse_PushInput: file target-unguarded.tmp, line 1 +# expect: Parse_PushInput: file target-unguarded.tmp, line 1 + +# The guard condition must consist of only the guard target, nothing else. +INCS+= target-plus +LINES.target-plus= \ + '.if !target(target-plus) && 1' \ + 'target-plus: .NOTMAIN' \ + '.endif' +# expect: Parse_PushInput: file target-plus.tmp, line 1 +# expect: Parse_PushInput: file target-plus.tmp, line 1 + +# If the guard target is defined before the file is included the first time, +# the file is not considered guarded. +INCS+= target-already-defined +LINES.target-already-defined= \ + '.if !target(target-already-defined)' \ + 'target-already-defined: .NOTMAIN' \ + '.endif' +target-already-defined: .NOTMAIN +# expect: Parse_PushInput: file target-already-defined.tmp, line 1 +# expect: Skipping 'target-already-defined.tmp' because 'target-already-defined' is defined + +# A target name cannot contain the character '!'. In the condition, the '!' +# is syntactically valid, but in the dependency declaration line, the '!' is +# interpreted as the '!' dependency operator, no matter whether it occurs at +# the beginning or in the middle of a target name. Escaping it as '${:U!}' +# doesn't work, as the whole line is first expanded and then scanned for the +# dependency operator. Escaping it as '\!' doesn't work either, even though +# the '\' escapes the '!' from being a dependency operator, but when reading +# the target name, the '\' is kept, resulting in the target name +# '\!target-name-exclamation' instead of '!target-name-exclamation'. +INCS+= target-name-exclamation +LINES.target-name-exclamation= \ + '.if !target(!target-name-exclamation)' \ + '\!target-name-exclamation: .NOTMAIN' \ + '.endif' +# expect: Parse_PushInput: file target-name-exclamation.tmp, line 1 +# expect: Parse_PushInput: file target-name-exclamation.tmp, line 1 + +# Now run all test cases by including each of the files twice and looking at +# the debug output. The files that properly guard against multiple inclusion +# generate a 'Skipping' line, the others repeat the 'Parse_PushInput' line. +# +# Some debug output lines are suppressed in the .exp file, see ./Makefile. +.for i in ${INCS} +. for fname in $i.tmp +_:= ${fname:H:N.:@dir@${:!mkdir -p ${dir}!}@} +_!= printf '%s\n' ${LINES.$i} > ${fname} +.MAKEFLAGS: -dp +.include "${.CURDIR}/${fname}" +.undef ${UNDEF_BETWEEN.$i:U} +.include "${.CURDIR}/${fname}" +.MAKEFLAGS: -d0 +_!= rm ${fname} +_:= ${fname:H:N.:@dir@${:!rmdir ${dir}!}@} +. endfor +.endfor + +all: diff --git a/unit-tests/directive-include.exp b/unit-tests/directive-include.exp index 0ddf40a75d2d..161f1750f7a7 100755 --- a/unit-tests/directive-include.exp +++ b/unit-tests/directive-include.exp @@ -2,12 +2,12 @@ CondParser_Eval: ${.MAKE.MAKEFILES:T} != "${.PARSEFILE} null" Comparing "directive-include.mk null" != "directive-include.mk null" CondParser_Eval: ${.MAKE.MAKEFILES:T} != "${.PARSEFILE} null" Comparing "directive-include.mk null" != "directive-include.mk null" -make: "directive-include.mk" line 25: Could not find nonexistent.mk -make: "directive-include.mk" line 47: Could not find " -make: "directive-include.mk" line 52: Unknown modifier "Z" -make: "directive-include.mk" line 52: Could not find nonexistent.mk -make: "directive-include.mk" line 57: Cannot open /nonexistent -make: "directive-include.mk" line 62: Invalid line type +make: "directive-include.mk" line 26: Could not find nonexistent.mk +make: "directive-include.mk" line 49: Could not find " +make: "directive-include.mk" line 56: Unknown modifier "Z" +make: "directive-include.mk" line 56: Could not find nonexistent.mk +make: "directive-include.mk" line 61: Cannot open /nonexistent +make: "directive-include.mk" line 66: Invalid line type make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/directive-include.mk b/unit-tests/directive-include.mk index edf27d02483e..404730a0cb6b 100755 --- a/unit-tests/directive-include.mk +++ b/unit-tests/directive-include.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-include.mk,v 1.11 2022/01/15 12:35:18 rillig Exp $ +# $NetBSD: directive-include.mk,v 1.12 2023/06/01 20:56:35 rillig Exp $ # # Tests for the .include directive, which includes another file. @@ -22,6 +22,7 @@ . error .endif +# expect+1: Could not find nonexistent.mk .include "nonexistent.mk" .include "/dev/null" # size 0 # including a directory technically succeeds, but shouldn't. @@ -44,11 +45,14 @@ DEV= null # would be empty, and the closing '"' would be in the trailing part of the # line, which is ignored as of 2021-12-03. DQUOT= " +# expect+1: Could not find " .include "${DQUOT}" # When the expression in a filename cannot be evaluated, the failing # expression is skipped and the file is included nevertheless. # FIXME: Add proper error handling, no file must be included here. +# expect+2: Could not find nonexistent.mk +# expect+1: Unknown modifier "Z" .include "nonexistent${:U123:Z}.mk" # The traditional include directive is seldom used. diff --git a/unit-tests/directive-info.exp b/unit-tests/directive-info.exp index 70def02441d1..397d9d31ef38 100644 --- a/unit-tests/directive-info.exp +++ b/unit-tests/directive-info.exp @@ -1,15 +1,15 @@ -make: "directive-info.mk" line 11: begin .info tests -make: "directive-info.mk" line 12: Unknown directive "inf" -make: "directive-info.mk" line 13: Missing argument for ".info" -make: "directive-info.mk" line 14: message -make: "directive-info.mk" line 15: indented message -make: "directive-info.mk" line 16: Unknown directive "information" -make: "directive-info.mk" line 17: Unknown directive "information" -make: "directive-info.mk" line 22: Missing argument for ".info" -make: "directive-info.mk" line 23: Missing argument for ".info" -make: "directive-info.mk" line 26: Unknown directive "info-message" -make: "directive-info.mk" line 27: no-target: no-source -make: "directive-info.mk" line 35: expect line 35 for multi-line message +make: "directive-info.mk" line 12: begin .info tests +make: "directive-info.mk" line 14: Unknown directive "inf" +make: "directive-info.mk" line 16: Missing argument for ".info" +make: "directive-info.mk" line 18: message +make: "directive-info.mk" line 20: indented message +make: "directive-info.mk" line 22: Unknown directive "information" +make: "directive-info.mk" line 24: Unknown directive "information" +make: "directive-info.mk" line 30: Missing argument for ".info" +make: "directive-info.mk" line 32: Missing argument for ".info" +make: "directive-info.mk" line 36: Unknown directive "info-message" +make: "directive-info.mk" line 38: no-target: no-source +make: "directive-info.mk" line 47: expect line 35 for multi-line message make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/directive-info.mk b/unit-tests/directive-info.mk index 327ff63e7f9b..ab550555d44f 100644 --- a/unit-tests/directive-info.mk +++ b/unit-tests/directive-info.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-info.mk,v 1.10 2022/05/08 06:51:27 rillig Exp $ +# $NetBSD: directive-info.mk,v 1.11 2023/06/01 20:56:35 rillig Exp $ # # Tests for the .info directive. # @@ -8,22 +8,33 @@ # TODO: Implementation +# expect+1: begin .info tests .info begin .info tests +# expect+1: Unknown directive "inf" .inf # misspelled -.info # "Missing argument" +# expect+1: Missing argument for ".info" +.info +# expect+1: message .info message +# expect+1: indented message .info indented message +# expect+1: Unknown directive "information" .information +# expect+1: Unknown directive "information" .information message # Accepted before 2020-12-13 01:07:54. .info.man: # not a message, but possibly a suffix rule # Even if lines would have trailing whitespace, this would be trimmed by # ParseRawLine. +# expect+1: Missing argument for ".info" .info +# expect+1: Missing argument for ".info" .info # comment .info: message # This is a dependency declaration. +# expect+1: Unknown directive "info-message" .info-message # This is an unknown directive. +# expect+1: no-target: no-source .info no-target: no-source # This is a .info directive, not a dependency. # See directive.mk for more tests of this kind. @@ -32,9 +43,7 @@ # number of completely read lines. For the following multi-line directive, # this meant that the reported line number was the one of the last line, not # of the first line. +# expect+1: expect line 35 for multi-line message .info expect line 35 for\ multi$\ -line message - -all: - @:; diff --git a/unit-tests/directive-misspellings.exp b/unit-tests/directive-misspellings.exp index e51d8473b305..a00615926740 100644 --- a/unit-tests/directive-misspellings.exp +++ b/unit-tests/directive-misspellings.exp @@ -1,45 +1,45 @@ -make: "directive-misspellings.mk" line 12: Unknown directive "dinclud" -make: "directive-misspellings.mk" line 14: Unknown directive "dincludx" -make: "directive-misspellings.mk" line 15: .include filename must be delimited by '"' or '<' -make: "directive-misspellings.mk" line 17: Unknown directive "erro" -make: "directive-misspellings.mk" line 18: Unknown directive "errox" -make: "directive-misspellings.mk" line 22: Unknown directive "expor" -make: "directive-misspellings.mk" line 24: Unknown directive "exporx" -make: "directive-misspellings.mk" line 25: Unknown directive "exports" -make: "directive-misspellings.mk" line 27: Unknown directive "export-en" -make: "directive-misspellings.mk" line 30: Unknown directive "export-environment" -make: "directive-misspellings.mk" line 32: Unknown directive "export-litera" -make: "directive-misspellings.mk" line 34: Unknown directive "export-literax" -make: "directive-misspellings.mk" line 35: Unknown directive "export-literally" -make: "directive-misspellings.mk" line 37: Unknown directive "-includ" -make: "directive-misspellings.mk" line 39: Unknown directive "-includx" -make: "directive-misspellings.mk" line 40: .include filename must be delimited by '"' or '<' -make: "directive-misspellings.mk" line 42: Unknown directive "includ" -make: "directive-misspellings.mk" line 43: Could not find file -make: "directive-misspellings.mk" line 44: Unknown directive "includx" -make: "directive-misspellings.mk" line 45: .include filename must be delimited by '"' or '<' -make: "directive-misspellings.mk" line 47: Unknown directive "inf" -make: "directive-misspellings.mk" line 48: msg -make: "directive-misspellings.mk" line 49: Unknown directive "infx" -make: "directive-misspellings.mk" line 50: Unknown directive "infos" -make: "directive-misspellings.mk" line 52: Unknown directive "sinclud" -make: "directive-misspellings.mk" line 54: Unknown directive "sincludx" -make: "directive-misspellings.mk" line 55: .include filename must be delimited by '"' or '<' -make: "directive-misspellings.mk" line 57: Unknown directive "unde" -make: "directive-misspellings.mk" line 59: Unknown directive "undex" -make: "directive-misspellings.mk" line 60: Unknown directive "undefs" -make: "directive-misspellings.mk" line 62: Unknown directive "unexpor" -make: "directive-misspellings.mk" line 64: Unknown directive "unexporx" -make: "directive-misspellings.mk" line 65: Unknown directive "unexports" -make: "directive-misspellings.mk" line 67: Unknown directive "unexport-en" -make: "directive-misspellings.mk" line 69: The directive .unexport-env does not take arguments -make: "directive-misspellings.mk" line 70: Unknown directive "unexport-enx" -make: "directive-misspellings.mk" line 71: Unknown directive "unexport-envs" -make: "directive-misspellings.mk" line 73: Unknown directive "warn" -make: "directive-misspellings.mk" line 74: Unknown directive "warnin" -make: "directive-misspellings.mk" line 75: warning: msg -make: "directive-misspellings.mk" line 76: Unknown directive "warninx" -make: "directive-misspellings.mk" line 77: Unknown directive "warnings" +make: "directive-misspellings.mk" line 13: Unknown directive "dinclud" +make: "directive-misspellings.mk" line 16: Unknown directive "dincludx" +make: "directive-misspellings.mk" line 18: .include filename must be delimited by '"' or '<' +make: "directive-misspellings.mk" line 21: Unknown directive "erro" +make: "directive-misspellings.mk" line 23: Unknown directive "errox" +make: "directive-misspellings.mk" line 28: Unknown directive "expor" +make: "directive-misspellings.mk" line 31: Unknown directive "exporx" +make: "directive-misspellings.mk" line 33: Unknown directive "exports" +make: "directive-misspellings.mk" line 36: Unknown directive "export-en" +make: "directive-misspellings.mk" line 40: Unknown directive "export-environment" +make: "directive-misspellings.mk" line 43: Unknown directive "export-litera" +make: "directive-misspellings.mk" line 46: Unknown directive "export-literax" +make: "directive-misspellings.mk" line 48: Unknown directive "export-literally" +make: "directive-misspellings.mk" line 51: Unknown directive "-includ" +make: "directive-misspellings.mk" line 54: Unknown directive "-includx" +make: "directive-misspellings.mk" line 56: .include filename must be delimited by '"' or '<' +make: "directive-misspellings.mk" line 59: Unknown directive "includ" +make: "directive-misspellings.mk" line 61: Could not find file +make: "directive-misspellings.mk" line 63: Unknown directive "includx" +make: "directive-misspellings.mk" line 65: .include filename must be delimited by '"' or '<' +make: "directive-misspellings.mk" line 68: Unknown directive "inf" +make: "directive-misspellings.mk" line 70: msg +make: "directive-misspellings.mk" line 72: Unknown directive "infx" +make: "directive-misspellings.mk" line 74: Unknown directive "infos" +make: "directive-misspellings.mk" line 77: Unknown directive "sinclud" +make: "directive-misspellings.mk" line 80: Unknown directive "sincludx" +make: "directive-misspellings.mk" line 82: .include filename must be delimited by '"' or '<' +make: "directive-misspellings.mk" line 85: Unknown directive "unde" +make: "directive-misspellings.mk" line 88: Unknown directive "undex" +make: "directive-misspellings.mk" line 90: Unknown directive "undefs" +make: "directive-misspellings.mk" line 93: Unknown directive "unexpor" +make: "directive-misspellings.mk" line 96: Unknown directive "unexporx" +make: "directive-misspellings.mk" line 98: Unknown directive "unexports" +make: "directive-misspellings.mk" line 101: Unknown directive "unexport-en" +make: "directive-misspellings.mk" line 104: The directive .unexport-env does not take arguments +make: "directive-misspellings.mk" line 106: Unknown directive "unexport-enx" +make: "directive-misspellings.mk" line 108: Unknown directive "unexport-envs" +make: "directive-misspellings.mk" line 111: Unknown directive "warn" +make: "directive-misspellings.mk" line 113: Unknown directive "warnin" +make: "directive-misspellings.mk" line 115: warning: msg +make: "directive-misspellings.mk" line 117: Unknown directive "warninx" +make: "directive-misspellings.mk" line 119: Unknown directive "warnings" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/directive-misspellings.mk b/unit-tests/directive-misspellings.mk index 5f479f03b7f1..0014076d041f 100644 --- a/unit-tests/directive-misspellings.mk +++ b/unit-tests/directive-misspellings.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-misspellings.mk,v 1.3 2020/12/13 01:10:22 rillig Exp $ +# $NetBSD: directive-misspellings.mk,v 1.4 2023/06/01 20:56:35 rillig Exp $ # # Tests for misspelled directives. # @@ -9,71 +9,111 @@ # ".information" were aliases to ".info" since the code for these diagnostic # directives just skipped any letters following the "error", "warn" or "info". +# expect+1: Unknown directive "dinclud" .dinclud "file" .dinclude "file" +# expect+1: Unknown directive "dincludx" .dincludx "file" +# expect+1: .include filename must be delimited by '"' or '<' .dincludes "file" # XXX: the 's' is not meant to be a filename +# expect+1: Unknown directive "erro" .erro msg +# expect+1: Unknown directive "errox" .errox msg # no .error since that would exit immediately # no .errors since that would exit immediately, even with the typo +# expect+1: Unknown directive "expor" .expor varname .export varname +# expect+1: Unknown directive "exporx" .exporx varname +# expect+1: Unknown directive "exports" .exports varname # Accepted before 2020-12-13 01:07:54. +# expect+1: Unknown directive "export-en" .export-en # Accepted before 2020-12-13 01:07:54. .export-env .export-env extra argument # XXX: undetected extra argument +# expect+1: Unknown directive "export-environment" .export-environment # Accepted before 2020-12-13 01:07:54. +# expect+1: Unknown directive "export-litera" .export-litera varname # Accepted before 2020-12-13 01:07:54. .export-literal varname +# expect+1: Unknown directive "export-literax" .export-literax varname # Accepted before 2020-12-13 01:07:54. +# expect+1: Unknown directive "export-literally" .export-literally varname # Accepted before 2020-12-13 01:07:54. +# expect+1: Unknown directive "-includ" .-includ "file" .-include "file" +# expect+1: Unknown directive "-includx" .-includx "file" +# expect+1: .include filename must be delimited by '"' or '<' .-includes "file" # XXX: the 's' is not meant to be a filename +# expect+1: Unknown directive "includ" .includ "file" +# expect+1: Could not find file .include "file" +# expect+1: Unknown directive "includx" .includx "file" +# expect+1: .include filename must be delimited by '"' or '<' .includex "file" # XXX: the 's' is not meant to be a filename +# expect+1: Unknown directive "inf" .inf msg +# expect+1: msg .info msg +# expect+1: Unknown directive "infx" .infx msg +# expect+1: Unknown directive "infos" .infos msg # Accepted before 2020-12-13 01:07:54. +# expect+1: Unknown directive "sinclud" .sinclud "file" .sinclude "file" +# expect+1: Unknown directive "sincludx" .sincludx "file" +# expect+1: .include filename must be delimited by '"' or '<' .sincludes "file" # XXX: the 's' is not meant to be a filename +# expect+1: Unknown directive "unde" .unde varname .undef varname +# expect+1: Unknown directive "undex" .undex varname +# expect+1: Unknown directive "undefs" .undefs varname # Accepted before 2020-12-13 01:07:54. +# expect+1: Unknown directive "unexpor" .unexpor varname .unexport varname +# expect+1: Unknown directive "unexporx" .unexporx varname +# expect+1: Unknown directive "unexports" .unexports varname # Accepted before 2020-12-12 18:00:18. +# expect+1: Unknown directive "unexport-en" .unexport-en # Accepted before 2020-12-12 18:11:42. .unexport-env +# expect+1: The directive .unexport-env does not take arguments .unexport-env extra argument # Accepted before 2020-12-12 18:00:18. +# expect+1: Unknown directive "unexport-enx" .unexport-enx # Accepted before 2020-12-12 18:00:18. +# expect+1: Unknown directive "unexport-envs" .unexport-envs # Accepted before 2020-12-12 18:00:18. +# expect+1: Unknown directive "warn" .warn msg +# expect+1: Unknown directive "warnin" .warnin msg +# expect+1: warning: msg .warning msg +# expect+1: Unknown directive "warninx" .warninx msg +# expect+1: Unknown directive "warnings" .warnings msg # Accepted before 2020-12-13 01:07:54. - -all: diff --git a/unit-tests/directive-undef.exp b/unit-tests/directive-undef.exp index 20df58a8dc73..f3957a990e18 100644 --- a/unit-tests/directive-undef.exp +++ b/unit-tests/directive-undef.exp @@ -1,6 +1,6 @@ -make: "directive-undef.mk" line 29: The .undef directive requires an argument -make: "directive-undef.mk" line 86: Unknown modifier "Z" -make: "directive-undef.mk" line 102: warning: UT_EXPORTED is still listed in .MAKE.EXPORTED even though spaceit is not exported anymore. +make: "directive-undef.mk" line 30: The .undef directive requires an argument +make: "directive-undef.mk" line 88: Unknown modifier "Z" +make: "directive-undef.mk" line 105: warning: UT_EXPORTED is still listed in .MAKE.EXPORTED even though spaceit is not exported anymore. make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/directive-undef.mk b/unit-tests/directive-undef.mk index 5ac7d939c71e..ef047fefe177 100644 --- a/unit-tests/directive-undef.mk +++ b/unit-tests/directive-undef.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-undef.mk,v 1.12 2022/03/26 12:44:57 rillig Exp $ +# $NetBSD: directive-undef.mk,v 1.13 2023/06/01 20:56:35 rillig Exp $ # # Tests for the .undef directive. # @@ -26,6 +26,7 @@ # to delete the variable with the empty name, which never exists; see # varname-empty.mk. Since var.c 1.737 from 2020-12-19, .undef complains # about a missing argument. +# expect+1: The .undef directive requires an argument .undef @@ -83,6 +84,7 @@ ${DOLLAR}= dollar # # As of var.c 1.762, this doesn't happen though because the error handling # in Var_Parse and Var_Subst is not done properly. +# expect+1: Unknown modifier "Z" .undef ${VARNAMES:L:Z} @@ -99,6 +101,7 @@ UT_EXPORTED= exported-value . error .endif .if ${.MAKE.EXPORTED:MUT_EXPORTED} +# expect+1: warning: UT_EXPORTED is still listed in .MAKE.EXPORTED even though spaceit is not exported anymore. . warning UT_EXPORTED is still listed in .MAKE.EXPORTED even though $\ it is not exported anymore. .endif diff --git a/unit-tests/directive-unexport-env.exp b/unit-tests/directive-unexport-env.exp index 22528c31c3a1..663034cee12c 100644 --- a/unit-tests/directive-unexport-env.exp +++ b/unit-tests/directive-unexport-env.exp @@ -1,9 +1,9 @@ -make: "directive-unexport-env.mk" line 13: Unknown directive "unexport-en" -make: "directive-unexport-env.mk" line 15: Unknown directive "unexport-environment" +make: "directive-unexport-env.mk" line 14: Unknown directive "unexport-en" +make: "directive-unexport-env.mk" line 17: Unknown directive "unexport-environment" Global: UT_EXPORTED = value Global: UT_UNEXPORTED = value Global: .MAKE.EXPORTED = UT_EXPORTED -make: "directive-unexport-env.mk" line 21: The directive .unexport-env does not take arguments +make: "directive-unexport-env.mk" line 24: The directive .unexport-env does not take arguments Var_Parse: ${.MAKE.EXPORTED:O:u} (eval) Evaluating modifier ${.MAKE.EXPORTED:O} on value "UT_EXPORTED" Result of ${.MAKE.EXPORTED:O} is "UT_EXPORTED" diff --git a/unit-tests/directive-unexport-env.mk b/unit-tests/directive-unexport-env.mk index e9620684dfcb..e56e47865011 100644 --- a/unit-tests/directive-unexport-env.mk +++ b/unit-tests/directive-unexport-env.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-unexport-env.mk,v 1.8 2022/01/23 16:09:38 rillig Exp $ +# $NetBSD: directive-unexport-env.mk,v 1.9 2023/06/01 20:56:35 rillig Exp $ # # Tests for the .unexport-env directive. # @@ -10,14 +10,17 @@ # TODO: Implementation +# expect+1: Unknown directive "unexport-en" .unexport-en # misspelled .unexport-env # ok +# expect+1: Unknown directive "unexport-environment" .unexport-environment # misspelled .MAKEFLAGS: -dv UT_EXPORTED= value UT_UNEXPORTED= value .export UT_EXPORTED +# expect+1: The directive .unexport-env does not take arguments .unexport-env UT_EXPORTED UT_UNEXPORTED .MAKEFLAGS: -d0 diff --git a/unit-tests/directive-unexport.exp b/unit-tests/directive-unexport.exp index d59fb4713259..b084daf5d147 100644 --- a/unit-tests/directive-unexport.exp +++ b/unit-tests/directive-unexport.exp @@ -1,5 +1,5 @@ -make: "directive-unexport.mk" line 18: UT_A=a UT_B=b UT_C=c -make: "directive-unexport.mk" line 19: UT_A UT_B UT_C -make: "directive-unexport.mk" line 27: UT_A=a UT_B=b UT_C=c -make: "directive-unexport.mk" line 28: +make: "directive-unexport.mk" line 19: UT_A=a UT_B=b UT_C=c +make: "directive-unexport.mk" line 21: UT_A UT_B UT_C +make: "directive-unexport.mk" line 30: UT_A=a UT_B=b UT_C=c +make: "directive-unexport.mk" line 31: exit status 0 diff --git a/unit-tests/directive-unexport.mk b/unit-tests/directive-unexport.mk index efc103efedf6..e759fe3e35f2 100644 --- a/unit-tests/directive-unexport.mk +++ b/unit-tests/directive-unexport.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-unexport.mk,v 1.7 2020/12/13 01:07:54 rillig Exp $ +# $NetBSD: directive-unexport.mk,v 1.8 2023/06/01 20:56:35 rillig Exp $ # # Tests for the .unexport directive. # @@ -15,7 +15,9 @@ UT_C= c .export UT_A UT_B UT_C # Show the exported variables and their values. +# expect+1: UT_A=a UT_B=b UT_C=c .info ${:!env|sort|grep '^UT_'!} +# expect+1: UT_A UT_B UT_C .info ${.MAKE.EXPORTED} # XXX: Now try to unexport all of them. The variables are still exported @@ -24,6 +26,7 @@ UT_C= c *= asterisk .unexport * +# expect+1: UT_A=a UT_B=b UT_C=c .info ${:!env|sort|grep '^UT_'!} .info ${.MAKE.EXPORTED} diff --git a/unit-tests/directive-warning.exp b/unit-tests/directive-warning.exp index 932b88a151e2..6fbeed91df0f 100644 --- a/unit-tests/directive-warning.exp +++ b/unit-tests/directive-warning.exp @@ -1,11 +1,11 @@ -make: "directive-warning.mk" line 9: Unknown directive "warn" make: "directive-warning.mk" line 10: Unknown directive "warn" -make: "directive-warning.mk" line 11: Unknown directive "warnin" -make: "directive-warning.mk" line 12: Unknown directive "warnin" -make: "directive-warning.mk" line 13: Missing argument for ".warning" -make: "directive-warning.mk" line 14: warning: message -make: "directive-warning.mk" line 15: Unknown directive "warnings" -make: "directive-warning.mk" line 16: Unknown directive "warnings" +make: "directive-warning.mk" line 12: Unknown directive "warn" +make: "directive-warning.mk" line 14: Unknown directive "warnin" +make: "directive-warning.mk" line 16: Unknown directive "warnin" +make: "directive-warning.mk" line 18: Missing argument for ".warning" +make: "directive-warning.mk" line 19: warning: message +make: "directive-warning.mk" line 21: Unknown directive "warnings" +make: "directive-warning.mk" line 23: Unknown directive "warnings" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/directive-warning.mk b/unit-tests/directive-warning.mk index 9d5cec1ff0b8..b4c8f4730b78 100644 --- a/unit-tests/directive-warning.mk +++ b/unit-tests/directive-warning.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-warning.mk,v 1.7 2022/01/23 16:09:38 rillig Exp $ +# $NetBSD: directive-warning.mk,v 1.8 2023/06/01 20:56:35 rillig Exp $ # # Tests for the .warning directive. # @@ -6,13 +6,20 @@ # produced the wrong error message "Unknown directive". Since parse.c 1.503 # from 2020-12-19, the correct "Missing argument" is produced. +# expect+1: Unknown directive "warn" .warn # misspelled +# expect+1: Unknown directive "warn" .warn message # misspelled +# expect+1: Unknown directive "warnin" .warnin # misspelled +# expect+1: Unknown directive "warnin" .warnin message # misspelled +# expect+1: Missing argument for ".warning" .warning # "Missing argument" .warning message # expect+0: message +# expect+1: Unknown directive "warnings" .warnings # misspelled +# expect+1: Unknown directive "warnings" .warnings messages # Accepted before 2020-12-13 01:07:54. all: .PHONY diff --git a/unit-tests/doterror.mk b/unit-tests/doterror.mk index d46fb3581a25..0f3698ad5cf2 100644 --- a/unit-tests/doterror.mk +++ b/unit-tests/doterror.mk @@ -1,4 +1,4 @@ -# $NetBSD: doterror.mk,v 1.2 2020/10/24 08:34:59 rillig Exp $ +# $NetBSD: doterror.mk,v 1.3 2023/06/01 20:56:35 rillig Exp $ .BEGIN: @@ -17,4 +17,3 @@ happy: sad: @echo and now: $@; exit 1 - diff --git a/unit-tests/error.exp b/unit-tests/error.exp index 3adc099a4625..e782664498bf 100644 --- a/unit-tests/error.exp +++ b/unit-tests/error.exp @@ -1,6 +1,6 @@ -make: "error.mk" line 6: just FYI -make: "error.mk" line 7: warning: this could be serious -make: "error.mk" line 8: this is fatal +make: "error.mk" line 7: just FYI +make: "error.mk" line 9: warning: this could be serious +make: "error.mk" line 11: this is fatal make: stopped in unit-tests exit status 1 diff --git a/unit-tests/error.mk b/unit-tests/error.mk index 0029b3bc6aa9..2383e60da6fb 100644 --- a/unit-tests/error.mk +++ b/unit-tests/error.mk @@ -1,10 +1,13 @@ -# $NetBSD: error.mk,v 1.3 2020/11/03 17:38:45 rillig Exp $ +# $NetBSD: error.mk,v 1.4 2023/06/01 20:56:35 rillig Exp $ # # Demonstrate that the .error directive exits immediately, without # continuing parsing until the end of the file. +# expect+1: just FYI .info just FYI +# expect+1: warning: this could be serious .warning this could be serious +# expect+1: this is fatal .error this is fatal .info this is not reached because of the .error above diff --git a/unit-tests/export-env.mk b/unit-tests/export-env.mk index 1605b1a71d61..80653f4bb3c9 100644 --- a/unit-tests/export-env.mk +++ b/unit-tests/export-env.mk @@ -1,4 +1,4 @@ -# $NetBSD: export-env.mk,v 1.4 2020/10/24 08:50:17 rillig Exp $ +# $NetBSD: export-env.mk,v 1.5 2023/06/01 20:56:35 rillig Exp $ # our normal .export, subsequent changes affect the environment UT_TEST= this @@ -21,7 +21,3 @@ UT_LIT= literal ${UT_TEST} all: @echo make:; ${UT_TEST UT_ENV UT_EXP UT_LIT:L:@v@echo $v=${$v};@} @echo env:; ${UT_TEST UT_ENV UT_EXP UT_LIT:L:@v@echo $v=$${$v};@} - - - - diff --git a/unit-tests/forsubst.exp b/unit-tests/forsubst.exp deleted file mode 100644 index 0a98c00aff30..000000000000 --- a/unit-tests/forsubst.exp +++ /dev/null @@ -1,2 +0,0 @@ -.for with :S;... OK -exit status 0 diff --git a/unit-tests/forsubst.mk b/unit-tests/forsubst.mk deleted file mode 100644 index 9f293ab7f94e..000000000000 --- a/unit-tests/forsubst.mk +++ /dev/null @@ -1,22 +0,0 @@ -# $NetBSD: forsubst.mk,v 1.3 2020/11/03 17:59:27 rillig Exp $ -# -# The parser used to break dependency lines at ';' without regard for -# substitution patterns. Back then, the first ';' was interpreted as the -# separator between the dependency and its commands. This (perhaps coupled -# with the new handling of .for variables in ${:U...) caused -# interesting results for lines like: -# -# .for file in ${LIST} -# for-subst: ${file:S;^;${here}/;g} -# .endfor -# -# See the commit to unit-tests/forsubst (without the .mk) from 2009-10-07. - -all: for-subst - -here := ${.PARSEDIR} -# this should not run foul of the parser -.for file in ${.PARSEFILE} -for-subst: ${file:S;^;${here}/;g} - @echo ".for with :S;... OK" -.endfor diff --git a/unit-tests/include-main.exp b/unit-tests/include-main.exp index f58870486f87..fcc38247109f 100644 --- a/unit-tests/include-main.exp +++ b/unit-tests/include-main.exp @@ -1,5 +1,5 @@ -make: "include-main.mk" line 14: main-before-ok -make: "include-main.mk" line 21: main-before-for-ok +make: "include-main.mk" line 15: main-before-ok +make: "include-main.mk" line 23: main-before-for-ok make: "include-sub.inc" line 4: sub-before-ok make: "include-sub.inc" line 14: sub-before-for-ok Parsing line 5: . info subsub-ok @@ -7,11 +7,11 @@ make: "include-subsub.inc" line 5: subsub-ok in .for loop from include-sub.inc:31 with i = include in .for loop from include-sub.inc:30 with i = nested in .for loop from include-sub.inc:29 with i = deeply - in include-main.mk:27 + in include-main.mk:29 Parsing line 6: .MAKEFLAGS: -d0 ParseDependency(.MAKEFLAGS: -d0) make: "include-sub.inc" line 38: sub-after-ok make: "include-sub.inc" line 45: sub-after-for-ok -make: "include-main.mk" line 30: main-after-ok -make: "include-main.mk" line 37: main-after-for-ok +make: "include-main.mk" line 33: main-after-ok +make: "include-main.mk" line 41: main-after-for-ok exit status 0 diff --git a/unit-tests/include-main.mk b/unit-tests/include-main.mk index 50be0587348b..373bbdea1721 100644 --- a/unit-tests/include-main.mk +++ b/unit-tests/include-main.mk @@ -1,4 +1,4 @@ -# $NetBSD: include-main.mk,v 1.8 2023/01/19 23:26:14 rillig Exp $ +# $NetBSD: include-main.mk,v 1.9 2023/06/01 20:56:35 rillig Exp $ # # Until 2020-09-05, the .INCLUDEDFROMFILE magic variable did not behave # as described in the manual page. @@ -11,6 +11,7 @@ # properly handle nested includes and even .for loops. .if !defined(.INCLUDEDFROMFILE) +# expect+1: main-before-ok . info main-before-ok .else . warning main-before-fail(${.INCLUDEDFROMFILE}) @@ -18,6 +19,7 @@ .for i in once . if !defined(.INCLUDEDFROMFILE) +# expect+1: main-before-for-ok . info main-before-for-ok . else . warning main-before-for-fail(${.INCLUDEDFROMFILE}) @@ -27,6 +29,7 @@ .include "include-sub.inc" .if !defined(.INCLUDEDFROMFILE) +# expect+1: main-after-ok . info main-after-ok .else . warning main-after-fail(${.INCLUDEDFROMFILE}) @@ -34,6 +37,7 @@ .for i in once . if !defined(.INCLUDEDFROMFILE) +# expect+1: main-after-for-ok . info main-after-for-ok . else . warning main-after-for-fail(${.INCLUDEDFROMFILE}) diff --git a/unit-tests/modmatch.exp b/unit-tests/modmatch.exp deleted file mode 100644 index fcaf6c02ed69..000000000000 --- a/unit-tests/modmatch.exp +++ /dev/null @@ -1,17 +0,0 @@ -LIB=a X_LIBS:M${LIB${LIB:tu}} is "/tmp/liba.a" -LIB=a X_LIBS:M*/lib${LIB}.a is "/tmp/liba.a" -LIB=a X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBA.A" -LIB=b X_LIBS:M${LIB${LIB:tu}} is "" -LIB=b X_LIBS:M*/lib${LIB}.a is "" -LIB=b X_LIBS:M*/lib${LIB}.a:tu is "" -LIB=c X_LIBS:M${LIB${LIB:tu}} is "" -LIB=c X_LIBS:M*/lib${LIB}.a is "" -LIB=c X_LIBS:M*/lib${LIB}.a:tu is "" -LIB=d X_LIBS:M${LIB${LIB:tu}} is "/tmp/libd.a" -LIB=d X_LIBS:M*/lib${LIB}.a is "/tmp/libd.a" -LIB=d X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBD.A" -LIB=e X_LIBS:M${LIB${LIB:tu}} is "/tmp/libe.a" -LIB=e X_LIBS:M*/lib${LIB}.a is "/tmp/libe.a" -LIB=e X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBE.A" -Mscanner=OK -exit status 0 diff --git a/unit-tests/modmatch.mk b/unit-tests/modmatch.mk deleted file mode 100644 index 7dcacf09da6d..000000000000 --- a/unit-tests/modmatch.mk +++ /dev/null @@ -1,30 +0,0 @@ -# $NetBSD: modmatch.mk,v 1.9 2020/10/24 08:50:17 rillig Exp $ -# -# Tests for the :M and :S modifiers. - -X= a b c d e - -.for x in $X -LIB${x:tu}= /tmp/lib$x.a -.endfor - -X_LIBS= ${LIBA} ${LIBD} ${LIBE} - -LIB?= a - -var= head -res= no -.if !empty(var:M${:Uhead\:tail:C/:.*//}) -res= OK -.endif - -all: show-libs - -show-libs: - @for x in $X; do ${.MAKE} -f ${MAKEFILE} show LIB=$$x; done - @echo "Mscanner=${res}" - -show: - @echo 'LIB=${LIB} X_LIBS:M$${LIB$${LIB:tu}} is "${X_LIBS:M${LIB${LIB:tu}}}"' - @echo 'LIB=${LIB} X_LIBS:M*/lib$${LIB}.a is "${X_LIBS:M*/lib${LIB}.a}"' - @echo 'LIB=${LIB} X_LIBS:M*/lib$${LIB}.a:tu is "${X_LIBS:M*/lib${LIB}.a:tu}"' diff --git a/unit-tests/modmisc.exp b/unit-tests/modmisc.exp index 10475e65ee0f..f243511ab491 100644 --- a/unit-tests/modmisc.exp +++ b/unit-tests/modmisc.exp @@ -6,7 +6,6 @@ path='/bin':'/tmp':'/':'/no/such/dir' path_/usr/xbin=/opt/xbin/ paths=/bin /tmp / /no/such/dir /opt/xbin PATHS=/BIN /TMP / /NO/SUCH/DIR /OPT/XBIN -The answer is 42 S: C: @: diff --git a/unit-tests/modmisc.mk b/unit-tests/modmisc.mk index 9ace35c15162..4868abef92f1 100644 --- a/unit-tests/modmisc.mk +++ b/unit-tests/modmisc.mk @@ -1,4 +1,4 @@ -# $NetBSD: modmisc.mk,v 1.52 2020/12/20 19:29:06 rillig Exp $ +# $NetBSD: modmisc.mk,v 1.53 2023/06/16 07:20:45 rillig Exp $ # # miscellaneous modifier tests @@ -15,14 +15,10 @@ MOD_HOMES= S,/home/,/homes/, MOD_OPT= @d@$${exists($$d):?$$d:$${d:S,/usr,/opt,}}@ MOD_SEP= S,:, ,g -all: modvar modvarloop modsysv emptyvar undefvar +all: modvar modvarloop emptyvar undefvar all: mod-quote all: mod-break-many-words -# See also sysv.mk. -modsysv: - @echo "The answer is ${libfoo.a:L:libfoo.a=42}" - # Demonstrates modifiers that are given indirectly from a variable. modvar: @echo "path='${path}'" @@ -60,6 +56,6 @@ undefvar: mod-quote: @echo $@: new${.newline:Q}${.newline:Q}line -# Cover the bmake_realloc in Str_Words. +# Cover the bmake_realloc in Substring_Words. mod-break-many-words: @echo $@: ${UNDEF:U:range=500:[#]} diff --git a/unit-tests/opt-debug-file.exp b/unit-tests/opt-debug-file.exp index 712686f60b3c..8bdaca612310 100644 --- a/unit-tests/opt-debug-file.exp +++ b/unit-tests/opt-debug-file.exp @@ -1,6 +1,6 @@ -make: "opt-debug-file.mk" line 43: This goes to stderr only, once. -make: "opt-debug-file.mk" line 45: This goes to stderr only, once. -make: "opt-debug-file.mk" line 47: This goes to stderr, and in addition to the debug log. +make: "opt-debug-file.mk" line 44: This goes to stderr only, once. +make: "opt-debug-file.mk" line 47: This goes to stderr only, once. +make: "opt-debug-file.mk" line 50: This goes to stderr, and in addition to the debug log. CondParser_Eval: ${:!cat opt-debug-file.debuglog!:Maddition:[#]} != 1 Comparing 1.000000 != 1.000000 make: Missing delimiter for modifier ':S' diff --git a/unit-tests/opt-debug-file.mk b/unit-tests/opt-debug-file.mk index b878c2bcf734..a8190b2f1b50 100644 --- a/unit-tests/opt-debug-file.mk +++ b/unit-tests/opt-debug-file.mk @@ -1,4 +1,4 @@ -# $NetBSD: opt-debug-file.mk,v 1.8 2022/01/11 19:47:34 rillig Exp $ +# $NetBSD: opt-debug-file.mk,v 1.9 2023/06/01 20:56:35 rillig Exp $ # # Tests for the -dF command line option, which redirects the debug log # to a file instead of writing it to stderr. @@ -40,10 +40,13 @@ DEBUG_OUTPUT:= ${:!cat opt-debug-file.debuglog!} # See Parse_Error. .MAKEFLAGS: -dFstdout +# expect+1: This goes to stderr only, once. . info This goes to stderr only, once. .MAKEFLAGS: -dFstderr +# expect+1: This goes to stderr only, once. . info This goes to stderr only, once. .MAKEFLAGS: -dFopt-debug-file.debuglog +# expect+1: This goes to stderr, and in addition to the debug log. . info This goes to stderr, and in addition to the debug log. .MAKEFLAGS: -dFstderr -d0c .if ${:!cat opt-debug-file.debuglog!:Maddition:[#]} != 1 diff --git a/unit-tests/opt-debug-for.exp b/unit-tests/opt-debug-for.exp index ea811b9bfcf5..a8f63b85fec3 100644 --- a/unit-tests/opt-debug-for.exp +++ b/unit-tests/opt-debug-for.exp @@ -1,22 +1,22 @@ For: new loop 2 For: end for 2 For: end for 1 -For: loop body: +For: loop body with outer = a: . for inner in 1 2 VAR.${:Ua}${inner}= value . endfor For: end for 1 -For: loop body: +For: loop body with inner = 1: VAR.${:Ua}${:U1}= value -For: loop body: +For: loop body with inner = 2: VAR.${:Ua}${:U2}= value -For: loop body: +For: loop body with outer = b: . for inner in 1 2 VAR.${:Ub}${inner}= value . endfor For: end for 1 -For: loop body: +For: loop body with inner = 1: VAR.${:Ub}${:U1}= value -For: loop body: +For: loop body with inner = 2: VAR.${:Ub}${:U2}= value exit status 0 diff --git a/unit-tests/opt-debug-hash.exp b/unit-tests/opt-debug-hash.exp index b239399ec44d..194b08daa5f2 100644 --- a/unit-tests/opt-debug-hash.exp +++ b/unit-tests/opt-debug-hash.exp @@ -1,4 +1,4 @@ -make: "opt-debug-hash.mk" line 11: Missing argument for ".error" +make: "opt-debug-hash.mk" line 12: Missing argument for ".error" make: Fatal errors encountered -- cannot continue HashTable targets: size=16 numEntries=0 maxchain=0 HashTable Global variables: size=16 numEntries= maxchain=3 diff --git a/unit-tests/opt-debug-hash.mk b/unit-tests/opt-debug-hash.mk index 8b757ff3f290..a1b21e145bf0 100644 --- a/unit-tests/opt-debug-hash.mk +++ b/unit-tests/opt-debug-hash.mk @@ -1,4 +1,4 @@ -# $NetBSD: opt-debug-hash.mk,v 1.3 2022/01/22 18:59:24 rillig Exp $ +# $NetBSD: opt-debug-hash.mk,v 1.4 2023/06/01 20:56:35 rillig Exp $ # # Tests for the -dh command line option, which adds debug logging for # hash tables. Even more detailed logging is available by compiling @@ -8,4 +8,5 @@ # Force a parse error, to demonstrate the newline character in the diagnostic # that had been missing before parse.c 1.655 from 2022-01-22. +# expect+1: Missing argument for ".error" .error diff --git a/unit-tests/opt-debug-lint.exp b/unit-tests/opt-debug-lint.exp index 83643e9a8772..5a6510bd029a 100644 --- a/unit-tests/opt-debug-lint.exp +++ b/unit-tests/opt-debug-lint.exp @@ -1,10 +1,10 @@ -make: "opt-debug-lint.mk" line 19: Variable "X" is undefined -make: "opt-debug-lint.mk" line 19: Malformed conditional ($X) -make: "opt-debug-lint.mk" line 41: Variable "UNDEF" is undefined -make: "opt-debug-lint.mk" line 41: Malformed conditional (${UNDEF}) -make: "opt-debug-lint.mk" line 61: Missing delimiter ':' after modifier "L" -make: "opt-debug-lint.mk" line 61: Missing delimiter ':' after modifier "P" -make: "opt-debug-lint.mk" line 69: Unknown modifier "${" +make: "opt-debug-lint.mk" line 21: Variable "X" is undefined +make: "opt-debug-lint.mk" line 21: Malformed conditional ($X) +make: "opt-debug-lint.mk" line 45: Variable "UNDEF" is undefined +make: "opt-debug-lint.mk" line 45: Malformed conditional (${UNDEF}) +make: "opt-debug-lint.mk" line 67: Missing delimiter ':' after modifier "L" +make: "opt-debug-lint.mk" line 67: Missing delimiter ':' after modifier "P" +make: "opt-debug-lint.mk" line 76: Unknown modifier "${" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/opt-debug-lint.mk b/unit-tests/opt-debug-lint.mk index 155e1a3de3be..0fcaf8b102ad 100644 --- a/unit-tests/opt-debug-lint.mk +++ b/unit-tests/opt-debug-lint.mk @@ -1,4 +1,4 @@ -# $NetBSD: opt-debug-lint.mk,v 1.14 2021/03/14 10:57:12 rillig Exp $ +# $NetBSD: opt-debug-lint.mk,v 1.15 2023/06/01 20:56:35 rillig Exp $ # # Tests for the -dL command line option, which runs additional checks # to catch common mistakes, such as unclosed variable expressions. @@ -16,6 +16,8 @@ # # See also: # cond-undef-lint.mk +# expect+2: Malformed conditional ($X) +# expect+1: Variable "X" is undefined .if $X . error .endif @@ -38,6 +40,8 @@ # hoping for the caller to print an error message. This resulted in the # well-known "Malformed conditional" error message, even though the # conditional was well-formed and the only error was an undefined variable. +# expect+2: Malformed conditional (${UNDEF}) +# expect+1: Variable "UNDEF" is undefined .if ${UNDEF} . error .endif @@ -58,6 +62,8 @@ ${UNDEF}: ${UNDEF} # Since 2020-10-03, in lint mode the variable modifier must be separated # by colons. See varparse-mod.mk. +# expect+2: Missing delimiter ':' after modifier "L" +# expect+1: Missing delimiter ':' after modifier "P" .if ${value:LPL} != "value" . error .endif @@ -66,6 +72,7 @@ ${UNDEF}: ${UNDEF} # variable modifier had to be separated by colons. This was wrong though # since make always fell back trying to parse the indirect modifier as a # SysV modifier. +# expect+1: Unknown modifier "${" .if ${value:${:UL}PL} != "LPL}" # FIXME: "LPL}" is unexpected here. . error ${value:${:UL}PL} .endif diff --git a/unit-tests/opt-debug-parse.exp b/unit-tests/opt-debug-parse.exp index 0e11024647a1..811c6b45dce5 100644 --- a/unit-tests/opt-debug-parse.exp +++ b/unit-tests/opt-debug-parse.exp @@ -1,26 +1,26 @@ Parse_PushInput: .for loop in opt-debug-parse.mk, line 16 SetFilenameVars: ${.PARSEDIR} = ${.PARSEFILE} = `opt-debug-parse.mk' -Parsing line 20: .info trace with multi-line .for loop head -make: "opt-debug-parse.mk" line 20: trace with multi-line .for loop head +Parsing line 21: .info trace with multi-line .for loop head +make: "opt-debug-parse.mk" line 21: trace with multi-line .for loop head in .for loop from opt-debug-parse.mk:16 with var = value -ParseEOF: returning to file opt-debug-parse.mk, line 22 +ParseEOF: returning to file opt-debug-parse.mk, line 23 SetFilenameVars: ${.PARSEDIR} = ${.PARSEFILE} = `opt-debug-parse.mk' -Parsing line 25: .include "/dev/null" +Parsing line 26: .include "/dev/null" Parse_PushInput: file /dev/null, line 1 SetFilenameVars: ${.PARSEDIR} = ${.PARSEFILE} = `null' SetFilenameVars: ${.INCLUDEDFROMDIR} = ${.INCLUDEDFROMFILE} = `opt-debug-parse.mk' -ParseEOF: returning to file opt-debug-parse.mk, line 26 +ParseEOF: returning to file opt-debug-parse.mk, line 27 SetFilenameVars: ${.PARSEDIR} = ${.PARSEFILE} = `opt-debug-parse.mk' -Parse_PushInput: .for loop in opt-debug-parse.mk, line 30 +Parse_PushInput: .for loop in opt-debug-parse.mk, line 31 SetFilenameVars: ${.PARSEDIR} = ${.PARSEFILE} = `opt-debug-parse.mk' -Parsing line 31: .info trace -make: "opt-debug-parse.mk" line 31: trace - in .for loop from opt-debug-parse.mk:30 with a = 1, b = 2, c = 3 -Parsing line 31: .info trace -make: "opt-debug-parse.mk" line 31: trace - in .for loop from opt-debug-parse.mk:30 with a = 4, b = 5, c = 6 -ParseEOF: returning to file opt-debug-parse.mk, line 33 +Parsing line 34: .info trace +make: "opt-debug-parse.mk" line 34: trace + in .for loop from opt-debug-parse.mk:31 with a = 1, b = 2, c = 3 +Parsing line 34: .info trace +make: "opt-debug-parse.mk" line 34: trace + in .for loop from opt-debug-parse.mk:31 with a = 4, b = 5, c = 6 +ParseEOF: returning to file opt-debug-parse.mk, line 36 SetFilenameVars: ${.PARSEDIR} = ${.PARSEFILE} = `opt-debug-parse.mk' -Parsing line 35: .MAKEFLAGS: -d0 +Parsing line 38: .MAKEFLAGS: -d0 ParseDependency(.MAKEFLAGS: -d0) exit status 0 diff --git a/unit-tests/opt-debug-parse.mk b/unit-tests/opt-debug-parse.mk index 9517bb62b976..347537015b52 100644 --- a/unit-tests/opt-debug-parse.mk +++ b/unit-tests/opt-debug-parse.mk @@ -1,4 +1,4 @@ -# $NetBSD: opt-debug-parse.mk,v 1.7 2022/02/09 21:09:24 rillig Exp $ +# $NetBSD: opt-debug-parse.mk,v 1.8 2023/06/01 20:56:35 rillig Exp $ # # Tests for the -dp command line option, which adds debug logging about # makefile parsing. @@ -17,6 +17,7 @@ var \ in \ value +# expect+1: trace with multi-line .for loop head .info trace with multi-line .for loop head .endfor @@ -28,6 +29,8 @@ # In .for loops with multiple variables, the variable details are included in # the stack trace, just as with a single variable. .for a b c in 1 2 3 ${:U4 5 6} +# expect+2: trace +# expect+1: trace .info trace .endfor diff --git a/unit-tests/opt-warnings-as-errors.exp b/unit-tests/opt-warnings-as-errors.exp index 1db56b753bed..87d1db249a20 100644 --- a/unit-tests/opt-warnings-as-errors.exp +++ b/unit-tests/opt-warnings-as-errors.exp @@ -1,6 +1,6 @@ -make: "opt-warnings-as-errors.mk" line 12: warning: message 1 +make: "opt-warnings-as-errors.mk" line 13: warning: message 1 make: parsing warnings being treated as errors -make: "opt-warnings-as-errors.mk" line 13: warning: message 2 +make: "opt-warnings-as-errors.mk" line 15: warning: message 2 parsing continues make: Fatal errors encountered -- cannot continue make: stopped in unit-tests diff --git a/unit-tests/opt-warnings-as-errors.mk b/unit-tests/opt-warnings-as-errors.mk index c29343f960a7..3896dad10f1a 100644 --- a/unit-tests/opt-warnings-as-errors.mk +++ b/unit-tests/opt-warnings-as-errors.mk @@ -1,4 +1,4 @@ -# $NetBSD: opt-warnings-as-errors.mk,v 1.5 2021/01/27 00:02:38 rillig Exp $ +# $NetBSD: opt-warnings-as-errors.mk,v 1.6 2023/06/01 20:56:35 rillig Exp $ # # Tests for the -W command line option, which turns warnings into errors. # @@ -9,7 +9,9 @@ .MAKEFLAGS: -W +# expect+1: warning: message 1 .warning message 1 +# expect+1: warning: message 2 .warning message 2 _!= echo 'parsing continues' 1>&2 diff --git a/unit-tests/parse.exp b/unit-tests/parse.exp index a11de0c194ae..694e35e3b6e2 100644 --- a/unit-tests/parse.exp +++ b/unit-tests/parse.exp @@ -1,6 +1,6 @@ make: "parse.mk" line 7: Makefile appears to contain unresolved CVS/RCS/??? merge conflicts make: "parse.mk" line 14: Makefile appears to contain unresolved CVS/RCS/??? merge conflicts -make: "parse.mk" line 24: Invalid line type +make: "parse.mk" line 25: Invalid line type make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/parse.mk b/unit-tests/parse.mk index 551dc98aaf24..296c19f5cd99 100644 --- a/unit-tests/parse.mk +++ b/unit-tests/parse.mk @@ -1,4 +1,4 @@ -# $NetBSD: parse.mk,v 1.4 2023/04/28 13:09:48 rillig Exp $ +# $NetBSD: parse.mk,v 1.5 2023/06/01 20:56:35 rillig Exp $ # # Test those parts of the parsing that do not belong in any of the other # categories. @@ -21,6 +21,7 @@ # the expanded line's terminating '\0'. # # https://bugs.freebsd.org/265119 +# expect+1: Invalid line type one-target ${:U } diff --git a/unit-tests/recursive.exp b/unit-tests/recursive.exp index 36cd1c989532..dc50fe034969 100644 --- a/unit-tests/recursive.exp +++ b/unit-tests/recursive.exp @@ -1,5 +1,5 @@ -make: "recursive.mk" line 36: Unclosed variable "MISSING_PAREN" -make: "recursive.mk" line 37: Unclosed variable "MISSING_BRACE" +make: "recursive.mk" line 37: Unclosed variable "MISSING_PAREN" +make: "recursive.mk" line 39: Unclosed variable "MISSING_BRACE" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/recursive.mk b/unit-tests/recursive.mk index 5265cec59a2d..307515d70a08 100644 --- a/unit-tests/recursive.mk +++ b/unit-tests/recursive.mk @@ -1,4 +1,4 @@ -# $NetBSD: recursive.mk,v 1.5 2021/03/15 12:15:03 rillig Exp $ +# $NetBSD: recursive.mk,v 1.6 2023/06/01 20:56:35 rillig Exp $ # # In -dL mode, a variable may get expanded before it makes sense. # This would stop make from doing anything since the "recursive" error @@ -33,6 +33,8 @@ AM_DEFAULT_VERBOSITY= 1 # therefore that's acceptable. In most practical cases, the missing # brace would be detected directly in the line where it is produced. MISSING_BRACE_INDIRECT:= ${:U\${MISSING_BRACE} +# expect+1: Unclosed variable "MISSING_PAREN" UNCLOSED= $(MISSING_PAREN +# expect+1: Unclosed variable "MISSING_BRACE" UNCLOSED= ${MISSING_BRACE UNCLOSED= ${MISSING_BRACE_INDIRECT} diff --git a/unit-tests/var-eval-short.exp b/unit-tests/var-eval-short.exp index ea6e0d7485f9..14e3d372f198 100644 --- a/unit-tests/var-eval-short.exp +++ b/unit-tests/var-eval-short.exp @@ -1,5 +1,5 @@ -make: "var-eval-short.mk" line 44: In the :@ modifier of "", the variable name "${FAIL}" must not contain a dollar -make: "var-eval-short.mk" line 44: Malformed conditional (0 && ${:Uword:@${FAIL}@expr@}) +make: "var-eval-short.mk" line 46: In the :@ modifier of "", the variable name "${FAIL}" must not contain a dollar +make: "var-eval-short.mk" line 46: Malformed conditional (0 && ${:Uword:@${FAIL}@expr@}) CondParser_Eval: 0 && ${0:?${FAIL}then:${FAIL}else} Var_Parse: ${0:?${FAIL}then:${FAIL}else} (parse-only) Parsing modifier ${0:?...} @@ -8,7 +8,7 @@ Modifier part: "${FAIL}then" Var_Parse: ${FAIL}else} (parse-only) Modifier part: "${FAIL}else" Result of ${0:?${FAIL}then:${FAIL}else} is "" (parse-only, defined) -Parsing line 165: DEFINED= defined +Parsing line 167: DEFINED= defined Global: DEFINED = defined CondParser_Eval: 0 && ${DEFINED:L:?${FAIL}then:${FAIL}else} Var_Parse: ${DEFINED:L:?${FAIL}then:${FAIL}else} (parse-only) @@ -20,7 +20,7 @@ Modifier part: "${FAIL}then" Var_Parse: ${FAIL}else} (parse-only) Modifier part: "${FAIL}else" Result of ${DEFINED:?${FAIL}then:${FAIL}else} is "defined" (parse-only, regular) -Parsing line 168: .MAKEFLAGS: -d0 +Parsing line 170: .MAKEFLAGS: -d0 ParseDependency(.MAKEFLAGS: -d0) Global: .MAKEFLAGS = -r -k -d cpv -d Global: .MAKEFLAGS = -r -k -d cpv -d 0 diff --git a/unit-tests/var-eval-short.mk b/unit-tests/var-eval-short.mk index 7faf1cc5d154..aa8bf79decec 100644 --- a/unit-tests/var-eval-short.mk +++ b/unit-tests/var-eval-short.mk @@ -1,4 +1,4 @@ -# $NetBSD: var-eval-short.mk,v 1.9 2023/05/09 16:27:00 rillig Exp $ +# $NetBSD: var-eval-short.mk,v 1.10 2023/06/01 20:56:35 rillig Exp $ # # Tests for each variable modifier to ensure that they only do the minimum # necessary computations. If the result of the expression is irrelevant, @@ -41,6 +41,8 @@ FAIL= ${:!echo unexpected 1>&2!} # after the loop, when undefining the temporary global loop variable. # Since var.c 1.907 from 2021-04-04, a '$' is no longer allowed in the # variable name. +# expect+2: In the :@ modifier of "", the variable name "${FAIL}" must not contain a dollar +# expect+1: Malformed conditional (0 && ${:Uword:@${FAIL}@expr@}) .if 0 && ${:Uword:@${FAIL}@expr@} .endif diff --git a/unit-tests/var-op-append.mk b/unit-tests/var-op-append.mk index 420ee376b75d..5f06fd887332 100644 --- a/unit-tests/var-op-append.mk +++ b/unit-tests/var-op-append.mk @@ -1,7 +1,20 @@ -# $NetBSD: var-op-append.mk,v 1.9 2021/04/04 10:13:09 rillig Exp $ +# $NetBSD: var-op-append.mk,v 1.10 2023/06/21 07:30:50 rillig Exp $ # -# Tests for the += variable assignment operator, which appends to a variable, -# creating it if necessary. +# Tests for the '+=' variable assignment operator, which appends to a +# variable, creating it if necessary. +# +# See also +# var-op.mk +# +# Standards +# The '+=' variable assignment operator is planned to be added in +# POSIX.1-202x. +# +# This implementation does not support the immediate-expansion macros +# specified in POSIX.1-202x. All variables are delayed-expansion. +# +# History +# The '+=' variable assignment operator was added before 1993-03-21. # Appending to an undefined variable is possible. # The variable is created, and no extra space is added before the value. diff --git a/unit-tests/var-op-assign.exp b/unit-tests/var-op-assign.exp index 73e580403d78..593dfa4b904b 100644 --- a/unit-tests/var-op-assign.exp +++ b/unit-tests/var-op-assign.exp @@ -1,6 +1,6 @@ this will be evaluated later -make: "var-op-assign.mk" line 59: Invalid line type -make: "var-op-assign.mk" line 93: Parsing still continues until here. +make: "var-op-assign.mk" line 60: Invalid line type +make: "var-op-assign.mk" line 95: Parsing still continues until here. make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/var-op-assign.mk b/unit-tests/var-op-assign.mk index 18ecf8d0d5ed..0a1c686fe5c5 100644 --- a/unit-tests/var-op-assign.mk +++ b/unit-tests/var-op-assign.mk @@ -1,4 +1,4 @@ -# $NetBSD: var-op-assign.mk,v 1.8 2021/03/15 19:15:04 rillig Exp $ +# $NetBSD: var-op-assign.mk,v 1.9 2023/06/01 20:56:35 rillig Exp $ # # Tests for the = variable assignment operator, which overwrites an existing # variable or creates it. @@ -56,6 +56,7 @@ VAR= ${:! echo 'this will be evaluated later' 1>&2 !} # In a variable assignment, the variable name must consist of a single word. # The following line therefore generates a parse error. +# expect+1: Invalid line type VARIABLE NAME= variable value # But if the whitespace appears inside parentheses or braces, everything is @@ -90,6 +91,7 @@ VARNAME_BRACES= VAR{spaces in braces} # unexpected variable values. # # Therefore, just output an info message. +# expect+1: Parsing still continues until here. .info Parsing still continues until here. all: diff --git a/unit-tests/var-op-expand.exp b/unit-tests/var-op-expand.exp index 4916336c0400..5ea4e6b6954c 100644 --- a/unit-tests/var-op-expand.exp +++ b/unit-tests/var-op-expand.exp @@ -1,7 +1,7 @@ make: "var-op-expand.mk" line 274: Unknown modifier "s,value,replaced," -make: "var-op-expand.mk" line 277: warning: XXX Neither branch should be taken. -make: "var-op-expand.mk" line 282: Unknown modifier "s,value,replaced," -make: "var-op-expand.mk" line 283: warning: XXX Neither branch should be taken. +make: "var-op-expand.mk" line 278: warning: XXX Neither branch should be taken. +make: "var-op-expand.mk" line 283: Unknown modifier "s,value,replaced," +make: "var-op-expand.mk" line 285: warning: XXX Neither branch should be taken. make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/var-op-expand.mk b/unit-tests/var-op-expand.mk index f89aa6fa4b56..a0b9cc475404 100644 --- a/unit-tests/var-op-expand.mk +++ b/unit-tests/var-op-expand.mk @@ -1,4 +1,4 @@ -# $NetBSD: var-op-expand.mk,v 1.17 2022/09/08 20:23:45 rillig Exp $ +# $NetBSD: var-op-expand.mk,v 1.18 2023/06/01 20:56:35 rillig Exp $ # # Tests for the := variable assignment operator, which expands its # right-hand side. @@ -274,12 +274,14 @@ indirect:= ${INDIRECT:tl} .if ${indirect} != " ok " . error .else +# expect+1: warning: XXX Neither branch should be taken. . warning XXX Neither branch should be taken. .endif LATER= uppercase-value later= lowercase-value # expect+1: Unknown modifier "s,value,replaced," .if ${indirect} != "uppercase-replaced ok uppercase-sysv" +# expect+1: warning: XXX Neither branch should be taken. . warning XXX Neither branch should be taken. .else . error diff --git a/unit-tests/var-op-shell.exp b/unit-tests/var-op-shell.exp index 0e9bd2cbc35a..0837cd4f832e 100644 --- a/unit-tests/var-op-shell.exp +++ b/unit-tests/var-op-shell.exp @@ -1,8 +1,8 @@ -make: "var-op-shell.mk" line 31: warning: "echo "failed"; false" returned non-zero status -make: "var-op-shell.mk" line 37: warning: "false" returned non-zero status -make: "var-op-shell.mk" line 59: warning: "kill $$" exited on a signal +make: "var-op-shell.mk" line 32: warning: "echo "failed"; false" returned non-zero status +make: "var-op-shell.mk" line 39: warning: "false" returned non-zero status +make: "var-op-shell.mk" line 62: warning: "kill $$" exited on a signal /bin/no/such/command: not found -make: "var-op-shell.mk" line 65: warning: "/bin/no/such/command" returned non-zero status +make: "var-op-shell.mk" line 69: warning: "/bin/no/such/command" returned non-zero status stderr Capturing the output of command "echo '$$$$'" Global: OUTPUT = $$$$ diff --git a/unit-tests/var-op-shell.mk b/unit-tests/var-op-shell.mk index bd2a48f17cc4..de26bff94905 100644 --- a/unit-tests/var-op-shell.mk +++ b/unit-tests/var-op-shell.mk @@ -1,4 +1,4 @@ -# $NetBSD: var-op-shell.mk,v 1.6 2022/01/10 20:32:29 rillig Exp $ +# $NetBSD: var-op-shell.mk,v 1.7 2023/06/01 20:56:35 rillig Exp $ # # Tests for the != variable assignment operator, which runs its right-hand # side through the shell. @@ -28,12 +28,14 @@ OUTPUT!= true # '::!=', expression modifier ':!...!'), a failed command generates only a # warning, not an "error". These "errors" are ignored in default mode, for # compatibility, but not in lint mode (-dL). +# expect+1: warning: "echo "failed"; false" returned non-zero status OUTPUT!= echo "failed"; false .if ${OUTPUT} != "failed" . error .endif # A command with empty output may fail as well. +# expect+1: warning: "false" returned non-zero status OUTPUT!= false .if ${OUTPUT} != "" . error @@ -56,12 +58,14 @@ OUTPUT!= echo "before"; false; echo "after" # This should result in a warning about "exited on a signal". # This used to be kill -14 (SIGALRM), but that stopped working on # Darwin18 after recent update. +# expect+1: warning: "kill $$" exited on a signal OUTPUT!= kill $$$$ .if ${OUTPUT} != "" . error .endif # A nonexistent command produces a non-zero exit status. +# expect+1: warning: "/bin/no/such/command" returned non-zero status OUTPUT!= /bin/no/such/command .if ${OUTPUT} != "" . error diff --git a/unit-tests/var-readonly.mk b/unit-tests/var-readonly.mk index 43799e4adb5c..050b44d1b4e8 100644 --- a/unit-tests/var-readonly.mk +++ b/unit-tests/var-readonly.mk @@ -1,4 +1,4 @@ -# $NetBSD: var-readonly.mk,v 1.1 2023/01/24 00:20:00 sjg Exp $ +# $NetBSD: var-readonly.mk,v 1.3 2023/06/19 15:37:48 sjg Exp $ # the answer N = 42 @@ -9,6 +9,12 @@ N = 666 .error N ($N) should be 42 .endif +# undef should fail +.undef N +.ifndef N +.error N should not be undef'd +.endif + .NOREADONLY: N # now we can change it N = 69 @@ -17,4 +23,3 @@ N = 69 .endif all: - diff --git a/unit-tests/var-recursive.exp b/unit-tests/var-recursive.exp index 44c381f94ff9..2158286749f3 100644 --- a/unit-tests/var-recursive.exp +++ b/unit-tests/var-recursive.exp @@ -1,19 +1,19 @@ -make: "var-recursive.mk" line 20: still there +make: "var-recursive.mk" line 21: still there Variable DIRECT is recursive. - in var-recursive.mk:21 + in var-recursive.mk:22 make: stopped in unit-tests Variable INDIRECT1 is recursive. - in var-recursive.mk:28 + in var-recursive.mk:29 make: stopped in unit-tests -make: "var-recursive.mk" line 35: ok +make: "var-recursive.mk" line 37: ok Variable V is recursive. - in var-recursive.mk:43 + in var-recursive.mk:45 make: stopped in unit-tests : OK -In a command near "var-recursive.mk" line 55: Variable VAR is recursive. +In a command near "var-recursive.mk" line 57: Variable VAR is recursive. make: stopped in unit-tests exit status 0 diff --git a/unit-tests/var-recursive.mk b/unit-tests/var-recursive.mk index 1825c8a63120..998d0d8c312a 100644 --- a/unit-tests/var-recursive.mk +++ b/unit-tests/var-recursive.mk @@ -1,4 +1,4 @@ -# $NetBSD: var-recursive.mk,v 1.4 2022/01/29 10:21:26 rillig Exp $ +# $NetBSD: var-recursive.mk,v 1.5 2023/06/01 20:56:35 rillig Exp $ # # Tests for variable expressions that refer to themselves and thus # cannot be evaluated. @@ -17,6 +17,7 @@ all: .elif ${TEST} == direct DIRECT= ${DIRECT} # Defining a recursive variable is not yet an error. +# expect+1: still there . info still there # Therefore this line is printed. . info ${DIRECT} # But expanding the variable is an error. @@ -32,6 +33,7 @@ INDIRECT2= ${INDIRECT1} # The variable refers to itself, but only in the branch of a condition that # is never satisfied and is thus not evaluated. CONDITIONAL= ${1:?ok:${CONDITIONAL}} +# expect+1: ok . info ${CONDITIONAL} .elif ${TEST} == short diff --git a/unit-tests/var-scope-cmdline.exp b/unit-tests/var-scope-cmdline.exp index 281b5af291ca..c663a9069a9f 100644 --- a/unit-tests/var-scope-cmdline.exp +++ b/unit-tests/var-scope-cmdline.exp @@ -1,4 +1,4 @@ -make: "var-scope-cmdline.mk" line 71: global -make: "var-scope-cmdline.mk" line 80: makeflags +make: "var-scope-cmdline.mk" line 72: global +make: "var-scope-cmdline.mk" line 82: makeflags makeflags exit status 0 diff --git a/unit-tests/var-scope-cmdline.mk b/unit-tests/var-scope-cmdline.mk index fbfb2d0290a4..eaa2c58347ae 100644 --- a/unit-tests/var-scope-cmdline.mk +++ b/unit-tests/var-scope-cmdline.mk @@ -1,4 +1,4 @@ -# $NetBSD: var-scope-cmdline.mk,v 1.2 2023/04/07 05:54:16 rillig Exp $ +# $NetBSD: var-scope-cmdline.mk,v 1.3 2023/06/01 20:56:35 rillig Exp $ # # Tests for variables specified on the command line. # @@ -68,6 +68,7 @@ # A normal global variable, without any cmdline variable nearby. VAR= global +# expect+1: global .info ${VAR} # The global variable is "overridden" by simply deleting it and then @@ -77,6 +78,7 @@ VAR= global # # See varmod-loop.mk for a non-obvious way to undefine a cmdline variable. .MAKEFLAGS: VAR=makeflags +# expect+1: makeflags .info ${VAR} # If Var_SetWithFlags should ever forget to delete the global variable, diff --git a/unit-tests/vardebug.exp b/unit-tests/vardebug.exp index 19e5c9c9fdd0..a668807b94e3 100644 --- a/unit-tests/vardebug.exp +++ b/unit-tests/vardebug.exp @@ -54,11 +54,11 @@ Var_Parse: ${:Uvariable:unknown} (eval-defined) Evaluating modifier ${:U...} on value "" (eval-defined, undefined) Result of ${:Uvariable} is "variable" (eval-defined, defined) Evaluating modifier ${:u...} on value "variable" (eval-defined, defined) -make: "vardebug.mk" line 44: Unknown modifier "unknown" +make: "vardebug.mk" line 46: Unknown modifier "unknown" Result of ${:unknown} is error (eval-defined, defined) -make: "vardebug.mk" line 44: Malformed conditional (${:Uvariable:unknown}) +make: "vardebug.mk" line 46: Malformed conditional (${:Uvariable:unknown}) Var_Parse: ${UNDEFINED} (eval-defined) -make: "vardebug.mk" line 53: Malformed conditional (${UNDEFINED}) +make: "vardebug.mk" line 56: Malformed conditional (${UNDEFINED}) Global: delete .SHELL (not found) Command: .SHELL = Command: .SHELL = overwritten ignored (read-only) diff --git a/unit-tests/vardebug.mk b/unit-tests/vardebug.mk index 4a16a7f2797f..34015aa71db9 100644 --- a/unit-tests/vardebug.mk +++ b/unit-tests/vardebug.mk @@ -1,4 +1,4 @@ -# $NetBSD: vardebug.mk,v 1.7 2021/02/04 21:42:47 rillig Exp $ +# $NetBSD: vardebug.mk,v 1.8 2023/06/01 20:56:35 rillig Exp $ # # Demonstrates the debugging output for var.c. @@ -41,6 +41,8 @@ VAR+= 3 # When ApplyModifiers results in an error, this appears in the debug log # as "is error", without surrounding quotes. +# expect+2: Malformed conditional (${:Uvariable:unknown}) +# expect+1: Unknown modifier "unknown" .if ${:Uvariable:unknown} .endif @@ -50,6 +52,7 @@ VAR+= 3 # There is a specialized error message for "Undefined variable", but as of # 2020-08-08, that is not covered by any unit tests. It might even be # unreachable. +# expect+1: Malformed conditional (${UNDEFINED}) .if ${UNDEFINED} .endif diff --git a/unit-tests/varmod-assign-shell.exp b/unit-tests/varmod-assign-shell.exp index 7bb41108cb62..b7c6cd223f24 100644 --- a/unit-tests/varmod-assign-shell.exp +++ b/unit-tests/varmod-assign-shell.exp @@ -1,4 +1,4 @@ -make: "varmod-assign-shell.mk" line 27: warning: "echo output; false" returned non-zero status +make: "varmod-assign-shell.mk" line 28: warning: "echo output; false" returned non-zero status Global: _ = # (empty) Var_Parse: ${ASSIGNED::!=echo output; ${:Ufalse}} (eval-keep-dollar-and-undefined) Evaluating modifier ${ASSIGNED::...} on value "previous" (eval-keep-dollar-and-undefined, regular) diff --git a/unit-tests/varmod-assign-shell.mk b/unit-tests/varmod-assign-shell.mk index d03692942d5b..6158bac14eaa 100644 --- a/unit-tests/varmod-assign-shell.mk +++ b/unit-tests/varmod-assign-shell.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-assign-shell.mk,v 1.4 2022/01/10 20:32:29 rillig Exp $ +# $NetBSD: varmod-assign-shell.mk,v 1.5 2023/06/01 20:56:35 rillig Exp $ # # Tests for the variable modifier '::!=', which assigns the output of a shell # command to the variable, but only if the command exited successfully. This @@ -24,6 +24,7 @@ # assignment operator '!=' is another unnecessary inconsistency. DIRECT= previous +# expect+1: warning: "echo output; false" returned non-zero status DIRECT!= echo output; false ASSIGNED= previous diff --git a/unit-tests/varmod-edge.exp b/unit-tests/varmod-edge.exp index d9db72b2e2ef..92204d8e1840 100644 --- a/unit-tests/varmod-edge.exp +++ b/unit-tests/varmod-edge.exp @@ -1,27 +1,27 @@ -make: "varmod-edge.mk" line 166: ok M-paren -make: "varmod-edge.mk" line 166: ok M-mixed -make: "varmod-edge.mk" line 166: ok M-unescape +make: "varmod-edge.mk" line 184: ok M-paren +make: "varmod-edge.mk" line 184: ok M-mixed +make: "varmod-edge.mk" line 184: ok M-unescape make: Unclosed variable expression, expecting '}' for modifier "U*)" of variable "" with value "*)" -make: "varmod-edge.mk" line 166: ok M-nest-mix -make: "varmod-edge.mk" line 166: ok M-nest-brk -make: "varmod-edge.mk" line 166: ok M-pat-err -make: "varmod-edge.mk" line 166: ok M-bsbs -make: "varmod-edge.mk" line 166: ok M-bs1-par -make: "varmod-edge.mk" line 166: ok M-bs2-par -make: "varmod-edge.mk" line 166: ok M-128 -make: "varmod-edge.mk" line 166: ok eq-ext -make: "varmod-edge.mk" line 166: ok eq-q -make: "varmod-edge.mk" line 166: ok eq-bs +make: "varmod-edge.mk" line 184: ok M-nest-mix +make: "varmod-edge.mk" line 184: ok M-nest-brk +make: "varmod-edge.mk" line 184: ok M-pat-err +make: "varmod-edge.mk" line 184: ok M-bsbs +make: "varmod-edge.mk" line 184: ok M-bs1-par +make: "varmod-edge.mk" line 184: ok M-bs2-par +make: "varmod-edge.mk" line 184: ok M-128 +make: "varmod-edge.mk" line 184: ok eq-ext +make: "varmod-edge.mk" line 184: ok eq-q +make: "varmod-edge.mk" line 184: ok eq-bs make: Unfinished modifier for "INP.eq-esc" ('=' missing) -make: "varmod-edge.mk" line 166: ok eq-esc -make: "varmod-edge.mk" line 166: ok colon -make: "varmod-edge.mk" line 165: Unknown modifier ":" -make: "varmod-edge.mk" line 165: Unknown modifier ":" -make: "varmod-edge.mk" line 166: ok colons -make: "varmod-edge.mk" line 175: Unknown modifier "Z" -make: "varmod-edge.mk" line 175: Malformed conditional (${:Z}) +make: "varmod-edge.mk" line 184: ok eq-esc +make: "varmod-edge.mk" line 184: ok colon +make: "varmod-edge.mk" line 167: Unknown modifier ":" +make: "varmod-edge.mk" line 167: Unknown modifier ":" +make: "varmod-edge.mk" line 184: ok colons +make: "varmod-edge.mk" line 195: Unknown modifier "Z" +make: "varmod-edge.mk" line 195: Malformed conditional (${:Z}) make: Unfinished modifier for "" (',' missing) -make: "varmod-edge.mk" line 188: Malformed conditional (${:S,}) +make: "varmod-edge.mk" line 209: Malformed conditional (${:S,}) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/varmod-edge.mk b/unit-tests/varmod-edge.mk index 762053d281a3..2d63b372e85e 100644 --- a/unit-tests/varmod-edge.mk +++ b/unit-tests/varmod-edge.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-edge.mk,v 1.16 2021/02/23 15:56:30 rillig Exp $ +# $NetBSD: varmod-edge.mk,v 1.17 2023/06/01 20:56:35 rillig Exp $ # # Tests for edge cases in variable modifiers. # @@ -162,7 +162,25 @@ MOD.colons= ${INP.colons::::} EXP.colons= # empty .for test in ${TESTS} +# expect+2: Unknown modifier ":" +# expect+1: Unknown modifier ":" . if ${MOD.${test}} == ${EXP.${test}} +# expect+16: ok M-paren +# expect+15: ok M-mixed +# expect+14: ok M-unescape +# expect+13: ok M-nest-mix +# expect+12: ok M-nest-brk +# expect+11: ok M-pat-err +# expect+10: ok M-bsbs +# expect+09: ok M-bs1-par +# expect+08: ok M-bs2-par +# expect+07: ok M-128 +# expect+06: ok eq-ext +# expect+05: ok eq-q +# expect+04: ok eq-bs +# expect+03: ok eq-esc +# expect+02: ok colon +# expect+01: ok colons . info ok ${test} . else . warning error in ${test}: expected "${EXP.${test}}", got "${MOD.${test}}" @@ -172,6 +190,8 @@ EXP.colons= # empty # Even in expressions based on an unnamed variable, there may be errors. # XXX: The error message should mention the variable name of the expression, # even though that name is empty in this case. +# expect+2: Malformed conditional (${:Z}) +# expect+1: Unknown modifier "Z" .if ${:Z} . error .else @@ -185,6 +205,7 @@ EXP.colons= # empty # modifier for (',' missing)", having two spaces in a row. # # XXX: The error message should report the filename:lineno. +# expect+1: Malformed conditional (${:S,}) .if ${:S,} . error .else diff --git a/unit-tests/varmod-gmtime.exp b/unit-tests/varmod-gmtime.exp index 916e471c462b..bbb8bd547bd5 100644 --- a/unit-tests/varmod-gmtime.exp +++ b/unit-tests/varmod-gmtime.exp @@ -1,13 +1,13 @@ -make: "varmod-gmtime.mk" line 59: Invalid time value "-1" -make: "varmod-gmtime.mk" line 59: Malformed conditional (${:L:gmtime=-1} != "") -make: "varmod-gmtime.mk" line 68: Invalid time value " 1" -make: "varmod-gmtime.mk" line 68: Malformed conditional (${:L:gmtime= 1} != "") -make: "varmod-gmtime.mk" line 114: Invalid time value "10000000000000000000000000000000" -make: "varmod-gmtime.mk" line 114: Malformed conditional (${:L:gmtime=10000000000000000000000000000000} != "") -make: "varmod-gmtime.mk" line 125: Invalid time value "error" -make: "varmod-gmtime.mk" line 125: Malformed conditional (${:L:gmtime=error} != "") -make: "varmod-gmtime.mk" line 134: Invalid time value "100000S,1970,bad," -make: "varmod-gmtime.mk" line 134: Malformed conditional (${%Y:L:gmtime=100000S,1970,bad,} != "bad") +make: "varmod-gmtime.mk" line 61: Invalid time value "-1" +make: "varmod-gmtime.mk" line 61: Malformed conditional (${:L:gmtime=-1} != "") +make: "varmod-gmtime.mk" line 72: Invalid time value " 1" +make: "varmod-gmtime.mk" line 72: Malformed conditional (${:L:gmtime= 1} != "") +make: "varmod-gmtime.mk" line 120: Invalid time value "10000000000000000000000000000000" +make: "varmod-gmtime.mk" line 120: Malformed conditional (${:L:gmtime=10000000000000000000000000000000} != "") +make: "varmod-gmtime.mk" line 133: Invalid time value "error" +make: "varmod-gmtime.mk" line 133: Malformed conditional (${:L:gmtime=error} != "") +make: "varmod-gmtime.mk" line 144: Invalid time value "100000S,1970,bad," +make: "varmod-gmtime.mk" line 144: Malformed conditional (${%Y:L:gmtime=100000S,1970,bad,} != "bad") make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/varmod-gmtime.mk b/unit-tests/varmod-gmtime.mk index 639c95b24f6b..9f68501fa128 100644 --- a/unit-tests/varmod-gmtime.mk +++ b/unit-tests/varmod-gmtime.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-gmtime.mk,v 1.14 2023/05/10 15:53:32 rillig Exp $ +# $NetBSD: varmod-gmtime.mk,v 1.15 2023/06/01 20:56:35 rillig Exp $ # # Tests for the :gmtime variable modifier, which formats a timestamp # using strftime(3) in UTC. @@ -56,6 +56,8 @@ # 1970. Going back 50 years in the past is not a practical use case for # make. Therefore, since var.c 1.631, negative time stamps produce a # parse error. +# expect+2: Invalid time value "-1" +# expect+1: Malformed conditional (${:L:gmtime=-1} != "") .if ${:L:gmtime=-1} != "" . error .else @@ -65,6 +67,8 @@ # Spaces were allowed before var.c 1.631 from 2020-10-31 21:40:20, not # because it would make sense but just as a side-effect from using strtoul. +# expect+2: Invalid time value " 1" +# expect+1: Malformed conditional (${:L:gmtime= 1} != "") .if ${:L:gmtime= 1} != "" . error .else @@ -111,6 +115,8 @@ # # Since var.c 1.631 from 2020-10-31, the overflow is detected and produces a # parse error. +# expect+2: Invalid time value "10000000000000000000000000000000" +# expect+1: Malformed conditional (${:L:gmtime=10000000000000000000000000000000} != "") .if ${:L:gmtime=10000000000000000000000000000000} != "" . error .else @@ -122,6 +128,8 @@ # stopped after the '=', and the remaining string was parsed for more variable # modifiers. Because of the unknown modifier 'e' from the 'error', the whole # variable value was discarded and thus not printed. +# expect+2: Invalid time value "error" +# expect+1: Malformed conditional (${:L:gmtime=error} != "") .if ${:L:gmtime=error} != "" . error .else @@ -131,6 +139,8 @@ # Before var.c 1.1050 from 2023-05-09, the timestamp could be directly # followed by the next modifier, without a ':' separator. This was the same # bug as for the ':L' and ':P' modifiers. +# expect+2: Invalid time value "100000S,1970,bad," +# expect+1: Malformed conditional (${%Y:L:gmtime=100000S,1970,bad,} != "bad") .if ${%Y:L:gmtime=100000S,1970,bad,} != "bad" . error .endif diff --git a/unit-tests/varmod-ifelse.exp b/unit-tests/varmod-ifelse.exp index 94cbcbdeae82..5b83ed49a759 100644 --- a/unit-tests/varmod-ifelse.exp +++ b/unit-tests/varmod-ifelse.exp @@ -1,32 +1,32 @@ make: Bad conditional expression 'variable expression == "literal"' in 'variable expression == "literal"?bad:bad' -make: "varmod-ifelse.mk" line 27: Malformed conditional (${${:Uvariable expression} == "literal":?bad:bad}) +make: "varmod-ifelse.mk" line 28: Malformed conditional (${${:Uvariable expression} == "literal":?bad:bad}) make: Bad conditional expression ' == ""' in ' == ""?bad-assign:bad-assign' make: Bad conditional expression ' == ""' in ' == ""?bad-cond:bad-cond' -make: "varmod-ifelse.mk" line 44: Malformed conditional (${${UNDEF} == "":?bad-cond:bad-cond}) +make: "varmod-ifelse.mk" line 46: Malformed conditional (${${UNDEF} == "":?bad-cond:bad-cond}) make: Bad conditional expression '1 == == 2' in '1 == == 2?yes:no' -make: "varmod-ifelse.mk" line 66: Malformed conditional (${1 == == 2:?yes:no} != "") +make: "varmod-ifelse.mk" line 69: Malformed conditional (${1 == == 2:?yes:no} != "") CondParser_Eval: "${1 == == 2:?yes:no}" != "" CondParser_Eval: 1 == == 2 Comparing 1.000000 == 0.000000 make: Bad conditional expression '1 == == 2' in '1 == == 2?yes:no' Comparing "" != "" -make: "varmod-ifelse.mk" line 92: warning: Oops, the parse error should have been propagated. +make: "varmod-ifelse.mk" line 96: warning: Oops, the parse error should have been propagated. CondParser_Eval: ${ ${:U\$}{VAR} == value:?ok:bad} != "ok" CondParser_Eval: ${VAR} == value Comparing "value" == "value" Comparing "ok" != "ok" -make: "varmod-ifelse.mk" line 153: no. -make: "varmod-ifelse.mk" line 154: Comparison with '>=' requires both operands 'no' and '10' to be numeric +make: "varmod-ifelse.mk" line 158: no. +make: "varmod-ifelse.mk" line 161: Comparison with '>=' requires both operands 'no' and '10' to be numeric make: Bad conditional expression 'string == "literal" || no >= 10' in 'string == "literal" || no >= 10?yes:no' -make: "varmod-ifelse.mk" line 154: . +make: "varmod-ifelse.mk" line 161: . make: Bad conditional expression 'string == "literal" && >= 10' in 'string == "literal" && >= 10?yes:no' -make: "varmod-ifelse.mk" line 159: . +make: "varmod-ifelse.mk" line 167: . make: Bad conditional expression 'string == "literal" || >= 10' in 'string == "literal" || >= 10?yes:no' -make: "varmod-ifelse.mk" line 160: . -make: "varmod-ifelse.mk" line 167: true -make: "varmod-ifelse.mk" line 169: false +make: "varmod-ifelse.mk" line 169: . +make: "varmod-ifelse.mk" line 177: true +make: "varmod-ifelse.mk" line 180: false make: Bad conditional expression ' ' in ' ?true:false' -make: "varmod-ifelse.mk" line 171: +make: "varmod-ifelse.mk" line 182: CondParser_Eval: 0 && ${1:?${:Uthen0:S,}},,}:${:Uelse0:S,}},,}} != "not evaluated" CondParser_Eval: 1 && ${0:?${:Uthen1:S,}},,}:${:Uelse1:S,}},,}} != "else1" CondParser_Eval: 0 diff --git a/unit-tests/varmod-ifelse.mk b/unit-tests/varmod-ifelse.mk index 0df45cae6870..1a71cab5c7a3 100644 --- a/unit-tests/varmod-ifelse.mk +++ b/unit-tests/varmod-ifelse.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-ifelse.mk,v 1.21 2023/02/18 18:23:58 rillig Exp $ +# $NetBSD: varmod-ifelse.mk,v 1.22 2023/06/01 20:56:35 rillig Exp $ # # Tests for the ${cond:?then:else} variable modifier, which evaluates either # the then-expression or the else-expression, depending on the condition. @@ -24,6 +24,7 @@ # Evaluating the variable name lazily would require additional code in # Var_Parse and ParseVarname, it would be more useful and predictable # though. +# expect+1: Malformed conditional (${${:Uvariable expression} == "literal":?bad:bad}) .if ${${:Uvariable expression} == "literal":?bad:bad} . error .else @@ -41,6 +42,7 @@ COND:= ${${UNDEF} == "":?bad-assign:bad-assign} # "Undefined variable" error message is generated. # The difference to the ':=' variable assignment is the additional # "Malformed conditional" error message. +# expect+1: Malformed conditional (${${UNDEF} == "":?bad-cond:bad-cond}) .if ${${UNDEF} == "":?bad-cond:bad-cond} . error .else @@ -63,6 +65,7 @@ COND:= ${${UNDEF} == "":?bad-assign:bad-assign} # conditional therefore returns a parse error from Var_Parse, and this parse # error propagates to CondEvalExpression, where the "Malformed conditional" # comes from. +# expect+1: Malformed conditional (${1 == == 2:?yes:no} != "") .if ${1 == == 2:?yes:no} != "" . error .else @@ -89,6 +92,7 @@ COND:= ${${UNDEF} == "":?bad-assign:bad-assign} .if "${1 == == 2:?yes:no}" != "" . error .else +# expect+1: warning: Oops, the parse error should have been propagated. . warning Oops, the parse error should have been propagated. .endif .MAKEFLAGS: -d0 @@ -150,13 +154,18 @@ VAR= value # instead of just saying that the whole condition is bad. STRING= string NUMBER= no # not really a number +# expect+1: no. .info ${${STRING} == "literal" && ${NUMBER} >= 10:?yes:no}. +# expect+2: . +# expect+1: Comparison with '>=' requires both operands 'no' and '10' to be numeric .info ${${STRING} == "literal" || ${NUMBER} >= 10:?yes:no}. # The following situation occasionally occurs with MKINET6 or similar # variables. NUMBER= # empty, not really a number either +# expect+1: . .info ${${STRING} == "literal" && ${NUMBER} >= 10:?yes:no}. +# expect+1: . .info ${${STRING} == "literal" || ${NUMBER} >= 10:?yes:no}. # CondParser_LeafToken handles [0-9-+] specially, treating them as a number. @@ -164,8 +173,10 @@ PLUS= + ASTERISK= * EMPTY= # empty # "true" since "+" is not the empty string. +# expect+1: true .info ${${PLUS} :?true:false} # "false" since the variable named "*" is not defined. +# expect+1: false .info ${${ASTERISK} :?true:false} # syntax error since the condition is completely blank. .info ${${EMPTY} :?true:false} diff --git a/unit-tests/varmod-indirect.exp b/unit-tests/varmod-indirect.exp index 46fa1af7a8cb..ecf52033ee4b 100644 --- a/unit-tests/varmod-indirect.exp +++ b/unit-tests/varmod-indirect.exp @@ -1,20 +1,20 @@ make: "varmod-indirect.mk" line 19: Unknown modifier "${" make: "varmod-indirect.mk" line 52: Unknown modifier "${" -make: "varmod-indirect.mk" line 53: warning: FIXME: this expression should have resulted in a parse error rather than returning the unparsed portion of the expression. -make: "varmod-indirect.mk" line 140: before -make: "varmod-indirect.mk" line 140: after -make: "varmod-indirect.mk" line 146: before -make: "varmod-indirect.mk" line 146: after -make: "varmod-indirect.mk" line 152: before -make: "varmod-indirect.mk" line 152: after -make: "varmod-indirect.mk" line 156: Unknown modifier "Z" -make: "varmod-indirect.mk" line 157: before -make: "varmod-indirect.mk" line 157: after -Parsing line 166: _:= before ${UNDEF} after +make: "varmod-indirect.mk" line 54: warning: FIXME: this expression should have resulted in a parse error rather than returning the unparsed portion of the expression. +make: "varmod-indirect.mk" line 143: before +make: "varmod-indirect.mk" line 143: after +make: "varmod-indirect.mk" line 151: before +make: "varmod-indirect.mk" line 151: after +make: "varmod-indirect.mk" line 159: before +make: "varmod-indirect.mk" line 159: after +make: "varmod-indirect.mk" line 164: Unknown modifier "Z" +make: "varmod-indirect.mk" line 167: before +make: "varmod-indirect.mk" line 167: after +Parsing line 176: _:= before ${UNDEF} after Global: _ = # (empty) Var_Parse: ${UNDEF} after (eval-keep-dollar-and-undefined) Global: _ = before ${UNDEF} after -Parsing line 169: _:= before ${UNDEF:${:US,a,a,}} after +Parsing line 179: _:= before ${UNDEF:${:US,a,a,}} after Var_Parse: ${UNDEF:${:US,a,a,}} after (eval-keep-dollar-and-undefined) Indirect modifier "S,a,a," from "${:US,a,a,}" Evaluating modifier ${UNDEF:S...} on value "" (eval-keep-dollar-and-undefined, undefined) @@ -23,18 +23,18 @@ Modifier part: "a" ModifyWords: split "" into 1 word Result of ${UNDEF:S,a,a,} is "" (eval-keep-dollar-and-undefined, undefined) Global: _ = before ${UNDEF:S,a,a,} after -Parsing line 179: _:= before ${UNDEF:${:U}} after +Parsing line 189: _:= before ${UNDEF:${:U}} after Var_Parse: ${UNDEF:${:U}} after (eval-keep-dollar-and-undefined) Indirect modifier "" from "${:U}" Global: _ = before ${UNDEF:} after -Parsing line 184: _:= before ${UNDEF:${:UZ}} after +Parsing line 195: _:= before ${UNDEF:${:UZ}} after Var_Parse: ${UNDEF:${:UZ}} after (eval-keep-dollar-and-undefined) Indirect modifier "Z" from "${:UZ}" Evaluating modifier ${UNDEF:Z} on value "" (eval-keep-dollar-and-undefined, undefined) -make: "varmod-indirect.mk" line 184: Unknown modifier "Z" +make: "varmod-indirect.mk" line 195: Unknown modifier "Z" Result of ${UNDEF:Z} is error (eval-keep-dollar-and-undefined, undefined) Global: _ = before ${UNDEF:Z} after -Parsing line 186: .MAKEFLAGS: -d0 +Parsing line 197: .MAKEFLAGS: -d0 ParseDependency(.MAKEFLAGS: -d0) Global: .MAKEFLAGS = -r -k -d 0 -d pv -d Global: .MAKEFLAGS = -r -k -d 0 -d pv -d 0 diff --git a/unit-tests/varmod-indirect.mk b/unit-tests/varmod-indirect.mk index 082efb035c74..f79f041cd1ea 100644 --- a/unit-tests/varmod-indirect.mk +++ b/unit-tests/varmod-indirect.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-indirect.mk,v 1.11 2022/01/15 12:35:18 rillig Exp $ +# $NetBSD: varmod-indirect.mk,v 1.12 2023/06/01 20:56:35 rillig Exp $ # # Tests for indirect variable modifiers, such as in ${VAR:${M_modifiers}}. # These can be used for very basic purposes like converting a string to either @@ -50,6 +50,7 @@ # expect+2: Unknown modifier "${" #.MAKEFLAGS: -dvc .if ${value:L:${:UM*}S,value,replaced,} == "M*S,value,replaced,}" +# expect+1: warning: FIXME: this expression should have resulted in a parse error rather than returning the unparsed portion of the expression. . warning FIXME: this expression should have resulted in a parse $\ error rather than returning the unparsed portion of the $\ expression. @@ -137,23 +138,32 @@ M_NoPrimes= ${PRIMES:${M_ListToSkip}} # An undefined expression without any modifiers expands to an empty string. .for var in before ${UNDEF} after +# expect+2: before +# expect+1: after . info ${var} .endfor # An undefined expression with only modifiers that keep the expression # undefined expands to an empty string. .for var in before ${UNDEF:${:US,a,a,}} after +# expect+2: before +# expect+1: after . info ${var} .endfor # Even in an indirect modifier based on an undefined variable, the value of # the expression in Var_Parse is a simple empty string. .for var in before ${UNDEF:${:U}} after +# expect+2: before +# expect+1: after . info ${var} .endfor # An error in an indirect modifier. +# expect+1: Unknown modifier "Z" .for var in before ${UNDEF:${:UZ}} after +# expect+2: before +# expect+1: after . info ${var} .endfor @@ -181,6 +191,7 @@ _:= before ${UNDEF:${:U}} after # XXX: This expands to ${UNDEF:Z}, which will behave differently if the # variable '_' is used in a context where the variable expression ${_} is # parsed but not evaluated. +# expect+1: Unknown modifier "Z" _:= before ${UNDEF:${:UZ}} after .MAKEFLAGS: -d0 diff --git a/unit-tests/varmod-localtime.exp b/unit-tests/varmod-localtime.exp index c734c234f083..a7c3ff6ab932 100644 --- a/unit-tests/varmod-localtime.exp +++ b/unit-tests/varmod-localtime.exp @@ -1,13 +1,13 @@ -make: "varmod-localtime.mk" line 59: Invalid time value "-1" -make: "varmod-localtime.mk" line 59: Malformed conditional (${:L:localtime=-1} != "") -make: "varmod-localtime.mk" line 68: Invalid time value " 1" -make: "varmod-localtime.mk" line 68: Malformed conditional (${:L:localtime= 1} != "") -make: "varmod-localtime.mk" line 114: Invalid time value "10000000000000000000000000000000" -make: "varmod-localtime.mk" line 114: Malformed conditional (${:L:localtime=10000000000000000000000000000000} != "") -make: "varmod-localtime.mk" line 125: Invalid time value "error" -make: "varmod-localtime.mk" line 125: Malformed conditional (${:L:localtime=error} != "") -make: "varmod-localtime.mk" line 134: Invalid time value "100000S,1970,bad," -make: "varmod-localtime.mk" line 134: Malformed conditional (${%Y:L:localtime=100000S,1970,bad,} != "bad") +make: "varmod-localtime.mk" line 61: Invalid time value "-1" +make: "varmod-localtime.mk" line 61: Malformed conditional (${:L:localtime=-1} != "") +make: "varmod-localtime.mk" line 72: Invalid time value " 1" +make: "varmod-localtime.mk" line 72: Malformed conditional (${:L:localtime= 1} != "") +make: "varmod-localtime.mk" line 120: Invalid time value "10000000000000000000000000000000" +make: "varmod-localtime.mk" line 120: Malformed conditional (${:L:localtime=10000000000000000000000000000000} != "") +make: "varmod-localtime.mk" line 133: Invalid time value "error" +make: "varmod-localtime.mk" line 133: Malformed conditional (${:L:localtime=error} != "") +make: "varmod-localtime.mk" line 144: Invalid time value "100000S,1970,bad," +make: "varmod-localtime.mk" line 144: Malformed conditional (${%Y:L:localtime=100000S,1970,bad,} != "bad") make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/varmod-localtime.mk b/unit-tests/varmod-localtime.mk index 7d66745aae8e..86f90064ded3 100644 --- a/unit-tests/varmod-localtime.mk +++ b/unit-tests/varmod-localtime.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-localtime.mk,v 1.12 2023/05/10 15:53:32 rillig Exp $ +# $NetBSD: varmod-localtime.mk,v 1.13 2023/06/01 20:56:35 rillig Exp $ # # Tests for the :localtime variable modifier, which formats a timestamp # using strftime(3) in local time. @@ -56,6 +56,8 @@ # 1970. Going back 50 years in the past is not a practical use case for # make. Therefore, since var.c 1.631, negative time stamps produce a # parse error. +# expect+2: Invalid time value "-1" +# expect+1: Malformed conditional (${:L:localtime=-1} != "") .if ${:L:localtime=-1} != "" . error .else @@ -65,6 +67,8 @@ # Spaces were allowed before var.c 1.631 from 2020-10-31 21:40:20, not # because it would make sense but just as a side-effect from using strtoul. +# expect+2: Invalid time value " 1" +# expect+1: Malformed conditional (${:L:localtime= 1} != "") .if ${:L:localtime= 1} != "" . error .else @@ -111,6 +115,8 @@ # # Since var.c 1.631 from 2020-10-31, the overflow is detected and produces a # parse error. +# expect+2: Invalid time value "10000000000000000000000000000000" +# expect+1: Malformed conditional (${:L:localtime=10000000000000000000000000000000} != "") .if ${:L:localtime=10000000000000000000000000000000} != "" . error .else @@ -122,6 +128,8 @@ # stopped after the '=', and the remaining string was parsed for more variable # modifiers. Because of the unknown modifier 'e' from the 'error', the whole # variable value was discarded and thus not printed. +# expect+2: Invalid time value "error" +# expect+1: Malformed conditional (${:L:localtime=error} != "") .if ${:L:localtime=error} != "" . error .else @@ -131,6 +139,8 @@ # Before var.c 1.1050 from 2023-05-09, the timestamp could be directly # followed by the next modifier, without a ':' separator. This was the same # bug as for the ':L' and ':P' modifiers. +# expect+2: Invalid time value "100000S,1970,bad," +# expect+1: Malformed conditional (${%Y:L:localtime=100000S,1970,bad,} != "bad") .if ${%Y:L:localtime=100000S,1970,bad,} != "bad" . error .endif diff --git a/unit-tests/varmod-loop-delete.exp b/unit-tests/varmod-loop-delete.exp index aac86ee39061..47a2f74545a3 100644 --- a/unit-tests/varmod-loop-delete.exp +++ b/unit-tests/varmod-loop-delete.exp @@ -1,4 +1,4 @@ -make: "varmod-loop-delete.mk" line 19: Cannot delete variable "VAR" while it is used +make: "varmod-loop-delete.mk" line 20: Cannot delete variable "VAR" while it is used make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/varmod-loop-delete.mk b/unit-tests/varmod-loop-delete.mk index ed145b59ba0f..1ec6d361949d 100644 --- a/unit-tests/varmod-loop-delete.mk +++ b/unit-tests/varmod-loop-delete.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-loop-delete.mk,v 1.2 2021/12/05 15:51:33 rillig Exp $ +# $NetBSD: varmod-loop-delete.mk,v 1.3 2023/06/01 20:56:35 rillig Exp $ # # Tests for the variable modifier ':@', which as a side effect allows to # delete an arbitrary variable. @@ -16,6 +16,7 @@ VAR= ${:U:@VAR@@} rest of the value # In an assignment, the scope is 'Global'. Since the variable 'VAR' is # defined in the global scope, it deletes itself. +# expect+1: Cannot delete variable "VAR" while it is used EVAL:= ${VAR} .if ${EVAL} != " rest of the value" . error diff --git a/unit-tests/varmod-loop-varname.exp b/unit-tests/varmod-loop-varname.exp index 4f0379d5ea0a..2060b51c31df 100644 --- a/unit-tests/varmod-loop-varname.exp +++ b/unit-tests/varmod-loop-varname.exp @@ -1,11 +1,11 @@ -make: "varmod-loop-varname.mk" line 16: In the :@ modifier of "", the variable name "${:Ubar:S,b,v,}" must not contain a dollar -make: "varmod-loop-varname.mk" line 16: Malformed conditional (${:Uone two three:@${:Ubar:S,b,v,}@+${var}+@} != "+one+ +two+ +three+") -make: "varmod-loop-varname.mk" line 85: In the :@ modifier of "1 2 3", the variable name "v$" must not contain a dollar -make: "varmod-loop-varname.mk" line 85: Malformed conditional (${1 2 3:L:@v$@($v)@} != "(1) (2) (3)") -make: "varmod-loop-varname.mk" line 90: In the :@ modifier of "1 2 3", the variable name "v$$" must not contain a dollar -make: "varmod-loop-varname.mk" line 90: Malformed conditional (${1 2 3:L:@v$$@($v)@} != "() () ()") -make: "varmod-loop-varname.mk" line 95: In the :@ modifier of "1 2 3", the variable name "v$$$" must not contain a dollar -make: "varmod-loop-varname.mk" line 95: Malformed conditional (${1 2 3:L:@v$$$@($v)@} != "() () ()") +make: "varmod-loop-varname.mk" line 18: In the :@ modifier of "", the variable name "${:Ubar:S,b,v,}" must not contain a dollar +make: "varmod-loop-varname.mk" line 18: Malformed conditional (${:Uone two three:@${:Ubar:S,b,v,}@+${var}+@} != "+one+ +two+ +three+") +make: "varmod-loop-varname.mk" line 89: In the :@ modifier of "1 2 3", the variable name "v$" must not contain a dollar +make: "varmod-loop-varname.mk" line 89: Malformed conditional (${1 2 3:L:@v$@($v)@} != "(1) (2) (3)") +make: "varmod-loop-varname.mk" line 96: In the :@ modifier of "1 2 3", the variable name "v$$" must not contain a dollar +make: "varmod-loop-varname.mk" line 96: Malformed conditional (${1 2 3:L:@v$$@($v)@} != "() () ()") +make: "varmod-loop-varname.mk" line 103: In the :@ modifier of "1 2 3", the variable name "v$$$" must not contain a dollar +make: "varmod-loop-varname.mk" line 103: Malformed conditional (${1 2 3:L:@v$$$@($v)@} != "() () ()") make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/varmod-loop-varname.mk b/unit-tests/varmod-loop-varname.mk index 91f8a4876466..43c72cee3ee5 100644 --- a/unit-tests/varmod-loop-varname.mk +++ b/unit-tests/varmod-loop-varname.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-loop-varname.mk,v 1.4 2021/12/05 15:01:04 rillig Exp $ +# $NetBSD: varmod-loop-varname.mk,v 1.5 2023/06/01 20:56:35 rillig Exp $ # # Tests for the first part of the variable modifier ':@var@...@', which # contains the variable name to use during the loop. @@ -13,6 +13,8 @@ # dynamically. There was no practical use-case for this. # Since var.c 1.907 from 2021-04-04, a '$' is no longer allowed in the # variable name. +# expect+2: In the :@ modifier of "", the variable name "${:Ubar:S,b,v,}" must not contain a dollar +# expect+1: Malformed conditional (${:Uone two three:@${:Ubar:S,b,v,}@+${var}+@} != "+one+ +two+ +three+") .if ${:Uone two three:@${:Ubar:S,b,v,}@+${var}+@} != "+one+ +two+ +three+" . error .else @@ -82,16 +84,22 @@ RES3= 3 # There's no point in allowing a dollar sign in that position. # Since var.c 1.907 from 2021-04-04, a '$' is no longer allowed in the # variable name. +# expect+2: In the :@ modifier of "1 2 3", the variable name "v$" must not contain a dollar +# expect+1: Malformed conditional (${1 2 3:L:@v$@($v)@} != "(1) (2) (3)") .if ${1 2 3:L:@v$@($v)@} != "(1) (2) (3)" . error .else . error .endif +# expect+2: In the :@ modifier of "1 2 3", the variable name "v$$" must not contain a dollar +# expect+1: Malformed conditional (${1 2 3:L:@v$$@($v)@} != "() () ()") .if ${1 2 3:L:@v$$@($v)@} != "() () ()" . error .else . error .endif +# expect+2: In the :@ modifier of "1 2 3", the variable name "v$$$" must not contain a dollar +# expect+1: Malformed conditional (${1 2 3:L:@v$$$@($v)@} != "() () ()") .if ${1 2 3:L:@v$$$@($v)@} != "() () ()" . error .else diff --git a/unit-tests/varmod-match-escape.exp b/unit-tests/varmod-match-escape.exp index 25cf6c0719d4..9a8f9ccf6082 100755 --- a/unit-tests/varmod-match-escape.exp +++ b/unit-tests/varmod-match-escape.exp @@ -30,10 +30,12 @@ Pattern for ':M' is ":\:" ModifyWords: split ": :: :\:" into 3 words Result of ${VALUES:M${:U\:}\:} is "::" Comparing ":" != "::" -make: "varmod-match-escape.mk" line 42: warning: XXX: Oops +make: "varmod-match-escape.mk" line 43: warning: XXX: Oops Global: .MAKEFLAGS = -r -k -d cv -d Global: .MAKEFLAGS = -r -k -d cv -d 0 -make: "varmod-match-escape.mk" line 67: Dollar followed by nothing +make: "varmod-match-escape.mk" line 69: Dollar followed by nothing +make: "varmod-match-escape.mk" line 110: warning: Unfinished character list in pattern '[A-]' of modifier ':M' +make: "varmod-match-escape.mk" line 110: warning: Unfinished character list in pattern '[^A-]' of modifier ':M' make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/varmod-match-escape.mk b/unit-tests/varmod-match-escape.mk index 5ac69f964a68..098a24dd9f72 100755 --- a/unit-tests/varmod-match-escape.mk +++ b/unit-tests/varmod-match-escape.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-match-escape.mk,v 1.7 2021/04/03 11:08:40 rillig Exp $ +# $NetBSD: varmod-match-escape.mk,v 1.10 2023/06/23 04:56:54 rillig Exp $ # # As of 2020-08-01, the :M and :N modifiers interpret backslashes differently, # depending on whether there was a variable expression somewhere before the @@ -39,6 +39,7 @@ SPECIALS= \: : \\ * \* # VALUES= : :: :\: .if ${VALUES:M\:${:U\:}} != ${VALUES:M${:U\:}\:} +# expect+1: warning: XXX: Oops . warning XXX: Oops .endif @@ -64,6 +65,7 @@ VALUES= : :: :\: # In lint mode, the case of a lonely '$' is covered with an error message. .MAKEFLAGS: -dL +# expect+1: Dollar followed by nothing .if ${:U\$:M\$} != "" . error .endif @@ -75,12 +77,41 @@ VALUES= : :: :\: # # TODO: Str_Match("a-z]", "[a-z]") # TODO: Str_Match("012", "[0-]]") -# TODO: Str_Match("0]", "[0-]]") -# TODO: Str_Match("1]", "[0-]]") # TODO: Str_Match("[", "[[]") # TODO: Str_Match("]", "[]") # TODO: Str_Match("]", "[[-]]") +# Demonstrate an inconsistency between positive and negative character lists +# when the range ends with the character ']'. +# +# 'A' begins the range, 'B' is in the middle of the range, ']' ends the range, +# 'a' is outside the range. +WORDS= A A] A]] B B] B]] ] ]] ]]] a a] a]] +# The ']' is part of the character range and at the same time ends the +# character list. +EXP.[A-]= A B ] +# The first ']' is part of the character range and at the same time ends the +# character list. +EXP.[A-]]= A] B] ]] +# The first ']' is part of the character range and at the same time ends the +# character list. +EXP.[A-]]]= A]] B]] ]]] +# For negative character lists, the ']' ends the character range but does not +# end the character list. +# XXX: This is unnecessarily inconsistent but irrelevant in practice as there +# is no practical need for a character range that ends at ']'. +EXP.[^A-]= a +EXP.[^A-]]= a +EXP.[^A-]]]= a] + +.for pattern in [A-] [A-]] [A-]]] [^A-] [^A-]] [^A-]]] +# expect+2: warning: Unfinished character list in pattern '[A-]' of modifier ':M' +# expect+1: warning: Unfinished character list in pattern '[^A-]' of modifier ':M' +. if ${WORDS:M${pattern}} != ${EXP.${pattern}} +. warning ${pattern}: ${WORDS:M${pattern}} != ${EXP.${pattern}} +. endif +.endfor + # In brackets, the backslash is just an ordinary character. # Outside brackets, it is an escape character for a few special characters. # TODO: Str_Match("\\", "[\\-]]") diff --git a/unit-tests/varmod-match.exp b/unit-tests/varmod-match.exp index 5bf3da46e524..4ac89bda8e0b 100644 --- a/unit-tests/varmod-match.exp +++ b/unit-tests/varmod-match.exp @@ -10,8 +10,16 @@ CondParser_Eval: ${:Ua \$ sign:M*$$*} != "\$" Comparing "$" != "$" CondParser_Eval: ${:Ua \$ sign any-asterisk:M*\$*} != "any-asterisk" Comparing "any-asterisk" != "any-asterisk" -make: "varmod-match.mk" line 157: Unknown modifier "]" -make: "varmod-match.mk" line 157: Malformed conditional (${ ${:U\:} ${:U\:\:} :L:M[:]} != ":") +make: "varmod-match.mk" line 162: warning: Unfinished character list in pattern '[' of modifier ':M' +make: "varmod-match.mk" line 162: Unknown modifier "]" +make: "varmod-match.mk" line 162: Malformed conditional (${ ${:U\:} ${:U\:\:} :L:M[:]} != ":") +make: "varmod-match.mk" line 205: warning: Unfinished character list in pattern 'a[' of modifier ':M' +make: "varmod-match.mk" line 213: warning: Unfinished character list in pattern 'a[^' of modifier ':M' +make: "varmod-match.mk" line 221: warning: Unfinished character list in pattern '[-x1-3' of modifier ':M' +make: "varmod-match.mk" line 229: warning: Unfinished character list in pattern '*[-x1-3' of modifier ':M' +make: "varmod-match.mk" line 238: warning: Unfinished character list in pattern '[^-x1-3' of modifier ':M' +make: "varmod-match.mk" line 258: warning: Unfinished character range in pattern '[x-' of modifier ':M' +make: "varmod-match.mk" line 270: warning: Unfinished character range in pattern '[^x-' of modifier ':M' make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/varmod-match.mk b/unit-tests/varmod-match.mk index 87928267d794..2804c2f2da4a 100644 --- a/unit-tests/varmod-match.mk +++ b/unit-tests/varmod-match.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-match.mk,v 1.12 2022/08/24 21:03:57 rillig Exp $ +# $NetBSD: varmod-match.mk,v 1.15 2023/06/23 04:56:54 rillig Exp $ # # Tests for the :M variable modifier, which filters words that match the # given pattern. @@ -33,8 +33,12 @@ NUMBERS= One Two Three Four five six seven .if ${:U****************:M****************b} .endif -# As of 2022-06-11, this expression calls Str_Match 5,242,223 times. -# Adding another '*?' to the pattern calls Str_Match 41,261,143 times. +# Before 2023-06-22, this expression called Str_Match 2,621,112 times. +# Adding another '*?' to the pattern called Str_Match 20,630,572 times. +# Adding another '*?' to the pattern called Str_Match 136,405,672 times. +# Adding another '*?' to the pattern called Str_Match 773,168,722 times. +# Adding another '*?' to the pattern called Str_Match 3,815,481,072 times. +# Since 2023-06-22, Str_Match no longer backtracks. .if ${:U..................................................b:M*?*?*?*?*?a} .endif @@ -152,6 +156,7 @@ WORDS= a\b a[\]b ab .endif # [:] matches never since the ':' starts the next modifier +# expect+3: warning: Unfinished character list in pattern '[' of modifier ':M' # expect+2: Unknown modifier "]" # expect+1: Malformed conditional (${ ${:U\:} ${:U\:\:} :L:M[:]} != ":") .if ${ ${:U\:} ${:U\:\:} :L:M[:]} != ":" @@ -196,6 +201,7 @@ WORDS= - -] # [ Incomplete empty character list, never matches. WORDS= a a[ +# expect+1: warning: Unfinished character list in pattern 'a[' of modifier ':M' .if ${WORDS:Ma[} != "" . error .endif @@ -203,6 +209,7 @@ WORDS= a a[ # [^ Incomplete negated empty character list, matches any single # character. WORDS= a a[ aX +# expect+1: warning: Unfinished character list in pattern 'a[^' of modifier ':M' .if ${WORDS:Ma[^} != "a[ aX" . error .endif @@ -210,14 +217,24 @@ WORDS= a a[ aX # [-x1-3 Incomplete character list, matches those elements that can be # parsed without lookahead. WORDS= - + x xx 0 1 2 3 4 [x1-3 +# expect+1: warning: Unfinished character list in pattern '[-x1-3' of modifier ':M' .if ${WORDS:M[-x1-3} != "- x 1 2 3" . error .endif +# *[-x1-3 Incomplete character list after a wildcard, matches those +# words that end with one of the characters from the list. +WORDS= - + x xx 0 1 2 3 4 00 01 10 11 000 001 010 011 100 101 110 111 [x1-3 +# expect+1: warning: Unfinished character list in pattern '*[-x1-3' of modifier ':M' +.if ${WORDS:M*[-x1-3} != "- x xx 1 2 3 01 11 001 011 101 111 [x1-3" +. warning ${WORDS:M*[-x1-3} +.endif + # [^-x1-3 # Incomplete negated character list, matches any character # except those elements that can be parsed without lookahead. WORDS= - + x xx 0 1 2 3 4 [x1-3 +# expect+1: warning: Unfinished character list in pattern '[^-x1-3' of modifier ':M' .if ${WORDS:M[^-x1-3} != "+ 0 4" . error .endif @@ -237,6 +254,7 @@ WORDS= \\ \a ${:Ux\\} # [x- Incomplete character list containing an incomplete character # range, matches only the 'x'. WORDS= [x- x x- y +# expect+1: warning: Unfinished character range in pattern '[x-' of modifier ':M' .if ${WORDS:M[x-} != "x" . error .endif @@ -248,6 +266,7 @@ WORDS= [x- x x- y # XXX: Even matches strings that are longer than a single # character. WORDS= [x- x x- y yyyyy +# expect+1: warning: Unfinished character range in pattern '[^x-' of modifier ':M' .if ${WORDS:M[^x-} != "[x- y yyyyy" . error .endif diff --git a/unit-tests/varmod-order.exp b/unit-tests/varmod-order.exp index e5d03f887fc7..487243a1678d 100644 --- a/unit-tests/varmod-order.exp +++ b/unit-tests/varmod-order.exp @@ -1,26 +1,26 @@ make: Bad modifier ":OX" for variable "WORDS" -make: "varmod-order.mk" line 14: Undefined variable "${WORDS:OX" +make: "varmod-order.mk" line 16: Undefined variable "${WORDS:OX" make: Bad modifier ":OxXX" for variable "WORDS" -make: "varmod-order.mk" line 17: Undefined variable "${WORDS:Ox" +make: "varmod-order.mk" line 21: Undefined variable "${WORDS:Ox" make: Unclosed variable expression, expecting '}' for modifier "O" of variable "WORDS" with value "eight five four nine one seven six ten three two" make: Unclosed variable expression, expecting '}' for modifier "On" of variable "NUMBERS" with value "1 2 3 4 5 6 7 8 9 10" make: Unclosed variable expression, expecting '}' for modifier "Onr" of variable "NUMBERS" with value "10 9 8 7 6 5 4 3 2 1" make: Bad modifier ":Oxn" for variable "NUMBERS" -make: "varmod-order.mk" line 29: Malformed conditional (${NUMBERS:Oxn}) +make: "varmod-order.mk" line 33: Malformed conditional (${NUMBERS:Oxn}) make: Bad modifier ":On_typo" for variable "NUMBERS" -make: "varmod-order.mk" line 39: Malformed conditional (${NUMBERS:On_typo}) +make: "varmod-order.mk" line 44: Malformed conditional (${NUMBERS:On_typo}) make: Bad modifier ":Onr_typo" for variable "NUMBERS" -make: "varmod-order.mk" line 48: Malformed conditional (${NUMBERS:Onr_typo}) +make: "varmod-order.mk" line 54: Malformed conditional (${NUMBERS:Onr_typo}) make: Bad modifier ":Orn_typo" for variable "NUMBERS" -make: "varmod-order.mk" line 57: Malformed conditional (${NUMBERS:Orn_typo}) +make: "varmod-order.mk" line 64: Malformed conditional (${NUMBERS:Orn_typo}) make: Bad modifier ":Onn" for variable "NUMBERS" -make: "varmod-order.mk" line 68: Malformed conditional (${NUMBERS:Onn}) +make: "varmod-order.mk" line 76: Malformed conditional (${NUMBERS:Onn}) make: Bad modifier ":Onrr" for variable "NUMBERS" -make: "varmod-order.mk" line 77: Malformed conditional (${NUMBERS:Onrr}) +make: "varmod-order.mk" line 86: Malformed conditional (${NUMBERS:Onrr}) make: Bad modifier ":Orrn" for variable "NUMBERS" -make: "varmod-order.mk" line 86: Malformed conditional (${NUMBERS:Orrn}) +make: "varmod-order.mk" line 96: Malformed conditional (${NUMBERS:Orrn}) make: Bad modifier ":On=Off" for variable "SWITCH" -make: "varmod-order.mk" line 100: Malformed conditional (${SWITCH:On=Off} != "Off") +make: "varmod-order.mk" line 111: Malformed conditional (${SWITCH:On=Off} != "Off") make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/varmod-order.mk b/unit-tests/varmod-order.mk index b4d5452263c7..67919543a93e 100644 --- a/unit-tests/varmod-order.mk +++ b/unit-tests/varmod-order.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-order.mk,v 1.10 2023/02/27 08:29:36 rillig Exp $ +# $NetBSD: varmod-order.mk,v 1.11 2023/06/01 20:56:35 rillig Exp $ # # Tests for the :O variable modifier and its variants, which either sort the # words of the value or shuffle them. @@ -11,9 +11,13 @@ NUMBERS= 8 5 4 9 1 7 6 10 3 2 # in English alphabetical order .endif # Unknown modifier "OX" +# FIXME: The error message is wrong. +# expect+1: Undefined variable "${WORDS:OX" _:= ${WORDS:OX} # Unknown modifier "OxXX" +# FIXME: The error message is wrong. +# expect+1: Undefined variable "${WORDS:Ox" _:= ${WORDS:OxXX} # Missing closing brace, to cover the error handling code. @@ -36,6 +40,7 @@ _:= ${NUMBERS:Onr # TODO: Add line number information to the "Bad modifier" diagnostic. # # expect: make: Bad modifier ":On_typo" for variable "NUMBERS" +# expect+1: Malformed conditional (${NUMBERS:On_typo}) .if ${NUMBERS:On_typo} . error .else @@ -45,6 +50,7 @@ _:= ${NUMBERS:Onr # Extra characters after ':Onr' are detected and diagnosed. # # expect: make: Bad modifier ":Onr_typo" for variable "NUMBERS" +# expect+1: Malformed conditional (${NUMBERS:Onr_typo}) .if ${NUMBERS:Onr_typo} . error .else @@ -54,6 +60,7 @@ _:= ${NUMBERS:Onr # Extra characters after ':Orn' are detected and diagnosed. # # expect: make: Bad modifier ":Orn_typo" for variable "NUMBERS" +# expect+1: Malformed conditional (${NUMBERS:Orn_typo}) .if ${NUMBERS:Orn_typo} . error .else @@ -65,6 +72,7 @@ _:= ${NUMBERS:Onr # not make sense. # # expect: make: Bad modifier ":Onn" for variable "NUMBERS" +# expect+1: Malformed conditional (${NUMBERS:Onn}) .if ${NUMBERS:Onn} . error .else @@ -74,6 +82,7 @@ _:= ${NUMBERS:Onr # Repeating the 'r' is not supported as well, for the same reasons as above. # # expect: make: Bad modifier ":Onrr" for variable "NUMBERS" +# expect+1: Malformed conditional (${NUMBERS:Onrr}) .if ${NUMBERS:Onrr} . error .else @@ -83,6 +92,7 @@ _:= ${NUMBERS:Onr # Repeating the 'r' is not supported as well, for the same reasons as above. # # expect: make: Bad modifier ":Orrn" for variable "NUMBERS" +# expect+1: Malformed conditional (${NUMBERS:Orrn}) .if ${NUMBERS:Orrn} . error .else @@ -97,6 +107,7 @@ _:= ${NUMBERS:Onr # There is no such fallback for the ':O' modifiers. SWITCH= On # expect: make: Bad modifier ":On=Off" for variable "SWITCH" +# expect+1: Malformed conditional (${SWITCH:On=Off} != "Off") .if ${SWITCH:On=Off} != "Off" . error .else diff --git a/unit-tests/varmod-range.exp b/unit-tests/varmod-range.exp index f4ada11ebde6..b6226ec82c5b 100644 --- a/unit-tests/varmod-range.exp +++ b/unit-tests/varmod-range.exp @@ -1,13 +1,13 @@ -make: "varmod-range.mk" line 53: Invalid number "x}Rest" != "Rest"" for ':range' modifier -make: "varmod-range.mk" line 53: Malformed conditional ("${:U:range=x}Rest" != "Rest") -make: "varmod-range.mk" line 62: Unknown modifier "x0" -make: "varmod-range.mk" line 62: Malformed conditional ("${:U:range=0x0}Rest" != "Rest") -make: "varmod-range.mk" line 78: Unknown modifier "rang" -make: "varmod-range.mk" line 78: Malformed conditional ("${a b c:L:rang}Rest" != "Rest") -make: "varmod-range.mk" line 85: Unknown modifier "rango" -make: "varmod-range.mk" line 85: Malformed conditional ("${a b c:L:rango}Rest" != "Rest") -make: "varmod-range.mk" line 92: Unknown modifier "ranger" -make: "varmod-range.mk" line 92: Malformed conditional ("${a b c:L:ranger}Rest" != "Rest") +make: "varmod-range.mk" line 55: Invalid number "x}Rest" != "Rest"" for ':range' modifier +make: "varmod-range.mk" line 55: Malformed conditional ("${:U:range=x}Rest" != "Rest") +make: "varmod-range.mk" line 66: Unknown modifier "x0" +make: "varmod-range.mk" line 66: Malformed conditional ("${:U:range=0x0}Rest" != "Rest") +make: "varmod-range.mk" line 84: Unknown modifier "rang" +make: "varmod-range.mk" line 84: Malformed conditional ("${a b c:L:rang}Rest" != "Rest") +make: "varmod-range.mk" line 93: Unknown modifier "rango" +make: "varmod-range.mk" line 93: Malformed conditional ("${a b c:L:rango}Rest" != "Rest") +make: "varmod-range.mk" line 102: Unknown modifier "ranger" +make: "varmod-range.mk" line 102: Malformed conditional ("${a b c:L:ranger}Rest" != "Rest") make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/varmod-range.mk b/unit-tests/varmod-range.mk index d63525248e58..86ef11a59eaf 100644 --- a/unit-tests/varmod-range.mk +++ b/unit-tests/varmod-range.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-range.mk,v 1.7 2020/11/01 14:36:25 rillig Exp $ +# $NetBSD: varmod-range.mk,v 1.8 2023/06/01 20:56:35 rillig Exp $ # # Tests for the :range variable modifier, which generates sequences # of integers from the given range. @@ -50,6 +50,8 @@ # # Since 2020-11-01, the parser issues a more precise "Invalid number" error # instead. +# expect+2: Invalid number "x}Rest" != "Rest"" for ':range' modifier +# expect+1: Malformed conditional ("${:U:range=x}Rest" != "Rest") .if "${:U:range=x}Rest" != "Rest" . error .else @@ -59,6 +61,8 @@ # The upper limit of the range must always be given in decimal. # This parse error stops at the 'x', trying to parse it as a variable # modifier. +# expect+2: Unknown modifier "x0" +# expect+1: Malformed conditional ("${:U:range=0x0}Rest" != "Rest") .if "${:U:range=0x0}Rest" != "Rest" . error .else @@ -75,6 +79,8 @@ #.endif # modifier name too short +# expect+2: Unknown modifier "rang" +# expect+1: Malformed conditional ("${a b c:L:rang}Rest" != "Rest") .if "${a b c:L:rang}Rest" != "Rest" . error .else @@ -82,6 +88,8 @@ .endif # misspelled modifier name +# expect+2: Unknown modifier "rango" +# expect+1: Malformed conditional ("${a b c:L:rango}Rest" != "Rest") .if "${a b c:L:rango}Rest" != "Rest" . error .else @@ -89,6 +97,8 @@ .endif # modifier name too long +# expect+2: Unknown modifier "ranger" +# expect+1: Malformed conditional ("${a b c:L:ranger}Rest" != "Rest") .if "${a b c:L:ranger}Rest" != "Rest" . error .else diff --git a/unit-tests/varmod-subst.mk b/unit-tests/varmod-subst.mk index 763535ff835a..0ddf2cfb2019 100644 --- a/unit-tests/varmod-subst.mk +++ b/unit-tests/varmod-subst.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-subst.mk,v 1.9 2021/09/06 21:18:55 rillig Exp $ +# $NetBSD: varmod-subst.mk,v 1.12 2023/06/16 07:20:45 rillig Exp $ # # Tests for the :S,from,to, variable modifier. @@ -9,83 +9,117 @@ all: mod-subst-dollar WORDS= sequences of letters +# The empty pattern never matches anything. .if ${WORDS:S,,,} != ${WORDS} -. warning The empty pattern matches something. +. error .endif +# The :S modifier flag '1' is applied exactly once. .if ${WORDS:S,e,*,1} != "s*quences of letters" -. warning The :S modifier flag '1' is not applied exactly once. +. error .endif +# The :S modifier flag '1' is applied to the first occurrence, no matter if +# the occurrence is in the first word or not. .if ${WORDS:S,f,*,1} != "sequences o* letters" -. warning The :S modifier flag '1' is only applied to the first word,\ - not to the first occurrence. +. error .endif +# The :S modifier replaces every first match per word. .if ${WORDS:S,e,*,} != "s*quences of l*tters" -. warning The :S modifier does not replace every first match per word. +. error .endif +# The :S modifier flag 'g' replaces every occurrence. .if ${WORDS:S,e,*,g} != "s*qu*nc*s of l*tt*rs" -. warning The :S modifier flag 'g' does not replace every occurrence. +. error .endif +# The '^' in the search pattern anchors the pattern at the beginning of each +# word, thereby matching a prefix. .if ${WORDS:S,^sequ,occurr,} != "occurrences of letters" -. warning The :S modifier fails for a short match anchored at the start. +. error .endif +# The :S modifier with a '^' anchor replaces the whole word if that word is +# exactly the pattern. .if ${WORDS:S,^of,with,} != "sequences with letters" -. warning The :S modifier fails for an exact match anchored at the start. +. error .endif +# The :S modifier does not match if the pattern is longer than the word. .if ${WORDS:S,^office,does not match,} != ${WORDS} -. warning The :S modifier matches a too long pattern anchored at the start. +. warning .endif +# The '$' in the search pattern anchors the pattern at the end of each word, +# thereby matching a suffix. .if ${WORDS:S,f$,r,} != "sequences or letters" -. warning The :S modifier fails for a short match anchored at the end. +. error .endif +# The :S modifier with a '$' anchor replaces at most one occurrence per word. .if ${WORDS:S,s$,,} != "sequence of letter" -. warning The :S modifier fails to replace one occurrence per word. +. error .endif +# The :S modifier with a '$' anchor replaces the whole word if that word is +# exactly the pattern. .if ${WORDS:S,of$,,} != "sequences letters" -. warning The :S modifier fails for an exact match anchored at the end. +. error .endif +# The :S modifier with a '$' anchor and a pattern that is longer than a word +# cannot match that word. .if ${WORDS:S,eof$,,} != ${WORDS} -. warning The :S modifier matches a too long pattern anchored at the end. +. warning .endif +# The :S modifier with the '^' and '$' anchors matches an exact word. .if ${WORDS:S,^of$,,} != "sequences letters" -. warning The :S modifier does not match a word anchored at both ends. +. error .endif +# The :S modifier with the '^' and '$' anchors does not match a word that +# starts with the pattern but is longer than the pattern. .if ${WORDS:S,^o$,,} != ${WORDS} -. warning The :S modifier matches a prefix anchored at both ends. +. error .endif +# The :S modifier with the '^' and '$' anchors does not match a word that ends +# with the pattern but is longer than the pattern. .if ${WORDS:S,^f$,,} != ${WORDS} -. warning The :S modifier matches a suffix anchored at both ends. +. error .endif +# The :S modifier with the '^' and '$' anchors does not match a word if the +# pattern ends with the word but is longer than the word. .if ${WORDS:S,^eof$,,} != ${WORDS} -. warning The :S modifier matches a too long prefix anchored at both ends. +. error .endif +# The :S modifier with the '^' and '$' anchors does not match a word if the +# pattern starts with the word but is longer than the word. .if ${WORDS:S,^office$,,} != ${WORDS} -. warning The :S modifier matches a too long suffix anchored at both ends. +. error .endif +# Except for the '^' and '$' anchors, the pattern does not contain any special +# characters, so the '*' from the pattern would only match a literal '*' in a +# word. .if ${WORDS:S,*,replacement,} != ${WORDS} -. error The '*' seems to be interpreted as a wildcard of some kind. +. error .endif +# Except for the '^' and '$' anchors, the pattern does not contain any special +# characters, so the '.' from the pattern would only match a literal '.' in a +# word. .if ${WORDS:S,.,replacement,} != ${WORDS} -. error The '.' seems to be interpreted as a wildcard of some kind. +. error .endif +# The '&' in the replacement is a placeholder for the text matched by the +# pattern. .if ${:Uvalue:S,^val,&,} != "value" . error .endif @@ -99,6 +133,14 @@ WORDS= sequences of letters . error .endif + +# When a word is replaced with nothing, the remaining words are separated by a +# single space, not two. +.if ${1 2 3:L:S,2,,} != "1 3" +. error +.endif + + mod-subst: @echo $@: @echo :${:Ua b b c:S,a b,,:Q}: diff --git a/unit-tests/varmod-sysv.exp b/unit-tests/varmod-sysv.exp index 59275857f98a..6a3728c3c0fc 100644 --- a/unit-tests/varmod-sysv.exp +++ b/unit-tests/varmod-sysv.exp @@ -1,5 +1,5 @@ make: Unfinished modifier for "word214" ('=' missing) -make: "varmod-sysv.mk" line 214: Malformed conditional (${word214:L:from${:D=}to}) +make: "varmod-sysv.mk" line 215: Malformed conditional (${word214:L:from${:D=}to}) word modifier result '' = "" suffix = "suffix" diff --git a/unit-tests/varmod-sysv.mk b/unit-tests/varmod-sysv.mk index 712c1731717b..78651ea869dc 100644 --- a/unit-tests/varmod-sysv.mk +++ b/unit-tests/varmod-sysv.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-sysv.mk,v 1.14 2021/04/12 16:09:57 rillig Exp $ +# $NetBSD: varmod-sysv.mk,v 1.15 2023/06/01 20:56:35 rillig Exp $ # # Tests for the variable modifier ':from=to', which replaces the suffix # "from" with "to". It can also use '%' as a wildcard. @@ -211,6 +211,7 @@ # XXX: As of 2020-12-05, this expression generates an "Unfinished modifier" # error, while the correct error message would be "Unknown modifier" since # there is no modifier named "fromto". +# expect+1: Malformed conditional (${word214:L:from${:D=}to}) .if ${word214:L:from${:D=}to} . error .endif diff --git a/unit-tests/varmod-to-abs.exp b/unit-tests/varmod-to-abs.exp index 426b4d39744f..4506d5ea8175 100644 --- a/unit-tests/varmod-to-abs.exp +++ b/unit-tests/varmod-to-abs.exp @@ -1,5 +1,5 @@ -make: "varmod-to-abs.mk" line 18: does-not-exist.c make: "varmod-to-abs.mk" line 19: does-not-exist.c +make: "varmod-to-abs.mk" line 21: does-not-exist.c cached_realpath: varmod-to-abs.mk -> varmod-to-abs.mk -make: "varmod-to-abs.mk" line 23: varmod-to-abs.mk +make: "varmod-to-abs.mk" line 26: varmod-to-abs.mk exit status 0 diff --git a/unit-tests/varmod-to-abs.mk b/unit-tests/varmod-to-abs.mk index 7f23318487e3..bc4722068988 100644 --- a/unit-tests/varmod-to-abs.mk +++ b/unit-tests/varmod-to-abs.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-to-abs.mk,v 1.5 2020/11/15 05:48:17 rillig Exp $ +# $NetBSD: varmod-to-abs.mk,v 1.6 2023/06/01 20:56:35 rillig Exp $ # # Tests for the :tA variable modifier, which returns the absolute path for # each of the words in the variable value. @@ -15,11 +15,14 @@ # keeping the cache, just like the GNode for global variables. .MAKEFLAGS: -dd does-not-exist.c= /dev/null +# expect+1: does-not-exist.c .info ${does-not-exist.c:L:tA} +# expect+1: does-not-exist.c .info ${does-not-exist.c:L:tA} # The output of the following line is modified by the global _SED_CMDS in # unit-tests/Makefile. See the .rawout file for the truth. +# expect+1: varmod-to-abs.mk .info ${MAKEFILE:tA} .MAKEFLAGS: -d0 diff --git a/unit-tests/varmod-to-separator.exp b/unit-tests/varmod-to-separator.exp index bfcfa3ebc103..a7d4ddb20147 100644 --- a/unit-tests/varmod-to-separator.exp +++ b/unit-tests/varmod-to-separator.exp @@ -1,25 +1,25 @@ -make: "varmod-to-separator.mk" line 153: Invalid character number at "400:tu}" -make: "varmod-to-separator.mk" line 153: Malformed conditional (${WORDS:[1..3]:ts\400:tu}) -make: "varmod-to-separator.mk" line 167: Invalid character number at "100:tu}" -make: "varmod-to-separator.mk" line 167: Malformed conditional (${WORDS:[1..3]:ts\x100:tu}) +make: "varmod-to-separator.mk" line 155: Invalid character number at "400:tu}" +make: "varmod-to-separator.mk" line 155: Malformed conditional (${WORDS:[1..3]:ts\400:tu}) +make: "varmod-to-separator.mk" line 171: Invalid character number at "100:tu}" +make: "varmod-to-separator.mk" line 171: Malformed conditional (${WORDS:[1..3]:ts\x100:tu}) make: Bad modifier ":ts\-300" for variable "WORDS" -make: "varmod-to-separator.mk" line 174: Malformed conditional (${WORDS:[1..3]:ts\-300:tu}) +make: "varmod-to-separator.mk" line 179: Malformed conditional (${WORDS:[1..3]:ts\-300:tu}) make: Bad modifier ":ts\8" for variable "1 2 3" -make: "varmod-to-separator.mk" line 182: Malformed conditional (${1 2 3:L:ts\8:tu}) +make: "varmod-to-separator.mk" line 188: Malformed conditional (${1 2 3:L:ts\8:tu}) make: Bad modifier ":ts\100L" for variable "1 2 3" -make: "varmod-to-separator.mk" line 189: Malformed conditional (${1 2 3:L:ts\100L}) +make: "varmod-to-separator.mk" line 196: Malformed conditional (${1 2 3:L:ts\100L}) make: Bad modifier ":ts\x40g" for variable "1 2 3" -make: "varmod-to-separator.mk" line 196: Malformed conditional (${1 2 3:L:ts\x40g}) +make: "varmod-to-separator.mk" line 204: Malformed conditional (${1 2 3:L:ts\x40g}) make: Bad modifier ":tx" for variable "WORDS" -make: "varmod-to-separator.mk" line 205: Malformed conditional (${WORDS:tx}) +make: "varmod-to-separator.mk" line 214: Malformed conditional (${WORDS:tx}) make: Bad modifier ":ts\X" for variable "WORDS" -make: "varmod-to-separator.mk" line 213: Malformed conditional (${WORDS:ts\X}) +make: "varmod-to-separator.mk" line 223: Malformed conditional (${WORDS:ts\X}) make: Bad modifier ":t\X" for variable "WORDS" -make: "varmod-to-separator.mk" line 221: Malformed conditional (${WORDS:t\X} != "anything") +make: "varmod-to-separator.mk" line 232: Malformed conditional (${WORDS:t\X} != "anything") make: Bad modifier ":ts\69" for variable "" -make: "varmod-to-separator.mk" line 237: Malformed conditional (${:Ua b:ts\69}) -make: "varmod-to-separator.mk" line 246: Invalid character number at "1F60E}" -make: "varmod-to-separator.mk" line 246: Malformed conditional (${:Ua b:ts\x1F60E}) +make: "varmod-to-separator.mk" line 249: Malformed conditional (${:Ua b:ts\69}) +make: "varmod-to-separator.mk" line 258: Invalid character number at "1F60E}" +make: "varmod-to-separator.mk" line 258: Malformed conditional (${:Ua b:ts\x1F60E}) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/varmod-to-separator.mk b/unit-tests/varmod-to-separator.mk index bf960639f831..f17dece447a9 100644 --- a/unit-tests/varmod-to-separator.mk +++ b/unit-tests/varmod-to-separator.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-to-separator.mk,v 1.11 2022/02/09 21:09:24 rillig Exp $ +# $NetBSD: varmod-to-separator.mk,v 1.12 2023/06/01 20:56:35 rillig Exp $ # # Tests for the :ts variable modifier, which joins the words of the variable # using an arbitrary character as word separator. @@ -150,6 +150,8 @@ WORDS= one two three four five six # for an unsigned character though. # # Since 2020-11-01, these out-of-bounds values are rejected. +# expect+2: Invalid character number at "400:tu}" +# expect+1: Malformed conditional (${WORDS:[1..3]:ts\400:tu}) .if ${WORDS:[1..3]:ts\400:tu} . warning The separator \400 is accepted even though it is out of bounds. .else @@ -164,6 +166,8 @@ WORDS= one two three four five six # The hexadecimal number must be in the range of an unsigned char. # # Since 2020-11-01, these out-of-bounds values are rejected. +# expect+2: Invalid character number at "100:tu}" +# expect+1: Malformed conditional (${WORDS:[1..3]:ts\x100:tu}) .if ${WORDS:[1..3]:ts\x100:tu} . warning The separator \x100 is accepted even though it is out of bounds. .else @@ -171,6 +175,7 @@ WORDS= one two three four five six .endif # Negative numbers are not allowed for the separator character. +# expect+1: Malformed conditional (${WORDS:[1..3]:ts\-300:tu}) .if ${WORDS:[1..3]:ts\-300:tu} . warning The separator \-300 is accepted even though it is negative. .else @@ -179,6 +184,7 @@ WORDS= one two three four five six # The character number is interpreted as octal number by default. # The digit '8' is not an octal digit though. +# expect+1: Malformed conditional (${1 2 3:L:ts\8:tu}) .if ${1 2 3:L:ts\8:tu} . warning The separator \8 is accepted even though it is not octal. .else @@ -186,6 +192,7 @@ WORDS= one two three four five six .endif # Trailing characters after the octal character number are rejected. +# expect+1: Malformed conditional (${1 2 3:L:ts\100L}) .if ${1 2 3:L:ts\100L} . warning The separator \100L is accepted even though it contains an 'L'. .else @@ -193,6 +200,7 @@ WORDS= one two three four five six .endif # Trailing characters after the hexadecimal character number are rejected. +# expect+1: Malformed conditional (${1 2 3:L:ts\x40g}) .if ${1 2 3:L:ts\x40g} . warning The separator \x40g is accepted even though it contains a 'g'. .else @@ -202,6 +210,7 @@ WORDS= one two three four five six # In the :t modifier, the :t must be followed by any of A, l, s, u. # expect: make: Bad modifier ":tx" for variable "WORDS" +# expect+1: Malformed conditional (${WORDS:tx}) .if ${WORDS:tx} . error .else @@ -210,6 +219,7 @@ WORDS= one two three four five six # The word separator can only be a single character. # expect: make: Bad modifier ":ts\X" for variable "WORDS" +# expect+1: Malformed conditional (${WORDS:ts\X}) .if ${WORDS:ts\X} . error .else @@ -218,6 +228,7 @@ WORDS= one two three four five six # After the backslash, only n, t, an octal number, or x and a hexadecimal # number are allowed. +# expect+1: Malformed conditional (${WORDS:t\X} != "anything") .if ${WORDS:t\X} != "anything" . info This line is not reached. .endif @@ -234,6 +245,7 @@ WORDS= one two three four five six # 2016.02.27.16.20.06, the result was '1E2', since 2016.03.07.20.20.35 make no # longer accepts this escape and complains. # expect: make: Bad modifier ":ts\69" for variable "" +# expect+1: Malformed conditional (${:Ua b:ts\69}) .if ${:Ua b:ts\69} . error .else diff --git a/unit-tests/varmod.exp b/unit-tests/varmod.exp index 3e588dc4d83f..19577fa495c7 100644 --- a/unit-tests/varmod.exp +++ b/unit-tests/varmod.exp @@ -1,8 +1,8 @@ -make: "varmod.mk" line 96: To escape a dollar, use \$, not $$, at "$$:L} != """ -make: "varmod.mk" line 96: Invalid variable name ':', at "$:L} != """ -make: "varmod.mk" line 101: Dollar followed by nothing -make: "varmod.mk" line 110: Missing delimiter ':' after modifier "P" -make: "varmod.mk" line 111: Missing argument for ".error" +make: "varmod.mk" line 98: To escape a dollar, use \$, not $$, at "$$:L} != """ +make: "varmod.mk" line 98: Invalid variable name ':', at "$:L} != """ +make: "varmod.mk" line 104: Dollar followed by nothing +make: "varmod.mk" line 114: Missing delimiter ':' after modifier "P" +make: "varmod.mk" line 116: Missing argument for ".error" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/varmod.mk b/unit-tests/varmod.mk index 17bc1e6e3ae3..2ed2f6ee7cea 100644 --- a/unit-tests/varmod.mk +++ b/unit-tests/varmod.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod.mk,v 1.7 2022/08/24 21:38:06 rillig Exp $ +# $NetBSD: varmod.mk,v 1.8 2023/06/01 20:56:35 rillig Exp $ # # Tests for variable modifiers, such as :Q, :S,from,to or :Ufallback. # @@ -93,11 +93,14 @@ DOLLAR2= ${:U\$} # For compatibility, make does not print these error messages in normal mode. # Should it? .MAKEFLAGS: -dL +# expect+2: To escape a dollar, use \$, not $$, at "$$:L} != """ +# expect+1: Invalid variable name ':', at "$:L} != """ .if ${$$:L} != "" . error .endif # A '$' followed by nothing is an error as well. +# expect+1: Dollar followed by nothing .if ${:Uword:@word@${word}$@} != "word" . error .endif @@ -107,7 +110,9 @@ DOLLAR2= ${:U\$} # XXX: The .error should not be reached since the variable expression is # malformed, and this error should be propagated up to Cond_EvalLine. VAR= STOP +# expect+1: Missing delimiter ':' after modifier "P" .if ${VAR:P=RE} != "STORE" +# expect+1: Missing argument for ".error" . error .endif diff --git a/unit-tests/varname-dollar.exp b/unit-tests/varname-dollar.exp index c880e82f0170..4f7c2ebbdf12 100644 --- a/unit-tests/varname-dollar.exp +++ b/unit-tests/varname-dollar.exp @@ -1,5 +1,5 @@ -make: "varname-dollar.mk" line 16: dollar is $. -make: "varname-dollar.mk" line 17: dollar in braces is . -make: "varname-dollar.mk" line 25: dollar is $. -make: "varname-dollar.mk" line 26: dollar in braces is dollar. +make: "varname-dollar.mk" line 17: dollar is $. +make: "varname-dollar.mk" line 19: dollar in braces is . +make: "varname-dollar.mk" line 28: dollar is $. +make: "varname-dollar.mk" line 30: dollar in braces is dollar. exit status 0 diff --git a/unit-tests/varname-dollar.mk b/unit-tests/varname-dollar.mk index d1db9f833306..e60c9dd43e8f 100644 --- a/unit-tests/varname-dollar.mk +++ b/unit-tests/varname-dollar.mk @@ -1,4 +1,4 @@ -# $NetBSD: varname-dollar.mk,v 1.3 2020/08/19 05:40:06 rillig Exp $ +# $NetBSD: varname-dollar.mk,v 1.4 2023/06/01 20:56:35 rillig Exp $ # # Tests for the expression "$$", which looks as if it referred to a variable, # but simply expands to a single '$' sign. @@ -13,7 +13,9 @@ DOLLAR= $$ # At this point, the variable '$' is not defined. Therefore the second line # returns an empty string. +# expect+1: dollar is $. .info dollar is $$. +# expect+1: dollar in braces is . .info dollar in braces is ${${DOLLAR}}. # Now overwrite the '$' variable to see whether '$$' really expands to that @@ -22,7 +24,9 @@ ${DOLLAR}= dollar # At this point, the variable '$' is defined, therefore its value is printed # in the second .info directive. +# expect+1: dollar is $. .info dollar is $$. +# expect+1: dollar in braces is dollar. .info dollar in braces is ${${DOLLAR}}. all: diff --git a/unit-tests/varname-dot-makeflags.exp b/unit-tests/varname-dot-makeflags.exp index 28cc64fd66c8..8004ab40a363 100644 --- a/unit-tests/varname-dot-makeflags.exp +++ b/unit-tests/varname-dot-makeflags.exp @@ -1,9 +1,9 @@ -make: "varname-dot-makeflags.mk" line 10: MAKEFLAGS= -make: "varname-dot-makeflags.mk" line 11: .MAKEFLAGS=< -r -k> -make: "varname-dot-makeflags.mk" line 12: .MAKEOVERRIDES=<> -make: "varname-dot-makeflags.mk" line 18: MAKEFLAGS= -make: "varname-dot-makeflags.mk" line 20: .MAKEFLAGS=< -r -k -D VARNAME -r> -make: "varname-dot-makeflags.mk" line 22: .MAKEOVERRIDES=< VAR> +make: "varname-dot-makeflags.mk" line 11: MAKEFLAGS= +make: "varname-dot-makeflags.mk" line 13: .MAKEFLAGS=< -r -k> +make: "varname-dot-makeflags.mk" line 15: .MAKEOVERRIDES=<> +make: "varname-dot-makeflags.mk" line 21: MAKEFLAGS= +make: "varname-dot-makeflags.mk" line 23: .MAKEFLAGS=< -r -k -D VARNAME -r> +make: "varname-dot-makeflags.mk" line 25: .MAKEOVERRIDES=< VAR> runtime: MAKEFLAGS=< -r -k -D VARNAME -r VAR=value> runtime: .MAKEFLAGS=< -r -k -D VARNAME -r> runtime: .MAKEOVERRIDES=< VAR> diff --git a/unit-tests/varname-dot-makeflags.mk b/unit-tests/varname-dot-makeflags.mk index cca285f93013..ffb09decb70e 100644 --- a/unit-tests/varname-dot-makeflags.mk +++ b/unit-tests/varname-dot-makeflags.mk @@ -1,4 +1,4 @@ -# $NetBSD: varname-dot-makeflags.mk,v 1.7 2023/02/25 19:24:07 rillig Exp $ +# $NetBSD: varname-dot-makeflags.mk,v 1.8 2023/06/01 20:56:35 rillig Exp $ # # Tests for the special .MAKEFLAGS variable, which collects almost all # command line arguments and passes them on to any child processes via @@ -7,8 +7,11 @@ # See also: # varname-dot-makeoverrides.mk +# expect+1: MAKEFLAGS= .info MAKEFLAGS=<${MAKEFLAGS:Uundefined}> +# expect+1: .MAKEFLAGS=< -r -k> .info .MAKEFLAGS=<${.MAKEFLAGS}> +# expect+1: .MAKEOVERRIDES=<> .info .MAKEOVERRIDES=<${.MAKEOVERRIDES:Uundefined}> # Append an option with argument, a plain option and a variable assignment. diff --git a/unit-tests/varname-dot-parsedir.exp b/unit-tests/varname-dot-parsedir.exp index c0bc56f41d6e..4ac953c813cd 100644 --- a/unit-tests/varname-dot-parsedir.exp +++ b/unit-tests/varname-dot-parsedir.exp @@ -1,5 +1,5 @@ -make: "varname-dot-parsedir.mk" line 28: At this point, .PARSEDIR is undefined. -make: "" line 34: The location can be faked in some cases. -make: "varname-dot-parsedir.mk" line 38: The location is no longer fake. +make: "varname-dot-parsedir.mk" line 37: At this point, .PARSEDIR is undefined. +make: "" line 43: The location can be faked in some cases. +make: "varname-dot-parsedir.mk" line 48: The location is no longer fake. At run time, .PARSEDIR is undefined. exit status 0 diff --git a/unit-tests/varname-dot-parsedir.mk b/unit-tests/varname-dot-parsedir.mk index 7c74419ddd10..525fdbd5636f 100644 --- a/unit-tests/varname-dot-parsedir.mk +++ b/unit-tests/varname-dot-parsedir.mk @@ -1,7 +1,15 @@ -# $NetBSD: varname-dot-parsedir.mk,v 1.6 2020/10/24 08:50:17 rillig Exp $ +# $NetBSD: varname-dot-parsedir.mk,v 1.8 2023/06/21 07:30:50 rillig Exp $ # # Tests for the special .PARSEDIR variable, which contains the directory part # of the file that is currently parsed. +# +# See also +# varname-dot-includedfromdir.mk +# varname-dot-includedfromfile.mk +# varname-dot-parsefile.mk +# +# History +# .PARSEDIR and .PARSEFILE were added on 1999-08-09. # The .PARSEDIR may be absolute or relative, therefore there is not much that # can be tested here. @@ -25,6 +33,7 @@ # # The .rawout file contains the full path to the current directory. # In the .out file, it is filtered out. +# expect+1: At this point, .PARSEDIR is undefined. .info At this point, .PARSEDIR is undefined. # There is absolutely no point in faking the location of the file that is @@ -35,6 +44,7 @@ # After including another file, .PARSEDIR is reset. .include "/dev/null" +# expect+1: The location is no longer fake. .info The location is no longer fake. all: diff --git a/unit-tests/varname-dot-parsefile.exp b/unit-tests/varname-dot-parsefile.exp index b61f01c01ab7..651666ebcf24 100644 --- a/unit-tests/varname-dot-parsefile.exp +++ b/unit-tests/varname-dot-parsefile.exp @@ -1,5 +1,5 @@ -make: "varname-dot-parsefile.mk" line 23: At this point, .PARSEFILE is undefined. -make: "" line 29: The location can be faked in some cases. -make: "varname-dot-parsefile.mk" line 33: The location is no longer fake. +make: "varname-dot-parsefile.mk" line 32: At this point, .PARSEFILE is undefined. +make: "" line 38: The location can be faked in some cases. +make: "varname-dot-parsefile.mk" line 43: The location is no longer fake. At run time, .PARSEFILE is undefined. exit status 0 diff --git a/unit-tests/varname-dot-parsefile.mk b/unit-tests/varname-dot-parsefile.mk index 17b48a5f77ec..0a6ed3c378e0 100644 --- a/unit-tests/varname-dot-parsefile.mk +++ b/unit-tests/varname-dot-parsefile.mk @@ -1,7 +1,15 @@ -# $NetBSD: varname-dot-parsefile.mk,v 1.5 2020/10/24 08:50:17 rillig Exp $ +# $NetBSD: varname-dot-parsefile.mk,v 1.7 2023/06/21 07:30:50 rillig Exp $ # # Tests for the special .PARSEFILE variable, which contains the basename part # of the file that is currently parsed. +# +# See also +# varname-dot-includedfromdir.mk +# varname-dot-includedfromfile.mk +# varname-dot-parsedir.mk +# +# History +# .PARSEDIR and .PARSEFILE were added on 1999-08-09. .if ${.PARSEFILE} != "varname-dot-parsefile.mk" . error @@ -20,6 +28,7 @@ # The variable .PARSEFILE is indirectly used by the .info directive, # via PrintLocation. +# expect+1: At this point, .PARSEFILE is undefined. .info At this point, .PARSEFILE is undefined. # There is absolutely no point in faking the location of the file that is @@ -30,6 +39,7 @@ # After including another file, .PARSEFILE is reset. .include "/dev/null" +# expect+1: The location is no longer fake. .info The location is no longer fake. all: diff --git a/unit-tests/varname-makeflags.mk b/unit-tests/varname-makeflags.mk index da339ba9c5e2..4173c5a92095 100644 --- a/unit-tests/varname-makeflags.mk +++ b/unit-tests/varname-makeflags.mk @@ -1,4 +1,4 @@ -# $NetBSD: varname-makeflags.mk,v 1.7 2023/02/25 19:24:07 rillig Exp $ +# $NetBSD: varname-makeflags.mk,v 1.8 2023/06/01 07:27:30 rillig Exp $ # # Tests for the environment variable 'MAKEFLAGS', from which additional # command line arguments are read before the actual command line arguments. @@ -96,7 +96,7 @@ dollars_stage_1: # $\ the value of the variable named '\' # {varname\} a literal string # - # Since the variable name '\' is not defined, the resulting value is + # Since the variable named '\' is not defined, the resulting value is # '\{varname\}'. Make doesn't handle isolated '$' characters in # strings well, instead each '$' has to be part of a '$$' or be part # of a subexpression like '${VAR}'. @@ -135,9 +135,9 @@ dollars_stage_3: @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>' -# Demonstrates in which exact order the MAKEFLAGS are built together from the -# parent MAKEFLAGS and the flags from the command line, in particular that -# variable assignments are passed at the end, after the options. +# Demonstrates in which exact order the MAKEFLAGS are built from the parent +# MAKEFLAGS and the flags from the command line, in particular that variable +# assignments are passed at the end, after the options. append_stage_0: @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>' @${MAKE} -Dbefore-0 -f ${MAKEFILE} append_stage_1 VAR0=value -Dafter-0 diff --git a/unit-tests/varname.exp b/unit-tests/varname.exp index 942532b654d5..72aea120c6e6 100644 --- a/unit-tests/varname.exp +++ b/unit-tests/varname.exp @@ -5,13 +5,13 @@ Var_Parse: ${VARNAME} (eval) Global: VAR((( = 3 open parentheses Var_Parse: ${VAR(((}}}}" != "3 open parentheses}}}" (eval) Global: .ALLTARGETS = VAR(((=) -make: "varname.mk" line 30: No closing parenthesis in archive specification -make: "varname.mk" line 30: Error in archive specification: "VAR" +make: "varname.mk" line 32: No closing parenthesis in archive specification +make: "varname.mk" line 32: Error in archive specification: "VAR" Var_Parse: ${:UVAR\(\(\(}= try2 (eval-defined) Evaluating modifier ${:U...} on value "" (eval-defined, undefined) Result of ${:UVAR\(\(\(} is "VAR\(\(\(" (eval-defined, defined) Global: .ALLTARGETS = VAR(((=) VAR\(\(\(= -make: "varname.mk" line 35: Invalid line type +make: "varname.mk" line 38: Invalid line type Var_Parse: ${VARNAME} (eval) Global: VAR((( = try3 Global: .MAKEFLAGS = -r -k -d v -d diff --git a/unit-tests/varname.mk b/unit-tests/varname.mk index e86fd9176a2a..f3e5bdeffeef 100644 --- a/unit-tests/varname.mk +++ b/unit-tests/varname.mk @@ -1,4 +1,4 @@ -# $NetBSD: varname.mk,v 1.10 2022/02/09 21:09:24 rillig Exp $ +# $NetBSD: varname.mk,v 1.11 2023/06/01 20:56:35 rillig Exp $ # # Tests for special variables, such as .MAKE or .PARSEDIR. # And for variable names in general. @@ -27,11 +27,14 @@ ${VARNAME}= 3 open parentheses # This is not a variable assignment since the parentheses and braces are not # balanced. At the end of the line, there are still 3 levels open, which # means the variable name is not finished. +# expect+2: Error in archive specification: "VAR" +# expect+1: No closing parenthesis in archive specification ${:UVAR(((}= try1 # On the left-hand side of a variable assignments, the backslash is not parsed # as an escape character, therefore the parentheses still count to the nesting # level, which at the end of the line is still 3. Therefore this is not a # variable assignment as well. +# expect+1: Invalid line type ${:UVAR\(\(\(}= try2 # To assign to a variable with an arbitrary name, the variable name has to # come from an external source, not the text that is parsed in the assignment diff --git a/unit-tests/varparse-dynamic.exp b/unit-tests/varparse-dynamic.exp index a2ff29413167..caf8424fa91a 100644 --- a/unit-tests/varparse-dynamic.exp +++ b/unit-tests/varparse-dynamic.exp @@ -1,5 +1,5 @@ -make: "varparse-dynamic.mk" line 8: Malformed conditional (${.TARGEX}) -make: "varparse-dynamic.mk" line 10: Malformed conditional (${.TARGXX}) +make: "varparse-dynamic.mk" line 9: Malformed conditional (${.TARGEX}) +make: "varparse-dynamic.mk" line 12: Malformed conditional (${.TARGXX}) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/unit-tests/varparse-dynamic.mk b/unit-tests/varparse-dynamic.mk index d4d165017a7f..88e4e6a4917e 100644 --- a/unit-tests/varparse-dynamic.mk +++ b/unit-tests/varparse-dynamic.mk @@ -1,12 +1,14 @@ -# $NetBSD: varparse-dynamic.mk,v 1.5 2021/02/22 20:38:55 rillig Exp $ +# $NetBSD: varparse-dynamic.mk,v 1.7 2023/06/01 20:56:35 rillig Exp $ # Before 2020-07-27, there was an off-by-one error in Var_Parse that skipped # the last character in the variable name. -# To trigger the bug, the variable must not be defined. +# To trigger the bug, the variable had to be undefined. .if ${.TARGET} # exact match, may be undefined .endif +# expect+1: Malformed conditional (${.TARGEX}) .if ${.TARGEX} # 1 character difference, must be defined .endif +# expect+1: Malformed conditional (${.TARGXX}) .if ${.TARGXX} # 2 characters difference, must be defined .endif @@ -30,6 +32,3 @@ .if ${.TARGET:M${UNDEF}} != "\${.TARGET:M\${UNDEF}}" . error .endif - -all: - @: diff --git a/unit-tests/varparse-errors.exp b/unit-tests/varparse-errors.exp index fc20e427296a..41db6d8c6f43 100644 --- a/unit-tests/varparse-errors.exp +++ b/unit-tests/varparse-errors.exp @@ -1,10 +1,10 @@ -make: "varparse-errors.mk" line 37: Unknown modifier "Z" -make: "varparse-errors.mk" line 45: Unknown modifier "Z" +make: "varparse-errors.mk" line 38: Unknown modifier "Z" +make: "varparse-errors.mk" line 47: Unknown modifier "Z" make: Bad modifier ":OX" for variable "" -make: "varparse-errors.mk" line 67: Undefined variable "${:U:OX" +make: "varparse-errors.mk" line 71: Undefined variable "${:U:OX" make: Bad modifier ":OX" for variable "" make: Bad modifier ":OX" for variable "" -make: "varparse-errors.mk" line 67: Undefined variable "${:U:OX" +make: "varparse-errors.mk" line 71: Undefined variable "${:U:OX" make: Bad modifier ":OX" for variable "" make: Unclosed variable expression, expecting '}' for modifier "Q" of variable "" with value "" make: Unclosed variable expression, expecting '}' for modifier "sh" of variable "" with value "" diff --git a/unit-tests/varparse-errors.mk b/unit-tests/varparse-errors.mk index 9ce41cc3be9a..3ae6d2db1de9 100644 --- a/unit-tests/varparse-errors.mk +++ b/unit-tests/varparse-errors.mk @@ -1,4 +1,4 @@ -# $NetBSD: varparse-errors.mk,v 1.8 2023/02/14 21:56:48 rillig Exp $ +# $NetBSD: varparse-errors.mk,v 1.9 2023/06/01 20:56:35 rillig Exp $ # Tests for parsing and evaluating all kinds of variable expressions. # @@ -34,6 +34,7 @@ ERR_EVAL= An evaluation error ${:Uvalue:C,.,\3,}. # As of 2020-12-01, errors in the variable name are silently ignored. # Since var.c 1.754 from 2020-12-20, unknown modifiers at parse time result # in an error message and a non-zero exit status. +# expect+1: Unknown modifier "Z" VAR.${:U:Z}= unknown modifier in the variable name .if ${VAR.} != "unknown modifier in the variable name" . error @@ -42,6 +43,7 @@ VAR.${:U:Z}= unknown modifier in the variable name # As of 2020-12-01, errors in the variable name are silently ignored. # Since var.c 1.754 from 2020-12-20, unknown modifiers at parse time result # in an error message and a non-zero exit status. +# expect+1: Unknown modifier "Z" VAR.${:U:Z}post= unknown modifier with text in the variable name .if ${VAR.post} != "unknown modifier with text in the variable name" . error @@ -64,6 +66,8 @@ VAR.${:U:Z}post= unknown modifier with text in the variable name # #.MAKEFLAGS: -dv IND= ${:OX} +# expect+2: Undefined variable "${:U:OX" +# expect+1: Undefined variable "${:U:OX" _:= ${:U:OX:U${IND}} ${:U:OX:U${IND}} #.MAKEFLAGS: -d0 diff --git a/var.c b/var.c index 074a96639bdb..43eaf75fb842 100644 --- a/var.c +++ b/var.c @@ -1,4 +1,4 @@ -/* $NetBSD: var.c,v 1.1054 2023/05/10 18:22:33 sjg Exp $ */ +/* $NetBSD: var.c,v 1.1059 2023/06/23 05:21:10 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -147,7 +147,7 @@ #include "metachar.h" /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: var.c,v 1.1054 2023/05/10 18:22:33 sjg Exp $"); +MAKE_RCSID("$NetBSD: var.c,v 1.1059 2023/06/23 05:21:10 rillig Exp $"); /* * Variables are defined using one of the VAR=value assignments. Their @@ -521,6 +521,11 @@ Var_Delete(GNode *scope, const char *varname) DEBUG2(VAR, "%s: delete %s\n", scope->name, varname); v = he->value; + if (v->readOnly) { + DEBUG2(VAR, "%s: delete %s (readOnly)\n", + scope->name, varname); + return; + } if (v->inUse) { Parse_Error(PARSE_FATAL, "Cannot delete variable \"%s\" while it is used", @@ -1322,7 +1327,7 @@ SepBuf_AddBytes(SepBuf *buf, const char *mem, size_t mem_size) } static void -SepBuf_AddBytesBetween(SepBuf *buf, const char *start, const char *end) +SepBuf_AddRange(SepBuf *buf, const char *start, const char *end) { SepBuf_AddBytes(buf, start, (size_t)(end - start)); } @@ -1336,7 +1341,7 @@ SepBuf_AddStr(SepBuf *buf, const char *str) static void SepBuf_AddSubstring(SepBuf *buf, Substring sub) { - SepBuf_AddBytesBetween(buf, sub.start, sub.end); + SepBuf_AddRange(buf, sub.start, sub.end); } static char * @@ -1393,7 +1398,7 @@ ModifyWord_Suffix(Substring word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED) { const char *lastDot = Substring_LastIndex(word, '.'); if (lastDot != NULL) - SepBuf_AddBytesBetween(buf, lastDot + 1, word.end); + SepBuf_AddRange(buf, lastDot + 1, word.end); } /* @@ -1408,35 +1413,7 @@ ModifyWord_Root(Substring word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED) lastDot = Substring_LastIndex(word, '.'); end = lastDot != NULL ? lastDot : word.end; - SepBuf_AddBytesBetween(buf, word.start, end); -} - -/* - * Callback for ModifyWords to implement the :M modifier. - * Place the word in the buffer if it matches the given pattern. - */ -static void -ModifyWord_Match(Substring word, SepBuf *buf, void *data) -{ - const char *pattern = data; - - assert(word.end[0] == '\0'); /* assume null-terminated word */ - if (Str_Match(word.start, pattern)) - SepBuf_AddSubstring(buf, word); -} - -/* - * Callback for ModifyWords to implement the :N modifier. - * Place the word in the buffer if it doesn't match the given pattern. - */ -static void -ModifyWord_NoMatch(Substring word, SepBuf *buf, void *data) -{ - const char *pattern = data; - - assert(word.end[0] == '\0'); /* assume null-terminated word */ - if (!Str_Match(word.start, pattern)) - SepBuf_AddSubstring(buf, word); + SepBuf_AddRange(buf, word.start, end); } #ifdef SYSVVARSUB @@ -1471,9 +1448,9 @@ ModifyWord_SysVSubst(Substring word, SepBuf *buf, void *data) percent = args->lhsPercent ? strchr(rhs.str, '%') : NULL; if (percent != NULL) - SepBuf_AddBytesBetween(buf, rhs.str, percent); + SepBuf_AddRange(buf, rhs.str, percent); if (percent != NULL || !args->lhsPercent) - SepBuf_AddBytesBetween(buf, + SepBuf_AddRange(buf, word.start + Substring_Length(args->lhsPrefix), word.end - Substring_Length(args->lhsSuffix)); SepBuf_AddStr(buf, percent != NULL ? percent + 1 : rhs.str); @@ -1530,7 +1507,7 @@ ModifyWord_Subst(Substring word, SepBuf *buf, void *data) /* :S,^prefix,replacement, or :S,^whole$,replacement, */ SepBuf_AddSubstring(buf, args->rhs); - SepBuf_AddBytesBetween(buf, word.start + lhsLen, wordEnd); + SepBuf_AddRange(buf, word.start + lhsLen, wordEnd); args->matched = true; return; } @@ -1542,7 +1519,7 @@ ModifyWord_Subst(Substring word, SepBuf *buf, void *data) goto nosub; /* :S,suffix$,replacement, */ - SepBuf_AddBytesBetween(buf, word.start, wordEnd - lhsLen); + SepBuf_AddRange(buf, word.start, wordEnd - lhsLen); SepBuf_AddSubstring(buf, args->rhs); args->matched = true; return; @@ -1553,7 +1530,7 @@ ModifyWord_Subst(Substring word, SepBuf *buf, void *data) /* unanchored case, may match more than once */ while ((match = Substring_Find(word, args->lhs)) != NULL) { - SepBuf_AddBytesBetween(buf, word.start, match); + SepBuf_AddRange(buf, word.start, match); SepBuf_AddSubstring(buf, args->rhs); args->matched = true; word.start = match + lhsLen; @@ -1567,7 +1544,7 @@ ModifyWord_Subst(Substring word, SepBuf *buf, void *data) #ifndef NO_REGEX /* Print the error caused by a regcomp or regexec call. */ static void -VarREError(int reerr, const regex_t *pat, const char *str) +RegexError(int reerr, const regex_t *pat, const char *str) { size_t errlen = regerror(reerr, pat, NULL, 0); char *errbuf = bmake_malloc(errlen); @@ -1589,7 +1566,7 @@ RegexReplaceBackref(char ref, SepBuf *buf, const char *wp, if (opts.strict) Error("No match for subexpression \\%u", n); } else { - SepBuf_AddBytesBetween(buf, + SepBuf_AddRange(buf, wp + (size_t)m[n].rm_so, wp + (size_t)m[n].rm_eo); } @@ -1613,7 +1590,7 @@ RegexReplace(Substring replace, SepBuf *buf, const char *wp, ch_isdigit(rp[1])) RegexReplaceBackref(*++rp, buf, wp, m, nsub); else if (*rp == '&') { - SepBuf_AddBytesBetween(buf, + SepBuf_AddRange(buf, wp + (size_t)m[0].rm_so, wp + (size_t)m[0].rm_eo); } else @@ -1652,9 +1629,9 @@ ModifyWord_SubstRegex(Substring word, SepBuf *buf, void *data) if (xrv == 0) goto ok; if (xrv != REG_NOMATCH) - VarREError(xrv, &args->re, "Unexpected regex error"); + RegexError(xrv, &args->re, "Unexpected regex error"); no_match: - SepBuf_AddBytesBetween(buf, wp, word.end); + SepBuf_AddRange(buf, wp, word.end); return; ok: @@ -1809,8 +1786,7 @@ SubstringWords_JoinFree(SubstringWords words) */ Buf_AddByte(&buf, ' '); } - Buf_AddBytesBetween(&buf, - words.words[i].start, words.words[i].end); + Buf_AddRange(&buf, words.words[i].start, words.words[i].end); } SubstringWords_Free(words); @@ -1824,7 +1800,7 @@ SubstringWords_JoinFree(SubstringWords words) * If quoteDollar is set, also quote and double any '$' characters. */ static void -VarQuote(const char *str, bool quoteDollar, LazyBuf *buf) +QuoteShell(const char *str, bool quoteDollar, LazyBuf *buf) { const char *p; @@ -1850,7 +1826,7 @@ VarQuote(const char *str, bool quoteDollar, LazyBuf *buf) * algorithm. Output is encoded as 8 hex digits, in Little Endian order. */ static char * -VarHash(const char *str) +Hash(const char *str) { static const char hexdigits[16] = "0123456789abcdef"; const unsigned char *ustr = (const unsigned char *)str; @@ -1910,7 +1886,7 @@ VarHash(const char *str) } static char * -VarStrftime(const char *fmt, time_t t, bool gmt) +FormatTime(const char *fmt, time_t t, bool gmt) { char buf[BUFSIZ]; @@ -2607,7 +2583,7 @@ ApplyModifier_Time(const char **pp, ModChain *ch) expr = ch->expr; if (Expr_ShouldEval(expr)) - Expr_SetValueOwn(expr, VarStrftime(Expr_Str(expr), t, gmt)); + Expr_SetValueOwn(expr, FormatTime(Expr_Str(expr), t, gmt)); return AMR_OK; } @@ -2621,7 +2597,7 @@ ApplyModifier_Hash(const char **pp, ModChain *ch) *pp += 4; if (ModChain_ShouldEval(ch)) - Expr_SetValueOwn(ch->expr, VarHash(Expr_Str(ch->expr))); + Expr_SetValueOwn(ch->expr, Hash(Expr_Str(ch->expr))); return AMR_OK; } @@ -2822,6 +2798,29 @@ ParseModifier_Match(const char **pp, const ModChain *ch) return pattern; } +struct ModifyWord_MatchArgs { + const char *pattern; + bool neg; + bool error_reported; +}; + +static void +ModifyWord_Match(Substring word, SepBuf *buf, void *data) +{ + struct ModifyWord_MatchArgs *args = data; + StrMatchResult res; + assert(word.end[0] == '\0'); /* assume null-terminated word */ + res = Str_Match(word.start, args->pattern); + if (res.error != NULL && !args->error_reported) { + args->error_reported = true; + Parse_Error(PARSE_WARNING, + "%s in pattern '%s' of modifier '%s'", + res.error, args->pattern, args->neg ? ":N" : ":M"); + } + if (res.matched != args->neg) + SepBuf_AddSubstring(buf, word); +} + /* :Mpattern or :Npattern */ static ApplyModifierResult ApplyModifier_Match(const char **pp, ModChain *ch) @@ -2832,9 +2831,11 @@ ApplyModifier_Match(const char **pp, ModChain *ch) pattern = ParseModifier_Match(pp, ch); if (ModChain_ShouldEval(ch)) { - ModifyWordProc modifyWord = - mod == 'M' ? ModifyWord_Match : ModifyWord_NoMatch; - ModifyWords(ch, modifyWord, pattern, ch->oneBigWord); + struct ModifyWord_MatchArgs args; + args.pattern = pattern; + args.neg = mod == 'N'; + args.error_reported = false; + ModifyWords(ch, ModifyWord_Match, &args, ch->oneBigWord); } free(pattern); @@ -3016,7 +3017,7 @@ ApplyModifier_Regex(const char **pp, ModChain *ch) error = regcomp(&args.re, re.str, REG_EXTENDED); if (error != 0) { - VarREError(error, &args.re, "Regex compilation error"); + RegexError(error, &args.re, "Regex compilation error"); LazyBuf_Done(&replaceBuf); FStr_Done(&re); return AMR_CLEANUP; @@ -3052,7 +3053,7 @@ ApplyModifier_Quote(const char **pp, ModChain *ch) if (!ModChain_ShouldEval(ch)) return AMR_OK; - VarQuote(Expr_Str(ch->expr), quoteDollar, &buf); + QuoteShell(Expr_Str(ch->expr), quoteDollar, &buf); if (buf.data != NULL) Expr_SetValue(ch->expr, LazyBuf_DoneGet(&buf)); else @@ -4743,7 +4744,7 @@ VarSubstPlain(const char **pp, Buffer *res) for (p++; *p != '$' && *p != '\0'; p++) continue; - Buf_AddBytesBetween(res, start, p); + Buf_AddRange(res, start, p); *pp = p; }