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 uint15 hash(uint num, uint num1)16 {17 return (num*1009 + num1*1013) % nelem(thash);18 }20 static uint21 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 void32 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 void43 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 else70 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)102 {103 Type *t;104 static int gen;106 t = emalloc(sizeof *t);107 t->gen = ++gen;108 alltypes = mktl(t, alltypes);109 return t;110 }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)243 {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;252 }254 void255 denumber(void)256 {257 memset(thash, 0, sizeof thash);258 memset(namehash, 0, sizeof namehash);259 }261 void262 renumber(TypeList *tl, uint n1)263 {264 Type *t;266 for(; tl; tl=tl->tl){267 t = tl->hd;268 t->n1 = n1;269 addhash(t);270 }271 }273 Type*274 defer(Type *t)275 {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;288 }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;300 }301 return u;302 }304 static void305 dotypedef(Type *t)306 {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);322 }324 static int325 countbytes(uvlong x)326 {327 int n;329 for(n=0; x; n++)330 x>>=8;331 return n;332 }334 static void335 dorange(Type *t)336 {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 else355 t->printfmt = 'd';356 if(t->xsizeof == 0)357 t->xsizeof = countbytes(t->hi);358 }361 char*362 nameof(Type *t, int doanon)363 {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 else374 return "";375 for(p=buf; *p; p++)376 if(isspace((uchar)*p))377 *p = '_';378 return buf;379 }381 static char382 basecharof(Type *t) //XXX383 {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 else393 return 'x';394 case 4:395 if(t->printfmt=='d')396 return 'D';397 else if(t->printfmt=='f')398 return 'f';399 else400 return 'X';401 case 8:402 if(t->printfmt=='d')403 return 'V';404 else if(t->printfmt=='f')405 return 'F';406 else407 return 'Y';408 }409 }411 static int412 nilstrcmp(char *a, char *b)413 {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);421 }423 int careaboutaggrcount;425 static int426 typecmp(Type *t, Type *u)427 {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;458 }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;472 }473 if(t < u)474 return -1;475 if(t > u)476 return 1;477 return 0;478 }480 static int481 qtypecmp(const void *va, const void *vb)482 {483 Type *t, *u;485 t = *(Type**)va;486 u = *(Type**)vb;487 return typecmp(t, u);488 }490 void491 printtype(Biobuf *b, Type *t)492 {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;513 }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;523 }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;536 }537 }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;552 }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 else565 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;582 }583 }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;608 }609 }611 void612 printtypes(Biobuf *b)613 {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);629 }630 }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);639 }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 algorithm649 * to find the actual equivalence classes, and then rename types650 * 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 else666 all[i]->equiv = all[nn-1];667 }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;674 }676 for(i=0; i<nn; i++)677 printtype(b, all[i]);679 free(all);680 }682 void683 freetypes(void)684 {685 memset(thash, 0, sizeof(thash));686 memset(namehash, 0, sizeof namehash);687 }