Tue Apr 23 22:51:28 2024 UTC (16d)
make: clean up comments, code and tests


(rillig)
diff -r1.362 -r1.363 src/usr.bin/make/cond.c
diff -r1.330 -r1.331 src/usr.bin/make/make.h
diff -r1.720 -r1.721 src/usr.bin/make/parse.c
diff -r1.1104 -r1.1105 src/usr.bin/make/var.c
diff -r1.5 -r1.6 src/usr.bin/make/unit-tests/cmd-errors-jobs.exp
diff -r1.5 -r1.6 src/usr.bin/make/unit-tests/cmd-errors-lint.exp
diff -r1.5 -r1.6 src/usr.bin/make/unit-tests/cmd-errors.mk
diff -r1.3 -r1.4 src/usr.bin/make/unit-tests/cmd-errors-jobs.mk
diff -r1.1 -r1.2 src/usr.bin/make/unit-tests/cmd-errors-lint.mk
diff -r1.8 -r1.9 src/usr.bin/make/unit-tests/cmd-errors.exp
diff -r1.8 -r1.9 src/usr.bin/make/unit-tests/cond-func-defined.exp
diff -r1.4 -r1.5 src/usr.bin/make/unit-tests/cmdline-undefined.mk
diff -r1.4 -r1.5 src/usr.bin/make/unit-tests/cmdline.mk
diff -r1.6 -r1.7 src/usr.bin/make/unit-tests/comment.mk
diff -r1.18 -r1.19 src/usr.bin/make/unit-tests/cond-cmp-string.mk
diff -r1.11 -r1.12 src/usr.bin/make/unit-tests/cond-func-defined.mk
diff -r1.27 -r1.28 src/usr.bin/make/unit-tests/varmod-ifelse.mk
diff -r1.15 -r1.16 src/usr.bin/make/unit-tests/varmod-match.exp
diff -r1.21 -r1.22 src/usr.bin/make/unit-tests/varmod-match.mk

cvs diff -r1.362 -r1.363 src/usr.bin/make/cond.c (expand / switch to unified diff)

--- src/usr.bin/make/cond.c 2024/02/07 07:21:22 1.362
+++ src/usr.bin/make/cond.c 2024/04/23 22:51:28 1.363
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: cond.c,v 1.362 2024/02/07 07:21:22 rillig Exp $ */ 1/* $NetBSD: cond.c,v 1.363 2024/04/23 22:51:28 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor. 8 * Adam de Boor.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -81,27 +81,27 @@ @@ -81,27 +81,27 @@
81 * of one of the .if directives or the condition in a 81 * of one of the .if directives or the condition in a
82 * ':?then:else' variable modifier. 82 * ':?then:else' variable modifier.
83 * 83 *
84 * Cond_EndFile At the end of reading a makefile, ensure that the 84 * Cond_EndFile At the end of reading a makefile, ensure that the
85 * conditional directives are well-balanced. 85 * conditional directives are well-balanced.
86 */ 86 */
87 87
88#include <errno.h> 88#include <errno.h>
89 89
90#include "make.h" 90#include "make.h"
91#include "dir.h" 91#include "dir.h"
92 92
93/* "@(#)cond.c 8.2 (Berkeley) 1/2/94" */ 93/* "@(#)cond.c 8.2 (Berkeley) 1/2/94" */
94MAKE_RCSID("$NetBSD: cond.c,v 1.362 2024/02/07 07:21:22 rillig Exp $"); 94MAKE_RCSID("$NetBSD: cond.c,v 1.363 2024/04/23 22:51:28 rillig Exp $");
95 95
96/* 96/*
97 * Conditional expressions conform to this grammar: 97 * Conditional expressions conform to this grammar:
98 * Or -> And ('||' And)* 98 * Or -> And ('||' And)*
99 * And -> Term ('&&' Term)* 99 * And -> Term ('&&' Term)*
100 * Term -> Function '(' Argument ')' 100 * Term -> Function '(' Argument ')'
101 * Term -> Leaf Operator Leaf 101 * Term -> Leaf Operator Leaf
102 * Term -> Leaf 102 * Term -> Leaf
103 * Term -> '(' Or ')' 103 * Term -> '(' Or ')'
104 * Term -> '!' Term 104 * Term -> '!' Term
105 * Leaf -> "string" 105 * Leaf -> "string"
106 * Leaf -> Number 106 * Leaf -> Number
107 * Leaf -> VariableExpression 107 * Leaf -> VariableExpression
@@ -414,33 +414,32 @@ CondParser_StringExpr(CondParser *par, c @@ -414,33 +414,32 @@ CondParser_StringExpr(CondParser *par, c
414 if (atStart && is_separator(par->p[0])) 414 if (atStart && is_separator(par->p[0]))
415 return false; 415 return false;
416 416
417 Buf_AddStr(buf, inout_str->str); 417 Buf_AddStr(buf, inout_str->str);
418 FStr_Done(inout_str); 418 FStr_Done(inout_str);
419 *inout_str = FStr_InitRefer(NULL); /* not finished yet */ 419 *inout_str = FStr_InitRefer(NULL); /* not finished yet */
420 return true; 420 return true;
421} 421}
422 422
423/* 423/*
424 * Parse a string from an expression or an optionally quoted string, 424 * Parse a string from an expression or an optionally quoted string,
425 * on the left-hand and right-hand sides of comparisons. 425 * on the left-hand and right-hand sides of comparisons.
426 * 426 *
427 * Results: 427 * Return the string without any enclosing quotes, or NULL on error.
428 * Returns the string without any enclosing quotes, or NULL on error. 428 * Sets out_quoted if the leaf was a quoted string literal.
429 * Sets out_quoted if the leaf was a quoted string literal. 
430 */ 429 */
431static void 430static FStr
432CondParser_Leaf(CondParser *par, bool doEval, bool unquotedOK, 431CondParser_Leaf(CondParser *par, bool doEval, bool unquotedOK,
433 FStr *out_str, bool *out_quoted) 432 bool *out_quoted)
434{ 433{
435 Buffer buf; 434 Buffer buf;
436 FStr str; 435 FStr str;
437 bool quoted; 436 bool quoted;
438 const char *start; 437 const char *start;
439 438
440 Buf_Init(&buf); 439 Buf_Init(&buf);
441 str = FStr_InitRefer(NULL); 440 str = FStr_InitRefer(NULL);
442 *out_quoted = quoted = par->p[0] == '"'; 441 *out_quoted = quoted = par->p[0] == '"';
443 start = par->p; 442 start = par->p;
444 if (quoted) 443 if (quoted)
445 par->p++; 444 par->p++;
446 445
@@ -482,27 +481,27 @@ CondParser_Leaf(CondParser *par, bool do @@ -482,27 +481,27 @@ CondParser_Leaf(CondParser *par, bool do
482 str = FStr_InitRefer(NULL); 481 str = FStr_InitRefer(NULL);
483 goto return_str; 482 goto return_str;
484 } 483 }
485 Buf_AddByte(&buf, par->p[0]); 484 Buf_AddByte(&buf, par->p[0]);
486 par->p++; 485 par->p++;
487 continue; 486 continue;
488 } 487 }
489 } 488 }
490return_buf: 489return_buf:
491 str = FStr_InitOwn(buf.data); 490 str = FStr_InitOwn(buf.data);
492 buf.data = NULL; 491 buf.data = NULL;
493return_str: 492return_str:
494 Buf_Done(&buf); 493 Buf_Done(&buf);
495 *out_str = str; 494 return str;
496} 495}
497 496
498/* 497/*
499 * Evaluate a "comparison without operator", such as in ".if ${VAR}" or 498 * Evaluate a "comparison without operator", such as in ".if ${VAR}" or
500 * ".if 0". 499 * ".if 0".
501 */ 500 */
502static bool 501static bool
503EvalTruthy(CondParser *par, const char *value, bool quoted) 502EvalTruthy(CondParser *par, const char *value, bool quoted)
504{ 503{
505 double num; 504 double num;
506 505
507 if (quoted) 506 if (quoted)
508 return value[0] != '\0'; 507 return value[0] != '\0';
@@ -592,47 +591,47 @@ CondParser_ComparisonOp(CondParser *par, @@ -592,47 +591,47 @@ CondParser_ComparisonOp(CondParser *par,
592 * 0 591 * 0
593 * ${VAR:Mpattern} 592 * ${VAR:Mpattern}
594 * ${VAR} == value 593 * ${VAR} == value
595 * ${VAR:U0} < 12345 594 * ${VAR:U0} < 12345
596 */ 595 */
597static Token 596static Token
598CondParser_Comparison(CondParser *par, bool doEval) 597CondParser_Comparison(CondParser *par, bool doEval)
599{ 598{
600 Token t = TOK_ERROR; 599 Token t = TOK_ERROR;
601 FStr lhs, rhs; 600 FStr lhs, rhs;
602 ComparisonOp op; 601 ComparisonOp op;
603 bool lhsQuoted, rhsQuoted; 602 bool lhsQuoted, rhsQuoted;
604 603
605 CondParser_Leaf(par, doEval, par->leftUnquotedOK, &lhs, &lhsQuoted); 604 lhs = CondParser_Leaf(par, doEval, par->leftUnquotedOK, &lhsQuoted);
606 if (lhs.str == NULL) 605 if (lhs.str == NULL)
607 goto done_lhs; 606 goto done_lhs;
608 607
609 CondParser_SkipWhitespace(par); 608 CondParser_SkipWhitespace(par);
610 609
611 if (!CondParser_ComparisonOp(par, &op)) { 610 if (!CondParser_ComparisonOp(par, &op)) {
612 t = ToToken(doEval && EvalTruthy(par, lhs.str, lhsQuoted)); 611 t = ToToken(doEval && EvalTruthy(par, lhs.str, lhsQuoted));
613 goto done_lhs; 612 goto done_lhs;
614 } 613 }
615 614
616 CondParser_SkipWhitespace(par); 615 CondParser_SkipWhitespace(par);
617 616
618 if (par->p[0] == '\0') { 617 if (par->p[0] == '\0') {
619 Parse_Error(PARSE_FATAL, 618 Parse_Error(PARSE_FATAL,
620 "Missing right-hand side of operator '%s'", opname[op]); 619 "Missing right-hand side of operator '%s'", opname[op]);
621 par->printedError = true; 620 par->printedError = true;
622 goto done_lhs; 621 goto done_lhs;
623 } 622 }
624 623
625 CondParser_Leaf(par, doEval, true, &rhs, &rhsQuoted); 624 rhs = CondParser_Leaf(par, doEval, true, &rhsQuoted);
626 t = rhs.str == NULL ? TOK_ERROR 625 t = rhs.str == NULL ? TOK_ERROR
627 : !doEval ? TOK_FALSE 626 : !doEval ? TOK_FALSE
628 : EvalCompare(par, lhs.str, lhsQuoted, op, rhs.str, rhsQuoted); 627 : EvalCompare(par, lhs.str, lhsQuoted, op, rhs.str, rhsQuoted);
629 FStr_Done(&rhs); 628 FStr_Done(&rhs);
630 629
631done_lhs: 630done_lhs:
632 FStr_Done(&lhs); 631 FStr_Done(&lhs);
633 return t; 632 return t;
634} 633}
635 634
636/* 635/*
637 * The argument to empty() is a variable name, optionally followed by 636 * The argument to empty() is a variable name, optionally followed by
638 * variable modifiers. 637 * variable modifiers.

cvs diff -r1.330 -r1.331 src/usr.bin/make/make.h (expand / switch to unified diff)

--- src/usr.bin/make/make.h 2024/04/20 10:18:55 1.330
+++ src/usr.bin/make/make.h 2024/04/23 22:51:28 1.331
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: make.h,v 1.330 2024/04/20 10:18:55 rillig Exp $ */ 1/* $NetBSD: make.h,v 1.331 2024/04/23 22:51:28 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990, 1993 4 * Copyright (c) 1988, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor. 8 * Adam de Boor.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -389,27 +389,27 @@ typedef struct GNodeFlags { @@ -389,27 +389,27 @@ typedef struct GNodeFlags {
389 389
390typedef struct List StringList; 390typedef struct List StringList;
391typedef struct ListNode StringListNode; 391typedef struct ListNode StringListNode;
392 392
393typedef struct List GNodeList; 393typedef struct List GNodeList;
394typedef struct ListNode GNodeListNode; 394typedef struct ListNode GNodeListNode;
395 395
396typedef struct SearchPath { 396typedef struct SearchPath {
397 List /* of CachedDir */ dirs; 397 List /* of CachedDir */ dirs;
398} SearchPath; 398} SearchPath;
399 399
400/* 400/*
401 * A graph node represents a target that can possibly be made, including its 401 * A graph node represents a target that can possibly be made, including its
402 * relation to other targets and a lot of other details. 402 * relation to other targets.
403 */ 403 */
404typedef struct GNode { 404typedef struct GNode {
405 /* The target's name, such as "clean" or "make.c" */ 405 /* The target's name, such as "clean" or "make.c" */
406 char *name; 406 char *name;
407 /* The unexpanded name of a .USE node */ 407 /* The unexpanded name of a .USE node */
408 char *uname; 408 char *uname;
409 /* 409 /*
410 * The full pathname of the file belonging to the target. 410 * The full pathname of the file belonging to the target.
411 * 411 *
412 * XXX: What about .PHONY targets? These don't have an associated 412 * XXX: What about .PHONY targets? These don't have an associated
413 * path. 413 * path.
414 */ 414 */
415 char *path; 415 char *path;
@@ -571,28 +571,28 @@ extern bool doing_depend; @@ -571,28 +571,28 @@ extern bool doing_depend;
571extern GNode *defaultNode; 571extern GNode *defaultNode;
572 572
573/* 573/*
574 * Variables defined internally by make which should not override those set 574 * Variables defined internally by make which should not override those set
575 * by makefiles. 575 * by makefiles.
576 */ 576 */
577extern GNode *SCOPE_INTERNAL; 577extern GNode *SCOPE_INTERNAL;
578/* Variables defined in a global scope, e.g in the makefile itself. */ 578/* Variables defined in a global scope, e.g in the makefile itself. */
579extern GNode *SCOPE_GLOBAL; 579extern GNode *SCOPE_GLOBAL;
580/* Variables defined on the command line. */ 580/* Variables defined on the command line. */
581extern GNode *SCOPE_CMDLINE; 581extern GNode *SCOPE_CMDLINE;
582 582
583/* 583/*
584 * Value returned by Var_Parse when an error is encountered. It actually 584 * Value returned by Var_Parse when an error is encountered. It points to an
585 * points to an empty string, so naive callers needn't worry about it. 585 * empty string, so naive callers needn't worry about it.
586 */ 586 */
587extern char var_Error[]; 587extern char var_Error[];
588 588
589/* The time at the start of this whole process */ 589/* The time at the start of this whole process */
590extern time_t now; 590extern time_t now;
591 591
592/* 592/*
593 * The list of directories to search when looking for targets (set by the 593 * The list of directories to search when looking for targets (set by the
594 * special target .PATH). 594 * special target .PATH).
595 */ 595 */
596extern SearchPath dirSearchPath; 596extern SearchPath dirSearchPath;
597/* Used for .include "...". */ 597/* Used for .include "...". */
598extern SearchPath *parseIncPath; 598extern SearchPath *parseIncPath;
@@ -668,31 +668,31 @@ void debug_printf(const char *, ...) MAK @@ -668,31 +668,31 @@ void debug_printf(const char *, ...) MAK
668#define DEBUG4(module, fmt, arg1, arg2, arg3, arg4) \ 668#define DEBUG4(module, fmt, arg1, arg2, arg3, arg4) \
669 DEBUG_IMPL(module, (fmt, arg1, arg2, arg3, arg4)) 669 DEBUG_IMPL(module, (fmt, arg1, arg2, arg3, arg4))
670#define DEBUG5(module, fmt, arg1, arg2, arg3, arg4, arg5) \ 670#define DEBUG5(module, fmt, arg1, arg2, arg3, arg4, arg5) \
671 DEBUG_IMPL(module, (fmt, arg1, arg2, arg3, arg4, arg5)) 671 DEBUG_IMPL(module, (fmt, arg1, arg2, arg3, arg4, arg5))
672 672
673typedef enum PrintVarsMode { 673typedef enum PrintVarsMode {
674 PVM_NONE, 674 PVM_NONE,
675 PVM_UNEXPANDED, 675 PVM_UNEXPANDED,
676 PVM_EXPANDED 676 PVM_EXPANDED
677} PrintVarsMode; 677} PrintVarsMode;
678 678
679/* Command line options */ 679/* Command line options */
680typedef struct CmdOpts { 680typedef struct CmdOpts {
681 /* -B: whether we are make compatible */ 681 /* -B: whether to be compatible to traditional make */
682 bool compatMake; 682 bool compatMake;
683 683
684 /* 684 /*
685 * -d: debug control: There is one bit per module. It is up to the 685 * -d: debug control: There is one flag per module. It is up to the
686 * module what debug information to print. 686 * module what debug information to print.
687 */ 687 */
688 DebugFlags debug; 688 DebugFlags debug;
689 689
690 /* -df: debug output is written here - default stderr */ 690 /* -df: debug output is written here - default stderr */
691 FILE *debug_file; 691 FILE *debug_file;
692 692
693 /* 693 /*
694 * -dL: lint mode 694 * -dL: lint mode
695 * 695 *
696 * Runs make in strict mode, with additional checks and better error 696 * Runs make in strict mode, with additional checks and better error
697 * handling. 697 * handling.
698 */ 698 */

cvs diff -r1.720 -r1.721 src/usr.bin/make/parse.c (expand / switch to unified diff)

--- src/usr.bin/make/parse.c 2024/04/20 10:18:55 1.720
+++ src/usr.bin/make/parse.c 2024/04/23 22:51:28 1.721
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: parse.c,v 1.720 2024/04/20 10:18:55 rillig Exp $ */ 1/* $NetBSD: parse.c,v 1.721 2024/04/23 22:51:28 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990, 1993 4 * Copyright (c) 1988, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor. 8 * Adam de Boor.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -95,27 +95,27 @@ @@ -95,27 +95,27 @@
95 */ 95 */
96 96
97#include <sys/types.h> 97#include <sys/types.h>
98#include <sys/stat.h> 98#include <sys/stat.h>
99#include <errno.h> 99#include <errno.h>
100#include <stdarg.h> 100#include <stdarg.h>
101 101
102#include "make.h" 102#include "make.h"
103#include "dir.h" 103#include "dir.h"
104#include "job.h" 104#include "job.h"
105#include "pathnames.h" 105#include "pathnames.h"
106 106
107/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */ 107/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */
108MAKE_RCSID("$NetBSD: parse.c,v 1.720 2024/04/20 10:18:55 rillig Exp $"); 108MAKE_RCSID("$NetBSD: parse.c,v 1.721 2024/04/23 22:51:28 rillig Exp $");
109 109
110/* Detects a multiple-inclusion guard in a makefile. */ 110/* Detects a multiple-inclusion guard in a makefile. */
111typedef enum { 111typedef enum {
112 GS_START, /* at the beginning of the file */ 112 GS_START, /* at the beginning of the file */
113 GS_COND, /* after the guard condition */ 113 GS_COND, /* after the guard condition */
114 GS_DONE, /* after the closing .endif */ 114 GS_DONE, /* after the closing .endif */
115 GS_NO /* the file is not guarded */ 115 GS_NO /* the file is not guarded */
116} GuardState; 116} GuardState;
117 117
118/* A file being parsed. */ 118/* A file being parsed. */
119typedef struct IncludedFile { 119typedef struct IncludedFile {
120 FStr name; /* absolute or relative to the cwd */ 120 FStr name; /* absolute or relative to the cwd */
121 unsigned lineno; /* 1-based */ 121 unsigned lineno; /* 1-based */
@@ -1612,56 +1612,56 @@ ParseDependencySources(char *p, GNodeTyp @@ -1612,56 +1612,56 @@ ParseDependencySources(char *p, GNodeTyp
1612 * which is where the nodes found for the targets are kept. 1612 * which is where the nodes found for the targets are kept.
1613 * 1613 *
1614 * The sources are parsed in much the same way as the targets, except 1614 * The sources are parsed in much the same way as the targets, except
1615 * that they are expanded using the wildcarding scheme of the C-Shell, 1615 * that they are expanded using the wildcarding scheme of the C-Shell,
1616 * and a target is created for each expanded word. Each of the resulting 1616 * and a target is created for each expanded word. Each of the resulting
1617 * nodes is then linked to each of the targets as one of its children. 1617 * nodes is then linked to each of the targets as one of its children.
1618 * 1618 *
1619 * Certain targets and sources such as .PHONY or .PRECIOUS are handled 1619 * Certain targets and sources such as .PHONY or .PRECIOUS are handled
1620 * specially, see ParseSpecial. 1620 * specially, see ParseSpecial.
1621 * 1621 *
1622 * Transformation rules such as '.c.o' are also handled here, see 1622 * Transformation rules such as '.c.o' are also handled here, see
1623 * Suff_AddTransform. 1623 * Suff_AddTransform.
1624 * 1624 *
1625 * Upon return, the value of the line is unspecified. 1625 * Upon return, the value of expandedLine is unspecified.
1626 */ 1626 */
1627static void 1627static void
1628ParseDependency(char *line, const char *unexpanded_line) 1628ParseDependency(char *expandedLine, const char *unexpandedLine)
1629{ 1629{
1630 char *p; 1630 char *p;
1631 SearchPathList *paths; /* search paths to alter when parsing a list 1631 SearchPathList *paths; /* search paths to alter when parsing a list
1632 * of .PATH targets */ 1632 * of .PATH targets */
1633 GNodeType targetAttr; /* from special sources */ 1633 GNodeType targetAttr; /* from special sources */
1634 ParseSpecial special; /* in special targets, the children are 1634 ParseSpecial special; /* in special targets, the children are
1635 * linked as children of the parent but not 1635 * linked as children of the parent but not
1636 * vice versa */ 1636 * vice versa */
1637 GNodeType op; 1637 GNodeType op;
1638 1638
1639 DEBUG1(PARSE, "ParseDependency(%s)\n", line); 1639 DEBUG1(PARSE, "ParseDependency(%s)\n", expandedLine);
1640 p = line; 1640 p = expandedLine;
1641 paths = NULL; 1641 paths = NULL;
1642 targetAttr = OP_NONE; 1642 targetAttr = OP_NONE;
1643 special = SP_NOT; 1643 special = SP_NOT;
1644 1644
1645 if (!ParseDependencyTargets(&p, line, &special, &targetAttr, &paths, 1645 if (!ParseDependencyTargets(&p, expandedLine, &special, &targetAttr,
1646 unexpanded_line)) 1646 &paths, unexpandedLine))
1647 goto out; 1647 goto out;
1648 1648
1649 if (!Lst_IsEmpty(targets)) 1649 if (!Lst_IsEmpty(targets))
1650 CheckSpecialMundaneMixture(special); 1650 CheckSpecialMundaneMixture(special);
1651 1651
1652 op = ParseDependencyOp(&p); 1652 op = ParseDependencyOp(&p);
1653 if (op == OP_NONE) { 1653 if (op == OP_NONE) {
1654 InvalidLineType(line, unexpanded_line); 1654 InvalidLineType(expandedLine, unexpandedLine);
1655 goto out; 1655 goto out;
1656 } 1656 }
1657 ApplyDependencyOperator(op); 1657 ApplyDependencyOperator(op);
1658 1658
1659 pp_skip_whitespace(&p); 1659 pp_skip_whitespace(&p);
1660 1660
1661 ParseDependencySources(p, targetAttr, special, &paths); 1661 ParseDependencySources(p, targetAttr, special, &paths);
1662 1662
1663out: 1663out:
1664 if (paths != NULL) 1664 if (paths != NULL)
1665 Lst_Free(paths); 1665 Lst_Free(paths);
1666} 1666}
1667 1667

cvs diff -r1.1104 -r1.1105 src/usr.bin/make/var.c (expand / switch to unified diff)

--- src/usr.bin/make/var.c 2024/04/21 21:59:48 1.1104
+++ src/usr.bin/make/var.c 2024/04/23 22:51:28 1.1105
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: var.c,v 1.1104 2024/04/21 21:59:48 rillig Exp $ */ 1/* $NetBSD: var.c,v 1.1105 2024/04/23 22:51:28 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990, 1993 4 * Copyright (c) 1988, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor. 8 * Adam de Boor.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -71,93 +71,88 @@ @@ -71,93 +71,88 @@
71/* 71/*
72 * Handling of variables and the expressions formed from them. 72 * Handling of variables and the expressions formed from them.
73 * 73 *
74 * Variables are set using lines of the form VAR=value. Both the variable 74 * Variables are set using lines of the form VAR=value. Both the variable
75 * name and the value can contain references to other variables, by using 75 * name and the value can contain references to other variables, by using
76 * expressions like ${VAR}, ${VAR:Modifiers}, ${${VARNAME}} or ${VAR:${MODS}}. 76 * expressions like ${VAR}, ${VAR:Modifiers}, ${${VARNAME}} or ${VAR:${MODS}}.
77 * 77 *
78 * Interface: 78 * Interface:
79 * Var_Init Initialize this module. 79 * Var_Init Initialize this module.
80 * 80 *
81 * Var_End Clean up the module. 81 * Var_End Clean up the module.
82 * 82 *
83 * Var_Set 83 * Var_Set
84 * Var_SetExpand 84 * Var_SetExpand Set the value of the variable, creating it if
85 * Set the value of the variable, creating it if 
86 * necessary. 85 * necessary.
87 * 86 *
88 * Var_Append 87 * Var_Append
89 * Var_AppendExpand 88 * Var_AppendExpand
90 * Append more characters to the variable, creating it if 89 * Append more characters to the variable, creating it if
91 * necessary. A space is placed between the old value and 90 * necessary. A space is placed between the old value and
92 * the new one. 91 * the new one.
93 * 92 *
94 * Var_Exists 93 * Var_Exists
95 * Var_ExistsExpand 94 * Var_ExistsExpand
96 * See if a variable exists. 95 * See if a variable exists.
97 * 96 *
98 * Var_Value Return the unexpanded value of a variable, or NULL if 97 * Var_Value Return the unexpanded value of a variable, or NULL if
99 * the variable is undefined. 98 * the variable is undefined.
100 * 99 *
101 * Var_Subst Substitute all expressions in a string. 100 * Var_Subst Substitute all expressions in a string.
102 * 101 *
103 * Var_Parse Parse an expression such as ${VAR:Mpattern}. 102 * Var_Parse Parse an expression such as ${VAR:Mpattern}.
104 * 103 *
105 * Var_Delete 104 * Var_Delete Delete a variable.
106 * Delete a variable. 
107 * 105 *
108 * Var_ReexportVars 106 * Var_ReexportVars
109 * Export some or even all variables to the environment 107 * Export some or even all variables to the environment
110 * of this process and its child processes. 108 * of this process and its child processes.
111 * 109 *
112 * Var_Export Export the variable to the environment of this process 110 * Var_Export Export the variable to the environment of this process
113 * and its child processes. 111 * and its child processes.
114 * 112 *
115 * Var_UnExport Don't export the variable anymore. 113 * Var_UnExport Don't export the variable anymore.
116 * 114 *
117 * Debugging: 115 * Debugging:
118 * Var_Stats Print out hashing statistics if in -dh mode. 116 * Var_Stats Print out hashing statistics if in -dh mode.
119 * 117 *
120 * Var_Dump Print out all variables defined in the given scope. 118 * Var_Dump Print out all variables defined in the given scope.
121 * 
122 * XXX: There's a lot of almost duplicate code in these functions that only 
123 * differs in subtle details that are not mentioned in the manual page. 
124 */ 119 */
125 120
126#include <sys/stat.h> 121#include <sys/stat.h>
127#include <sys/types.h> 122#include <sys/types.h>
128#include <regex.h> 123#include <regex.h>
129#include <errno.h> 124#include <errno.h>
130#include <inttypes.h> 125#include <inttypes.h>
131#include <limits.h> 126#include <limits.h>
132#include <time.h> 127#include <time.h>
133 128
134#include "make.h" 129#include "make.h"
135#include "dir.h" 130#include "dir.h"
136#include "job.h" 131#include "job.h"
137#include "metachar.h" 132#include "metachar.h"
138 133
139/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ 134/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
140MAKE_RCSID("$NetBSD: var.c,v 1.1104 2024/04/21 21:59:48 rillig Exp $"); 135MAKE_RCSID("$NetBSD: var.c,v 1.1105 2024/04/23 22:51:28 rillig Exp $");
141 136
142/* 137/*
143 * Variables are defined using one of the VAR=value assignments. Their 138 * Variables are defined using one of the VAR=value assignments. Their
144 * value can be queried by expressions such as $V, ${VAR}, or with modifiers 139 * value can be queried by expressions such as $V, ${VAR}, or with modifiers
145 * such as ${VAR:S,from,to,g:Q}. 140 * such as ${VAR:S,from,to,g:Q}.
146 * 141 *
147 * There are 3 kinds of variables: scope variables, environment variables, 142 * There are 3 kinds of variables: scope variables, environment variables,
148 * undefined variables. 143 * undefined variables.
149 * 144 *
150 * Scope variables are stored in a GNode.scope. The only way to undefine 145 * Scope variables are stored in GNode.vars. The only way to undefine
151 * a scope variable is using the .undef directive. In particular, it must 146 * a scope variable is using the .undef directive. In particular, it must
152 * not be possible to undefine a variable during the evaluation of an 147 * not be possible to undefine a variable during the evaluation of an
153 * expression, or Var.name might point nowhere. (There is another, 148 * expression, or Var.name might point nowhere. (There is another,
154 * unintended way to undefine a scope variable, see varmod-loop-delete.mk.) 149 * unintended way to undefine a scope variable, see varmod-loop-delete.mk.)
155 * 150 *
156 * Environment variables are short-lived. They are returned by VarFind, and 151 * Environment variables are short-lived. They are returned by VarFind, and
157 * after using them, they must be freed using VarFreeShortLived. 152 * after using them, they must be freed using VarFreeShortLived.
158 * 153 *
159 * Undefined variables occur during evaluation of expressions such 154 * Undefined variables occur during evaluation of expressions such
160 * as ${UNDEF:Ufallback} in Var_Parse and ApplyModifiers. 155 * as ${UNDEF:Ufallback} in Var_Parse and ApplyModifiers.
161 */ 156 */
162typedef struct Var { 157typedef struct Var {
163 /* 158 /*
@@ -172,27 +167,27 @@ typedef struct Var { @@ -172,27 +167,27 @@ typedef struct Var {
172 167
173 /* The variable came from the command line. */ 168 /* The variable came from the command line. */
174 bool fromCmd:1; 169 bool fromCmd:1;
175 170
176 /* 171 /*
177 * The variable is short-lived. 172 * The variable is short-lived.
178 * These variables are not registered in any GNode, therefore they 173 * These variables are not registered in any GNode, therefore they
179 * must be freed after use. 174 * must be freed after use.
180 */ 175 */
181 bool shortLived:1; 176 bool shortLived:1;
182 177
183 /* 178 /*
184 * The variable comes from the environment. 179 * The variable comes from the environment.
185 * Appending to its value moves the variable to the global scope. 180 * Appending to its value depends on the scope, see var-op-append.mk.
186 */ 181 */
187 bool fromEnvironment:1; 182 bool fromEnvironment:1;
188 183
189 /* 184 /*
190 * The variable value cannot be changed anymore, and the variable 185 * The variable value cannot be changed anymore, and the variable
191 * cannot be deleted. Any attempts to do so are silently ignored, 186 * cannot be deleted. Any attempts to do so are silently ignored,
192 * they are logged with -dv though. 187 * they are logged with -dv though.
193 * Use .[NO]READONLY: to adjust. 188 * Use .[NO]READONLY: to adjust.
194 * 189 *
195 * See VAR_SET_READONLY. 190 * See VAR_SET_READONLY.
196 */ 191 */
197 bool readOnly:1; 192 bool readOnly:1;
198 193
@@ -475,31 +470,28 @@ VarFindSubstring(Substring name, GNode * @@ -475,31 +470,28 @@ VarFindSubstring(Substring name, GNode *
475 470
476 if (var == NULL && scope != SCOPE_CMDLINE) 471 if (var == NULL && scope != SCOPE_CMDLINE)
477 var = GNode_FindVar(SCOPE_CMDLINE, name, nameHash); 472 var = GNode_FindVar(SCOPE_CMDLINE, name, nameHash);
478 473
479 if (!opts.checkEnvFirst && var == NULL && scope != SCOPE_GLOBAL) { 474 if (!opts.checkEnvFirst && var == NULL && scope != SCOPE_GLOBAL) {
480 var = GNode_FindVar(SCOPE_GLOBAL, name, nameHash); 475 var = GNode_FindVar(SCOPE_GLOBAL, name, nameHash);
481 if (var == NULL && scope != SCOPE_INTERNAL) { 476 if (var == NULL && scope != SCOPE_INTERNAL) {
482 /* SCOPE_INTERNAL is subordinate to SCOPE_GLOBAL */ 477 /* SCOPE_INTERNAL is subordinate to SCOPE_GLOBAL */
483 var = GNode_FindVar(SCOPE_INTERNAL, name, nameHash); 478 var = GNode_FindVar(SCOPE_INTERNAL, name, nameHash);
484 } 479 }
485 } 480 }
486 481
487 if (var == NULL) { 482 if (var == NULL) {
488 FStr envName; 483 FStr envName = Substring_Str(name);
489 const char *envValue; 484 const char *envValue = getenv(envName.str);
490 
491 envName = Substring_Str(name); 
492 envValue = getenv(envName.str); 
493 if (envValue != NULL) 485 if (envValue != NULL)
494 return VarNew(envName, envValue, true, true, false); 486 return VarNew(envName, envValue, true, true, false);
495 FStr_Done(&envName); 487 FStr_Done(&envName);
496 488
497 if (opts.checkEnvFirst && scope != SCOPE_GLOBAL) { 489 if (opts.checkEnvFirst && scope != SCOPE_GLOBAL) {
498 var = GNode_FindVar(SCOPE_GLOBAL, name, nameHash); 490 var = GNode_FindVar(SCOPE_GLOBAL, name, nameHash);
499 if (var == NULL && scope != SCOPE_INTERNAL) 491 if (var == NULL && scope != SCOPE_INTERNAL)
500 var = GNode_FindVar(SCOPE_INTERNAL, name, 492 var = GNode_FindVar(SCOPE_INTERNAL, name,
501 nameHash); 493 nameHash);
502 return var; 494 return var;
503 } 495 }
504 496
505 return NULL; 497 return NULL;
@@ -994,29 +986,30 @@ Var_SetWithFlags(GNode *scope, const cha @@ -994,29 +986,30 @@ Var_SetWithFlags(GNode *scope, const cha
994 scope->name, name, val); 986 scope->name, name, val);
995 return; 987 return;
996 } 988 }
997 989
998 /* 990 /*
999 * Only look for a variable in the given scope since anything set 991 * Only look for a variable in the given scope since anything set
1000 * here will override anything in a lower scope, so there's not much 992 * here will override anything in a lower scope, so there's not much
1001 * point in searching them all. 993 * point in searching them all.
1002 */ 994 */
1003 v = VarFind(name, scope, false); 995 v = VarFind(name, scope, false);
1004 if (v == NULL) { 996 if (v == NULL) {
1005 if (scope == SCOPE_CMDLINE && !(flags & VAR_SET_NO_EXPORT)) { 997 if (scope == SCOPE_CMDLINE && !(flags & VAR_SET_NO_EXPORT)) {
1006 /* 998 /*
1007 * This var would normally prevent the same name being 999 * This variable would normally prevent the same name
1008 * added to SCOPE_GLOBAL, so delete it from there if 1000 * being added to SCOPE_GLOBAL, so delete it from
1009 * needed. Otherwise -V name may show the wrong value. 1001 * there if needed. Otherwise -V name may show the
 1002 * wrong value.
1010 * 1003 *
1011 * See ExistsInCmdline. 1004 * See ExistsInCmdline.
1012 */ 1005 */
1013 Var_Delete(SCOPE_GLOBAL, name); 1006 Var_Delete(SCOPE_GLOBAL, name);
1014 } 1007 }
1015 if (strcmp(name, ".SUFFIXES") == 0) { 1008 if (strcmp(name, ".SUFFIXES") == 0) {
1016 /* special: treat as read-only */ 1009 /* special: treat as read-only */
1017 DEBUG3(VAR, 1010 DEBUG3(VAR,
1018 "%s: ignoring '%s = %s' as it is read-only\n", 1011 "%s: ignoring '%s = %s' as it is read-only\n",
1019 scope->name, name, val); 1012 scope->name, name, val);
1020 return; 1013 return;
1021 } 1014 }
1022 v = VarAdd(name, val, scope, flags); 1015 v = VarAdd(name, val, scope, flags);
@@ -4706,30 +4699,29 @@ VarSubstPlain(const char **pp, Buffer *r @@ -4706,30 +4699,29 @@ VarSubstPlain(const char **pp, Buffer *r
4706 const char *start = p; 4699 const char *start = p;
4707 4700
4708 for (p++; *p != '$' && *p != '\0'; p++) 4701 for (p++; *p != '$' && *p != '\0'; p++)
4709 continue; 4702 continue;
4710 Buf_AddRange(res, start, p); 4703 Buf_AddRange(res, start, p);
4711 *pp = p; 4704 *pp = p;
4712} 4705}
4713 4706
4714/* 4707/*
4715 * Expand all expressions like $V, ${VAR}, $(VAR:Modifiers) in the 4708 * Expand all expressions like $V, ${VAR}, $(VAR:Modifiers) in the
4716 * given string. 4709 * given string.
4717 * 4710 *
4718 * Input: 4711 * Input:
4719 * str The string in which the expressions are 4712 * str The string in which the expressions are expanded.
4720 * expanded. 4713 * scope The scope in which to start searching for variables.
4721 * scope The scope in which to start searching for 4714 * The other scopes are searched as well.
4722 * variables. The other scopes are searched as well. 
4723 * emode The mode for parsing or evaluating subexpressions. 4715 * emode The mode for parsing or evaluating subexpressions.
4724 */ 4716 */
4725char * 4717char *
4726Var_Subst(const char *str, GNode *scope, VarEvalMode emode) 4718Var_Subst(const char *str, GNode *scope, VarEvalMode emode)
4727{ 4719{
4728 const char *p = str; 4720 const char *p = str;
4729 Buffer res; 4721 Buffer res;
4730 4722
4731 /* 4723 /*
4732 * Set true if an error has already been reported, to prevent a 4724 * Set true if an error has already been reported, to prevent a
4733 * plethora of messages when recursing 4725 * plethora of messages when recursing
4734 */ 4726 */
4735 static bool errorReported; 4727 static bool errorReported;

cvs diff -r1.5 -r1.6 src/usr.bin/make/unit-tests/cmd-errors-jobs.exp (expand / switch to unified diff)

--- src/usr.bin/make/unit-tests/cmd-errors-jobs.exp 2024/04/20 10:18:55 1.5
+++ src/usr.bin/make/unit-tests/cmd-errors-jobs.exp 2024/04/23 22:51:28 1.6
@@ -1,9 +1,9 @@ @@ -1,9 +1,9 @@
1: undefined--eol 1: undefined--eol
2make: in target "unclosed-variable": Unclosed variable "UNCLOSED" 2make: in target "unclosed-expression": Unclosed variable "UNCLOSED"
3: unclosed-variable- 3: unclosed-expression-
4make: Unclosed expression, expecting '}' for "UNCLOSED" 4make: Unclosed expression, expecting '}' for "UNCLOSED"
5: unclosed-modifier- 5: unclosed-modifier-
6make: in target "unknown-modifier": while evaluating variable "UNKNOWN": Unknown modifier "Z" 6make: in target "unknown-modifier": while evaluating variable "UNKNOWN": Unknown modifier "Z"
7: unknown-modifier--eol 7: unknown-modifier--eol
8: end-eol 8: end-eol
9exit status 0 9exit status 0

cvs diff -r1.5 -r1.6 src/usr.bin/make/unit-tests/cmd-errors-lint.exp (expand / switch to unified diff)

--- src/usr.bin/make/unit-tests/cmd-errors-lint.exp 2024/04/20 10:18:55 1.5
+++ src/usr.bin/make/unit-tests/cmd-errors-lint.exp 2024/04/23 22:51:28 1.6
@@ -1,9 +1,9 @@ @@ -1,9 +1,9 @@
1: undefined  1: undefined
2make: in target "unclosed-variable": Unclosed variable "UNCLOSED" 2make: in target "unclosed-expression": Unclosed variable "UNCLOSED"
3: unclosed-variable  3: unclosed-expression
4make: Unclosed expression, expecting '}' for "UNCLOSED" 4make: Unclosed expression, expecting '}' for "UNCLOSED"
5: unclosed-modifier  5: unclosed-modifier
6make: in target "unknown-modifier": while evaluating variable "UNKNOWN": Unknown modifier "Z" 6make: in target "unknown-modifier": while evaluating variable "UNKNOWN": Unknown modifier "Z"
7: unknown-modifier  7: unknown-modifier
8: end 8: end
9exit status 2 9exit status 2

cvs diff -r1.5 -r1.6 src/usr.bin/make/unit-tests/cmd-errors.mk (expand / switch to unified diff)

--- src/usr.bin/make/unit-tests/cmd-errors.mk 2022/09/25 12:51:37 1.5
+++ src/usr.bin/make/unit-tests/cmd-errors.mk 2024/04/23 22:51:28 1.6
@@ -1,27 +1,28 @@ @@ -1,27 +1,28 @@
1# $NetBSD: cmd-errors.mk,v 1.5 2022/09/25 12:51:37 rillig Exp $ 1# $NetBSD: cmd-errors.mk,v 1.6 2024/04/23 22:51:28 rillig Exp $
2# 2#
3# Demonstrate how errors in variable expansions affect whether the commands 3# Demonstrate how errors in expressions affect whether the commands
4# are actually executed in compat mode. 4# are actually executed in compat mode.
5 5
6all: undefined unclosed-variable unclosed-modifier unknown-modifier end 6all: undefined unclosed-expression unclosed-modifier unknown-modifier end
7 7
8# Undefined variables are not an error. They expand to empty strings. 8# Undefined variables in expressions are not an error. They expand to empty
 9# strings.
9undefined: 10undefined:
10 : $@-${UNDEFINED}-eol 11 : $@-${UNDEFINED}-eol
11 12
12# XXX: As of 2020-11-01, this command is executed even though it contains 13# XXX: As of 2020-11-01, this command is executed even though it contains
13# parse errors. 14# parse errors.
14unclosed-variable: 15unclosed-expression:
15 : $@-${UNCLOSED 16 : $@-${UNCLOSED
16 17
17# XXX: As of 2020-11-01, this command is executed even though it contains 18# XXX: As of 2020-11-01, this command is executed even though it contains
18# parse errors. 19# parse errors.
19unclosed-modifier: 20unclosed-modifier:
20 : $@-${UNCLOSED: 21 : $@-${UNCLOSED:
21 22
22# XXX: As of 2020-11-01, this command is executed even though it contains 23# XXX: As of 2020-11-01, this command is executed even though it contains
23# parse errors. 24# parse errors.
24unknown-modifier: 25unknown-modifier:
25 : $@-${UNKNOWN:Z}-eol 26 : $@-${UNKNOWN:Z}-eol
26 27
27end: 28end:

cvs diff -r1.3 -r1.4 src/usr.bin/make/unit-tests/cmd-errors-jobs.mk (expand / switch to unified diff)

--- src/usr.bin/make/unit-tests/cmd-errors-jobs.mk 2024/04/20 10:18:55 1.3
+++ src/usr.bin/make/unit-tests/cmd-errors-jobs.mk 2024/04/23 22:51:28 1.4
@@ -1,31 +1,32 @@ @@ -1,31 +1,32 @@
1# $NetBSD: cmd-errors-jobs.mk,v 1.3 2024/04/20 10:18:55 rillig Exp $ 1# $NetBSD: cmd-errors-jobs.mk,v 1.4 2024/04/23 22:51:28 rillig Exp $
2# 2#
3# Demonstrate how errors in variable expansions affect whether the commands 3# Demonstrate how errors in expressions affect whether the commands
4# are actually executed in jobs mode. 4# are actually executed in jobs mode.
5 5
6.MAKEFLAGS: -j1 6.MAKEFLAGS: -j1
7 7
8all: undefined unclosed-variable unclosed-modifier unknown-modifier end 8all: undefined unclosed-expression unclosed-modifier unknown-modifier end
9 9
10# Undefined variables are not an error. They expand to empty strings. 10# Undefined variables in expressions are not an error. They expand to empty
 11# strings.
11# expect: : undefined--eol 12# expect: : undefined--eol
12undefined: 13undefined:
13 : $@-${UNDEFINED}-eol 14 : $@-${UNDEFINED}-eol
14 15
15# XXX: This command is executed even though it contains parse errors. 16# XXX: This command is executed even though it contains parse errors.
16# expect: make: in target "unclosed-variable": Unclosed variable "UNCLOSED" 17# expect: make: in target "unclosed-expression": Unclosed variable "UNCLOSED"
17# expect: : unclosed-variable- 18# expect: : unclosed-expression-
18unclosed-variable: 19unclosed-expression:
19 : $@-${UNCLOSED 20 : $@-${UNCLOSED
20 21
21# XXX: This command is executed even though it contains parse errors. 22# XXX: This command is executed even though it contains parse errors.
22# expect: make: Unclosed expression, expecting '}' for "UNCLOSED" 23# expect: make: Unclosed expression, expecting '}' for "UNCLOSED"
23# expect: : unclosed-modifier- 24# expect: : unclosed-modifier-
24unclosed-modifier: 25unclosed-modifier:
25 : $@-${UNCLOSED: 26 : $@-${UNCLOSED:
26 27
27# XXX: This command is executed even though it contains parse errors. 28# XXX: This command is executed even though it contains parse errors.
28# expect: make: in target "unknown-modifier": while evaluating variable "UNKNOWN": Unknown modifier "Z" 29# expect: make: in target "unknown-modifier": while evaluating variable "UNKNOWN": Unknown modifier "Z"
29# expect: : unknown-modifier--eol 30# expect: : unknown-modifier--eol
30unknown-modifier: 31unknown-modifier:
31 : $@-${UNKNOWN:Z}-eol 32 : $@-${UNKNOWN:Z}-eol

cvs diff -r1.1 -r1.2 src/usr.bin/make/unit-tests/cmd-errors-lint.mk (expand / switch to unified diff)

--- src/usr.bin/make/unit-tests/cmd-errors-lint.mk 2020/11/02 20:43:27 1.1
+++ src/usr.bin/make/unit-tests/cmd-errors-lint.mk 2024/04/23 22:51:28 1.2
@@ -1,30 +1,31 @@ @@ -1,30 +1,31 @@
1# $NetBSD: cmd-errors-lint.mk,v 1.1 2020/11/02 20:43:27 rillig Exp $ 1# $NetBSD: cmd-errors-lint.mk,v 1.2 2024/04/23 22:51:28 rillig Exp $
2# 2#
3# Demonstrate how errors in variable expansions affect whether the commands 3# Demonstrate how errors in expressions affect whether the commands
4# are actually executed. 4# are actually executed.
5 5
6.MAKEFLAGS: -dL 6.MAKEFLAGS: -dL
7 7
8all: undefined unclosed-variable unclosed-modifier unknown-modifier end 8all: undefined unclosed-expression unclosed-modifier unknown-modifier end
9 9
10# Undefined variables are not an error. They expand to empty strings. 10# Undefined variables in expressions are not an error. They expand to empty
 11# strings.
11undefined: 12undefined:
12 : $@ ${UNDEFINED} 13 : $@ ${UNDEFINED}
13 14
14# XXX: As of 2020-11-01, this obvious syntax error is not detected. 15# XXX: As of 2020-11-01, this obvious syntax error is not detected.
15# XXX: As of 2020-11-01, this command is executed even though it contains 16# XXX: As of 2020-11-01, this command is executed even though it contains
16# parse errors. 17# parse errors.
17unclosed-variable: 18unclosed-expression:
18 : $@ ${UNCLOSED 19 : $@ ${UNCLOSED
19 20
20# XXX: As of 2020-11-01, this obvious syntax error is not detected. 21# XXX: As of 2020-11-01, this obvious syntax error is not detected.
21# XXX: As of 2020-11-01, this command is executed even though it contains 22# XXX: As of 2020-11-01, this command is executed even though it contains
22# parse errors. 23# parse errors.
23unclosed-modifier: 24unclosed-modifier:
24 : $@ ${UNCLOSED: 25 : $@ ${UNCLOSED:
25 26
26# XXX: As of 2020-11-01, this command is executed even though it contains 27# XXX: As of 2020-11-01, this command is executed even though it contains
27# parse errors. 28# parse errors.
28unknown-modifier: 29unknown-modifier:
29 : $@ ${UNKNOWN:Z} 30 : $@ ${UNKNOWN:Z}
30 31

cvs diff -r1.8 -r1.9 src/usr.bin/make/unit-tests/cmd-errors.exp (expand / switch to unified diff)

--- src/usr.bin/make/unit-tests/cmd-errors.exp 2024/04/20 10:18:55 1.8
+++ src/usr.bin/make/unit-tests/cmd-errors.exp 2024/04/23 22:51:28 1.9
@@ -1,9 +1,9 @@ @@ -1,9 +1,9 @@
1: undefined--eol 1: undefined--eol
2make: in target "unclosed-variable": Unclosed variable "UNCLOSED" 2make: in target "unclosed-expression": Unclosed variable "UNCLOSED"
3: unclosed-variable- 3: unclosed-expression-
4make: Unclosed expression, expecting '}' for "UNCLOSED" 4make: Unclosed expression, expecting '}' for "UNCLOSED"
5: unclosed-modifier- 5: unclosed-modifier-
6make: in target "unknown-modifier": while evaluating variable "UNKNOWN": Unknown modifier "Z" 6make: in target "unknown-modifier": while evaluating variable "UNKNOWN": Unknown modifier "Z"
7: unknown-modifier--eol 7: unknown-modifier--eol
8: end-eol 8: end-eol
9exit status 0 9exit status 0

cvs diff -r1.8 -r1.9 src/usr.bin/make/unit-tests/cond-func-defined.exp (expand / switch to unified diff)

--- src/usr.bin/make/unit-tests/cond-func-defined.exp 2023/11/19 21:47:52 1.8
+++ src/usr.bin/make/unit-tests/cond-func-defined.exp 2024/04/23 22:51:28 1.9
@@ -1,8 +1,5 @@ @@ -1,8 +1,5 @@
1make: "cond-func-defined.mk" line 24: Missing closing parenthesis for defined() 1make: "cond-func-defined.mk" line 24: Missing closing parenthesis for defined()
2make: "cond-func-defined.mk" line 34: Missing closing parenthesis for defined() 2make: "cond-func-defined.mk" line 34: Missing closing parenthesis for defined()
3make: "cond-func-defined.mk" line 47: In .for loops, expressions for the loop variables are 
4make: "cond-func-defined.mk" line 49: substituted at evaluation time. There is no actual variable 
5make: "cond-func-defined.mk" line 51: involved, even if it feels like it. 
6make: Fatal errors encountered -- cannot continue 3make: Fatal errors encountered -- cannot continue
7make: stopped in unit-tests 4make: stopped in unit-tests
8exit status 1 5exit status 1

cvs diff -r1.4 -r1.5 src/usr.bin/make/unit-tests/cmdline-undefined.mk (expand / switch to unified diff)

--- src/usr.bin/make/unit-tests/cmdline-undefined.mk 2023/11/19 21:47:52 1.4
+++ src/usr.bin/make/unit-tests/cmdline-undefined.mk 2024/04/23 22:51:28 1.5
@@ -1,16 +1,16 @@ @@ -1,16 +1,16 @@
1# $NetBSD: cmdline-undefined.mk,v 1.4 2023/11/19 21:47:52 rillig Exp $ 1# $NetBSD: cmdline-undefined.mk,v 1.5 2024/04/23 22:51:28 rillig Exp $
2# 2#
3# Tests for undefined expressions in the command line. 3# Tests for undefined variables in expressions in the command line.
4 4
5all: 5all:
6 # When the command line is parsed, variable assignments using the 6 # When the command line is parsed, variable assignments using the
7 # '=' assignment operator do get their variable name expanded 7 # '=' assignment operator do get their variable name expanded
8 # (which probably occurs rarely in practice, if at all), but their 8 # (which probably occurs rarely in practice, if at all), but their
9 # variable value is not expanded, as usual. 9 # variable value is not expanded, as usual.
10 # 10 #
11 @echo 'The = assignment operator' 11 @echo 'The = assignment operator'
12 @${.MAKE} -f ${MAKEFILE} print-undefined \ 12 @${.MAKE} -f ${MAKEFILE} print-undefined \
13 CMDLINE='Undefined is $${UNDEFINED}.' 13 CMDLINE='Undefined is $${UNDEFINED}.'
14 @echo 14 @echo
15 15
16 # The interesting case is using the ':=' assignment operator, which 16 # The interesting case is using the ':=' assignment operator, which

cvs diff -r1.4 -r1.5 src/usr.bin/make/unit-tests/cmdline.mk (expand / switch to unified diff)

--- src/usr.bin/make/unit-tests/cmdline.mk 2022/06/10 18:58:07 1.4
+++ src/usr.bin/make/unit-tests/cmdline.mk 2024/04/23 22:51:28 1.5
@@ -1,40 +1,40 @@ @@ -1,40 +1,40 @@
1# $NetBSD: cmdline.mk,v 1.4 2022/06/10 18:58:07 rillig Exp $ 1# $NetBSD: cmdline.mk,v 1.5 2024/04/23 22:51:28 rillig Exp $
2# 2#
3# Tests for command line parsing and related special variables. 3# Tests for command line parsing and related special variables.
4 4
5TMPBASE?= ${TMPDIR:U/tmp/uid${.MAKE.UID}} 5TMPBASE?= ${TMPDIR:U/tmp/uid${.MAKE.UID}}
6SUB1= a7b41170-53f8-4cc2-bc5c-e4c3dd93ec45 # just a random UUID 6SUB1= a7b41170-53f8-4cc2-bc5c-e4c3dd93ec45 # just a random UUID
7SUB2= 6a8899d2-d227-4b55-9b6b-f3c8eeb83fd5 # just a random UUID 7SUB2= 6a8899d2-d227-4b55-9b6b-f3c8eeb83fd5 # just a random UUID
8MAKE_CMD= env TMPBASE=${TMPBASE}/${SUB1} ${.MAKE} -f ${MAKEFILE} -r 8MAKE_CMD= env TMPBASE=${TMPBASE}/${SUB1} ${.MAKE} -f ${MAKEFILE} -r
9DIR2= ${TMPBASE}/${SUB2} 9DIR2= ${TMPBASE}/${SUB2}
10DIR12= ${TMPBASE}/${SUB1}/${SUB2} 10DIR12= ${TMPBASE}/${SUB1}/${SUB2}
11 11
12all: prepare-dirs 12all: prepare-dirs
13all: makeobjdir-direct makeobjdir-indirect 13all: makeobjdir-direct makeobjdir-indirect
14all: space-and-comment 14all: space-and-comment
15 15
16prepare-dirs: 16prepare-dirs:
17 @rm -rf ${DIR2} ${DIR12} 17 @rm -rf ${DIR2} ${DIR12}
18 @mkdir -p ${DIR2} ${DIR12} 18 @mkdir -p ${DIR2} ${DIR12}
19 19
20# The .OBJDIR can be set via the MAKEOBJDIR command line variable. 20# The .OBJDIR can be set via the MAKEOBJDIR command line variable.
21# It must be a command line variable; an environment variable would not work. 21# It must be a command line variable; an environment variable would not work.
22makeobjdir-direct: 22makeobjdir-direct:
23 @echo $@: 23 @echo $@:
24 @${MAKE_CMD} MAKEOBJDIR=${DIR2} show-objdir 24 @${MAKE_CMD} MAKEOBJDIR=${DIR2} show-objdir
25 25
26# The .OBJDIR can be set via the MAKEOBJDIR command line variable, 26# The .OBJDIR can be set via the MAKEOBJDIR command line variable,
27# and that variable could even contain the usual modifiers. 27# and expressions based on that variable can contain the usual modifiers.
28# Since the .OBJDIR=MAKEOBJDIR assignment happens very early, 28# Since the .OBJDIR=MAKEOBJDIR assignment happens very early,
29# the SUB2 variable in the modifier is not defined yet and is therefore empty. 29# the SUB2 variable in the modifier is not defined yet and is therefore empty.
30# The SUB1 in the resulting path comes from the environment variable TMPBASE, 30# The SUB1 in the resulting path comes from the environment variable TMPBASE,
31# see MAKE_CMD. 31# see MAKE_CMD.
32makeobjdir-indirect: 32makeobjdir-indirect:
33 @echo $@: 33 @echo $@:
34 @${MAKE_CMD} MAKEOBJDIR='$${TMPBASE}/$${SUB2}' show-objdir 34 @${MAKE_CMD} MAKEOBJDIR='$${TMPBASE}/$${SUB2}' show-objdir
35 35
36show-objdir: 36show-objdir:
37 @echo $@: ${.OBJDIR:Q} 37 @echo $@: ${.OBJDIR:Q}
38 38
39 39
40# Variable assignments in the command line are handled differently from 40# Variable assignments in the command line are handled differently from

cvs diff -r1.6 -r1.7 src/usr.bin/make/unit-tests/comment.mk (expand / switch to unified diff)

--- src/usr.bin/make/unit-tests/comment.mk 2023/11/19 21:47:52 1.6
+++ src/usr.bin/make/unit-tests/comment.mk 2024/04/23 22:51:28 1.7
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1# $NetBSD: comment.mk,v 1.6 2023/11/19 21:47:52 rillig Exp $ 1# $NetBSD: comment.mk,v 1.7 2024/04/23 22:51:28 rillig Exp $
2# 2#
3# Demonstrate how comments are written in makefiles. 3# Demonstrate how comments are written in makefiles.
4 4
5# This is a comment. 5# This is a comment.
6 6
7#\ 7#\
8This is a multiline comment. 8This is a multiline comment.
9 9
10# Another multiline comment \ 10# Another multiline comment \
11that \ 11that \
12goes \ 12goes \
13on and on. 13on and on.
14 14
@@ -43,29 +43,29 @@ VAR= value @@ -43,29 +43,29 @@ VAR= value
43# not count as a line continuation, therefore the variable assignment that 43# not count as a line continuation, therefore the variable assignment that
44# follows is actively interpreted. \\ 44# follows is actively interpreted. \\
45VAR= not part of the comment 45VAR= not part of the comment
46.if ${VAR} != "not part of the comment" 46.if ${VAR} != "not part of the comment"
47. error 47. error
48.endif 48.endif
49 49
50# To escape a comment sign, precede it with a backslash. 50# To escape a comment sign, precede it with a backslash.
51VAR= \# # Both in the assignment. 51VAR= \# # Both in the assignment.
52.if ${VAR} != "\#" # And in the comparison. 52.if ${VAR} != "\#" # And in the comparison.
53. error 53. error
54.endif 54.endif
55 55
56# Since 2012-03-24 the variable modifier :[#] does not need to be escaped. 56# Since 2012-03-24 the modifier :[#] does not need to be escaped.
57# To keep the parsing code simple, any "[#" does not start a comment, even 57# To keep the parsing code simple, the "#" in "[#" does not start a comment,
58# outside of an expression. 58# regardless of the syntactical context it appears in.
59WORDS= ${VAR:[#]} [# 59WORDS= ${VAR:[#]} [#
60.if ${WORDS} != "1 [#" 60.if ${WORDS} != "1 [#"
61. error 61. error
62.endif 62.endif
63 63
64# An odd number of backslashes makes a line continuation, \\\ 64# An odd number of backslashes makes a line continuation, \\\
65no matter if it is 3 or 5 \\\\\ 65no matter if it is 3 or 5 \\\\\
66or 9 backslashes. \\\\\\\\\ 66or 9 backslashes. \\\\\\\\\
67This is the last line of the comment. 67This is the last line of the comment.
68VAR= no comment anymore 68VAR= no comment anymore
69.if ${VAR} != "no comment anymore" 69.if ${VAR} != "no comment anymore"
70. error 70. error
71.endif 71.endif

cvs diff -r1.18 -r1.19 src/usr.bin/make/unit-tests/cond-cmp-string.mk (expand / switch to unified diff)

--- src/usr.bin/make/unit-tests/cond-cmp-string.mk 2023/11/19 21:47:52 1.18
+++ src/usr.bin/make/unit-tests/cond-cmp-string.mk 2024/04/23 22:51:28 1.19
@@ -1,41 +1,41 @@ @@ -1,41 +1,41 @@
1# $NetBSD: cond-cmp-string.mk,v 1.18 2023/11/19 21:47:52 rillig Exp $ 1# $NetBSD: cond-cmp-string.mk,v 1.19 2024/04/23 22:51:28 rillig Exp $
2# 2#
3# Tests for string comparisons in .if conditions. 3# Tests for string comparisons in .if conditions.
4 4
5# This is a simple comparison of string literals. 5# This is a simple comparison of string literals.
6# Nothing surprising here. 6# Nothing surprising here.
7.if "str" != "str" 7.if "str" != "str"
8. error 8. error
9.endif 9.endif
10 10
11# The right-hand side of the comparison may be written without quotes. 11# The right-hand side of the comparison may be written without quotes.
12.if "str" != str 12.if "str" != str
13. error 13. error
14.endif 14.endif
15 15
16# The left-hand side of the comparison must be enclosed in quotes. 16# The left-hand side of the comparison must be enclosed in quotes.
17# This one is not enclosed in quotes and thus generates an error message. 17# This one is not enclosed in quotes and thus generates an error message.
18# expect+1: Malformed conditional (str != str) 18# expect+1: Malformed conditional (str != str)
19.if str != str 19.if str != str
20. error 20. error
21.endif 21.endif
22 22
23# The left-hand side of the comparison requires that any expression 23# An expression that occurs on the left-hand side of the comparison must be
24# is defined. 24# defined.
25# 25#
26# The variable named "" is never defined, nevertheless it can be used as a 26# The variable named "" is never defined, nevertheless it can be used as a
27# starting point for expressions. Applying the :U modifier to such 27# starting point for an expression. Applying the :U modifier to such an
28# an undefined expression turns it into a defined expression. 28# undefined expression turns it into a defined expression.
29# 29#
30# See ApplyModifier_Defined and DEF_DEFINED. 30# See ApplyModifier_Defined and DEF_DEFINED.
31.if ${:Ustr} != "str" 31.if ${:Ustr} != "str"
32. error 32. error
33.endif 33.endif
34 34
35# Any character in a string literal may be escaped using a backslash. 35# Any character in a string literal may be escaped using a backslash.
36# This means that "\n" does not mean a newline but a simple "n". 36# This means that "\n" does not mean a newline but a simple "n".
37.if "string" != "\s\t\r\i\n\g" 37.if "string" != "\s\t\r\i\n\g"
38. error 38. error
39.endif 39.endif
40 40
41# It is not possible to concatenate two string literals to form a single 41# It is not possible to concatenate two string literals to form a single
@@ -59,53 +59,53 @@ @@ -59,53 +59,53 @@
59# expect+1: Malformed conditional (!("value" === "value")) 59# expect+1: Malformed conditional (!("value" === "value"))
60.if !("value" === "value") 60.if !("value" === "value")
61. error 61. error
62.else 62.else
63. error 63. error
64.endif 64.endif
65 65
66# An expression can be enclosed in double quotes. 66# An expression can be enclosed in double quotes.
67.if ${:Uword} != "${:Uword}" 67.if ${:Uword} != "${:Uword}"
68. error 68. error
69.endif 69.endif
70 70
71# Between 2003-01-01 (maybe even earlier) and 2020-10-30, adding one of the 71# Between 2003-01-01 (maybe even earlier) and 2020-10-30, adding one of the
72# characters " \t!=><" directly after an expression resulted in a 72# characters " \t!=><" directly after an expression in a string literal
73# "Malformed conditional", even though the string was well-formed. 73# resulted in a "Malformed conditional", even though the string was
 74# well-formed.
74.if ${:Uword } != "${:Uword} " 75.if ${:Uword } != "${:Uword} "
75. error 76. error
76.endif 77.endif
77# Some other characters worked though, and some didn't. 78# Some other characters worked though, and some didn't.
78# Those that are mentioned in is_separator didn't work. 79# Those that are mentioned in is_separator didn't work.
79.if ${:Uword0} != "${:Uword}0" 80.if ${:Uword0} != "${:Uword}0"
80. error 81. error
81.endif 82.endif
82.if ${:Uword&} != "${:Uword}&" 83.if ${:Uword&} != "${:Uword}&"
83. error 84. error
84.endif 85.endif
85.if ${:Uword!} != "${:Uword}!" 86.if ${:Uword!} != "${:Uword}!"
86. error 87. error
87.endif 88.endif
88.if ${:Uword<} != "${:Uword}<" 89.if ${:Uword<} != "${:Uword}<"
89. error 90. error
90.endif 91.endif
91 92
92# Adding another expression to the string literal works though. 93# Adding another expression to the string literal works though.
93.if ${:Uword} != "${:Uwo}${:Urd}" 94.if ${:Uword} != "${:Uwo}${:Urd}"
94. error 95. error
95.endif 96.endif
96 97
97# Adding a space at the beginning of the quoted expression works 98# Adding a space at the beginning of the quoted expression works though.
98# though. 
99.if ${:U word } != " ${:Uword} " 99.if ${:U word } != " ${:Uword} "
100. error 100. error
101.endif 101.endif
102 102
103# If at least one side of the comparison is a string literal, the string 103# If at least one side of the comparison is a string literal, the string
104# comparison is performed. 104# comparison is performed.
105.if 12345 != "12345" 105.if 12345 != "12345"
106. error 106. error
107.endif 107.endif
108 108
109# If at least one side of the comparison is a string literal, the string 109# If at least one side of the comparison is a string literal, the string
110# comparison is performed. The ".0" in the left-hand side makes the two 110# comparison is performed. The ".0" in the left-hand side makes the two
111# sides of the equation unequal. 111# sides of the equation unequal.
@@ -135,20 +135,20 @@ @@ -135,20 +135,20 @@
135. error 135. error
136.else 136.else
137. error 137. error
138.endif 138.endif
139 139
140# Strings cannot be compared relationally, only for equality. 140# Strings cannot be compared relationally, only for equality.
141# expect+1: Comparison with '>=' requires both operands 'string' and 'string' to be numeric 141# expect+1: Comparison with '>=' requires both operands 'string' and 'string' to be numeric
142.if "string" >= "string" 142.if "string" >= "string"
143. error 143. error
144.else 144.else
145. error 145. error
146.endif 146.endif
147 147
148# Two variables with different values compare unequal. 148# Two expressions with different values compare unequal.
149VAR1= value1 149VAR1= value1
150VAR2= value2 150VAR2= value2
151.if ${VAR1} != ${VAR2} 151.if ${VAR1} != ${VAR2}
152.else 152.else
153. error 153. error
154.endif 154.endif

cvs diff -r1.11 -r1.12 src/usr.bin/make/unit-tests/cond-func-defined.mk (expand / switch to unified diff)

--- src/usr.bin/make/unit-tests/cond-func-defined.mk 2023/11/19 21:47:52 1.11
+++ src/usr.bin/make/unit-tests/cond-func-defined.mk 2024/04/23 22:51:28 1.12
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1# $NetBSD: cond-func-defined.mk,v 1.11 2023/11/19 21:47:52 rillig Exp $ 1# $NetBSD: cond-func-defined.mk,v 1.12 2024/04/23 22:51:28 rillig Exp $
2# 2#
3# Tests for the defined() function in .if conditions. 3# Tests for the defined() function in .if conditions.
4 4
5DEF= defined 5DEF= defined
6${:UA B}= variable name with spaces 6${:UA B}= variable name with spaces
7 7
8.if !defined(DEF) 8.if !defined(DEF)
9. error 9. error
10.endif 10.endif
11 11
12# Horizontal whitespace (space tab) after the opening parenthesis is ignored. 12# Horizontal whitespace (space tab) after the opening parenthesis is ignored.
13.if !defined( DEF) 13.if !defined( DEF)
14. error 14. error
@@ -33,29 +33,26 @@ ${:UA B}= variable name with spaces @@ -33,29 +33,26 @@ ${:UA B}= variable name with spaces
33# expect+1: Missing closing parenthesis for defined() 33# expect+1: Missing closing parenthesis for defined()
34.if defined(DEF 34.if defined(DEF
35. error 35. error
36.else 36.else
37. error 37. error
38.endif 38.endif
39 39
40# Variables from .for loops are not defined. 40# Variables from .for loops are not defined.
41# See directive-for.mk for more details. 41# See directive-for.mk for more details.
42.for var in value 42.for var in value
43. if defined(var) 43. if defined(var)
44. error 44. error
45. else 45. else
46# expect+1: In .for loops, expressions for the loop variables are 46# In .for loops, expressions based on the loop variables are substituted at
47. info In .for loops, expressions for the loop variables are 47# evaluation time. There is no actual variable involved, even if the code in
48# expect+1: substituted at evaluation time. There is no actual variable 48# the makefiles looks like it.
49. info substituted at evaluation time. There is no actual variable 
50# expect+1: involved, even if it feels like it. 
51. info involved, even if it feels like it. 
52. endif 49. endif
53.endfor 50.endfor
54 51
55# Neither of the conditions is true. Before July 2020, the right-hand 52# Neither of the conditions is true. Before July 2020, the right-hand
56# condition was evaluated even though it was irrelevant. 53# condition was evaluated even though it was irrelevant.
57.if defined(UNDEF) && ${UNDEF:Mx} != "" 54.if defined(UNDEF) && ${UNDEF:Mx} != ""
58. error 55. error
59.endif 56.endif
60 57
61all: .PHONY 58all: .PHONY

cvs diff -r1.27 -r1.28 src/usr.bin/make/unit-tests/varmod-ifelse.mk (expand / switch to unified diff)

--- src/usr.bin/make/unit-tests/varmod-ifelse.mk 2024/04/20 10:18:55 1.27
+++ src/usr.bin/make/unit-tests/varmod-ifelse.mk 2024/04/23 22:51:28 1.28
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1# $NetBSD: varmod-ifelse.mk,v 1.27 2024/04/20 10:18:55 rillig Exp $ 1# $NetBSD: varmod-ifelse.mk,v 1.28 2024/04/23 22:51:28 rillig Exp $
2# 2#
3# Tests for the ${cond:?then:else} variable modifier, which evaluates either 3# Tests for the ${cond:?then:else} variable modifier, which evaluates either
4# the then-expression or the else-expression, depending on the condition. 4# the then-expression or the else-expression, depending on the condition.
5# 5#
6# The modifier was added on 1998-04-01. 6# The modifier was added on 1998-04-01.
7# 7#
8# Until 2015-10-11, the modifier always evaluated both the "then" and the 8# Until 2015-10-11, the modifier always evaluated both the "then" and the
9# "else" expressions. 9# "else" expressions.
10 10
11# TODO: Implementation 11# TODO: Implementation
12 12
13# The variable name of the expression is expanded and then taken as the 13# The variable name of the expression is expanded and then taken as the
14# condition. In the below example it becomes: 14# condition. In the below example it becomes:
@@ -284,24 +284,24 @@ DELAYED= two @@ -284,24 +284,24 @@ DELAYED= two
284.info ${ ${:U \${DELAYED\} == "two"}:?yes:no} 284.info ${ ${:U \${DELAYED\} == "two"}:?yes:no}
285INDIRECT_COND1= $${DELAYED} == "one" 285INDIRECT_COND1= $${DELAYED} == "one"
286# expect+1: no 286# expect+1: no
287.info ${ ${INDIRECT_COND1}:?yes:no} 287.info ${ ${INDIRECT_COND1}:?yes:no}
288INDIRECT_COND2= $${DELAYED} == "two" 288INDIRECT_COND2= $${DELAYED} == "two"
289# expect+1: yes 289# expect+1: yes
290.info ${ ${INDIRECT_COND2}:?yes:no} 290.info ${ ${INDIRECT_COND2}:?yes:no}
291 291
292 292
293.MAKEFLAGS: -d0 293.MAKEFLAGS: -d0
294 294
295 295
296# In the modifier parts for the 'then' and 'else' branches, subexpressions are 296# In the modifier parts for the 'then' and 'else' branches, subexpressions are
297# parsed in by inspecting the actual modifiers. In 2008, 2015, 2020, 2022 and 297# parsed by inspecting the actual modifiers. In 2008, 2015, 2020, 2022 and
298# 2023, the exact parsing algorithm switched a few times, counting balanced 298# 2023, the exact parsing algorithm switched a few times, counting balanced
299# braces instead of proper subexpressions, which meant that unbalanced braces 299# braces instead of proper subexpressions, which meant that unbalanced braces
300# were parsed differently, depending on whether the branch was active or not. 300# were parsed differently, depending on whether the branch was active or not.
301BRACES= }}} 301BRACES= }}}
302NO= ${0:?${BRACES:S,}}},yes,}:${BRACES:S,}}},no,}} 302NO= ${0:?${BRACES:S,}}},yes,}:${BRACES:S,}}},no,}}
303YES= ${1:?${BRACES:S,}}},yes,}:${BRACES:S,}}},no,}} 303YES= ${1:?${BRACES:S,}}},yes,}:${BRACES:S,}}},no,}}
304BOTH= <${YES}> <${NO}> 304BOTH= <${YES}> <${NO}>
305.if ${BOTH} != "<yes> <no>" 305.if ${BOTH} != "<yes> <no>"
306. error 306. error
307.endif 307.endif

cvs diff -r1.15 -r1.16 src/usr.bin/make/unit-tests/varmod-match.exp (expand / switch to unified diff)

--- src/usr.bin/make/unit-tests/varmod-match.exp 2024/04/20 10:18:55 1.15
+++ src/usr.bin/make/unit-tests/varmod-match.exp 2024/04/23 22:51:28 1.16
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1make: "varmod-match.mk" line 289: while evaluating variable "WORDS": warning: Unfinished character list in pattern 'a[' of modifier ':M' 1make: "varmod-match.mk" line 290: while evaluating variable "WORDS": warning: Unfinished character list in pattern 'a[' of modifier ':M'
2make: "varmod-match.mk" line 297: while evaluating variable "WORDS": warning: Unfinished character list in pattern 'a[^' of modifier ':M' 2make: "varmod-match.mk" line 298: while evaluating variable "WORDS": warning: Unfinished character list in pattern 'a[^' of modifier ':M'
3make: "varmod-match.mk" line 305: while evaluating variable "WORDS": warning: Unfinished character list in pattern '[-x1-3' of modifier ':M' 3make: "varmod-match.mk" line 306: while evaluating variable "WORDS": warning: Unfinished character list in pattern '[-x1-3' of modifier ':M'
4make: "varmod-match.mk" line 313: while evaluating variable "WORDS": warning: Unfinished character list in pattern '*[-x1-3' of modifier ':M' 4make: "varmod-match.mk" line 314: while evaluating variable "WORDS": warning: Unfinished character list in pattern '*[-x1-3' of modifier ':M'
5make: "varmod-match.mk" line 322: while evaluating variable "WORDS": warning: Unfinished character list in pattern '[^-x1-3' of modifier ':M' 5make: "varmod-match.mk" line 323: while evaluating variable "WORDS": warning: Unfinished character list in pattern '[^-x1-3' of modifier ':M'
6make: "varmod-match.mk" line 336: while evaluating variable "WORDS": warning: Unfinished character list in pattern '?[\' of modifier ':M' 6make: "varmod-match.mk" line 337: while evaluating variable "WORDS": warning: Unfinished character list in pattern '?[\' of modifier ':M'
7make: "varmod-match.mk" line 344: while evaluating variable "WORDS": warning: Unfinished character range in pattern '[x-' of modifier ':M' 7make: "varmod-match.mk" line 345: while evaluating variable "WORDS": warning: Unfinished character range in pattern '[x-' of modifier ':M'
8make: "varmod-match.mk" line 356: while evaluating variable "WORDS": warning: Unfinished character range in pattern '[^x-' of modifier ':M' 8make: "varmod-match.mk" line 357: while evaluating variable "WORDS": warning: Unfinished character range in pattern '[^x-' of modifier ':M'
9make: "varmod-match.mk" line 364: while evaluating variable " : :: ": warning: Unfinished character list in pattern '[' of modifier ':M' 9make: "varmod-match.mk" line 365: while evaluating variable " : :: ": warning: Unfinished character list in pattern '[' of modifier ':M'
10make: "varmod-match.mk" line 364: while evaluating variable " : :: ": Unknown modifier "]" 10make: "varmod-match.mk" line 365: while evaluating variable " : :: ": Unknown modifier "]"
11make: "varmod-match.mk" line 364: Malformed conditional (${ ${:U\:} ${:U\:\:} :L:M[:]} != ":") 11make: "varmod-match.mk" line 365: Malformed conditional (${ ${:U\:} ${:U\:\:} :L:M[:]} != ":")
12make: Fatal errors encountered -- cannot continue 12make: Fatal errors encountered -- cannot continue
13make: stopped in unit-tests 13make: stopped in unit-tests
14exit status 1 14exit status 1

cvs diff -r1.21 -r1.22 src/usr.bin/make/unit-tests/varmod-match.mk (expand / switch to unified diff)

--- src/usr.bin/make/unit-tests/varmod-match.mk 2024/04/20 10:18:55 1.21
+++ src/usr.bin/make/unit-tests/varmod-match.mk 2024/04/23 22:51:28 1.22
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1# $NetBSD: varmod-match.mk,v 1.21 2024/04/20 10:18:55 rillig Exp $ 1# $NetBSD: varmod-match.mk,v 1.22 2024/04/23 22:51:28 rillig Exp $
2# 2#
3# Tests for the ':M' modifier, which keeps only those words that match the 3# Tests for the ':M' modifier, which keeps only those words that match the
4# given pattern. 4# given pattern.
5# 5#
6# Table of contents 6# Table of contents
7# 7#
8# 1. Pattern characters '*', '?' and '\' 8# 1. Pattern characters '*', '?' and '\'
9# 2. Character lists and character ranges 9# 2. Character lists and character ranges
10# 3. Parsing and escaping 10# 3. Parsing and escaping
11# 4. Interaction with other modifiers 11# 4. Interaction with other modifiers
12# 5. Performance 12# 5. Performance
13# 6. Error handling 13# 6. Error handling
14# 7. Historical bugs 14# 7. Historical bugs
@@ -23,42 +23,42 @@ @@ -23,42 +23,42 @@
23# ? matches 1 character 23# ? matches 1 character
24# \x matches the character 'x' 24# \x matches the character 'x'
25 25
26# The pattern is anchored both at the beginning and at the end of the word. 26# The pattern is anchored both at the beginning and at the end of the word.
27# Since the pattern 'e' does not contain any pattern matching characters, it 27# Since the pattern 'e' does not contain any pattern matching characters, it
28# matches exactly the word 'e', twice. 28# matches exactly the word 'e', twice.
29.if ${a c e aa cc ee e f g:L:Me} != "e e" 29.if ${a c e aa cc ee e f g:L:Me} != "e e"
30. error 30. error
31.endif 31.endif
32 32
33# The pattern character '?' matches exactly 1 character, the pattern character 33# The pattern character '?' matches exactly 1 character, the pattern character
34# '*' matches 0 or more characters. The whole pattern matches all words that 34# '*' matches 0 or more characters. The whole pattern matches all words that
35# start with 's' and have 3 or more characters. 35# start with 's' and have 3 or more characters.
36.if ${One Two Three Four five six seven:L:Ms??*} != "six seven" 36.if ${One Two Three Four five six seven so s:L:Ms??*} != "six seven"
37. error 37. error
38.endif 38.endif
39 39
40# Ensure that a pattern without placeholders only matches itself. 40# A pattern without placeholders only matches itself.
41.if ${a aa aaa b ba baa bab:L:Ma} != "a" 41.if ${a aa aaa b ba baa bab:L:Ma} != "a"
42. error 42. error
43.endif 43.endif
44 44
45# Ensure that a pattern that ends with '*' is properly anchored at the 45# A pattern that ends with '*' is anchored at the
46# beginning. 46# beginning.
47.if ${a aa aaa b ba baa bab:L:Ma*} != "a aa aaa" 47.if ${a aa aaa b ba baa bab:L:Ma*} != "a aa aaa"
48. error 48. error
49.endif 49.endif
50 50
51# Ensure that a pattern that starts with '*' is properly anchored at the end. 51# A pattern that starts with '*' is anchored at the end.
52.if ${a aa aaa b ba baa bab:L:M*a} != "a aa aaa ba baa" 52.if ${a aa aaa b ba baa bab:L:M*a} != "a aa aaa ba baa"
53. error 53. error
54.endif 54.endif
55 55
56# Test the fast code path for '*' followed by a regular character. 56# Test the fast code path for '*' followed by a regular character.
57.if ${:U file.c file.*c file.h file\.c :M*.c} != "file.c file\\.c" 57.if ${:U file.c file.*c file.h file\.c :M*.c} != "file.c file\\.c"
58. error 58. error
59.endif 59.endif
60# Ensure that the fast code path correctly handles the backslash. 60# Ensure that the fast code path correctly handles the backslash.
61.if ${:U file.c file.*c file.h file\.c :M*\.c} != "file.c file\\.c" 61.if ${:U file.c file.*c file.h file\.c :M*\.c} != "file.c file\\.c"
62. error 62. error
63.endif 63.endif
64# Ensure that the fast code path correctly handles '\*'. 64# Ensure that the fast code path correctly handles '\*'.
@@ -247,28 +247,29 @@ ${:U*}= asterisk @@ -247,28 +247,29 @@ ${:U*}= asterisk
247# TODO: ${VAR:M{{{)))} 247# TODO: ${VAR:M{{{)))}
248# TODO: ${VAR:M${UNBALANCED}} 248# TODO: ${VAR:M${UNBALANCED}}
249# TODO: ${VAR:M${:U(((\}\}\}}} 249# TODO: ${VAR:M${:U(((\}\}\}}}
250 250
251 251
252# 4. Interaction with other modifiers 252# 4. Interaction with other modifiers
253 253
254# The modifier ':tW' prevents splitting at whitespace. Even leading and 254# The modifier ':tW' prevents splitting at whitespace. Even leading and
255# trailing whitespace is preserved. 255# trailing whitespace is preserved.
256.if ${ plain string :L:tW:M*} != " plain string " 256.if ${ plain string :L:tW:M*} != " plain string "
257. error 257. error
258.endif 258.endif
259 259
260# Without the modifier ':tW', the string is split into words. All whitespace 260# Without the modifier ':tW', the string is split into words. Whitespace
261# around and between the words is normalized to a single space. 261# around the words is discarded, and whitespace between the words is
 262# normalized to a single space.
262.if ${ plain string :L:M*} != "plain string" 263.if ${ plain string :L:M*} != "plain string"
263. error 264. error
264.endif 265.endif
265 266
266 267
267# 5. Performance 268# 5. Performance
268 269
269# Before 2020-06-13, this expression called Str_Match 601,080,390 times. 270# Before 2020-06-13, this expression called Str_Match 601,080,390 times.
270# Since 2020-06-13, this expression calls Str_Match 1 time. 271# Since 2020-06-13, this expression calls Str_Match 1 time.
271.if ${:U****************:M****************b} 272.if ${:U****************:M****************b}
272.endif 273.endif
273 274
274# Before 2023-06-22, this expression called Str_Match 2,621,112 times. 275# Before 2023-06-22, this expression called Str_Match 2,621,112 times.
@@ -362,19 +363,26 @@ WORDS= [x- x x- y yyyyy @@ -362,19 +363,26 @@ WORDS= [x- x x- y yyyyy
362# expect+2: while evaluating variable " : :: ": Unknown modifier "]" 363# expect+2: while evaluating variable " : :: ": Unknown modifier "]"
363# expect+1: Malformed conditional (${ ${:U\:} ${:U\:\:} :L:M[:]} != ":") 364# expect+1: Malformed conditional (${ ${:U\:} ${:U\:\:} :L:M[:]} != ":")
364.if ${ ${:U\:} ${:U\:\:} :L:M[:]} != ":" 365.if ${ ${:U\:} ${:U\:\:} :L:M[:]} != ":"
365. error 366. error
366.else 367.else
367. error 368. error
368.endif 369.endif
369 370
370 371
371# 7. Historical bugs 372# 7. Historical bugs
372 373
373# Before var.c 1.1031 from 2022-08-24, the following expressions caused an 374# Before var.c 1.1031 from 2022-08-24, the following expressions caused an
374# out-of-bounds read beyond the indirect ':M' modifiers. 375# out-of-bounds read beyond the indirect ':M' modifiers.
375.if ${:U:${:UM\\}} # The ':M' pattern need not be unescaped, the 376#
376. error # resulting pattern is '\', it never matches 377# The argument to the inner ':U' is unescaped to 'M\'.
377.endif # anything. 378# This 'M\' becomes an # indirect modifier ':M' with the pattern '\'.
378.if ${:U:${:UM\\\:\\}} # The ':M' pattern must be unescaped, the 379# The pattern '\' never matches.
379. error # resulting pattern is ':\', it never matches 380.if ${:U:${:UM\\}}
380.endif # anything. 381. error
 382.endif
 383# The argument to the inner ':U' is unescaped to 'M\:\'.
 384# This 'M\:\' becomes an indirect modifier ':M' with the pattern ':\'.
 385# The pattern ':\' never matches.
 386.if ${:U:${:UM\\\:\\}}
 387. error
 388.endif