scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

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:
Msrc/cmd/scc-make/parser.c | 82+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Atests/make/execute/0091-expansion.sh | 23+++++++++++++++++++++++
Atests/make/execute/0092-expansion.sh | 30++++++++++++++++++++++++++++++
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