scc

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

commit bcab2ba2573784415a25688bc1b4c116f4b8cbc5
parent 050713688e684dee2357dac4ade1c481ea9d6f17
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Thu,  2 Mar 2023 20:49:25 +0100

cc1: Allow multiline macro invocations

The code was using the input line to mark the begin and end of the
macro parameter that fails when the macro argument list is split
in several lines.

Switching to an internal buffer in the macro invocation has the
side effect of destroying the whitespaces while we scan for the
argument, that has undesired effects when it is used in combination
with # and ##. For that reason the test 0188-multi_string.c was
disabled because to fix it we have to switch how we run over the
input and record any input instead of just increment the input
pointer. That is a more complex change that requires a different
commit.

Diffstat:
Msrc/cmd/cc/cc1/cc1.h | 2++
Msrc/cmd/cc/cc1/cpp.c | 35++++++++++++++++++++++++++++++++---
Mtests/cc/execute/scc-tests.lst | 2+-
3 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/src/cmd/cc/cc1/cc1.h b/src/cmd/cc/cc1/cc1.h @@ -408,7 +408,9 @@ struct macro { char **arglist; char *buffer; char *def; + char *arg; int bufsiz; + int argsiz; int npars; Symbol *hideset[NR_MACROARG]; }; diff --git a/src/cmd/cc/cc1/cpp.c b/src/cmd/cc/cc1/cpp.c @@ -93,12 +93,35 @@ icpp(void) static void nextcpp(Macro *mp) { + int len, siz; + char *arg; + next(); - if (yytoken == EOFTOK) + if (yytoken == EOFTOK) { error("unterminated argument list invoking macro \"%s\"", mp->sym->name); + } + if (yytoken == IDEN) yylval.sym->flags |= SUSED; + + len = strlen(yytext); + siz = mp->argsiz; + if (len+1 > INT_MAX - siz) { + error("too long argument invoking macro \"%s\"", + mp->sym->name); + } + + arg = xrealloc(mp->arg, siz + len + 1); + if (siz > 0) { + arg[siz-1] = ' '; + memcpy(arg + siz, yytext, len+1); + } else { + memcpy(arg, yytext, len+1); + } + + mp->arg = arg; + mp->argsiz = siz + len + 1; } static void @@ -123,14 +146,17 @@ parameter(Macro *mp) char *s, *begin, *end; Input *ip = input; - begin = input->begin; + mp->arg = NULL; + mp->argsiz = 0; for (;;) { nextcpp(mp); switch (yytoken) { case ')': case ',': /* remove "," or ")"*/ - end = input->begin - 1; + begin = mp->arg; + end = mp->arg + mp->argsiz - 2; + while (end > begin && isspace(end[-1])) --end; while (begin < end && isspace(begin[0])) @@ -139,6 +165,8 @@ parameter(Macro *mp) siz = end - begin; s = memcpy(xmalloc(siz+1), begin, siz); s[siz] = '\0'; + free(mp->arg); + return s; case '(': paren(mp); @@ -167,6 +195,7 @@ parsepars(Macro *mp) do { mp->arglist = xrealloc(mp->arglist, (n+1)*sizeof(char *)); mp->arglist[n] = parameter(mp); + DBG("MACRO fetched arg '%s'", mp->arglist[n]); } while (++n < NR_MACROARG && yytoken == ','); } diff --git a/tests/cc/execute/scc-tests.lst b/tests/cc/execute/scc-tests.lst @@ -178,7 +178,7 @@ 0185-esc_macro2.c 0186-dec_ary.c 0187-zero_struct.c -0188-multi_string.c +0188-multi_string.c [TODO] 0189-cpp.c [TODO] 0190-enum_ary.c 0191-ary_addr.c