diff options
-rw-r--r-- | miscutils/make.c | 142 |
1 files changed, 92 insertions, 50 deletions
diff --git a/miscutils/make.c b/miscutils/make.c index 856ecbff0..bc84e8242 100644 --- a/miscutils/make.c +++ b/miscutils/make.c | |||
@@ -28,7 +28,7 @@ | |||
28 | //config: - '--posix' command line option | 28 | //config: - '--posix' command line option |
29 | //config: - PDPMAKE_POSIXLY_CORRECT environment variable | 29 | //config: - PDPMAKE_POSIXLY_CORRECT environment variable |
30 | //config: Enable this if you want to check whether your makefiles are | 30 | //config: Enable this if you want to check whether your makefiles are |
31 | //config: POSIX compliant. This adds about 1.6 kb. | 31 | //config: POSIX compliant. This adds about 1.7 kb. |
32 | 32 | ||
33 | //applet:IF_MAKE(APPLET(make, BB_DIR_USR_BIN, BB_SUID_DROP)) | 33 | //applet:IF_MAKE(APPLET(make, BB_DIR_USR_BIN, BB_SUID_DROP)) |
34 | //applet:IF_PDPMAKE(APPLET_ODDNAME(pdpmake, make, BB_DIR_USR_BIN, BB_SUID_DROP, make)) | 34 | //applet:IF_PDPMAKE(APPLET_ODDNAME(pdpmake, make, BB_DIR_USR_BIN, BB_SUID_DROP, make)) |
@@ -37,7 +37,7 @@ | |||
37 | 37 | ||
38 | //usage:#define make_trivial_usage | 38 | //usage:#define make_trivial_usage |
39 | //usage: IF_FEATURE_MAKE_POSIX( | 39 | //usage: IF_FEATURE_MAKE_POSIX( |
40 | //usage: "[--posix] [-C DIR] [-f FILE] [-j NUM] [-eiknpqrsSt] [MACRO[::]=VAL]... [TARGET]..." | 40 | //usage: "[--posix] [-C DIR] [-f FILE] [-j NUM] [-x PRAG] [-eiknpqrsSt] [MACRO[::]=VAL]... [TARGET]..." |
41 | //usage: ) | 41 | //usage: ) |
42 | //usage: IF_NOT_FEATURE_MAKE_POSIX( | 42 | //usage: IF_NOT_FEATURE_MAKE_POSIX( |
43 | //usage: "[-C DIR] [-f FILE] [-j NUM] [-eiknpqrsSt] [MACRO[::]=VAL]... [TARGET]..." | 43 | //usage: "[-C DIR] [-f FILE] [-j NUM] [-eiknpqrsSt] [MACRO[::]=VAL]... [TARGET]..." |
@@ -50,6 +50,9 @@ | |||
50 | //usage: "\n -C DIR Change to DIR" | 50 | //usage: "\n -C DIR Change to DIR" |
51 | //usage: "\n -f FILE Makefile" | 51 | //usage: "\n -f FILE Makefile" |
52 | //usage: "\n -j NUM Jobs to run in parallel (not implemented)" | 52 | //usage: "\n -j NUM Jobs to run in parallel (not implemented)" |
53 | //usage: IF_FEATURE_MAKE_POSIX( | ||
54 | //usage: "\n -x PRAG Make POSIX mode less strict" | ||
55 | //usage: ) | ||
53 | //usage: "\n -e Environment variables override macros in makefiles" | 56 | //usage: "\n -e Environment variables override macros in makefiles" |
54 | //usage: "\n -i Ignore exit status" | 57 | //usage: "\n -i Ignore exit status" |
55 | //usage: "\n -k Continue on error" | 58 | //usage: "\n -k Continue on error" |
@@ -69,28 +72,52 @@ | |||
69 | #define POSIX_2017 (posix && !(pragma & P_POSIX_202X)) | 72 | #define POSIX_2017 (posix && !(pragma & P_POSIX_202X)) |
70 | 73 | ||
71 | #define OPTSTR1 "eij:+knqrsSt" | 74 | #define OPTSTR1 "eij:+knqrsSt" |
75 | #if ENABLE_FEATURE_MAKE_POSIX | ||
76 | #define OPTSTR2 "pf:*C:*x:*" | ||
77 | #else | ||
72 | #define OPTSTR2 "pf:*C:*" | 78 | #define OPTSTR2 "pf:*C:*" |
79 | #endif | ||
73 | 80 | ||
74 | enum { | 81 | enum { |
75 | OPT_e = (1 << 0), | 82 | OPTBIT_e = 0, |
76 | OPT_i = (1 << 1), | 83 | OPTBIT_i, |
77 | OPT_j = (1 << 2), | 84 | OPTBIT_j, |
78 | OPT_k = (1 << 3), | 85 | OPTBIT_k, |
79 | OPT_n = (1 << 4), | 86 | OPTBIT_n, |
80 | OPT_q = (1 << 5), | 87 | OPTBIT_q, |
81 | OPT_r = (1 << 6), | 88 | OPTBIT_r, |
82 | OPT_s = (1 << 7), | 89 | OPTBIT_s, |
83 | OPT_S = (1 << 8), | 90 | OPTBIT_S, |
84 | OPT_t = (1 << 9), | 91 | OPTBIT_t, |
92 | OPTBIT_p, | ||
93 | OPTBIT_f, | ||
94 | OPTBIT_C, | ||
95 | IF_FEATURE_MAKE_POSIX(OPTBIT_x,) | ||
96 | OPTBIT_precious, | ||
97 | OPTBIT_phony, | ||
98 | OPTBIT_include, | ||
99 | OPTBIT_make, | ||
100 | |||
101 | OPT_e = (1 << OPTBIT_e), | ||
102 | OPT_i = (1 << OPTBIT_i), | ||
103 | OPT_j = (1 << OPTBIT_j), | ||
104 | OPT_k = (1 << OPTBIT_k), | ||
105 | OPT_n = (1 << OPTBIT_n), | ||
106 | OPT_q = (1 << OPTBIT_q), | ||
107 | OPT_r = (1 << OPTBIT_r), | ||
108 | OPT_s = (1 << OPTBIT_s), | ||
109 | OPT_S = (1 << OPTBIT_S), | ||
110 | OPT_t = (1 << OPTBIT_t), | ||
85 | // These options aren't allowed in MAKEFLAGS | 111 | // These options aren't allowed in MAKEFLAGS |
86 | OPT_p = (1 << 10), | 112 | OPT_p = (1 << OPTBIT_p), |
87 | OPT_f = (1 << 11), | 113 | OPT_f = (1 << OPTBIT_f), |
88 | OPT_C = (1 << 12), | 114 | OPT_C = (1 << OPTBIT_C), |
115 | OPT_x = IF_FEATURE_MAKE_POSIX((1 << OPTBIT_x)) + 0, | ||
89 | // The following aren't command line options and must be last | 116 | // The following aren't command line options and must be last |
90 | OPT_precious = (1 << 13), | 117 | OPT_precious = (1 << OPTBIT_precious), |
91 | OPT_phony = (1 << 14), | 118 | OPT_phony = (1 << OPTBIT_phony), |
92 | OPT_include = (1 << 15), | 119 | OPT_include = (1 << OPTBIT_include), |
93 | OPT_make = (1 << 16), | 120 | OPT_make = (1 << OPTBIT_make), |
94 | }; | 121 | }; |
95 | 122 | ||
96 | // Options in OPTSTR1 that aren't included in MAKEFLAGS | 123 | // Options in OPTSTR1 that aren't included in MAKEFLAGS |
@@ -169,7 +196,7 @@ struct macro { | |||
169 | #define M_IMMEDIATE 8 // immediate-expansion macro is being defined | 196 | #define M_IMMEDIATE 8 // immediate-expansion macro is being defined |
170 | #define M_VALID 16 // assert macro name is valid | 197 | #define M_VALID 16 // assert macro name is valid |
171 | 198 | ||
172 | // Constants for PRAGMA. Order must match strings in addrule(). | 199 | // Constants for PRAGMA. Order must match strings in set_pragma(). |
173 | #define P_MACRO_NAME 0x01 | 200 | #define P_MACRO_NAME 0x01 |
174 | #define P_TARGET_NAME 0x02 | 201 | #define P_TARGET_NAME 0x02 |
175 | #define P_COMMAND_COMMENT 0x04 | 202 | #define P_COMMAND_COMMENT 0x04 |
@@ -194,12 +221,11 @@ struct globals { | |||
194 | #define IF_MAX 10 | 221 | #define IF_MAX 10 |
195 | uint8_t clevel; | 222 | uint8_t clevel; |
196 | uint8_t cstate[IF_MAX + 1]; | 223 | uint8_t cstate[IF_MAX + 1]; |
224 | int numjobs; | ||
197 | #if ENABLE_FEATURE_MAKE_POSIX | 225 | #if ENABLE_FEATURE_MAKE_POSIX |
198 | bool posix; | 226 | bool posix; |
199 | bool seen_first; | 227 | bool seen_first; |
200 | #endif | 228 | llist_t *pragmas; |
201 | int numjobs; | ||
202 | #if ENABLE_FEATURE_MAKE_POSIX | ||
203 | unsigned char pragma; | 229 | unsigned char pragma; |
204 | #endif | 230 | #endif |
205 | } FIX_ALIASING; | 231 | } FIX_ALIASING; |
@@ -223,16 +249,14 @@ struct globals { | |||
223 | #define rulepos (G.rulepos) | 249 | #define rulepos (G.rulepos) |
224 | #define clevel (G.clevel) | 250 | #define clevel (G.clevel) |
225 | #define cstate (G.cstate) | 251 | #define cstate (G.cstate) |
252 | #define numjobs (G.numjobs) | ||
226 | #if ENABLE_FEATURE_MAKE_POSIX | 253 | #if ENABLE_FEATURE_MAKE_POSIX |
227 | #define posix (G.posix) | 254 | #define posix (G.posix) |
228 | #define seen_first (G.seen_first) | 255 | #define seen_first (G.seen_first) |
229 | #else | 256 | #define pragmas (G.pragmas) |
230 | #define posix 0 | ||
231 | #endif | ||
232 | #define numjobs (G.numjobs) | ||
233 | #if ENABLE_FEATURE_MAKE_POSIX | ||
234 | #define pragma (G.pragma) | 257 | #define pragma (G.pragma) |
235 | #else | 258 | #else |
259 | #define posix 0 | ||
236 | #define pragma 0 | 260 | #define pragma 0 |
237 | #endif | 261 | #endif |
238 | 262 | ||
@@ -432,9 +456,9 @@ newname(const char *name) | |||
432 | #if ENABLE_FEATURE_MAKE_POSIX | 456 | #if ENABLE_FEATURE_MAKE_POSIX |
433 | error("invalid target name '%s'%s", name, | 457 | error("invalid target name '%s'%s", name, |
434 | potentially_valid_target(name) ? | 458 | potentially_valid_target(name) ? |
435 | ". Allow with .PRAGMA: target_name" : ""); | 459 | ": allow with pragma target_name" : ""); |
436 | #else | 460 | #else |
437 | error("invalid target name '%s'"); | 461 | error("invalid target name '%s'", name); |
438 | #endif | 462 | #endif |
439 | 463 | ||
440 | bucket = getbucket(name); | 464 | bucket = getbucket(name); |
@@ -509,6 +533,28 @@ inc_ref(void *vp) | |||
509 | return vp; | 533 | return vp; |
510 | } | 534 | } |
511 | 535 | ||
536 | #if ENABLE_FEATURE_MAKE_POSIX | ||
537 | static void | ||
538 | set_pragma(const char *name) | ||
539 | { | ||
540 | // Order must match constants above. | ||
541 | static const char *p_name = | ||
542 | "macro_name\0" | ||
543 | "target_name\0" | ||
544 | "command_comment\0" | ||
545 | "empty_suffix\0" | ||
546 | "posix_202x\0" | ||
547 | ; | ||
548 | int idx = index_in_strings(p_name, name); | ||
549 | |||
550 | if (idx != -1) { | ||
551 | pragma |= 1 << idx; | ||
552 | return; | ||
553 | } | ||
554 | warning("invalid pragma '%s'", name); | ||
555 | } | ||
556 | #endif | ||
557 | |||
512 | /* | 558 | /* |
513 | * Add a new rule to a target. This checks to see if commands already | 559 | * Add a new rule to a target. This checks to see if commands already |
514 | * exist for the target. If flag is TRUE the target can have multiple | 560 | * exist for the target. If flag is TRUE the target can have multiple |
@@ -569,21 +615,8 @@ addrule(struct name *np, struct depend *dp, struct cmd *cp, int flag) | |||
569 | np->n_flag |= N_DOUBLE; | 615 | np->n_flag |= N_DOUBLE; |
570 | #if ENABLE_FEATURE_MAKE_POSIX | 616 | #if ENABLE_FEATURE_MAKE_POSIX |
571 | if (strcmp(np->n_name, ".PRAGMA") == 0) { | 617 | if (strcmp(np->n_name, ".PRAGMA") == 0) { |
572 | // Order must match constants above | ||
573 | static const char *p_name = | ||
574 | "macro_name\0" | ||
575 | "target_name\0" | ||
576 | "command_comment\0" | ||
577 | "empty_suffix\0" | ||
578 | "posix_202x\0" | ||
579 | ; | ||
580 | |||
581 | for (; dp; dp = dp->d_next) { | 618 | for (; dp; dp = dp->d_next) { |
582 | int idx = index_in_strings(p_name, dp->d_name->n_name); | 619 | set_pragma(dp->d_name->n_name); |
583 | if (idx != -1) | ||
584 | pragma |= 1 << idx; | ||
585 | else | ||
586 | warning("invalid .PRAGMA %s", dp->d_name->n_name); | ||
587 | } | 620 | } |
588 | } | 621 | } |
589 | #endif | 622 | #endif |
@@ -657,7 +690,7 @@ setmacro(const char *name, const char *val, int level) | |||
657 | #if ENABLE_FEATURE_MAKE_POSIX | 690 | #if ENABLE_FEATURE_MAKE_POSIX |
658 | error("invalid macro name '%s'%s", name, | 691 | error("invalid macro name '%s'%s", name, |
659 | potentially_valid_macro(name) ? | 692 | potentially_valid_macro(name) ? |
660 | ". Allow with .PRAGMA: macro_name" : ""); | 693 | ": allow with pragma macro_name" : ""); |
661 | #else | 694 | #else |
662 | error("invalid macro name '%s'", name); | 695 | error("invalid macro name '%s'", name); |
663 | #endif | 696 | #endif |
@@ -1155,7 +1188,7 @@ expand_macros(const char *str, int except_dollar) | |||
1155 | if (posix && !(pragma & P_EMPTY_SUFFIX) && lenf == 0) | 1188 | if (posix && !(pragma & P_EMPTY_SUFFIX) && lenf == 0) |
1156 | error("empty suffix%s", | 1189 | error("empty suffix%s", |
1157 | !ENABLE_FEATURE_MAKE_POSIX ? "" : | 1190 | !ENABLE_FEATURE_MAKE_POSIX ? "" : |
1158 | ". Allow with .PRAGMA: empty_suffix"); | 1191 | ": allow with pragma empty_suffix"); |
1159 | find_suff = expfind; | 1192 | find_suff = expfind; |
1160 | repl_suff = replace; | 1193 | repl_suff = replace; |
1161 | lenr = strlen(repl_suff); | 1194 | lenr = strlen(repl_suff); |
@@ -1544,7 +1577,7 @@ process_command(char *s) | |||
1544 | t = strchr(s, '#'); | 1577 | t = strchr(s, '#'); |
1545 | if (t) { | 1578 | if (t) { |
1546 | *t = '\0'; | 1579 | *t = '\0'; |
1547 | warning("comment in command. Allow with .PRAGMA: command_comment"); | 1580 | warning("comment in command removed: keep with pragma command_comment"); |
1548 | } | 1581 | } |
1549 | } | 1582 | } |
1550 | 1583 | ||
@@ -2409,7 +2442,7 @@ print_details(void) | |||
2409 | 2442 | ||
2410 | /* | 2443 | /* |
2411 | * Process options from an argv array. If from_env is non-zero we're | 2444 | * Process options from an argv array. If from_env is non-zero we're |
2412 | * handling options from MAKEFLAGS so skip '-C', '-f' and '-p'. | 2445 | * handling options from MAKEFLAGS so skip '-C', '-f', '-p' and '-x'. |
2413 | */ | 2446 | */ |
2414 | static uint32_t | 2447 | static uint32_t |
2415 | process_options(char **argv, int from_env) | 2448 | process_options(char **argv, int from_env) |
@@ -2417,8 +2450,9 @@ process_options(char **argv, int from_env) | |||
2417 | uint32_t flags; | 2450 | uint32_t flags; |
2418 | 2451 | ||
2419 | flags = getopt32(argv, "^" OPTSTR1 OPTSTR2 "\0k-S:S-k", | 2452 | flags = getopt32(argv, "^" OPTSTR1 OPTSTR2 "\0k-S:S-k", |
2420 | &numjobs, &makefiles, &dirs); | 2453 | &numjobs, &makefiles, &dirs |
2421 | if (from_env && (flags & (OPT_C | OPT_f | OPT_p))) | 2454 | IF_FEATURE_MAKE_POSIX(, &pragmas)); |
2455 | if (from_env && (flags & (OPT_C | OPT_f | OPT_p | OPT_x))) | ||
2422 | error("invalid MAKEFLAGS"); | 2456 | error("invalid MAKEFLAGS"); |
2423 | if (posix && (flags & OPT_C)) | 2457 | if (posix && (flags & OPT_C)) |
2424 | error("-C not allowed"); | 2458 | error("-C not allowed"); |
@@ -2656,6 +2690,9 @@ int make_main(int argc UNUSED_PARAM, char **argv) | |||
2656 | const char *path, *newpath = NULL; | 2690 | const char *path, *newpath = NULL; |
2657 | char **fargv, **fargv0; | 2691 | char **fargv, **fargv0; |
2658 | const char *dir, *file; | 2692 | const char *dir, *file; |
2693 | #if ENABLE_FEATURE_MAKE_POSIX | ||
2694 | const char *prag; | ||
2695 | #endif | ||
2659 | char def_make[] = "makefile"; | 2696 | char def_make[] = "makefile"; |
2660 | int estat; | 2697 | int estat; |
2661 | FILE *ifd; | 2698 | FILE *ifd; |
@@ -2719,6 +2756,11 @@ int make_main(int argc UNUSED_PARAM, char **argv) | |||
2719 | } | 2756 | } |
2720 | } | 2757 | } |
2721 | 2758 | ||
2759 | #if ENABLE_FEATURE_MAKE_POSIX | ||
2760 | while ((prag = llist_pop(&pragmas))) | ||
2761 | set_pragma(prag); | ||
2762 | #endif | ||
2763 | |||
2722 | #if !ENABLE_PLATFORM_MINGW32 | 2764 | #if !ENABLE_PLATFORM_MINGW32 |
2723 | init_signal(SIGHUP); | 2765 | init_signal(SIGHUP); |
2724 | init_signal(SIGTERM); | 2766 | init_signal(SIGTERM); |