diff options
author | zakk <zakk@edf5b092-35ff-0310-97b2-ce42778d08ea> | 2005-08-26 17:39:27 +0000 |
---|---|---|
committer | zakk <zakk@edf5b092-35ff-0310-97b2-ce42778d08ea> | 2005-08-26 17:39:27 +0000 |
commit | 6bf20c78f5b69d40bcc4931df93d29198435ab67 (patch) | |
tree | e3eda937a05d7db42de725b7013bd0344b987f34 /lcc/src/types.c | |
parent | 872d4d7f55af706737ffb361bb76ad13e7496770 (diff) | |
download | ioquake3-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-x | lcc/src/types.c | 1496 |
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; +} + |