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(1): improve .for loop documentation, clean...



details:   https://anonhg.NetBSD.org/src/rev/33d977685a42
branches:  trunk
changeset: 958284:33d977685a42
user:      rillig <rillig%NetBSD.org@localhost>
date:      Wed Dec 30 14:28:32 2020 +0000

description:
make(1): improve .for loop documentation, clean up ForReadMore

The comma expression in ForReadMore may be a nice trick, but it's not as
easy to read as a simple if-then-else chain.  Test for '{' before '('
since BSD makefiles use braces by convention.

diffstat:

 usr.bin/make/for.c |  74 +++++++++++++++++++++++++++---------------------------
 1 files changed, 37 insertions(+), 37 deletions(-)

diffs (154 lines):

diff -r 9ecdbe5b0d88 -r 33d977685a42 usr.bin/make/for.c
--- a/usr.bin/make/for.c        Wed Dec 30 13:42:19 2020 +0000
+++ b/usr.bin/make/for.c        Wed Dec 30 14:28:32 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: for.c,v 1.122 2020/12/30 10:03:16 rillig Exp $ */
+/*     $NetBSD: for.c,v 1.123 2020/12/30 14:28:32 rillig Exp $ */
 
 /*
  * Copyright (c) 1992, The Regents of the University of California.
@@ -32,24 +32,22 @@
 /*-
  * Handling of .for/.endfor loops in a makefile.
  *
- * For loops are of the form:
+ * For loops have the form:
  *
- * .for <varname...> in <value...>
- * ...
- * .endfor
+ *     .for <varname...> in <value...>
+ *     # the body
+ *     .endfor
  *
- * When a .for line is parsed, all following lines are accumulated into a
- * buffer, up to but excluding the corresponding .endfor line.  To find the
- * corresponding .endfor, the number of nested .for and .endfor directives
- * are counted.
+ * When a .for line is parsed, the following lines are copied to the body of
+ * the .for loop, until the corresponding .endfor line is reached.  In this
+ * phase, the body is not yet evaluated.  This also applies to any nested
+ * .for loops.
  *
- * During parsing, any nested .for loops are just passed through; they get
- * handled recursively in For_Eval when the enclosing .for loop is evaluated
- * in For_Run.
- *
- * When the .for loop has been parsed completely, the variable expressions
- * for the iteration variables are replaced with expressions of the form
- * ${:Uvalue}, and then this modified body is "included" as a special file.
+ * After reaching the .endfor, the values from the .for line are grouped
+ * according to the number of variables.  For each such group, the unexpanded
+ * body is scanned for variable expressions, and those that match the variable
+ * names are replaced with expressions of the form ${:U...} or $(:U...).
+ * After that, the body is treated like a file from an .include directive.
  *
  * Interface:
  *     For_Eval        Evaluate the loop in the passed line.
@@ -60,14 +58,14 @@
 #include "make.h"
 
 /*     "@(#)for.c      8.1 (Berkeley) 6/6/93"  */
-MAKE_RCSID("$NetBSD: for.c,v 1.122 2020/12/30 10:03:16 rillig Exp $");
+MAKE_RCSID("$NetBSD: for.c,v 1.123 2020/12/30 14:28:32 rillig Exp $");
 
 static int forLevel = 0;       /* Nesting level */
 
 /* One of the variables to the left of the "in" in a .for loop. */
 typedef struct ForVar {
        char *name;
-       size_t len;
+       size_t nameLen;
 } ForVar;
 
 /*
@@ -92,7 +90,7 @@
 {
        ForVar *var = Vector_Push(&f->vars);
        var->name = bmake_strldup(name, len);
-       var->len = len;
+       var->nameLen = len;
 }
 
 static void
@@ -354,8 +352,8 @@
 }
 
 /*
- * While expanding the body of a .for loop, replace expressions like
- * ${i}, ${i:...}, $(i) or $(i:...) with their ${:U...} expansion.
+ * While expanding the body of a .for loop, replace the inner part of an
+ * expression like ${i} or ${i:...} or $(i) or $(i:...) with ":Uvalue".
  */
 static void
 SubstVarLong(For *f, const char **pp, const char **inout_mark, char ech)
@@ -365,14 +363,15 @@
 
        for (i = 0; i < f->vars.len; i++) {
                ForVar *forVar = Vector_Get(&f->vars, i);
-               char *var = forVar->name;
-               size_t vlen = forVar->len;
+               char *varname = forVar->name;
+               size_t varnameLen = forVar->nameLen;
 
-               /* XXX: undefined behavior for p if vlen is longer than p? */
-               if (memcmp(p, var, vlen) != 0)
+               /* XXX: undefined behavior for p if varname is longer than p? */
+               if (memcmp(p, varname, varnameLen) != 0)
                        continue;
                /* XXX: why test for backslash here? */
-               if (p[vlen] != ':' && p[vlen] != ech && p[vlen] != '\\')
+               if (p[varnameLen] != ':' && p[varnameLen] != ech &&
+                   p[varnameLen] != '\\')
                        continue;
 
                /* Found a variable match. Replace with :U<value> */
@@ -381,7 +380,7 @@
                Buf_AddEscaped(&f->curBody,
                    f->items.words[f->sub_next + i], ech);
 
-               p += vlen;
+               p += varnameLen;
                *inout_mark = p;
                break;
        }
@@ -394,9 +393,10 @@
  * variable expressions like $i with their ${:U...} expansion.
  */
 static void
-SubstVarShort(For *f, char ch, const char **pp, const char **inout_mark)
+SubstVarShort(For *f, const char **pp, const char **inout_mark)
 {
        const char *p = *pp;
+       const char ch = *p;
        size_t i;
 
        /* Probably a single character name, ignore $$ and stupid ones. */
@@ -459,18 +459,18 @@
        mark = Buf_GetAll(&f->body, NULL);
        body_end = mark + Buf_Len(&f->body);
        for (p = mark; (p = strchr(p, '$')) != NULL;) {
-               char ch, ech;
-               ch = *++p;
-               if ((ch == '(' && (ech = ')', 1)) ||
-                   (ch == '{' && (ech = '}', 1))) {
+               if (p[1] == '{') {
+                       p += 2;
+                       SubstVarLong(f, &p, &mark, '}');
+               } else if (p[1] == '(') {
+                       p += 2;
+                       SubstVarLong(f, &p, &mark, ')');
+               } else if (p[1] != '\0') {
                        p++;
-                       SubstVarLong(f, &p, &mark, ech);
-                       continue;
-               }
-               if (ch == '\0')
+                       SubstVarShort(f, &p, &mark);
+               } else
                        break;
 
-               SubstVarShort(f, ch, &p, &mark);
        }
        Buf_AddBytesBetween(&f->curBody, mark, body_end);
 



Home | Main Index | Thread Index | Old Index