aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/cc
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2020-05-19 19:59:26 -0700
committerNicholas Noll <nbnoll@eml.cc>2020-05-19 19:59:26 -0700
commit74ccc8cc01d365f30a502dd42825de19c05c3743 (patch)
tree0eafca0b2dccf3ef09e33555c9c887141ef18568 /sys/cmd/cc
parentb779c6f7d73e5f70b2d886ed75e6e65217ad1e85 (diff)
fix: arguments now hold their state correctly throughout macro parsing
Diffstat (limited to 'sys/cmd/cc')
-rw-r--r--sys/cmd/cc/cc.c1
-rw-r--r--sys/cmd/cc/pp.c55
2 files changed, 41 insertions, 15 deletions
diff --git a/sys/cmd/cc/cc.c b/sys/cmd/cc/cc.c
index 74040eb..d7bb12c 100644
--- a/sys/cmd/cc/cc.c
+++ b/sys/cmd/cc/cc.c
@@ -249,6 +249,7 @@ init(void)
memset(C.iostk, 0, sizeof(C.iostk));
C.lxr = (Lexer){ 0 };
+ C.lxr.b = C.lxr.buf;
}
error
diff --git a/sys/cmd/cc/pp.c b/sys/cmd/cc/pp.c
index 264f11a..6ab4ecd 100644
--- a/sys/cmd/cc/pp.c
+++ b/sys/cmd/cc/pp.c
@@ -3,6 +3,8 @@
// -----------------------------------------------------------------------
// helper functions
+// NOTE: The iterator of lexer lx->b IS NOT reset.
+// Its the caller's responsibility.
static
string
ident(Lexer *lx)
@@ -16,17 +18,18 @@ ident(Lexer *lx)
return "";
}
- for (s = lx->buf;;) {
- *s++ = b;
+ s = lx->b;
+ for (;;) {
+ *lx->b++ = b;
b = getbyte(lx);
if (isalnum(b) || b == '_' || b >= RuneSelf)
continue;
ungetbyte(lx);
break;
}
- *s = '\0';
+ *lx->b++ = '\0';
- return lx->buf;
+ return s;
}
static
@@ -424,6 +427,7 @@ ppund(Lexer *lx)
s = ident(lx);
intern(&s);
+ lx->b = lx->buf;
printf("FORGETTING %s\n", s);
err = forget(&lx->sym, s);
@@ -442,7 +446,7 @@ ppdef(Lexer *lx)
int b;
Sym *sym;
int i, j, f, n, dot;
- string s, a, base, buf, args[PPnarg];
+ string s, a, base, end, buf, args[PPnarg];
s = ident(lx);
if (!s) {
@@ -450,6 +454,7 @@ ppdef(Lexer *lx)
goto Bad;
}
intern(&s);
+ lx->b = lx->buf;
sym = lookup(&lx->sym, s);
if (sym)
@@ -463,6 +468,7 @@ ppdef(Lexer *lx)
if (b != ')') {
ungetbyte(lx);
for (;;) {
+ // NOTE: This is a pointer to the lx->buffer.
a = identdots(lx, &dot);
if (a == nil) {
errorat(lx->pos, "macro syntax error: improper argument");
@@ -492,24 +498,34 @@ ppdef(Lexer *lx)
b = getnsbyte(lx);
base = lx->b;
+ end = lx->buf + arrlen(lx->buf);
+ if (base >= end) {
+ errorat(lx->pos, "out of macro buffer space!");
+ goto Bad;
+ }
buf = str·makef("%c%c", n, PPbeg);
for (;;) {
if (isalpha(b) || b == '_') {
+ lx->b = base;
*lx->b++ = b;
b = getbyte(lx);
while (isalnum(b) || b == '_') {
*lx->b++ = b;
+ if (lx->b >= end) {
+ errorat(lx->pos, "out of macro buffer space!");
+ goto Bad;
+ }
b = getbyte(lx);
}
*lx->b++ = '\0';
for (i = 0; i < n; i++) {
- if (strcmp(lx->buf, args[i]) == 0) {
+ if (strcmp(base, args[i]) == 0) {
goto Args;
}
}
- str·appendlen(&buf, (lx->b - lx->buf), lx->buf);
+ str·appendlen(&buf, (lx->b - base - 1), base);
continue;
Args:
/* Check for argx ## argy OR argx##argy */
@@ -525,15 +541,19 @@ ppdef(Lexer *lx)
goto Arg;
}
b = getnsbyte(lx);
- lx->b = lx->buf;
+ lx->b = base;
while (isalnum(b) || b == '_') {
*lx->b++ = b;
+ if (lx->b >= end) {
+ errorat(lx->pos, "out of macro buffer space!");
+ goto Bad;
+ }
b = getbyte(lx);
}
*lx->b = '\0';
for (j = 0; j < n; j++) {
- if (strcmp(lx->buf, args[j]) == 0)
+ if (strcmp(base, args[j]) == 0)
goto CatArgs;
}
errorat(lx->pos, "macro operator '##' must be terminated by valid variable identifier");
@@ -612,7 +632,7 @@ ppdef(Lexer *lx)
goto Bad;
}
- lx->b = lx->buf;
+ lx->b = base;
while (isalnum(b) || b == '_') {
*lx->b++ = b;
b = getbyte(lx);
@@ -620,7 +640,7 @@ ppdef(Lexer *lx)
*lx->b = '\0';
for (i = 0; i < n; i++) {
- if (strcmp(lx->buf, args[i]) == 0)
+ if (strcmp(base, args[i]) == 0)
goto Str;
}
errorat(lx->pos, "macro operator '#' must be followed by a valid variable identifier");
@@ -667,9 +687,6 @@ expandmacro(Lexer *lx, Sym *s, byte *dst)
strcpy(dst, s->macro + 2);
return str·len(s->macro)-2;
}
- printf("%c\n", s->macro[0]);
- printf("%c\n", s->macro[1]);
-
dots = *s->macro & PPvar;
nargs = (*s->macro & ~PPvar) - 1;
@@ -854,6 +871,7 @@ Nospace:
errorat(lx->pos, "out of memory during macro expansion %s", s->name);
Bad:
ppend(lx);
+ lx->b = lx->buf;
errorat(lx->pos, "failed to expand macro %s", s->name);
return -1;
}
@@ -925,6 +943,7 @@ ppinc(Lexer *lx)
Bad:
ungetbyte(lx);
+ lx->b = lx->buf;
errorat(lx->pos, "failed include");
ppend(lx);
return 1;
@@ -942,11 +961,13 @@ ppprag(Lexer *lx)
errorat(lx->pos, "failed to parse pragma identifier");
goto Bad;
}
+ lx->b = lx->buf;
if (strcmp(s, "once") == 0) {
pushomit(lx->io->path);
return 0;
}
Bad:
+ lx->b = lx->buf;
errorat(lx->pos, "unrecognized pragma '%s'", s);
ppend(lx);
return 1;
@@ -979,6 +1000,7 @@ ppif(Lexer *lx, int f)
goto Bad;
}
intern(&s);
+ lx->b = lx->buf;
sym = lookup(&lx->sym, s);
if ((!sym && (f == 3)) || (sym && (f == 2)))
@@ -1004,7 +1026,8 @@ Skip:
}
if (!b)
continue;
- s = ident(lx);
+ s = ident(lx);
+ lx->b = lx->buf;
if (!s)
continue;
@@ -1032,6 +1055,7 @@ Skip:
}
Bad:
+ lx->b = lx->buf;
errorat(lx->pos, "bad syntax in preprocessor conditional directive");
ppend(lx);
return 1;
@@ -1088,6 +1112,7 @@ domacro(Lexer *lx)
s = ident(lx);
intern(&s);
+ lx->b = lx->buf;
for (n = 0; n < NUM_DIRECTIVES; n++) {
if ((uintptr)s == (uintptr)directives[n]) {
goto Do;