scc

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

commit 57722b5e8fb04004d69edee448957a8dc10c982f
parent 8460493b18d3aeb17947c988b2062fc546cde80a
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Thu, 23 Feb 2017 21:25:48 +0100

[cc1] Move concatenation of strings to primary()

The concatenation of strings was done in lex.c:/^string
and it was to soon. There was a trick in string() which
look ahead to see if the next character was a ", and then
concatenate them. This strategy failed when the consecutive
string was the result of a macro expansion.

Diffstat:
Mcc1/expr.c | 33++++++++++++++++++++++++++++++---
Mcc1/lex.c | 2--
Atests/execute/0119-macrostr.c | 18++++++++++++++++++
Mtests/execute/scc-tests.lst | 1+
4 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/cc1/expr.c b/cc1/expr.c @@ -600,6 +600,34 @@ notdefined(Symbol *sym) return install(sym->ns, yylval.sym); } +static Symbol * +adjstrings(Symbol *sym) +{ + char *s, *t; + size_t len, n; + Type *tp; + + tp = sym->type; + s = sym->u.s; + for (len = strlen(s);; len += n) { + next(); + if (yytoken != STRING) + break; + t = yylval.sym->u.s; + n = strlen(t); + s = xrealloc(s, len + n + 1); + memcpy(s+len, t, n); + s[len + n] = '\0'; + killsym(yylval.sym); + } + ++len; + if (tp->n.elem != len) { + sym->type = mktype(chartype, ARY, len, NULL); + sym->u.s = s; + } + return sym; +} + /************************************************************* * grammar functions * *************************************************************/ @@ -613,12 +641,11 @@ primary(void) sym = yylval.sym; switch (yytoken) { case STRING: - np = constnode(sym); + np = constnode(adjstrings(sym)); sym->flags |= SHASINIT; emit(ODECL, sym); emit(OINIT, np); - np = varnode(sym); - break; + return varnode(sym); case BUILTIN: fun = sym->u.fun; next(); diff --git a/cc1/lex.c b/cc1/lex.c @@ -561,8 +561,6 @@ repeat: } input->begin = ++input->p; - if (ahead() == '"') - goto repeat; *bp = '\0'; yylen = bp - yytext + 1; diff --git a/tests/execute/0119-macrostr.c b/tests/execute/0119-macrostr.c @@ -0,0 +1,18 @@ + +#define B "b" + +char s[] = "a" B "c"; + +int +main() +{ + if (s[0] != 'a') + return 1; + if (s[1] != 'b') + return 2; + if (s[2] != 'c') + return 3; + if (s[3] != '\0') + return 4; + return 0; +} diff --git a/tests/execute/scc-tests.lst b/tests/execute/scc-tests.lst @@ -109,3 +109,4 @@ 0116-floatcmp.c 0117-pointarith.c 0118-voidmain.c +0119-macrostr.c