📄 types.c
字号:
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 t xx(inttype); xx(longtype); xx(longlong);#undef xx assert(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 xx assert(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;}/* 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, Type ty) { List list = append(ty, NULL); list = append(voidtype, list); 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); else fprint(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, ",..."); else fprint(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); } } else fprint(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); else for (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); else return 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); else return 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); else str = stringf("%s, %s", str, typestring(ty->u.f.proto[i], "")); str = stringf("%s)", str); } else str = 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); else str = stringf("%s[]", str); break; default: assert(0); } } assert(0); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -