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 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 case '&': /* reference */ /* guess - C++? (rob) */
388 t->ty = Pointer;
389 t->sub = parseinfo(p+1, &p);
390 break;
391 case 'a': /* array */
392 case 'P': /* packed array */
393 t->ty = Pointer;
394 tt = newtype();
395 parsedefn(p+1, tt, &p); /* index type */
396 if(*p == ';')
397 p++;
398 tt = newtype();
399 t->sub = tt;
400 parsedefn(p, tt, &p); /* element type */
401 break;
402 case 'e': /* enum listing */
403 p++;
404 t->sue = 'e';
405 t->ty = Enum;
406 while(*p != ';'){
407 name = p;
408 p = findcolon(p)+1;
409 namelen = (p-name)-1;
410 val = parsebigint(&p);
411 comma(&p);
412 if(t->n%32 == 0){
413 t->tname = erealloc(t->tname, (t->n+32)*sizeof(t->tname[0]));
414 t->val = erealloc(t->val, (t->n+32)*sizeof(t->val[0]));
416 t->tname[t->n] = estrndup(name, namelen);
417 t->val[t->n] = val;
418 t->n++;
420 semi(&p);
421 break;
423 case 's': /* struct */
424 case 'u': /* union */
425 p++;
426 t->sue = c;
427 t->ty = Aggr;
428 n = parseint(&p);
429 while(*p != ';'){
430 name = p;
431 p = findcolon(p)+1;
432 namelen = (p-name)-1;
433 tt = parseinfo(p, &p);
434 comma(&p);
435 offset = parseint(&p);
436 comma(&p);
437 bits = parseint(&p);
438 semi(&p);
439 if(t->n%32 == 0){
440 t->tname = erealloc(t->tname, (t->n+32)*sizeof(t->tname[0]));
441 t->val = erealloc(t->val, (t->n+32)*sizeof(t->val[0]));
442 t->t = erealloc(t->t, (t->n+32)*sizeof(t->t[0]));
444 t->tname[t->n] = estrndup(name, namelen);
445 t->val[t->n] = offset;
446 t->t[t->n] = tt;
447 t->n++;
449 semi(&p);
450 break;
452 case 'x': /* struct, union, enum reference */
453 p++;
454 t->ty = Defer;
455 if(*p != 's' && *p != 'u' && *p != 'e')
456 oops();
457 c = *p;
458 name = p+1;
459 p = findcolon(p+1);
460 name = estrndup(name, p-name);
461 t->sub = typebysue(c, name);
462 p++;
463 break;
465 #if 0 /* AIX */
466 case 'f': /* function */
467 case 'p': /* procedure */
468 case 'F': /* Pascal function */
469 /* case 'R': /* Pascal procedure */
470 /*
471 * Even though we don't use the info, we have
472 * to parse it in case it is embedded in other descriptions.
473 */
474 t->ty = Function;
475 p++;
476 if(c == 'f' || c == 'F'){
477 t->sub = parseinfo(p, &p);
478 if(*p != ','){
479 if(*p == ';')
480 p++;
481 break;
483 comma(&p);
485 n = parseint(&p); /* number of params */
486 semi(&p);
487 while(*p != ';'){
488 if(c == 'F' || c == 'R'){
489 name = p; /* parameter name */
490 p = findcolon(p)+1;
492 parseinfo(p, &p); /* param type */
493 comma(&p);
494 parseint(&p); /* bool: passed by value? */
495 semi(&p);
497 semi(&p);
498 break;
499 #endif
501 case 'f': /* static function */
502 case 'F': /* global function */
503 t->ty = Function;
504 p++;
505 t->sub = parseinfo(p, &p);
506 break;
508 /*
509 * We'll never see any of this stuff.
510 * When we do, we can worry about it.
511 */
512 case 'D': /* n-dimensional array */
513 case 'E': /* subarray of n-dimensional array */
514 case 'M': /* fortran multiple instance type */
515 case 'N': /* pascal string ptr */
516 case 'S': /* set */
517 case 'c': /* aix complex */
518 case 'd': /* file of */
519 case 'g': /* aix float */
520 case 'n': /* max length string */
521 case 'w': /* aix wide char */
522 case 'z': /* another max length string */
523 default:
524 fprint(2, "unsupported type char %c (%d)\n", *p, *p);
525 oops();
527 *pp = p;
528 return t;
531 /*
532 bound ::=
533 'A' offset (bound is on stack by ref at offset offset from arg list)
534 | 'T' offset (bound is on stack by val at offset offset from arg list)
535 | 'a' regnum (bound passed by reference in register)
536 | 't' regnum (bound passed by value in register)
537 | 'J' (no bound)
538 | bigint
539 */
540 static int
541 parsebound(char **pp)
543 char *p;
544 int n;
546 n = 0;
547 p = *pp;
548 switch(*p){
549 case 'A': /* bound is on stack by reference at offset n from arg list */
550 case 'T': /* bound is on stack by value at offset n from arg list */
551 case 'a': /* bound is passed by reference in register n */
552 case 't': /* bound is passed by value in register n */
553 p++;
554 parseint(&p);
555 break;
556 case 'J': /* no bound */
557 p++;
558 break;
559 default:
560 n = parsebigint(&p);
561 break;
563 *pp = p;
564 return n;
567 /*
568 bigint ::= '-'? decimal
569 | 0 octal
570 | -1
571 */
572 static vlong
573 parsebigint(char **pp)
575 char *p;
576 int n, neg;
578 p = *pp;
579 if(*p == '0'){
580 errno = 0;
581 n = strtoll(p, &p, 8);
582 if(errno)
583 n = 0;
584 goto out;
586 neg = 0;
587 if(*p == '-'){
588 neg = 1;
589 p++;
591 if(!isdigit((uchar)*p))
592 oops();
593 n = strtol(p, &p, 10);
594 if(neg)
595 n = -n;
597 out:
598 *pp = p;
599 return n;
602 int
603 stabs2acid(Stab *stabs, Biobuf *b)
605 volatile int fno, i;
606 char c, *file, *desc, *p;
607 char *volatile dir, *volatile fn, *volatile name;
608 Ftypes *f;
609 Type *t, *tt;
610 StabSym sym;
612 dir = nil;
613 file = nil;
614 fno = 0;
615 fn = nil;
616 for(i=0; stabsym(stabs, i, &sym)>=0; i++){
617 if(verbose)
618 print("%d %s\n", sym.type, sym.name);
619 switch(sym.type){
620 case N_SO:
621 if(sym.name){
622 if(sym.name[0] && sym.name[strlen(sym.name)-1] == '/')
623 dir = sym.name;
624 else
625 file = 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;