From e90345c1048f2c53074a1bd88e7870ee6a452b01 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Thu, 8 Aug 2024 12:17:54 +0100 Subject: 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) --- miscutils/make.c | 22 ++++++++++++---------- 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) while (isspace(*str)) str++; - if (*str == '\0') // No command, leave current head unchanged - return; - while (*cphead) cphead = &(*cphead)->c_next; *cphead = xzalloc(sizeof(struct cmd)); @@ -1708,7 +1705,7 @@ make_fgets(char *s, int size, FILE *fd) * Ignore comment lines. Return NULL on EOF. */ static char * -readline(FILE *fd) +readline(FILE *fd, int want_command) { char *p, *str = NULL; int pos = 0; @@ -1748,6 +1745,9 @@ readline(FILE *fd) } dispno = lineno; + if (want_command && *str == '\t') + return str; + // Check for comment lines and lines that are conditionally skipped. p = str; while (isblank(*p)) @@ -2043,7 +2043,7 @@ input(FILE *fd, int ilevel) bool minus; lineno = 0; - str1 = readline(fd); + str1 = readline(fd, FALSE); while (str1) { str2 = NULL; if (*str1 == '\t') // Command without target @@ -2292,7 +2292,7 @@ input(FILE *fd, int ilevel) // Create list of commands startno = dispno; - while ((str2 = readline(fd)) && *str2 == '\t') { + while ((str2 = readline(fd, TRUE)) && *str2 == '\t') { newcmd(&cp, process_command(str2)); free(str2); } @@ -2343,7 +2343,7 @@ input(FILE *fd, int ilevel) end_loop: free(str1); dispno = lineno; - str1 = str2 ? str2 : readline(fd); + str1 = str2 ? str2 : readline(fd, FALSE); free(copy); free(expanded); #if ENABLE_FEATURE_MAKE_POSIX @@ -2427,7 +2427,9 @@ docmds(struct name *np, struct cmd *cp) sdomake = TRUE + 1; else break; - q++; + do { + q++; + } while (isblank(*q)); } if (sdomake > TRUE) { @@ -2437,7 +2439,7 @@ docmds(struct name *np, struct cmd *cp) } else if (!sdomake) ssilent = dotouch; - if (!ssilent) { + if (!ssilent && *q != '\0') { // Ignore empty commands puts(q); fflush_all(); } @@ -2448,7 +2450,7 @@ docmds(struct name *np, struct cmd *cp) continue; } - if (sdomake) { + if (sdomake && *q != '\0') { // Ignore empty commands // Get the shell to execute it int status; 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" \ target: source ' +mkdir make.tempdir && cd make.tempdir || exit 1 +touch target.xyz +testing "make empty command overrides inference rule" \ + "make -f - target 2>/dev/null" "" "" ' +.SUFFIXES: .xyz +.xyz: + @echo xyz +target: ; +' +cd .. || exit 1; rm -rf make.tempdir 2>/dev/null + # Macros should be expanded before suffix substitution. The suffixes # can be obtained by macro expansion. testing "make macro expansion and suffix substitution" \ -- cgit v1.2.3-55-g6feb