Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5 #include <ctype.h>
6 #include "dat.h"
8 char *prefix = "";
10 static TypeList *thash[1021];
11 static TypeList *namehash[1021];
12 static TypeList *alltypes;
14 static uint
15 hash(uint num, uint num1)
16 {
17 return (num*1009 + num1*1013) % nelem(thash);
18 }
20 static uint
21 shash(char *s)
22 {
23 uint h;
25 h = 0;
26 for(; *s; s++)
27 h = 37*h + *s;
28 return h%nelem(namehash);
29 }
31 void
32 addnamehash(Type *t)
33 {
34 uint h;
36 if(t->name){
37 h = shash(t->name);
38 namehash[h] = mktl(t, namehash[h]);
39 }
40 }
42 static void
43 addhash(Type *t)
44 {
45 uint h;
47 if(t->n1 || t->n2){
48 h = hash(t->n1, t->n2);
49 thash[h] = mktl(t, thash[h]);
50 }
51 if(t->name)
52 addnamehash(t);
53 }
55 Type*
56 typebysue(char sue, char *name)
57 {
58 Type *t;
59 TypeList *tl;
61 for(tl=namehash[shash(name)]; tl; tl=tl->tl){
62 t = tl->hd;
63 if(t->sue==sue && t->suename && strcmp(name, t->suename)==0)
64 return t;
65 }
66 t = newtype();
67 if(sue=='e')
68 t->ty = Enum;
69 else
70 t->ty = Aggr;
71 if(sue=='u')
72 t->isunion = 1;
73 t->sue = sue;
74 t->suename = name;
75 addnamehash(t);
76 return t;
77 }
79 Type*
80 typebynum(uint n1, uint n2)
81 {
82 Type *t;
83 TypeList *tl;
85 if(n1 || n2){
86 for(tl=thash[hash(n1, n2)]; tl; tl=tl->tl){
87 t = tl->hd;
88 if(t->n1==n1 && t->n2==n2)
89 return t;
90 }
91 }
93 t = newtype();
94 t->n1 = n1;
95 t->n2 = n2;
96 addhash(t);
97 return t;
98 }
100 Type*
101 newtype(void)
103 Type *t;
104 static int gen;
106 t = emalloc(sizeof *t);
107 t->gen = ++gen;
108 alltypes = mktl(t, alltypes);
109 return t;
112 struct {
113 char *old;
114 char *new;
115 } fixes[] = { /* Font Tab 4 */
116 "append", "$append",
117 "builtin", "$builtin",
118 "complex", "$complex",
119 "delete", "$delete",
120 "do", "$do",
121 "else", "$else",
122 "eval", "$eval",
123 "fmt", "$fmt",
124 "fn", "$fn",
125 "head", "$head",
126 "if", "$if",
127 "local", "$local",
128 "loop", "$loop",
129 "ret", "$ret",
130 "tail", "$tail",
131 "then", "$then",
132 "var", "$var",
133 "whatis", "$whatis",
134 "while", "$while",
136 /* register names! */
137 /* generic */
138 "PC", "$PC",
139 "SP", "$SP",
140 "LR", "$LR",
141 "R0", "$R0",
142 "R1", "$R1",
143 "R2", "$R2",
144 "R3", "$R3",
145 "R4", "$R4",
146 "R5", "$R5",
147 "R6", "$R6",
148 "R7", "$R7",
149 "R8", "$R8",
150 "R9", "$R9",
151 "R10", "$R10",
152 "R11", "$R11",
153 "R12", "$R12",
154 "R13", "$R13",
155 "R14", "$R14",
156 "R15", "$R15",
157 "R16", "$R16",
158 "R17", "$R17",
159 "R18", "$R18",
160 "R19", "$R19",
161 "R20", "$R20",
162 "R21", "$R21",
163 "R22", "$R22",
164 "R23", "$R23",
165 "R24", "$R24",
166 "R25", "$R25",
167 "R26", "$R26",
168 "R27", "$R27",
169 "R28", "$R28",
170 "R29", "$R29",
171 "R30", "$R30",
172 "R31", "$R31",
173 "E0", "$E0",
174 "E1", "$E1",
175 "E2", "$E2",
176 "E3", "$E3",
177 "E4", "$E4",
178 "E5", "$E5",
179 "E6", "$E6",
180 "F0", "$F0",
181 "F1", "$F1",
182 "F2", "$F2",
183 "F3", "$F3",
184 "F4", "$F4",
185 "F5", "$F5",
186 "F6", "$F6",
187 "F7", "$F7",
188 "F8", "$F8",
189 "F9", "$F9",
190 "F10", "$F10",
191 "F11", "$F11",
192 "F12", "$F12",
193 "F13", "$F13",
194 "F14", "$F14",
195 "F15", "$F15",
196 "F16", "$F16",
197 "F17", "$F17",
198 "F18", "$F18",
199 "F19", "$F19",
200 "F20", "$F20",
201 "F21", "$F21",
202 "F22", "$F22",
203 "F23", "$F23",
204 "F24", "$F24",
205 "F25", "$F25",
206 "F26", "$F26",
207 "F27", "$F27",
208 "F28", "$F28",
209 "F29", "$F29",
210 "F30", "$F30",
211 "F31", "$F31",
213 /* 386 */
214 "DI", "$DI",
215 "SI", "$SI",
216 "BP", "$BP",
217 "BX", "$BX",
218 "DX", "$DX",
219 "CX", "$CX",
220 "AX", "$AX",
221 "GS", "$GS",
222 "FS", "$FS",
223 "ES", "$ES",
224 "DS", "$DS",
225 "TRAP", "$TRAP",
226 "ECODE", "$ECODE",
227 "CS", "$CS",
228 "EFLAGS", "$EFLAGS",
229 "SS", "$SS",
231 /* power */
232 "CAUSE", "$CAUSE",
233 "SRR1", "$SRR1",
234 "CR", "$CR",
235 "XER", "$XER",
236 "CTR", "$CTR",
237 "VRSAVE", "$VRSAVE",
238 "FPSCR", "$FPSCR",
239 };
241 char*
242 fixname(char *name)
244 int i;
246 if(name == nil)
247 return nil;
248 for(i=0; i<nelem(fixes); i++)
249 if(name[0]==fixes[i].old[0] && strcmp(name, fixes[i].old)==0)
250 return fixes[i].new;
251 return name;
254 void
255 denumber(void)
257 memset(thash, 0, sizeof thash);
258 memset(namehash, 0, sizeof namehash);
261 void
262 renumber(TypeList *tl, uint n1)
264 Type *t;
266 for(; tl; tl=tl->tl){
267 t = tl->hd;
268 t->n1 = n1;
269 addhash(t);
273 Type*
274 defer(Type *t)
276 Type *u, *oldt;
277 int n;
279 u = t;
280 n = 0;
281 oldt = t;
282 while(t && (t->ty == Defer || t->ty == Typedef)){
283 if(n++%2)
284 u = u->sub;
285 t = t->sub;
286 if(t == u) /* cycle */
287 goto cycle;
289 return t;
291 cycle:
292 fprint(2, "cycle\n");
293 t = oldt;
294 n = 0;
295 while(t && (t->ty==Defer || t->ty==Typedef)){
296 fprint(2, "t %p/%d %s\n", t, t->ty, t->name);
297 if(t == u && n++ == 2)
298 break;
299 t = t->sub;
301 return u;
304 static void
305 dotypedef(Type *t)
307 if(t->ty != Typedef && t->ty != Defer)
308 return;
310 if(t->didtypedef)
311 return;
313 t->didtypedef = 1;
314 if(t->sub == nil)
315 return;
317 /* push names downward to remove anonymity */
318 if(t->name && t->sub->name == nil)
319 t->sub->name = t->name;
321 dotypedef(t->sub);
324 static int
325 countbytes(uvlong x)
327 int n;
329 for(n=0; x; n++)
330 x>>=8;
331 return n;
334 static void
335 dorange(Type *t)
337 Type *tt;
339 if(t->ty != Range)
340 return;
341 if(t->didrange)
342 return;
343 t->didrange = 1;
344 tt = defer(t->sub);
345 if(tt == nil)
346 return;
347 dorange(tt);
348 if(t != tt && tt->ty != Base)
349 return;
350 t->ty = Base;
351 t->xsizeof = tt->xsizeof;
352 if(t->lo == 0)
353 t->printfmt = 'x';
354 else
355 t->printfmt = 'd';
356 if(t->xsizeof == 0)
357 t->xsizeof = countbytes(t->hi);
361 char*
362 nameof(Type *t, int doanon)
364 static char buf[1024];
365 char *p;
367 if(t->name)
368 strcpy(buf, fixname(t->name));
369 else if(t->suename)
370 snprint(buf, sizeof buf, "%s_%s", t->isunion ? "union" : "struct", t->suename);
371 else if(doanon)
372 snprint(buf, sizeof buf, "%s_%lud_", prefix, t->gen);
373 else
374 return "";
375 for(p=buf; *p; p++)
376 if(isspace((uchar)*p))
377 *p = '_';
378 return buf;
381 static char
382 basecharof(Type *t) //XXX
384 switch(t->xsizeof){
385 default:
386 return 'X';
387 case 1:
388 return 'b';
389 case 2:
390 if(t->printfmt=='d')
391 return 'd';
392 else
393 return 'x';
394 case 4:
395 if(t->printfmt=='d')
396 return 'D';
397 else if(t->printfmt=='f')
398 return 'f';
399 else
400 return 'X';
401 case 8:
402 if(t->printfmt=='d')
403 return 'V';
404 else if(t->printfmt=='f')
405 return 'F';
406 else
407 return 'Y';
411 static int
412 nilstrcmp(char *a, char *b)
414 if(a == b)
415 return 0;
416 if(a == nil)
417 return -1;
418 if(b == nil)
419 return 1;
420 return strcmp(a, b);
423 int careaboutaggrcount;
425 static int
426 typecmp(Type *t, Type *u)
428 int i;
430 if(t == u)
431 return 0;
432 if(t == nil)
433 return -1;
434 if(u == nil)
435 return 1;
437 if(t->ty < u->ty)
438 return -1;
439 if(t->ty > u->ty)
440 return 1;
442 if(t->isunion != u->isunion)
443 return t->isunion - u->isunion;
445 i = nilstrcmp(t->name, u->name);
446 if(i)
447 return i;
449 i = nilstrcmp(t->suename, u->suename);
450 if(i)
451 return i;
453 if(careaboutaggrcount && t->ty == Aggr){
454 if(t->n > u->n)
455 return -1;
456 if(t->n < u->n)
457 return 1;
460 if(t->name || t->suename)
461 return 0;
463 if(t->ty==Enum){
464 if(t->n < u->n)
465 return -1;
466 if(t->n > u->n)
467 return 1;
468 if(t->n == 0)
469 return 0;
470 i = strcmp(t->tname[0], u->tname[0]);
471 return i;
473 if(t < u)
474 return -1;
475 if(t > u)
476 return 1;
477 return 0;
480 static int
481 qtypecmp(const void *va, const void *vb)
483 Type *t, *u;
485 t = *(Type**)va;
486 u = *(Type**)vb;
487 return typecmp(t, u);
490 void
491 printtype(Biobuf *b, Type *t)
493 char *name;
494 int j, nprint;
495 Type *tt, *ttt;
497 if(t->printed)
498 return;
499 t->printed = 1;
500 switch(t->ty){
501 case Aggr:
502 name = nameof(t, 1);
503 Bprint(b, "sizeof%s = %lud;\n", name, t->xsizeof);
504 Bprint(b, "aggr %s {\n", name);
505 nprint = 0;
506 for(j=0; j<t->n; j++){
507 tt = defer(t->t[j]);
508 if(tt && tt->equiv)
509 tt = tt->equiv;
510 if(tt == nil){
511 Bprint(b, "// oops: nil type\n");
512 continue;
514 switch(tt->ty){
515 default:
516 Bprint(b, "// oops: unknown type %d for %p/%s (%d,%d; %c,%s; %p)\n",
517 tt->ty, tt, fixname(t->tname[j]),
518 tt->n1, tt->n2, tt->sue ? tt->sue : '.', tt->suename, tt->sub);
519 Bprint(b, "// t->t[j] = %p\n", ttt=t->t[j]);
520 while(ttt){
521 Bprint(b, "// %s %d (%d,%d) sub %p\n", ttt->name, ttt->ty, ttt->n1, ttt->n2, ttt->sub);
522 ttt=ttt->sub;
524 case Base:
525 case Pointer:
526 case Enum:
527 case Array:
528 case Function:
529 nprint++;
530 Bprint(b, "\t'%c' %lud %s;\n", basecharof(tt), t->val[j], fixname(t->tname[j]));
531 break;
532 case Aggr:
533 nprint++;
534 Bprint(b, "\t%s %lud %s;\n", nameof(tt, 1), t->val[j], fixname(t->tname[j]));
535 break;
538 if(nprint == 0)
539 Bprint(b, "\t'X' 0 __dummy;\n");
540 Bprint(b, "};\n\n");
542 name = nameof(t, 1); /* might have smashed it */
543 Bprint(b, "defn %s(addr) { indent_%s(addr, \"\"); }\n", name, name);
544 Bprint(b, "defn\nindent_%s(addr, indent) {\n", name);
545 Bprint(b, "\tcomplex %s addr;\n", name);
546 for(j=0; j<t->n; j++){
547 name = fixname(t->tname[j]);
548 tt = defer(t->t[j]);
549 if(tt == nil){
550 Bprint(b, "// oops nil %s\n", name);
551 continue;
553 switch(tt->ty){
554 case Base:
555 base:
556 Bprint(b, "\tprint(indent, \"%s\t\", addr.%s, \"\\n\");\n",
557 name, name);
558 break;
559 case Pointer:
560 ttt = defer(tt->sub);
561 if(ttt && ttt->ty == Aggr)
562 Bprint(b, "\tprint(indent, \"%s\t(%s)\", addr.%s, \"\\n\");\n",
563 name, nameof(ttt, 1), name);
564 else
565 goto base;
566 break;
567 case Array:
568 Bprint(b, "\tprint(indent, \"%s\t\", addr.%s\\X, \"\\n\");\n",
569 name, name);
570 break;
571 case Enum:
572 Bprint(b, "\tprint(indent, \"%s\t\", addr.%s, \" \", %s(addr.%s), \"\\n\");\n",
573 name, name, nameof(tt, 1), name);
574 break;
575 case Aggr:
576 Bprint(b, "\tprint(indent, \"%s\t%s{\\n\");\n",
577 name, nameof(tt, 0));
578 Bprint(b, "\tindent_%s(addr+%lud, indent+\" \");\n",
579 nameof(tt, 1), t->val[j]);
580 Bprint(b, "\tprint(indent, \"}\\n\");\n");
581 break;
584 Bprint(b, "};\n\n");
585 break;
587 case Enum:
588 name = nameof(t, 1);
589 Bprint(b, "// enum %s\n", name);
590 for(j=0; j<t->n; j++)
591 Bprint(b, "%s = %ld;\n", fixname(t->tname[j]), t->val[j]);
593 Bprint(b, "vals_%s = {\n", name);
594 for(j=0; j<t->n; j++)
595 Bprint(b, "\t%lud,\n", t->val[j]);
596 Bprint(b, "};\n");
597 Bprint(b, "names_%s = {\n", name);
598 for(j=0; j<t->n; j++)
599 Bprint(b, "\t\"%s\",\n", fixname(t->tname[j]));
600 Bprint(b, "};\n");
601 Bprint(b, "defn\n%s(val) {\n", name);
602 Bprint(b, "\tlocal i;\n");
603 Bprint(b, "\ti = match(val, vals_%s);\n", name);
604 Bprint(b, "\tif i >= 0 then return names_%s[i];\n", name);
605 Bprint(b, "\treturn \"???\";\n");
606 Bprint(b, "};\n");
607 break;
611 void
612 printtypes(Biobuf *b)
614 int i, n, nn;
615 Type *t, *tt, **all;
616 TypeList *tl;
618 /* check that pointer resolved */
619 for(tl=alltypes; tl; tl=tl->tl){
620 t = tl->hd;
621 if(t->ty==None){
622 if(t->n1 || t->n2)
623 warn("type %d,%d referenced but not defined", t->n1, t->n2);
624 else if(t->sue && t->suename)
625 warn("%s %s referenced but not defined",
626 t->sue=='s' ? "struct" :
627 t->sue=='u' ? "union" :
628 t->sue=='e' ? "enum" : "???", t->suename);
632 /* push typedefs down, base types up */
633 n = 0;
634 for(tl=alltypes; tl; tl=tl->tl){
635 n++;
636 t = tl->hd;
637 if(t->ty == Typedef || t->ty == Defer)
638 dotypedef(t);
641 /* push ranges around */
642 for(tl=alltypes; tl; tl=tl->tl)
643 dorange(tl->hd);
645 /*
646 * only take one type of a given name; acid is going to do this anyway,
647 * and this will reduce the amount of code we output considerably.
648 * we could run a DFA equivalence relaxation sort of algorithm
649 * to find the actual equivalence classes, and then rename types
650 * appropriately, but this will do for now.
651 */
652 all = emalloc(n*sizeof(all[0]));
653 n = 0;
654 for(tl=alltypes; tl; tl=tl->tl)
655 all[n++] = tl->hd;
657 careaboutaggrcount = 1;
658 qsort(all, n, sizeof(all[0]), qtypecmp);
659 careaboutaggrcount = 0;
661 nn = 0;
662 for(i=0; i<n; i++){
663 if(i==0 || typecmp(all[i-1], all[i]) != 0)
664 all[nn++] = all[i];
665 else
666 all[i]->equiv = all[nn-1];
669 for(tl=alltypes; tl; tl=tl->tl){
670 t = tl->hd;
671 tt = defer(t);
672 if(tt && tt->equiv)
673 t->equiv = tt->equiv;
676 for(i=0; i<nn; i++)
677 printtype(b, all[i]);
679 free(all);
682 void
683 freetypes(void)
685 memset(thash, 0, sizeof(thash));
686 memset(namehash, 0, sizeof namehash);