ref: c24c773d732b95df1f5d612d5ec54f265506d7e0
parent: 9cd10aa29ae615f703ec0c91275cd9c413e38c01
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Wed May 27 11:23:42 EDT 2015
Add string builder to the preprocessor The string builder creates a string from one parameter of the macro.
--- a/cc1/cpp.c
+++ b/cc1/cpp.c
@@ -143,7 +143,7 @@
switch (yytoken) {
case ')':
case ',':
- argp -= 2;
+ argp -= 3;
*argp++ = '\0';
return;
case '(':
@@ -197,8 +197,8 @@
expand(Symbol *sym)
{
unsigned len;
- char *arglist[NR_MACROARG], buffer[BUFSIZE];
- char c, *bp, *arg, *s = sym->u.s;
+ char *arglist[NR_MACROARG], arguments[INPUTSIZ], buffer[BUFSIZE];
+ char prevc, c, *bp, *lim, *arg, *s = sym->u.s;
if (sym == symfile) {
sprintf(buffer, "\"%s\"", getfname());
@@ -210,13 +210,15 @@
}
macroname = sym->name;
- if (!parsepars(buffer, arglist, atoi(s)))
+ if (!parsepars(arguments, arglist, atoi(s)))
return 0;
- bp = buffer;
len = INPUTSIZ-1;
- for (s += 3; c = *s; ++s) {
+ bp = buffer;
+ for (prevc = '\0', s += 3; c = *s; prevc = c, ++s) {
if (c != '@') {
+ if (c == '#')
+ continue;
if (len-- == 0)
goto expansion_too_long;
*bp++ = c;
@@ -223,12 +225,18 @@
} else {
unsigned size;
+ if (prevc == '#')
+ len -= 2;
arg = arglist[atoi(++s)];
size = strlen(arg);
if (size > len)
goto expansion_too_long;
+ if (prevc == '#')
+ *bp++ = '"';
memcpy(bp, arg, size);
bp += size;
+ if (prevc == '#')
+ *bp++ = '"';
len -= size;
s += 2;
}
@@ -292,6 +300,7 @@
*nargs = n;
return s;
}
+
/*
* Copy a string define, and substitute formal arguments of the
* macro into strings in the form @XX@, where XX is the position
@@ -302,18 +311,24 @@
{
int n;
size_t ncopy;
- char arroba[6], *p, **bp, c;
+ char arroba[6], *p, **bp, c, prevc;
- while ((c = *s) && bufsiz > 0) {
+ for (prevc = '\0'; c = *s++; prevc = c) {
if (!isalpha(c) && c != '_' || nargs < 1) {
+ if (bufsiz-- == 0)
+ goto too_long;
+ if (prevc == '#')
+ goto bad_stringer;
*buff++ = c;
- ++s, --bufsiz;
- continue;
+ if (c != '#')
+ continue;
+ while (isspace(*++s))
+ /* nothing */;
}
/* found an identifier, is it one of the macro arguments? */
- for (p = s+1; isalnum(c = *p) || c == '_'; ++p)
+ for (p = s; isalnum(c = *p) || c == '_'; ++p)
/* nothing */;
- ncopy = p - s;
+ ncopy = p - --s;
bp = args;
for (n = 0; n < nargs; ++n) {
if (strncmp(s, *bp++, ncopy))
@@ -322,6 +337,8 @@
s = arroba, ncopy = 4;
break;
}
+ if (n == nargs && prevc == '#')
+ goto bad_stringer;
if ((bufsiz -= ncopy) < 0)
goto too_long;
memcpy(buff, s, ncopy);
@@ -332,6 +349,8 @@
*buff = '\0';
return s;
+bad_stringer:
+ error("'#' is not followed by a macro parameter");
too_long:
error("macro definition too long");
}