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] == '/' || 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 }
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((uchar)**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((uchar)*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((uchar)*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((uchar)*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 ischar = 0;
341 if(*p == 'c'){
342 ischar = 1;
343 p++;
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]));
419 t->tname[t->n] = estrndup(name, namelen);
420 t->val[t->n] = val;
421 t->n++;
423 semi(&p);
424 break;
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]));
447 t->tname[t->n] = estrndup(name, namelen);
448 t->val[t->n] = offset;
449 t->t[t->n] = tt;
450 t->n++;
452 semi(&p);
453 break;
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;
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;
486 comma(&p);
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;
495 parseinfo(p, &p); /* param type */
496 comma(&p);
497 parseint(&p); /* bool: passed by value? */
498 semi(&p);
500 semi(&p);
501 break;
502 #endif
504 case 'f': /* static function */
505 case 'F': /* global function */
506 t->ty = Function;
507 p++;
508 t->sub = parseinfo(p, &p);
509 break;
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();
530 *pp = p;
531 return t;
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)
546 char *p;
547 int n;
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;
566 *pp = p;
567 return n;
570 /*
571 bigint ::= '-'? decimal
572 | 0 octal
573 | -1
574 */
575 static vlong
576 parsebigint(char **pp)
578 char *p;
579 int n, neg;
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;
589 neg = 0;
590 if(*p == '-'){
591 neg = 1;
592 p++;
594 if(!isdigit((uchar)*p))
595 oops();
596 n = strtol(p, &p, 10);
597 if(neg)
598 n = -n;
600 out:
601 *pp = p;
602 return n;
605 int
606 stabs2acid(Stab *stabs, Biobuf *b)
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;
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;
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;
646 if(cannotprint++ == 0)
647 fprint(2, "cannot find remembered %s\n", sym.name);
648 continue;
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;
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;
674 if(setjmp(kaboom)){
675 static int cannotparse;
677 if(cannotparse++ == 0)
678 fprint(2, "cannot parse %s\n", name);
679 continue;
681 t = parsename(desc, &p);
682 if(t == nil)
683 continue;
684 if(*p != 0){
685 static int extradesc;
687 if(extradesc++ == 0)
688 fprint(2, "extra desc '%s' in '%s'\n", p, desc);
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';
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;
707 if(c=='t'){
708 tt = newtype();
709 tt->ty = Typedef;
710 tt->name = name;
711 tt->sub = t;
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';
720 if(strcmp(name, "int") == 0){
721 t->ty = Base;
722 t->xsizeof = 4;
723 t->printfmt = 'd';
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;
743 break;
745 if(1) print("");
748 printtypes(b);
749 dumpsyms(b);
750 freetypes();
752 return 0;