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: migrate ModifyWord functions to use Subst...
details: https://anonhg.NetBSD.org/src/rev/4b8c156b0340
branches: trunk
changeset: 961167:4b8c156b0340
user: rillig <rillig%NetBSD.org@localhost>
date: Sun Apr 11 18:44:57 2021 +0000
description:
make: migrate ModifyWord functions to use Substring
This benefits the modifiers ':T' and ':H' since these scan the word from
the end. The SysV modifier '.c=.o' does not benefit yet, this will be
done in a follow-up commit.
Currently ModifyWords calls strlen for each single word, which degrades
performance. This will be cleaned up in a follow-up commit as well.
No functional change.
diffstat:
usr.bin/make/str.h | 41 ++++++++++++++-
usr.bin/make/var.c | 142 ++++++++++++++++++++++++++++++----------------------
2 files changed, 123 insertions(+), 60 deletions(-)
diffs (truncated from 419 to 300 lines):
diff -r 2c00160ac046 -r 4b8c156b0340 usr.bin/make/str.h
--- a/usr.bin/make/str.h Sun Apr 11 18:18:39 2021 +0000
+++ b/usr.bin/make/str.h Sun Apr 11 18:44:57 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: str.h,v 1.1 2021/04/11 12:06:53 rillig Exp $ */
+/* $NetBSD: str.h,v 1.2 2021/04/11 18:44:57 rillig Exp $ */
/*
Copyright (c) 2021 Roland Illig <rillig%NetBSD.org@localhost>
@@ -162,6 +162,12 @@
}
MAKE_INLINE bool
+Substring_IsEmpty(Substring sub)
+{
+ return sub.start == sub.end;
+}
+
+MAKE_INLINE bool
Substring_Equals(Substring sub, const char *str)
{
size_t len = strlen(str);
@@ -183,6 +189,39 @@
return FStr_InitOwn(bmake_strsedup(sub.start, sub.end));
}
+MAKE_INLINE const char *
+Substring_LastIndex(Substring sub, char ch)
+{
+ const char *p;
+
+ for (p = sub.end; p != sub.start; p--)
+ if (p[-1] == ch)
+ return p - 1;
+ return NULL;
+}
+
+MAKE_INLINE Substring
+Substring_Dirname(Substring pathname)
+{
+ const char *p;
+
+ for (p = pathname.end; p != pathname.start; p--)
+ if (p[-1] == '/')
+ return Substring_Init(pathname.start, p - 1);
+ return Substring_InitStr(".");
+}
+
+MAKE_INLINE Substring
+Substring_Basename(Substring pathname)
+{
+ const char *p;
+
+ for (p = pathname.end; p != pathname.start; p--)
+ if (p[-1] == '/')
+ return Substring_Init(p, pathname.end);
+ return pathname;
+}
+
MAKE_INLINE void
LazyBuf_Init(LazyBuf *buf, Substring expected)
diff -r 2c00160ac046 -r 4b8c156b0340 usr.bin/make/var.c
--- a/usr.bin/make/var.c Sun Apr 11 18:18:39 2021 +0000
+++ b/usr.bin/make/var.c Sun Apr 11 18:44:57 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: var.c,v 1.918 2021/04/11 17:48:01 rillig Exp $ */
+/* $NetBSD: var.c,v 1.919 2021/04/11 18:44:57 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -140,7 +140,7 @@
#include "metachar.h"
/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: var.c,v 1.918 2021/04/11 17:48:01 rillig Exp $");
+MAKE_RCSID("$NetBSD: var.c,v 1.919 2021/04/11 18:44:57 rillig Exp $");
/*
* Variables are defined using one of the VAR=value assignments. Their
@@ -1334,6 +1334,12 @@
SepBuf_AddBytes(buf, str, strlen(str));
}
+static void
+SepBuf_AddSubstring(SepBuf *buf, Substring sub)
+{
+ SepBuf_AddBytesBetween(buf, sub.start, sub.end);
+}
+
static char *
SepBuf_DoneData(SepBuf *buf)
{
@@ -1348,8 +1354,12 @@
*
* For example, when evaluating the modifier ':M*b' in ${:Ua b c:M*b}, the
* callback is called 3 times, once for "a", "b" and "c".
+ *
+ * Some ModifyWord functions assume that they are always passed a
+ * null-terminated substring, which is currently guaranteed but may change in
+ * the future.
*/
-typedef void (*ModifyWordProc)(const char *word, SepBuf *buf, void *data);
+typedef void (*ModifyWordProc)(Substring word, SepBuf *buf, void *data);
/*
@@ -1358,13 +1368,9 @@
*/
/*ARGSUSED*/
static void
-ModifyWord_Head(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
+ModifyWord_Head(Substring word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
{
- const char *slash = strrchr(word, '/');
- if (slash != NULL)
- SepBuf_AddBytesBetween(buf, word, slash);
- else
- SepBuf_AddStr(buf, ".");
+ SepBuf_AddSubstring(buf, Substring_Dirname(word));
}
/*
@@ -1373,9 +1379,9 @@
*/
/*ARGSUSED*/
static void
-ModifyWord_Tail(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
+ModifyWord_Tail(Substring word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
{
- SepBuf_AddStr(buf, str_basename(word));
+ SepBuf_AddSubstring(buf, Substring_Basename(word));
}
/*
@@ -1384,11 +1390,11 @@
*/
/*ARGSUSED*/
static void
-ModifyWord_Suffix(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
+ModifyWord_Suffix(Substring word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
{
- const char *lastDot = strrchr(word, '.');
+ const char *lastDot = Substring_LastIndex(word, '.');
if (lastDot != NULL)
- SepBuf_AddStr(buf, lastDot + 1);
+ SepBuf_AddBytesBetween(buf, lastDot + 1, word.end);
}
/*
@@ -1397,11 +1403,13 @@
*/
/*ARGSUSED*/
static void
-ModifyWord_Root(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
+ModifyWord_Root(Substring word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
{
- const char *lastDot = strrchr(word, '.');
- size_t len = lastDot != NULL ? (size_t)(lastDot - word) : strlen(word);
- SepBuf_AddBytes(buf, word, len);
+ const char *lastDot, *end;
+
+ lastDot = Substring_LastIndex(word, '.');
+ end = lastDot != NULL ? lastDot : word.end;
+ SepBuf_AddBytesBetween(buf, word.start, end);
}
/*
@@ -1409,12 +1417,13 @@
* Place the word in the buffer if it matches the given pattern.
*/
static void
-ModifyWord_Match(const char *word, SepBuf *buf, void *data)
+ModifyWord_Match(Substring word, SepBuf *buf, void *data)
{
const char *pattern = data;
- if (Str_Match(word, pattern))
- SepBuf_AddStr(buf, word);
+ assert(word.end[0] == '\0'); /* assume null-terminated word */
+ if (Str_Match(word.start, pattern))
+ SepBuf_AddSubstring(buf, word);
}
/*
@@ -1422,12 +1431,13 @@
* Place the word in the buffer if it doesn't match the given pattern.
*/
static void
-ModifyWord_NoMatch(const char *word, SepBuf *buf, void *data)
+ModifyWord_NoMatch(Substring word, SepBuf *buf, void *data)
{
const char *pattern = data;
- if (!Str_Match(word, pattern))
- SepBuf_AddStr(buf, word);
+ assert(word.end[0] == '\0'); /* assume null-terminated word */
+ if (!Str_Match(word.start, pattern))
+ SepBuf_AddSubstring(buf, word);
}
#ifdef SYSVVARSUB
@@ -1444,6 +1454,7 @@
* out_match_len returns the length of the match, if any.
* out_hasPercent returns whether the pattern contains a percent.
*/
+/* TODO: migrate to using Substring */
static const char *
SysVMatch(const char *word, const char *pattern,
size_t *out_match_len, bool *out_hasPercent)
@@ -1498,18 +1509,20 @@
/* Callback for ModifyWords to implement the :%.from=%.to modifier. */
static void
-ModifyWord_SYSVSubst(const char *word, SepBuf *buf, void *data)
+ModifyWord_SYSVSubst(Substring word, SepBuf *buf, void *data)
{
const struct ModifyWord_SYSVSubstArgs *args = data;
char *rhs_expanded;
const char *rhs;
const char *percent;
-
size_t match_len;
bool lhsPercent;
- const char *match = SysVMatch(word, args->lhs, &match_len, &lhsPercent);
+ const char *match;
+
+ assert(word.end[0] == '\0'); /* assume null-terminated word */
+ match = SysVMatch(word.start, args->lhs, &match_len, &lhsPercent);
if (match == NULL) {
- SepBuf_AddStr(buf, word);
+ SepBuf_AddSubstring(buf, word);
return;
}
@@ -1565,29 +1578,29 @@
* Perform a string substitution on the given word.
*/
static void
-ModifyWord_Subst(const char *word, SepBuf *buf, void *data)
+ModifyWord_Subst(Substring word, SepBuf *buf, void *data)
{
struct ModifyWord_SubstArgs *args = data;
size_t wordLen, lhsLen;
const char *wordEnd, *match;
- wordLen = strlen(word);
- wordEnd = word + wordLen;
+ wordLen = Substring_Length(word);
+ wordEnd = word.end;
if (args->pflags.subOnce && args->matched)
goto nosub;
lhsLen = Substring_Length(args->lhs);
if (args->pflags.anchorStart) {
if (wordLen < lhsLen ||
- memcmp(word, args->lhs.start, lhsLen) != 0)
+ memcmp(word.start, args->lhs.start, lhsLen) != 0)
goto nosub;
if (args->pflags.anchorEnd && wordLen != lhsLen)
goto nosub;
/* :S,^prefix,replacement, or :S,^whole$,replacement, */
- SepBuf_AddBytesBetween(buf, args->rhs.start, args->rhs.end);
- SepBuf_AddBytesBetween(buf, word + lhsLen, wordEnd);
+ SepBuf_AddSubstring(buf, args->rhs);
+ SepBuf_AddBytesBetween(buf, word.start + lhsLen, wordEnd);
args->matched = true;
return;
}
@@ -1599,8 +1612,8 @@
goto nosub;
/* :S,suffix$,replacement, */
- SepBuf_AddBytesBetween(buf, word, wordEnd - lhsLen);
- SepBuf_AddBytesBetween(buf, args->rhs.start, args->rhs.end);
+ SepBuf_AddBytesBetween(buf, word.start, wordEnd - lhsLen);
+ SepBuf_AddSubstring(buf, args->rhs);
args->matched = true;
return;
}
@@ -1609,17 +1622,16 @@
goto nosub;
/* unanchored case, may match more than once */
- while ((match = Substring_Find(Substring_Init(word, wordEnd),
- args->lhs)) != NULL) {
- SepBuf_AddBytesBetween(buf, word, match);
- SepBuf_AddBytesBetween(buf, args->rhs.start, args->rhs.end);
+ while ((match = Substring_Find(word, args->lhs)) != NULL) {
+ SepBuf_AddBytesBetween(buf, word.start, match);
+ SepBuf_AddSubstring(buf, args->rhs);
args->matched = true;
- word += (size_t)(match - word) + lhsLen;
- if (word == wordEnd || !args->pflags.subGlobal)
+ word.start += (size_t)(match - word.start) + lhsLen;
+ if (Substring_IsEmpty(word) || !args->pflags.subGlobal)
break;
}
Home |
Main Index |
Thread Index |
Old Index