ref: 598c09bdd15ed4acf036700f3e4ec6e3b8d9be44
parent: 4a695da3a6e31f002608accb745d4369fe7f0eaa
author: Roberto E. Vargas Caballero <[email protected]>
date: Thu Feb 23 16:25:48 EST 2017
[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.
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -600,6 +600,34 @@
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 @@
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();
--- a/cc1/lex.c
+++ b/cc1/lex.c
@@ -561,8 +561,6 @@
}
input->begin = ++input->p;
- if (ahead() == '"')
- goto repeat;
*bp = '\0';
yylen = bp - yytext + 1;
--- /dev/null
+++ b/tests/execute/0119-macrostr.c
@@ -1,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;
+}
--- 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