Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

types.c (20851B)


      1 #include "c.h"
      2 #include <float.h>
      3 
      4 
      5 static Field isfield(const char *, Field);
      6 static Type type(int, Type, int, int, void *);
      7 
      8 static struct entry {
      9 	struct type type;
     10 	struct entry *link;
     11 } *typetable[128];
     12 static int maxlevel;
     13 
     14 static Symbol pointersym;
     15 
     16 Type chartype;			/* char */
     17 Type doubletype;		/* double */
     18 Type floattype;			/* float */
     19 Type inttype;			/* signed int */
     20 Type longdouble;		/* long double */
     21 Type longtype;			/* long */
     22 Type longlong;			/* long long */
     23 Type shorttype;			/* signed short int */
     24 Type signedchar;		/* signed char */
     25 Type unsignedchar;		/* unsigned char */
     26 Type unsignedlong;		/* unsigned long int */
     27 Type unsignedlonglong;		/* unsigned long long int */
     28 Type unsignedshort;		/* unsigned short int */
     29 Type unsignedtype;		/* unsigned int */
     30 Type funcptype;			/* void (*)() */
     31 Type charptype;			/* char* */
     32 Type voidptype;			/* void* */
     33 Type voidtype;			/* basic types: void */
     34 Type unsignedptr;		/* unsigned type to hold void* */
     35 Type signedptr;			/* signed type to hold void* */
     36 Type widechar;			/* unsigned type that represents wchar_t */
     37 
     38 static Type xxinit(int op, char *name, Metrics m) {
     39 	Symbol p = install(string(name), &types, GLOBAL, PERM);
     40 	Type ty = type(op, 0, m.size, m.align, p);
     41 
     42 	assert(ty->align == 0 || ty->size%ty->align == 0);
     43 	p->type = ty;
     44 	p->addressed = m.outofline;
     45 	switch (ty->op) {
     46 	case INT:
     47 		p->u.limits.max.i = ones(8*ty->size)>>1;
     48 		p->u.limits.min.i = -p->u.limits.max.i - 1;
     49 		break;
     50 	case UNSIGNED:
     51 		p->u.limits.max.u = ones(8*ty->size);
     52 		p->u.limits.min.u = 0;
     53 		break;
     54 	case FLOAT:
     55 		if (ty->size == sizeof (float))
     56 			p->u.limits.max.d =  FLT_MAX;
     57 		else if (ty->size == sizeof (double))
     58 			p->u.limits.max.d =  DBL_MAX;
     59 		else
     60 			p->u.limits.max.d = LDBL_MAX;
     61 		p->u.limits.min.d = -p->u.limits.max.d;
     62 		break;
     63 	default: assert(0);
     64 	}
     65 	return ty;
     66 }
     67 static Type type(int op, Type ty, int size, int align, void *sym) {
     68 	unsigned h = (op^((unsigned long)ty>>3))
     69 &(NELEMS(typetable)-1);
     70 	struct entry *tn;
     71 
     72 	if (op != FUNCTION && (op != ARRAY || size > 0))
     73 		for (tn = typetable[h]; tn; tn = tn->link)
     74 			if (tn->type.op    == op   && tn->type.type  == ty
     75 			&&  tn->type.size  == size && tn->type.align == align
     76 			&&  tn->type.u.sym == sym)
     77 				return &tn->type;
     78 	NEW0(tn, PERM);
     79 	tn->type.op = op;
     80 	tn->type.type = ty;
     81 	tn->type.size = size;
     82 	tn->type.align = align;
     83 	tn->type.u.sym = sym;
     84 	tn->link = typetable[h];
     85 	typetable[h] = tn;
     86 	return &tn->type;
     87 }
     88 void type_init(int argc, char *argv[]) {
     89 	static int inited;
     90 	int i;
     91 
     92 	if (inited)
     93 		return;
     94 	inited = 1;
     95 	if (!IR)
     96 		return;
     97 	for (i = 1; i < argc; i++) {
     98 		int size, align, outofline;
     99 		if (strncmp(argv[i], "-unsigned_char=", 15) == 0)
    100 			IR->unsigned_char = argv[i][15] - '0';
    101 #define xx(name) \
    102 		else if (sscanf(argv[i], "-" #name "=%d,%d,%d", &size, &align, &outofline) == 3) { \
    103 			IR->name.size = size; IR->name.align = align; \
    104 			IR->name.outofline = outofline; }
    105 	xx(charmetric)
    106 	xx(shortmetric)
    107 	xx(intmetric)
    108 	xx(longmetric)
    109 	xx(longlongmetric)
    110 	xx(floatmetric)
    111 	xx(doublemetric)
    112 	xx(longdoublemetric)
    113 	xx(ptrmetric)
    114 	xx(structmetric)
    115 #undef xx
    116 	}
    117 #define xx(v,name,op,metrics) v=xxinit(op,name,IR->metrics)
    118 	xx(chartype,        "char",              IR->unsigned_char ? UNSIGNED : INT,charmetric);
    119 	xx(doubletype,      "double",            FLOAT,   doublemetric);
    120 	xx(floattype,       "float",             FLOAT,   floatmetric);
    121 	xx(inttype,         "int",               INT,     intmetric);
    122 	xx(longdouble,      "long double",       FLOAT,   longdoublemetric);
    123 	xx(longtype,        "long int",          INT,     longmetric);
    124 	xx(longlong,        "long long int",     INT,     longlongmetric);
    125 	xx(shorttype,       "short",             INT,     shortmetric);
    126 	xx(signedchar,      "signed char",       INT,     charmetric);
    127 	xx(unsignedchar,    "unsigned char",     UNSIGNED,charmetric);
    128 	xx(unsignedlong,    "unsigned long",     UNSIGNED,longmetric);
    129 	xx(unsignedshort,   "unsigned short",    UNSIGNED,shortmetric);
    130 	xx(unsignedtype,    "unsigned int",      UNSIGNED,intmetric);
    131 	xx(unsignedlonglong,"unsigned long long",UNSIGNED,longlongmetric);
    132 #undef xx
    133 	{
    134 		Symbol p;
    135 		p = install(string("void"), &types, GLOBAL, PERM);
    136 		voidtype = type(VOID, NULL, 0, 0, p);
    137 		p->type = voidtype;
    138 	}
    139 	pointersym = install(string("T*"), &types, GLOBAL, PERM);
    140 	pointersym->addressed = IR->ptrmetric.outofline;
    141 	pointersym->u.limits.max.p = (void*)ones(8*IR->ptrmetric.size);
    142 	pointersym->u.limits.min.p = 0;
    143 	voidptype = ptr(voidtype);
    144 	funcptype = ptr(func(voidtype, NULL, 1));
    145 	charptype = ptr(chartype);
    146 #define xx(v,t) if (v==NULL && t->size==voidptype->size && t->align==voidptype->align) v=t
    147 	xx(unsignedptr,unsignedshort);
    148 	xx(unsignedptr,unsignedtype);
    149 	xx(unsignedptr,unsignedlong);
    150 	xx(unsignedptr,unsignedlonglong);
    151 	if (unsignedptr == NULL)
    152 		unsignedptr = type(UNSIGNED, NULL, voidptype->size, voidptype->align, voidptype->u.sym);
    153 	xx(signedptr,shorttype);
    154 	xx(signedptr,inttype);
    155 	xx(signedptr,longtype);
    156 	xx(signedptr,longlong);
    157 	if (signedptr == NULL)
    158 		signedptr = type(INT, NULL, voidptype->size, voidptype->align, voidptype->u.sym);
    159 #undef xx
    160 	widechar = unsignedshort;
    161 	for (i = 0; i < argc; i++) {
    162 #define xx(name,type) \
    163 		if (strcmp(argv[i], "-wchar_t=" #name) == 0) \
    164 			widechar = type;
    165 		xx(unsigned_char,unsignedchar)
    166 		xx(unsigned_int,unsignedtype)
    167 		xx(unsigned_short,unsignedshort)
    168 	}
    169 #undef xx
    170 }
    171 void rmtypes(int lev) {
    172 	if (maxlevel >= lev) {
    173 		int i;
    174 		maxlevel = 0;
    175 		for (i = 0; i < NELEMS(typetable); i++) {
    176 			struct entry *tn, **tq = &typetable[i];
    177 			while ((tn = *tq) != NULL)
    178 				if (tn->type.op == FUNCTION)
    179 					tq = &tn->link;
    180 				else if (tn->type.u.sym && tn->type.u.sym->scope >= lev)
    181 					*tq = tn->link;
    182 				else {
    183 					if (tn->type.u.sym && tn->type.u.sym->scope > maxlevel)
    184 						maxlevel = tn->type.u.sym->scope;
    185 					tq = &tn->link;
    186 				}
    187 
    188 		}
    189 	}
    190 }
    191 Type ptr(Type ty) {
    192 	return type(POINTER, ty, IR->ptrmetric.size,
    193 		IR->ptrmetric.align, pointersym);
    194 }
    195 Type deref(Type ty) {
    196 	if (isptr(ty))
    197 		ty = ty->type;
    198 	else
    199 		error("type error: %s\n", "pointer expected");
    200 	return isenum(ty) ? unqual(ty)->type : ty;
    201 }
    202 Type array(Type ty, int n, int a) {
    203 	assert(ty);
    204 	if (isfunc(ty)) {
    205 		error("illegal type `array of %t'\n", ty);
    206 		return array(inttype, n, 0);
    207 	}
    208 	if (isarray(ty) && ty->size == 0)
    209 		error("missing array size\n");
    210 	if (ty->size == 0) {
    211 		if (unqual(ty) == voidtype)
    212 			error("illegal type `array of %t'\n", ty);
    213 		else if (Aflag >= 2)
    214 			warning("declaring type array of %t' is undefined\n", ty);
    215 
    216 	} else if (n > INT_MAX/ty->size) {
    217 		error("size of `array of %t' exceeds %d bytes\n",
    218 			ty, INT_MAX);
    219 		n = 1;
    220 	}
    221 	return type(ARRAY, ty, n*ty->size,
    222 		a ? a : ty->align, NULL);
    223 }
    224 Type atop(Type ty) {
    225 	if (isarray(ty))
    226 		return ptr(ty->type);
    227 	error("type error: %s\n", "array expected");
    228 	return ptr(ty);
    229 }
    230 Type qual(int op, Type ty) {
    231 	if (isarray(ty))
    232 		ty = type(ARRAY, qual(op, ty->type), ty->size,
    233 			ty->align, NULL);
    234 	else if (isfunc(ty))
    235 		warning("qualified function type ignored\n");
    236 	else if (isconst(ty)    && op == CONST
    237 	||       isvolatile(ty) && op == VOLATILE)
    238 		error("illegal type `%k %t'\n", op, ty);
    239 	else {
    240 		if (isqual(ty)) {
    241 			op += ty->op;
    242 			ty = ty->type;
    243 		}
    244 		ty = type(op, ty, ty->size, ty->align, NULL);
    245 	}
    246 	return ty;
    247 }
    248 Type func(Type ty, Type *proto, int style) {
    249 	if (ty && (isarray(ty) || isfunc(ty)))
    250 		error("illegal return type `%t'\n", ty);
    251 	ty = type(FUNCTION, ty, 0, 0, NULL);
    252 	ty->u.f.proto = proto;
    253 	ty->u.f.oldstyle = style;
    254 	return ty;
    255 }
    256 Type freturn(Type ty) {
    257 	if (isfunc(ty))
    258 		return ty->type;
    259 	error("type error: %s\n", "function expected");
    260 	return inttype;
    261 }
    262 int variadic(Type ty) {
    263 	if (isfunc(ty) && ty->u.f.proto) {
    264 		int i;
    265 		for (i = 0; ty->u.f.proto[i]; i++)
    266 			;
    267 		return i > 1 && ty->u.f.proto[i-1] == voidtype;
    268 	}
    269 	return 0;
    270 }
    271 Type newstruct(int op, char *tag) {
    272 	Symbol p;
    273 
    274 	assert(tag);
    275 	if (*tag == 0)
    276 		tag = stringd(genlabel(1));
    277 	else
    278 		if ((p = lookup(tag, types)) != NULL && (p->scope == level
    279 		|| p->scope == PARAM && level == PARAM+1)) {
    280 			if (p->type->op == op && !p->defined)
    281 				return p->type;
    282 			error("redefinition of `%s' previously defined at %w\n",
    283 				p->name, &p->src);
    284 		}
    285 	p = install(tag, &types, level, PERM);
    286 	p->type = type(op, NULL, 0, 0, p);
    287 	if (p->scope > maxlevel)
    288 		maxlevel = p->scope;
    289 	p->src = src;
    290 	return p->type;
    291 }
    292 Field newfield(char *name, Type ty, Type fty) {
    293 	Field p, *q = &ty->u.sym->u.s.flist;
    294 
    295 	if (name == NULL)
    296 		name = stringd(genlabel(1));
    297 	for (p = *q; p; q = &p->link, p = *q)
    298 		if (p->name == name)
    299 			error("duplicate field name `%s' in `%t'\n",
    300 				name, ty);
    301 	NEW0(p, PERM);
    302 	*q = p;
    303 	p->name = name;
    304 	p->type = fty;
    305 	if (xref) {							/* omit */
    306 		if (ty->u.sym->u.s.ftab == NULL)			/* omit */
    307 			ty->u.sym->u.s.ftab = table(NULL, level);	/* omit */
    308 		install(name, &ty->u.sym->u.s.ftab, 0, PERM)->src = src;/* omit */
    309 	}								/* omit */
    310 	return p;
    311 }
    312 int eqtype(Type ty1, Type ty2, int ret) {
    313 	if (ty1 == ty2)
    314 		return 1;
    315 	if (ty1->op != ty2->op)
    316 		return 0;
    317 	switch (ty1->op) {
    318 	case ENUM: case UNION: case STRUCT:
    319 	case UNSIGNED: case INT: case FLOAT:
    320 		return 0;
    321 	case POINTER:  return eqtype(ty1->type, ty2->type, 1);
    322 	case VOLATILE: case CONST+VOLATILE:
    323 	case CONST:    return eqtype(ty1->type, ty2->type, 1);
    324 	case ARRAY:    if (eqtype(ty1->type, ty2->type, 1)) {
    325 		       	if (ty1->size == ty2->size)
    326 		       		return 1;
    327 		       	if (ty1->size == 0 || ty2->size == 0)
    328 		       		return ret;
    329 		       }
    330 		       return 0;
    331 	case FUNCTION: if (eqtype(ty1->type, ty2->type, 1)) {
    332 		       	Type *p1 = ty1->u.f.proto, *p2 = ty2->u.f.proto;
    333 		       	if (p1 == p2)
    334 		       		return 1;
    335 		       	if (p1 && p2) {
    336 		       		for ( ; *p1 && *p2; p1++, p2++)
    337 					if (eqtype(unqual(*p1), unqual(*p2), 1) == 0)
    338 						return 0;
    339 				if (*p1 == NULL && *p2 == NULL)
    340 					return 1;
    341 		       	} else {
    342 		       		if (variadic(p1 ? ty1 : ty2))
    343 					return 0;
    344 				if (p1 == NULL)
    345 					p1 = p2;
    346 				for ( ; *p1; p1++) {
    347 					Type ty = unqual(*p1);
    348 					if (promote(ty) != (isenum(ty) ? ty->type : ty))
    349 						return 0;
    350 				}
    351 				return 1;
    352 		       	}
    353 		       }
    354 		       return 0;
    355 	}
    356 	assert(0); return 0;
    357 }
    358 Type promote(Type ty) {
    359 	ty = unqual(ty);
    360 	switch (ty->op) {
    361 	case ENUM:
    362 		return inttype;
    363 	case INT:
    364 		if (ty->size < inttype->size)
    365 			return inttype;
    366 		break;
    367 	case UNSIGNED:
    368 		if (ty->size < inttype->size)
    369 			return inttype;
    370 		if (ty->size < unsignedtype->size)
    371 			return unsignedtype;
    372 		break;
    373 	case FLOAT:
    374 		if (ty->size < doubletype->size)
    375 			return doubletype;
    376 	}
    377 	return ty;
    378 }
    379 Type signedint(Type ty) {
    380 	if (ty->op == INT)
    381 		return ty;
    382 	assert(ty->op == UNSIGNED);
    383 #define xx(t) if (ty->size == t->size) return t
    384 	xx(inttype);
    385 	xx(longtype);
    386 	xx(longlong);
    387 #undef xx
    388 	assert(0); return NULL;
    389 }
    390 Type compose(Type ty1, Type ty2) {
    391 	if (ty1 == ty2)
    392 		return ty1;
    393 	assert(ty1->op == ty2->op);
    394 	switch (ty1->op) {
    395 	case POINTER:
    396 		return ptr(compose(ty1->type, ty2->type));
    397 	case CONST+VOLATILE:
    398 		return qual(CONST, qual(VOLATILE,
    399 			compose(ty1->type, ty2->type)));
    400 	case CONST: case VOLATILE:
    401 		return qual(ty1->op, compose(ty1->type, ty2->type));
    402 	case ARRAY:    { Type ty = compose(ty1->type, ty2->type);
    403 			 if (ty1->size && (ty1->type->size && ty2->size == 0 || ty1->size == ty2->size))
    404 			 	return array(ty, ty1->size/ty1->type->size, ty1->align);
    405 			 if (ty2->size && ty2->type->size && ty1->size == 0)
    406 			 	return array(ty, ty2->size/ty2->type->size, ty2->align);
    407 			 return array(ty, 0, 0);    }
    408 	case FUNCTION: { Type *p1  = ty1->u.f.proto, *p2 = ty2->u.f.proto;
    409 			 Type ty   = compose(ty1->type, ty2->type);
    410 			 List tlist = NULL;
    411 			 if (p1 == NULL && p2 == NULL)
    412 			 	return func(ty, NULL, 1);
    413 			 if (p1 && p2 == NULL)
    414 			 	return func(ty, p1, ty1->u.f.oldstyle);
    415 			 if (p2 && p1 == NULL)
    416 			 	return func(ty, p2, ty2->u.f.oldstyle);
    417 			 for ( ; *p1 && *p2; p1++, p2++) {
    418 			 	Type ty = compose(unqual(*p1), unqual(*p2));
    419 			 	if (isconst(*p1)    || isconst(*p2))
    420 			 		ty = qual(CONST, ty);
    421 			 	if (isvolatile(*p1) || isvolatile(*p2))
    422 			 		ty = qual(VOLATILE, ty);
    423 			 	tlist = append(ty, tlist);
    424 			 }
    425 			 assert(*p1 == NULL && *p2 == NULL);
    426 			 return func(ty, ltov(&tlist, PERM), 0); }
    427 	}
    428 	assert(0); return NULL;
    429 }
    430 int ttob(Type ty) {
    431 	switch (ty->op) {
    432 	case CONST: case VOLATILE: case CONST+VOLATILE:
    433 		return ttob(ty->type);
    434 	case VOID: case INT: case UNSIGNED: case FLOAT:
    435 		return ty->op + sizeop(ty->size);
    436 	case POINTER:
    437 		return POINTER + sizeop(voidptype->size);
    438 	case FUNCTION:
    439 		return POINTER + sizeop(funcptype->size);
    440 	case ARRAY: case STRUCT: case UNION:
    441 		return STRUCT;
    442 	case ENUM:
    443 		return INT + sizeop(inttype->size);
    444 	}
    445 	assert(0); return INT;
    446 }
    447 Type btot(int op, int size) {
    448 #define xx(ty) if (size == (ty)->size) return ty;
    449 	switch (optype(op)) {
    450 	case F:
    451 		xx(floattype);
    452 		xx(doubletype);
    453 		xx(longdouble);
    454 		assert(0); return 0;
    455 	case I:
    456 		if (chartype->op == INT)
    457 			xx(chartype);
    458 		xx(signedchar);
    459 		xx(shorttype);
    460 		xx(inttype);
    461 		xx(longtype);
    462 		xx(longlong);
    463 		assert(0); return 0;
    464 	case U:
    465 		if (chartype->op == UNSIGNED)
    466 			xx(chartype);
    467 		xx(unsignedchar);
    468 		xx(unsignedshort);
    469 		xx(unsignedtype);
    470 		xx(unsignedlong);
    471 		xx(unsignedlonglong);
    472 		assert(0); return 0;
    473 	case P:
    474 		xx(voidptype);
    475 		xx(funcptype);
    476 		assert(0); return 0;
    477 	}
    478 #undef xx
    479 	assert(0); return 0;
    480 }
    481 int hasproto(Type ty) {
    482 	if (ty == 0)
    483 		return 1;
    484 	switch (ty->op) {
    485 	case CONST: case VOLATILE: case CONST+VOLATILE: case POINTER:
    486 	case ARRAY:
    487 		return hasproto(ty->type);
    488 	case FUNCTION:
    489 		return hasproto(ty->type) && ty->u.f.proto;
    490 	case STRUCT: case UNION:
    491 	case VOID:   case FLOAT: case ENUM:  case INT: case UNSIGNED:
    492 		return 1;
    493 	}
    494 	assert(0); return 0;
    495 }
    496 /* fieldlist - construct a flat list of fields in type ty */
    497 Field fieldlist(Type ty) {
    498 	return ty->u.sym->u.s.flist;
    499 }
    500 
    501 /* fieldref - find field name of type ty, return entry */
    502 Field fieldref(const char *name, Type ty) {
    503 	Field p = isfield(name, unqual(ty)->u.sym->u.s.flist);
    504 
    505 	if (p && xref) {
    506 		Symbol q;
    507 		assert(unqual(ty)->u.sym->u.s.ftab);
    508 		q = lookup(name, unqual(ty)->u.sym->u.s.ftab);
    509 		assert(q);
    510 		use(q, src);
    511 	}
    512 	return p;
    513 }
    514 
    515 /* ftype - return a function type for rty function (ty,...)' */
    516 Type ftype(Type rty, Type ty) {
    517 	List list = append(ty, NULL);
    518 
    519 	list = append(voidtype, list);
    520 	return func(rty, ltov(&list, PERM), 0);
    521 }
    522 
    523 /* isfield - if name is a field in flist, return pointer to the field structure */
    524 static Field isfield(const char *name, Field flist) {
    525 	for ( ; flist; flist = flist->link)
    526 		if (flist->name == name)
    527 			break;
    528 	return flist;
    529 }
    530 
    531 /* outtype - output type ty */
    532 void outtype(Type ty, FILE *f) {
    533 	switch (ty->op) {
    534 	case CONST+VOLATILE: case CONST: case VOLATILE:
    535 		fprint(f, "%k %t", ty->op, ty->type);
    536 		break;
    537 	case STRUCT: case UNION: case ENUM:
    538 		assert(ty->u.sym);
    539 		if (ty->size == 0)
    540 			fprint(f, "incomplete ");
    541 		assert(ty->u.sym->name);
    542 		if (*ty->u.sym->name >= '1' && *ty->u.sym->name <= '9') {
    543 			Symbol p = findtype(ty);
    544 			if (p == 0)
    545 				fprint(f, "%k defined at %w", ty->op, &ty->u.sym->src);
    546 			else
    547 				fprint(f, p->name);
    548 		} else {
    549 			fprint(f, "%k %s", ty->op, ty->u.sym->name);
    550 			if (ty->size == 0)
    551 				fprint(f, " defined at %w", &ty->u.sym->src);
    552 		}
    553 		break;
    554 	case VOID: case FLOAT: case INT: case UNSIGNED:
    555 		fprint(f, ty->u.sym->name);
    556 		break;
    557 	case POINTER:
    558 		fprint(f, "pointer to %t", ty->type);
    559 		break;
    560 	case FUNCTION:
    561 		fprint(f, "%t function", ty->type);
    562 		if (ty->u.f.proto && ty->u.f.proto[0]) {
    563 			int i;
    564 			fprint(f, "(%t", ty->u.f.proto[0]);
    565 			for (i = 1; ty->u.f.proto[i]; i++)
    566 				if (ty->u.f.proto[i] == voidtype)
    567 					fprint(f, ",...");
    568 				else
    569 					fprint(f, ",%t", ty->u.f.proto[i]);
    570 			fprint(f, ")");
    571 		} else if (ty->u.f.proto && ty->u.f.proto[0] == 0)
    572 			fprint(f, "(void)");
    573 
    574 		break;
    575 	case ARRAY:
    576 		if (ty->size > 0 && ty->type && ty->type->size > 0) {
    577 			fprint(f, "array %d", ty->size/ty->type->size);
    578 			while (ty->type && isarray(ty->type) && ty->type->type->size > 0) {
    579 				ty = ty->type;
    580 				fprint(f, ",%d", ty->size/ty->type->size);
    581 			}
    582 		} else
    583 			fprint(f, "incomplete array");
    584 		if (ty->type)
    585 			fprint(f, " of %t", ty->type);
    586 		break;
    587 	default: assert(0);
    588 	}
    589 }
    590 
    591 /* printdecl - output a C declaration for symbol p of type ty */
    592 void printdecl(Symbol p, Type ty) {
    593 	switch (p->sclass) {
    594 	case AUTO:
    595 		fprint(stderr, "%s;\n", typestring(ty, p->name));
    596 		break;
    597 	case STATIC: case EXTERN:
    598 		fprint(stderr, "%k %s;\n", p->sclass, typestring(ty, p->name));
    599 		break;
    600 	case TYPEDEF: case ENUM:
    601 		break;
    602 	default: assert(0);
    603 	}
    604 }
    605 
    606 /* printproto - output a prototype declaration for function p */
    607 void printproto(Symbol p, Symbol callee[]) {
    608 	if (p->type->u.f.proto)
    609 		printdecl(p, p->type);
    610 	else {
    611 		int i;
    612 		List list = 0;
    613 		if (callee[0] == 0)
    614 			list = append(voidtype, list);
    615 		else
    616 			for (i = 0; callee[i]; i++)
    617 				list = append(callee[i]->type, list);
    618 		printdecl(p, func(freturn(p->type), ltov(&list, PERM), 0));
    619 	}
    620 }
    621 
    622 /* prtype - print details of type ty on f with given indent */
    623 static void prtype(Type ty, FILE *f, int indent, unsigned mark) {
    624 	switch (ty->op) {
    625 	default:
    626 		fprint(f, "(%d %d %d [%p])", ty->op, ty->size, ty->align, ty->u.sym);
    627 		break;
    628 	case FLOAT: case INT: case UNSIGNED: case VOID:
    629 		fprint(f, "(%k %d %d [\"%s\"])", ty->op, ty->size, ty->align, ty->u.sym->name);
    630 		break;
    631 	case CONST+VOLATILE: case CONST: case VOLATILE: case POINTER: case ARRAY:
    632 		fprint(f, "(%k %d %d ", ty->op, ty->size, ty->align);
    633 		prtype(ty->type, f, indent+1, mark);
    634 		fprint(f, ")");
    635 		break;
    636 	case STRUCT: case UNION:
    637 		fprint(f, "(%k %d %d [\"%s\"]", ty->op, ty->size, ty->align, ty->u.sym->name);
    638 		if (ty->x.marked != mark) {
    639 			Field p;
    640 			ty->x.marked = mark;
    641 			for (p = ty->u.sym->u.s.flist; p; p = p->link) {
    642 				fprint(f, "\n%I", indent+1);
    643 				prtype(p->type, f, indent+1, mark);
    644 				fprint(f, " %s@%d", p->name, p->offset);
    645 				if (p->lsb)
    646 					fprint(f, ":%d..%d",
    647 						fieldsize(p) + fieldright(p), fieldright(p));
    648 			}
    649 			fprint(f, "\n%I", indent);
    650 		}
    651 		fprint(f, ")");
    652 		break;
    653 	case ENUM:
    654 		fprint(f, "(%k %d %d [\"%s\"]", ty->op, ty->size, ty->align, ty->u.sym->name);
    655 		if (ty->x.marked != mark) {
    656 			int i;
    657 			Symbol *p = ty->u.sym->u.idlist;
    658 			ty->x.marked = mark;
    659 			for (i = 0; p[i] != NULL; i++)
    660 				fprint(f, "%I%s=%d\n", indent+1, p[i]->name, p[i]->u.value);
    661 		}
    662 		fprint(f, ")");
    663 		break;
    664 	case FUNCTION:
    665 		fprint(f, "(%k %d %d ", ty->op, ty->size, ty->align);
    666 		prtype(ty->type, f, indent+1, mark);
    667 		if (ty->u.f.proto) {
    668 			int i;
    669 			fprint(f, "\n%I{", indent+1);
    670 			for (i = 0; ty->u.f.proto[i]; i++) {
    671 				if (i > 0)
    672 					fprint(f, "%I", indent+2);
    673 				prtype(ty->u.f.proto[i], f, indent+2, mark);
    674 				fprint(f, "\n");
    675 			}
    676 			fprint(f, "%I}", indent+1);
    677 		}
    678 		fprint(f, ")");
    679 		break;
    680 	}
    681 }
    682 
    683 /* printtype - print details of type ty on fd */
    684 void printtype(Type ty, int fd) {
    685 	static unsigned mark;
    686 	prtype(ty, fd == 1 ? stdout : stderr, 0, ++mark);
    687 	fprint(fd == 1 ? stdout : stderr, "\n");
    688 }
    689 
    690 /* typestring - return ty as C declaration for str, which may be "" */
    691 char *typestring(Type ty, char *str) {
    692 	for ( ; ty; ty = ty->type) {
    693 		Symbol p;
    694 		switch (ty->op) {
    695 		case CONST+VOLATILE: case CONST: case VOLATILE:
    696 			if (isptr(ty->type))
    697 				str = stringf("%k %s", ty->op, str);
    698 			else
    699 				return stringf("%k %s", ty->op, typestring(ty->type, str));
    700 			break;
    701 		case STRUCT: case UNION: case ENUM:
    702 			assert(ty->u.sym);
    703 			if ((p = findtype(ty)) != NULL)
    704 				return *str ? stringf("%s %s", p->name, str) : p->name;
    705 			if (*ty->u.sym->name >= '1' && *ty->u.sym->name <= '9')
    706 				warning("unnamed %k in prototype\n", ty->op);
    707 			if (*str)
    708 				return stringf("%k %s %s", ty->op, ty->u.sym->name, str);
    709 			else
    710 				return stringf("%k %s", ty->op, ty->u.sym->name);
    711 		case VOID: case FLOAT: case INT: case UNSIGNED:
    712 			return *str ? stringf("%s %s", ty->u.sym->name, str) : ty->u.sym->name;
    713 		case POINTER:
    714 			if (!ischar(ty->type) && (p = findtype(ty)) != NULL)
    715 				return *str ? stringf("%s %s", p->name, str) : p->name;
    716 			str = stringf(isarray(ty->type) || isfunc(ty->type) ? "(*%s)" : "*%s", str);
    717 			break;
    718 		case FUNCTION:
    719 			if ((p = findtype(ty)) != NULL)
    720 				return *str ? stringf("%s %s", p->name, str) : p->name;
    721 			if (ty->u.f.proto == 0)
    722 				str = stringf("%s()", str);
    723 			else if (ty->u.f.proto[0]) {
    724 				int i;
    725 				str = stringf("%s(%s", str, typestring(ty->u.f.proto[0], ""));
    726 				for (i = 1; ty->u.f.proto[i]; i++)
    727 					if (ty->u.f.proto[i] == voidtype)
    728 						str = stringf("%s, ...", str);
    729 					else
    730 						str = stringf("%s, %s", str, typestring(ty->u.f.proto[i], ""));
    731 				str = stringf("%s)", str);
    732 			} else
    733 				str = stringf("%s(void)", str);
    734 			break;
    735 		case ARRAY:
    736 			if ((p = findtype(ty)) != NULL)
    737 				return *str ? stringf("%s %s", p->name, str) : p->name;
    738 			if (ty->type && ty->type->size > 0)
    739 				str = stringf("%s[%d]", str, ty->size/ty->type->size);
    740 			else
    741 				str = stringf("%s[]", str);
    742 			break;
    743 		default: assert(0);
    744 		}
    745 	}
    746 	assert(0); return 0;
    747 }
    748