Module Name:    src
Committed By:   rillig
Date:           Sat Nov  7 23:41:39 UTC 2020

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

Log Message:
make(1): replace strstr in ParseMaybeSubMake with optimized code

This code is called for each command that is parsed.  Calling strstr with
4 strings that all start with the same character is unnecessary work.
Therefore, replace strstr with manually optimized code.  Neither GCC
5.5.0 nor GCC 10 inlines strncmp like this, otherwise I would have used
that.

Change in behavior: previously, a${MAKE}b would not be considered to be a
sub-make command, which is probably correct but does not occur in
practice.  The check for non-alphanumeric characters around the found
string was probably meant only for the plain word "make".


To generate a diff of this commit:
cvs rdiff -u -r1.431 -r1.432 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/parse.c
diff -u src/usr.bin/make/parse.c:1.431 src/usr.bin/make/parse.c:1.432
--- src/usr.bin/make/parse.c:1.431	Sat Nov  7 22:26:42 2020
+++ src/usr.bin/make/parse.c	Sat Nov  7 23:41:38 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: parse.c,v 1.431 2020/11/07 22:26:42 rillig Exp $	*/
+/*	$NetBSD: parse.c,v 1.432 2020/11/07 23:41:38 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -117,7 +117,7 @@
 #include "pathnames.h"
 
 /*	"@(#)parse.c	8.3 (Berkeley) 3/19/94"	*/
-MAKE_RCSID("$NetBSD: parse.c,v 1.431 2020/11/07 22:26:42 rillig Exp $");
+MAKE_RCSID("$NetBSD: parse.c,v 1.432 2020/11/07 23:41:38 rillig Exp $");
 
 /* types and constants */
 
@@ -2031,36 +2031,41 @@ Parse_DoVar(VarAssign *var, GNode *ctxt)
 }
 
 
-/*
- * ParseMaybeSubMake --
- *	Scan the command string to see if it a possible submake node
- * Input:
- *	cmd		the command to scan
- * Results:
- *	TRUE if the command is possibly a submake, FALSE if not.
- */
+/* See if the command possibly calls a sub-make by using the variable
+ * expressions ${.MAKE}, ${MAKE} or the plain word "make". */
 static Boolean
-ParseMaybeSubMake(const char *cmd)
+MaybeSubMake(const char *cmd)
 {
-    size_t i;
-    static struct {
-	const char *name;
-	size_t len;
-    } vals[] = {
-#define MKV(A)	{	A, sizeof (A) - 1	}
-	MKV("${MAKE}"),
-	MKV("${.MAKE}"),
-	MKV("$(MAKE)"),
-	MKV("$(.MAKE)"),
-	MKV("make"),
-    };
-    for (i = 0; i < sizeof vals / sizeof vals[0]; i++) {
-	char *ptr;
-	if ((ptr = strstr(cmd, vals[i].name)) == NULL)
+    const char *start;
+
+    for (start = cmd; *start != '\0'; start++) {
+	const char *p = start;
+	char endc;
+
+	/* XXX: What if progname != "make"? */
+	if (p[0] == 'm' && p[1] == 'a' && p[2] == 'k' && p[3] == 'e')
+	    if (start == cmd || !ch_isalnum(p[-1]))
+		if (!ch_isalnum(p[4]))
+		    return TRUE;
+
+	if (*p != '$')
 	    continue;
-	if ((ptr == cmd || !ch_isalnum(ptr[-1]))
-	    && !ch_isalnum(ptr[vals[i].len]))
-	    return TRUE;
+	p++;
+
+	if (*p == '{')
+	    endc = '}';
+	else if (*p == '(')
+	    endc = ')';
+	else
+	    continue;
+	p++;
+
+	if (*p == '.')		/* Accept either ${.MAKE} or ${MAKE}. */
+	    p++;
+
+	if (p[0] == 'M' && p[1] == 'A' && p[2] == 'K' && p[3] == 'E')
+	    if (p[4] == endc)
+		return TRUE;
     }
     return FALSE;
 }
@@ -2079,7 +2084,7 @@ ParseAddCmd(GNode *gn, char *cmd)
     /* if target already supplied, ignore commands */
     if (!(gn->type & OP_HAS_COMMANDS)) {
 	Lst_Append(gn->commands, cmd);
-	if (ParseMaybeSubMake(cmd))
+	if (MaybeSubMake(cmd))
 	    gn->type |= OP_SUBMAKE;
 	ParseMark(gn);
     } else {

Reply via email to