diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
| commit | 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch) | |
| tree | c6e220ba61db3a6ea4052e6841296d829654e664 /utils/c2l/dcl.c | |
| parent | 46439007cf417cbd9ac8049bb4122c890097a0fa (diff) | |
20060303
Diffstat (limited to 'utils/c2l/dcl.c')
| -rw-r--r-- | utils/c2l/dcl.c | 1387 |
1 files changed, 1387 insertions, 0 deletions
diff --git a/utils/c2l/dcl.c b/utils/c2l/dcl.c new file mode 100644 index 00000000..6fb6977a --- /dev/null +++ b/utils/c2l/dcl.c @@ -0,0 +1,1387 @@ +#include "cc.h" + +Node* +dodecl(void (*f)(int,Type*,Sym*), int c, Type *t, Node *n, int gen) +{ + Sym *s; + Node *n1; + long v; + + nearln = lineno; + lastfield = 0; + +loop: + if(n != Z) + switch(n->op) { + default: + diag(n, "unknown declarator: %O", n->op); + break; + + case OARRAY: + t = typ(TARRAY, t); + t->width = 0; + n1 = n->right; + n = n->left; + if(n1 != Z) { + complex(n1); + v = -1; + if(n1->op == OCONST) + v = n1->vconst; + if(v <= 0) { + diag(n, "array size must be a positive constant"); + v = 1; + } + t->width = v * t->link->width; + t->nwidth = n1->left; + } + goto loop; + + case OIND: + t = typ(TIND, t); + t->garb = n->garb; + n = n->left; + goto loop; + + case OFUNC: + t = typ(TFUNC, t); + t->down = fnproto(n); + n = n->left; + goto loop; + + case OBIT: + n1 = n->right; + complex(n1); + lastfield = -1; + if(n1->op == OCONST) + lastfield = n1->vconst; + if(lastfield < 0) { + diag(n, "field width must be non-negative constant"); + lastfield = 1; + } + if(lastfield == 0) { + lastbit = 0; + firstbit = 1; + if(n->left != Z) { + diag(n, "zero width named field"); + lastfield = 1; + } + } + if(!typei[t->etype]) { + diag(n, "field type must be int-like"); + t = types[TINT]; + lastfield = 1; + } + if(lastfield > tfield->width*8) { + diag(n, "field width larger than field unit"); + lastfield = 1; + } + lastbit += lastfield; + if(lastbit > tfield->width*8) { + lastbit = lastfield; + firstbit = 1; + } + n = n->left; + goto loop; + + case ONAME: + if(f == NODECL) + break; + s = n->sym; + (*f)(c, t, s); + if(s->class == CLOCAL) + s = mkstatic(s); + firstbit = 0; + n->sym = s; + n->type = s->type; + acidvar(s); + if(gen) + vtgen(n); + break; + } + lastdcl = t; + return n; +} + +Sym* +mkstatic(Sym *s) +{ + Sym *s1; + + if(s->class != CLOCAL) + return s; + snprint(symb, NSYMB, "%s$%d", s->name, s->block); + s1 = lookup(); + if(s1->class != CSTATIC) { + s1->type = s->type; + s1->offset = s->offset; + s1->block = s->block; + s1->class = CSTATIC; + } + return s1; +} + +/* + * make a copy of a typedef + * the problem is to split out incomplete + * arrays so that it is in the variable + * rather than the typedef. + */ +Type* +tcopy(Type *t) +{ + Type *tl, *tx; + int et; + + if(t == T) + return t; + et = t->etype; + if(typesu[et]) + return t; + tl = tcopy(t->link); + if(tl != t->link || + (et == TARRAY && t->width == 0)) { + tx = typ(TXXX, 0); + *tx = *t; + tx->link = tl; + return tx; + } + return t; +} + +Node* +doinit(Sym *s, Type *t, long o, Node *a) +{ + Node *n, *reta; + + if(t == T) + return Z; + if(s->class == CEXTERN) + s->class = CGLOBL; + if(0) { + print("t = %T; o = %ld; n = %s\n", t, o, s->name); + prtree(a, "doinit value"); + } + + n = initlist; + if(a->op == OINIT) + a = a->left; + initlist = a; + + reta = a; + init1(s, t, o, 0); + if(initlist != Z) + diag(initlist, "more initializers than structure: %s", + s->name); + initlist = n; + + return reta; +} + +/* + * get next major operator, + * dont advance initlist. + */ +Node* +peekinit(void) +{ + Node *a; + + a = initlist; + +loop: + if(a == Z) + return a; + if(a->op == OLIST) { + a = a->left; + goto loop; + } + return a; +} + +/* + * consume and return next element on + * initlist. expand strings. + */ +Node* +nextinit(void) +{ + Node *a, *n; + + a = initlist; + n = Z; + + if(a == Z) + return a; + if(a->op == OLIST) { + n = a->right; + a = a->left; + } + initlist = n; + return a; +} + +int +isstruct(Node *a, Type *t) +{ + Node *n; + + switch(a->op) { + case ODOTDOT: + n = a->left; + if(n && n->type && sametype(n->type, t)) + return 1; + case OSTRING: + case OLSTRING: + case OCONST: + case OINIT: + case OELEM: + return 0; + } + + n = new(ODOTDOT, Z, Z); + *n = *a; + + /* + * ODOTDOT is a flag for tcom + * a second tcom will not be performed + */ + a->op = ODOTDOT; + a->left = n; + a->right = Z; + + if(tcom(n)) + return 0; + + if(sametype(n->type, t)) + return 1; + return 0; +} + +void +init1(Sym *s, Type *t, long o, int exflag) +{ + Node *a, *r, nod; + Type *t1; + long e, w, so, mw; + + a = peekinit(); + if(a == Z) + return; + + if(0) { + print("t = %T; o = %ld; n = %s\n", t, o, s->name); + prtree(a, "init1 value"); + } + + if(exflag && a->op == OINIT){ + doinit(s, t, o, nextinit()); + return; + } + + switch(t->etype) { + default: + diag(Z, "unknown type in initialization: %T to: %s", t, s->name); + return; + + case TCHAR: + case TUCHAR: + case TINT: + case TUINT: + case TSHORT: + case TUSHORT: + case TLONG: + case TULONG: + case TVLONG: + case TUVLONG: + case TFLOAT: + case TDOUBLE: + case TIND: + single: + if(a->op == OARRAY || a->op == OELEM) + return; + + a = nextinit(); + if(a == Z) + return; + + if(t->nbits) + diag(Z, "cannot initialize bitfields"); + if(0 && s->class == CAUTO) + return; + + complex(a); + if(a->type == T) + return; + + if(a->op == OCONST) { + if(!sametype(a->type, t)) { + /* hoop jumping to save malloc */ + if(nodcast == Z) + nodcast = new(OCAST, Z, Z); + nod = *nodcast; + nod.left = a; + nod.type = t; + nod.lineno = a->lineno; + complex(&nod); + if(nod.type) + *a = nod; + } + if(a->op != OCONST) { +/* + diag(a, "initializer is not a constant: %s", + s->name); +*/ + return; + } + if(vconst(a) == 0) + return; + return; + } + if(t->etype == TIND) { + while(a->op == OCAST) { + warn(a, "CAST in initialization ignored"); + a = a->left; + } + if(0 && !sametype(t, a->type)) { + diag(a, "initialization of incompatible pointers: %s", + s->name); + print("%T and %T\n", t, a->type); + } +/* + if(a->op == OADDR) + a = a->left; +*/ + return; + } + + while(a->op == OCAST) + a = a->left; + if(a->op == OADDR) { + warn(a, "initialize pointer to an integer: %s", s->name); + /* a = a->left; */ + return; + } + /* diag(a, "initializer is not a constant: %s", s->name); */ + return; + + case TARRAY: + w = t->link->width; + if(a->op == OSTRING || a->op == OLSTRING) + if(typei[t->link->etype]) { + + /* + * get rid of null if sizes match exactly + */ + a = nextinit(); + /* mw = t->width/w; */ + so = a->type->width/a->type->link->width; + if(t->width <= 0) + t->width = w*(so-1); + USED(a); + return; + } + + mw = -w; + for(e=0;;) { + /* + * peek ahead for element initializer + */ + a = peekinit(); + if(a == Z) + break; + if(a->op == OELEM && t->link->etype != TSTRUCT) + break; + if(a->op == OARRAY) { + if(e && exflag) + break; + a = nextinit(); + r = a->left; + complex(r); + if(r->op != OCONST) { + diag(r, "initializer subscript must be constant"); + return; + } + e = r->vconst; + if(t->width != 0) + if(e < 0 || e*w >= t->width) { + diag(a, "initialization index out of range: %ld", e); + continue; + } + } + + so = e*w; + if(so > mw) + mw = so; + if(t->width != 0) + if(mw >= t->width) + break; + init1(s, t->link, o+so, 1); + e++; + } + if(t->width == 0) + t->width = mw+w; + return; + + case TUNION: + case TSTRUCT: + /* + * peek ahead to find type of rhs. + * if its a structure, then treat + * this element as a variable + * rather than an aggregate. + */ + if(isstruct(a, t)) + goto single; + + if(t->width <= 0) { + diag(Z, "incomplete structure: %s", s->name); + return; + } + + again: + for(t1 = t->link; t1 != T; t1 = t1->down) { + if(a->op == OARRAY && t1->etype != TARRAY) + break; + if(a->op == OELEM) { + if(t1->sym != a->sym) + continue; + nextinit(); + } + init1(s, t1, o+t1->offset, 1); + a = peekinit(); + if(a == Z) + break; + if(a->op == OELEM) + goto again; + } + if(a && a->op == OELEM) + diag(a, "structure element not found %F", a); + return; + } +} + +/* +Node* +newlist(Node *l, Node *r) +{ + if(r == Z) + return l; + if(l == Z) + return r; + return new(OLIST, l, r); +} +*/ + +void +suallign(Type *t) +{ + Type *l; + long o, w; + + o = 0; + switch(t->etype) { + + case TSTRUCT: + t->offset = 0; + w = 0; + for(l = t->link; l != T; l = l->down) { + if(l->nbits) { + if(l->shift <= 0) { + l->shift = -l->shift; + w = round(w, tfield->width); + o = w; + w += tfield->width; + } + l->offset = o; + } else { + if(l->width <= 0) + if(l->sym) + diag(Z, "incomplete structure element: %s", + l->sym->name); + else + diag(Z, "incomplete structure element"); + w = align(w, l, Ael1); + l->offset = w; + w = align(w, l, Ael2); + } + } + w = align(w, t, Asu2); + t->width = w; + acidtype(t); + ttgen(t); + return; + + case TUNION: + t->offset = 0; + w = 0; + for(l = t->link; l != T; l = l->down) { + if(l->width <= 0) + if(l->sym) + diag(Z, "incomplete union element: %s", + l->sym->name); + else + diag(Z, "incomplete union element"); + l->offset = 0; + l->shift = 0; + o = align(align(0, l, Ael1), l, Ael2); + if(o > w) + w = o; + } + w = align(w, t, Asu2); + t->width = w; + acidtype(t); + ttgen(t); + return; + + default: + diag(Z, "unknown type in suallign: %T", t); + break; + } +} + +long +round(long v, int w) +{ + int r; + + if(w <= 0 || w > 8) { + diag(Z, "rounding by %d", w); + w = 1; + } + r = v%w; + if(r) + v += w-r; + return v; +} + +Type* +ofnproto(Node *n) +{ + Type *tl, *tr, *t; + + if(n == Z) + return T; + switch(n->op) { + case OLIST: + tl = ofnproto(n->left); + tr = ofnproto(n->right); + if(tl == T) + return tr; + tl->down = tr; + return tl; + + case ONAME: + if(n->type == T) + n->type = n->sym->type; + t = typ(TXXX, T); + *t = *n->sym->type; + t->down = T; + return t; + } + return T; +} + +#define ANSIPROTO 1 +#define OLDPROTO 2 + +void +argmark(Node *n, int pass) +{ + Type *t; + + autoffset = align(0, thisfn->link, Aarg0); + for(; n->left != Z; n = n->left) { + if(n->op != OFUNC || n->left->op != ONAME) + continue; + walkparam(n->right, pass); + if(pass != 0 && anyproto(n->right) == OLDPROTO) { + t = typ(TFUNC, n->left->sym->type->link); + t->down = typ(TOLD, T); + t->down->down = ofnproto(n->right); + tmerge(t, n->left->sym); + n->left->sym->type = t; + } + break; + } + autoffset = 0; +} + +void +walkparam(Node *n, int pass) +{ + Sym *s; + Node *n1; + + if(n != Z && n->op == OPROTO && n->left == Z && n->type == types[TVOID]) + return; + +loop: + if(n == Z) + return; + switch(n->op) { + default: + diag(n, "argument not a name/prototype: %O", n->op); + break; + + case OLIST: + walkparam(n->left, pass); + n = n->right; + goto loop; + + case OPROTO: + for(n1 = n; n1 != Z; n1=n1->left) + if(n1->op == ONAME) { + if(pass == 0) { + s = n1->sym; + push1(s); + s->offset = -1; + break; + } + dodecl(pdecl, CPARAM, n->type, n->left, 1); + break; + } + if(n1) + break; + if(pass == 0) { + /* + * extension: + * allow no name in argument declaration + diag(Z, "no name in argument declaration"); + */ + break; + } + dodecl(NODECL, CPARAM, n->type, n->left, 1); + pdecl(CPARAM, lastdcl, S); + break; + + case ODOTDOT: + break; + + case ONAME: + s = n->sym; + if(pass == 0) { + push1(s); + s->offset = -1; + break; + } + if(s->offset != -1) { + autoffset = align(autoffset, s->type, Aarg1); + s->offset = autoffset; + autoffset = align(autoffset, s->type, Aarg2); + } else + dodecl(pdecl, CXXX, types[TINT], n, 1); + break; + } +} + +void +markdcl(void) +{ + Decl *d; + + blockno++; + d = push(); + d->val = DMARK; + d->offset = autoffset; + d->block = autobn; + autobn = blockno; +} + +Node* +revertdcl(void) +{ + Decl *d; + Sym *s; + + for(;;) { + d = dclstack; + if(d == D) { + diag(Z, "pop off dcl stack"); + break; + } + dclstack = d->link; + s = d->sym; + switch(d->val) { + case DMARK: + autoffset = d->offset; + autobn = d->block; + free(d); + return Z; + + case DAUTO: + if(0) { + if(s->class == CAUTO) + warn(Z, "auto declared and not used: %s", s->name); + if(s->class == CPARAM) + warn(Z, "param declared and not used: %s", s->name); + } + s->type = d->type; + s->class = d->class; + s->offset = d->offset; + s->block = d->block; + s->lineno = d->lineno; + break; + + case DSUE: + s->suetag = d->type; + s->sueblock = d->block; + s->lineno = d->lineno; + break; + + case DLABEL: + if(0 && s->label) + warn(s->label, "label declared and not used \"%s\"", s->name); + s->label = Z; + s->lineno = d->lineno; + break; + } + free(d); + } + return Z; +} + +Type* +fnproto(Node *n) +{ + int r; + + r = anyproto(n->right); + if(r == 0 || (r & OLDPROTO)) { + if(r & ANSIPROTO) + diag(n, "mixed ansi/old function declaration: %F", n->left); + return T; + } + return fnproto1(n->right); +} + +int +anyproto(Node *n) +{ + int r; + + r = 0; + +loop: + if(n == Z) + return r; + switch(n->op) { + case OLIST: + r |= anyproto(n->left); + n = n->right; + goto loop; + + case ODOTDOT: + case OPROTO: + return r | ANSIPROTO; + } + return r | OLDPROTO; +} + +Type* +fnproto1(Node *n) +{ + Type *t; + + if(n == Z) + return T; + switch(n->op) { + case OLIST: + t = fnproto1(n->left); + if(t != T) + t->down = fnproto1(n->right); + return t; + + case OPROTO: + lastdcl = T; + n = dodecl(NODECL, CXXX, n->type, n->left, 1); + t = typ(TXXX, T); + if(lastdcl != T) + *t = *paramconv(lastdcl, 1); + if(n != Z && n->op == ONAME) + t->sym = n->sym; + return t; + + case ONAME: + diag(n, "incomplete argument prototype"); + return typ(TINT, T); + + case ODOTDOT: + return typ(TDOT, T); + } + diag(n, "unknown op in fnproto"); + return T; +} + +void +dbgdecl(Sym *s) +{ + + print("decl \"%s\": C=%s [B=%d:O=%ld] T=%T\n", + s->name, cnames[s->class], s->block, s->offset, s->type); +} + +Decl* +push(void) +{ + static Decl zdecl; + Decl *d; + + d = alloc(sizeof(*d)); + *d = zdecl; + d->link = dclstack; + dclstack = d; + return d; +} + +Decl* +push1(Sym *s) +{ + Decl *d; + + d = push(); + d->sym = s; + d->val = DAUTO; + d->type = s->type; + d->class = s->class; + d->offset = s->offset; + d->block = s->block; + d->lineno = s->lineno; + return d; +} + +int +sametype(Type *t1, Type *t2) +{ + + if(t1 == t2) + return 1; + return rsametype(t1, t2, 5, 1); +} + +int +rsametype(Type *t1, Type *t2, int n, int f) +{ + int et; + + n--; + for(;;) { + if(t1 == t2) + return 1; + if(t1 == T || t2 == T) + return 0; + if(n <= 0) + return 1; + et = t1->etype; + if(et != t2->etype) + return 0; + if(et == TFUNC) { + if(!rsametype(t1->link, t2->link, n, 0)) + return 0; + t1 = t1->down; + t2 = t2->down; + while(t1 != T && t2 != T) { + if(t1->etype == TOLD) { + t1 = t1->down; + continue; + } + if(t2->etype == TOLD) { + t2 = t2->down; + continue; + } + while(t1 != T || t2 != T) { + if(!rsametype(t1, t2, n, 0)) + return 0; + t1 = t1->down; + t2 = t2->down; + } + break; + } + return 1; + } + if(et == TARRAY) + if(t1->width != t2->width && t1->width != 0 && t2->width != 0) + return 0; + if(typesu[et] || et == TTUPLE) { + if(t1->link == T) + snap(t1); + if(t2->link == T) + snap(t2); + t1 = t1->link; + t2 = t2->link; + for(;;) { + if(t1 == t2) + return 1; + if(!rsametype(t1, t2, n, 0)) + return 0; + t1 = t1->down; + t2 = t2->down; + } + } + t1 = t1->link; + t2 = t2->link; + if((f || 1) && et == TIND) { + if(t1 != T && t1->etype == TVOID) + return 1; + if(t2 != T && t2->etype == TVOID) + return 1; + } + } + return 0; +} + +ulong +signature(Type *t, int n) +{ + Type *t1; + long s; + + s = 0; + if(n > 0) + for(; t; t=t->link) { + s = s*thash1 + thash[t->etype]; + switch(t->etype) { + default: + return s; + case TARRAY: + s = s*thash2 + t->width; + break; + case TFUNC: + case TSTRUCT: + case TUNION: + for(t1=t; t1; t1=t1->down) + s = s*thash3 + signature(t1, n-1); + case TIND: + break; + } + } + return s; +} + +void +snap(Type *t) +{ + if(typesu[t->etype]) + if(t->link == T && t->tag && t->tag->suetag) { + t->link = t->tag->suetag->link; + t->width = t->tag->suetag->width; + } +} + +Type* +dotag(Sym *s, int et, int bn) +{ + Decl *d; + + if(bn != 0 && bn != s->sueblock) { + d = push(); + d->sym = s; + d->val = DSUE; + d->type = s->suetag; + d->block = s->sueblock; + d->lineno = s->lineno; + s->suetag = T; + } + if(s->suetag == T) { + s->suetag = typ(et, T); + s->sueblock = autobn; + } + if(s->suetag->etype != et) + diag(Z, "tag used for more than one type: %s", + s->name); + if(s->suetag->tag == S) + s->suetag->tag = s; + return s->suetag; +} + +Node* +dcllabel(Sym *s, int f) +{ + Decl *d, d1; + Node *n; + + n = s->label; + if(n != Z) { + if(f) { + if(0) + diag(Z, "label reused: %s", s->name); + } + return n; + } + + d = push(); + d->sym = s; + d->val = DLABEL; + d->lineno = s->lineno; + dclstack = d->link; + + d1 = *firstdcl; + *firstdcl = *d; + *d = d1; + + firstdcl->link = d; + firstdcl = d; + + n = new(OXXX, Z, Z); + n->sym = s; + s->label = n; + return n; +} + +Type* +paramconv(Type *t, int f) +{ + f = 1; + switch(t->etype) { + case TUNION: + case TSTRUCT: + if(t->width <= 0) + diag(Z, "incomplete structure: %s", t->tag->name); + break; + + case TARRAY: + t = typ(TIND, t->link); + t->width = types[TIND]->width; + break; + + case TFUNC: + t = typ(TIND, t); + t->width = types[TIND]->width; + break; + + case TFLOAT: + if(!f) + t = types[TDOUBLE]; + break; + + case TCHAR: + case TSHORT: + if(!f) + t = types[TINT]; + break; + + case TUCHAR: + case TUSHORT: + if(!f) + t = types[TUINT]; + break; + } + return t; +} + +void +adecl(int c, Type *t, Sym *s) +{ + + if(c == CSTATIC) + c = CLOCAL; + if(t->etype == TFUNC) { + if(c == CXXX) + c = CEXTERN; + if(c == CLOCAL) + c = CSTATIC; + if(c == CAUTO || c == CEXREG) + diag(Z, "function cannot be %s %s", cnames[c], s->name); + } + if(c == CXXX) + c = CAUTO; + if(s) { + if(s->class == CSTATIC) + if(c == CEXTERN || c == CGLOBL) { + warn(Z, "just say static: %s", s->name); + c = CSTATIC; + } + if(s->class == CAUTO || s->class == CPARAM || s->class == CLOCAL) + if(s->block == autobn) + diag(Z, "auto redeclaration of: %s", s->name); + if(c != CPARAM) + push1(s); + s->block = autobn; + s->offset = 0; + s->type = t; + s->class = c; + } + switch(c) { + case CAUTO: + autoffset = align(autoffset, t, Aaut3); + s->offset = -autoffset; + break; + + case CPARAM: + autoffset = align(autoffset, t, Aarg1); + if(s) + s->offset = autoffset; + autoffset = align(autoffset, t, Aarg2); + break; + } + if(s) + s->lineno = lineno; +} + +void +pdecl(int c, Type *t, Sym *s) +{ + if(s && s->offset != -1) { + diag(Z, "not a parameter: %s", s->name); + return; + } + t = paramconv(t, c==CPARAM); + if(c == CXXX) + c = CPARAM; + if(c != CPARAM) { + diag(Z, "parameter cannot have class: %s", s->name); + c = CPARAM; + } + adecl(c, t, s); + if(s) + s->lineno = lineno; +} + +void +xdecl(int c, Type *t, Sym *s) +{ + long o; + + o = 0; + if(c == CEXREG) + c = CEXTERN; + if(c == CXXX) { + c = CGLOBL; + if(s->class == CEXTERN) + s->class = c; + } + if(c == CEXTERN) + if(s->class == CGLOBL) + c = CGLOBL; + if(c == CAUTO) { + diag(Z, "overspecified class: %s %s %s", s->name, cnames[c], cnames[s->class]); + c = CEXTERN; + } + if(s->class == CSTATIC) + if(c == CEXTERN || c == CGLOBL) { + warn(Z, "overspecified class: %s %s %s", s->name, cnames[c], cnames[s->class]); + c = CSTATIC; + } + if(s->type != T) + if(s->class != c || !sametype(t, s->type) || t->etype == TENUM) { + diag(Z, "external redeclaration of: %s", s->name); + print(" %s %T; %s %T\n", cnames[c], t, cnames[s->class], s->type); + } + tmerge(t, s); + s->type = t; + s->class = c; + s->block = 0; + s->offset = o; +} + +void +tmerge(Type *t1, Sym *s) +{ + Type *ta, *tb, *t2; + + t2 = s->type; +/*print("merge %T; %T\n", t1, t2);/**/ + for(;;) { + if(t1 == T || t2 == T || t1 == t2) + break; + if(t1->etype != t2->etype) + break; + switch(t1->etype) { + case TFUNC: + ta = t1->down; + tb = t2->down; + if(ta == T) { + t1->down = tb; + break; + } + if(tb == T) + break; + while(ta != T && tb != T) { + if(ta == tb) + break; + /* ignore old-style flag */ + if(ta->etype == TOLD) { + ta = ta->down; + continue; + } + if(tb->etype == TOLD) { + tb = tb->down; + continue; + } + /* checking terminated by ... */ + if(ta->etype == TDOT && tb->etype == TDOT) { + ta = T; + tb = T; + break; + } + if(!sametype(ta, tb)) + break; + ta = ta->down; + tb = tb->down; + } + if(ta != tb) + diag(Z, "function inconsistently declared: %s", s->name); + + /* take new-style over old-style */ + ta = t1->down; + tb = t2->down; + if(ta != T && ta->etype == TOLD) + if(tb != T && tb->etype != TOLD) + t1->down = tb; + break; + + case TARRAY: + /* should we check array size change? */ + if(t2->width > t1->width) + t1->width = t2->width; + break; + + case TUNION: + case TSTRUCT: + return; + } + t1 = t1->link; + t2 = t2->link; + } +} + +void +edecl(int c, Type *t, Sym *s) +{ + long l; + Type *t1; + + if(s == S) { + if(!typesu[t->etype]) + diag(Z, "unnamed structure element must be struct/union"); + if(c != CXXX) + diag(Z, "unnamed structure element cannot have class"); + } else + if(c != CXXX) + diag(Z, "structure element cannot have class: %s", s->name); + t1 = t; + t = typ(TXXX, T); + l = t->lineno; + *t = *t1; + t->lineno = l; + t->sym = s; + t->down = T; + if(lastfield) { + t->shift = lastbit - lastfield; + t->nbits = lastfield; + if(firstbit) + t->shift = -t->shift; + if(typeu[t->etype]) + t->etype = tufield->etype; + else + t->etype = tfield->etype; + } + if(strf == T) + strf = t; + else + strl->down = t; + strl = t; +} + +/* + * this routine is very suspect. + * ansi requires the enum type to + * be represented as an 'int' + * this means that 0x81234567 + * would be illegal. this routine + * makes signed and unsigned go + * to unsigned. + */ +Type* +maxtype(Type *t1, Type *t2) +{ + + if(t1 == T) + return t2; + if(t2 == T) + return t1; + if(t1->etype > t2->etype) + return t1; + return t2; +} + +void +doenum(Sym *s, Node *n) +{ + int k = KDEC; + Node *nc; + + nc = Z; + if(n) { + k = n->kind; + complex(n); + if(n->op != OCONST && n->op != OSTRING && n->op != OLSTRING) { + diag(n, "enum not a constant: %s", s->name); + return; + } + nc = n->left; + en.cenum = n->type; + en.tenum = maxtype(en.cenum, en.tenum); + + if(!typefd[en.cenum->etype]) + en.lastenum = n->vconst; + else + en.floatenum = n->fconst; + } + if(dclstack) + push1(s); + xdecl(CXXX, types[TENUM], s); + + if(en.cenum == T) { + en.tenum = types[TINT]; + en.cenum = types[TINT]; + en.lastenum = 0; + } + s->tenum = en.cenum; + + if(s->tenum->etype == TIND){ /* string */ + nc = n; + s->tenum = n->type; + } + else if(!typefd[s->tenum->etype]) { + s->vconst = convvtox(en.lastenum, s->tenum->etype); + en.lastenum++; + s->tenum = types[TINT]; + } else { + s->fconst = en.floatenum; + if(n) + s->cstring = n->cstring; + else + s->cstring = nil; + en.floatenum++; + s->tenum = types[TDOUBLE]; + } + s->nconst = nc; + + acidvar(s); + s->kind = k; + etgen(s); +} + +void +symadjust(Sym *s, Node *n, long del) +{ + + switch(n->op) { + default: + if(n->left) + symadjust(s, n->left, del); + if(n->right) + symadjust(s, n->right, del); + return; + + case ONAME: + return; + + case OCONST: + case OSTRING: + case OLSTRING: + case OINDREG: + case OREGISTER: + return; + } +} |
