From 0b87e69888e52ce5ca797560124564efc794414c Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 10 Sep 2024 13:47:56 +0100 Subject: make: handling of leading whitespace in makefiles Try to match how different makes handle leading whitespace in makefiles. (Tested with GNU, BSD, Schily and UNIX Version 7 make.) - Commands in rules must start with a tab. It's the law. - BSD make doesn't allow any whitespace at the start of an include line. Enforce this restriction in POSIX mode: 'the word include ... appears at the beginning of a line'. As an extension allow arbitrary tabs or spaces. - All implementations allow a space as the first character of a macro definition or rule. Permit this in all cases. - Only GNU make allows a tab as the first character of a macro definition, but POSIX 2024 seems to permit it too: 'string1 is defined as all characters from the first non- character to the last non- character, inclusive'. Allow this in POSIX 2024 mode and as an extension. - No implementation allows a tab as the first character of a rule. Disallow this in all cases. Adds 32-64 bytes. (pdpmake GitHub issue 63) --- miscutils/make.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/miscutils/make.c b/miscutils/make.c index b2edfdbb4..1e7b77ddb 100644 --- a/miscutils/make.c +++ b/miscutils/make.c @@ -1478,15 +1478,10 @@ expand_macros(const char *str, int except_dollar) /* * Process a non-command line */ -static char * +static void process_line(char *s) { - char *r, *t; - - // Skip leading blanks - while (isblank(*s)) - s++; - r = s; + char *t; // Strip comment // don't treat '#' in macro expansion as a comment @@ -1519,8 +1514,6 @@ process_line(char *s) } } *t = '\0'; - - return r; } enum { @@ -1605,8 +1598,8 @@ skip_line(const char *str1) int ret = cstate[clevel] & SKIP_LINE; int key; - copy = xstrdup(str1); - q = process_line(copy); + q = copy = xstrdup(str1); + process_line(copy); if ((token = gettok(&q)) != NULL) { switch (index_in_strings("else\0endif\0", token)) { case ENDIF: @@ -2055,8 +2048,6 @@ input(FILE *fd, int ilevel) str1 = readline(fd, FALSE); while (str1) { str2 = NULL; - if (*str1 == '\t') // Command without target - error("command not allowed here"); // Newlines and comments are handled differently in command lines // and other types of line. Take a copy of the current line before @@ -2066,9 +2057,13 @@ input(FILE *fd, int ilevel) // target: prereq; command // copy = xstrdup(str1); - str = process_line(str1); + process_line(str1); + str = str1; // Check for an include line + if (!posix) + while (isblank(*str)) + ++str; minus = !POSIX_2017 && *str == '-'; p = str + minus; if (strncmp(p, "include", 7) == 0 && isblank(p[7])) { @@ -2117,6 +2112,11 @@ input(FILE *fd, int ilevel) } // Check for a macro definition + str = str1; + // POSIX 2024 seems to allow a tab as the first character of + // a macro definition, though most implementations don't. + if (POSIX_2017 && *str == '\t') + error("command not allowed here"); if (find_char(str, '=') != NULL) { int level = (useenv || fd == NULL) ? 4 : 3; // Use a copy of the line: we might need the original @@ -2221,6 +2221,8 @@ input(FILE *fd, int ilevel) // If we get here it must be a target rule try_target: + if (*str == '\t') // Command without target + error("command not allowed here"); p = expanded = expand_macros(str, FALSE); // Look for colon separator -- cgit v1.2.3-55-g6feb