aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2024-05-29 17:07:19 +0100
committerRon Yorston <rmy@pobox.com>2024-05-29 17:07:19 +0100
commit2a0923c400fe5df140e1c5aad8dc59f4733e8598 (patch)
treebea94ec747825a054a5f9d080bf241c1cbec62a1
parente46cb57b07b4b2c54e8219a5035ee4dff8a20a4c (diff)
downloadbusybox-w32-2a0923c400fe5df140e1c5aad8dc59f4733e8598.tar.gz
busybox-w32-2a0923c400fe5df140e1c5aad8dc59f4733e8598.tar.bz2
busybox-w32-2a0923c400fe5df140e1c5aad8dc59f4733e8598.zip
make: allow :::= macro assignment on command line
GNU make and bmake have different implementations for := macro assignment. In POSIX 202X these are supported by the forms ::= and :::= respectively. Only the former was supported on the pdpmake command line. Add the required support in process_macros() and update the usage message. Adds 48-64 bytes.
-rw-r--r--miscutils/make.c44
-rwxr-xr-xtestsuite/make.tests24
2 files changed, 52 insertions, 16 deletions
diff --git a/miscutils/make.c b/miscutils/make.c
index a4fecd640..8d5664500 100644
--- a/miscutils/make.c
+++ b/miscutils/make.c
@@ -51,10 +51,10 @@
51 51
52//usage:#define make_trivial_usage 52//usage:#define make_trivial_usage
53//usage: IF_FEATURE_MAKE_POSIX( 53//usage: IF_FEATURE_MAKE_POSIX(
54//usage: "[--posix] [-C DIR] [-f FILE] [-j NUM] [-x PRAG] [-eiknpqrsSt] [MACRO[::]=VAL]... [TARGET]..." 54//usage: "[--posix] [-C DIR] [-f FILE] [-j NUM] [-x PRAG] [-eiknpqrsSt] [MACRO[::[:]]=VAL]... [TARGET]..."
55//usage: ) 55//usage: )
56//usage: IF_NOT_FEATURE_MAKE_POSIX( 56//usage: IF_NOT_FEATURE_MAKE_POSIX(
57//usage: "[-C DIR] [-f FILE] [-j NUM] [-eiknpqrsSt] [MACRO[::]=VAL]... [TARGET]..." 57//usage: "[-C DIR] [-f FILE] [-j NUM] [-eiknpqrsSt] [MACRO[::[:]]=VAL]... [TARGET]..."
58//usage: ) 58//usage: )
59//usage:#define make_full_usage "\n\n" 59//usage:#define make_full_usage "\n\n"
60//usage: "Maintain files based on their dependencies\n" 60//usage: "Maintain files based on their dependencies\n"
@@ -2837,12 +2837,14 @@ expand_makeflags(void)
2837static char ** 2837static char **
2838process_macros(char **argv, int level) 2838process_macros(char **argv, int level)
2839{ 2839{
2840 char *p; 2840 char *equal;
2841 2841
2842 for (; *argv; argv++) { 2842 for (; *argv; argv++) {
2843 char *colon = NULL;
2843 int idx, immediate = 0; 2844 int idx, immediate = 0;
2845 int except_dollar = FALSE;
2844 2846
2845 if (!(p = strchr(*argv, '='))) { 2847 if (!(equal = strchr(*argv, '='))) {
2846 // Skip targets on the command line 2848 // Skip targets on the command line
2847 if (!posix && level == 1) 2849 if (!posix && level == 1)
2848 continue; 2850 continue;
@@ -2851,13 +2853,23 @@ process_macros(char **argv, int level)
2851 break; 2853 break;
2852 } 2854 }
2853 2855
2854 if (p - 2 > *argv && p[-1] == ':' && p[-2] == ':') { 2856 if (equal - 2 > *argv && equal[-1] == ':' && equal[-2] == ':') {
2855 if (POSIX_2017) 2857 if (POSIX_2017)
2856 error("invalid macro assignment"); 2858 error("invalid macro assignment");
2857 immediate = M_IMMEDIATE; 2859 if (equal - 3 > *argv && equal[-3] == ':') {
2858 p[-2] = '\0'; 2860 // BSD-style ':='. Expand RHS, but not '$$',
2861 // resulting macro is delayed expansion.
2862 colon = equal - 3;
2863 except_dollar = TRUE;
2864 } else {
2865 // GNU-style ':='. Expand RHS, including '$$',
2866 // resulting macro is immediate expansion.
2867 colon = equal - 2;
2868 immediate = M_IMMEDIATE;
2869 }
2870 *colon = '\0';
2859 } else 2871 } else
2860 *p = '\0'; 2872 *equal = '\0';
2861 2873
2862 /* We want to process _most_ macro assignments. 2874 /* We want to process _most_ macro assignments.
2863 * There are exceptions for particular values from the 2875 * There are exceptions for particular values from the
@@ -2866,18 +2878,18 @@ process_macros(char **argv, int level)
2866 if (!(level == 3 && 2878 if (!(level == 3 &&
2867 (idx == MAKEFLAGS || idx == SHELL || 2879 (idx == MAKEFLAGS || idx == SHELL ||
2868 (idx == CURDIR && !useenv && !POSIX_2017)))) { 2880 (idx == CURDIR && !useenv && !POSIX_2017)))) {
2869 if (immediate) { 2881 if (colon) {
2870 char *exp = expand_macros(p + 1, FALSE); 2882 char *exp = expand_macros(equal + 1, except_dollar);
2871 setmacro(*argv, exp, level | immediate); 2883 setmacro(*argv, exp, level | immediate);
2872 free(exp); 2884 free(exp);
2873 } else { 2885 } else
2874 setmacro(*argv, p + 1, level); 2886 setmacro(*argv, equal + 1, level);
2875 }
2876 } 2887 }
2877 2888
2878 *p = '='; 2889 if (colon)
2879 if (immediate) 2890 *colon = ':';
2880 p[-2] = ':'; 2891 else
2892 *equal = '=';
2881 } 2893 }
2882 return argv; 2894 return argv;
2883} 2895}
diff --git a/testsuite/make.tests b/testsuite/make.tests
index bac673178..0397ab4de 100755
--- a/testsuite/make.tests
+++ b/testsuite/make.tests
@@ -176,6 +176,30 @@ target:
176 @echo $(reset) 176 @echo $(reset)
177' 177'
178 178
179# Since GNU make and bmake interpret := macro assignments differently,
180# POSIX has ::= for the GNU variant and :::= for BSD.
181testing "make different styles of := macro assignment" \
182 "make -f -" \
183 '65 a a $A\n' "" '
184A = a
185GNU ::= $A
186BSD1 :::= $A
187BSD2 :::= $$A
188A = 65
189
190target:
191 @echo '\''$(A) $(GNU) $(BSD1) $(BSD2)'\''
192'
193
194# Similar to the above but for macro assignments on the command line.
195# POSIX has ::= for the GNU variant and :::= for BSD.
196testing "make := macro assignment on command line" \
197 "make -f - A=a 'GNU::=\$A' 'BSD1:::=\$A' 'BSD2:::=\$\$A' A=65" \
198 '65 a a $A\n' "" '
199target:
200 @echo '\''$(A) $(GNU) $(BSD1) $(BSD2)'\''
201'
202
179# basic pattern macro expansion 203# basic pattern macro expansion
180testing "make basic pattern macro expansion" \ 204testing "make basic pattern macro expansion" \
181 "make -f -" \ 205 "make -f -" \