aboutsummaryrefslogtreecommitdiff
path: root/miscutils/make.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2024-04-21 10:58:52 +0100
committerRon Yorston <rmy@pobox.com>2024-04-21 11:05:12 +0100
commitacda99ca9984570b03825c295a5617e67f0c1d7c (patch)
treee614f7774b03094330c854b95a8626a8d48a93a6 /miscutils/make.c
parent90c5352a9746ee76d6219528e00ef5ef39d9dee4 (diff)
downloadbusybox-w32-acda99ca9984570b03825c295a5617e67f0c1d7c.tar.gz
busybox-w32-acda99ca9984570b03825c295a5617e67f0c1d7c.tar.bz2
busybox-w32-acda99ca9984570b03825c295a5617e67f0c1d7c.zip
make: allow mixed macros and targets on command line
POSIX requires macro definitions to appear before targets on the command line. Allow mixed macros and targets as an extension. All macros on the command line are read first, then the targets are processed. Costs 64-80 bytes. (GitHub issue #406)
Diffstat (limited to 'miscutils/make.c')
-rw-r--r--miscutils/make.c38
1 files changed, 30 insertions, 8 deletions
diff --git a/miscutils/make.c b/miscutils/make.c
index cc35d89eb..97ee8d879 100644
--- a/miscutils/make.c
+++ b/miscutils/make.c
@@ -2686,15 +2686,26 @@ expand_makeflags(void)
2686/* 2686/*
2687 * Instantiate all macros in an argv-style array of pointers. Stop 2687 * Instantiate all macros in an argv-style array of pointers. Stop
2688 * processing at the first string that doesn't contain an equal sign. 2688 * processing at the first string that doesn't contain an equal sign.
2689 * As an extension, target arguments on the command line (level 1)
2690 * are skipped and will be processed later.
2689 */ 2691 */
2690static char ** 2692static char **
2691process_macros(char **argv, int level) 2693process_macros(char **argv, int level)
2692{ 2694{
2693 char *p; 2695 char *p;
2694 2696
2695 while (*argv && (p = strchr(*argv, '=')) != NULL) { 2697 for (; *argv; argv++) {
2696 int immediate = 0; 2698 int immediate = 0;
2697 2699
2700 if (!(p = strchr(*argv, '='))) {
2701 // Skip targets on the command line
2702 if (!posix && level == 1)
2703 continue;
2704 else
2705 // Stop at first target
2706 break;
2707 }
2708
2698 if (p - 2 > *argv && p[-1] == ':' && p[-2] == ':') { 2709 if (p - 2 > *argv && p[-1] == ':' && p[-2] == ':') {
2699 if (POSIX_2017) 2710 if (POSIX_2017)
2700 error("invalid macro assignment"); 2711 error("invalid macro assignment");
@@ -2714,8 +2725,6 @@ process_macros(char **argv, int level)
2714 *p = '='; 2725 *p = '=';
2715 if (immediate) 2726 if (immediate)
2716 p[-2] = ':'; 2727 p[-2] = ':';
2717
2718 argv++;
2719 } 2728 }
2720 return argv; 2729 return argv;
2721} 2730}
@@ -2846,6 +2855,7 @@ int make_main(int argc UNUSED_PARAM, char **argv)
2846#endif 2855#endif
2847 char def_make[] = "makefile"; 2856 char def_make[] = "makefile";
2848 int estat; 2857 int estat;
2858 bool found_target;
2849 FILE *ifd; 2859 FILE *ifd;
2850 2860
2851 INIT_G(); 2861 INIT_G();
@@ -2923,7 +2933,12 @@ int make_main(int argc UNUSED_PARAM, char **argv)
2923 setmacro("$", "$", 0 | M_VALID); 2933 setmacro("$", "$", 0 | M_VALID);
2924 2934
2925 // Process macro definitions from the command line 2935 // Process macro definitions from the command line
2926 argv = process_macros(argv, 1); 2936 if (posix)
2937 // In POSIX mode macros must appear before targets.
2938 // argv should now point to targets only.
2939 argv = process_macros(argv, 1);
2940 else
2941 process_macros(argv, 1);
2927 2942
2928 // Process macro definitions from MAKEFLAGS 2943 // Process macro definitions from MAKEFLAGS
2929 if (fargv) { 2944 if (fargv) {
@@ -2983,13 +2998,20 @@ int make_main(int argc UNUSED_PARAM, char **argv)
2983 mark_special(".PHONY", OPT_phony, N_PHONY); 2998 mark_special(".PHONY", OPT_phony, N_PHONY);
2984 2999
2985 estat = 0; 3000 estat = 0;
2986 if (*argv == NULL) { 3001 found_target = FALSE;
3002 for (; *argv; argv++) {
3003 // In POSIX mode only targets should now be in argv.
3004 // As an extension macros may still be present: skip them.
3005 if (posix || !strchr(*argv, '='))
3006 {
3007 found_target = TRUE;
3008 estat |= make(newname(*argv), 0);
3009 }
3010 }
3011 if (!found_target) {
2987 if (!firstname) 3012 if (!firstname)
2988 error("no targets defined"); 3013 error("no targets defined");
2989 estat = make(firstname, 0); 3014 estat = make(firstname, 0);
2990 } else {
2991 while (*argv != NULL)
2992 estat |= make(newname(*argv++), 0);
2993 } 3015 }
2994 3016
2995#if ENABLE_FEATURE_CLEAN_UP 3017#if ENABLE_FEATURE_CLEAN_UP