Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/make make: clean up handling of .break in .for loops



details:   https://anonhg.NetBSD.org/src/rev/47a1536914e8
branches:  trunk
changeset: 369829:47a1536914e8
user:      rillig <rillig%NetBSD.org@localhost>
date:      Sat Sep 03 00:50:07 2022 +0000

description:
make: clean up handling of .break in .for loops

Move For_Break further up, as the functions in that file are sorted from
small to big.  The cast from size_t to unsigned int is required by lint.

In parse.c, move the code into a separate function to keep
ParseDirective small.  Its only job is to parse the directive and then
delegate to another function doing the actual work.

In the manual page, remove empty lines.

In the test, ensure that .break stops processing of the .for loop
immediately; anything after the .break is not processed anymore.
Replace ':=' with '=', as there is no need to evaluate '$i' early.
Check the expected value in the .mk file instead of the .exp file, to
keep the reading scope as small as possible.

diffstat:

 usr.bin/make/for.c                              |  19 ++++----
 usr.bin/make/make.1                             |   8 +--
 usr.bin/make/parse.c                            |  32 ++++++++-----
 usr.bin/make/unit-tests/directive-for-break.exp |   3 +-
 usr.bin/make/unit-tests/directive-for-break.mk  |  55 +++++++++++++++++-------
 5 files changed, 70 insertions(+), 47 deletions(-)

diffs (207 lines):

diff -r 1f4f232af7e2 -r 47a1536914e8 usr.bin/make/for.c
--- a/usr.bin/make/for.c        Sat Sep 03 00:31:02 2022 +0000
+++ b/usr.bin/make/for.c        Sat Sep 03 00:50:07 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: for.c,v 1.169 2022/09/02 16:24:31 sjg Exp $    */
+/*     $NetBSD: for.c,v 1.170 2022/09/03 00:50:07 rillig Exp $ */
 
 /*
  * Copyright (c) 1992, The Regents of the University of California.
@@ -58,7 +58,7 @@
 #include "make.h"
 
 /*     "@(#)for.c      8.1 (Berkeley) 6/6/93"  */
-MAKE_RCSID("$NetBSD: for.c,v 1.169 2022/09/02 16:24:31 sjg Exp $");
+MAKE_RCSID("$NetBSD: for.c,v 1.170 2022/09/03 00:50:07 rillig Exp $");
 
 
 typedef struct ForLoop {
@@ -490,6 +490,13 @@
        return true;
 }
 
+/* Break out of the .for loop. */
+void
+For_Break(ForLoop *f)
+{
+       f->nextItem = (unsigned int)f->items.len;
+}
+
 /* Run the .for loop, imitating the actions of an include file. */
 void
 For_Run(unsigned headLineno, unsigned bodyReadLines)
@@ -504,11 +511,3 @@
        } else
                ForLoop_Free(f);
 }
-
-/* Breaking out of a .for loop */
-void
-For_Break(ForLoop *f)
-{
-    f->nextItem = f->items.len;
-}
-     
diff -r 1f4f232af7e2 -r 47a1536914e8 usr.bin/make/make.1
--- a/usr.bin/make/make.1       Sat Sep 03 00:31:02 2022 +0000
+++ b/usr.bin/make/make.1       Sat Sep 03 00:50:07 2022 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: make.1,v 1.331 2022/09/02 16:24:31 sjg Exp $
+.\"    $NetBSD: make.1,v 1.332 2022/09/03 00:50:07 rillig Exp $
 .\"
 .\" Copyright (c) 1990, 1993
 .\"    The Regents of the University of California.  All rights reserved.
@@ -2084,14 +2084,12 @@
 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.
-
+.Pp
 If
 .Sq Ic .break
 is encountered within a
 .Cm \&.for
-loop, it causes early termination of the loop,
-otherwise a parse error.
-
+loop, it causes early termination of the loop, otherwise a parse error.
 .Sh COMMENTS
 Comments begin with a hash
 .Pq Ql \&#
diff -r 1f4f232af7e2 -r 47a1536914e8 usr.bin/make/parse.c
--- a/usr.bin/make/parse.c      Sat Sep 03 00:31:02 2022 +0000
+++ b/usr.bin/make/parse.c      Sat Sep 03 00:50:07 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: parse.c,v 1.682 2022/09/02 16:24:31 sjg Exp $  */
+/*     $NetBSD: parse.c,v 1.683 2022/09/03 00:50:07 rillig 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.682 2022/09/02 16:24:31 sjg Exp $");
+MAKE_RCSID("$NetBSD: parse.c,v 1.683 2022/09/03 00:50:07 rillig Exp $");
 
 /*
  * A file being read.
@@ -2661,6 +2661,20 @@
        }
 }
 
+static void
+HandleBreak(void)
+{
+       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");
+}
+
 /*
  * See if the line starts with one of the known directives, and if so, handle
  * the directive.
@@ -2689,17 +2703,9 @@
        pp_skip_whitespace(&cp);
        arg = cp;
 
-       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"))
+       if (Substring_Equals(dir, "break"))
+               HandleBreak();
+       else if (Substring_Equals(dir, "undef"))
                Var_Undef(arg);
        else if (Substring_Equals(dir, "export"))
                Var_Export(VEM_PLAIN, arg);
diff -r 1f4f232af7e2 -r 47a1536914e8 usr.bin/make/unit-tests/directive-for-break.exp
--- a/usr.bin/make/unit-tests/directive-for-break.exp   Sat Sep 03 00:31:02 2022 +0000
+++ b/usr.bin/make/unit-tests/directive-for-break.exp   Sat Sep 03 00:50:07 2022 +0000
@@ -1,5 +1,4 @@
-make: "directive-for-break.mk" line 16: I=3
-make: "directive-for-break.mk" line 24: break outside of for loop
+make: "directive-for-break.mk" line 45: break outside of for loop
 make: Fatal errors encountered -- cannot continue
 make: stopped in unit-tests
 exit status 1
diff -r 1f4f232af7e2 -r 47a1536914e8 usr.bin/make/unit-tests/directive-for-break.mk
--- a/usr.bin/make/unit-tests/directive-for-break.mk    Sat Sep 03 00:31:02 2022 +0000
+++ b/usr.bin/make/unit-tests/directive-for-break.mk    Sat Sep 03 00:50:07 2022 +0000
@@ -1,25 +1,46 @@
-# $NetBSD: directive-for-break.mk,v 1.1 2022/09/02 16:24:31 sjg Exp $
+# $NetBSD: directive-for-break.mk,v 1.2 2022/09/03 00:50:07 rillig Exp $
 #
-# Tests for .break in .for loops
+# Tests for .break in .for loops, which immediately terminates processing of
+# the surrounding .for loop.
+
 
-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 1 2 3 4 5 6 7 8
+.  if $i == 3
+I=     $i
+.    break
+I=     unreached
+.  endif
+.endfor
+.if $I != "3"
+.  error
+.endif
+
 
-# .break terminates the loop early
-# this is usually done within a conditional
-.for i in ${LIST}
-.if $i == 3
-I:= $i
-.break
-.endif
+# The .break only breaks out of the immediately surrounding .for loop, any
+# other .for loops are continued normally.
+.for outer in o1 o2 o3
+.  for inner in i1 i2 i3
+.    if ${outer} == o2 && ${inner} == i2
+.      break
+.    endif
+COMBINED+=     ${outer}-${inner}
+.  endfor
 .endfor
-.info I=$I
+# Only o2-i2 and o2-i3 are missing.
+.if ${COMBINED} != "o1-i1 o1-i2 o1-i3 o2-i1 o3-i1 o3-i2 o3-i3"
+.  error
+.endif
 
-# .break outside the context of a .for loop is an error
+
+# A .break outside the context of a .for loop is an error.
 .if $I == 0
-# harmless
-.break
+# No parse error, even though the .break occurs outside a .for loop, since
+# lines from inactive branches are only parsed as far as necessary to see
+# whether they belong to an .if/.elif/.else/.endif chain.
+.  break
 .else
-# error
-.break
+# expect+1: break outside of for loop
+.  break
 .endif



Home | Main Index | Thread Index | Old Index