aboutsummaryrefslogtreecommitdiffstats
path: root/lcc/src/types.c
diff options
context:
space:
mode:
authorzakk <zakk@edf5b092-35ff-0310-97b2-ce42778d08ea>2005-08-26 17:39:27 +0000
committerzakk <zakk@edf5b092-35ff-0310-97b2-ce42778d08ea>2005-08-26 17:39:27 +0000
commit6bf20c78f5b69d40bcc4931df93d29198435ab67 (patch)
treee3eda937a05d7db42de725b7013bd0344b987f34 /lcc/src/types.c
parent872d4d7f55af706737ffb361bb76ad13e7496770 (diff)
downloadioquake3-aero-6bf20c78f5b69d40bcc4931df93d29198435ab67.tar.gz
ioquake3-aero-6bf20c78f5b69d40bcc4931df93d29198435ab67.zip
newlines fixed
git-svn-id: svn://svn.icculus.org/quake3/trunk@6 edf5b092-35ff-0310-97b2-ce42778d08ea
Diffstat (limited to 'lcc/src/types.c')
-rwxr-xr-xlcc/src/types.c1496
1 files changed, 748 insertions, 748 deletions
diff --git a/lcc/src/types.c b/lcc/src/types.c
index eead3e1..207cdb5 100755
--- a/lcc/src/types.c
+++ b/lcc/src/types.c
@@ -1,748 +1,748 @@
-#include "c.h"
-#include <float.h>
-
-
-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);
- 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;
- else
- p->u.limits.max.d = LDBL_MAX;
- p->u.limits.min.d = -p->u.limits.max.d;
- break;
- default: assert(0);
- }
- return ty;
-}
-static Type type(int op, Type ty, int size, int align, void *sym) {
- 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)
- 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;
- tn->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; }
- 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)
- 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
- {
- 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=t
- xx(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 xx
- widechar = 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;
- else
- error("type error: %s\n", "pointer expected");
- return isenum(ty) ? unqual(ty)->type : 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)
- 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);
-}
-Type 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++)
- ;
- return i > 1 && ty->u.f.proto[i-1] == voidtype;
- }
- return 0;
-}
-Type newstruct(int op, char *tag) {
- Symbol p;
-
- assert(tag);
- if (*tag == 0)
- tag = stringd(genlabel(1));
- else
- if ((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);
- }
- p = 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 newfield(char *name, Type ty, Type fty) {
- Field p, *q = &ty->u.sym->u.s.flist;
-
- 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->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)) {
- 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 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;
-}
-
+#include "c.h"
+#include <float.h>
+
+
+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);
+ 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;
+ else
+ p->u.limits.max.d = LDBL_MAX;
+ p->u.limits.min.d = -p->u.limits.max.d;
+ break;
+ default: assert(0);
+ }
+ return ty;
+}
+static Type type(int op, Type ty, int size, int align, void *sym) {
+ 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)
+ 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;
+ tn->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; }
+ 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)
+ 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
+ {
+ 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=t
+ xx(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 xx
+ widechar = 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;
+ else
+ error("type error: %s\n", "pointer expected");
+ return isenum(ty) ? unqual(ty)->type : 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)
+ 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);
+}
+Type 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++)
+ ;
+ return i > 1 && ty->u.f.proto[i-1] == voidtype;
+ }
+ return 0;
+}
+Type newstruct(int op, char *tag) {
+ Symbol p;
+
+ assert(tag);
+ if (*tag == 0)
+ tag = stringd(genlabel(1));
+ else
+ if ((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);
+ }
+ p = 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 newfield(char *name, Type ty, Type fty) {
+ Field p, *q = &ty->u.sym->u.s.flist;
+
+ 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->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)) {
+ 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 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;
+}
+