diff options
Diffstat (limited to 'src/compiler')
| -rw-r--r-- | src/compiler/lex.zc | 6 | ||||
| -rw-r--r-- | src/compiler/stmt.zc | 12 |
2 files changed, 15 insertions, 3 deletions
diff --git a/src/compiler/lex.zc b/src/compiler/lex.zc index 712eff8..95415a6 100644 --- a/src/compiler/lex.zc +++ b/src/compiler/lex.zc @@ -533,8 +533,9 @@ int lex1() { while (isidc(ch)) { n = token_char(n, ch); nextch(); } tbuf[n] = 0; if (n == 1 && tbuf[0] == 'b' && ch == 34) { - n = 0; nextch(); + n = 0; dg = line; nextch(); while (ch >= 0 && ch != 34) { v = escch(); n = token_char(n, v); } + if (ch < 0) { tline = dg; serr("unterminated string literal"); } // spec 1.4.4 nextch(); tbuf[n] = 0; tk = T_BSTR; tv = intern(tbuf); return 0; @@ -556,8 +557,9 @@ int lex1() { return 0; } if (ch == 34) { - nextch(); + dg = line; nextch(); while (ch >= 0 && ch != 34) { v = escch(); n = token_char(n, v); } + if (ch < 0) { tline = dg; serr("unterminated string literal"); } // spec 1.4.4 nextch(); tbuf[n] = 0; tk = T_STR; tv = intern(tbuf); return 0; diff --git a/src/compiler/stmt.zc b/src/compiler/stmt.zc index e98cb27..79e5fb8 100644 --- a/src/compiler/stmt.zc +++ b/src/compiler/stmt.zc @@ -566,11 +566,19 @@ int casebody(int s0, int live0) { live = 0; return 0; } +// a case label seen twice in one switch is an error (spec 4.7.2): the second +// arm could never run. the first 256 labels of a switch are checked. +int case_seen(word seen, int n, int v) { + int i = 0; + while (i < n) { if (seen[i] == v) { serr("duplicate case label"); return n; } i++; } + if (n < 256) { seen[n] = v; n++; } + return n; +} // compile a switch statement. int kw_switch() { int sl = tline; int save = nloc, tmp, c, s0, live0, defent = -1, skip, nxt, bj, v, a = -1, st, tg = 0, cov = 0, gi, nb = 0, j, arm, bi; - word[8] pbn; word[8] pbl; + word[8] pbn; word[8] pbl; word[256] seen; int nseen = 0; stmtonly(); next(); expect(s_lp); c = expr(); st = xty; rval(); plainuse(c); expect(s_rp); @@ -609,6 +617,7 @@ int kw_switch() { expect(s_rp); if (nb && nb != pm_nf[gi]) serr("a case binds every field of its member"); // member() with no names matches by tag (spec 4.7.3) v = pm_tag[gi]; + nseen = case_seen(seen, nseen, v); if (v < 63) cov = cov | (1 << v); laddr(lslot[tmp]); op(O_LD); op(O_LD); lit(v); op(O_SUB); bj = fixnew(hole(), bj); op(O_JZ); @@ -633,6 +642,7 @@ int kw_switch() { } else { while (1) { v = cexpr(); + nseen = case_seen(seen, nseen, v); if (tg && v >= 0 && v < 63) cov = cov | (1 << v); laddr(lslot[tmp]); op(O_LD); if (tg) op(O_LD); |
