From 13772a8a2120017981d280bfe120fdbb74f27860 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Tue, 19 May 2020 16:37:23 -0700 Subject: fix: many bug fixes to number parsing --- sys/cmd/cc/cc.c | 2 +- sys/cmd/cc/lex.c | 23 ++++++++++++---------- sys/cmd/cc/pp.c | 58 ++++++++++++++++++++++++++++++++++++++++++------------- sys/libn/bufio.c | 2 -- sys/libn/string.c | 9 ++++++--- 5 files changed, 65 insertions(+), 29 deletions(-) (limited to 'sys') diff --git a/sys/cmd/cc/cc.c b/sys/cmd/cc/cc.c index 87d9a35..e348893 100644 --- a/sys/cmd/cc/cc.c +++ b/sys/cmd/cc/cc.c @@ -143,7 +143,7 @@ makeio() .pos = C.io->buf.buf + bufio·ungets, .end = C.io->buf.buf + bufio·ungets, }; - C.io->b = C.io->buf.buf; + C.io->b = C.io->buf.beg; return C.io++; } diff --git a/sys/cmd/cc/lex.c b/sys/cmd/cc/lex.c index c84ea68..fc9dc0f 100644 --- a/sys/cmd/cc/lex.c +++ b/sys/cmd/cc/lex.c @@ -37,6 +37,11 @@ getnsbyte(Lexer *lx) int b; b = getbyte(lx); for (;;) { + if (b == EOF) { + popio(lx); + b = getbyte(lx); + continue; + } if (b >= RuneSelf || !isspace(b)) return b; if (b == '\n') @@ -477,24 +482,23 @@ Dispatch: if (b == '.' || tolower(b) == 'e') goto Tflt; Tint: - r = b; n = 10; s = lx->buf; if (*s == '0') { - b = *++s; switch (b) { case 'x': n = 16; break; case 'b': n = 2; break; case 'o': n = 8; break; - default: --s; - } - if (s >= e) { - errorat(lx->pos, "number overflows lexer buffer"); - goto Nospace; + default: goto Rint; } + lx->b = s; + /* reparse number, now with base info */ + while (b = getbyte(lx), (isdigit(b) || ('a' <= b && b <= 'f') || ('A' <= b && b <= 'F') || b == '_')) + *lx->b++ = b; } - + Rint: v = 0; + r = b; for (; s != lx->b ; s++) { b = *s; if (b == '_') continue; @@ -593,7 +597,7 @@ Dispatch: errorat(lx->pos, "identifier too long for buffer: %s", s); goto Nospace; } - if (u >= RuneSelf) { + if (u != EOF && u >= RuneSelf) { ungetbyte(lx); r = getrune(lx); if (!utf8·isletter(r) && !utf8·isdigit(r) && r != 0xb7) { @@ -626,7 +630,6 @@ Dispatch: } goto Return; - default: tok.kind = Anil; errorat(lx->pos, "invalid token, crashing"); diff --git a/sys/cmd/cc/pp.c b/sys/cmd/cc/pp.c index 16fac29..2aa1291 100644 --- a/sys/cmd/cc/pp.c +++ b/sys/cmd/cc/pp.c @@ -62,7 +62,7 @@ defmacro(Lexer *lx, string name, string macro) { Sym *mac; - printf("DEFINING MACRO %s = %s, ON LINE %d\n", name, macro+1, lx->pos.line); + printf("DEFINING MACRO %s = %s, ON LINE %d\n", name, macro+2, lx->pos.line); mac = define(&lx->sym, name, Smacro); mac->macro = macro; @@ -187,7 +187,10 @@ evalmacro(Lexer *lx, byte prec) l = opand(lx); for (;;) { b = getnsbyte(lx); - if (b == '\n') { + // NOTE: Either this or we pass in what are stopping byte is + // New line should always stop us... + // Is there any case where we SHOULDN'T STOP ON ')'? + if (b == '\n' || b == ')') { ungetbyte(lx); break; } @@ -196,7 +199,6 @@ evalmacro(Lexer *lx, byte prec) tok = lex(lx); // simplified jump table of precedence // unpacked to evaluate inline - // NOTE: You might have to unget bytes to replace token on stack switch (tok.kind & Vmask) { case Astar: if (prec > 10) { @@ -451,12 +453,14 @@ ppdef(Lexer *lx) sym = lookup(&lx->sym, s); if (sym) { + // TODO: should be a warning... errorat(lx->pos, "macro redefined: '%s'", sym->name); // goto Bad; } - n = 0; - b = getbyte(lx); + n = 0; + dot = 0; + b = getbyte(lx); if (b == '(') { b = getnsbyte(lx); if (b != ')') { @@ -490,7 +494,7 @@ ppdef(Lexer *lx) if (b != '\n') b = getnsbyte(lx); - buf = str·makef("%d%c", n, PPbeg); + buf = str·makef("%c%c", n, PPbeg); for (;;) { if (isalpha(b) || b == '_') { lx->b = lx->buf; @@ -512,7 +516,8 @@ ppdef(Lexer *lx) continue; Args: /* Check for argx ## argy OR argx##argy */ - if (isspace(b)) { + f = 0; + if (b != '\n' && isspace(b)) { b = getnsbyte(lx); f = 1; } @@ -550,6 +555,7 @@ ppdef(Lexer *lx) str·appendbyte(&buf, 'a' + i); continue; } + if (b == '/') { b = getbyte(lx); if (b == '/') { @@ -577,6 +583,7 @@ ppdef(Lexer *lx) str·appendbyte(&buf, '/'); continue; } + if (b == '\\') { b = getbyte(lx); /* unix */ @@ -607,6 +614,7 @@ ppdef(Lexer *lx) errorat(lx->pos, "macro operator '##' must be proceeded by a valid variable identifier"); goto Bad; } + lx->b = lx->buf; while (isalnum(b) || b == '_') { *lx->b++ = b; @@ -654,17 +662,25 @@ expandmacro(Lexer *lx, Sym *s, byte *dst) byte b, *it, *e, *arg[PPnarg]; /* not a function macro */ - if (*s->macro == '\0') { - strcpy(dst, s->macro + 1); - return 0; + if (s->macro[0] == '\0') { + if (s->macro[1] != PPbeg) { + errorat(lx->pos, "malformed macro"); + goto Bad; + } + 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; b = getnsbyte(lx); - if (b != '(') + if (b != '(') { + errorat(lx->pos, "macro function not given arguments"); goto Bad; + } n = 0; b = getbyte(lx); if (b != ')') { @@ -791,23 +807,39 @@ expandmacro(Lexer *lx, Sym *s, byte *dst) } strcpy(dst, arg[b]); dst += strlen(arg[b]); + break; case PPstr: b = *it++; b -= 'a'; + if (b < 0 && b > n) { + errorat(lx->pos, "malformed macro index: %s", s->name); + goto Bad; + } *dst++ = '"'; strcpy(dst, arg[b]); *dst++ = '"'; + break; case PPcat: b = *it++; b -= 'a'; + if (b < 0 && b > n) { + errorat(lx->pos, "malformed macro index: %s", s->name); + goto Bad; + } strcpy(dst, arg[b]); + b = *it++; b -= 'a'; + if (b < 0 && b > n) { + errorat(lx->pos, "malformed macro index: %s", s->name); + goto Bad; + } strcpy(dst, arg[b]); + break; case '\0': @@ -822,10 +854,10 @@ End: *dst = '\0'; return dst - e; Nospace: - errorf("out of memory during macro expansion %s", s->name); + errorat(lx->pos, "out of memory during macro expansion %s", s->name); Bad: ppend(lx); - errorf("failed to expand macro %s", s->name); + errorat(lx->pos, "failed to expand macro %s", s->name); return -1; } diff --git a/sys/libn/bufio.c b/sys/libn/bufio.c index cde56b7..9bca46a 100644 --- a/sys/libn/bufio.c +++ b/sys/libn/bufio.c @@ -75,7 +75,6 @@ getbyte: error bufio·ungetbyte(io·Buffer *buf, byte c) { - buf->state &= ~bufio·end; if (!(buf->state & bufio·rdr)) { errorf("attempted to unget on non-active reader"); return bufio·err; @@ -135,7 +134,6 @@ nextbyte: error bufio·ungetrune(io·Buffer *buf, rune r) { - buf->state ^= bufio·end; if (buf->state & bufio·rdr) { errorf("attempted to unget on non-active reader"); return bufio·err; diff --git a/sys/libn/string.c b/sys/libn/string.c index 4c8c903..7c152e3 100644 --- a/sys/libn/string.c +++ b/sys/libn/string.c @@ -243,19 +243,22 @@ str·make(const byte *s) string str·makef(const byte *fmt, ...) { + vlong n; + string s; va_list args; + va_start(args, fmt); - vlong n = vsnprintf(nil, 0, fmt, args); + n = vsnprintf(nil, 0, fmt, args); va_end(args); - string s = str·makecap(nil, 0, n); + s = str·makecap(nil, 0, n); va_start(args, fmt); vsnprintf(s, n + 1, fmt, args); va_end(args); Hdr* h = (Hdr*)(s - sizeof(Hdr)); - h->len = n; + h->len = n; return s; } -- cgit v1.2.1