commit d323767195562ff8b8784044206b1d2945160546
parent 1d0baf52bd4313b0d6d6ed6fb595273f21aa9b14
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Tue, 29 Oct 2024 12:47:22 +0100
make: Enable use of expansions in items
An item can be composed by the concatenation of digits and the
expansion of a macro. This change smells a bit, because we are
duplicating the call to expand in too many different places,
but the different behaviour of rules, actions and assignments
drives to something like this, or a nextc() function with
too many globals and conditions.
Diffstat:
3 files changed, 100 insertions(+), 35 deletions(-)
diff --git a/src/cmd/scc-make/parser.c b/src/cmd/scc-make/parser.c
@@ -350,6 +350,18 @@ nextc(void)
return input->buf[input->pos++];
}
+/*
+ * This function only can be called after a call to nextc
+ * that didn't return EOF. It can return '\0', but as
+ * it is used only to check against '$' then it is not
+ * a problem.
+ */
+static int
+ahead(void)
+{
+ return input->buf[input->pos];
+}
+
static int
back(int c)
{
@@ -388,28 +400,6 @@ validchar(int c)
return c == '.' || c == '/' || c == '_' || c == '-' || isalnum(c);
}
-static int
-item(void)
-{
- int c;
- char *s;
-
- for (s = token; s < &token[MAXTOKEN] - 1; *s++ = c) {
- c = nextc();
- if (!validchar(c))
- break;
- }
-
- if (s >= &token[MAXTOKEN] - 1)
- error("token too long");
- if (s == token)
- error("invalid empty token");
- *s = '\0';
- back(c);
-
- return ITEM;
-}
-
static void
expandmacro(char *name, char *repl, char *to)
{
@@ -609,23 +599,31 @@ expandstring(char *line, Target *tp)
}
static int
-readchar(void)
+item(void)
{
int c;
+ char *s;
+ char buf[MAXTOKEN];
- while ((c = nextc()) != EOF) {
- if (c == ' ' || c == '\t')
- continue;
- if (c == '\\') {
- if ((c = nextc()) == '\n')
- continue;
- back(c);
- c = '\\';
- }
- break;
+ for (s = buf; s < &buf[MAXTOKEN] - 1; ) {
+ c = nextc();
+ if (c == '$' && ahead() != '$')
+ expansion(NULL);
+ else if (validchar(c))
+ *s++ = c;
+ else
+ break;
}
+ back(c);
+
+ if (s >= &buf[MAXTOKEN] - 1)
+ error("token too long");
+ if (s == buf)
+ error("invalid empty token");
+ *s++ = '\0';
+ memcpy(token, buf, s - buf);
- return c;
+ return ITEM;
}
static int
@@ -634,7 +632,21 @@ next(void)
int c;
repeat:
- c = readchar();
+ /*
+ * It is better to avoid skipspaces() here, because
+ * it can generate the need for 2 calls to back(),
+ * and we need the character anyway.
+ */
+ c = nextc();
+ if (c == ' ' || c == '\t')
+ goto repeat;
+
+ if (c == '\\') {
+ if ((c = nextc()) == '\n')
+ goto repeat;
+ back(c);
+ c = '\\';
+ }
switch (c) {
case EOF:
diff --git a/tests/make/execute/0091-expansion.sh b/tests/make/execute/0091-expansion.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+trap 'rm -f $tmp1 $tmp2' EXIT INT TERM QUIT HUP
+
+tmp1=tmp1.$$
+tmp2=tmp2.$$
+
+cat >$tmp2 <<EOF
+But before!
+Hello World!
+EOF
+
+scc-make -f- <<'EOF' > $tmp1 2>&1
+STARGET = all
+
+b.$(STARGET): b$(STARGET)
+ @echo Hello World!
+
+ball:
+ @echo But before!
+EOF
+
+diff -u $tmp1 $tmp2
diff --git a/tests/make/execute/0092-expansion.sh b/tests/make/execute/0092-expansion.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+trap 'rm -f $tmp1 $tmp2' EXIT INT TERM QUIT HUP
+
+tmp1=tmp1.$$
+tmp2=tmp2.$$
+
+cat >$tmp2 <<EOF
+yeah!
+done
+EOF
+
+scc-make -f- <<'EOF' > $tmp1 2>&1
+VAR =\
+ all\
+ f1\
+ f2\
+
+OBJS = f.$O
+
+O = e
+
+$(VAR) all : $(OBJS)
+ @echo done
+
+f.$O:
+ @echo yeah!
+EOF
+
+diff $tmp1 $tmp2