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;
33 estrndup(char *s, int n)
43 mkpath(char *dir, char *name)
46 if(name[0] == '/' || dir == nil)
49 s = emalloc(strlen(dir)+strlen(name)+1);
57 mkftypes(char *dir, char *name)
61 f = emalloc(sizeof(*f));
62 f->file = mkpath(dir, name);
69 findftypes(char *dir, char *name)
75 s = mkpath(dir, name);
76 for(f=allftypes; f; f=f->next)
77 if(strcmp(f->file, s) == 0)
88 /* find a : but skip over :: */
92 while((p = strchr(p, ':')) != nil && *(p+1) == ':')
118 if(!isdigit((uchar)**pp))
120 return strtol(*pp, pp, 10);
124 name ::= symbol_opt info
127 parsename(char *desc, char **pp)
132 if(isdigit((uchar)*desc) || *desc=='-' || *desc=='(')
133 return parseinfo(desc, pp);
136 return parseinfo(desc+1, pp);
140 info ::= num | num '=' attr* defn
143 parseinfo(char *desc, char **pp)
150 parsenum(desc, &n1, &n2, &desc);
151 t = typebynum(n1, n2);
158 fstack->list = mktl(t, fstack->list);
159 while(parseattr(desc, &attr, &desc) >= 0){
161 t->xsizeof = atoi(attr+1)/8;
163 return parsedefn(desc, t, pp);
167 num ::= integer | '(' integer ',' integer ')'
170 parsenum(char *p, int *n1, int *n2, char **pp)
172 if(isdigit((uchar)*p)){
173 *n1 = strtol(p, &p, 10);
179 *n1 = strtol(p+1, &p, 10);
182 *n2 = strtol(p+1, &p, 10);
193 attr ::= '@' text ';'
196 'a' integer (alignment)
197 'p' integer (pointer class)
199 's' integer (size of type in bits)
200 'S' (string instead of array of chars)
203 parseattr(char *p, char **text, char **pp)
208 if((p = strchr(p, ';')) == nil)
215 typedef struct Basic Basic;
222 static Basic baseints[] =
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 */
261 static Basic basefloats[] =
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 */
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=)
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)
312 parsedefn(char *p, Type *t, char **pp)
315 int ischar, namelen, n, wid, offset, bits, sign;
319 if(*p == '(' || isdigit((uchar)*p)){
321 t->sub = parseinfo(p, pp);
326 case '-': /* builtin */
327 n = strtol(p+1, &p, 10);
328 if(n >= nelem(baseints) || n < 0)
331 t->xsizeof = baseints[n].size;
332 t->printfmt = baseints[n].fmt;
334 case 'b': /* builtin */
336 if(*p != 'u' && *p != 's')
347 offset = parseint(&p);
360 case 'R': /* fp type */
367 if(n < 0 || n >= nelem(basefloats))
369 t->xsizeof = basefloats[n].size;
370 t->printfmt = basefloats[n].fmt;
372 case 'r': /* subrange */
374 t->sub = parseinfo(p+1, &p);
375 if(*(p-1) == ';' && *p != ';')
378 t->lo = parsebound(&p);
380 t->hi = parsebound(&p);
383 case 'B': /* volatile */
384 case 'k': /* const */
386 t->sub = parseinfo(p+1, &p);
388 case '*': /* pointer */
389 case 'A': /* open array */
390 case '&': /* reference */ /* guess - C++? (rob) */
392 t->sub = parseinfo(p+1, &p);
394 case 'a': /* array */
395 case 'P': /* packed array */
398 parsedefn(p+1, tt, &p); /* index type */
403 parsedefn(p, tt, &p); /* element type */
405 case 'e': /* enum listing */
412 namelen = (p-name)-1;
413 val = parsebigint(&p);
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);
426 case 's': /* struct */
427 case 'u': /* union */
435 namelen = (p-name)-1;
436 tt = parseinfo(p, &p);
438 offset = parseint(&p);
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;
455 case 'x': /* struct, union, enum reference */
458 if(*p != 's' && *p != 'u' && *p != 'e')
463 name = estrndup(name, p-name);
464 t->sub = typebysue(c, name);
469 case 'f': /* function */
470 case 'p': /* procedure */
471 case 'F': /* Pascal function */
472 /* case 'R': /* Pascal procedure */
474 * Even though we don't use the info, we have
475 * to parse it in case it is embedded in other descriptions.
479 if(c == 'f' || c == 'F'){
480 t->sub = parseinfo(p, &p);
488 n = parseint(&p); /* number of params */
491 if(c == 'F' || c == 'R'){
492 name = p; /* parameter name */
495 parseinfo(p, &p); /* param type */
497 parseint(&p); /* bool: passed by value? */
504 case 'f': /* static function */
505 case 'F': /* global function */
508 t->sub = parseinfo(p, &p);
512 * We'll never see any of this stuff.
513 * When we do, we can worry about it.
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 */
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 */
527 fprint(2, "unsupported type char %c (%d)\n", *p, *p);
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)
544 parsebound(char **pp)
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 */
559 case 'J': /* no bound */
571 bigint ::= '-'? decimal
576 parsebigint(char **pp)
584 n = strtoll(p, &p, 8);
594 if(!isdigit((uchar)*p))
596 n = strtol(p, &p, 10);
606 stabs2acid(Stab *stabs, Biobuf *b)
610 char *volatile dir, *volatile fn, *volatile name;
618 for(i=0; stabsym(stabs, i, &sym)>=0; i++){
620 print("%d %s\n", sym.type, sym.name);
624 if(sym.name[0] && sym.name[strlen(sym.name)-1] == '/')
633 f = mkftypes(dir, sym.name);
639 fstack = fstack->down;
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);
650 renumber(f->list, fno);
665 if((p = findcolon(name)) == nil)
667 name = estrndup(name, p-name);
671 fprint(2, "skip constant %s\n", name);
675 static int cannotparse;
677 if(cannotparse++ == 0)
678 fprint(2, "cannot parse %s\n", name);
681 t = parsename(desc, &p);
685 static int extradesc;
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){
696 if(*name==' ' && *(name+1) == 0)
698 /* attach names to structs, unions, enums */
699 if(c=='T' && *name && t->sue){
703 tt = typebysue(t->sue, name);
713 /* define base c types */
714 if(t->ty==None || t->ty==Range){
715 if(strcmp(name, "char") == 0){
720 if(strcmp(name, "int") == 0){
726 /* record declaration in list for later. */
727 if(c != 't' && c != 'T')
730 addsymx(nil, name, t);
740 addsymx(fn, name, t);