From 04e7f6dd0fc57ab98f39fb6fc9df610d0737ff17 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Wed, 16 Nov 2022 14:27:34 +0000 Subject: make: changes to suffix substitution in macro expansion The POSIX standard defines suffix substitution in macro expansion as taking the form: $(string1 [: subst1 =[ subst2 ]]) Since 'subst1' isn't bracketed a value must be supplied. Enforce this in POSIX mode. As a non-POSIX extension an empty 'subst1' is permitted with 'subst2' being added to all words unconditionally. If both 'subst1' and 'subst2' are empty the words are returned unchanged. --- miscutils/make.c | 27 ++++++++++++++++++--------- testsuite/make.tests | 11 +++++++++++ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/miscutils/make.c b/miscutils/make.c index 1104dfe87..941aa49e3 100644 --- a/miscutils/make.c +++ b/miscutils/make.c @@ -913,14 +913,14 @@ skip_macro(const char *s) * Returns an allocated string or NULL if the input is unmodified. */ static char * -modify_words(const char *val, int modifier, size_t lenf, +modify_words(const char *val, int modifier, size_t lenf, size_t lenr, const char *find_pref, const char *repl_pref, const char *find_suff, const char *repl_suff) { char *s, *copy, *word, *sep, *buf = NULL; size_t find_pref_len = 0, find_suff_len = 0; - if (!modifier && !lenf) + if (!modifier && lenf == 0 && lenr == 0) return buf; if (find_pref) { @@ -948,14 +948,18 @@ modify_words(const char *val, int modifier, size_t lenf, word = sep + 1; } } - if (lenf) { + if (find_pref != NULL || lenf != 0 || lenr != 0) { size_t lenw = strlen(word); // This code implements pattern macro expansions: // https://austingroupbugs.net/view.php?id=519 // // find: % // example: src/%.c - if (lenw >= lenf - 1 && find_pref) { + // + // For a pattern of the form: + // $(string1:[op]%[os]=[np][%][ns]) + // lenf is the length of [op]%[os]. So lenf >= 1. + if (find_pref != NULL && lenw + 1 >= lenf) { // If prefix and suffix of word match find_pref and // find_suff, then do substitution. if (strncmp(word, find_pref, find_pref_len) == 0 && @@ -1011,7 +1015,7 @@ expand_macros(const char *str, int except_dollar) char *find, *replace, *modified; char *expval, *expfind, *find_suff, *repl_suff; char *find_pref = NULL, *repl_pref = NULL; - size_t lenf; + size_t lenf, lenr; char modifier; struct macro *mp; @@ -1041,11 +1045,13 @@ expand_macros(const char *str, int except_dollar) } // Only do suffix replacement or pattern macro expansion - // if both ':' and '=' are found. This is indicated by - // lenf != 0. + // if both ':' and '=' are found, plus a '%' for the latter. + // Suffix replacement is indicated by + // find_pref == NULL && (lenf != 0 || lenr != 0); + // pattern macro expansion by find_pref != NULL. expfind = NULL; find_suff = repl_suff = NULL; - lenf = 0; + lenf = lenr = 0; if ((find = find_char(name, ':'))) { *find++ = '\0'; expfind = expand_macros(find, FALSE); @@ -1059,8 +1065,11 @@ expand_macros(const char *str, int except_dollar) if ((repl_suff = strchr(replace, '%'))) *repl_suff++ = '\0'; } else { + if (posix && lenf == 0) + error("empty suffix"); find_suff = expfind; repl_suff = replace; + lenr = strlen(repl_suff); } } } @@ -1105,7 +1114,7 @@ expand_macros(const char *str, int except_dollar) mp->m_flag = TRUE; expval = expand_macros(mp->m_val, FALSE); mp->m_flag = FALSE; - modified = modify_words(expval, modifier, lenf, + modified = modify_words(expval, modifier, lenf, lenr, find_pref, repl_pref, find_suff, repl_suff); if (modified) free(expval); diff --git a/testsuite/make.tests b/testsuite/make.tests index 8a0f1a7d2..7749bed52 100755 --- a/testsuite/make.tests +++ b/testsuite/make.tests @@ -450,6 +450,17 @@ test.b: ' cd .. || exit 1; rm -rf make.tempdir 2>/dev/null +# An empty original suffix indicates that every word should have +# the new suffix added. If neither suffix is provided the words +# remain unchanged. +testing "make macro expansion and suffix substitution 3" \ + "make -f -" "src1.c src2.c\nsrc1 src2\n" "" ' +SRCS = src1 src2 +target: + @echo $(SRCS:=.c) + @echo $(SRCS:=) +' + # Skip duplicate entries in $? and $^ mkdir make.tempdir && cd make.tempdir || exit 1 touch -t 202206171200 file1 file3 -- cgit v1.2.3-55-g6feb