Wed Oct 7 16:40:30 2009 UTC ()
The parser used to break dependency lines at ';' without regard
for substitution patterns.  This (perhaps coupled with the
new handling of .for variables in ${:U<value>...) caused interesting
results for lines like:

.for file in ${LIST}
for-subst:       ${file:S;^;${here}/;g}

add a unit-test to keep an eye on this.


(sjg)
diff -r1.157 -r1.158 src/usr.bin/make/parse.c
diff -r1.23 -r1.24 src/usr.bin/make/unit-tests/Makefile
diff -r0 -r1.1 src/usr.bin/make/unit-tests/forsubst
diff -r1.28 -r1.29 src/usr.bin/make/unit-tests/test.exp

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

--- src/usr.bin/make/parse.c 2009/01/23 21:26:30 1.157
+++ src/usr.bin/make/parse.c 2009/10/07 16:40:30 1.158
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: parse.c,v 1.157 2009/01/23 21:26:30 dsl Exp $ */ 1/* $NetBSD: parse.c,v 1.158 2009/10/07 16:40:30 sjg 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.
@@ -59,34 +59,34 @@ @@ -59,34 +59,34 @@
59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 * SUCH DAMAGE. 68 * SUCH DAMAGE.
69 */ 69 */
70 70
71#ifndef MAKE_NATIVE 71#ifndef MAKE_NATIVE
72static char rcsid[] = "$NetBSD: parse.c,v 1.157 2009/01/23 21:26:30 dsl Exp $"; 72static char rcsid[] = "$NetBSD: parse.c,v 1.158 2009/10/07 16:40:30 sjg Exp $";
73#else 73#else
74#include <sys/cdefs.h> 74#include <sys/cdefs.h>
75#ifndef lint 75#ifndef lint
76#if 0 76#if 0
77static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94"; 77static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94";
78#else 78#else
79__RCSID("$NetBSD: parse.c,v 1.157 2009/01/23 21:26:30 dsl Exp $"); 79__RCSID("$NetBSD: parse.c,v 1.158 2009/10/07 16:40:30 sjg Exp $");
80#endif 80#endif
81#endif /* not lint */ 81#endif /* not lint */
82#endif 82#endif
83 83
84/*- 84/*-
85 * parse.c -- 85 * parse.c --
86 * Functions to parse a makefile. 86 * Functions to parse a makefile.
87 * 87 *
88 * One function, Parse_Init, must be called before any functions 88 * One function, Parse_Init, must be called before any functions
89 * in this module are used. After that, the function Parse_File is the 89 * in this module are used. After that, the function Parse_File is the
90 * main entry point and controls most of the other functions in this 90 * main entry point and controls most of the other functions in this
91 * module. 91 * module.
92 * 92 *
@@ -2580,35 +2580,50 @@ Parse_File(const char *name, int fd) @@ -2580,35 +2580,50 @@ Parse_File(const char *name, int fd)
2580 if (inLine) { 2580 if (inLine) {
2581 Parse_Error(PARSE_WARNING, 2581 Parse_Error(PARSE_WARNING,
2582 "Shell command needs a leading tab"); 2582 "Shell command needs a leading tab");
2583 goto shellCommand; 2583 goto shellCommand;
2584 } 2584 }
2585 } 2585 }
2586 } 2586 }
2587#endif 2587#endif
2588 ParseFinishLine(); 2588 ParseFinishLine();
2589 2589
2590 /* 2590 /*
2591 * For some reason - probably to make the parser impossible - 2591 * For some reason - probably to make the parser impossible -
2592 * a ';' can be used to separate commands from dependencies. 2592 * a ';' can be used to separate commands from dependencies.
2593 * No attempt is made to avoid ';' inside substitution patterns. 2593 * Attempt to avoid ';' inside substitution patterns.
2594 */ 2594 */
2595 for (cp = line; *cp != 0; cp++) { 2595 {
2596 if (*cp == '\\' && cp[1] != 0) { 2596 int level = 0;
2597 cp++; 2597
2598 continue; 2598 for (cp = line; *cp != 0; cp++) {
 2599 if (*cp == '\\' && cp[1] != 0) {
 2600 cp++;
 2601 continue;
 2602 }
 2603 if (*cp == '$' &&
 2604 (cp[1] == '(' || cp[1] == '{')) {
 2605 level++;
 2606 continue;
 2607 }
 2608 if (level > 0) {
 2609 if (*cp == ')' || *cp == '}') {
 2610 level--;
 2611 continue;
 2612 }
 2613 } else if (*cp == ';') {
 2614 break;
 2615 }
2599 } 2616 }
2600 if (*cp == ';') 
2601 break; 
2602 } 2617 }
2603 if (*cp != 0) 2618 if (*cp != 0)
2604 /* Terminate the dependency list at the ';' */ 2619 /* Terminate the dependency list at the ';' */
2605 *cp++ = 0; 2620 *cp++ = 0;
2606 else 2621 else
2607 cp = NULL; 2622 cp = NULL;
2608 2623
2609 /* 2624 /*
2610 * We now know it's a dependency line so it needs to have all 2625 * We now know it's a dependency line so it needs to have all
2611 * variables expanded before being parsed. Tell the variable 2626 * variables expanded before being parsed. Tell the variable
2612 * module to complain if some variable is undefined... 2627 * module to complain if some variable is undefined...
2613 */ 2628 */
2614 line = Var_Subst(NULL, line, VAR_CMD, TRUE); 2629 line = Var_Subst(NULL, line, VAR_CMD, TRUE);

cvs diff -r1.23 -r1.24 src/usr.bin/make/unit-tests/Makefile (expand / switch to unified diff)

--- src/usr.bin/make/unit-tests/Makefile 2008/10/25 22:27:39 1.23
+++ src/usr.bin/make/unit-tests/Makefile 2009/10/07 16:40:30 1.24
@@ -1,39 +1,40 @@ @@ -1,39 +1,40 @@
1# $NetBSD: Makefile,v 1.23 2008/10/25 22:27:39 apb Exp $ 1# $NetBSD: Makefile,v 1.24 2009/10/07 16:40:30 sjg Exp $
2# 2#
3# Unit tests for make(1) 3# Unit tests for make(1)
4# The main targets are: 4# The main targets are:
5#  5#
6# all: run all the tests 6# all: run all the tests
7# test: run 'all', capture output and compare to expected results 7# test: run 'all', capture output and compare to expected results
8# accept: move generated output to expected results 8# accept: move generated output to expected results
9# 9#
10# Adding a test case.  10# Adding a test case.
11# Each feature should get its own set of tests in its own suitably 11# Each feature should get its own set of tests in its own suitably
12# named makefile which should be added to SUBFILES to hook it in. 12# named makefile which should be added to SUBFILES to hook it in.
13#  13#
14 14
15.MAIN: all 15.MAIN: all
16 16
17UNIT_TESTS:= ${.PARSEDIR} 17UNIT_TESTS:= ${.PARSEDIR}
18 18
19# Simple sub-makefiles - we run them as a black box 19# Simple sub-makefiles - we run them as a black box
20# keep the list sorted. 20# keep the list sorted.
21SUBFILES= \ 21SUBFILES= \
22 comment \ 22 comment \
23 cond1 \ 23 cond1 \
24 export \ 24 export \
25 export-all \ 25 export-all \
26 dotwait \ 26 dotwait \
 27 forsubst \
27 moderrs \ 28 moderrs \
28 modmatch \ 29 modmatch \
29 modmisc \ 30 modmisc \
30 modorder \ 31 modorder \
31 modts \ 32 modts \
32 modword \ 33 modword \
33 posix \ 34 posix \
34 qequals \ 35 qequals \
35 ternary \ 36 ternary \
36 varcmd 37 varcmd
37 38
38all: ${SUBFILES} 39all: ${SUBFILES}
39 40

File Added: src/usr.bin/make/unit-tests/Attic/forsubst
# $Id: forsubst,v 1.1 2009/10/07 16:40:30 sjg Exp $

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

cvs diff -r1.28 -r1.29 src/usr.bin/make/unit-tests/Attic/test.exp (expand / switch to unified diff)

--- src/usr.bin/make/unit-tests/Attic/test.exp 2009/09/07 17:56:23 1.28
+++ src/usr.bin/make/unit-tests/Attic/test.exp 2009/10/07 16:40:30 1.29
@@ -57,26 +57,27 @@ recursive.2.99 @@ -57,26 +57,27 @@ recursive.2.99
57shared.0 57shared.0
58shared.0 58shared.0
59shared.1.99 59shared.1.99
60shared.1.99 60shared.1.99
61shared.2.1 61shared.2.1
62shared.2.1 62shared.2.1
63shared.2.99 63shared.2.99
64shared.2.99 64shared.2.99
65make: Graph cycles through `cycle.2.99' 65make: Graph cycles through `cycle.2.99'
66make: Graph cycles through `cycle.2.98' 66make: Graph cycles through `cycle.2.98'
67make: Graph cycles through `cycle.2.97' 67make: Graph cycles through `cycle.2.97'
68cycle.1.99 68cycle.1.99
69cycle.1.99 69cycle.1.99
 70.for with :S;... OK
70Expect: Unknown modifier 'Z' 71Expect: Unknown modifier 'Z'
71make: Unknown modifier 'Z' 72make: Unknown modifier 'Z'
72VAR:Z= 73VAR:Z=
73Expect: Unknown modifier 'Z' 74Expect: Unknown modifier 'Z'
74make: Unknown modifier 'Z' 75make: Unknown modifier 'Z'
75VAR:Z= 76VAR:Z=
76Expect: Unclosed variable specification for VAR 77Expect: Unclosed variable specification for VAR
77make: Unclosed variable specification (expecting '}') for "VAR" (value "Thevariable") modifier S 78make: Unclosed variable specification (expecting '}') for "VAR" (value "Thevariable") modifier S
78VAR:S,V,v,=Thevariable 79VAR:S,V,v,=Thevariable
79Expect: Unclosed variable specification for VAR 80Expect: Unclosed variable specification for VAR
80make: Unclosed variable specification after complex modifier (expecting '}') for VAR 81make: Unclosed variable specification after complex modifier (expecting '}') for VAR
81VAR:S,V,v,=Thevariable 82VAR:S,V,v,=Thevariable
82Expect: Unclosed substitution for VAR (, missing) 83Expect: Unclosed substitution for VAR (, missing)