From 74ccc8cc01d365f30a502dd42825de19c05c3743 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Tue, 19 May 2020 19:59:26 -0700 Subject: fix: arguments now hold their state correctly throughout macro parsing --- sys/cmd/cc/cc.c | 1 + sys/cmd/cc/pp.c | 55 ++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 41 insertions(+), 15 deletions(-) (limited to 'sys/cmd/cc') 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; -- cgit v1.2.1