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 parsenum(desc, &n1, &n2, &desc);
150 t = typebynum(n1, n2);
151 if(*desc != '='){
152 *pp = desc;
153 return t;
155 desc++;
156 if(fstack)
157 fstack->list = mktl(t, fstack->list);
158 while(parseattr(desc, &attr, &desc) >= 0){
159 if(*attr == 's')
160 t->xsizeof = atoi(attr+1)/8;
162 return parsedefn(desc, t, pp);
165 /*
166 num ::= integer | '(' integer ',' integer ')'
167 */
168 static int
169 parsenum(char *p, int *n1, int *n2, char **pp)
171 if(isdigit(*p)){
172 *n1 = strtol(p, &p, 10);
173 *n2 = 0;
174 *pp = p;
175 return 0;
177 if(*p == '('){
178 *n1 = strtol(p+1, &p, 10);
179 if(*p != ',')
180 oops();
181 *n2 = strtol(p+1, &p, 10);
182 if(*p != ')')
183 oops();
184 *pp = p+1;
185 return 0;
187 oops();
188 return -1;
191 /*
192 attr ::= '@' text ';'
194 text is
195 'a' integer (alignment)
196 'p' integer (pointer class)
197 'P' (packed type)
198 's' integer (size of type in bits)
199 'S' (string instead of array of chars)
200 */
201 static int
202 parseattr(char *p, char **text, char **pp)
204 if(*p != '@')
205 return -1;
206 *text = p+1;
207 if((p = strchr(p, ';')) == nil)
208 oops();
209 *pp = p+1;
210 return 0;
214 typedef struct Basic Basic;
215 struct Basic
217 int size;
218 int fmt;
219 };
221 static Basic baseints[] =
223 0, 0,
224 /*1*/ 4, 'd', /* int32 */
225 /*2*/ 1, 'd', /* char8 */
226 /*3*/ 2, 'd', /* int16 */
227 /*4*/ 4, 'd', /* long int32 */
228 /*5*/ 1, 'x', /* uchar8 */
229 /*6*/ 1, 'd', /* schar8 */
230 /*7*/ 2, 'x', /* uint16 */
231 /*8*/ 4, 'x', /* uint32 */
232 /*9*/ 4, 'x', /* uint32 */
233 /*10*/ 4, 'x', /* ulong32 */
234 /*11*/ 0, 0, /* void */
235 /*12*/ 4, 'f', /* float */
236 /*13*/ 8, 'f', /* double */
237 /*14*/ 10, 'f', /* long double */
238 /*15*/ 4, 'd', /* int32 */
239 /*16*/ 4, 'd', /* bool32 */
240 /*17*/ 2, 'f', /* short real */
241 /*18*/ 4, 'f', /* real */
242 /*19*/ 4, 'x', /* stringptr */
243 /*20*/ 1, 'd', /* character8 */
244 /*21*/ 1, 'x', /* logical*1 */
245 /*22*/ 2, 'x', /* logical*2 */
246 /*23*/ 4, 'X', /* logical*4 */
247 /*24*/ 4, 'X', /* logical32 */
248 /*25*/ 8, 'F', /* complex (two single) */
249 /*26*/ 16, 'F', /* complex (two double) */
250 /*27*/ 1, 'd', /* integer*1 */
251 /*28*/ 2, 'd', /* integer*2 */
252 /*29*/ 4, 'd', /* integer*4 */
253 /*30*/ 2, 'x', /* wide char */
254 /*31*/ 8, 'd', /* int64 */
255 /*32*/ 8, 'x', /* uint64 */
256 /*33*/ 8, 'x', /* logical*8 */
257 /*34*/ 8, 'd', /* integer*8 */
258 };
260 static Basic basefloats[] =
262 0,0,
263 /*1*/ 4, 'f', /* 32-bit */
264 /*2*/ 8, 'f', /* 64-bit */
265 /*3*/ 8, 'F', /* complex */
266 /*4*/ 4, 'F', /* complex16 */
267 /*5*/ 8, 'F', /* complex32 */
268 /*6*/ 10, 'f', /* long double */
269 };
271 /*
272 defn ::= info
273 | 'b' ('u' | 's') 'c'? width; offset; nbits; (builtin, signed/unsigned, char/not, width in bytes, offset & nbits of type)
274 | 'w' (aix wide char type, not used)
275 | 'R' fptype; bytes; (fptype 1=32-bit, 2=64-bit, 3=complex, 4=complex16, 5=complex32, 6=long double)
276 | 'g' typeinfo ';' nbits (aix floating, not used)
277 | 'c' typeinfo ';' nbits (aix complex, not used)
278 | 'b' typeinfo ';' bytes (ibm, no idea)
279 | 'B' typeinfo (volatile typref)
280 | 'd' typeinfo (file of typeref)
281 | 'k' typeinfo (const typeref)
282 | 'M' typeinfo ';' length (multiple instance type, fortran)
283 | 'S' typeinfo (set, typeref must have small number of values)
284 | '*' typeinfo (pointer to typeref)
285 | 'x' ('s'|'u'|'e') name ':' (struct, union, enum reference. name can have '::' in it)
286 | 'r' typeinfo ';' low ';' high ';' (subrange. typeref can be type being defined for base types!)
287 low and high are bounds
288 if bound is octal power of two, it's a big negative number
289 | ('a'|'P') indextypedef arraytypeinfo (array, index should be range type)
290 indextype is type definition not typeinfo (need not say typenum=)
291 P means packed array
292 | 'A' arraytypeinfo (open array (no index bounds))
293 | 'D' dims ';' typeinfo (dims-dimensional dynamic array)
294 | 'E' dims ';' typeinfo (subarray of N-dimensional array)
295 | 'n' typeinfo ';' bytes (max length string)
296 | 'z' typeinfo ';' bytes (no idea what difference is from 'n')
297 | 'N' (pascal stringptr)
298 | 'e' (name ':' bigint ',')* ';' (enum listing)
299 | ('s'|'u') bytes (name ':' type ',' bitoffset ',' bitsize ';')* ';' (struct/union defn)
300 tag is given as name in stabs entry, with 'T' symbol
301 | 'f' typeinfo ';' (function returning type)
302 | 'f' rettypeinfo ',' paramcount ';' (typeinfo ',' (0|1) ';')* ';'
303 | 'p' paramcount ';' (typeinfo ',' (0|1) ';')* ';'
304 | 'F' rettypeinfo ',' paramcount ';' (name ':' typeinfo ',' (0|1) ';')* ';'
305 | 'R' paramcount ';' (name ':' typeinfo ',' (0|1) ';')* ';'
306 (the 0 or 1 is pass-by-reference vs pass-by-value)
307 (the 0 or 1 is pass-by-reference vs pass-by-value)
308 */
310 static Type*
311 parsedefn(char *p, Type *t, char **pp)
313 char c, *name;
314 int ischar, namelen, n, wid, offset, bits, sign;
315 long val;
316 Type *tt;
318 if(*p == '(' || isdigit(*p)){
319 t->ty = Defer;
320 t->sub = parseinfo(p, pp);
321 return t;
324 switch(c = *p){
325 case '-': /* builtin */
326 n = strtol(p+1, &p, 10);
327 if(n >= nelem(baseints) || n < 0)
328 n = 0;
329 t->ty = Base;
330 t->xsizeof = baseints[n].size;
331 t->printfmt = baseints[n].fmt;
332 break;
333 case 'b': /* builtin */
334 p++;
335 if(*p != 'u' && *p != 's')
336 oops();
337 sign = (*p == 's');
338 p++;
339 if(*p == 'c'){
340 ischar = 1;
341 p++;
343 wid = parseint(&p);
344 semi(&p);
345 offset = parseint(&p);
346 semi(&p);
347 bits = parseint(&p);
348 semi(&p);
349 t->ty = Base;
350 t->xsizeof = wid;
351 if(sign == 1)
352 t->printfmt = 'd';
353 else
354 t->printfmt = 'x';
355 break;
356 case 'R': /* fp type */
357 n = parseint(&p);
358 semi(&p);
359 wid = parseint(&p);
360 semi(&p);
361 t->ty = Base;
362 t->xsizeof = wid;
363 if(n < 0 || n >= nelem(basefloats))
364 n = 0;
365 t->xsizeof = basefloats[n].size;
366 t->printfmt = basefloats[n].fmt;
367 break;
368 case 'r': /* subrange */
369 t->ty = Range;
370 t->sub = parseinfo(p+1, &p);
371 if(*(p-1) == ';' && *p != ';')
372 p--;
373 semi(&p);
374 t->lo = parsebound(&p);
375 semi(&p);
376 t->hi = parsebound(&p);
377 semi(&p);
378 break;
379 case 'B': /* volatile */
380 case 'k': /* const */
381 t->ty = Defer;
382 t->sub = parseinfo(p+1, &p);
383 break;
384 case '*': /* pointer */
385 case 'A': /* open array */
386 t->ty = Pointer;
387 t->sub = parseinfo(p+1, &p);
388 break;
389 case 'a': /* array */
390 case 'P': /* packed array */
391 t->ty = Pointer;
392 tt = newtype();
393 parsedefn(p+1, tt, &p); /* index type */
394 if(*p == ';')
395 p++;
396 tt = newtype();
397 t->sub = tt;
398 parsedefn(p, tt, &p); /* element type */
399 break;
400 case 'e': /* enum listing */
401 p++;
402 t->sue = 'e';
403 t->ty = Enum;
404 while(*p != ';'){
405 name = p;
406 p = findcolon(p)+1;
407 namelen = (p-name)-1;
408 val = parsebigint(&p);
409 comma(&p);
410 if(t->n%32 == 0){
411 t->tname = erealloc(t->tname, (t->n+32)*sizeof(t->tname[0]));
412 t->val = erealloc(t->val, (t->n+32)*sizeof(t->val[0]));
414 t->tname[t->n] = estrndup(name, namelen);
415 t->val[t->n] = val;
416 t->n++;
418 semi(&p);
419 break;
421 case 's': /* struct */
422 case 'u': /* union */
423 p++;
424 t->sue = c;
425 t->ty = Aggr;
426 n = parseint(&p);
427 while(*p != ';'){
428 name = p;
429 p = findcolon(p)+1;
430 namelen = (p-name)-1;
431 tt = parseinfo(p, &p);
432 comma(&p);
433 offset = parseint(&p);
434 comma(&p);
435 bits = parseint(&p);
436 semi(&p);
437 if(t->n%32 == 0){
438 t->tname = erealloc(t->tname, (t->n+32)*sizeof(t->tname[0]));
439 t->val = erealloc(t->val, (t->n+32)*sizeof(t->val[0]));
440 t->t = erealloc(t->t, (t->n+32)*sizeof(t->t[0]));
442 t->tname[t->n] = estrndup(name, namelen);
443 t->val[t->n] = offset;
444 t->t[t->n] = tt;
445 t->n++;
447 semi(&p);
448 break;
450 case 'x': /* struct, union, enum reference */
451 p++;
452 t->ty = Defer;
453 if(*p != 's' && *p != 'u' && *p != 'e')
454 oops();
455 c = *p;
456 name = p+1;
457 p = findcolon(p+1);
458 name = estrndup(name, p-name);
459 t->sub = typebysue(c, name);
460 p++;
461 break;
463 #if 0 /* AIX */
464 case 'f': /* function */
465 case 'p': /* procedure */
466 case 'F': /* Pascal function */
467 /* case 'R': /* Pascal procedure */
468 /*
469 * Even though we don't use the info, we have
470 * to parse it in case it is embedded in other descriptions.
471 */
472 t->ty = Function;
473 p++;
474 if(c == 'f' || c == 'F'){
475 t->sub = parseinfo(p, &p);
476 if(*p != ','){
477 if(*p == ';')
478 p++;
479 break;
481 comma(&p);
483 n = parseint(&p); /* number of params */
484 semi(&p);
485 while(*p != ';'){
486 if(c == 'F' || c == 'R'){
487 name = p; /* parameter name */
488 p = findcolon(p)+1;
490 parseinfo(p, &p); /* param type */
491 comma(&p);
492 parseint(&p); /* bool: passed by value? */
493 semi(&p);
495 semi(&p);
496 break;
497 #endif
499 case 'f': /* static function */
500 case 'F': /* global function */
501 t->ty = Function;
502 p++;
503 t->sub = parseinfo(p, &p);
504 break;
506 /*
507 * We'll never see any of this stuff.
508 * When we do, we can worry about it.
509 */
510 case 'D': /* n-dimensional array */
511 case 'E': /* subarray of n-dimensional array */
512 case 'M': /* fortran multiple instance type */
513 case 'N': /* pascal string ptr */
514 case 'S': /* set */
515 case 'c': /* aix complex */
516 case 'd': /* file of */
517 case 'g': /* aix float */
518 case 'n': /* max length string */
519 case 'w': /* aix wide char */
520 case 'z': /* another max length string */
521 default:
522 fprint(2, "unsupported type char %c (%d)\n", *p, *p);
523 oops();
525 *pp = p;
526 return t;
529 /*
530 bound ::=
531 'A' offset (bound is on stack by ref at offset offset from arg list)
532 | 'T' offset (bound is on stack by val at offset offset from arg list)
533 | 'a' regnum (bound passed by reference in register)
534 | 't' regnum (bound passed by value in register)
535 | 'J' (no bound)
536 | bigint
537 */
538 static int
539 parsebound(char **pp)
541 char *p;
542 int n;
544 n = 0;
545 p = *pp;
546 switch(*p){
547 case 'A': /* bound is on stack by reference at offset n from arg list */
548 case 'T': /* bound is on stack by value at offset n from arg list */
549 case 'a': /* bound is passed by reference in register n */
550 case 't': /* bound is passed by value in register n */
551 p++;
552 parseint(&p);
553 break;
554 case 'J': /* no bound */
555 p++;
556 break;
557 default:
558 n = parsebigint(&p);
559 break;
561 *pp = p;
562 return n;
565 /*
566 bigint ::= '-'? decimal
567 | 0 octal
568 | -1
569 */
570 static vlong
571 parsebigint(char **pp)
573 char *p;
574 int n, neg;
576 p = *pp;
577 if(*p == '0'){
578 errno = 0;
579 n = strtoll(p, &p, 8);
580 if(errno)
581 n = 0;
582 goto out;
584 neg = 0;
585 if(*p == '-'){
586 neg = 1;
587 p++;
589 if(!isdigit(*p))
590 oops();
591 n = strtol(p, &p, 10);
592 if(neg)
593 n = -n;
595 out:
596 *pp = p;
597 return n;
600 int
601 stabs2acid(Stab *stabs, Biobuf *b)
603 volatile int fno, i;
604 char c, *file, *desc, *p;
605 char *volatile dir, *volatile fn, *volatile name;
606 Ftypes *f;
607 Type *t, *tt;
608 StabSym sym;
610 dir = nil;
611 file = nil;
612 fno = 0;
613 fn = nil;
614 for(i=0; stabsym(stabs, i, &sym)>=0; i++){
615 switch(sym.type){
616 case N_SO:
617 if(sym.name){
618 if(sym.name[0] && sym.name[strlen(sym.name)-1] == '/')
619 dir = sym.name;
620 else
621 file = sym.name;
623 denumber();
624 fstack = nil;
625 fno = 0;
626 break;
627 case N_BINCL:
628 fno++;
629 f = mkftypes(dir, sym.name);
630 f->down = fstack;
631 fstack = f;
632 break;
633 case N_EINCL:
634 if(fstack)
635 fstack = fstack->down;
636 break;
637 case N_EXCL:
638 fno++;
639 if((f = findftypes(dir, sym.name)) == nil){
640 fprint(2, "cannot find remembered %s\n", sym.name);
641 continue;
643 renumber(f->list, fno);
644 break;
645 case N_GSYM:
646 case N_FUN:
647 case N_PSYM:
648 case N_LSYM:
649 case N_LCSYM:
650 case N_STSYM:
651 case N_RSYM:
652 name = sym.name;
653 if(name == nil){
654 if(sym.type==N_FUN)
655 fn = nil;
656 continue;
658 if((p = strchr(name, ':')) == nil)
659 continue;
660 name = estrndup(name, p-name);
661 desc = ++p;
662 c = *desc;
663 if(c == 'c'){
664 fprint(2, "skip constant %s\n", name);
665 continue;
667 if(setjmp(kaboom)){
668 fprint(2, "cannot parse %s\n", name);
669 continue;
671 t = parsename(desc, &p);
672 if(t == nil)
673 continue;
674 if(*p != 0)
675 fprint(2, "extra desc '%s' in '%s'\n", p, desc);
676 /* void is defined as itself */
677 if(t->ty==Defer && t->sub==t && strcmp(name, "void")==0){
678 t->ty = Base;
679 t->xsizeof = 0;
680 t->printfmt = '0';
682 if(*name==' ' && *(name+1) == 0)
683 *name = 0;
684 /* attach names to structs, unions, enums */
685 if(c=='T' && *name && t->sue){
686 t->suename = name;
687 if(t->name == nil)
688 t->name = name;
689 tt = typebysue(t->sue, name);
690 tt->ty = Defer;
691 tt->sub = t;
693 if(c=='t'){
694 tt = newtype();
695 tt->ty = Typedef;
696 tt->name = name;
697 tt->sub = t;
699 /* define base c types */
700 if(t->ty==None || t->ty==Range){
701 if(strcmp(name, "char") == 0){
702 t->ty = Base;
703 t->xsizeof = 1;
704 t->printfmt = 'x';
706 if(strcmp(name, "int") == 0){
707 t->ty = Base;
708 t->xsizeof = 4;
709 t->printfmt = 'd';
712 /* record declaration in list for later. */
713 if(c != 't' && c != 'T')
714 switch(sym.type){
715 case N_GSYM:
716 addsymx(nil, name, t);
717 break;
718 case N_FUN:
719 fn = name;
720 break;
721 case N_PSYM:
722 case N_LSYM:
723 case N_LCSYM:
724 case N_STSYM:
725 case N_RSYM:
726 addsymx(fn, name, t);
727 break;
729 break;
733 printtypes(b);
734 dumpsyms(b);
735 freetypes();
737 return 0;