Module Name:    src
Committed By:   rillig
Date:           Sun Oct  4 19:36:32 UTC 2020

Modified Files:
        src/usr.bin/make: main.c nonints.h parse.c

Log Message:
make(1): remove duplicate code for parsing a variable name


To generate a diff of this commit:
cvs rdiff -u -r1.365 -r1.366 src/usr.bin/make/main.c
cvs rdiff -u -r1.136 -r1.137 src/usr.bin/make/nonints.h
cvs rdiff -u -r1.355 -r1.356 src/usr.bin/make/parse.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/main.c
diff -u src/usr.bin/make/main.c:1.365 src/usr.bin/make/main.c:1.366
--- src/usr.bin/make/main.c:1.365	Sun Oct  4 08:22:59 2020
+++ src/usr.bin/make/main.c	Sun Oct  4 19:36:32 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: main.c,v 1.365 2020/10/04 08:22:59 rillig Exp $	*/
+/*	$NetBSD: main.c,v 1.366 2020/10/04 19:36:32 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -122,7 +122,7 @@
 #endif
 
 /*	"@(#)main.c	8.3 (Berkeley) 3/19/94"	*/
-MAKE_RCSID("$NetBSD: main.c,v 1.365 2020/10/04 08:22:59 rillig Exp $");
+MAKE_RCSID("$NetBSD: main.c,v 1.366 2020/10/04 19:36:32 rillig Exp $");
 #if defined(MAKE_NATIVE) && !defined(lint)
 __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 "
 	    "The Regents of the University of California.  "
@@ -673,9 +673,10 @@ rearg:
 	 * perform them if so. Else take them to be targets and stuff them
 	 * on the end of the "create" list.
 	 */
-	for (; argc > 1; ++argv, --argc)
-		if (Parse_IsVar(argv[1])) {
-			Parse_DoVar(argv[1], VAR_CMD);
+	for (; argc > 1; ++argv, --argc) {
+		VarAssign var;
+		if (Parse_IsVar(argv[1], &var)) {
+			Parse_DoVar(&var, VAR_CMD);
 		} else {
 			if (!*argv[1])
 				Punt("illegal (null) argument.");
@@ -683,6 +684,7 @@ rearg:
 				goto rearg;
 			Lst_Append(create, bmake_strdup(argv[1]));
 		}
+	}
 
 	return;
 noarg:

Index: src/usr.bin/make/nonints.h
diff -u src/usr.bin/make/nonints.h:1.136 src/usr.bin/make/nonints.h:1.137
--- src/usr.bin/make/nonints.h:1.136	Sun Oct  4 14:40:13 2020
+++ src/usr.bin/make/nonints.h	Sun Oct  4 19:36:32 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: nonints.h,v 1.136 2020/10/04 14:40:13 rillig Exp $	*/
+/*	$NetBSD: nonints.h,v 1.137 2020/10/04 19:36:32 rillig Exp $	*/
 
 /*-
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -120,9 +120,26 @@ Boolean getBoolean(const char *, Boolean
 char *cached_realpath(const char *, char *);
 
 /* parse.c */
+
+typedef enum VarAssignOp {
+    VAR_NORMAL,			/* = */
+    VAR_SUBST,			/* := */
+    VAR_SHELL,			/* != or :sh= */
+    VAR_APPEND,			/* += */
+    VAR_DEFAULT			/* ?= */
+} VarAssignOp;
+
+typedef struct VarAssign {
+    const char *name;		/* unexpanded */
+    const char *nameEndDraft;	/* before operator adjustment */
+    const char *eq;		/* the '=' of the assignment operator */
+    VarAssignOp op;
+    const char *value;		/* unexpanded */
+} VarAssign;
+
 void Parse_Error(int, const char *, ...) MAKE_ATTR_PRINTFLIKE(2, 3);
-Boolean Parse_IsVar(const char *);
-void Parse_DoVar(const char *, GNode *);
+Boolean Parse_IsVar(const char *, VarAssign *out_var);
+void Parse_DoVar(VarAssign *, GNode *);
 void Parse_AddIncludeDir(const char *);
 void Parse_File(const char *, int);
 void Parse_Init(void);

Index: src/usr.bin/make/parse.c
diff -u src/usr.bin/make/parse.c:1.355 src/usr.bin/make/parse.c:1.356
--- src/usr.bin/make/parse.c:1.355	Sun Oct  4 19:21:13 2020
+++ src/usr.bin/make/parse.c	Sun Oct  4 19:36:32 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: parse.c,v 1.355 2020/10/04 19:21:13 rillig Exp $	*/
+/*	$NetBSD: parse.c,v 1.356 2020/10/04 19:36:32 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.355 2020/10/04 19:21:13 rillig Exp $");
+MAKE_RCSID("$NetBSD: parse.c,v 1.356 2020/10/04 19:36:32 rillig Exp $");
 
 /* types and constants */
 
@@ -204,14 +204,6 @@ typedef enum {
     Attribute		/* Generic attribute */
 } ParseSpecial;
 
-typedef enum VarAssignOp {
-    VAR_NORMAL,			/* = */
-    VAR_SUBST,			/* := */
-    VAR_SHELL,			/* != or :sh= */
-    VAR_APPEND,			/* += */
-    VAR_DEFAULT			/* ?= */
-} VarAssignOp;
-
 /* result data */
 
 /*
@@ -1672,15 +1664,15 @@ out:
 	Lst_Free(curTargs);
 }
 
-/* See if the given string is a variable assignment, consisting of a
- * single-word variable name, optional whitespace, an assignment operator,
- * optional whitespace and the variable value.
+/* Parse a variable assignment, consisting of a single-word variable name,
+ * optional whitespace, an assignment operator, optional whitespace and the
+ * variable value.
  *
  * Used for both lines in a file and command line arguments. */
 Boolean
-Parse_IsVar(const char *p)
+Parse_IsVar(const char *p, VarAssign *out_var)
 {
-    Boolean wasSpace = FALSE;	/* set TRUE if found a space */
+    const char *firstSpace = NULL;
     char ch;
     int level = 0;
 
@@ -1688,6 +1680,8 @@ Parse_IsVar(const char *p)
     while (*p == ' ' || *p == '\t')
 	p++;
 
+    out_var->name = p;
+
     /* Scan for one of the assignment operators outside a variable expansion */
     while ((ch = *p++) != 0) {
 	if (ch == '(' || ch == '{') {
@@ -1698,75 +1692,58 @@ Parse_IsVar(const char *p)
 	    level--;
 	    continue;
 	}
+
 	if (level != 0)
 	    continue;
-	while (ch == ' ' || ch == '\t') {
+
+	if (ch == ' ' || ch == '\t')
+	    if (firstSpace == NULL)
+	        firstSpace = p - 1;
+	while (ch == ' ' || ch == '\t')
 	    ch = *p++;
-	    wasSpace = TRUE;
-	}
+
 #ifdef SUNSHCMD
 	if (ch == ':' && strncmp(p, "sh", 2) == 0) {
 	    p += 2;
 	    continue;
 	}
 #endif
-	if (ch == '=')
+	if (ch == '=') {
+	    out_var->eq = p - 1;
+	    out_var->nameEndDraft = firstSpace != NULL ? firstSpace : p - 1;
+	    out_var->op = VAR_NORMAL;
+	    cpp_skip_whitespace(&p);
+	    out_var->value = p;
 	    return TRUE;
-	if (*p == '=' && (ch == '+' || ch == ':' || ch == '?' || ch == '!'))
+	}
+	if (*p == '=' && (ch == '+' || ch == ':' || ch == '?' || ch == '!')) {
+	    out_var->eq = p;
+	    out_var->nameEndDraft = firstSpace != NULL ? firstSpace : p;
+	    out_var->op = ch == '+' ? VAR_APPEND :
+			  ch == ':' ? VAR_SUBST :
+			  ch == '?' ? VAR_DEFAULT : VAR_SHELL;
+	    p++;
+	    cpp_skip_whitespace(&p);
+	    out_var->value = p;
 	    return TRUE;
-	if (wasSpace)
+	}
+	if (firstSpace != NULL)
 	    return FALSE;
     }
 
     return FALSE;
 }
 
-/*
-* Parse the variable name, up to the assignment operator.
-* XXX Rather than counting () and {} we should look for $ and
-* then expand the variable.
-*/
-static const char *
-ParseVarname(const char **pp)
-{
-    const char *p = *pp;
-    const char *nameEnd = NULL;
-    int depth;
-
-    for (depth = 0; depth > 0 || *p != '='; p++) {
-	if (*p == '(' || *p == '{') {
-	    depth++;
-	    continue;
-	}
-	if (*p == ')' || *p == '}') {
-	    depth--;
-	    continue;
-	}
-	if (depth == 0 && ch_isspace(*p)) {
-	    if (nameEnd == NULL)
-		nameEnd = p;
-	}
-    }
-
-    if (nameEnd == NULL)
-	nameEnd = p;
-
-    *pp = p;
-    return nameEnd;
-}
-
 static Boolean
-ParseVarassignOp(const char *p, const char *const nameEnd, const char **out_op,
-		 const char **inout_name, VarAssignOp *out_type,
-		 void **inout_name_freeIt, GNode *ctxt)
+ParseVarassignOp(VarAssign *var,
+		 const char **out_op, const char **inout_name,
+		 VarAssignOp *out_type, void **inout_name_freeIt, GNode *ctxt)
 {
-    const char *op;
+    const char *op = var->eq;
     const char *name = *inout_name;
     void *name_freeIt = *inout_name_freeIt;
     VarAssignOp type;
 
-    op = p;			/* points at the '=' */
-
     if (op > name && op[-1] == '+') {
 	type = VAR_APPEND;
 	op--;
@@ -1774,9 +1751,11 @@ ParseVarassignOp(const char *p, const ch
     } else if (op > name && op[-1] == '?') {
 	/* If the variable already has a value, we don't do anything. */
 	Boolean exists;
+	const char *nameEnd;
 
 	op--;
-	name = name_freeIt = bmake_strsedup(name, nameEnd < op ? nameEnd : op);
+	nameEnd = var->nameEndDraft < op ? var->nameEndDraft : op;
+	name = name_freeIt = bmake_strsedup(name, nameEnd);
 	exists = Var_Exists(name, ctxt);
 	if (exists) {
 	    free(name_freeIt);
@@ -1829,7 +1808,7 @@ VarCheckSyntax(VarAssignOp type, const c
 }
 
 static void
-VarAssign(VarAssignOp const type, const char *const name,
+VarAssign_Eval(VarAssignOp const type, const char *const name,
 	  const char *const uvalue, const char **out_avalue, char **out_evalue,
 	  GNode *ctxt)
 {
@@ -1933,7 +1912,7 @@ VarAssignSpecial(const char *name, const
  *	ctxt		Context in which to do the assignment
  */
 void
-Parse_DoVar(const char *p, GNode *ctxt)
+Parse_DoVar(VarAssign *var, GNode *ctxt)
 {
     VarAssignOp type;
     const char *name;
@@ -1949,33 +1928,25 @@ Parse_DoVar(const char *p, GNode *ctxt)
      * 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
-     */
-    while (*p == ' ' || *p == '\t')
-	p++;
+    const char *op;
 
-    name = p;
+    name = var->name;
     name_freeIt = NULL;
 
-    nameEnd = ParseVarname(&p);
-
-    if (!ParseVarassignOp(p, nameEnd, &op, &name, &type, &name_freeIt, ctxt))
+    if (!ParseVarassignOp(var, &op, &name, &type, &name_freeIt, ctxt))
 	return;
 
-    p++;			/* Skip the '=' */
-    cpp_skip_whitespace(&p);
-    uvalue = p;
+    uvalue = var->value;
     avalue = uvalue;
 
     VarCheckSyntax(type, uvalue, ctxt);
 
-    if (name_freeIt == NULL)
-    	name = name_freeIt = bmake_strsedup(name, nameEnd < op ? nameEnd : op);
+    if (name_freeIt == NULL) {
+	const char *nameEnd = var->nameEndDraft < op ? var->nameEndDraft : op;
+	name = name_freeIt = bmake_strsedup(name, nameEnd);
+    }
 
-    VarAssign(type, name, uvalue, &avalue, &evalue, ctxt);
+    VarAssign_Eval(type, name, uvalue, &avalue, &evalue, ctxt);
     VarAssignSpecial(name, avalue);
 
     free(evalue);
@@ -2939,10 +2910,13 @@ Parse_File(const char *name, int fd)
 		continue;
 	    }
 #endif
-	    if (Parse_IsVar(line)) {
-		FinishDependencyGroup();
-		Parse_DoVar(line, VAR_GLOBAL);
-		continue;
+	    {
+	        VarAssign var;
+		if (Parse_IsVar(line, &var)) {
+		    FinishDependencyGroup();
+		    Parse_DoVar(&var, VAR_GLOBAL);
+		    continue;
+		}
 	    }
 
 #ifndef POSIX

Reply via email to