diff options
author | Quentin Carbonneaux <quentin.carbonneaux@yale.edu> | 2016-08-15 22:59:52 -0700 |
---|---|---|
committer | Quentin Carbonneaux <quentin.carbonneaux@yale.edu> | 2016-08-16 12:54:24 -0700 |
commit | fbbb8e4d78e8b2e9410699fd27af282cc6ddfc4b (patch) | |
tree | ff19ad7b7d03c8ed953e253106fd603dfdf65a76 /parse.c | |
parent | 3f8af2ba7b8f79bd577ca4f2fef5fb922494042d (diff) | |
download | roux-fbbb8e4d78e8b2e9410699fd27af282cc6ddfc4b.tar.gz |
parse union types
Diffstat (limited to 'parse.c')
-rw-r--r-- | parse.c | 163 |
1 files changed, 97 insertions, 66 deletions
diff --git a/parse.c b/parse.c index 38c212e..7afa977 100644 --- a/parse.c +++ b/parse.c @@ -412,20 +412,23 @@ parseref() } static int -parsecls(int *tyn) +findtyp(int i) { - int i; + while (--i >= 0) + if (strcmp(tokval.str, typ[i].name) == 0) + return i; + err("undefined type :%s", tokval.str); +} +static int +parsecls(int *tyn) +{ switch (next()) { default: err("invalid class specifier"); case Ttyp: - for (i=0; i<ntyp; i++) - if (strcmp(tokval.str, typ[i].name) == 0) { - *tyn = i; - return 4; - } - err("undefined type :%s", tokval.str); + *tyn = findtyp(ntyp); + return 4; case Tw: return Kw; case Tl: @@ -788,18 +791,85 @@ parsefn(int export) } static void +parseseg(Seg *seg, Typ *ty, int t) +{ + Typ *ty1; + int n, c, a, al, type; + size_t sz, s; + + n = 0; + sz = 0; + al = ty->align; + while (t != Trbrace) { + type = Sint; + switch (t) { + default: err("invalid type member specifier"); + case Td: type = Sflt; + case Tl: s = 8; a = 3; break; + case Ts: type = Sflt; + case Tw: s = 4; a = 2; break; + case Th: s = 2; a = 1; break; + case Tb: s = 1; a = 0; break; + case Ttyp: + type = Styp; + ty1 = &typ[findtyp(ntyp-1)]; + s = ty1->size; + a = ty1->align; + break; + } + if (a > al) + al = a; + if ((a = sz & (s-1))) { + a = s - a; + if (n < NSeg) { + /* padding segment */ + seg[n].type = Spad; + seg[n].len = a; + n++; + } + } + t = nextnl(); + if (t == Tint) { + c = tokval.num; + t = nextnl(); + } else + c = 1; + sz += a + c*s; + if (type == Styp) + s = ty1 - typ; + for (; c>0 && n<NSeg; c--, n++) { + seg[n].type = type; + seg[n].len = s; + } + if (t != Tcomma) + break; + t = nextnl(); + } + if (t != Trbrace) + err(", or } expected"); + seg[n].type = Sint; + seg[n].len = 0; + a = 1 << al; + sz = (sz + a - 1) & -a; + if (sz >= ty->size) + ty->size = sz; + ty->align = al; +} + +static void parsetyp() { Typ *ty; - int t, n, c, a, al, type; - ulong sz, s; + int t, n, al; if (ntyp >= NTyp) err("too many type definitions"); ty = &typ[ntyp++]; + ty->dark = 0; ty->align = -1; + ty->size = 0; if (nextnl() != Ttyp || nextnl() != Teq) - err("type name, then = expected"); + err("type name and then = expected"); strcpy(ty->name, tokval.str); t = nextnl(); if (t == Talign) { @@ -818,62 +888,23 @@ parsetyp() ty->size = tokval.num; if (ty->align == -1) err("dark types need alignment"); - t = nextnl(); - } else { - ty->dark = 0; - n = 0; - sz = 0; - al = 0; - while (t != Trbrace) { - type = Sint; - switch (t) { - default: err("invalid size specifier %c", tokval.chr); - case Td: type = Sflt; - case Tl: s = 8; a = 3; break; - case Ts: type = Sflt; - case Tw: s = 4; a = 2; break; - case Th: s = 2; a = 1; break; - case Tb: s = 1; a = 0; break; - } - if (a > al) - al = a; - if ((a = sz & (s-1))) { - a = s - a; - if (n < NSeg) { - /* padding segment */ - ty->seg[n].type = Spad; - ty->seg[n].len = a; - n++; - } - } - t = nextnl(); - if (t == Tint) { - c = tokval.num; - t = nextnl(); - } else - c = 1; - sz += a + c*s; - for (; c>0 && n<NSeg; c--, n++) { - ty->seg[n].type = type; - ty->seg[n].len = s; - } - if (t != Tcomma) - break; - t = nextnl(); - } - if (n >= NSeg) - ty->dark = 1; - else - ty->seg[n].len = 0; - if (ty->align == -1) - ty->align = al; - else - al = ty->align; - a = 1 << al; - ty->size = (sz + a - 1) & -a; + if (nextnl() != Trbrace) + err("} expected"); + return; } - if (t != Trbrace) - err(", or } expected"); + n = 0; + ty->seg = vnew(1, sizeof ty->seg[0], emalloc); + if (t == Tlbrace) + do { + if (t != Tlbrace) + err("invalid union member"); + vgrow(&ty->seg, n+1); + parseseg(ty->seg[n++], ty, nextnl()); + t = nextnl(); + } while (t != Trbrace); + else + parseseg(ty->seg[n++], ty, t); + ty->nunion = n; } static void |