Module Name: src Committed By: rillig Date: Sun Dec 5 11:40:03 UTC 2021
Modified Files: src/usr.bin/make: for.c str.h src/usr.bin/make/unit-tests: directive-for-escape.mk Log Message: make: inline Str_Words into .for loop handling This saves one memory allocation and a bit of copying, per .for loop. No functional change. To generate a diff of this commit: cvs rdiff -u -r1.147 -r1.148 src/usr.bin/make/for.c cvs rdiff -u -r1.9 -r1.10 src/usr.bin/make/str.h cvs rdiff -u -r1.11 -r1.12 \ src/usr.bin/make/unit-tests/directive-for-escape.mk 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.147 src/usr.bin/make/for.c:1.148 --- src/usr.bin/make/for.c:1.147 Thu Sep 2 07:02:07 2021 +++ src/usr.bin/make/for.c Sun Dec 5 11:40:03 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: for.c,v 1.147 2021/09/02 07:02:07 rillig Exp $ */ +/* $NetBSD: for.c,v 1.148 2021/12/05 11:40:03 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.147 2021/09/02 07:02:07 rillig Exp $"); +MAKE_RCSID("$NetBSD: for.c,v 1.148 2021/12/05 11:40:03 rillig Exp $"); /* One of the variables to the left of the "in" in a .for loop. */ @@ -70,7 +70,7 @@ typedef struct ForVar { typedef struct ForLoop { Buffer body; /* Unexpanded body of the loop */ Vector /* of ForVar */ vars; /* Iteration variables */ - Words items; /* Substitution items */ + SubstringWords items; /* Substitution items */ Buffer curBody; /* Expanded body of the current iteration */ unsigned int sub_next; /* Where to continue iterating */ } ForLoop; @@ -87,8 +87,7 @@ ForLoop_New(void) Buf_Init(&f->body); Vector_Init(&f->vars, sizeof(ForVar)); - f->items.words = NULL; - f->items.freeIt = NULL; + SubstringWords_Init(&f->items); Buf_Init(&f->curBody); f->sub_next = 0; @@ -106,7 +105,7 @@ ForLoop_Free(ForLoop *f) } Vector_Done(&f->vars); - Words_Free(f->items); + SubstringWords_Free(f->items); Buf_Done(&f->curBody); free(f); @@ -171,10 +170,10 @@ ForLoop_ParseItems(ForLoop *f, const cha return false; } - f->items = Str_Words(items, false); + f->items = Substring_Words(items, false); free(items); - if (f->items.len == 1 && f->items.words[0][0] == '\0') + if (f->items.len == 1 && Substring_IsEmpty(f->items.words[0])) f->items.len = 0; /* .for var in ${:U} */ if (f->items.len != 0 && f->items.len % f->vars.len != 0) { @@ -278,17 +277,16 @@ For_Accum(const char *line) static size_t -ExprLen(const char *expr) +ExprLen(const char *s, const char *e) { - char ch, expr_open, expr_close; + char expr_open, expr_close; int depth; - size_t len; + const char *p; - expr_open = expr[0]; - if (expr_open == '\0') - /* just escape the $ */ - return 0; + if (s == e) + return 0; /* just escape the '$' */ + expr_open = s[0]; if (expr_open == '(') expr_close = ')'; else if (expr_open == '{') @@ -297,11 +295,11 @@ ExprLen(const char *expr) return 1; /* Single char variable */ depth = 1; - for (len = 1; (ch = expr[len++]) != '\0';) { - if (ch == expr_open) + for (p = s + 1; p != e; p++) { + if (*p == expr_open) depth++; - else if (ch == expr_close && --depth == 0) - return len; + else if (*p == expr_close && --depth == 0) + return (size_t)(p + 1 - s); } /* Expression end not found, escape the $ */ @@ -313,11 +311,11 @@ ExprLen(const char *expr) * that characters that break this syntax must be backslash-escaped. */ static bool -NeedsEscapes(const char *value, char endc) +NeedsEscapes(Substring value, char endc) { const char *p; - for (p = value; *p != '\0'; p++) { + for (p = value.start; p != value.end; p++) { if (*p == ':' || *p == '$' || *p == '\\' || *p == endc || *p == '\n') return true; @@ -332,27 +330,29 @@ NeedsEscapes(const char *value, char end * The result is later unescaped by ApplyModifier_Defined. */ static void -Buf_AddEscaped(Buffer *cmds, const char *item, char endc) +Buf_AddEscaped(Buffer *cmds, Substring item, char endc) { + const char *p; char ch; if (!NeedsEscapes(item, endc)) { - Buf_AddStr(cmds, item); + Buf_AddBytesBetween(cmds, item.start, item.end); return; } /* Escape ':', '$', '\\' and 'endc' - these will be removed later by * :U processing, see ApplyModifier_Defined. */ - while ((ch = *item++) != '\0') { + for (p = item.start; p != item.end; p++) { + ch = *p; if (ch == '$') { - size_t len = ExprLen(item); + size_t len = ExprLen(p + 1, item.end); if (len != 0) { /* * XXX: Should a '\' be added here? * See directive-for-escape.mk, ExprLen. */ - Buf_AddBytes(cmds, item - 1, len + 1); - item += len; + Buf_AddBytes(cmds, p, 1 + len); + p += len; continue; } Buf_AddByte(cmds, '\\'); Index: src/usr.bin/make/str.h diff -u src/usr.bin/make/str.h:1.9 src/usr.bin/make/str.h:1.10 --- src/usr.bin/make/str.h:1.9 Sun May 30 21:16:54 2021 +++ src/usr.bin/make/str.h Sun Dec 5 11:40:03 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: str.h,v 1.9 2021/05/30 21:16:54 rillig Exp $ */ +/* $NetBSD: str.h,v 1.10 2021/12/05 11:40:03 rillig Exp $ */ /* Copyright (c) 2021 Roland Illig <ril...@netbsd.org> @@ -353,6 +353,14 @@ Words_Free(Words w) SubstringWords Substring_Words(const char *, bool); MAKE_INLINE void +SubstringWords_Init(SubstringWords *w) +{ + w->words = NULL; + w->len = 0; + w->freeIt = NULL; +} + +MAKE_INLINE void SubstringWords_Free(SubstringWords w) { free(w.words); Index: src/usr.bin/make/unit-tests/directive-for-escape.mk diff -u src/usr.bin/make/unit-tests/directive-for-escape.mk:1.11 src/usr.bin/make/unit-tests/directive-for-escape.mk:1.12 --- src/usr.bin/make/unit-tests/directive-for-escape.mk:1.11 Thu Sep 2 07:02:08 2021 +++ src/usr.bin/make/unit-tests/directive-for-escape.mk Sun Dec 5 11:40:03 2021 @@ -1,4 +1,4 @@ -# $NetBSD: directive-for-escape.mk,v 1.11 2021/09/02 07:02:08 rillig Exp $ +# $NetBSD: directive-for-escape.mk,v 1.12 2021/12/05 11:40:03 rillig Exp $ # # Test escaping of special characters in the iteration values of a .for loop. # These values get expanded later using the :U variable modifier, and this @@ -13,8 +13,8 @@ ASCII= !"\#$$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~ # XXX: As of 2020-12-31, the '#' is not preserved in the expanded body of -# the loop since it would not need only the escaping for the :U variable -# modifier but also the escaping for the line-end comment. +# the loop. Not only would it need the escaping for the variable modifier +# ':U' but also the escaping for the line-end comment. .for chars in ${ASCII} . info ${chars} .endfor @@ -34,7 +34,7 @@ ASCII.2020-12-31= !"\\\#$$%&'()*+,-./0-9 # XXX: It is unexpected that the variable V gets expanded in the loop body. # The double '$$' should intuitively prevent exactly this. Probably nobody # was adventurous enough to use literal dollar signs in the values of a .for -# loop. +# loop, allowing this edge case to go unnoticed for years. # # See for.c, function ExprLen. V= value