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 int fno, i;
604 char c, *dir, *fn, *file, *name, *desc, *p;
605 Ftypes *f;
606 Type *t, *tt;
607 StabSym sym;
609 dir = nil;
610 file = nil;
611 fno = 0;
612 fn = nil;
613 for(i=0; stabsym(stabs, i, &sym)>=0; i++){
614 switch(sym.type){
615 case N_SO:
616 if(sym.name){
617 if(sym.name[0] && sym.name[strlen(sym.name)-1] == '/')
618 dir = sym.name;
619 else
620 file = sym.name;
622 denumber();
623 fstack = nil;
624 fno = 0;
625 break;
626 case N_BINCL:
627 fno++;
628 f = mkftypes(dir, sym.name);
629 f->down = fstack;
630 fstack = f;
631 break;
632 case N_EINCL:
633 if(fstack)
634 fstack = fstack->down;
635 break;
636 case N_EXCL:
637 fno++;
638 if((f = findftypes(dir, sym.name)) == nil){
639 fprint(2, "cannot find remembered %s\n", sym.name);
640 continue;
642 renumber(f->list, fno);
643 break;
644 case N_GSYM:
645 case N_FUN:
646 case N_PSYM:
647 case N_LSYM:
648 case N_LCSYM:
649 case N_STSYM:
650 case N_RSYM:
651 name = sym.name;
652 if(name == nil){
653 if(sym.type==N_FUN)
654 fn = nil;
655 continue;
657 if((p = strchr(name, ':')) == nil)
658 continue;
659 name = estrndup(name, p-name);
660 desc = ++p;
661 c = *desc;
662 if(c == 'c'){
663 fprint(2, "skip constant %s\n", name);
664 continue;
666 if(setjmp(kaboom)){
667 fprint(2, "cannot parse %s\n", name);
668 continue;
670 t = parsename(desc, &p);
671 if(t == nil)
672 continue;
673 if(*p != 0)
674 fprint(2, "extra desc '%s' in '%s'\n", p, desc);
675 /* void is defined as itself */
676 if(t->ty==Defer && t->sub==t && strcmp(name, "void")==0){
677 t->ty = Base;
678 t->xsizeof = 0;
679 t->printfmt = '0';
681 if(*name==' ' && *(name+1) == 0)
682 *name = 0;
683 /* attach names to structs, unions, enums */
684 if(c=='T' && *name && t->sue){
685 t->suename = name;
686 if(t->name == nil)
687 t->name = name;
688 tt = typebysue(t->sue, name);
689 tt->ty = Defer;
690 tt->sub = t;
692 if(c=='t'){
693 tt = newtype();
694 tt->ty = Typedef;
695 tt->name = name;
696 tt->sub = t;
698 /* define base c types */
699 if(t->ty==None || t->ty==Range){
700 if(strcmp(name, "char") == 0){
701 t->ty = Base;
702 t->xsizeof = 1;
703 t->printfmt = 'x';
705 if(strcmp(name, "int") == 0){
706 t->ty = Base;
707 t->xsizeof = 4;
708 t->printfmt = 'd';
711 /* record declaration in list for later. */
712 if(c != 't' && c != 'T')
713 switch(sym.type){
714 case N_GSYM:
715 addsymx(nil, name, t);
716 break;
717 case N_FUN:
718 fn = name;
719 break;
720 case N_PSYM:
721 case N_LSYM:
722 case N_LCSYM:
723 case N_STSYM:
724 case N_RSYM:
725 addsymx(fn, name, t);
726 break;
728 break;
732 printtypes(b);
733 dumpsyms(b);
734 freetypes();
736 return 0;