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 |