📄 norm.c
字号:
/* @(#) norm.c 1.3 1/27/86 17:49:14 */ /*ident "@(#)cfront:src/norm.c 1.3" *//************************************************************************ C++ source for cfront, the C++ compiler front-end written in the computer science research center of Bell Labs Copyright (c) 1984 AT&T, Inc. All Rights Reserved THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.norm.c: "normalization" handles problems which could have been handled by the syntax analyser; but has not been done. The idea is to simplify the grammar and the actions accociated with it, and to get a more robust error handling****************************************************************************/#include "cfront.h"#include "size.h"extern void syn_init();void syn_init(){ any_type = new basetype(ANY,0); PERM(any_type); dummy = new expr(DUMMY,0,0); PERM(dummy); dummy->tp = any_type; zero = new expr(ZERO,0,0); PERM(zero);}int stcount;char* make_name(TOK c){ char* s = new char[8]; /* as it happens: fits in two words */ if (99999 <= ++stcount) error('i',"too many generated names"); s[0] = '_'; s[1] = c; int count = stcount; int i = 2; if (10000 <= count) { s[i++] = '0' + count/10000; count %= 10000; } if (1000 <= count) { s[i++] = '0' + count/1000; count %= 1000; } else if (2<i) s[i++] = '0'; if (100 <= count) { s[i++] = '0' + count/100; count %= 100; } else if (2<i) s[i++] = '0'; if (10 <= count) { s[i++] = '0' + count/10; count %= 10; } else if (2<i) s[i++] = '0'; s[i++] = '0' + count; s[i] = 0; return s;}Pbase basetype.type_adj(TOK t){ switch (base) { case COBJ: case EOBJ: { Pbase bt = new basetype(0,0); *bt = *this; DEL(this); this = bt; } } if (b_xname) { if (base) error("badBT:%n%k",b_xname,t); else { base = TYPE; b_name = b_xname; } b_xname = 0; } switch (t) { case TYPEDEF: b_typedef = 1; break; case INLINE: b_inline = 1; break; case VIRTUAL: b_virtual = 1; break; case CONST: b_const = 1; break; case UNSIGNED: b_unsigned = 1; break; case SHORT: b_short = 1; break; case LONG: b_long = 1; break; case FRIEND: case OVERLOAD: case EXTERN: case STATIC: case AUTO: case REGISTER: if (b_sto) error("badBT:%k%k",b_sto,t); else b_sto = t; break; case VOID: case CHAR: case INT: case FLOAT: case DOUBLE: if (base) error("badBT:%k%k",base,t); else base = t; break; default: error('i',"basetype.type_adj(%k)",t); } return this;}Pbase basetype.name_adj(Pname n){ if (b_xname) { if (base) error("badBT:%n%n",b_xname,n); else { base = TYPE; b_name = b_xname; } b_xname = 0; } b_xname = n; return this;}Pbase basetype.base_adj(Pbase b){ Pname bn = b->b_name; switch (base) { case COBJ: case EOBJ: error("NX after%k%n",base,b_name); return this; } if (base) { if (b_name) error("badBT:%k%n%k%n",base,b_name,b->base,bn); else error("badBT:%k%k%n",base,b->base,bn); } else { base = b->base; b_name = bn; b_table = b->b_table; } return this;}Pbase basetype.check(Pname n)/* "n" is the first name to be declared using "this" check the consistency of "this" and use "b_xname" for "n->string" if possible and needed*/{ b_inline = 0; b_virtual = 0;//fprintf(stderr,"check n: %d %s n_oper %d b: %d %d %s\n",n,(n)?n->string:"",n?n->n_oper:0,this,base,(b_name)?b_name->string:"");fflush(stderr); if (b_xname && (n->tp || n->string)) { if (base) error("badBT:%k%n",base,b_xname); else { base = TYPE; b_name = b_xname; } b_xname = 0; } if (b_xname) { if (n->string) error("twoNs inD:%n%n",b_xname,n); else { n->string = b_xname->string; b_xname->hide(); } b_xname = 0; } if (ccl==0 && n && n->n_oper==TNAME && n->n_qualifier==0 && n->string) { // hide type name Pname nx = ktbl->look(n->string,0); if (nx) nx->hide(); } switch (base) { case 0: base = INT; break; case EOBJ: case COBJ: if (b_name->base == TNAME) error('i',"TN%n inCO %d",b_name,this); } if (b_long || b_short) { TOK sl = (b_short) ? SHORT : LONG; if (b_long && b_short) error("badBT:long short%k%n",base,n); if (base != INT) error("badBT:%k%k%n",sl,base,n); else base = sl; b_short = b_long = 0; } if (b_typedef && b_sto) error("badBT:typedef%k%n",b_sto,n); b_typedef = b_sto = 0; if (Pfctvec_type == 0) return this; if (b_const) { if (b_unsigned) { switch (base) { default: error("badBT: unsigned const %k%n",base,n); b_unsigned = 0; case LONG: case SHORT: case INT: case CHAR: return this; } } return this; } else if (b_unsigned) { switch (base) { case LONG: delete this; return ulong_type; case SHORT: delete this; return ushort_type; case INT: delete this; return uint_type; case CHAR: delete this; return uchar_type; default: error("badBT: unsigned%k%n",base,n); b_unsigned = 0; return this; } } else { switch (base) { case LONG: delete this; return long_type; case SHORT: delete this; return short_type; case INT: if (this != int_type) delete this; return int_type; case CHAR: delete this; return char_type; case VOID: delete this; return void_type; case TYPE: /* use a single base saved in the keyword *///fprintf(stderr,"type %d bn %d %s q %d\n",this,b_name,b_name->string,b_name->n_qualifier); if (b_name->n_qualifier) { delete this; return (Pbase)b_name->n_qualifier; } else { PERM(this); b_name->n_qualifier = (Pname)this; return this; } default: return this; } }}Pname basetype.aggr()/* "type SM" seen e.g. struct s {}; class x; enum e; int tname; friend cname; friend class x; int; convert union { ... }; into union name { ... } name ;*/{ Pname n; if (b_xname) { if (base) { Pname n = new name(b_xname->string); b_xname->hide(); b_xname = 0; return n->normalize(this,0,0); } else { base = TYPE; b_name = b_xname; b_xname = 0; } } switch (base) { case COBJ: { Pclass cl = (Pclass)b_name->tp; char* s = cl->string;/*fprintf(stderr,"COBJ (%d %s) -> (%d %d) ->(%d %d)\n",this,b_name->string,b_name,b_name->base,cl,cl->base);*/ if (b_name->base == TNAME) error('i',"TN%n inCO",b_name); if (b_const) error("const%k%n",cl->csu,b_name); if (cl->c_body == 2) { /* body seen */ if (s[0]=='_' && s[1]=='C') { char* ss = new char[5]; Pname obj = new name(ss); if (cl->csu == UNION) { strcpy(ss,s); ss[1] = 'O'; cl->csu = ANON; return obj->normalize(this,0,0); } error('w',"un-usable%k ignored",cl->csu); } cl->c_body = 1; return b_name; } else { /* really a typedef for cfront only: class x; */ if (b_sto == FRIEND) goto frr; return 0; } } case EOBJ: { Penum en = (Penum)b_name->tp;/*fprintf(stderr,"EOBJ (%d %s) -> (%d %d) ->(%d %d)\n",this,b_name->string,b_name,b_name->base,en,en->base);*/ if (b_name->base == TNAME) error('i',"TN%n in enumO",b_name); if (b_const) error("const enum%n",b_name); if (en->e_body == 2) { en->e_body = 1; return b_name; } else { if (b_sto == FRIEND) goto frr; return 0; } } default: if (b_typedef) error('w',"illegal typedef ignored"); if (b_sto == FRIEND) { frr: Pname fr = ktbl->look(b_name->string,0); if (fr == 0) error('i',"cannot find friend%n",b_name); n = new name(b_name->string); n->n_sto = FRIEND; n->tp = fr->tp; return n; } else { n = new name(make_name('D')); n->tp = any_type; error('w',"NX inDL"); return n; } }}void name.hide()/* hide "this": that is, "this" should not be a keyword in this scope*/{//error('d',"hide%n %d %k tp %d",this,this,base,tp); if (base != TNAME) return; if (n_key == 0) {//error('d',"ll %d bl %d base %k",lex_level,bl_level,base); if (lex_level == bl_level) { if (this->base != TNAME) error("%n redefined",this); else { // is it a CN? error('w',"%n redefined",this); } } modified_tn = new name_list(this,modified_tn); n_key = HIDDEN; }}void set_scope(Pname tn)/* enter the scope of class tn after seeing "tn.f"*/{ if (tn->base != TNAME) error('i',"set_scope: not aTN %d %d",tn,tn->base); Pbase b = (Pbase)tn->tp; if (b->b_name->tp->base != CLASS) error('i',"T of%n not aC (%k)",tn,b->b_name->tp->base); Pclass cl = (Pclass)b->b_name->tp; for (Plist l=cl->tn_list; l; l=l->l) { Pname n = l->f; n->n_key = (n->lex_level) ? 0 : HIDDEN;//error('d',"set_scope%n %d",n,n->n_key); modified_tn = new name_list(n,modified_tn); }}void restore(){ for (Plist l=modified_tn; l; l=l->l) { Pname n = l->f; n->n_key = (n->lex_level <= bl_level) ? 0 : HIDDEN;//error('d',"restore%n %d",n,n->n_key); }}Pbase start_cl(TOK t, Pname c, Pname b){ if (c == 0) c = new name(make_name('C'));//error('d',"c: %d %s",c->base,c->string); Pname n = c->tname(t); /* t ignored */ n->where = curloc; Pbase bt = (Pbase)n->tp; /* COBJ */ if (bt->base != COBJ) { error("twoDs of%n:%t andC",n,bt); error('i', "can't recover from previous errors"); } Pclass occl = ccl; ccl = (Pclass)bt->b_name->tp; /* CLASS */ if (ccl->defined) { error("C%n defined twice"); ccl->defined |= IN_ERROR; } ccl->defined |= DEF_SEEN; if (ccl->in_class = occl) occl->tn_list = modified_tn; // save mod-list modified_tn = 0; ccl->string = n->string; ccl->csu = t; if (b) ccl->clbase = b->tname(t); return bt; }void end_cl(){ Pclass occl = ccl->in_class; Plist ol = occl ? occl->tn_list : 0; // saved modified name list ccl->c_body = 2; if (modified_tn) { // export nested class names to outer scope: Plist local = 0; for (Plist l=modified_tn, nl=0; l; l=nl) { nl = l->l; Pname n = l->f; if (ktbl->look(n->string,0)) { // add it to enclosing class's modified name list l->l = ol; ol = l; } else { // retain it in this class's modified name list l->l = local; local = l; } } if (ccl->tn_list = modified_tn = local) restore(); } modified_tn = ol; // restore mod-list (possibly modified) ccl = occl;}Pbase end_enum(Pname n, Pname b){ if (n == 0) n = new name(make_name('E')); n = n->tname(ENUM); Pbase bt = (Pbase)n->tp; if (bt->base != EOBJ) { error("twoDs of%n:%t and enum",n,bt); error('i', "can't recover from previous errors"); } Penum en = (Penum)bt->b_name->tp; en->e_body = 2; en->mem = name_unlist((class nlist *)b); if (en->defined) { error("enum%n defined twice",n); en->defined |= IN_ERROR; } en->defined |= DEF_SEEN; return bt;}Pname name.tdef()/* typedef "this"*/{//error('d',"tdef%n",this); Pname n = ktbl->insert(this,0); if (tp == 0) error('i',"typedef%n tp==0",this); n->base = base = TNAME; PERM(n); PERM(tp); modified_tn = new name_list(n,modified_tn); return n;}Pname name.tname(TOK csu)/* "csu" "this" seen, return typedef'd name for "this" return (TNAME,x) x: (COBJ,y) y: (NAME,z) z: (CLASS,ae);*/{//fprintf(stderr,"tname %s %d ll %d\n",string,this,lex_level); switch (base) { case TNAME: return this; case NAME: { Pname tn = ktbl->insert(this,0);//fprintf(stderr,"tname tn %s %d ll %d (mod %d)\n",tn->string,tn,tn->lex_level,modified_tn); Pname on = new name; tn->base = TNAME; tn->lex_level = lex_level; modified_tn = new name_list(tn,modified_tn); tn->n_list = n_list = 0; string = tn->string; *on = *this; switch (csu) { case ENUM: tn->tp = new basetype(EOBJ,on); on->tp = new enumdef(0); break; default: on->tp = new classdef(csu,0); Pclass(on->tp)->string = tn->string; tn->tp = new basetype(COBJ,on); Pbase(tn->tp)->b_table = Pclass(on->tp)->memtbl; } PERM(tn); PERM(tn->tp); PERM(on);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -