📄 norm.c
字号:
PERM(on->tp);/*fprintf(stderr,"tname %s -> n (%d %d) n->tp (%d %d)\n",string,tn,tn->base,tn->tp,tn->tp->base); fflush(stderr);*/ return tn; } default: error('i',"tname(%s %d %k)",string,this,base); } }Pname name.normalize(Pbase b, Pblock bl, bit cast)/* if (bl) : a function definition (check that it really is a type if (cast) : no name string for each name on the name list invert the declarator list(s) and attatch basetype watch out for class object initializers convert struct s { int a; } a; into struct s { int a; }; struct s a;*/{ Pname n; Pname nn; TOK stc = b->b_sto; bit tpdf = b->b_typedef; bit inli = b->b_inline; bit virt = b->b_virtual; Pfct f; Pname nx; if (b == 0) error('i',"%d->N.normalize(0)",this); if (this == 0) error('i',"0->N.normalize(%k)",base); if (inli && stc==EXTERN) { error("both extern and inline"); inli = 0; }//fprintf(stderr,"name.norm(%d %s) tp (%d %d)\n",this,string,tp,tp->base); if (stc==FRIEND && tp==0) { /* friend x; must be handled during syntax analysis to cope with class x { friend y; y* p; }; "y" is not local to "x": class x { friend y; ... }; y* p; is legal */ if (b->base) error(0,"T specified for friend"); if (n_list) { error("L of friends"); n_list = 0; } Pname nx = tname(CLASS); modified_tn = modified_tn->l; /* global */ n_sto = FRIEND; tp = nx->tp; return this; } if (tp && n_oper==TNAME && tp->base==FCT) { /* HORRIBLE FUDGE: fix the bad grammar */ Pfct f = (Pfct)tp; Pfct f2 = (Pfct)f->returns; if (f2 && f2->base==FCT) { Pexpr e = f2->argtype;//error('d',"%s: mis-analyzedP toF",string); if (e->base == ELIST) { // get the real name, fix its type if (e->e2 || e->e1->base!=DEREF) goto zse1; Pname rn = (Pname)e->e1->e1; if (rn->base!=NAME) goto zse1; f->returns = new ptr(PTR,0); b = new basetype(TYPE,ktbl->look(string,0)); n_oper = 0; string = rn->string; base = NAME;//error('d',"realN %n b==%t",rn,b); } } }zse1: if (cast) string = ""; b = b->check(this); switch (b->base) { // separate class definitions // from object and function type declarations case COBJ: nn = b->b_name;//fprintf(stderr,"COBJ (%d %s) -> (%d %d body=%d)\n",nn,nn->string,nn->tp,nn->tp->base,Pclass(nn->tp)->c_body); if (Pclass(nn->tp)->c_body==2) { /* first occurrence */ if (tp && tp->base==FCT) { error('s',&this->where,"%k%n defined as returnT for%n (did you forget a ';' after '}' ?)",Pclass(nn->tp)->csu,nn,this); nn = this; break; } nn->n_list = this; Pclass(nn->tp)->c_body = 1; /* other occurences */ } else nn = this; break; case EOBJ: nn = b->b_name; if (Penum(nn->tp)->e_body==2) { if (tp && tp->base==FCT) { error('s',"enum%n defined as returnT for%n (did you forget a ';'?)",nn,this); nn = this; break; } nn->n_list = this; Penum(nn->tp)->e_body = 1; } else nn = this; break; default: nn = this; } for (n=this; n; n=nx) { Ptype t = n->tp; nx = n->n_list; n->n_sto = stc;/* if (t && n_oper==TNAME && t->base==FCT) { // HORRIBLE FUDGE: fix the bad grammar Pfct f = (Pfct)t; Pfct f2 = (Pfct)f->returns; if (f2 && f2->base==FCT) { Pexpr e = f2->argtype; if (e->base == ELIST) { // get the real name, fix its type if (e->e2 || e->e1->base!=DEREF) goto zse; Pname rn = (Pname)e->e1->e1; if (rn->base!=NAME) goto zse; f->returns = new ptr(PTR,0); b = new basetype(TYPE,ktbl->look(n->string,0)); n->n_oper = 0; n->string = rn->string; n->base = NAME; } } }zse:*/ if (n->base == TNAME) error('i',"redefinition ofTN%n",n); if (t == 0) { if (bl == 0) n->tp = t = b; else { error("body of nonF%n",n); t = new fct(defa_type,0,0); } } switch (t->base) { case PTR: case RPTR: n->tp = Pptr(t)->normalize(b); break; case VEC: n->tp = Pvec(t)->normalize(b); break; case FCT: n->tp = Pfct(t)->normalize(b); break; case FIELD: if (n->string == 0) n->string = make_name('F'); n->tp = t; Pbase tb = b; flatten://error('d',"flatten %d %d %d",tb->base,b->b_unsigned,b->b_const); switch (tb->base) { case TYPE: /* chase typedefs */ tb = (Pbase)tb->b_name->tp; goto flatten; case INT: Pbase(t)->b_fieldtype = (b->b_unsigned) ? uint_type : int_type; goto iii; case CHAR: Pbase(t)->b_fieldtype = (b->b_unsigned) ? uchar_type : char_type; goto iii; case SHORT: Pbase(t)->b_fieldtype = (b->b_unsigned) ? ushort_type : short_type; goto iii; iii: Pbase(t)->b_unsigned = b->b_unsigned; Pbase(t)->b_const = b->b_const; break; default: error("non-int field"); n->tp = defa_type; } break; } f = (Pfct) n->tp; if (f->base != FCT) { if (bl) { error("body for nonF%n",n); n->tp = f = new fct(defa_type,0,0); continue; } if (inli) error("inline nonF%n",n); if (virt) error("virtual nonF%n",n); if (tpdf) { if (n->n_initializer) { error("Ir for typedefN%n",n); n->n_initializer = 0; } n->tdef(); } continue; } f->f_inline = inli; f->f_virtual = virt; if (tpdf) { if (f->body = bl) error("typedef%n { ... }",n); n->tdef(); continue; } if (f->body = bl) continue; /* Check function declarations. Look for class object instansiations The real ambiguity: ; class x fo(); is interpreted as an extern function declaration NOT a class object with an empty initializer */ { Pname cn = f->returns->is_cl_obj(); bit clob = (cn || cl_obj_vec);//error('d',"%n: fr%t cn%n",n,f->returns,cn); if (f->argtype) { /* check argument/initializer list */ Pname nn; for (nn=f->argtype; nn; nn=nn->n_list) { if (nn->base != NAME) { if (!clob) { error("ATX for%n",n); goto zzz; } goto is_obj; }/* if (nn->string) { error("AN%n inD of%n",nn,n); nn->string = 0; }*/ if (nn->tp) goto ok; } if (!clob) { error("FALX"); goto zzz; } is_obj://fprintf(stderr,"is_obj: %d %s tp = %d %d\n",this,string,f->returns,f->returns->base); fflush(stderr); /* it was an initializer: expand to constructor */ n->tp = f->returns; if (f->argtype->base != ELIST) f->argtype = (Pname)new expr(ELIST,(Pexpr)f->argtype,0); n->n_initializer = new texpr(VALUE,cn->tp,(Pexpr)f->argtype); goto ok; zzz: if (f->argtype) { DEL(f->argtype); f->argtype = 0; f->nargs = 0; f->nargs_known = !fct_void; } } else { /* T a(); => function declaration *//* if (clob) { DEL(n->tp); n->tp = f->returns; }*/ } ok: ; } } return nn;}Ptype vec.normalize(Ptype vecof)/**/{ Ptype t = typ; if (this == 0) error('i',"0->vec.normalize()"); typ = vecof; if (t == 0) return this;xx: switch (t->base) { case TYPE: t = Pbase(t)->b_name->tp; goto xx; case PTR: case RPTR: return Pptr(t)->normalize(this); case VEC: return Pvec(t)->normalize(this); case FCT: return Pfct(t)->normalize(this); default: error('i',"bad vectorT(%d)",t->base); }}Ptype ptr.normalize(Ptype ptrto){ Ptype t = typ; if (this == 0) error('i',"0->ptr.normalize()"); typ = ptrto; if (t == 0) { Pbase b = (Pbase) ptrto; if (Pfctvec_type && rdo==0 && b->b_unsigned==0 && b->b_const==0 && base==PTR) { switch (b->base) { case INT: delete this; return Pint_type; case CHAR: delete this; return Pchar_type; case VOID: delete this; return Pvoid_type; case TYPE: break; } } if (base==RPTR && b->base==VOID) error("void& is not a validT"); return this; }xx: switch (t->base) { case TYPE: t = Pbase(t)->b_name->tp; goto xx; case PTR: case RPTR: return Pptr(t)->normalize(this); case VEC: return Pvec(t)->normalize(this); case FCT: return Pfct(t)->normalize(this); default: error('i',"badPT(%d)",t->base); }}Ptype fct.normalize(Ptype ret)/* normalize return type*/{ register Ptype t = returns; if (this==0 || ret==0) error('i',"%d->fct.normalize(%d)",this,ret); returns = ret; if (t == 0) return this; if (argtype) { if (argtype->base != NAME) { error('i',"syntax: ANX"); argtype = 0; nargs = 0; nargs_known = 0; }/* else { Pname n; for (n=argtype; n; n=n->n_list) { if (n->string) { error("N inATL"); n->string = 0; } } }*/ }xx: switch (t->base) { case PTR: case RPTR: return Pptr(t)->normalize(this); case VEC: return Pvec(t)->normalize(this); case FCT: return Pfct(t)->normalize(this); case TYPE: t = Pbase(t)->b_name->tp; goto xx; default: error('i',"badFT:%k",t->base); }} void fct.argdcl(Pname dcl, Pname fn)/* sort out the argument types for old syntax: f(a,b) int a; char b; { ... } beware of f(a) struct s { int a; }; struct s a;*/{ Pname n;/*fprintf(stderr,"%d argtype %d %d dcl %d %d\n",this, argtype, argtype?argtype->base:0, dcl, dcl?dcl->base:0); fflush(stderr);*/ switch (base) { case FCT: break; case ANY: return; default: error('i',"argdcl(%d)",base); } if (argtype) { switch (argtype->base) { case NAME: if (dcl) error("badF definition syntax"); for (n=argtype; n; n=n->n_list) { if (n->string == 0) n->string = make_name('A'); } return; case ELIST: // expression list: f(a,b,c) int a; ... { ... } // scan the elist and build a NAME list { Pexpr e; Pname nn; Pname tail = 0; n = 0; if (old_fct_accepted == 0) error('w',&fn->where,"old style definition of%n",fn); for (e=Pexpr(argtype); e; e=e->e2) { Pexpr id = e->e1; if (id->base != NAME) { error("NX inAL"); argtype = 0; dcl = 0; break; } nn = new name(id->string); if (n) tail = tail->n_list = nn; else tail = n = nn; } argtype = n; break; } default: error("ALX(%d)",argtype->base); argtype = 0; dcl = 0; } } else { nargs_known = !fct_void; nargs = 0; if (dcl) error("ADL forF withoutAs"); return; } nargs_known = 0; if (dcl) { Pname d; Pname dx; /* for each argument name see if its type is specified in the declaration list otherwise give it the default type */ for (n=argtype; n; n=n->n_list) { char* s = n->string; if (s == 0) { error("AN missing inF definition"); n->string = s = make_name('A'); } else if (n->tp) error("twoTs forA %s",n->string); for (d=dcl; d; d=d->n_list) { if (strcmp(s,d->string) == 0) { if (d->tp->base == VOID) { error("voidA%n",d); d->tp = any_type; } n->tp = d->tp; n->n_sto = d->n_sto; d->tp = 0; /* now merged into argtype */ goto xx; } } n->tp = defa_type; xx:; if (n->tp == 0) error('i',"noT for %s",n->string); } /* now scan the declaration list for "unused declarations" and delete it */ for (d=dcl; d; d=dx) { dx = d->n_list; if (d->tp) { /* not merged with argtype list */ /*if (d->base == TNAME) ??? */ switch (d->tp->base) { case CLASS: case ENUM: /* WARNING: this will reverse the order of class and enum declarations */ d->n_list = argtype; argtype = d; break; default: error("%n inADL not inAL",d); } } } } /* add default argument types if necessary */ for (n=argtype; n; n=n->n_list) { if (n->tp == 0) n->tp = defa_type; nargs++; }}Pname cl_obj_vec; /* set if is_cl_obj() found a vector of class objects */Pname eobj; /* set if is_cl_obj() found an enum */Pname type.is_cl_obj()/* returns this->b_name if this is a class object returns 0 and sets cl_obj_vec to this->b_name if this is a vector of class objects returns 0 and sets eobj to this->b_name if this is an enum object else returns 0*/{ bit v = 0; register Ptype t = this; eobj = 0; cl_obj_vec = 0;xx: switch (t->base) { case TYPE: t = Pbase(t)->b_name->tp; goto xx; case COBJ: if (v) { cl_obj_vec = Pbase(t)->b_name; return 0; } else return Pbase(t)->b_name; case VEC: t = Pvec(t)->typ; v=1; goto xx; case EOBJ: eobj = Pbase(t)->b_name; default: return 0; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -