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): don't modify the given line during Par...



details:   https://anonhg.NetBSD.org/src/rev/48c9e92e4e5b
branches:  trunk
changeset: 940136:48c9e92e4e5b
user:      rillig <rillig%NetBSD.org@localhost>
date:      Sun Oct 04 14:40:13 2020 +0000

description:
make(1): don't modify the given line during Parse_DoVar

Placing null characters all over the line made the code hard to
understand.  The null characters were placed for top-level whitespace as
well as the operator.

Working with a read-only line makes it easier to inspect the parsing
state during debugging.

This change involves an additional bmake_malloc for each variable name.
This will be compensated later by extending the API of the Var module to
also accept a pair of pointers (start, end) as the variable name.

diffstat:

 usr.bin/make/nonints.h |    4 +-
 usr.bin/make/parse.c   |  107 ++++++++++++++++++++++++++----------------------
 2 files changed, 59 insertions(+), 52 deletions(-)

diffs (204 lines):

diff -r 1f082b6f063b -r 48c9e92e4e5b usr.bin/make/nonints.h
--- a/usr.bin/make/nonints.h    Sun Oct 04 14:22:52 2020 +0000
+++ b/usr.bin/make/nonints.h    Sun Oct 04 14:40:13 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nonints.h,v 1.135 2020/10/04 10:35:25 rillig Exp $     */
+/*     $NetBSD: nonints.h,v 1.136 2020/10/04 14:40:13 rillig Exp $     */
 
 /*-
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -122,7 +122,7 @@
 /* parse.c */
 void Parse_Error(int, const char *, ...) MAKE_ATTR_PRINTFLIKE(2, 3);
 Boolean Parse_IsVar(const char *);
-void Parse_DoVar(char *, GNode *);
+void Parse_DoVar(const char *, GNode *);
 void Parse_AddIncludeDir(const char *);
 void Parse_File(const char *, int);
 void Parse_Init(void);
diff -r 1f082b6f063b -r 48c9e92e4e5b usr.bin/make/parse.c
--- a/usr.bin/make/parse.c      Sun Oct 04 14:22:52 2020 +0000
+++ b/usr.bin/make/parse.c      Sun Oct 04 14:40:13 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: parse.c,v 1.352 2020/10/04 13:24:59 rillig Exp $       */
+/*     $NetBSD: parse.c,v 1.353 2020/10/04 14:40:13 rillig Exp $       */
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -131,7 +131,7 @@
 #include "pathnames.h"
 
 /*     "@(#)parse.c    8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: parse.c,v 1.352 2020/10/04 13:24:59 rillig Exp $");
+MAKE_RCSID("$NetBSD: parse.c,v 1.353 2020/10/04 14:40:13 rillig Exp $");
 
 /* types and constants */
 
@@ -1738,23 +1738,30 @@
  * Input:
  *     p               A line guaranteed to be a variable assignment
  *                     (see Parse_IsVar).
- *                     Is destroyed but not freed during parsing.
  *     ctxt            Context in which to do the assignment
  */
 void
-Parse_DoVar(char *p, GNode *ctxt)
+Parse_DoVar(const char *p, GNode *ctxt)
 {
     enum {
        VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL
     } type;                    /* Type of assignment */
-    char *opc;                 /* ptr to operator character to
-                                * null-terminate the variable name */
     int depth;
     const char *name;
+    void *name_freeIt;
     const char *uvalue;                /* unexpanded value */
     const char *avalue;                /* actual value */
     char *evalue = NULL;       /* expanded value */
 
+    /* The variable name consists of a single word (that is, no whitespace).
+     * It ends at the whitespace after that word (nameEnd).  If there is no
+     * whitespace, the name is followed directly by the assignment operator
+     * (op).  During parsing, the '+' of the '+=' operator is initially parsed
+     * as part of the variable name.  It is later corrected, as is the ':sh'
+     * modifier. Of these two (nameEnd and op), the earlier one determines the
+     * actual end of the variable name. */
+    const char *nameEnd, *op;
+
     /*
      * Skip to variable name
      */
@@ -1762,12 +1769,14 @@
        p++;
 
     name = p;
+    name_freeIt = NULL;
 
     /*
-     * Skip to operator character, nulling out whitespace as we go
+     * Parse the variable name, up to the assignment operator.
      * XXX Rather than counting () and {} we should look for $ and
      * then expand the variable.
      */
+    nameEnd = NULL;
     for (depth = 0; depth > 0 || *p != '='; p++) {
        if (*p == '(' || *p == '{') {
            depth++;
@@ -1778,61 +1787,55 @@
            continue;
        }
        if (depth == 0 && ch_isspace(*p)) {
-           *p = '\0';
+           if (nameEnd == NULL)
+               nameEnd = p;
        }
     }
-    opc = p > name ? p - 1 : p;        /* operator is the previous character */
-    *p++ = '\0';               /* nuke the = */
 
-    /*
-     * Check operator type
-     */
-    switch (*opc) {
-       case '+':
-           type = VAR_APPEND;
-           *opc = '\0';
-           break;
+    if (nameEnd == NULL)
+       nameEnd = p;
+    op = p;                    /* points at the '=' */
 
-       case '?':
-           /*
-            * If the variable already has a value, we don't do anything.
-            */
-           *opc = '\0';
-           if (Var_Exists(name, ctxt)) {
-               return;
-           } else {
-               type = VAR_NORMAL;
-           }
-           break;
+    if (op > name && op[-1] == '+') {
+        type = VAR_APPEND;
+        op--;
+
+    } else if (op > name && op[-1] == '?') {
+       /* If the variable already has a value, we don't do anything. */
+        Boolean exists;
 
-       case ':':
-           type = VAR_SUBST;
-           *opc = '\0';
-           break;
+        op--;
+       name = name_freeIt = bmake_strsedup(name, nameEnd < op ? nameEnd : op);
+        exists = Var_Exists(name, ctxt);
+       if (exists) {
+           free(name_freeIt);
+           return;
+       }
+       type = VAR_NORMAL;
 
-       case '!':
-           type = VAR_SHELL;
-           *opc = '\0';
-           break;
+    } else if (op > name && op[-1] == ':') {
+        op--;
+       type = VAR_SUBST;
 
-       default:
+    } else if (op > name && op[-1] == '!') {
+        op--;
+        type = VAR_SHELL;
+
+    } else {
+       type = VAR_NORMAL;
 #ifdef SUNSHCMD
-           while (opc > name && *opc == '\0')
-               opc--;
+       while (op > name && ch_isspace(op[-1]))
+           op--;
 
-           if (opc >= name + 2 &&
-               opc[-2] == ':' && opc[-1] == 's' && opc[0] == 'h')
-           {
-               type = VAR_SHELL;
-               opc[-2] = '\0';
-               break;
-           }
+       if (op >= name + 3 && op[-3] == ':' && op[-2] == 's' && op[-1] == 'h') {
+           type = VAR_SHELL;
+           op -= 3;
+       }
 #endif
-           type = VAR_NORMAL;
-           break;
     }
 
-    pp_skip_whitespace(&p);
+    p++;                       /* Skip the '=' */
+    cpp_skip_whitespace(&p);
     uvalue = p;
     avalue = uvalue;
 
@@ -1848,6 +1851,9 @@
        }
     }
 
+    if (name_freeIt == NULL)
+       name = name_freeIt = bmake_strsedup(name, nameEnd < op ? nameEnd : op);
+
     if (type == VAR_APPEND) {
        Var_Append(name, uvalue, ctxt);
     } else if (type == VAR_SUBST) {
@@ -1922,6 +1928,7 @@
        Var_Export(avalue, FALSE);
     }
     free(evalue);
+    free(name_freeIt);
 }
 
 



Home | Main Index | Thread Index | Old Index