Module Name:    src
Committed By:   rillig
Date:           Mon Jan 25 19:39:34 UTC 2021

Modified Files:
        src/usr.bin/make: for.c

Log Message:
make(1): split For_Eval into separate functions


To generate a diff of this commit:
cvs rdiff -u -r1.137 -r1.138 src/usr.bin/make/for.c

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/for.c
diff -u src/usr.bin/make/for.c:1.137 src/usr.bin/make/for.c:1.138
--- src/usr.bin/make/for.c:1.137	Mon Jan 25 19:10:57 2021
+++ src/usr.bin/make/for.c	Mon Jan 25 19:39:34 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: for.c,v 1.137 2021/01/25 19:10:57 rillig Exp $	*/
+/*	$NetBSD: for.c,v 1.138 2021/01/25 19:39:34 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.137 2021/01/25 19:10:57 rillig Exp $");
+MAKE_RCSID("$NetBSD: for.c,v 1.138 2021/01/25 19:39:34 rillig Exp $");
 
 
 /* One of the variables to the left of the "in" in a .for loop. */
@@ -126,6 +126,76 @@ ForLoop_AddVar(ForLoop *f, const char *n
 }
 
 static Boolean
+ForLoop_ParseVarnames(ForLoop *f, const char **pp)
+{
+	const char *p = *pp;
+
+	for (;;) {
+		size_t len;
+
+		cpp_skip_whitespace(&p);
+		if (*p == '\0') {
+			Parse_Error(PARSE_FATAL, "missing `in' in for");
+			return FALSE;
+		}
+
+		/*
+		 * XXX: This allows arbitrary variable names;
+		 * see directive-for.mk.
+		 */
+		for (len = 1; p[len] != '\0' && !ch_isspace(p[len]); len++)
+			continue;
+
+		if (len == 2 && p[0] == 'i' && p[1] == 'n') {
+			p += 2;
+			break;
+		}
+		if (len == 1)
+			f->short_var = TRUE;
+
+		ForLoop_AddVar(f, p, len);
+		p += len;
+	}
+
+	if (f->vars.len == 0) {
+		Parse_Error(PARSE_FATAL, "no iteration variables in for");
+		return FALSE;
+	}
+
+	*pp = p;
+	return TRUE;
+}
+
+static Boolean
+ForLoop_ParseItems(ForLoop *f, const char *p)
+{
+	char *items;
+
+	cpp_skip_whitespace(&p);
+
+	if (Var_Subst(p, VAR_GLOBAL, VARE_WANTRES, &items) != VPR_OK) {
+		Parse_Error(PARSE_FATAL, "Error in .for loop items");
+		return FALSE;
+	}
+
+	f->items = Str_Words(items, FALSE);
+	free(items);
+
+	if (f->items.len == 1 && f->items.words[0][0] == '\0')
+		f->items.len = 0; /* .for var in ${:U} */
+
+	if (f->items.len != 0 && f->items.len % f->vars.len != 0) {
+		Parse_Error(PARSE_FATAL,
+		    "Wrong number of words (%u) in .for "
+		    "substitution list with %u variables",
+		    (unsigned)f->items.len, (unsigned)f->vars.len);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static Boolean
 IsFor(const char *p)
 {
 	return p[0] == 'f' && p[1] == 'o' && p[2] == 'r' && ch_isspace(p[3]);
@@ -168,83 +238,18 @@ For_Eval(const char *line)
 	}
 	p += 3;
 
-	/*
-	 * we found a for loop, and now we are going to parse it.
-	 */
-
 	f = ForLoop_New();
 
-	/* Grab the variables. Terminate on "in". */
-	for (;;) {
-		size_t len;
-
-		cpp_skip_whitespace(&p);
-		if (*p == '\0') {
-			Parse_Error(PARSE_FATAL, "missing `in' in for");
-			ForLoop_Free(f);
-			return -1;
-		}
-
-		/*
-		 * XXX: This allows arbitrary variable names;
-		 * see directive-for.mk.
-		 */
-		for (len = 1; p[len] != '\0' && !ch_isspace(p[len]); len++)
-			continue;
-
-		if (len == 2 && p[0] == 'i' && p[1] == 'n') {
-			p += 2;
-			break;
-		}
-		if (len == 1)
-			f->short_var = TRUE;
-
-		ForLoop_AddVar(f, p, len);
-		p += len;
-	}
-
-	if (f->vars.len == 0) {
-		Parse_Error(PARSE_FATAL, "no iteration variables in for");
+	if (!ForLoop_ParseVarnames(f, &p)) {
 		ForLoop_Free(f);
 		return -1;
 	}
 
-	cpp_skip_whitespace(&p);
-
-	{
-		char *items;
-		if (Var_Subst(p, VAR_GLOBAL, VARE_WANTRES, &items) != VPR_OK) {
-			Parse_Error(PARSE_FATAL, "Error in .for loop items");
-			f->items.len = 0;
-			goto done;
-		}
-
-		f->items = Str_Words(items, FALSE);
-		free(items);
-
-		if (f->items.len == 1 && f->items.words[0][0] == '\0')
-			f->items.len = 0; /* .for var in ${:U} */
-	}
-
-	{
-		size_t nitems, nvars;
-
-		if ((nitems = f->items.len) > 0 &&
-		    nitems % (nvars = f->vars.len) != 0) {
-			Parse_Error(PARSE_FATAL,
-			    "Wrong number of words (%u) in .for "
-			    "substitution list with %u variables",
-			    (unsigned)nitems, (unsigned)nvars);
-			/*
-			 * Return 'success' so that the body of the .for loop
-			 * is accumulated.
-			 * Remove all items so that the loop doesn't iterate.
-			 */
-			f->items.len = 0;
-		}
+	if (!ForLoop_ParseItems(f, p)) {
+		/* Continue parsing the .for loop, but don't iterate. */
+		f->items.len = 0;
 	}
 
-done:
 	accumFor = f;
 	forLevel = 1;
 	return 1;

Reply via email to