plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

type.c (13406B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <bio.h>
      4 #include <mach.h>
      5 #include <ctype.h>
      6 #include "dat.h"
      7 
      8 char *prefix = "";
      9 
     10 static TypeList *thash[1021];
     11 static TypeList *namehash[1021];
     12 static TypeList *alltypes;
     13 
     14 static uint
     15 hash(uint num, uint num1)
     16 {
     17 	return (num*1009 + num1*1013) % nelem(thash);
     18 }
     19 
     20 static uint
     21 shash(char *s)
     22 {
     23 	uint h;
     24 
     25 	h = 0;
     26 	for(; *s; s++)
     27 		h = 37*h + *s;
     28 	return h%nelem(namehash);
     29 }
     30 
     31 void
     32 addnamehash(Type *t)
     33 {
     34 	uint h;
     35 
     36 	if(t->name){
     37 		h = shash(t->name);
     38 		namehash[h] = mktl(t, namehash[h]);
     39 	}
     40 }
     41 
     42 static void
     43 addhash(Type *t)
     44 {
     45 	uint h;
     46 
     47 	if(t->n1 || t->n2){
     48 		h = hash(t->n1, t->n2);
     49 		thash[h] = mktl(t, thash[h]);
     50 	}
     51 	if(t->name)
     52 		addnamehash(t);
     53 }
     54 
     55 Type*
     56 typebysue(char sue, char *name)
     57 {
     58 	Type *t;
     59 	TypeList *tl;
     60 
     61 	for(tl=namehash[shash(name)]; tl; tl=tl->tl){
     62 		t = tl->hd;
     63 		if(t->sue==sue && t->suename && strcmp(name, t->suename)==0)
     64 			return t;
     65 	}
     66 	t = newtype();
     67 	if(sue=='e')
     68 		t->ty = Enum;
     69 	else
     70 		t->ty = Aggr;
     71 	if(sue=='u')
     72 		t->isunion = 1;
     73 	t->sue = sue;
     74 	t->suename = name;
     75 	addnamehash(t);
     76 	return t;
     77 }
     78 
     79 Type*
     80 typebynum(uint n1, uint n2)
     81 {
     82 	Type *t;
     83 	TypeList *tl;
     84 
     85 	if(n1 || n2){
     86 		for(tl=thash[hash(n1, n2)]; tl; tl=tl->tl){
     87 			t = tl->hd;
     88 			if(t->n1==n1 && t->n2==n2)
     89 				return t;
     90 		}
     91 	}
     92 
     93 	t = newtype();
     94 	t->n1 = n1;
     95 	t->n2 = n2;
     96 	addhash(t);
     97 	return t;
     98 }
     99 
    100 Type*
    101 newtype(void)
    102 {
    103 	Type *t;
    104 	static int gen;
    105 
    106 	t = emalloc(sizeof *t);
    107 	t->gen = ++gen;
    108 	alltypes = mktl(t, alltypes);
    109 	return t;
    110 }
    111 
    112 struct {
    113 	char *old;
    114 	char *new;
    115 } fixes[] = { /* Font Tab 4 */
    116 	"append",		"$append",
    117 	"builtin",		"$builtin",
    118 	"complex",		"$complex",
    119 	"delete",		"$delete",
    120 	"do",			"$do",
    121 	"else",			"$else",
    122 	"eval",			"$eval",
    123 	"fmt",			"$fmt",
    124 	"fn",			"$fn",
    125 	"head",			"$head",
    126 	"if",			"$if",
    127 	"local",		"$local",
    128 	"loop",			"$loop",
    129 	"ret",			"$ret",
    130 	"tail",			"$tail",
    131 	"then",			"$then",
    132 	"var",		"$var",
    133 	"whatis",		"$whatis",
    134 	"while",		"$while",
    135 
    136 /* register names! */
    137 	/* generic */
    138 	"PC",		"$PC",
    139 	"SP",		"$SP",
    140 	"LR",		"$LR",
    141 	"R0",		"$R0",
    142 	"R1",		"$R1",
    143 	"R2",		"$R2",
    144 	"R3",		"$R3",
    145 	"R4",		"$R4",
    146 	"R5",		"$R5",
    147 	"R6",		"$R6",
    148 	"R7",		"$R7",
    149 	"R8",		"$R8",
    150 	"R9",		"$R9",
    151 	"R10",		"$R10",
    152 	"R11",		"$R11",
    153 	"R12",		"$R12",
    154 	"R13",		"$R13",
    155 	"R14",		"$R14",
    156 	"R15",		"$R15",
    157 	"R16",		"$R16",
    158 	"R17",		"$R17",
    159 	"R18",		"$R18",
    160 	"R19",		"$R19",
    161 	"R20",		"$R20",
    162 	"R21",		"$R21",
    163 	"R22",		"$R22",
    164 	"R23",		"$R23",
    165 	"R24",		"$R24",
    166 	"R25",		"$R25",
    167 	"R26",		"$R26",
    168 	"R27",		"$R27",
    169 	"R28",		"$R28",
    170 	"R29",		"$R29",
    171 	"R30",		"$R30",
    172 	"R31",		"$R31",
    173 	"E0",		"$E0",
    174 	"E1",		"$E1",
    175 	"E2",		"$E2",
    176 	"E3",		"$E3",
    177 	"E4",		"$E4",
    178 	"E5",		"$E5",
    179 	"E6",		"$E6",
    180 	"F0",		"$F0",
    181 	"F1",		"$F1",
    182 	"F2",		"$F2",
    183 	"F3",		"$F3",
    184 	"F4",		"$F4",
    185 	"F5",		"$F5",
    186 	"F6",		"$F6",
    187 	"F7",		"$F7",
    188 	"F8",		"$F8",
    189 	"F9",		"$F9",
    190 	"F10",		"$F10",
    191 	"F11",		"$F11",
    192 	"F12",		"$F12",
    193 	"F13",		"$F13",
    194 	"F14",		"$F14",
    195 	"F15",		"$F15",
    196 	"F16",		"$F16",
    197 	"F17",		"$F17",
    198 	"F18",		"$F18",
    199 	"F19",		"$F19",
    200 	"F20",		"$F20",
    201 	"F21",		"$F21",
    202 	"F22",		"$F22",
    203 	"F23",		"$F23",
    204 	"F24",		"$F24",
    205 	"F25",		"$F25",
    206 	"F26",		"$F26",
    207 	"F27",		"$F27",
    208 	"F28",		"$F28",
    209 	"F29",		"$F29",
    210 	"F30",		"$F30",
    211 	"F31",		"$F31",
    212 
    213 	/* 386 */
    214 	"DI",		"$DI",
    215 	"SI",		"$SI",
    216 	"BP",		"$BP",
    217 	"BX",		"$BX",
    218 	"DX",		"$DX",
    219 	"CX",		"$CX",
    220 	"AX",		"$AX",
    221 	"GS",		"$GS",
    222 	"FS",		"$FS",
    223 	"ES",		"$ES",
    224 	"DS",		"$DS",
    225 	"TRAP",		"$TRAP",
    226 	"ECODE",		"$ECODE",
    227 	"CS",		"$CS",
    228 	"EFLAGS",		"$EFLAGS",
    229 	"SS",		"$SS",
    230 
    231 	/* power */
    232 	"CAUSE",		"$CAUSE",
    233 	"SRR1",		"$SRR1",
    234 	"CR",		"$CR",
    235 	"XER",		"$XER",
    236 	"CTR",		"$CTR",
    237 	"VRSAVE",		"$VRSAVE",
    238 	"FPSCR",		"$FPSCR"
    239 };
    240 
    241 char*
    242 nonempty(char *name)
    243 {
    244 	if(name[0] == '\0')
    245 		return "__empty__name__";
    246 	return name;
    247 }
    248 
    249 char*
    250 cleanstl(char *name)
    251 {
    252 	char *b, *p;
    253 	static char buf[65536];	/* These can be huge. */
    254 
    255 	if(strchr(name, '<') == nil)
    256 		return nonempty(name);
    257 
    258 	b = buf;
    259 	for(p = name; *p != 0; p++){
    260 		switch(*p){
    261 		case '<':
    262 			strcpy(b, "_L_");
    263 			b += 3;
    264 			break;
    265 		case '>':
    266 			strcpy(b, "_R_");
    267 			b += 3;
    268 			break;
    269 		case '*':
    270 			strcpy(b, "_A_");
    271 			b += 3;
    272 			break;
    273 		case ',':
    274 			strcpy(b, "_C_");
    275 			b += 3;
    276 			break;
    277 		case '.':
    278 			strcpy(b, "_D_");
    279 			b += 3;
    280 			break;
    281 		default:
    282 			*b++ = *p;
    283 			break;
    284 		}
    285 	}
    286 	*b = 0;
    287 	return buf;
    288 }
    289 
    290 char*
    291 fixname(char *name)
    292 {
    293 	int i;
    294 	char *s;
    295 	static int nbuf;
    296 	static char buf[8][65536];
    297 
    298 	if(name == nil)
    299 		return nil;
    300 	s = demangle(name, buf[nbuf], 1);
    301 	if(s != name){
    302 		if(++nbuf == nelem(buf))
    303 			nbuf = 0;
    304 		name = s;
    305 	}
    306 	for(i=0; i<nelem(fixes); i++)
    307 		if(name[0]==fixes[i].old[0] && strcmp(name, fixes[i].old)==0)
    308 			return nonempty(fixes[i].new);
    309 	return nonempty(name);
    310 }
    311 
    312 void
    313 denumber(void)
    314 {
    315 	memset(thash, 0, sizeof thash);
    316 	memset(namehash, 0, sizeof namehash);
    317 }
    318 
    319 void
    320 renumber(TypeList *tl, uint n1)
    321 {
    322 	int n;
    323 	Type *t, *tt;
    324 
    325 	for(; tl; tl=tl->tl){
    326 		t = tl->hd;
    327 		tt = typebynum(n1, t->n2);
    328 		*tt = *t;
    329 		tt->n1 = n1;
    330 		if(tt->n){
    331 			n = (tt->n+31)&~31;
    332 			if(tt->tname){
    333 				tt->tname = emalloc(n*sizeof tt->tname[0]);
    334 				memmove(tt->tname, t->tname, n*sizeof tt->tname[0]);
    335 			}
    336 			if(tt->val){
    337 				tt->val = emalloc(n*sizeof tt->val[0]);
    338 				memmove(tt->val, t->val, n*sizeof tt->val[0]);
    339 			}
    340 			if(tt->t){
    341 				tt->t = emalloc(n*sizeof tt->t[0]);
    342 				memmove(tt->t, t->t, n*sizeof tt->t[0]);
    343 			}
    344 		}
    345 		addhash(tt);
    346 	}
    347 }
    348 
    349 Type*
    350 defer(Type *t)
    351 {
    352 	Type *u, *oldt;
    353 	int n;
    354 
    355 	if(t == nil)
    356 		return nil;
    357 
    358 /* XXX rob has return t; here */
    359 	u = t;
    360 	n = 0;
    361 	oldt = t;
    362 	while(t && (t->ty == Defer || t->ty == Typedef)){
    363 		if(n++%2)
    364 			u = u->sub;
    365 		t = t->sub;
    366 		if(t == u)	/* cycle */
    367 			goto cycle;
    368 	}
    369 	if(oldt != t)
    370 		oldt->sub = t;
    371 	return t;
    372 
    373 cycle:
    374 	fprint(2, "cycle\n");
    375 	t = oldt;
    376 	n = 0;
    377 	while(t && (t->ty==Defer || t->ty==Typedef)){
    378 		fprint(2, "t %p/%d %s\n", t, t->ty, t->name);
    379 		if(t == u && n++ == 2)
    380 			break;
    381 		t = t->sub;
    382 	}
    383 	return u;
    384 }
    385 
    386 static void
    387 dotypedef(Type *t)
    388 {
    389 	if(t->ty != Typedef && t->ty != Defer)
    390 		return;
    391 
    392 	if(t->didtypedef)
    393 		return;
    394 
    395 	t->didtypedef = 1;
    396 	if(t->sub == nil)
    397 		return;
    398 
    399 	/* push names downward to remove anonymity */
    400 	if(t->name && t->sub->name == nil)
    401 		t->sub->name = t->name;
    402 
    403 	dotypedef(t->sub);
    404 }
    405 
    406 static int
    407 countbytes(uvlong x)
    408 {
    409 	int n;
    410 
    411 	for(n=0; x; n++)
    412 		x>>=8;
    413 	return n;
    414 }
    415 
    416 static void
    417 dorange(Type *t)
    418 {
    419 	Type *tt;
    420 
    421 	if(t->ty != Range)
    422 		return;
    423 	if(t->didrange)
    424 		return;
    425 	t->didrange = 1;
    426 	tt = defer(t->sub);
    427 	if(tt == nil)
    428 		return;
    429 	dorange(tt);
    430 	if(t != tt && tt->ty != Base)
    431 		return;
    432 	t->ty = Base;
    433 	t->xsizeof = tt->xsizeof;
    434 	if(t->lo == 0)
    435 		t->printfmt = 'x';
    436 	else
    437 		t->printfmt = 'd';
    438 	if(t->xsizeof == 0)
    439 		t->xsizeof = countbytes(t->hi);
    440 }
    441 
    442 char*
    443 mkname(char *prefix, char *name)
    444 {
    445 	static char buf[65536];
    446 
    447 	snprint(buf, sizeof buf, "%s%s", prefix, name);
    448 	return buf;
    449 }
    450 
    451 char*
    452 nameof(Type *t, int doanon)
    453 {
    454 	static char buf[65536];
    455 	char *p;
    456 
    457 	if(t->name)
    458 		strcpy(buf, fixname(t->name));
    459 	else if(t->suename)
    460 		snprint(buf, sizeof buf, "%s_%s", t->isunion ? "union" : "struct", t->suename);
    461 	else if(doanon)
    462 		snprint(buf, sizeof buf, "%s_%lud_", prefix, t->gen);
    463 	else
    464 		return "";
    465 	for(p=buf; *p; p++)
    466 		if(isspace((uchar)*p))
    467 			*p = '_';
    468 	return buf;
    469 }
    470 
    471 static char
    472 basecharof(Type *t)	/*XXX */
    473 {
    474 	switch(t->xsizeof){
    475 	default:
    476 		return 'X';
    477 	case 1:
    478 		return 'b';
    479 	case 2:
    480 		if(t->printfmt=='d')
    481 			return 'd';
    482 		else
    483 			return 'x';
    484 	case 4:
    485 		if(t->printfmt=='d')
    486 			return 'D';
    487 		else if(t->printfmt=='f')
    488 			return 'f';
    489 		else
    490 			return 'X';
    491 	case 8:
    492 		if(t->printfmt=='d')
    493 			return 'V';
    494 		else if(t->printfmt=='f')
    495 			return 'F';
    496 		else
    497 			return 'Y';
    498 	}
    499 }
    500 
    501 static int
    502 nilstrcmp(char *a, char *b)
    503 {
    504 	if(a == b)
    505 		return 0;
    506 	if(a == nil)
    507 		return -1;
    508 	if(b == nil)
    509 		return 1;
    510 	return strcmp(a, b);
    511 }
    512 
    513 int careaboutaggrcount;
    514 
    515 static int
    516 typecmp(Type *t, Type *u)
    517 {
    518 	int i;
    519 
    520 	if(t == u)
    521 		return 0;
    522 	if(t == nil)
    523 		return -1;
    524 	if(u == nil)
    525 		return 1;
    526 
    527 	if(t->ty < u->ty)
    528 		return -1;
    529 	if(t->ty > u->ty)
    530 		return 1;
    531 
    532 	if(t->isunion != u->isunion)
    533 		return t->isunion - u->isunion;
    534 
    535 	i = nilstrcmp(t->name, u->name);
    536 	if(i)
    537 		return i;
    538 
    539 	i = nilstrcmp(t->suename, u->suename);
    540 	if(i)
    541 		return i;
    542 
    543 	if(careaboutaggrcount && t->ty == Aggr){
    544 		if(t->n > u->n)
    545 			return -1;
    546 		if(t->n < u->n)
    547 			return 1;
    548 	}
    549 
    550 	if(t->name || t->suename)
    551 		return 0;
    552 
    553 	if(t->ty==Enum){
    554 		if(t->n < u->n)
    555 			return -1;
    556 		if(t->n > u->n)
    557 			return 1;
    558 		if(t->n == 0)
    559 			return 0;
    560 		i = strcmp(t->tname[0], u->tname[0]);
    561 		return i;
    562 	}
    563 	if(t < u)
    564 		return -1;
    565 	if(t > u)
    566 		return 1;
    567 	return 0;
    568 }
    569 
    570 static int
    571 qtypecmp(const void *va, const void *vb)
    572 {
    573 	Type *t, *u;
    574 
    575 	t = *(Type**)va;
    576 	u = *(Type**)vb;
    577 	return typecmp(t, u);
    578 }
    579 
    580 void
    581 printtype(Biobuf *b, Type *t)
    582 {
    583 	char *name;
    584 	int j, nprint;
    585 	Type *tt, *ttt;
    586 
    587 	if(t->printed)
    588 		return;
    589 	t->printed = 1;
    590 	switch(t->ty){
    591 	case Aggr:
    592 		name = nameof(t, 1);
    593 		Bprint(b, "%B = %lud;\n", mkname("sizeof", name), t->xsizeof);
    594 		Bprint(b, "aggr %B {\n", name);
    595 		nprint = 0;
    596 		for(j=0; j<t->n; j++){
    597 			tt = defer(t->t[j]);
    598 			if(tt && tt->equiv)
    599 				tt = tt->equiv;
    600 			if(tt == nil){
    601 				Bprint(b, "// oops: nil type\n");
    602 				continue;
    603 			}
    604 			switch(tt->ty){
    605 			default:
    606 				Bprint(b, "// oops: unknown type %d for %p/%s (%d,%d; %c,%s; %p)\n",
    607 					tt->ty, tt, fixname(t->tname[j]),
    608 					tt->n1, tt->n2, tt->sue ? tt->sue : '.', tt->suename, tt->sub);
    609 if(0){
    610 Bprint(b, "// t->t[j] = %p\n", ttt=t->t[j]);
    611 while(ttt){
    612 Bprint(b, "// %s %d (%d,%d) sub %p\n", ttt->name, ttt->ty, ttt->n1, ttt->n2, ttt->sub);
    613 ttt=ttt->sub;
    614 }
    615 }
    616 			case Base:
    617 			case Pointer:
    618 			case Enum:
    619 			case Array:
    620 			case Function:
    621 				nprint++;
    622 				Bprint(b, "\t'%c' %lud %B;\n", basecharof(tt), t->val[j], fixname(t->tname[j]));
    623 				break;
    624 			case Aggr:
    625 				nprint++;
    626 				Bprint(b, "\t%B %lud %B;\n", nameof(tt, 1), t->val[j], fixname(t->tname[j]));
    627 				break;
    628 			}
    629 		}
    630 		if(nprint == 0)
    631 			Bprint(b, "\t'X' 0 __dummy;\n");
    632 		Bprint(b, "};\n\n");
    633 
    634 		name = nameof(t, 1);	/* might have smashed it */
    635 		Bprint(b, "defn %B(addr) { %B(addr, \"\"); }\n", name, mkname("indent_", name));
    636 		Bprint(b, "defn %B(addr, indent) {\n", mkname("indent_", name));
    637 		Bprint(b, "\tcomplex %B addr;\n", name);
    638 		for(j=0; j<t->n; j++){
    639 			name = fixname(t->tname[j]);
    640 			tt = defer(t->t[j]);
    641 			if(tt == nil){
    642 				Bprint(b, "// oops nil %s\n", name);
    643 				continue;
    644 			}
    645 			switch(tt->ty){
    646 			case Base:
    647 			base:
    648 				Bprint(b, "\tprint(indent, \"%s\t\", addr.%B, \"\\n\");\n",
    649 					name, name);
    650 				break;
    651 			case Pointer:
    652 				ttt = defer(tt->sub);
    653 				if(ttt && ttt->ty == Aggr)
    654 					Bprint(b, "\tprint(indent, \"%s\t(%s)\", addr.%B, \"\\n\");\n",
    655 						name, nameof(ttt, 1), name);
    656 				else
    657 					goto base;
    658 				break;
    659 			case Array:
    660 				Bprint(b, "\tprint(indent, \"%s\t\", addr.%B\\X, \"\\n\");\n",
    661 					name, name);
    662 				break;
    663 			case Enum:
    664 				Bprint(b, "\tprint(indent, \"%s\t\", addr.%B, \" \", %B(addr.%B), \"\\n\");\n",
    665 					name, name, nameof(tt, 1), name);
    666 				break;
    667 			case Aggr:
    668 				Bprint(b, "\tprint(indent, \"%s\t%s{\\n\");\n",
    669 					name, nameof(tt, 0));
    670 				Bprint(b, "\t%B(addr+%lud, indent+\"  \");\n",
    671 					mkname("indent_", nameof(tt, 1)), t->val[j]);
    672 				Bprint(b, "\tprint(indent, \"}\\n\");\n");
    673 				break;
    674 			}
    675 		}
    676 		Bprint(b, "};\n\n");
    677 		break;
    678 
    679 	case Enum:
    680 		name = nameof(t, 1);
    681 		Bprint(b, "// enum %s\n", name);
    682 		for(j=0; j<t->n; j++)
    683 			Bprint(b, "%B = %ld;\n", fixname(t->tname[j]), t->val[j]);
    684 
    685 		Bprint(b, "%B = {\n", mkname("vals_", name));
    686 		for(j=0; j<t->n; j++)
    687 			Bprint(b, "\t%lud,\n", t->val[j]);
    688 		Bprint(b, "};\n");
    689 		Bprint(b, "%B = {\n", mkname("names_", name));
    690 		for(j=0; j<t->n; j++)
    691 			Bprint(b, "\t\"%s\",\n", fixname(t->tname[j]));
    692 		Bprint(b, "};\n");
    693 		Bprint(b, "defn %B(val) {\n", name);
    694 		Bprint(b, "\tlocal i;\n");
    695 		Bprint(b, "\ti = match(val, %B);\n", mkname("vals_", name));
    696 		Bprint(b, "\tif i >= 0 then return %B[i];\n", mkname("names_", name));
    697 		Bprint(b, "\treturn \"???\";\n");
    698 		Bprint(b, "};\n");
    699 		break;
    700 	}
    701 }
    702 
    703 void
    704 printtypes(Biobuf *b)
    705 {
    706 	int i, n, nn;
    707 	Type *t, *tt, **all;
    708 	TypeList *tl;
    709 
    710 	/* check that pointer resolved */
    711 	for(tl=alltypes; tl; tl=tl->tl){
    712 		t = tl->hd;
    713 		if(t->ty==None){
    714 			if(t->n1 || t->n2)
    715 				warn("type %d,%d referenced but not defined - %p", t->n1, t->n2, t);
    716 			else if(t->sue && t->suename)
    717 				warn("%s %s referenced but not defined",
    718 					t->sue=='s' ? "struct" :
    719 					t->sue=='u' ? "union" :
    720 					t->sue=='e' ? "enum" : "???", t->suename);
    721 		}
    722 	}
    723 
    724 	/* push typedefs down, base types up */
    725 	n = 0;
    726 	for(tl=alltypes; tl; tl=tl->tl){
    727 		n++;
    728 		t = tl->hd;
    729 		if(t->ty == Typedef || t->ty == Defer)
    730 			dotypedef(t);
    731 	}
    732 
    733 	/* push ranges around */
    734 	for(tl=alltypes; tl; tl=tl->tl)
    735 		dorange(tl->hd);
    736 
    737 	/*
    738 	 * only take one type of a given name; acid is going to do this anyway,
    739 	 * and this will reduce the amount of code we output considerably.
    740 	 * we could run a DFA equivalence relaxation sort of algorithm
    741 	 * to find the actual equivalence classes, and then rename types
    742 	 * appropriately, but this will do for now.
    743 	 */
    744 	all = emalloc(n*sizeof(all[0]));
    745 	n = 0;
    746 	for(tl=alltypes; tl; tl=tl->tl)
    747 		all[n++] = tl->hd;
    748 
    749 	careaboutaggrcount = 1;
    750 	qsort(all, n, sizeof(all[0]), qtypecmp);
    751 	careaboutaggrcount = 0;
    752 
    753 	nn = 0;
    754 	for(i=0; i<n; i++){
    755 		if(i==0 || typecmp(all[i-1], all[i]) != 0)
    756 			all[nn++] = all[i];
    757 		else
    758 			all[i]->equiv = all[nn-1];
    759 	}
    760 
    761 	for(tl=alltypes; tl; tl=tl->tl){
    762 		t = tl->hd;
    763 		tt = defer(t);
    764 		if(tt && tt->equiv)
    765 			t->equiv = tt->equiv;
    766 	}
    767 
    768 	for(i=0; i<nn; i++)
    769 		printtype(b, all[i]);
    770 
    771 	free(all);
    772 }
    773 
    774 void
    775 freetypes(void)
    776 {
    777 	memset(thash, 0, sizeof(thash));
    778 	memset(namehash, 0, sizeof namehash);
    779 }