lcc源代码解析之types.c

来源:互联网 发布:江西豫章书院知乎 编辑:程序博客网 时间:2024/06/13 23:27

最近好TM的忙啊,坑爹教练让每天五点钟起床去练车,平均每天至少有四个设备启动,运行中异常重启的问题报过来,我也是醉了。

今天终于有点时间继续写blog了,废话不多说,代码上。

今天解析lcc中的一个重要模块,类型管理相关,主要代码在types.c中,前面的符号表管理模块中就有对这部分的使用。

首先,依然是相关数据结构的解析,在c.h中

#define fieldsize(p)  (p)->bitsize//位域以位为单位的长度#define fieldright(p) ((p)->lsb - 1)//位域最右边的位号,可用于对位域进行移位,使位域从符号或无符号的最低有效位开始#define fieldleft(p)  (8*(p)->type->size - \                        fieldsize(p) - fieldright(p))//最左边的位号,用于符号位域的符号扩展操作。//掩码,由bitsize个1组成,用于抽取位域清除无用的位            #define fieldmask(p)  (~(fieldsize(p) < 8*unsignedtype->size ? ~0u<<fieldsize(p) : 0u))


/*CHAR LONG INT SHORT UNSIGNED ENUM -->整数类型,同时也是算术类型,除ENUM外,其他无操作数,ENUM操作数为与其兼容的整型FLOAT DOUBLE                      -->浮点类型,同时也是算术类型,无操作数ARRAY STRUCT UNION                -->聚合类型,ARRAY的操作数是数组元素的类型,后两者没有操作数,域存放在结构和联合标记的附加符号表入口中,即f的sym字段POINTER-->指针类型,操作数为引用类型FUNCTION                  -->函数类型,操作数为返回类型 CONST VOLATILE                    -->限定类型,操作数为类型的未限定形式VOID                              -->空类型,无操作数*/struct type {int op;  //类型操作符编码Type type;//类型的操作数int align;//对齐字节数int size;//此类型对象的大小,align的整数倍union {Symbol sym;//符号表入口,对于带名字和标记的未限定类型,sym中有更多附加信息//函数类型使用struct {unsigned oldstyle:1;//老风格的函数参数格式Type *proto;//向量,proto[i]表示第i + 1个参数的类型} f;} u;Xtype x;};struct field {char *name;//域的名字Type type;  //域的类型int offset; //该域在结构实例中的偏移量short bitsize;//以位为单位的长度short lsb;//等于位域中最低有效位的位号加1,最低有效位的位号从0开始Field link;};

代码部分,types.c

#include "c.h"#include <float.h>static char rcsid[] = "$Id: types.c,v 1.1 2002/08/28 23:12:47 drh Exp $";static Field isfield(const char *, Field);static Type type(int, Type, int, int, void *);static struct entry {struct type type;struct entry *link;} *typetable[128];static int maxlevel;static Symbol pointersym;Type chartype;/* char */Type doubletype;/* double */Type floattype;/* float */Type inttype;/* signed int */Type longdouble;/* long double */Type longtype;/* long */Type longlong;/* long long */Type shorttype;/* signed short int */Type signedchar;/* signed char */Type unsignedchar;/* unsigned char */Type unsignedlong;/* unsigned long int */Type unsignedlonglong;/* unsigned long long int */Type unsignedshort;/* unsigned short int */Type unsignedtype;/* unsigned int */Type funcptype;/* void (*)() */Type charptype;/* char* */Type voidptype;/* void* */Type voidtype;/* basic types: void */Type unsignedptr;/* unsigned type to hold void* */Type signedptr;/* signed type to hold void* */Type widechar;/* unsigned type that represents wchar_t */static Type xxinit(int op, char *name, Metrics m) {Symbol p = install(string(name), &types, GLOBAL, PERM);//在types符号表里新建一个符号Type ty = type(op, 0, m.size, m.align, p);assert(ty->align == 0 || ty->size%ty->align == 0);p->type = ty;p->addressed = m.outofline;switch (ty->op) {case INT:p->u.limits.max.i = ones(8*ty->size)>>1;p->u.limits.min.i = -p->u.limits.max.i - 1;break;case UNSIGNED:p->u.limits.max.u = ones(8*ty->size);p->u.limits.min.u = 0;break;case FLOAT:if (ty->size == sizeof (float))p->u.limits.max.d =  FLT_MAX;else if (ty->size == sizeof (double))p->u.limits.max.d =  DBL_MAX;elsep->u.limits.max.d = LDBL_MAX;p->u.limits.min.d = -p->u.limits.max.d;break;default: assert(0);}return ty;}/*在typetable中搜索指定类型或创建一个新的类型*/static Type type(int op, Type ty, int size, int align, void *sym) {//计算hash值unsigned h = (op^((unsigned long)ty>>3))&(NELEMS(typetable)-1);struct entry *tn;if (op != FUNCTION && (op != ARRAY || size > 0))//函数类型和不完全数组创建类型for (tn = typetable[h]; tn; tn = tn->link)//遍历hash链表,查看是否已经存在if (tn->type.op    == op   && tn->type.type  == ty&&  tn->type.size  == size && tn->type.align == align&&  tn->type.u.sym == sym)return &tn->type;//新建类型,赋值NEW0(tn, PERM);tn->type.op = op;tn->type.type = ty;tn->type.size = size;tn->type.align = align;tn->type.u.sym = sym;//加入typetabletn->link = typetable[h];typetable[h] = tn;return &tn->type;}//初始化固有类型void type_init(int argc, char *argv[]) {static int inited;int i;if (inited)return;inited = 1;if (!IR)return;for (i = 1; i < argc; i++) {int size, align, outofline;if (strncmp(argv[i], "-unsigned_char=", 15) == 0)IR->unsigned_char = argv[i][15] - '0';#define xx(name) \else if (sscanf(argv[i], "-" #name "=%d,%d,%d", &size, &align, &outofline) == 3) { \IR->name.size = size; IR->name.align = align; \IR->name.outofline = outofline; }//else if(sscanf(-charmetric = size, align, outofline))xx(charmetric)xx(shortmetric)xx(intmetric)xx(longmetric)xx(longlongmetric)xx(floatmetric)xx(doublemetric)xx(longdoublemetric)xx(ptrmetric)xx(structmetric)#undef xx}#define xx(v,name,op,metrics) v=xxinit(op,name,IR->metrics)//chartype = xxinit(UNSIGNED, "char", charmetric)xx(chartype,        "char",              IR->unsigned_char ? UNSIGNED : INT,charmetric);xx(doubletype,      "double",            FLOAT,   doublemetric);xx(floattype,       "float",             FLOAT,   floatmetric);xx(inttype,         "int",               INT,     intmetric);xx(longdouble,      "long double",       FLOAT,   longdoublemetric);xx(longtype,        "long int",          INT,     longmetric);xx(longlong,        "long long int",     INT,     longlongmetric);xx(shorttype,       "short",             INT,     shortmetric);xx(signedchar,      "signed char",       INT,     charmetric);xx(unsignedchar,    "unsigned char",     UNSIGNED,charmetric);xx(unsignedlong,    "unsigned long",     UNSIGNED,longmetric);xx(unsignedshort,   "unsigned short",    UNSIGNED,shortmetric);xx(unsignedtype,    "unsigned int",      UNSIGNED,intmetric);xx(unsignedlonglong,"unsigned long long",UNSIGNED,longlongmetric);#undef xx//void 没有metric,单独处理{Symbol p;p = install(string("void"), &types, GLOBAL, PERM);voidtype = type(VOID, NULL, 0, 0, p);p->type = voidtype;}//指针类型pointersym = install(string("T*"), &types, GLOBAL, PERM);pointersym->addressed = IR->ptrmetric.outofline;pointersym->u.limits.max.p = (void*)ones(8*IR->ptrmetric.size);pointersym->u.limits.min.p = 0;voidptype = ptr(voidtype);funcptype = ptr(func(voidtype, NULL, 1));charptype = ptr(chartype);#define xx(v,t) if (v==NULL && t->size==voidptype->size && t->align==voidptype->align) v=txx(unsignedptr,unsignedshort);xx(unsignedptr,unsignedtype);xx(unsignedptr,unsignedlong);xx(unsignedptr,unsignedlonglong);if (unsignedptr == NULL)unsignedptr = type(UNSIGNED, NULL, voidptype->size, voidptype->align, voidptype->u.sym);xx(signedptr,shorttype);xx(signedptr,inttype);xx(signedptr,longtype);xx(signedptr,longlong);if (signedptr == NULL)signedptr = type(INT, NULL, voidptype->size, voidptype->align, voidptype->u.sym);#undef xxwidechar = unsignedshort;for (i = 0; i < argc; i++) {#define xx(name,type) \if (strcmp(argv[i], "-wchar_t=" #name) == 0) \widechar = type;xx(unsigned_char,unsignedchar)xx(unsigned_int,unsignedtype)xx(unsigned_short,unsignedshort)}#undef xx}//删除某个作用域的类型void rmtypes(int lev) {if (maxlevel >= lev) {int i;maxlevel = 0;for (i = 0; i < NELEMS(typetable); i++) {struct entry *tn, **tq = &typetable[i];while ((tn = *tq) != NULL)if (tn->type.op == FUNCTION)tq = &tn->link;else if (tn->type.u.sym && tn->type.u.sym->scope >= lev)*tq = tn->link;else {if (tn->type.u.sym && tn->type.u.sym->scope > maxlevel)maxlevel = tn->type.u.sym->scope;tq = &tn->link;}}}}//构造指针类型Type ptr(Type ty) {return type(POINTER, ty, IR->ptrmetric.size,IR->ptrmetric.align, pointersym);}//Type deref(Type ty) {if (isptr(ty))ty = ty->type;elseerror("type error: %s\n", "pointer expected");//间接访问枚举指针单独处理,必须返回与它关联的未限定整数类型return isenum(ty) ? unqual(ty)->type : ty;}//构造数组类型ty,Type array(Type ty, int n, int a) {assert(ty);if (isfunc(ty)) {error("illegal type `array of %t'\n", ty);return array(inttype, n, 0);}if (isarray(ty) && ty->size == 0)error("missing array size\n");if (ty->size == 0) {if (unqual(ty) == voidtype)error("illegal type `array of %t'\n", ty);else if (Aflag >= 2)//-A选项warning("declaring type array of %t' is undefined\n", ty);} else if (n > INT_MAX/ty->size) {error("size of `array of %t' exceeds %d bytes\n",ty, INT_MAX);n = 1;}return type(ARRAY, ty, n*ty->size,a ? a : ty->align, NULL);}//数组转指针Type atop(Type ty) {if (isarray(ty))return ptr(ty->type);error("type error: %s\n", "array expected");return ptr(ty);}//构造限定类型,CONST/VOLATILE/CONST+VOLATILEType qual(int op, Type ty) {if (isarray(ty))ty = type(ARRAY, qual(op, ty->type), ty->size,ty->align, NULL);else if (isfunc(ty))warning("qualified function type ignored\n");else if (isconst(ty)    && op == CONST||       isvolatile(ty) && op == VOLATILE)error("illegal type `%k %t'\n", op, ty);else {if (isqual(ty)) {op += ty->op;ty = ty->type;}ty = type(op, ty, ty->size, ty->align, NULL);}return ty;}//创建函数类型Type func(Type ty, Type *proto, int style) {if (ty && (isarray(ty) || isfunc(ty)))error("illegal return type `%t'\n", ty);ty = type(FUNCTION, ty, 0, 0, NULL);ty->u.f.proto = proto;//参数列表向量ty->u.f.oldstyle = style;//函数声明是新老风格return ty;}Type freturn(Type ty) {if (isfunc(ty))return ty->type;error("type error: %s\n", "function expected");return inttype;}//函数是否带可变数目参数int variadic(Type ty) {if (isfunc(ty) && ty->u.f.proto) {int i;for (i = 0; ty->u.f.proto[i]; i++);//找到参数列表的末尾//参数个数大于1,且最后一个参数为void类型,函数为参数数目可变return i > 1 && ty->u.f.proto[i-1] == voidtype;}return 0;}//创建新的结构或者联合,tag是标记,也可以创建枚举Type newstruct(int op, char *tag) {Symbol p;assert(tag);//没有tag,生成tagif (*tag == 0)tag = stringd(genlabel(1));elseif ((p = lookup(tag, types)) != NULL && (p->scope == level|| p->scope == PARAM && level == PARAM+1)) {if (p->type->op == op && !p->defined)//找到一个声明但是未定义return p->type;//重复定义报错error("redefinition of `%s' previously defined at %w\n",p->name, &p->src);}//将tag装入符号表typesp = install(tag, &types, level, PERM);p->type = type(op, NULL, 0, 0, p);if (p->scope > maxlevel)maxlevel = p->scope;p->src = src;return p->type;}//分配一个field结构,并将该filed附加到结构类型ty的符号表入口的域列表中//从而在ty中加入一个类型为fty的域Field newfield(char *name, Type ty, Type fty) {Field p, *q = &ty->u.sym->u.s.flist;//filed链表的表头//名字为空,则生成一个名字if (name == NULL)name = stringd(genlabel(1));for (p = *q; p; q = &p->link, p = *q)if (p->name == name)error("duplicate field name `%s' in `%t'\n",name, ty);NEW0(p, PERM);*q = p;p->name = name;p->type = fty;if (xref) {/* omit */if (ty->u.sym->u.s.ftab == NULL)/* omit */ty->u.sym->u.s.ftab = table(NULL, level);/* omit */install(name, &ty->u.sym->u.s.ftab, 0, PERM)->src = src;/* omit */}/* omit */return p;}//判断两个类型是否兼容int eqtype(Type ty1, Type ty2, int ret) {if (ty1 == ty2)return 1;if (ty1->op != ty2->op)//不同的操作符,绝对不兼容return 0;//所以这个switch里面判断的应该是ty1和ty2的opswitch (ty1->op) {case ENUM: case UNION: case STRUCT:case UNSIGNED: case INT: case FLOAT:return 0;case POINTER:  return eqtype(ty1->type, ty2->type, 1);case VOLATILE: case CONST+VOLATILE:case CONST:    return eqtype(ty1->type, ty2->type, 1);case ARRAY:    if (eqtype(ty1->type, ty2->type, 1)) {//size大小一致,认为是兼容的       if (ty1->size == ty2->size)       return 1;//两个中有至少一个不完全类型       if (ty1->size == 0 || ty2->size == 0)       return ret;       }       return 0;case FUNCTION: if (eqtype(ty1->type, ty2->type, 1)) {       Type *p1 = ty1->u.f.proto, *p2 = ty2->u.f.proto;       if (p1 == p2)       return 1;       if (p1 && p2) {       for ( ; *p1 && *p2; p1++, p2++)if (eqtype(unqual(*p1), unqual(*p2), 1) == 0)return 0;if (*p1 == NULL && *p2 == NULL)return 1;       } else {       if (variadic(p1 ? ty1 : ty2))return 0;if (p1 == NULL)p1 = p2;for ( ; *p1; p1++) {Type ty = unqual(*p1);if (promote(ty) != (isenum(ty) ? ty->type : ty))return 0;}return 1;       }       }       return 0;}assert(0); return 0;}//Type promote(Type ty) {ty = unqual(ty);switch (ty->op) {case ENUM:return inttype;case INT:if (ty->size < inttype->size)return inttype;break;case UNSIGNED:if (ty->size < inttype->size)return inttype;if (ty->size < unsignedtype->size)return unsignedtype;break;case FLOAT:if (ty->size < doubletype->size)return doubletype;}return ty;}Type signedint(Type ty) {if (ty->op == INT)return ty;assert(ty->op == UNSIGNED);#define xx(t) if (ty->size == t->size) return txx(inttype);xx(longtype);xx(longlong);#undef xxassert(0); return NULL;}Type compose(Type ty1, Type ty2) {if (ty1 == ty2)return ty1;assert(ty1->op == ty2->op);switch (ty1->op) {case POINTER:return ptr(compose(ty1->type, ty2->type));case CONST+VOLATILE:return qual(CONST, qual(VOLATILE,compose(ty1->type, ty2->type)));case CONST: case VOLATILE:return qual(ty1->op, compose(ty1->type, ty2->type));case ARRAY:    { Type ty = compose(ty1->type, ty2->type); if (ty1->size && (ty1->type->size && ty2->size == 0 || ty1->size == ty2->size)) return array(ty, ty1->size/ty1->type->size, ty1->align); if (ty2->size && ty2->type->size && ty1->size == 0) return array(ty, ty2->size/ty2->type->size, ty2->align); return array(ty, 0, 0);    }case FUNCTION: { Type *p1  = ty1->u.f.proto, *p2 = ty2->u.f.proto; Type ty   = compose(ty1->type, ty2->type); List tlist = NULL; if (p1 == NULL && p2 == NULL) return func(ty, NULL, 1); if (p1 && p2 == NULL) return func(ty, p1, ty1->u.f.oldstyle); if (p2 && p1 == NULL) return func(ty, p2, ty2->u.f.oldstyle); for ( ; *p1 && *p2; p1++, p2++) { Type ty = compose(unqual(*p1), unqual(*p2)); if (isconst(*p1)    || isconst(*p2)) ty = qual(CONST, ty); if (isvolatile(*p1) || isvolatile(*p2)) ty = qual(VOLATILE, ty); tlist = append(ty, tlist); } assert(*p1 == NULL && *p2 == NULL); return func(ty, ltov(&tlist, PERM), 0); }}assert(0); return NULL;}int ttob(Type ty) {switch (ty->op) {case CONST: case VOLATILE: case CONST+VOLATILE:return ttob(ty->type);case VOID: case INT: case UNSIGNED: case FLOAT:return ty->op + sizeop(ty->size);case POINTER:return POINTER + sizeop(voidptype->size);case FUNCTION:return POINTER + sizeop(funcptype->size);case ARRAY: case STRUCT: case UNION:return STRUCT;case ENUM:return INT + sizeop(inttype->size);}assert(0); return INT;}Type btot(int op, int size) {#define xx(ty) if (size == (ty)->size) return ty;switch (optype(op)) {case F:xx(floattype);xx(doubletype);xx(longdouble);assert(0); return 0;case I:if (chartype->op == INT)xx(chartype);xx(signedchar);xx(shorttype);xx(inttype);xx(longtype);xx(longlong);assert(0); return 0;case U:if (chartype->op == UNSIGNED)xx(chartype);xx(unsignedchar);xx(unsignedshort);xx(unsignedtype);xx(unsignedlong);xx(unsignedlonglong);assert(0); return 0;case P:xx(voidptype);xx(funcptype);assert(0); return 0;}#undef xxassert(0); return 0;}int hasproto(Type ty) {if (ty == 0)return 1;switch (ty->op) {case CONST: case VOLATILE: case CONST+VOLATILE: case POINTER:case ARRAY:return hasproto(ty->type);//递归其操作数case FUNCTION:return hasproto(ty->type) && ty->u.f.proto;case STRUCT: case UNION:case VOID:   case FLOAT: case ENUM:  case INT: case UNSIGNED:return 1;}assert(0); return 0;}/* fieldlist - construct a flat list of fields in type ty */Field fieldlist(Type ty) {return ty->u.sym->u.s.flist;//返回fieldlist头指针}/* fieldref - find field name of type ty, return entry */Field fieldref(const char *name, Type ty) {Field p = isfield(name, unqual(ty)->u.sym->u.s.flist);if (p && xref) {Symbol q;assert(unqual(ty)->u.sym->u.s.ftab);q = lookup(name, unqual(ty)->u.sym->u.s.ftab);assert(q);use(q, src);}return p;}/* ftype - return a function type for rty function (ty,...)' */Type ftype(Type rty, ...) {va_list ap;Type ty = NULL;List list = NULL;va_start(ap, rty);ty = va_arg(ap, Type);for ( ; ty != NULL; ty = va_arg(ap, Type))list = append(ty, list);va_end(ap);return func(rty, ltov(&list, PERM), 0);}/* isfield - if name is a field in flist, return pointer to the field structure */static Field isfield(const char *name, Field flist) {for ( ; flist; flist = flist->link)if (flist->name == name)break;return flist;}/* outtype - output type ty */void outtype(Type ty, FILE *f) {switch (ty->op) {case CONST+VOLATILE: case CONST: case VOLATILE:fprint(f, "%k %t", ty->op, ty->type);break;case STRUCT: case UNION: case ENUM:assert(ty->u.sym);if (ty->size == 0)fprint(f, "incomplete ");assert(ty->u.sym->name);if (*ty->u.sym->name >= '1' && *ty->u.sym->name <= '9') {Symbol p = findtype(ty);if (p == 0)fprint(f, "%k defined at %w", ty->op, &ty->u.sym->src);elsefprint(f, p->name);} else {fprint(f, "%k %s", ty->op, ty->u.sym->name);if (ty->size == 0)fprint(f, " defined at %w", &ty->u.sym->src);}break;case VOID: case FLOAT: case INT: case UNSIGNED:fprint(f, ty->u.sym->name);break;case POINTER:fprint(f, "pointer to %t", ty->type);break;case FUNCTION:fprint(f, "%t function", ty->type);if (ty->u.f.proto && ty->u.f.proto[0]) {int i;fprint(f, "(%t", ty->u.f.proto[0]);for (i = 1; ty->u.f.proto[i]; i++)if (ty->u.f.proto[i] == voidtype)fprint(f, ",...");elsefprint(f, ",%t", ty->u.f.proto[i]);fprint(f, ")");} else if (ty->u.f.proto && ty->u.f.proto[0] == 0)fprint(f, "(void)");break;case ARRAY:if (ty->size > 0 && ty->type && ty->type->size > 0) {fprint(f, "array %d", ty->size/ty->type->size);while (ty->type && isarray(ty->type) && ty->type->type->size > 0) {ty = ty->type;fprint(f, ",%d", ty->size/ty->type->size);}} elsefprint(f, "incomplete array");if (ty->type)fprint(f, " of %t", ty->type);break;default: assert(0);}}/* printdecl - output a C declaration for symbol p of type ty */void printdecl(Symbol p, Type ty) {switch (p->sclass) {case AUTO:fprint(stderr, "%s;\n", typestring(ty, p->name));break;case STATIC: case EXTERN:fprint(stderr, "%k %s;\n", p->sclass, typestring(ty, p->name));break;case TYPEDEF: case ENUM:break;default: assert(0);}}/* printproto - output a prototype declaration for function p */void printproto(Symbol p, Symbol callee[]) {if (p->type->u.f.proto)printdecl(p, p->type);else {int i;List list = 0;if (callee[0] == 0)list = append(voidtype, list);elsefor (i = 0; callee[i]; i++)list = append(callee[i]->type, list);printdecl(p, func(freturn(p->type), ltov(&list, PERM), 0));}}/* prtype - print details of type ty on f with given indent */static void prtype(Type ty, FILE *f, int indent, unsigned mark) {switch (ty->op) {default:fprint(f, "(%d %d %d [%p])", ty->op, ty->size, ty->align, ty->u.sym);break;case FLOAT: case INT: case UNSIGNED: case VOID:fprint(f, "(%k %d %d [\"%s\"])", ty->op, ty->size, ty->align, ty->u.sym->name);break;case CONST+VOLATILE: case CONST: case VOLATILE: case POINTER: case ARRAY:fprint(f, "(%k %d %d ", ty->op, ty->size, ty->align);prtype(ty->type, f, indent+1, mark);fprint(f, ")");break;case STRUCT: case UNION:fprint(f, "(%k %d %d [\"%s\"]", ty->op, ty->size, ty->align, ty->u.sym->name);if (ty->x.marked != mark) {Field p;ty->x.marked = mark;for (p = ty->u.sym->u.s.flist; p; p = p->link) {fprint(f, "\n%I", indent+1);prtype(p->type, f, indent+1, mark);fprint(f, " %s@%d", p->name, p->offset);if (p->lsb)fprint(f, ":%d..%d",fieldsize(p) + fieldright(p), fieldright(p));}fprint(f, "\n%I", indent);}fprint(f, ")");break;case ENUM:fprint(f, "(%k %d %d [\"%s\"]", ty->op, ty->size, ty->align, ty->u.sym->name);if (ty->x.marked != mark) {int i;Symbol *p = ty->u.sym->u.idlist;ty->x.marked = mark;for (i = 0; p[i] != NULL; i++)fprint(f, "%I%s=%d\n", indent+1, p[i]->name, p[i]->u.value);}fprint(f, ")");break;case FUNCTION:fprint(f, "(%k %d %d ", ty->op, ty->size, ty->align);prtype(ty->type, f, indent+1, mark);if (ty->u.f.proto) {int i;fprint(f, "\n%I{", indent+1);for (i = 0; ty->u.f.proto[i]; i++) {if (i > 0)fprint(f, "%I", indent+2);prtype(ty->u.f.proto[i], f, indent+2, mark);fprint(f, "\n");}fprint(f, "%I}", indent+1);}fprint(f, ")");break;}}/* printtype - print details of type ty on fd */void printtype(Type ty, int fd) {static unsigned mark;prtype(ty, fd == 1 ? stdout : stderr, 0, ++mark);fprint(fd == 1 ? stdout : stderr, "\n");}/* typestring - return ty as C declaration for str, which may be "" */char *typestring(Type ty, char *str) {for ( ; ty; ty = ty->type) {Symbol p;switch (ty->op) {case CONST+VOLATILE: case CONST: case VOLATILE:if (isptr(ty->type))str = stringf("%k %s", ty->op, str);elsereturn stringf("%k %s", ty->op, typestring(ty->type, str));break;case STRUCT: case UNION: case ENUM:assert(ty->u.sym);if ((p = findtype(ty)) != NULL)return *str ? stringf("%s %s", p->name, str) : p->name;if (*ty->u.sym->name >= '1' && *ty->u.sym->name <= '9')warning("unnamed %k in prototype\n", ty->op);if (*str)return stringf("%k %s %s", ty->op, ty->u.sym->name, str);elsereturn stringf("%k %s", ty->op, ty->u.sym->name);case VOID: case FLOAT: case INT: case UNSIGNED:return *str ? stringf("%s %s", ty->u.sym->name, str) : ty->u.sym->name;case POINTER:if (!ischar(ty->type) && (p = findtype(ty)) != NULL)return *str ? stringf("%s %s", p->name, str) : p->name;str = stringf(isarray(ty->type) || isfunc(ty->type) ? "(*%s)" : "*%s", str);break;case FUNCTION:if ((p = findtype(ty)) != NULL)return *str ? stringf("%s %s", p->name, str) : p->name;if (ty->u.f.proto == 0)str = stringf("%s()", str);else if (ty->u.f.proto[0]) {int i;str = stringf("%s(%s", str, typestring(ty->u.f.proto[0], ""));for (i = 1; ty->u.f.proto[i]; i++)if (ty->u.f.proto[i] == voidtype)str = stringf("%s, ...", str);elsestr = stringf("%s, %s", str, typestring(ty->u.f.proto[i], ""));str = stringf("%s)", str);} elsestr = stringf("%s(void)", str);break;case ARRAY:if ((p = findtype(ty)) != NULL)return *str ? stringf("%s %s", p->name, str) : p->name;if (ty->type && ty->type->size > 0)str = stringf("%s[%d]", str, ty->size/ty->type->size);elsestr = stringf("%s[]", str);break;default: assert(0);}}assert(0); return 0;}




0 0
原创粉丝点击