📄 dcl.c
字号:
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);}intanyproto(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; dodecl(NODECL, CXXX, n->type, n->left); t = typ(TXXX, T); if(lastdcl != T) *t = *paramconv(lastdcl, 1); 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;}voiddbgdecl(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){ Decl *d; d = alloc(sizeof(*d)); 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->varlineno = s->varlineno; d->aused = s->aused; return d;}intsametype(Type *t1, Type *t2){ if(t1 == t2) return 1; return rsametype(t1, t2, 5, 1);}intrsametype(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]) { 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 || !debug['V']) && et == TIND) { if(t1 != T && t1->etype == TVOID) return 1; if(t2 != T && t2->etype == TVOID) return 1; } }}typedef struct Typetab Typetab;struct Typetab{ int n; Type **a;};static intsigind(Type *t, Typetab *tt){ int n; Type **a, **na, **p, **e; n = tt->n; a = tt->a; e = a+n; /* linear search seems ok */ for(p = a ; p < e; p++) if(sametype(*p, t)) return p-a; if((n&15) == 0){ na = malloc((n+16)*sizeof(Type*)); memmove(na, a, n*sizeof(Type*)); free(a); a = tt->a = na; } a[tt->n++] = t; return -1;}static ulongsignat(Type *t, Typetab *tt){ int i; Type *t1; long s; s = 0; for(; t; t=t->link) { s = s*thash1 + thash[t->etype]; if(t->garb&GINCOMPLETE) return s; switch(t->etype) { default: return s; case TARRAY: s = s*thash2 + 0; /* was t->width */ break; case TFUNC: for(t1=t->down; t1; t1=t1->down) s = s*thash3 + signat(t1, tt); break; case TSTRUCT: case TUNION: if((i = sigind(t, tt)) >= 0){ s = s*thash2 + i; return s; } for(t1=t->link; t1; t1=t1->down) s = s*thash3 + signat(t1, tt); return s; case TIND: break; } } return s;}ulongsignature(Type *t){ ulong s; Typetab tt; tt.n = 0; tt.a = nil; s = signat(t, &tt); free(tt.a); return s;}ulongsign(Sym *s){ ulong v; Type *t; if(s->sig == SIGINTERN) return SIGNINTERN; if((t = s->type) == T) return 0; v = signature(t); if(v == 0) v = SIGNINTERN; return v;}voidsnap(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; 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(n->complex) diag(Z, "label reused: %s", s->name); n->complex = 1; // declared } else n->addable = 1; // used return n; } d = push(); d->sym = s; d->val = DLABEL; dclstack = d->link; d1 = *firstdcl; *firstdcl = *d; *d = d1; firstdcl->link = d; firstdcl = d; n = new(OXXX, Z, Z); n->sym = s; n->complex = f; n->addable = !f; s->label = n; if(debug['d']) dbgdecl(s); return n;}Type*paramconv(Type *t, int f){ 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;}voidadecl(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; s->aused = 0; } switch(c) { case CAUTO: autoffset = align(autoffset, t, Aaut3); stkoff = maxround(stkoff, autoffset); s->offset = -autoffset; break; case CPARAM: if(autoffset == 0) { firstarg = s; firstargtype = t; } autoffset = align(autoffset, t, Aarg1); if(s) s->offset = autoffset; autoffset = align(autoffset, t, Aarg2); break; }}voidpdecl(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);}voidxdecl(int c, Type *t, Sym *s){ long o; o = 0; switch(c) { case CEXREG: o = exreg(t); if(o == 0) c = CEXTERN; if(s->class == CGLOBL) c = CGLOBL; break; case CEXTERN: if(s->class == CGLOBL) c = CGLOBL; break; case CXXX: c = CGLOBL; if(s->class == CEXTERN) s->class = CGLOBL; break; case CAUTO: diag(Z, "overspecified class: %s %s %s", s->name, cnames[c], cnames[s->class]); c = CEXTERN; break; case CTYPESTR: if(!typesuv[t->etype]) { diag(Z, "typestr must be struct/union: %s", s->name); break; } dclfunct(t, s); break; } 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); Bprint(&diagbuf, " %s %T %L\n", cnames[c], t, nearln); Bprint(&diagbuf, " %s %T %L\n", cnames[s->class], s->type, s->varlineno); } tmerge(t, s); s->type = t; s->class = c; s->block = 0; s->offset = o;}voidtmerge(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; }}voidedecl(int c, Type *t, Sym *s){ 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 = copytyp(t1); 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;}voiddoenum(Sym *s, Node *n){ if(n) { complex(n); if(n->op != OCONST) { diag(n, "enum not a constant: %s", s->name); return; } 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(!typefd[s->tenum->etype]) { s->vconst = convvtox(en.lastenum, s->tenum->etype); en.lastenum++; } else { s->fconst = en.floatenum; en.floatenum++; } if(debug['d']) dbgdecl(s); acidvar(s);}voidsymadjust(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: if(n->sym == s) n->xoffset -= del; return; case OCONST: case OSTRING: case OLSTRING: case OINDREG: case OREGISTER: return; }}Node*contig(Sym *s, Node *n, long v){ Node *p, *r, *q, *m; long w; Type *zt; if(debug['i']) { print("contig v = %ld; s = %s\n", v, s->name); prtree(n, "doinit value"); } if(n == Z) goto no; w = s->type->width; /* * nightmare: an automatic array whose size * increases when it is initialized */ if(v != w) { if(v != 0) diag(n, "automatic adjustable array: %s", s->name); v = s->offset; autoffset = align(autoffset, s->type, Aaut3); s->offset = -autoffset; stkoff = maxround(stkoff, autoffset); symadjust(s, n, v - s->offset); } if(w <= ewidth[TIND]) goto no; if(n->op == OAS) diag(Z, "oops in contig");/*ZZZ this appears incorrectneed to check if the list completely covers the data.if not, bail */ if(n->op == OLIST) goto no; if(n->op == OASI) if(n->left->type) if(n->left->type->width == w) goto no; while(w & (ewidth[TIND]-1)) w++;/* * insert the following code, where long becomes vlong if pointers are fat * *(long**)&X = (long*)((char*)X + sizeof(X)); do { *(long**)&X -= 1; **(long**)&X = 0; } while(*(long**)&X); */ for(q=n; q->op != ONAME; q=q->left) ; zt = ewidth[TIND] > ewidth[TLONG]? types[TVLONG]: types[TLONG]; p = new(ONAME, Z, Z); *p = *q; p->type = typ(TIND, zt); p->xoffset = s->offset; r = new(ONAME, Z, Z); *r = *p; r = new(OPOSTDEC, r, Z); q = new(ONAME, Z, Z); *q = *p; q = new(OIND, q, Z); m = new(OCONST, Z, Z); m->vconst = 0; m->type = zt; q = new(OAS, q, m); r = new(OLIST, r, q); q = new(ONAME, Z, Z); *q = *p; r = new(ODWHILE, q, r); q = new(ONAME, Z, Z); *q = *p; q->type = q->type->link; q->xoffset += w; q = new(OADDR, q, 0); q = new(OASI, p, q); r = new(OLIST, q, r); n = new(OLIST, r, n);no: return n;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -