commit 615f2e2509a94bd67cf4992cb9418a39a637b96f
parent 6d8bae308fef0e3a0c6678a61fb375733e30e535
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Fri, 19 Jan 2024 11:02:53 +0100
make: Deal escaped newlines in rule lines
When a escaped newline is detected in the definition of a rule
it and all the following whitespaces must be replaced by a single
space. Skipspaces() cannot be used because it is used in several
scopes where the newline and escape has to be deal in a different
way.
Diffstat:
1 file changed, 36 insertions(+), 7 deletions(-)
diff --git a/src/cmd/make/parser.c b/src/cmd/make/parser.c
@@ -296,7 +296,8 @@ repeat:
c = getc(fp);
if (c == '\n' || c == EOF) {
input->loc.lineno++;
- *s++ = c;
+ if (c == '\n')
+ *s++ = c;
break;
}
if (c == '#') {
@@ -370,6 +371,7 @@ back(int c)
{
if (c == EOF)
return c;
+ assert(input->pos > 0);
input->buf[--input->pos] = c;
}
@@ -608,17 +610,38 @@ expandstring(char *line, Target *tp)
}
static int
+readchar(void)
+{
+ int c;
+
+ while ((c = nextc()) != EOF) {
+ if (c == ' ' || c == '\t')
+ continue;
+ if (c == '\\') {
+ if ((c = nextc()) == '\n')
+ continue;
+ back(c);
+ c = '\\';
+ }
+ break;
+ }
+
+ return c;
+}
+
+static int
next(void)
{
int c;
repeat:
- skipspaces();
+ c = readchar();
- switch (c = nextc()) {
+ switch (c) {
case EOF:
strcpy(token, "<EOF>");
- return tok = EOF;
+ tok = EOF;
+ break;
case '$':
if ((c = nextc()) == '$')
goto single;
@@ -632,11 +655,17 @@ repeat:
single:
token[0] = c;
token[1] = '\0';
- return tok = c;
+ tok = c;
+ break;
default:
+ if (!validchar(c))
+ error("unexpected character '%c'", c);
back(c);
- return tok = item();
+ tok = item();
+ break;
}
+
+ return tok;
}
static char *
@@ -772,7 +801,7 @@ parseinput(void)
targets = NULL;
next();
- if (tok == '\n' || tok == EOF)
+ if (tok == '\n')
continue;
while (tok == ITEM) {