plan9port

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

stabs.c (15296B)


      1 #include <u.h>
      2 #include <errno.h>
      3 #include <libc.h>
      4 #include <bio.h>
      5 #include <mach.h>
      6 #include <stabs.h>
      7 #include <ctype.h>
      8 #include "dat.h"
      9 
     10 static jmp_buf kaboom;
     11 
     12 static Type *parsename(char*, char**);
     13 static Type *parseinfo(char*, char**);
     14 static int parsenum(char*, int*, int*, char**);
     15 static int parseattr(char*, char**, char**);
     16 static Type *parsedefn(char *p, Type *t, char **pp);
     17 static int parsebound(char**);
     18 static vlong parsebigint(char**);
     19 
     20 typedef struct Ftypes Ftypes;
     21 struct Ftypes
     22 {
     23 	Ftypes *down;
     24 	Ftypes *next;
     25 	char *file;
     26 	TypeList *list;
     27 };
     28 
     29 Ftypes *fstack;
     30 Ftypes *allftypes;
     31 
     32 static char*
     33 estrndup(char *s, int n)
     34 {
     35 	char *t;
     36 
     37 	t = emalloc(n+1);
     38 	memmove(t, s, n);
     39 	return t;
     40 }
     41 
     42 static char*
     43 mkpath(char *dir, char *name)
     44 {
     45 	char *s;
     46 	if(name[0] == '/' || dir == nil)
     47 		return estrdup(name);
     48 	else{
     49 		s = emalloc(strlen(dir)+strlen(name)+1);
     50 		strcpy(s, dir);
     51 		strcat(s, name);
     52 		return s;
     53 	}
     54 }
     55 
     56 static Ftypes*
     57 mkftypes(char *dir, char *name)
     58 {
     59 	Ftypes *f;
     60 
     61 	f = emalloc(sizeof(*f));
     62 	f->file = mkpath(dir, name);
     63 	f->next = allftypes;
     64 	allftypes = f;
     65 	return f;
     66 }
     67 
     68 static Ftypes*
     69 findftypes(char *dir, char *name)
     70 {
     71 	char *s;
     72 	Ftypes *f, *found;
     73 
     74 	found = nil;
     75 	s = mkpath(dir, name);
     76 	for(f=allftypes; f; f=f->next)
     77 		if(strcmp(f->file, s) == 0)
     78 			found = f;
     79 	return found;
     80 }
     81 
     82 static void
     83 oops(void)
     84 {
     85 	longjmp(kaboom, 1);
     86 }
     87 
     88 /* find a : but skip over :: */
     89 static char*
     90 findcolon(char *p)
     91 {
     92 	while((p = strchr(p, ':')) != nil && *(p+1) == ':')
     93 		p += 2;
     94 	if(p == nil)
     95 		oops();
     96 	return p;
     97 }
     98 
     99 static void
    100 semi(char **p)
    101 {
    102 	if(**p != ';')
    103 		oops();
    104 	(*p)++;
    105 }
    106 
    107 static void
    108 comma(char **p)
    109 {
    110 	if(**p != ',')
    111 		oops();
    112 	(*p)++;
    113 }
    114 
    115 static int
    116 parseint(char **pp)
    117 {
    118 	if(!isdigit((uchar)**pp))
    119 		oops();
    120 	return strtol(*pp, pp, 10);
    121 }
    122 
    123 /*
    124 	name ::= symbol_opt info
    125  */
    126 static Type*
    127 parsename(char *desc, char **pp)
    128 {
    129 	if(*desc == 'c')
    130 		return nil;
    131 
    132 	if(isdigit((uchar)*desc) || *desc=='-' || *desc=='(')
    133 		return parseinfo(desc, pp);
    134 	if(*desc == 0)
    135 		oops();
    136 	return parseinfo(desc+1, pp);
    137 }
    138 
    139 /*
    140 	info ::= num | num '=' attr* defn
    141  */
    142 static Type*
    143 parseinfo(char *desc, char **pp)
    144 {
    145 	int n1, n2;
    146 	Type *t;
    147 	char *attr;
    148 
    149 	n1 = n2 = 0;
    150 	parsenum(desc, &n1, &n2, &desc);
    151 	t = typebynum(n1, n2);
    152 	if(*desc != '='){
    153 		*pp = desc;
    154 		return t;
    155 	}
    156 	desc++;
    157 	if(fstack)
    158 		fstack->list = mktl(t, fstack->list);
    159 	while(parseattr(desc, &attr, &desc) >= 0){
    160 		if(*attr == 's')
    161 			t->xsizeof = atoi(attr+1)/8;
    162 	}
    163 	return parsedefn(desc, t, pp);
    164 }
    165 
    166 /*
    167 	num ::= integer | '(' integer ',' integer ')'
    168 */
    169 static int
    170 parsenum(char *p, int *n1, int *n2, char **pp)
    171 {
    172 	if(isdigit((uchar)*p)){
    173 		*n1 = strtol(p, &p, 10);
    174 		*n2 = 0;
    175 		*pp = p;
    176 		return 0;
    177 	}
    178 	if(*p == '('){
    179 		*n1 = strtol(p+1, &p, 10);
    180 		if(*p != ',')
    181 			oops();
    182 		*n2 = strtol(p+1, &p, 10);
    183 		if(*p != ')')
    184 			oops();
    185 		*pp = p+1;
    186 		return 0;
    187 	}
    188 	oops();
    189 	return -1;
    190 }
    191 
    192 /*
    193 	attr ::= '@' text ';'
    194 
    195 	text is
    196 		'a' integer (alignment)
    197 		'p' integer (pointer class)
    198 		'P' (packed type)
    199 		's' integer (size of type in bits)
    200 		'S' (string instead of array of chars)
    201 */
    202 static int
    203 parseattr(char *p, char **text, char **pp)
    204 {
    205 	if(*p != '@')
    206 		return -1;
    207 	*text = p+1;
    208 	if((p = strchr(p, ';')) == nil)
    209 		oops();
    210 	*pp = p+1;
    211 	return 0;
    212 }
    213 
    214 
    215 typedef struct Basic Basic;
    216 struct Basic
    217 {
    218 	int size;
    219 	int fmt;
    220 };
    221 
    222 static Basic baseints[] =
    223 {
    224 	0, 0,
    225 /*1*/	4, 'd',	/* int32 */
    226 /*2*/	1, 'd',	/* char8 */
    227 /*3*/	2, 'd',	/* int16 */
    228 /*4*/	4, 'd',	/* long int32 */
    229 /*5*/	1, 'x',	/* uchar8 */
    230 /*6*/	1, 'd',	/* schar8 */
    231 /*7*/	2, 'x',	/* uint16 */
    232 /*8*/	4, 'x',	/* uint32 */
    233 /*9*/	4, 'x',	/* uint32 */
    234 /*10*/	4, 'x',	/* ulong32 */
    235 /*11*/	0, 0,		/* void */
    236 /*12*/	4, 'f',		/* float */
    237 /*13*/	8, 'f',		/* double */
    238 /*14*/	10, 'f',	/* long double */
    239 /*15*/	4, 'd',	/* int32 */
    240 /*16*/	4, 'd',	/* bool32 */
    241 /*17*/	2, 'f',		/* short real */
    242 /*18*/	4, 'f',		/* real */
    243 /*19*/	4, 'x',	/* stringptr */
    244 /*20*/	1, 'd',	/* character8 */
    245 /*21*/	1, 'x',	/* logical*1 */
    246 /*22*/	2, 'x',	/* logical*2 */
    247 /*23*/	4, 'X',	/* logical*4 */
    248 /*24*/	4, 'X',	/* logical32 */
    249 /*25*/	8, 'F',		/* complex (two single) */
    250 /*26*/	16, 'F',	/* complex (two double) */
    251 /*27*/	1, 'd',	/* integer*1 */
    252 /*28*/	2, 'd',	/* integer*2 */
    253 /*29*/	4, 'd',	/* integer*4 */
    254 /*30*/	2, 'x',	/* wide char */
    255 /*31*/	8, 'd',	/* int64 */
    256 /*32*/	8, 'x',	/* uint64 */
    257 /*33*/	8, 'x',	/* logical*8 */
    258 /*34*/	8, 'd',	/* integer*8 */
    259 };
    260 
    261 static Basic basefloats[] =
    262 {
    263 	0,0,
    264 /*1*/	4, 'f',	/* 32-bit */
    265 /*2*/	8, 'f',	/* 64-bit */
    266 /*3*/	8, 'F',	/* complex */
    267 /*4*/	4, 'F',	/* complex16 */
    268 /*5*/	8, 'F', /* complex32 */
    269 /*6*/	10, 'f',	/* long double */
    270 };
    271 
    272 /*
    273 	defn ::= info
    274 		| 'b' ('u' | 's') 'c'? width; offset; nbits; 		(builtin, signed/unsigned, char/not, width in bytes, offset & nbits of type)
    275 		| 'w'		(aix wide char type, not used)
    276 		| 'R' fptype; bytes;			(fptype 1=32-bit, 2=64-bit, 3=complex, 4=complex16, 5=complex32, 6=long double)
    277 		| 'g' typeinfo ';' nbits 		(aix floating, not used)
    278 		| 'c' typeinfo ';' nbits		(aix complex, not used)
    279 		| 'b' typeinfo ';' bytes		(ibm, no idea)
    280 		| 'B' typeinfo		(volatile typref)
    281 		| 'd' typeinfo		(file of typeref)
    282 		| 'k' typeinfo		(const typeref)
    283 		| 'M' typeinfo ';' length		(multiple instance type, fortran)
    284 		| 'S' typeinfo		(set, typeref must have small number of values)
    285 		| '*' typeinfo		(pointer to typeref)
    286 		| 'x' ('s'|'u'|'e') name ':'	(struct, union, enum reference.  name can have '::' in it)
    287 		| 'r' typeinfo ';' low ';' high ';'		(subrange.  typeref can be type being defined for base types!)
    288 				low and high are bounds
    289 				if bound is octal power of two, it's a big negative number
    290 		| ('a'|'P') indextypedef arraytypeinfo 	(array, index should be range type)
    291 					indextype is type definition not typeinfo (need not say typenum=)
    292 					P means packed array
    293 		| 'A' arraytypeinfo		(open array (no index bounds))
    294 		| 'D' dims ';' typeinfo		(dims-dimensional dynamic array)
    295 		| 'E' dims ';' typeinfo		(subarray of N-dimensional array)
    296 		| 'n' typeinfo ';' bytes		(max length string)
    297 		| 'z' typeinfo ';' bytes		(no idea what difference is from 'n')
    298 		| 'N'					(pascal stringptr)
    299 		| 'e' (name ':' bigint ',')* ';'	(enum listing)
    300 		| ('s'|'u') bytes (name ':' type ',' bitoffset ',' bitsize ';')* ';'		(struct/union defn)
    301 							tag is given as name in stabs entry, with 'T' symbol
    302 		| 'f' typeinfo ';' 			(function returning type)
    303 		| 'f' rettypeinfo ',' paramcount ';' (typeinfo ',' (0|1) ';')* ';'
    304 		| 'p' paramcount ';' (typeinfo ',' (0|1) ';')* ';'
    305 		| 'F' rettypeinfo ',' paramcount ';' (name ':' typeinfo ',' (0|1) ';')* ';'
    306 		| 'R' paramcount ';' (name ':' typeinfo ',' (0|1) ';')* ';'
    307 							(the 0 or 1 is pass-by-reference vs pass-by-value)
    308 							(the 0 or 1 is pass-by-reference vs pass-by-value)
    309 */
    310 
    311 static Type*
    312 parsedefn(char *p, Type *t, char **pp)
    313 {
    314 	char c, *name;
    315 	int ischar, namelen, n, wid, offset, bits, sign;
    316 	long val;
    317 	Type *tt;
    318 
    319 	if(*p == '(' || isdigit((uchar)*p)){
    320 		t->ty = Defer;
    321 		t->sub = parseinfo(p, pp);
    322 		return t;
    323 	}
    324 
    325 	switch(c = *p){
    326 	case '-':	/* builtin */
    327 		n = strtol(p+1, &p, 10);
    328 		if(n >= nelem(baseints) || n < 0)
    329 			n = 0;
    330 		t->ty = Base;
    331 		t->xsizeof = baseints[n].size;
    332 		t->printfmt = baseints[n].fmt;
    333 		break;
    334 	case 'b':	/* builtin */
    335 		p++;
    336 		if(*p != 'u' && *p != 's')
    337 			oops();
    338 		sign = (*p == 's');
    339 		p++;
    340 		ischar = 0;
    341 		if(*p == 'c'){
    342 			ischar = 1;
    343 			p++;
    344 		}
    345 		wid = parseint(&p);
    346 		semi(&p);
    347 		offset = parseint(&p);
    348 		semi(&p);
    349 		bits = parseint(&p);
    350 		semi(&p);
    351 		t->ty = Base;
    352 		t->xsizeof = wid;
    353 		if(sign == 1)
    354 			t->printfmt = 'd';
    355 		else
    356 			t->printfmt = 'x';
    357 		USED(bits);
    358 		USED(ischar);
    359 		break;
    360 	case 'R':	/* fp type */
    361 		n = parseint(&p);
    362 		semi(&p);
    363 		wid = parseint(&p);
    364 		semi(&p);
    365 		t->ty = Base;
    366 		t->xsizeof = wid;
    367 		if(n < 0 || n >= nelem(basefloats))
    368 			n = 0;
    369 		t->xsizeof = basefloats[n].size;
    370 		t->printfmt = basefloats[n].fmt;
    371 		break;
    372 	case 'r':	/* subrange */
    373 		t->ty = Range;
    374 		t->sub = parseinfo(p+1, &p);
    375 		if(*(p-1) == ';' && *p != ';')
    376 			p--;
    377 		semi(&p);
    378 		t->lo = parsebound(&p);
    379 		semi(&p);
    380 		t->hi = parsebound(&p);
    381 		semi(&p);
    382 		break;
    383 	case 'B':	/* volatile */
    384 	case 'k':	/* const */
    385 		t->ty = Defer;
    386 		t->sub = parseinfo(p+1, &p);
    387 		break;
    388 	case '*':	/* pointer */
    389 	case 'A':	/* open array */
    390 	case '&':	/* reference */	/* guess - C++? (rob) */
    391 		t->ty = Pointer;
    392 		t->sub = parseinfo(p+1, &p);
    393 		break;
    394 	case 'a':	/* array */
    395 	case 'P':	/* packed array */
    396 		t->ty = Pointer;
    397 		tt = newtype();
    398 		parsedefn(p+1, tt, &p);	/* index type */
    399 		if(*p == ';')
    400 			p++;
    401 		tt = newtype();
    402 		t->sub = tt;
    403 		parsedefn(p, tt, &p);	/* element type */
    404 		break;
    405 	case 'e':	/* enum listing */
    406 		p++;
    407 		t->sue = 'e';
    408 		t->ty = Enum;
    409 		while(*p != ';'){
    410 			name = p;
    411 			p = findcolon(p)+1;
    412 			namelen = (p-name)-1;
    413 			val = parsebigint(&p);
    414 			comma(&p);
    415 			if(t->n%32 == 0){
    416 				t->tname = erealloc(t->tname, (t->n+32)*sizeof(t->tname[0]));
    417 				t->val = erealloc(t->val, (t->n+32)*sizeof(t->val[0]));
    418 			}
    419 			t->tname[t->n] = estrndup(name, namelen);
    420 			t->val[t->n] = val;
    421 			t->n++;
    422 		}
    423 		semi(&p);
    424 		break;
    425 
    426 	case 's':	/* struct */
    427 	case 'u':	/* union */
    428 		p++;
    429 		t->sue = c;
    430 		t->ty = Aggr;
    431 		n = parseint(&p);
    432 		while(*p != ';'){
    433 			name = p;
    434 			p = findcolon(p)+1;
    435 			namelen = (p-name)-1;
    436 			tt = parseinfo(p, &p);
    437 			comma(&p);
    438 			offset = parseint(&p);
    439 			comma(&p);
    440 			bits = parseint(&p);
    441 			semi(&p);
    442 			if(t->n%32 == 0){
    443 				t->tname = erealloc(t->tname, (t->n+32)*sizeof(t->tname[0]));
    444 				t->val = erealloc(t->val, (t->n+32)*sizeof(t->val[0]));
    445 				t->t = erealloc(t->t, (t->n+32)*sizeof(t->t[0]));
    446 			}
    447 			t->tname[t->n] = estrndup(name, namelen);
    448 			t->val[t->n] = offset;
    449 			t->t[t->n] = tt;
    450 			t->n++;
    451 		}
    452 		semi(&p);
    453 		break;
    454 
    455 	case 'x':	/* struct, union, enum reference */
    456 		p++;
    457 		t->ty = Defer;
    458 		if(*p != 's' && *p != 'u' && *p != 'e')
    459 			oops();
    460 		c = *p;
    461 		name = p+1;
    462 		p = findcolon(p+1);
    463 		name = estrndup(name, p-name);
    464 		t->sub = typebysue(c, name);
    465 		p++;
    466 		break;
    467 
    468 #if 0	/* AIX */
    469 	case 'f':	/* function */
    470 	case 'p':	/* procedure */
    471 	case 'F':	/* Pascal function */
    472 	/* case 'R':	/* Pascal procedure */
    473 		/*
    474 		 * Even though we don't use the info, we have
    475 		 * to parse it in case it is embedded in other descriptions.
    476 		 */
    477 		t->ty = Function;
    478 		p++;
    479 		if(c == 'f' || c == 'F'){
    480 			t->sub = parseinfo(p, &p);
    481 			if(*p != ','){
    482 				if(*p == ';')
    483 					p++;
    484 				break;
    485 			}
    486 			comma(&p);
    487 		}
    488 		n = parseint(&p);	/* number of params */
    489 		semi(&p);
    490 		while(*p != ';'){
    491 			if(c == 'F' || c == 'R'){
    492 				name = p;		/* parameter name */
    493 				p = findcolon(p)+1;
    494 			}
    495 			parseinfo(p, &p);	/* param type */
    496 			comma(&p);
    497 			parseint(&p);	/* bool: passed by value? */
    498 			semi(&p);
    499 		}
    500 		semi(&p);
    501 		break;
    502 #endif
    503 
    504 	case 'f':	/* static function */
    505 	case 'F':	/* global function */
    506 		t->ty = Function;
    507 		p++;
    508 		t->sub = parseinfo(p, &p);
    509 		break;
    510 
    511 	/*
    512 	 * We'll never see any of this stuff.
    513 	 * When we do, we can worry about it.
    514 	 */
    515 	case 'D':	/* n-dimensional array */
    516 	case 'E':	/* subarray of n-dimensional array */
    517 	case 'M':	/* fortran multiple instance type */
    518 	case 'N':	/* pascal string ptr */
    519 	case 'S':	/* set */
    520 	case 'c':	/* aix complex */
    521 	case 'd':	/* file of */
    522 	case 'g':	/* aix float */
    523 	case 'n':	/* max length string */
    524 	case 'w':	/* aix wide char */
    525 	case 'z':	/* another max length string */
    526 	default:
    527 		fprint(2, "unsupported type char %c (%d)\n", *p, *p);
    528 		oops();
    529 	}
    530 	*pp = p;
    531 	return t;
    532 }
    533 
    534 /*
    535 	bound ::=
    536 		'A' offset			(bound is on stack by ref at offset offset from arg list)
    537 		| 'T' offset			(bound is on stack by val at offset offset from arg list)
    538 		| 'a' regnum		(bound passed by reference in register)
    539 		| 't' regnum		(bound passed by value in register)
    540 		| 'J'				(no bound)
    541 		| bigint
    542 */
    543 static int
    544 parsebound(char **pp)
    545 {
    546 	char *p;
    547 	int n;
    548 
    549 	n = 0;
    550 	p = *pp;
    551 	switch(*p){
    552 	case 'A':	/* bound is on stack by reference at offset n from arg list */
    553 	case 'T':	/* bound is on stack by value at offset n from arg list */
    554 	case 'a':	/* bound is passed by reference in register n */
    555 	case 't':	/* bound is passed by value in register n */
    556 		p++;
    557 		parseint(&p);
    558 		break;
    559 	case 'J':	/* no bound */
    560 		p++;
    561 		break;
    562 	default:
    563 		n = parsebigint(&p);
    564 		break;
    565 	}
    566 	*pp = p;
    567 	return n;
    568 }
    569 
    570 /*
    571 	bigint ::= '-'? decimal
    572 		| 0 octal
    573 		| -1
    574  */
    575 static vlong
    576 parsebigint(char **pp)
    577 {
    578 	char *p;
    579 	int n, neg;
    580 
    581 	p = *pp;
    582 	if(*p == '0'){
    583 		errno = 0;
    584 		n = strtoll(p, &p, 8);
    585 		if(errno)
    586 			n = 0;
    587 		goto out;
    588 	}
    589 	neg = 0;
    590 	if(*p == '-'){
    591 		neg = 1;
    592 		p++;
    593 	}
    594 	if(!isdigit((uchar)*p))
    595 		oops();
    596 	n = strtol(p, &p, 10);
    597 	if(neg)
    598 		n = -n;
    599 
    600 out:
    601 	*pp = p;
    602 	return n;
    603 }
    604 
    605 int
    606 stabs2acid(Stab *stabs, Biobuf *b)
    607 {
    608 	volatile int fno, i;
    609 	char c, *desc, *p;
    610 	char *volatile dir, *volatile fn, *volatile name;
    611 	Ftypes *f;
    612 	Type *t, *tt;
    613 	StabSym sym;
    614 
    615 	dir = nil;
    616 	fno = 0;
    617 	fn = nil;
    618 	for(i=0; stabsym(stabs, i, &sym)>=0; i++){
    619 		if(verbose)
    620 			print("%d %s\n", sym.type, sym.name);
    621 		switch(sym.type){
    622 		case N_SO:
    623 			if(sym.name){
    624 				if(sym.name[0] && sym.name[strlen(sym.name)-1] == '/')
    625 					dir = sym.name;
    626 			}
    627 			denumber();
    628 			fstack = nil;
    629 			fno = 0;
    630 			break;
    631 		case N_BINCL:
    632 			fno++;
    633 			f = mkftypes(dir, sym.name);
    634 			f->down = fstack;
    635 			fstack = f;
    636 			break;
    637 		case N_EINCL:
    638 			if(fstack)
    639 				fstack = fstack->down;
    640 			break;
    641 		case N_EXCL:
    642 			fno++;
    643 			if((f = findftypes(dir, sym.name)) == nil){
    644 				static int cannotprint;
    645 
    646 				if(cannotprint++ == 0)
    647 					fprint(2, "cannot find remembered %s\n", sym.name);
    648 				continue;
    649 			}
    650 			renumber(f->list, fno);
    651 			break;
    652 		case N_GSYM:
    653 		case N_FUN:
    654 		case N_PSYM:
    655 		case N_LSYM:
    656 		case N_LCSYM:
    657 		case N_STSYM:
    658 		case N_RSYM:
    659 			name = sym.name;
    660 			if(name == nil){
    661 				if(sym.type==N_FUN)
    662 					fn = nil;
    663 				continue;
    664 			}
    665 			if((p = findcolon(name)) == nil)
    666 				continue;
    667 			name = estrndup(name, p-name);
    668 			desc = ++p;
    669 			c = *desc;
    670 			if(c == 'c'){
    671 				fprint(2, "skip constant %s\n", name);
    672 				continue;
    673 			}
    674 			if(setjmp(kaboom)){
    675 				static int cannotparse;
    676 
    677 				if(cannotparse++ == 0)
    678 					fprint(2, "cannot parse %s\n", name);
    679 				continue;
    680 			}
    681 			t = parsename(desc, &p);
    682 			if(t == nil)
    683 				continue;
    684 			if(*p != 0){
    685 				static int extradesc;
    686 
    687 				if(extradesc++ == 0)
    688 					fprint(2, "extra desc '%s' in '%s'\n", p, desc);
    689 			}
    690 			/* void is defined as itself */
    691 			if(t->ty==Defer && t->sub==t && strcmp(name, "void")==0){
    692 				t->ty = Base;
    693 				t->xsizeof = 0;
    694 				t->printfmt = '0';
    695 			}
    696 			if(*name==' ' && *(name+1) == 0)
    697 				*name = 0;
    698 			/* attach names to structs, unions, enums */
    699 			if(c=='T' && *name && t->sue){
    700 				t->suename = name;
    701 				if(t->name == nil)
    702 					t->name = name;
    703 				tt = typebysue(t->sue, name);
    704 				tt->ty = Defer;
    705 				tt->sub = t;
    706 			}
    707 			if(c=='t'){
    708 				tt = newtype();
    709 				tt->ty = Typedef;
    710 				tt->name = name;
    711 				tt->sub = t;
    712 			}
    713 			/* define base c types */
    714 			if(t->ty==None || t->ty==Range){
    715 				if(strcmp(name, "char") == 0){
    716 					t->ty = Base;
    717 					t->xsizeof = 1;
    718 					t->printfmt = 'x';
    719 				}
    720 				if(strcmp(name, "int") == 0){
    721 					t->ty = Base;
    722 					t->xsizeof = 4;
    723 					t->printfmt = 'd';
    724 				}
    725 			}
    726 			/* record declaration in list for later. */
    727 			if(c != 't' && c != 'T')
    728 			switch(sym.type){
    729 			case N_GSYM:
    730 				addsymx(nil, name, t);
    731 				break;
    732 			case N_FUN:
    733 				fn = name;
    734 				break;
    735 			case N_PSYM:
    736 			case N_LSYM:
    737 			case N_LCSYM:
    738 			case N_STSYM:
    739 			case N_RSYM:
    740 				addsymx(fn, name, t);
    741 				break;
    742 			}
    743 			break;
    744 		}
    745 if(1) print("");
    746 	}
    747 
    748 	printtypes(b);
    749 	dumpsyms(b);
    750 	freetypes();
    751 
    752 	return 0;
    753 }