commit 693af8c7f3cef75f855092950a8601e25714a23d
parent f2553ae4bbaeabd5c6ecee8d2b0aa1c7e1f3f16f
Author: Roberto E. Vargas Caballero <k0ga@shike2.net>
Date: Fri, 22 May 2026 11:06:58 +0200
cc1: Consolidate spaces in stringize operator
The rules about spaces in stringize operators are specified in 6.10.3.2 of
the C99 spec, and it defines that any sequence of white space between
preprocessor tokens must be consolidated to a single white space
character, but the white characters in strings or character constants
must be preserved. In the same way, " and \ must be escaped.
Diffstat:
1 file changed, 74 insertions(+), 19 deletions(-)
diff --git a/src/cmd/scc-cc/cc1/cpp.c b/src/cmd/scc-cc/cc1/cpp.c
@@ -263,6 +263,79 @@ concatoper(char *def, char *cur)
}
static int
+stringoper(char **bpp, int *sizep, char *arg)
+{
+ int c, esc, delim, siz;
+ char *bp;
+
+ bp = *bpp;
+ siz = *sizep;
+
+ if (siz < 3)
+ return 0;
+
+ esc = delim = 0;
+
+ *bp++ = '"';
+ while ((c = *arg++) != '\0') {
+ switch (c) {
+ case '\'':
+ case '"':
+ if (!esc) {
+ if (!delim)
+ delim = c;
+ else if (delim == c)
+ delim = 0;
+ }
+
+ if (c == '"') {
+ if (siz < 4)
+ return 0;
+ *bp++ = '\\';
+ siz--;
+ } else {
+ if (siz < 3)
+ return 0;
+ }
+
+ *bp++ = c;
+ siz--;
+ break;
+ case '\\':
+ if (siz < 4)
+ return 0;
+ *bp++ = '\\';
+ *bp++ = '\\';
+ siz -= 2;
+
+ if (!esc) {
+ esc = 1;
+ continue;
+ }
+ break;
+ default:
+ if (!delim && isspace(c)) {
+ while (isspace(*arg))
+ ++arg;
+ c = ' ';
+ }
+ if (siz < 3)
+ return 0;
+ *bp++ = c;
+ siz--;
+ break;
+ }
+ esc = 0;
+ }
+ *bp++ = '"';
+
+ *bpp = bp;
+ *sizep = siz;
+
+ return 1;
+}
+
+static int
expandarg(char *arg, char *def, char *curdef, char *buf, int bufsiz)
{
int siz;
@@ -352,26 +425,8 @@ copymacro(Macro *mp)
arg = mp->arglist[atoi(s += 2)];
s += 2;
- if (bufsiz < 3)
+ if (!stringoper(&bp, &bufsiz, arg))
goto expansion_too_long;
-
- *bp++ = '"';
- while ((c = *arg++) != '\0') {
- if (c == '"') {
- if (bufsiz < 3)
- goto expansion_too_long;
- *bp++ = '\\';
- *bp++ = '"';
- bufsiz -= 2;
- } else {
- if (bufsiz < 2)
- goto expansion_too_long;
- *bp++ = c;
- bufsiz--;
- }
- }
- *bp++ = '"';
-
break;
case MACROPAR:
/* parameter substitution */