diff options
author | Ron Yorston <rmy@pobox.com> | 2024-08-08 12:17:54 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2024-08-08 12:24:28 +0100 |
commit | e90345c1048f2c53074a1bd88e7870ee6a452b01 (patch) | |
tree | 08fd6ce81f7f322df21e0f2d7b7e7cd44f12cd61 | |
parent | c7f8fcfb3e26067019de01fdeeffd1ab556f73b9 (diff) | |
download | busybox-w32-e90345c1048f2c53074a1bd88e7870ee6a452b01.tar.gz busybox-w32-e90345c1048f2c53074a1bd88e7870ee6a452b01.tar.bz2 busybox-w32-e90345c1048f2c53074a1bd88e7870ee6a452b01.zip |
make: allow empty commands
pdpmake didn't allow rules to have empty commands. There are
circumstances where this may be useful.
Make the following changes:
- Add a flag to readline() to indicate the next line is expected
to be a command. If this flag is true and the input line starts
with a tab return it immediately, thus skipping the check for
an empty line or comment line.
- In docmds() skip tabs and spaces after a command prefix. If the
resulting command is empty don't print it or try to execute it.
- In newcmd() allow empty commands.
Adds 48-96 bytes.
(pdpmake GitHub issue 56)
-rw-r--r-- | miscutils/make.c | 22 | ||||
-rwxr-xr-x | testsuite/make.tests | 11 |
2 files changed, 23 insertions, 10 deletions
diff --git a/miscutils/make.c b/miscutils/make.c index c65d32e78..1dfbd8c44 100644 --- a/miscutils/make.c +++ b/miscutils/make.c | |||
@@ -456,9 +456,6 @@ newcmd(struct cmd **cphead, char *str) | |||
456 | while (isspace(*str)) | 456 | while (isspace(*str)) |
457 | str++; | 457 | str++; |
458 | 458 | ||
459 | if (*str == '\0') // No command, leave current head unchanged | ||
460 | return; | ||
461 | |||
462 | while (*cphead) | 459 | while (*cphead) |
463 | cphead = &(*cphead)->c_next; | 460 | cphead = &(*cphead)->c_next; |
464 | *cphead = xzalloc(sizeof(struct cmd)); | 461 | *cphead = xzalloc(sizeof(struct cmd)); |
@@ -1708,7 +1705,7 @@ make_fgets(char *s, int size, FILE *fd) | |||
1708 | * Ignore comment lines. Return NULL on EOF. | 1705 | * Ignore comment lines. Return NULL on EOF. |
1709 | */ | 1706 | */ |
1710 | static char * | 1707 | static char * |
1711 | readline(FILE *fd) | 1708 | readline(FILE *fd, int want_command) |
1712 | { | 1709 | { |
1713 | char *p, *str = NULL; | 1710 | char *p, *str = NULL; |
1714 | int pos = 0; | 1711 | int pos = 0; |
@@ -1748,6 +1745,9 @@ readline(FILE *fd) | |||
1748 | } | 1745 | } |
1749 | dispno = lineno; | 1746 | dispno = lineno; |
1750 | 1747 | ||
1748 | if (want_command && *str == '\t') | ||
1749 | return str; | ||
1750 | |||
1751 | // Check for comment lines and lines that are conditionally skipped. | 1751 | // Check for comment lines and lines that are conditionally skipped. |
1752 | p = str; | 1752 | p = str; |
1753 | while (isblank(*p)) | 1753 | while (isblank(*p)) |
@@ -2043,7 +2043,7 @@ input(FILE *fd, int ilevel) | |||
2043 | bool minus; | 2043 | bool minus; |
2044 | 2044 | ||
2045 | lineno = 0; | 2045 | lineno = 0; |
2046 | str1 = readline(fd); | 2046 | str1 = readline(fd, FALSE); |
2047 | while (str1) { | 2047 | while (str1) { |
2048 | str2 = NULL; | 2048 | str2 = NULL; |
2049 | if (*str1 == '\t') // Command without target | 2049 | if (*str1 == '\t') // Command without target |
@@ -2292,7 +2292,7 @@ input(FILE *fd, int ilevel) | |||
2292 | 2292 | ||
2293 | // Create list of commands | 2293 | // Create list of commands |
2294 | startno = dispno; | 2294 | startno = dispno; |
2295 | while ((str2 = readline(fd)) && *str2 == '\t') { | 2295 | while ((str2 = readline(fd, TRUE)) && *str2 == '\t') { |
2296 | newcmd(&cp, process_command(str2)); | 2296 | newcmd(&cp, process_command(str2)); |
2297 | free(str2); | 2297 | free(str2); |
2298 | } | 2298 | } |
@@ -2343,7 +2343,7 @@ input(FILE *fd, int ilevel) | |||
2343 | end_loop: | 2343 | end_loop: |
2344 | free(str1); | 2344 | free(str1); |
2345 | dispno = lineno; | 2345 | dispno = lineno; |
2346 | str1 = str2 ? str2 : readline(fd); | 2346 | str1 = str2 ? str2 : readline(fd, FALSE); |
2347 | free(copy); | 2347 | free(copy); |
2348 | free(expanded); | 2348 | free(expanded); |
2349 | #if ENABLE_FEATURE_MAKE_POSIX | 2349 | #if ENABLE_FEATURE_MAKE_POSIX |
@@ -2427,7 +2427,9 @@ docmds(struct name *np, struct cmd *cp) | |||
2427 | sdomake = TRUE + 1; | 2427 | sdomake = TRUE + 1; |
2428 | else | 2428 | else |
2429 | break; | 2429 | break; |
2430 | q++; | 2430 | do { |
2431 | q++; | ||
2432 | } while (isblank(*q)); | ||
2431 | } | 2433 | } |
2432 | 2434 | ||
2433 | if (sdomake > TRUE) { | 2435 | if (sdomake > TRUE) { |
@@ -2437,7 +2439,7 @@ docmds(struct name *np, struct cmd *cp) | |||
2437 | } else if (!sdomake) | 2439 | } else if (!sdomake) |
2438 | ssilent = dotouch; | 2440 | ssilent = dotouch; |
2439 | 2441 | ||
2440 | if (!ssilent) { | 2442 | if (!ssilent && *q != '\0') { // Ignore empty commands |
2441 | puts(q); | 2443 | puts(q); |
2442 | fflush_all(); | 2444 | fflush_all(); |
2443 | } | 2445 | } |
@@ -2448,7 +2450,7 @@ docmds(struct name *np, struct cmd *cp) | |||
2448 | continue; | 2450 | continue; |
2449 | } | 2451 | } |
2450 | 2452 | ||
2451 | if (sdomake) { | 2453 | if (sdomake && *q != '\0') { // Ignore empty commands |
2452 | // Get the shell to execute it | 2454 | // Get the shell to execute it |
2453 | int status; | 2455 | int status; |
2454 | char *cmd = !signore && posix ? auto_concat("set -e;", q) : q; | 2456 | char *cmd = !signore && posix ? auto_concat("set -e;", q) : q; |
diff --git a/testsuite/make.tests b/testsuite/make.tests index 2425ae99d..5485233f6 100755 --- a/testsuite/make.tests +++ b/testsuite/make.tests | |||
@@ -31,6 +31,17 @@ testing "make .DEFAULT rule for prerequisite" \ | |||
31 | target: source | 31 | target: source |
32 | ' | 32 | ' |
33 | 33 | ||
34 | mkdir make.tempdir && cd make.tempdir || exit 1 | ||
35 | touch target.xyz | ||
36 | testing "make empty command overrides inference rule" \ | ||
37 | "make -f - target 2>/dev/null" "" "" ' | ||
38 | .SUFFIXES: .xyz | ||
39 | .xyz: | ||
40 | @echo xyz | ||
41 | target: ; | ||
42 | ' | ||
43 | cd .. || exit 1; rm -rf make.tempdir 2>/dev/null | ||
44 | |||
34 | # Macros should be expanded before suffix substitution. The suffixes | 45 | # Macros should be expanded before suffix substitution. The suffixes |
35 | # can be obtained by macro expansion. | 46 | # can be obtained by macro expansion. |
36 | testing "make macro expansion and suffix substitution" \ | 47 | testing "make macro expansion and suffix substitution" \ |