Module Name:    src
Committed By:   sjg
Date:           Fri Sep  2 16:24:31 UTC 2022

Modified Files:
        src/usr.bin/make: cond.c for.c make.1 make.h parse.c
        src/usr.bin/make/unit-tests: Makefile
Added Files:
        src/usr.bin/make/unit-tests: directive-for-break.exp
            directive-for-break.mk

Log Message:
make: add .break to terminate .for loop early

When .break is encountered within a .for loop
it causes immediate termination.

Outside of a .for loop .break causes a parse error.

Reviewed by: christos


To generate a diff of this commit:
cvs rdiff -u -r1.334 -r1.335 src/usr.bin/make/cond.c
cvs rdiff -u -r1.168 -r1.169 src/usr.bin/make/for.c
cvs rdiff -u -r1.330 -r1.331 src/usr.bin/make/make.1
cvs rdiff -u -r1.303 -r1.304 src/usr.bin/make/make.h
cvs rdiff -u -r1.681 -r1.682 src/usr.bin/make/parse.c
cvs rdiff -u -r1.321 -r1.322 src/usr.bin/make/unit-tests/Makefile
cvs rdiff -u -r0 -r1.1 src/usr.bin/make/unit-tests/directive-for-break.exp \
    src/usr.bin/make/unit-tests/directive-for-break.mk

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/make/cond.c
diff -u src/usr.bin/make/cond.c:1.334 src/usr.bin/make/cond.c:1.335
--- src/usr.bin/make/cond.c:1.334	Fri Apr 15 09:33:20 2022
+++ src/usr.bin/make/cond.c	Fri Sep  2 16:24:31 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: cond.c,v 1.334 2022/04/15 09:33:20 rillig Exp $	*/
+/*	$NetBSD: cond.c,v 1.335 2022/09/02 16:24:31 sjg Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -95,7 +95,7 @@
 #include "dir.h"
 
 /*	"@(#)cond.c	8.2 (Berkeley) 1/2/94"	*/
-MAKE_RCSID("$NetBSD: cond.c,v 1.334 2022/04/15 09:33:20 rillig Exp $");
+MAKE_RCSID("$NetBSD: cond.c,v 1.335 2022/09/02 16:24:31 sjg Exp $");
 
 /*
  * Conditional expressions conform to this grammar:
@@ -1275,3 +1275,14 @@ Cond_save_depth(void)
 	cond_min_depth = cond_depth;
 	return depth;
 }
+
+/*
+ * When we break out of a .for loop
+ * we want to restore cond_depth to where it was
+ * when the loop started.
+ */
+void
+Cond_reset_depth(unsigned int depth)
+{
+    cond_depth = depth;
+}

Index: src/usr.bin/make/for.c
diff -u src/usr.bin/make/for.c:1.168 src/usr.bin/make/for.c:1.169
--- src/usr.bin/make/for.c:1.168	Sun Jun 12 16:09:21 2022
+++ src/usr.bin/make/for.c	Fri Sep  2 16:24:31 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: for.c,v 1.168 2022/06/12 16:09:21 rillig Exp $	*/
+/*	$NetBSD: for.c,v 1.169 2022/09/02 16:24:31 sjg 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.168 2022/06/12 16:09:21 rillig Exp $");
+MAKE_RCSID("$NetBSD: for.c,v 1.169 2022/09/02 16:24:31 sjg Exp $");
 
 
 typedef struct ForLoop {
@@ -504,3 +504,11 @@ For_Run(unsigned headLineno, unsigned bo
 	} else
 		ForLoop_Free(f);
 }
+
+/* Breaking out of a .for loop */
+void
+For_Break(ForLoop *f)
+{
+    f->nextItem = f->items.len;
+}
+     

Index: src/usr.bin/make/make.1
diff -u src/usr.bin/make/make.1:1.330 src/usr.bin/make/make.1:1.331
--- src/usr.bin/make/make.1:1.330	Sun Aug 14 22:11:20 2022
+++ src/usr.bin/make/make.1	Fri Sep  2 16:24:31 2022
@@ -1,4 +1,4 @@
-.\"	$NetBSD: make.1,v 1.330 2022/08/14 22:11:20 uwe Exp $
+.\"	$NetBSD: make.1,v 1.331 2022/09/02 16:24:31 sjg Exp $
 .\"
 .\" Copyright (c) 1990, 1993
 .\"	The Regents of the University of California.  All rights reserved.
@@ -29,7 +29,7 @@
 .\"
 .\"	from: @(#)make.1	8.4 (Berkeley) 3/19/94
 .\"
-.Dd August 14, 2022
+.Dd September 2, 2022
 .Dt MAKE 1
 .Os
 .Sh NAME
@@ -2084,6 +2084,14 @@ inside the body of the for loop.
 The number of words must come out even; that is, if there are three
 iteration variables, the number of words provided must be a multiple
 of three.
+
+If
+.Sq Ic .break
+is encountered within a
+.Cm \&.for
+loop, it causes early termination of the loop,
+otherwise a parse error.
+
 .Sh COMMENTS
 Comments begin with a hash
 .Pq Ql \&#

Index: src/usr.bin/make/make.h
diff -u src/usr.bin/make/make.h:1.303 src/usr.bin/make/make.h:1.304
--- src/usr.bin/make/make.h:1.303	Sun Jun 12 13:37:32 2022
+++ src/usr.bin/make/make.h	Fri Sep  2 16:24:31 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: make.h,v 1.303 2022/06/12 13:37:32 rillig Exp $	*/
+/*	$NetBSD: make.h,v 1.304 2022/09/02 16:24:31 sjg Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -800,6 +800,7 @@ void Compat_Make(GNode *, GNode *);
 CondResult Cond_EvalCondition(const char *) MAKE_ATTR_USE;
 CondResult Cond_EvalLine(const char *) MAKE_ATTR_USE;
 void Cond_restore_depth(unsigned int);
+void Cond_reset_depth(unsigned int);
 unsigned int Cond_save_depth(void) MAKE_ATTR_USE;
 
 /* dir.c; see also dir.h */
@@ -829,6 +830,7 @@ void For_Run(unsigned, unsigned);
 bool For_NextIteration(struct ForLoop *, Buffer *);
 char *ForLoop_Details(struct ForLoop *);
 void ForLoop_Free(struct ForLoop *);
+void For_Break(struct ForLoop *);
 
 /* job.c */
 void JobReapChild(pid_t, int, bool);

Index: src/usr.bin/make/parse.c
diff -u src/usr.bin/make/parse.c:1.681 src/usr.bin/make/parse.c:1.682
--- src/usr.bin/make/parse.c:1.681	Sun Jul 24 20:25:23 2022
+++ src/usr.bin/make/parse.c	Fri Sep  2 16:24:31 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: parse.c,v 1.681 2022/07/24 20:25:23 rillig Exp $	*/
+/*	$NetBSD: parse.c,v 1.682 2022/09/02 16:24:31 sjg Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -105,7 +105,7 @@
 #include "pathnames.h"
 
 /*	"@(#)parse.c	8.3 (Berkeley) 3/19/94"	*/
-MAKE_RCSID("$NetBSD: parse.c,v 1.681 2022/07/24 20:25:23 rillig Exp $");
+MAKE_RCSID("$NetBSD: parse.c,v 1.682 2022/09/02 16:24:31 sjg Exp $");
 
 /*
  * A file being read.
@@ -2689,7 +2689,17 @@ ParseDirective(char *line)
 	pp_skip_whitespace(&cp);
 	arg = cp;
 
-	if (Substring_Equals(dir, "undef"))
+	if (Substring_Equals(dir, "break")) {
+		IncludedFile *curFile = CurFile();
+
+		if (curFile->forLoop != NULL) {
+			/* pretend we reached EOF */
+			For_Break(curFile->forLoop);
+			Cond_reset_depth(curFile->cond_depth);
+			ParseEOF();
+		} else
+			Parse_Error(PARSE_FATAL, "break outside of for loop");
+	} else if (Substring_Equals(dir, "undef"))
 		Var_Undef(arg);
 	else if (Substring_Equals(dir, "export"))
 		Var_Export(VEM_PLAIN, arg);

Index: src/usr.bin/make/unit-tests/Makefile
diff -u src/usr.bin/make/unit-tests/Makefile:1.321 src/usr.bin/make/unit-tests/Makefile:1.322
--- src/usr.bin/make/unit-tests/Makefile:1.321	Thu Aug 25 06:23:38 2022
+++ src/usr.bin/make/unit-tests/Makefile	Fri Sep  2 16:24:31 2022
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.321 2022/08/25 06:23:38 rillig Exp $
+# $NetBSD: Makefile,v 1.322 2022/09/02 16:24:31 sjg Exp $
 #
 # Unit tests for make(1)
 #
@@ -168,6 +168,7 @@ TESTS+=		directive-export-impl
 TESTS+=		directive-export-gmake
 TESTS+=		directive-export-literal
 TESTS+=		directive-for
+#TESTS+=		directive-for-break
 TESTS+=		directive-for-empty
 TESTS+=		directive-for-errors
 TESTS+=		directive-for-escape

Added files:

Index: src/usr.bin/make/unit-tests/directive-for-break.exp
diff -u /dev/null src/usr.bin/make/unit-tests/directive-for-break.exp:1.1
--- /dev/null	Fri Sep  2 16:24:31 2022
+++ src/usr.bin/make/unit-tests/directive-for-break.exp	Fri Sep  2 16:24:31 2022
@@ -0,0 +1,5 @@
+make: "directive-for-break.mk" line 16: I=3
+make: "directive-for-break.mk" line 24: break outside of for loop
+make: Fatal errors encountered -- cannot continue
+make: stopped in unit-tests
+exit status 1
Index: src/usr.bin/make/unit-tests/directive-for-break.mk
diff -u /dev/null src/usr.bin/make/unit-tests/directive-for-break.mk:1.1
--- /dev/null	Fri Sep  2 16:24:31 2022
+++ src/usr.bin/make/unit-tests/directive-for-break.mk	Fri Sep  2 16:24:31 2022
@@ -0,0 +1,25 @@
+# $NetBSD: directive-for-break.mk,v 1.1 2022/09/02 16:24:31 sjg Exp $
+#
+# Tests for .break in .for loops
+
+I= 0
+LIST= 1 2 3 4 5 6 7 8
+
+# .break terminates the loop early
+# this is usually done within a conditional
+.for i in ${LIST}
+.if $i == 3
+I:= $i
+.break
+.endif
+.endfor
+.info I=$I
+
+# .break outside the context of a .for loop is an error
+.if $I == 0
+# harmless
+.break
+.else
+# error
+.break
+.endif

Reply via email to