diff options
| author | Ron Yorston <rmy@pobox.com> | 2022-11-16 14:27:34 +0000 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2022-11-16 14:27:34 +0000 |
| commit | 04e7f6dd0fc57ab98f39fb6fc9df610d0737ff17 (patch) | |
| tree | 945247f2283a290c082b1292021e9fe87aae7d10 | |
| parent | f3f72ac1d2a56b97c6e90aa359ad236f528b5294 (diff) | |
| download | busybox-w32-04e7f6dd0fc57ab98f39fb6fc9df610d0737ff17.tar.gz busybox-w32-04e7f6dd0fc57ab98f39fb6fc9df610d0737ff17.tar.bz2 busybox-w32-04e7f6dd0fc57ab98f39fb6fc9df610d0737ff17.zip | |
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.
| -rw-r--r-- | miscutils/make.c | 27 | ||||
| -rwxr-xr-x | 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) | |||
| 913 | * Returns an allocated string or NULL if the input is unmodified. | 913 | * Returns an allocated string or NULL if the input is unmodified. |
| 914 | */ | 914 | */ |
| 915 | static char * | 915 | static char * |
| 916 | modify_words(const char *val, int modifier, size_t lenf, | 916 | modify_words(const char *val, int modifier, size_t lenf, size_t lenr, |
| 917 | const char *find_pref, const char *repl_pref, | 917 | const char *find_pref, const char *repl_pref, |
| 918 | const char *find_suff, const char *repl_suff) | 918 | const char *find_suff, const char *repl_suff) |
| 919 | { | 919 | { |
| 920 | char *s, *copy, *word, *sep, *buf = NULL; | 920 | char *s, *copy, *word, *sep, *buf = NULL; |
| 921 | size_t find_pref_len = 0, find_suff_len = 0; | 921 | size_t find_pref_len = 0, find_suff_len = 0; |
| 922 | 922 | ||
| 923 | if (!modifier && !lenf) | 923 | if (!modifier && lenf == 0 && lenr == 0) |
| 924 | return buf; | 924 | return buf; |
| 925 | 925 | ||
| 926 | if (find_pref) { | 926 | if (find_pref) { |
| @@ -948,14 +948,18 @@ modify_words(const char *val, int modifier, size_t lenf, | |||
| 948 | word = sep + 1; | 948 | word = sep + 1; |
| 949 | } | 949 | } |
| 950 | } | 950 | } |
| 951 | if (lenf) { | 951 | if (find_pref != NULL || lenf != 0 || lenr != 0) { |
| 952 | size_t lenw = strlen(word); | 952 | size_t lenw = strlen(word); |
| 953 | // This code implements pattern macro expansions: | 953 | // This code implements pattern macro expansions: |
| 954 | // https://austingroupbugs.net/view.php?id=519 | 954 | // https://austingroupbugs.net/view.php?id=519 |
| 955 | // | 955 | // |
| 956 | // find: <prefix>%<suffix> | 956 | // find: <prefix>%<suffix> |
| 957 | // example: src/%.c | 957 | // example: src/%.c |
| 958 | if (lenw >= lenf - 1 && find_pref) { | 958 | // |
| 959 | // For a pattern of the form: | ||
| 960 | // $(string1:[op]%[os]=[np][%][ns]) | ||
| 961 | // lenf is the length of [op]%[os]. So lenf >= 1. | ||
| 962 | if (find_pref != NULL && lenw + 1 >= lenf) { | ||
| 959 | // If prefix and suffix of word match find_pref and | 963 | // If prefix and suffix of word match find_pref and |
| 960 | // find_suff, then do substitution. | 964 | // find_suff, then do substitution. |
| 961 | if (strncmp(word, find_pref, find_pref_len) == 0 && | 965 | if (strncmp(word, find_pref, find_pref_len) == 0 && |
| @@ -1011,7 +1015,7 @@ expand_macros(const char *str, int except_dollar) | |||
| 1011 | char *find, *replace, *modified; | 1015 | char *find, *replace, *modified; |
| 1012 | char *expval, *expfind, *find_suff, *repl_suff; | 1016 | char *expval, *expfind, *find_suff, *repl_suff; |
| 1013 | char *find_pref = NULL, *repl_pref = NULL; | 1017 | char *find_pref = NULL, *repl_pref = NULL; |
| 1014 | size_t lenf; | 1018 | size_t lenf, lenr; |
| 1015 | char modifier; | 1019 | char modifier; |
| 1016 | struct macro *mp; | 1020 | struct macro *mp; |
| 1017 | 1021 | ||
| @@ -1041,11 +1045,13 @@ expand_macros(const char *str, int except_dollar) | |||
| 1041 | } | 1045 | } |
| 1042 | 1046 | ||
| 1043 | // Only do suffix replacement or pattern macro expansion | 1047 | // Only do suffix replacement or pattern macro expansion |
| 1044 | // if both ':' and '=' are found. This is indicated by | 1048 | // if both ':' and '=' are found, plus a '%' for the latter. |
| 1045 | // lenf != 0. | 1049 | // Suffix replacement is indicated by |
| 1050 | // find_pref == NULL && (lenf != 0 || lenr != 0); | ||
| 1051 | // pattern macro expansion by find_pref != NULL. | ||
| 1046 | expfind = NULL; | 1052 | expfind = NULL; |
| 1047 | find_suff = repl_suff = NULL; | 1053 | find_suff = repl_suff = NULL; |
| 1048 | lenf = 0; | 1054 | lenf = lenr = 0; |
| 1049 | if ((find = find_char(name, ':'))) { | 1055 | if ((find = find_char(name, ':'))) { |
| 1050 | *find++ = '\0'; | 1056 | *find++ = '\0'; |
| 1051 | expfind = expand_macros(find, FALSE); | 1057 | expfind = expand_macros(find, FALSE); |
| @@ -1059,8 +1065,11 @@ expand_macros(const char *str, int except_dollar) | |||
| 1059 | if ((repl_suff = strchr(replace, '%'))) | 1065 | if ((repl_suff = strchr(replace, '%'))) |
| 1060 | *repl_suff++ = '\0'; | 1066 | *repl_suff++ = '\0'; |
| 1061 | } else { | 1067 | } else { |
| 1068 | if (posix && lenf == 0) | ||
| 1069 | error("empty suffix"); | ||
| 1062 | find_suff = expfind; | 1070 | find_suff = expfind; |
| 1063 | repl_suff = replace; | 1071 | repl_suff = replace; |
| 1072 | lenr = strlen(repl_suff); | ||
| 1064 | } | 1073 | } |
| 1065 | } | 1074 | } |
| 1066 | } | 1075 | } |
| @@ -1105,7 +1114,7 @@ expand_macros(const char *str, int except_dollar) | |||
| 1105 | mp->m_flag = TRUE; | 1114 | mp->m_flag = TRUE; |
| 1106 | expval = expand_macros(mp->m_val, FALSE); | 1115 | expval = expand_macros(mp->m_val, FALSE); |
| 1107 | mp->m_flag = FALSE; | 1116 | mp->m_flag = FALSE; |
| 1108 | modified = modify_words(expval, modifier, lenf, | 1117 | modified = modify_words(expval, modifier, lenf, lenr, |
| 1109 | find_pref, repl_pref, find_suff, repl_suff); | 1118 | find_pref, repl_pref, find_suff, repl_suff); |
| 1110 | if (modified) | 1119 | if (modified) |
| 1111 | free(expval); | 1120 | 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: | |||
| 450 | ' | 450 | ' |
| 451 | cd .. || exit 1; rm -rf make.tempdir 2>/dev/null | 451 | cd .. || exit 1; rm -rf make.tempdir 2>/dev/null |
| 452 | 452 | ||
| 453 | # An empty original suffix indicates that every word should have | ||
| 454 | # the new suffix added. If neither suffix is provided the words | ||
| 455 | # remain unchanged. | ||
| 456 | testing "make macro expansion and suffix substitution 3" \ | ||
| 457 | "make -f -" "src1.c src2.c\nsrc1 src2\n" "" ' | ||
| 458 | SRCS = src1 src2 | ||
| 459 | target: | ||
| 460 | @echo $(SRCS:=.c) | ||
| 461 | @echo $(SRCS:=) | ||
| 462 | ' | ||
| 463 | |||
| 453 | # Skip duplicate entries in $? and $^ | 464 | # Skip duplicate entries in $? and $^ |
| 454 | mkdir make.tempdir && cd make.tempdir || exit 1 | 465 | mkdir make.tempdir && cd make.tempdir || exit 1 |
| 455 | touch -t 202206171200 file1 file3 | 466 | touch -t 202206171200 file1 file3 |
