aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--miscutils/make.c173
1 files changed, 135 insertions, 38 deletions
diff --git a/miscutils/make.c b/miscutils/make.c
index 941aa49e3..856ecbff0 100644
--- a/miscutils/make.c
+++ b/miscutils/make.c
@@ -23,12 +23,12 @@
23//config: default n 23//config: default n
24//config: depends on MAKE || PDPMAKE 24//config: depends on MAKE || PDPMAKE
25//config: help 25//config: help
26//config: Allow strict enforcement of POSIX 2017 at runtime by: 26//config: Allow strict enforcement of POSIX compliance at runtime by:
27//config: - .POSIX special target in makefile 27//config: - .POSIX special target in makefile
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 500 bytes. 31//config: POSIX compliant. This adds about 1.6 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))
@@ -66,6 +66,8 @@
66#include "common_bufsiz.h" 66#include "common_bufsiz.h"
67#include <glob.h> 67#include <glob.h>
68 68
69#define POSIX_2017 (posix && !(pragma & P_POSIX_202X))
70
69#define OPTSTR1 "eij:+knqrsSt" 71#define OPTSTR1 "eij:+knqrsSt"
70#define OPTSTR2 "pf:*C:*" 72#define OPTSTR2 "pf:*C:*"
71 73
@@ -167,6 +169,13 @@ struct macro {
167#define M_IMMEDIATE 8 // immediate-expansion macro is being defined 169#define M_IMMEDIATE 8 // immediate-expansion macro is being defined
168#define M_VALID 16 // assert macro name is valid 170#define M_VALID 16 // assert macro name is valid
169 171
172// Constants for PRAGMA. Order must match strings in addrule().
173#define P_MACRO_NAME 0x01
174#define P_TARGET_NAME 0x02
175#define P_COMMAND_COMMENT 0x04
176#define P_EMPTY_SUFFIX 0x08
177#define P_POSIX_202X 0x10
178
170#define HTABSIZE 39 179#define HTABSIZE 39
171 180
172struct globals { 181struct globals {
@@ -190,6 +199,9 @@ struct globals {
190 bool seen_first; 199 bool seen_first;
191#endif 200#endif
192 int numjobs; 201 int numjobs;
202#if ENABLE_FEATURE_MAKE_POSIX
203 unsigned char pragma;
204#endif
193} FIX_ALIASING; 205} FIX_ALIASING;
194 206
195#define G (*(struct globals*)bb_common_bufsiz1) 207#define G (*(struct globals*)bb_common_bufsiz1)
@@ -218,6 +230,11 @@ struct globals {
218#define posix 0 230#define posix 0
219#endif 231#endif
220#define numjobs (G.numjobs) 232#define numjobs (G.numjobs)
233#if ENABLE_FEATURE_MAKE_POSIX
234#define pragma (G.pragma)
235#else
236#define pragma 0
237#endif
221 238
222static int make(struct name *np, int level); 239static int make(struct name *np, int level);
223 240
@@ -377,12 +394,29 @@ is_valid_target(const char *name)
377{ 394{
378 const char *s; 395 const char *s;
379 for (s = name; *s; ++s) { 396 for (s = name; *s; ++s) {
380 if (posix && !ispname(*s)) 397 if (posix &&
398 ((pragma & P_TARGET_NAME) || !POSIX_2017 ?
399 !(isfname(*s) || *s == '/') : !ispname(*s)))
381 return FALSE; 400 return FALSE;
382 } 401 }
383 return TRUE; 402 return TRUE;
384} 403}
385 404
405#if ENABLE_FEATURE_MAKE_POSIX
406static int
407potentially_valid_target(const char *name)
408{
409 int ret = FALSE;
410
411 if (!(pragma & P_TARGET_NAME)) {
412 pragma |= P_TARGET_NAME;
413 ret = is_valid_target(name);
414 pragma &= ~P_TARGET_NAME;
415 }
416 return ret;
417}
418#endif
419
386/* 420/*
387 * Intern a name. Return a pointer to the name struct 421 * Intern a name. Return a pointer to the name struct
388 */ 422 */
@@ -395,7 +429,13 @@ newname(const char *name)
395 unsigned int bucket; 429 unsigned int bucket;
396 430
397 if (!is_valid_target(name)) 431 if (!is_valid_target(name))
398 error("invalid target name '%s'", name); 432#if ENABLE_FEATURE_MAKE_POSIX
433 error("invalid target name '%s'%s", name,
434 potentially_valid_target(name) ?
435 ". Allow with .PRAGMA: target_name" : "");
436#else
437 error("invalid target name '%s'");
438#endif
399 439
400 bucket = getbucket(name); 440 bucket = getbucket(name);
401 np = xzalloc(sizeof(struct name)); 441 np = xzalloc(sizeof(struct name));
@@ -496,6 +536,10 @@ addrule(struct name *np, struct depend *dp, struct cmd *cp, int flag)
496 if ((np->n_flag & N_SPECIAL) && !dp && !cp) { 536 if ((np->n_flag & N_SPECIAL) && !dp && !cp) {
497 if (strcmp(np->n_name, ".PHONY") == 0) 537 if (strcmp(np->n_name, ".PHONY") == 0)
498 return; 538 return;
539#if ENABLE_FEATURE_MAKE_POSIX
540 if (strcmp(np->n_name, ".PRAGMA") == 0)
541 pragma = 0;
542#endif
499 freerules(np->n_rule); 543 freerules(np->n_rule);
500 np->n_rule = NULL; 544 np->n_rule = NULL;
501 return; 545 return;
@@ -523,6 +567,26 @@ addrule(struct name *np, struct depend *dp, struct cmd *cp, int flag)
523 np->n_flag |= N_TARGET; 567 np->n_flag |= N_TARGET;
524 if (flag) 568 if (flag)
525 np->n_flag |= N_DOUBLE; 569 np->n_flag |= N_DOUBLE;
570#if ENABLE_FEATURE_MAKE_POSIX
571 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) {
582 int idx = index_in_strings(p_name, 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 }
588 }
589#endif
526} 590}
527 591
528/* 592/*
@@ -542,7 +606,9 @@ is_valid_macro(const char *name)
542 for (s = name; *s; ++s) { 606 for (s = name; *s; ++s) {
543 // In POSIX mode only a limited set of characters are guaranteed 607 // In POSIX mode only a limited set of characters are guaranteed
544 // to be allowed in macro names. 608 // to be allowed in macro names.
545 if (posix && !ispname(*s)) 609 if (posix &&
610 ((pragma & P_MACRO_NAME) || !POSIX_2017 ?
611 !isfname(*s) : !ispname(*s)))
546 return FALSE; 612 return FALSE;
547 // As an extension allow anything that can get through the 613 // As an extension allow anything that can get through the
548 // input parser, apart from the following. 614 // input parser, apart from the following.
@@ -552,6 +618,21 @@ is_valid_macro(const char *name)
552 return TRUE; 618 return TRUE;
553} 619}
554 620
621#if ENABLE_FEATURE_MAKE_POSIX
622static int
623potentially_valid_macro(const char *name)
624{
625 int ret = FALSE;
626
627 if (!(pragma & P_MACRO_NAME)) {
628 pragma |= P_MACRO_NAME;
629 ret = is_valid_macro(name);
630 pragma &= ~P_MACRO_NAME;
631 }
632 return ret;
633}
634#endif
635
555static void 636static void
556setmacro(const char *name, const char *val, int level) 637setmacro(const char *name, const char *val, int level)
557{ 638{
@@ -573,7 +654,13 @@ setmacro(const char *name, const char *val, int level)
573 unsigned int bucket; 654 unsigned int bucket;
574 655
575 if (!valid && !is_valid_macro(name)) 656 if (!valid && !is_valid_macro(name))
657#if ENABLE_FEATURE_MAKE_POSIX
658 error("invalid macro name '%s'%s", name,
659 potentially_valid_macro(name) ?
660 ". Allow with .PRAGMA: macro_name" : "");
661#else
576 error("invalid macro name '%s'", name); 662 error("invalid macro name '%s'", name);
663#endif
577 664
578 bucket = getbucket(name); 665 bucket = getbucket(name);
579 mp = xzalloc(sizeof(struct macro)); 666 mp = xzalloc(sizeof(struct macro));
@@ -1058,15 +1145,17 @@ expand_macros(const char *str, int except_dollar)
1058 if ((replace = find_char(expfind, '='))) { 1145 if ((replace = find_char(expfind, '='))) {
1059 *replace++ = '\0'; 1146 *replace++ = '\0';
1060 lenf = strlen(expfind); 1147 lenf = strlen(expfind);
1061 if (!posix && (find_suff = strchr(expfind, '%'))) { 1148 if (!POSIX_2017 && (find_suff = strchr(expfind, '%'))) {
1062 find_pref = expfind; 1149 find_pref = expfind;
1063 repl_pref = replace; 1150 repl_pref = replace;
1064 *find_suff++ = '\0'; 1151 *find_suff++ = '\0';
1065 if ((repl_suff = strchr(replace, '%'))) 1152 if ((repl_suff = strchr(replace, '%')))
1066 *repl_suff++ = '\0'; 1153 *repl_suff++ = '\0';
1067 } else { 1154 } else {
1068 if (posix && lenf == 0) 1155 if (posix && !(pragma & P_EMPTY_SUFFIX) && lenf == 0)
1069 error("empty suffix"); 1156 error("empty suffix%s",
1157 !ENABLE_FEATURE_MAKE_POSIX ? "" :
1158 ". Allow with .PRAGMA: empty_suffix");
1070 find_suff = expfind; 1159 find_suff = expfind;
1071 repl_suff = replace; 1160 repl_suff = replace;
1072 lenr = strlen(repl_suff); 1161 lenr = strlen(repl_suff);
@@ -1076,7 +1165,7 @@ expand_macros(const char *str, int except_dollar)
1076 1165
1077 p = q = name; 1166 p = q = name;
1078 // If not in POSIX mode expand macros in the name. 1167 // If not in POSIX mode expand macros in the name.
1079 if (!posix) { 1168 if (!POSIX_2017) {
1080 char *expname = expand_macros(name, FALSE); 1169 char *expname = expand_macros(name, FALSE);
1081 free(name); 1170 free(name);
1082 name = expname; 1171 name = expname;
@@ -1092,7 +1181,7 @@ expand_macros(const char *str, int except_dollar)
1092 switch (name[0]) { 1181 switch (name[0]) {
1093 case '^': 1182 case '^':
1094 case '+': 1183 case '+':
1095 if (posix) 1184 if (POSIX_2017)
1096 break; 1185 break;
1097 // fall through 1186 // fall through
1098 case '@': case '%': case '?': case '<': case '*': 1187 case '@': case '%': case '?': case '<': case '*':
@@ -1395,25 +1484,27 @@ target_type(char *s)
1395{ 1484{
1396 char *sfx; 1485 char *sfx;
1397 int ret; 1486 int ret;
1398 static const char *s_name[] = { 1487 static const char *s_name =
1399 ".DEFAULT", 1488 ".DEFAULT\0"
1400 ".POSIX", 1489 ".POSIX\0"
1401 ".IGNORE", 1490 ".IGNORE\0"
1402 ".PRECIOUS", 1491 ".PRECIOUS\0"
1403 ".SILENT", 1492 ".SILENT\0"
1404 ".SUFFIXES", 1493 ".SUFFIXES\0"
1405 ".PHONY", 1494 ".PHONY\0"
1406 ".NOTPARALLEL", 1495 ".NOTPARALLEL\0"
1407 ".WAIT", 1496 ".WAIT\0"
1408 }; 1497#if ENABLE_FEATURE_MAKE_POSIX
1498 ".PRAGMA\0"
1499#endif
1500 ;
1409 1501
1410 if (*s != '.') 1502 if (*s != '.')
1411 return T_NORMAL; 1503 return T_NORMAL;
1412 1504
1413 // Check for one of the known special targets 1505 // Check for one of the known special targets
1414 for (ret = 0; ret < ARRAY_SIZE(s_name); ret++) 1506 if (index_in_strings(s_name, s) >= 0)
1415 if (strcmp(s_name[ret], s) == 0) 1507 return T_SPECIAL;
1416 return T_SPECIAL;
1417 1508
1418 // Check for an inference rule 1509 // Check for an inference rule
1419 ret = T_NORMAL; 1510 ret = T_NORMAL;
@@ -1448,11 +1539,13 @@ process_command(char *s)
1448 int len; 1539 int len;
1449 char *outside; 1540 char *outside;
1450 1541
1451 if (posix) { 1542 if (!(pragma & P_COMMAND_COMMENT) && posix) {
1452 // POSIX strips comments from command lines 1543 // POSIX strips comments from command lines
1453 t = strchr(s, '#'); 1544 t = strchr(s, '#');
1454 if (t) 1545 if (t) {
1455 *t = '\0'; 1546 *t = '\0';
1547 warning("comment in command. Allow with .PRAGMA: command_comment");
1548 }
1456 } 1549 }
1457 1550
1458 len = strlen(s) + 1; 1551 len = strlen(s) + 1;
@@ -1464,7 +1557,7 @@ process_command(char *s)
1464 // Process escaped newlines. Stop at first non-escaped newline. 1557 // Process escaped newlines. Stop at first non-escaped newline.
1465 for (t = u = s; *u && *u != '\n'; ) { 1558 for (t = u = s; *u && *u != '\n'; ) {
1466 if (u[0] == '\\' && u[1] == '\n') { 1559 if (u[0] == '\\' && u[1] == '\n') {
1467 if (posix || outside[u - s]) { 1560 if (POSIX_2017 || outside[u - s]) {
1468 // Outside macro: remove tab following escaped newline. 1561 // Outside macro: remove tab following escaped newline.
1469 *t++ = *u++; 1562 *t++ = *u++;
1470 *t++ = *u++; 1563 *t++ = *u++;
@@ -1624,7 +1717,7 @@ input(FILE *fd, int ilevel)
1624 str = process_line(str1); 1717 str = process_line(str1);
1625 1718
1626 // Check for an include line 1719 // Check for an include line
1627 minus = !posix && *str == '-'; 1720 minus = !POSIX_2017 && *str == '-';
1628 p = str + minus; 1721 p = str + minus;
1629 if (strncmp(p, "include", 7) == 0 && isblank(p[7])) { 1722 if (strncmp(p, "include", 7) == 0 && isblank(p[7])) {
1630 const char *old_makefile = makefile; 1723 const char *old_makefile = makefile;
@@ -1637,7 +1730,7 @@ input(FILE *fd, int ilevel)
1637 while ((p = gettok(&q)) != NULL) { 1730 while ((p = gettok(&q)) != NULL) {
1638 FILE *ifd; 1731 FILE *ifd;
1639 1732
1640 if (!posix) { 1733 if (!POSIX_2017) {
1641 // Try to create include file or bring it up-to-date 1734 // Try to create include file or bring it up-to-date
1642 opts |= OPT_include; 1735 opts |= OPT_include;
1643 make(newname(p), 1); 1736 make(newname(p), 1);
@@ -1651,10 +1744,10 @@ input(FILE *fd, int ilevel)
1651 input(ifd, ilevel + 1); 1744 input(ifd, ilevel + 1);
1652 fclose(ifd); 1745 fclose(ifd);
1653 } 1746 }
1654 if (posix) 1747 if (POSIX_2017)
1655 break; 1748 break;
1656 } 1749 }
1657 if (posix) { 1750 if (POSIX_2017) {
1658 // In POSIX 2017 zero or more than one include file is 1751 // In POSIX 2017 zero or more than one include file is
1659 // unspecified behaviour. 1752 // unspecified behaviour.
1660 if (p == NULL || gettok(&q)) { 1753 if (p == NULL || gettok(&q)) {
@@ -1678,7 +1771,7 @@ input(FILE *fd, int ilevel)
1678 switch (q[-1]) { 1771 switch (q[-1]) {
1679 case ':': 1772 case ':':
1680 // '::=' and ':::=' are from POSIX 202X. 1773 // '::=' and ':::=' are from POSIX 202X.
1681 if (!posix && q - 2 > str && q[-2] == ':') { 1774 if (!POSIX_2017 && q - 2 > str && q[-2] == ':') {
1682 if (q - 3 > str && q[-3] == ':') { 1775 if (q - 3 > str && q[-3] == ':') {
1683 eq = 'B'; // BSD-style ':=' 1776 eq = 'B'; // BSD-style ':='
1684 q[-3] = '\0'; 1777 q[-3] = '\0';
@@ -1689,12 +1782,16 @@ input(FILE *fd, int ilevel)
1689 break; 1782 break;
1690 } 1783 }
1691 // ':=' is a non-POSIX extension. 1784 // ':=' is a non-POSIX extension.
1785 if (posix)
1786 break;
1787 goto set_eq;
1692 case '+': 1788 case '+':
1693 case '?': 1789 case '?':
1694 case '!': 1790 case '!':
1695 // '+=', '?=' and '!=' are from POSIX 202X. 1791 // '+=', '?=' and '!=' are from POSIX 202X.
1696 if (posix) 1792 if (POSIX_2017)
1697 break; 1793 break;
1794 set_eq:
1698 eq = q[-1]; 1795 eq = q[-1];
1699 q[-1] = '\0'; 1796 q[-1] = '\0';
1700 break; 1797 break;
@@ -1817,7 +1914,7 @@ input(FILE *fd, int ilevel)
1817 files = gd.gl_pathv; 1914 files = gd.gl_pathv;
1818 } 1915 }
1819 for (i = 0; i < nfile; ++i) { 1916 for (i = 0; i < nfile; ++i) {
1820 if (!posix && strcmp(files[i], ".WAIT") == 0) 1917 if (!POSIX_2017 && strcmp(files[i], ".WAIT") == 0)
1821 continue; 1918 continue;
1822 np = newname(files[i]); 1919 np = newname(files[i]);
1823 newdep(&dp, np); 1920 newdep(&dp, np);
@@ -2018,7 +2115,7 @@ make1(struct name *np, struct cmd *cp, char *oodate, char *allsrc,
2018 2115
2019 name = splitlib(np->n_name, &member); 2116 name = splitlib(np->n_name, &member);
2020 setmacro("?", oodate, 0 | M_VALID); 2117 setmacro("?", oodate, 0 | M_VALID);
2021 if (!posix) { 2118 if (!POSIX_2017) {
2022 setmacro("+", allsrc, 0 | M_VALID); 2119 setmacro("+", allsrc, 0 | M_VALID);
2023 setmacro("^", dedup, 0 | M_VALID); 2120 setmacro("^", dedup, 0 | M_VALID);
2024 } 2121 }
@@ -2414,7 +2511,7 @@ process_macros(char **argv, int level)
2414 int immediate = 0; 2511 int immediate = 0;
2415 2512
2416 if (p - 2 > *argv && p[-1] == ':' && p[-2] == ':') { 2513 if (p - 2 > *argv && p[-1] == ':' && p[-2] == ':') {
2417 if (posix) 2514 if (POSIX_2017)
2418 error("invalid macro assignment"); 2515 error("invalid macro assignment");
2419 immediate = M_IMMEDIATE; 2516 immediate = M_IMMEDIATE;
2420 p[-2] = '\0'; 2517 p[-2] = '\0';
@@ -2577,7 +2674,7 @@ int make_main(int argc UNUSED_PARAM, char **argv)
2577 } 2674 }
2578#endif 2675#endif
2579 2676
2580 if (!posix) { 2677 if (!POSIX_2017) {
2581 path = argv[0]; 2678 path = argv[0];
2582#if ENABLE_PLATFORM_MINGW32 2679#if ENABLE_PLATFORM_MINGW32
2583 if (has_path(argv[0])) { 2680 if (has_path(argv[0])) {
@@ -2686,7 +2783,7 @@ int make_main(int argc UNUSED_PARAM, char **argv)
2686 mark_special(".SILENT", OPT_s, N_SILENT); 2783 mark_special(".SILENT", OPT_s, N_SILENT);
2687 mark_special(".IGNORE", OPT_i, N_IGNORE); 2784 mark_special(".IGNORE", OPT_i, N_IGNORE);
2688 mark_special(".PRECIOUS", OPT_precious, N_PRECIOUS); 2785 mark_special(".PRECIOUS", OPT_precious, N_PRECIOUS);
2689 if (!posix) 2786 if (!POSIX_2017)
2690 mark_special(".PHONY", OPT_phony, N_PHONY); 2787 mark_special(".PHONY", OPT_phony, N_PHONY);
2691 2788
2692 estat = 0; 2789 estat = 0;