Blob


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"
10 static jmp_buf kaboom;
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**);
20 typedef struct Ftypes Ftypes;
21 struct Ftypes
22 {
23 Ftypes *down;
24 Ftypes *next;
25 char *file;
26 TypeList *list;
27 };
29 Ftypes *fstack;
30 Ftypes *allftypes;
32 static char*
33 estrndup(char *s, int n)
34 {
35 char *t;
37 t = emalloc(n+1);
38 memmove(t, s, n);
39 return t;
40 }
42 static char*
43 mkpath(char *dir, char *name)
44 {
45 char *s;
46 if(name[0] == '/')
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 }
56 static Ftypes*
57 mkftypes(char *dir, char *name)
58 {
59 Ftypes *f;
61 f = emalloc(sizeof(*f));
62 f->file = mkpath(dir, name);
63 f->next = allftypes;
64 allftypes = f;
65 return f;
66 }
68 static Ftypes*
69 findftypes(char *dir, char *name)
70 {
71 char *s;
72 Ftypes *f, *found;
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 }
82 static void
83 oops(void)
84 {
85 longjmp(kaboom, 1);
86 }
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 }
99 static void
100 semi(char **p)
102 if(**p != ';')
103 oops();
104 (*p)++;
107 static void
108 comma(char **p)
110 if(**p != ',')
111 oops();
112 (*p)++;
115 static int
116 parseint(char **pp)
118 if(!isdigit(**pp))
119 oops();
120 return strtol(*pp, pp, 10);
123 /*
124 name ::= symbol_opt info
125 */
126 static Type*
127 parsename(char *desc, char **pp)
129 if(*desc == 'c')
130 return nil;
132 if(isdigit(*desc) || *desc=='-' || *desc=='(')
133 return parseinfo(desc, pp);
134 if(*desc == 0)
135 oops();
136 return parseinfo(desc+1, pp);
139 /*
140 info ::= num | num '=' attr* defn
141 */
142 static Type*
143 parseinfo(char *desc, char **pp)
145 int n1, n2;
146 Type *t;
147 char *attr;
149 n1 = n2 = 0;
150 parsenum(desc, &n1, &n2, &desc);
151 t = typebynum(n1, n2);
152 if(*desc != '='){
153 *pp = desc;
154 return t;
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;
163 return parsedefn(desc, t, pp);
166 /*
167 num ::= integer | '(' integer ',' integer ')'
168 */
169 static int
170 parsenum(char *p, int *n1, int *n2, char **pp)
172 if(isdigit(*p)){
173 *n1 = strtol(p, &p, 10);
174 *n2 = 0;
175 *pp = p;
176 return 0;
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;
188 oops();
189 return -1;
192 /*
193 attr ::= '@' text ';'
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)
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;
215 typedef struct Basic Basic;
216 struct Basic
218 int size;
219 int fmt;
220 };
222 static Basic baseints[] =
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 };
261 static Basic basefloats[] =
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 };
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 */
311 static Type*
312 parsedefn(char *p, Type *t, char **pp)
314 char c, *name;
315 int ischar, namelen, n, wid, offset, bits, sign;
316 long val;
317 Type *tt;
319 if(*p == '(' || isdigit(*p)){
320 t->ty = Defer;
321 t->sub = parseinfo(p, pp);
322 return t;
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 if(*p == 'c'){
341 ischar = 1;
342 p++;
344 wid = parseint(&p);
345 semi(&p);
346 offset = parseint(&p);
347 semi(&p);
348 bits = parseint(&p);
349 semi(&p);
350 t->ty = Base;
351 t->xsizeof = wid;
352 if(sign == 1)
353 t->printfmt = 'd';
354 else
355 t->printfmt = 'x';
356 break;
357 case 'R': /* fp type */
358 n = parseint(&p);
359 semi(&p);
360 wid = parseint(&p);
361 semi(&p);
362 t->ty = Base;
363 t->xsizeof = wid;
364 if(n < 0 || n >= nelem(basefloats))
365 n = 0;
366 t->xsizeof = basefloats[n].size;
367 t->printfmt = basefloats[n].fmt;
368 break;
369 case 'r': /* subrange */
370 t->ty = Range;
371 t->sub = parseinfo(p+1, &p);
372 if(*(p-1) == ';' && *p != ';')
373 p--;
374 semi(&p);
375 t->lo = parsebound(&p);
376 semi(&p);
377 t->hi = parsebound(&p);
378 semi(&p);
379 break;
380 case 'B': /* volatile */
381 case 'k': /* const */
382 t->ty = Defer;
383 t->sub = parseinfo(p+1, &p);
384 break;
385 case '*': /* pointer */
386 case 'A': /* open array */
387 t->ty = Pointer;
388 t->sub = parseinfo(p+1, &p);
389 break;
390 case 'a': /* array */
391 case 'P': /* packed array */
392 t->ty = Pointer;
393 tt = newtype();
394 parsedefn(p+1, tt, &p); /* index type */
395 if(*p == ';')
396 p++;
397 tt = newtype();
398 t->sub = tt;
399 parsedefn(p, tt, &p); /* element type */
400 break;
401 case 'e': /* enum listing */
402 p++;
403 t->sue = 'e';
404 t->ty = Enum;
405 while(*p != ';'){
406 name = p;
407 p = findcolon(p)+1;
408 namelen = (p-name)-1;
409 val = parsebigint(&p);
410 comma(&p);
411 if(t->n%32 == 0){
412 t->tname = erealloc(t->tname, (t->n+32)*sizeof(t->tname[0]));
413 t->val = erealloc(t->val, (t->n+32)*sizeof(t->val[0]));
415 t->tname[t->n] = estrndup(name, namelen);
416 t->val[t->n] = val;
417 t->n++;
419 semi(&p);
420 break;
422 case 's': /* struct */
423 case 'u': /* union */
424 p++;
425 t->sue = c;
426 t->ty = Aggr;
427 n = parseint(&p);
428 while(*p != ';'){
429 name = p;
430 p = findcolon(p)+1;
431 namelen = (p-name)-1;
432 tt = parseinfo(p, &p);
433 comma(&p);
434 offset = parseint(&p);
435 comma(&p);
436 bits = parseint(&p);
437 semi(&p);
438 if(t->n%32 == 0){
439 t->tname = erealloc(t->tname, (t->n+32)*sizeof(t->tname[0]));
440 t->val = erealloc(t->val, (t->n+32)*sizeof(t->val[0]));
441 t->t = erealloc(t->t, (t->n+32)*sizeof(t->t[0]));
443 t->tname[t->n] = estrndup(name, namelen);
444 t->val[t->n] = offset;
445 t->t[t->n] = tt;
446 t->n++;
448 semi(&p);
449 break;
451 case 'x': /* struct, union, enum reference */
452 p++;
453 t->ty = Defer;
454 if(*p != 's' && *p != 'u' && *p != 'e')
455 oops();
456 c = *p;
457 name = p+1;
458 p = findcolon(p+1);
459 name = estrndup(name, p-name);
460 t->sub = typebysue(c, name);
461 p++;
462 break;
464 #if 0 /* AIX */
465 case 'f': /* function */
466 case 'p': /* procedure */
467 case 'F': /* Pascal function */
468 /* case 'R': /* Pascal procedure */
469 /*
470 * Even though we don't use the info, we have
471 * to parse it in case it is embedded in other descriptions.
472 */
473 t->ty = Function;
474 p++;
475 if(c == 'f' || c == 'F'){
476 t->sub = parseinfo(p, &p);
477 if(*p != ','){
478 if(*p == ';')
479 p++;
480 break;
482 comma(&p);
484 n = parseint(&p); /* number of params */
485 semi(&p);
486 while(*p != ';'){
487 if(c == 'F' || c == 'R'){
488 name = p; /* parameter name */
489 p = findcolon(p)+1;
491 parseinfo(p, &p); /* param type */
492 comma(&p);
493 parseint(&p); /* bool: passed by value? */
494 semi(&p);
496 semi(&p);
497 break;
498 #endif
500 case 'f': /* static function */
501 case 'F': /* global function */
502 t->ty = Function;
503 p++;
504 t->sub = parseinfo(p, &p);
505 break;
507 /*
508 * We'll never see any of this stuff.
509 * When we do, we can worry about it.
510 */
511 case 'D': /* n-dimensional array */
512 case 'E': /* subarray of n-dimensional array */
513 case 'M': /* fortran multiple instance type */
514 case 'N': /* pascal string ptr */
515 case 'S': /* set */
516 case 'c': /* aix complex */
517 case 'd': /* file of */
518 case 'g': /* aix float */
519 case 'n': /* max length string */
520 case 'w': /* aix wide char */
521 case 'z': /* another max length string */
522 default:
523 fprint(2, "unsupported type char %c (%d)\n", *p, *p);
524 oops();
526 *pp = p;
527 return t;
530 /*
531 bound ::=
532 'A' offset (bound is on stack by ref at offset offset from arg list)
533 | 'T' offset (bound is on stack by val at offset offset from arg list)
534 | 'a' regnum (bound passed by reference in register)
535 | 't' regnum (bound passed by value in register)
536 | 'J' (no bound)
537 | bigint
538 */
539 static int
540 parsebound(char **pp)
542 char *p;
543 int n;
545 n = 0;
546 p = *pp;
547 switch(*p){
548 case 'A': /* bound is on stack by reference at offset n from arg list */
549 case 'T': /* bound is on stack by value at offset n from arg list */
550 case 'a': /* bound is passed by reference in register n */
551 case 't': /* bound is passed by value in register n */
552 p++;
553 parseint(&p);
554 break;
555 case 'J': /* no bound */
556 p++;
557 break;
558 default:
559 n = parsebigint(&p);
560 break;
562 *pp = p;
563 return n;
566 /*
567 bigint ::= '-'? decimal
568 | 0 octal
569 | -1
570 */
571 static vlong
572 parsebigint(char **pp)
574 char *p;
575 int n, neg;
577 p = *pp;
578 if(*p == '0'){
579 errno = 0;
580 n = strtoll(p, &p, 8);
581 if(errno)
582 n = 0;
583 goto out;
585 neg = 0;
586 if(*p == '-'){
587 neg = 1;
588 p++;
590 if(!isdigit(*p))
591 oops();
592 n = strtol(p, &p, 10);
593 if(neg)
594 n = -n;
596 out:
597 *pp = p;
598 return n;
601 int
602 stabs2acid(Stab *stabs, Biobuf *b)
604 volatile int fno, i;
605 char c, *file, *desc, *p;
606 char *volatile dir, *volatile fn, *volatile name;
607 Ftypes *f;
608 Type *t, *tt;
609 StabSym sym;
611 dir = nil;
612 file = nil;
613 fno = 0;
614 fn = nil;
615 for(i=0; stabsym(stabs, i, &sym)>=0; i++){
616 switch(sym.type){
617 case N_SO:
618 if(sym.name){
619 if(sym.name[0] && sym.name[strlen(sym.name)-1] == '/')
620 dir = sym.name;
621 else
622 file = sym.name;
624 denumber();
625 fstack = nil;
626 fno = 0;
627 break;
628 case N_BINCL:
629 fno++;
630 f = mkftypes(dir, sym.name);
631 f->down = fstack;
632 fstack = f;
633 break;
634 case N_EINCL:
635 if(fstack)
636 fstack = fstack->down;
637 break;
638 case N_EXCL:
639 fno++;
640 if((f = findftypes(dir, sym.name)) == nil){
641 fprint(2, "cannot find remembered %s\n", sym.name);
642 continue;
644 renumber(f->list, fno);
645 break;
646 case N_GSYM:
647 case N_FUN:
648 case N_PSYM:
649 case N_LSYM:
650 case N_LCSYM:
651 case N_STSYM:
652 case N_RSYM:
653 name = sym.name;
654 if(name == nil){
655 if(sym.type==N_FUN)
656 fn = nil;
657 continue;
659 if((p = strchr(name, ':')) == nil)
660 continue;
661 name = estrndup(name, p-name);
662 desc = ++p;
663 c = *desc;
664 if(c == 'c'){
665 fprint(2, "skip constant %s\n", name);
666 continue;
668 if(setjmp(kaboom)){
669 fprint(2, "cannot parse %s\n", name);
670 continue;
672 t = parsename(desc, &p);
673 if(t == nil)
674 continue;
675 if(*p != 0)
676 fprint(2, "extra desc '%s' in '%s'\n", p, desc);
677 /* void is defined as itself */
678 if(t->ty==Defer && t->sub==t && strcmp(name, "void")==0){
679 t->ty = Base;
680 t->xsizeof = 0;
681 t->printfmt = '0';
683 if(*name==' ' && *(name+1) == 0)
684 *name = 0;
685 /* attach names to structs, unions, enums */
686 if(c=='T' && *name && t->sue){
687 t->suename = name;
688 if(t->name == nil)
689 t->name = name;
690 tt = typebysue(t->sue, name);
691 tt->ty = Defer;
692 tt->sub = t;
694 if(c=='t'){
695 tt = newtype();
696 tt->ty = Typedef;
697 tt->name = name;
698 tt->sub = t;
700 /* define base c types */
701 if(t->ty==None || t->ty==Range){
702 if(strcmp(name, "char") == 0){
703 t->ty = Base;
704 t->xsizeof = 1;
705 t->printfmt = 'x';
707 if(strcmp(name, "int") == 0){
708 t->ty = Base;
709 t->xsizeof = 4;
710 t->printfmt = 'd';
713 /* record declaration in list for later. */
714 if(c != 't' && c != 'T')
715 switch(sym.type){
716 case N_GSYM:
717 addsymx(nil, name, t);
718 break;
719 case N_FUN:
720 fn = name;
721 break;
722 case N_PSYM:
723 case N_LSYM:
724 case N_LCSYM:
725 case N_STSYM:
726 case N_RSYM:
727 addsymx(fn, name, t);
728 break;
730 break;
734 printtypes(b);
735 dumpsyms(b);
736 freetypes();
738 return 0;