#include "i.h" // Descriptors of all types that need to be garbage collected typedef struct Descr Descr; struct Descr { char* name; uchar size; // in bytes; 0 means variable uchar align; uchar* members; }; // keep this enum synchronized with descr table, below! // start enum at 1 so 0 marks end of members array. enum { DTchar = 1, // 1 byte DTshort, // 2 bytes DTlong, // 4 bytes DTstring, // ptr to null terminated char array DTString, // ptr to null terminated Rune array DTptr, // followed by code for pointed-to object DTptrnogc, // pointer to stuff from usual malloc regime (just copy) DTptrnogcnil, // pointer that should be nil at gc time DTarray, // next two bytes are length, high order first // ((255,x) means use x as signed char byte offset // from array start to long elem count)), // then code for element type DTptrarray, // pointer to array // next two bytes are length (as in DTarray), with // count offset relative to this ptr in current struct DTptrarray2d, // pointer to array of arrays, both counts in this struct // first comes count for rows // then count for cols, then elem type DTunion, // union assumed to start with a long tag. // following byte is DT code for type (of data following tag) // correponding to tag==0, and rest of variants are // assumed sequential after that, // up until (and including) code of next byte DTvunion, // "variable union": i.e., different variants are allocated // at different lengths. // following byte is offset to long tag. // then comes DT code for type (of all data in the vunion) // correponding to tag==0, and rest of variants are // assumed sequential after that // up until (and including) code of next byte NUMBUILTINDTS, // from draw.h DTPoint = NUMBUILTINDTS, DTRectangle, // from i.h DTList, DTStrlist, DTParsedUrl, DTStringInt, DTConfig, DTReqInfo, DTMaskedImage, DTCImage, DTHeader, DTResourceState, DTToken, DTAttr, DTAlign, DTDimen, DTBackground, DTItem, DTItext, DTIrule, DTIimage, DTIformfield, DTItable, DTIfloat, DTIspacer, DTItemlist, DTGenattr, DTFormfield, DTOption, DTForm, DTTable, DTTablecol, DTTablerow, DTTablecell, DTAnchor, DTDestAnchor, DTMap, DTArea, DTKidinfo, DTDocinfo, DTFrame, DTFramelist, DTLine, DTLoc, DTLocelem, DTControl, DTCbutton, DTCentry, DTCcheckbox, DTCselect, DTCscrollbar, DTCanimimage, DTCprogbox, DTClabel, DTLay, DTEV, DTEVkey, DTEVmouse, DTEVmove, DTEVresize, DTEVexpose, DTEVhide, DTEVquit, DTEVstop, DTEValert, DTEVform, DTEVgo, DTEVanim, DTEVprogress, DTEVdelay, DTScriptEvent, DTGoSpec, DTDocConfig, DTHistNode, DTHistNode_list, DTHistory, DTAuthInfo, DTCtlLayout, DTProgLayout, DTPopupLayout, DTPopupAns, NUMDTS }; // (acid used to derive the descriptor tables) static uchar d_point[] = { DTlong, DTlong, 0 }; static uchar d_rectangle[] = { DTPoint, DTPoint, 0 }; static uchar d_list[] = { DTptr, DTList, DTlong, 0 }; static uchar d_strlist[]= { DTptr, DTStrlist, DTString, 0 }; static uchar d_parsedurl[] = { DTarray, 0, 18, DTlong, DTarray, 255, (uchar)((signed char)-4), DTshort, 0 }; static uchar d_stringint[] = { DTString, DTlong, 0 }; static uchar d_config[] = { DTString, // userdir DTptr, DTParsedUrl, // starturl DTptr, DTParsedUrl, // homeurl DTptr, DTParsedUrl, // httpproxy DTlong, // defaultwidth DTlong, // defaultheight DTlong, // x DTlong, // y DTlong, // nocache DTlong, // maxstale DTlong, // imagelvl DTlong, // imagecachenum DTlong, // imagecachemem DTlong, // docookies DTlong, // doscripts DTlong, // saveauthinfo DTlong, // showprogress DTlong, // usecci DTlong, // httpminor DTString, // agentname DTlong, // nthreads DTString, // dbgfile DTarray, 0, 128, DTchar, // dbg 0 }; static uchar d_reqinfo[] = { DTptr, DTParsedUrl, DTlong, DTstring, DTlong, DTString, DTlong, 0 }; static uchar d_maskedimage[] = { DTptrnogc, DTptrnogc, DTlong, DTlong, DTlong, DTPoint, 0 }; static uchar d_cimage[] = { DTptr, DTCImage, DTptr, DTParsedUrl, DTptr, DTParsedUrl, DTlong, DTlong, DTlong, DTlong, DTptrarray, 255, 4, DTptr, DTMaskedImage, DTlong, 0 }; static uchar d_header[] = { DTlong, DTptr, DTParsedUrl, DTptr, DTParsedUrl, DTptr, DTParsedUrl, DTlong, DTlong, DTlong, DTString, DTString, DTString, DTString, 0 }; static uchar d_resourcestate[] = { DTlong, DTlong, DTlong, 0 }; static uchar d_token[] = { DTlong, DTString, DTptr, DTAttr, DTlong, 0 }; static uchar d_attr[] = { DTptr, DTAttr, DTlong, DTString, 0 }; static uchar d_align[] = { DTchar, DTchar, 0 }; static uchar d_dimen[] = { DTlong, 0 }; static uchar d_background[] = { DTptr, DTCImage, DTlong, 0 }; static uchar d_item[] = { DTvunion, 28, DTItext, DTIspacer, 0 }; static uchar d_itext[] = { DTptr, DTItem, DTlong, DTlong, DTlong, DTlong, DTlong, DTptr, DTGenattr, DTlong, DTString, DTlong,DTlong, DTchar, DTchar, 0 }; static uchar d_irule[] = { DTptr, DTItem, DTlong, DTlong, DTlong, DTlong, DTlong, DTptr, DTGenattr, DTlong, DTchar, DTchar, DTlong, DTDimen, 0 }; static uchar d_iimage[] = { DTptr, DTItem, DTlong, DTlong, DTlong, DTlong, DTlong, DTptr, DTGenattr, DTlong, DTptr, DTCImage, DTlong, DTlong, // ci, imwidth, imheight DTString, DTptr, DTMap, DTlong, // altrep, map, ctlid DTchar, DTchar, DTchar, DTchar, // align, hspace, vspace, border DTptr, DTIimage, // nextimage 0 }; static uchar d_iformfield[] = { DTptr, DTItem, DTlong, DTlong, DTlong, DTlong, DTlong, DTptr, DTGenattr, DTlong, DTptr, DTFormfield, 0 }; static uchar d_itable[] = { DTptr, DTItem, DTlong, DTlong, DTlong, DTlong, DTlong, DTptr, DTGenattr, DTlong, DTptr, DTTable, 0 }; static uchar d_ifloat[] = { DTptr, DTItem, DTlong, DTlong, DTlong, DTlong, DTlong, DTptr, DTGenattr, DTlong, DTptr, DTItem, DTlong, DTlong, DTchar, DTchar, DTptr, DTIfloat, 0 }; static uchar d_ispacer[] = { DTptr, DTItem, DTlong, DTlong, DTlong, DTlong, DTlong, DTptr, DTGenattr, DTlong, DTlong, 0 }; static uchar d_iitemlist[] = { DTptr, DTItemlist, DTptr, DTItem, 0 }; static uchar d_genattr[] = { DTString, DTString, DTString, DTString, DTptr, DTAttr, 0 }; static uchar d_formfield[] = { DTptr, DTFormfield, DTlong, DTlong, DTptr, DTForm, DTString, DTString, DTlong, DTlong, DTlong, DTlong, DTchar, DTptr, DTOption, DTptr, DTItem, DTlong, DTptr, DTAttr, 0 }; static uchar d_option[] = { DTptr, DTOption, DTlong, DTString, DTString, 0 }; static uchar d_form[] = { DTptr, DTForm, DTlong, DTString, DTptr, DTParsedUrl, DTlong, DTlong, DTlong, DTptr, DTFormfield, 0 }; static uchar d_table[] = { DTptr, DTTable, DTlong, DTlong, DTptrarray, 255, 4, DTTablerow, // NOTE: don't gc during parsing! DTlong, DTptrarray, 255, 4, DTTablecol, DTptr, DTTablecell, DTlong, DTptrarray2d, 255, (uchar)-20, 255, (uchar)-12, DTptr, DTTablecell, DTAlign, DTDimen, DTlong, DTlong, DTlong, DTBackground, DTptr, DTItem, DTchar, DTptr, DTLay, DTlong, DTlong, DTlong, DTlong, DTptr, DTToken, DTchar, 0 }; static uchar d_tablecol[] = { DTlong, DTAlign, DTPoint, 0 }; static uchar d_tablerow[] = { DTptr, DTTablerow, DTptr, DTTablecell, DTlong, DTlong, DTAlign, DTBackground, DTPoint, DTchar, 0 }; static uchar d_tablecell[] = { DTptr, DTTablecell, DTptr, DTTablecell, DTlong, DTptr, DTItem, DTptr, DTLay, DTlong, DTlong, DTAlign, DTchar, DTDimen, DTlong, DTBackground, DTlong, DTlong, DTlong, DTlong, DTlong, DTPoint, 0 }; static uchar d_anchor[] = { DTptr, DTAnchor, DTlong, DTString, DTptr, DTParsedUrl, DTlong, 0 }; static uchar d_destanchor[] = { DTptr, DTDestAnchor, DTlong, DTString, DTptr, DTItem, 0 }; static uchar d_map[] = { DTptr, DTMap, DTString, DTptr, DTArea, 0}; static uchar d_area[] = { DTptr, DTArea, DTlong, DTptr, DTParsedUrl, DTlong, DTptrarray, 255, 4, DTDimen, DTlong, 0 }; static uchar d_kidinfo[] = { DTptr, DTKidinfo, DTlong, DTptr, DTParsedUrl, DTString, DTlong, DTlong, DTlong, DTlong, DTptrarray, 255, 4, DTDimen, DTlong, DTptrarray, 255, 4, DTDimen, DTlong, DTptr, DTKidinfo, DTptr, DTKidinfo, 0 }; static uchar d_docinfo[] = { DTptr, DTParsedUrl, DTptr, DTParsedUrl, // src, base DTString, DTBackground, // doctitle, background DTptr, DTIimage, // backgrounditem DTlong, DTlong, DTlong, DTlong, // text, link, vlink, alink DTlong, DTlong, DTlong, DTlong, // target, chset, scripttype, hasscripts DTString, DTptr, DTKidinfo, DTlong, // refresh, kidinfo, frameid DTptr, DTAnchor, DTptr, DTDestAnchor, // anchors, dests DTptr, DTForm, DTptr, DTTable, // forms, tables DTptr, DTMap, DTptr, DTIimage, // maps, images 0 }; static uchar d_frame[] = { DTlong, DTptr, DTDocinfo, // id, doc DTptr, DTParsedUrl, DTString, // src, name DTlong, DTlong, DTlong, DTlong, // marginw, marginh, framebd, flags DTptr, DTLay, // layout DTptrarray, 255, 4, DTptr, DTControl, // controls DTlong, DTlong, // controlslen, controlid DTptrnogc, // cim DTRectangle, DTRectangle, // r, cr DTRectangle, DTRectangle, // totalr, viewr DTptr, DTControl, DTptr, DTControl, // vscr, hscr DTptr, DTFrame, DTptr, DTFramelist, // parent, kids 0 }; static uchar d_framelist[] = { DTptr, DTFramelist, DTptr, DTFrame, 0 }; static uchar d_line[] = { DTptr, DTLine, DTptr, DTLine, DTptr, DTItem, DTPoint, DTlong, DTlong, DTlong, DTchar, 0 }; static uchar d_loc[] = { DTptrarray, 255, 4, DTLocelem, DTlong, DTlong, DTPoint, 0 }; static uchar d_locelem[] = { DTlong, DTPoint, DTptr, DTFrame, DTptr, DTLine, DTptr, DTItem, DTptr, DTTablecell, DTptr, DTControl, 0 }; static uchar d_control[] = { DTvunion, 16, DTCbutton, DTClabel, 0 }; static uchar d_cbutton[] = { DTptr, DTFrame, DTptr, DTFormfield, DTRectangle, DTlong, DTlong, DTptrnogc, DTptrnogc, DTptrnogc, DTptrnogc, DTString, DTlong, 0 }; static uchar d_centry[] = { DTptr, DTFrame, DTptr, DTFormfield, DTRectangle, DTlong, DTlong, DTString, DTlong, DTlong, DTlong, 0 }; static uchar d_ccheckbox[] = { DTptr, DTFrame, DTptr, DTFormfield, DTRectangle, DTlong, DTlong, DTlong, 0 }; static uchar d_cselect[] = { DTptr, DTFrame, DTptr, DTFormfield, DTRectangle, DTlong, DTlong, DTptr, DTCscrollbar, DTlong, DTlong, DTptr, DTOption, DTlong, 0 }; static uchar d_cscrollbar[] = { DTptr, DTFrame, DTptr, DTFormfield, DTRectangle, DTlong, DTlong, DTlong, DTlong, DTlong, DTlong, DTptr, DTControl, 0 }; static uchar d_canimimage[] = { DTptr, DTFrame, DTptr, DTFormfield, DTRectangle, DTlong, DTlong, DTptr, DTCImage, DTlong, DTlong, DTBackground, 0 }; static uchar d_cprogbox[] = { DTptr, DTFrame, DTptr, DTFormfield, DTRectangle, DTlong, DTlong, DTlong, DTlong, DTlong, DTString, DTString, 0 }; static uchar d_clabel[] = { DTptr, DTFrame, DTptr, DTFormfield, DTRectangle, DTlong, DTlong, DTString, 0 }; static uchar d_lay[] = { DTptr, DTLine, DTptr, DTLine, DTlong, DTlong, DTlong, DTlong, DTptr, DTIfloat, DTBackground, DTchar, DTchar, 0 }; static uchar d_ev[] = { DTunion, DTEVkey, DTEVdelay, 0 }; static uchar d_evkey[] = { DTlong, DTlong, 0 }; static uchar d_evmouse[] = { DTlong, DTPoint, DTlong, 0 }; static uchar d_evmove[] = { DTlong, DTPoint, 0 }; static uchar d_evresize[] = { DTlong, DTRectangle, 0 }; static uchar d_evexpose[] = { DTlong, 0 }; static uchar d_evhide[] = { DTlong, 0 }; static uchar d_evquit[] = { DTlong, 0 }; static uchar d_evstop[] = { DTlong, 0 }; static uchar d_evalert[] = { DTlong, DTString, DTptrnogc, 0 }; static uchar d_evform[] = { DTlong, DTlong, DTlong, DTlong, 0 }; static uchar d_evgo[] = { DTlong, DTptr, DTParsedUrl, DTlong, DTlong, 0 }; static uchar d_evanim[] = { DTlong, DTlong, DTptr, DTCanimimage, 0 }; static uchar d_evprogress[] = { DTlong, DTlong, DTlong, DTlong, DTString, 0 }; static uchar d_evdelay[] = { DTlong, DTlong, DTptr, DTEV, 0 }; static uchar d_scriptevent[] = { DTarray, 0, 8, DTlong, 0 }; static uchar d_gospec[] = { DTlong, DTptr, DTParsedUrl, DTlong, DTString, DTlong, DTString, DTptr, DTHistNode, 0 }; static uchar d_docconfig[] = { DTString, DTString, DTlong, DTptr, DTGoSpec, 0 }; static uchar d_histnode[] = { DTptr, DTDocConfig, DTptrarray, 255, 4, DTptr, DTDocConfig, DTlong, DTptr, DTHistNode_list, DTptr, DTHistNode_list, 0 }; static uchar d_histnode_list[] = { DTptr, DTHistNode_list, DTptr, DTHistNode, 0 }; static uchar d_history[] = { DTptrarray, 255, 4, DTlong, DTlong, DTlong, 0 }; static uchar d_authinfo[] = { DTptr, DTAuthInfo, DTString, DTString, 0 }; static uchar d_ctllayout[] = { DTptrnogc, DTPoint, DTPoint, DTPoint, DTPoint, DTarray, 0, NUMCLCS, DTptr, DTControl, DTString, 0 }; static uchar d_proglayout[] = { DTptrarray, 255, 4, DTptr, DTControl, DTlong, DTlong, DTPoint, DTlong, 0 }; static uchar d_popuplayout[] = { DTlong, DTptrarray, 255, 4, DTptr, DTControl, DTlong, DTptr, DTControl, DTptr, DTControl, 0 }; static uchar d_popupans[] = { DTlong, DTString, 0 }; // keep this table synchronized with DT enum! Descr descr[] = { { "dummy", 0, 0, nil }, { "char", sizeof(char), sizeof(char), nil }, { "short", sizeof(short), sizeof(short), nil }, { "long", sizeof(long), sizeof(long), nil }, { "string", sizeof(void*), sizeof(void*), nil }, { "String", sizeof(void*), sizeof(void*), nil }, { "ptr", sizeof(void*), sizeof(void*), nil }, { "ptrnogc", sizeof(void*), sizeof(void*), nil }, { "ptrnogcnil", sizeof(void*), sizeof(void*), nil }, { "array", 0, 4, nil }, { "ptrarray", sizeof(void*), sizeof(void*), nil }, { "ptrarray2d", sizeof(void*), sizeof(void*), nil }, { "union", 0, 4, nil }, { "vunion", 0, 4, nil }, { "Point", sizeof(Point), 4, d_point }, { "Rectangle", sizeof(Rectangle), 4, d_rectangle }, { "List", sizeof(List), 4, d_list }, { "Strlist", sizeof(Strlist), 4, d_strlist }, { "ParsedUrl", 0, 4, d_parsedurl }, { "StringInt", sizeof(StringInt), 4, d_stringint }, { "Config", sizeof(Config), 4, d_config }, { "ReqInfo", sizeof(ReqInfo), 4, d_reqinfo }, { "MaskedImage", sizeof(MaskedImage), 4, d_maskedimage }, { "CImage", sizeof(CImage), 4, d_cimage }, { "Header", sizeof(Header), 4, d_header }, { "ResourceState", sizeof(ResourceState), 4, d_resourcestate }, { "Token", sizeof(Token), 4, d_token }, { "Attr", sizeof(Attr), 4, d_attr }, { "Align", sizeof(Align), 4, d_align }, { "Dimen", sizeof(Dimen), 4, d_dimen }, { "Background", sizeof(Background), 4, d_background }, { "Item", 0, 4, d_item }, { "Itext", sizeof(Itext), 4, d_itext }, { "Irule", sizeof(Irule), 4, d_irule }, { "Iimage", sizeof(Iimage), 4, d_iimage }, { "Iformfield", sizeof(Iformfield), 4, d_iformfield }, { "Itable", sizeof(Itable), 4, d_itable }, { "Ifloat", sizeof(Ifloat), 4, d_ifloat }, { "Ispacer", sizeof(Ispacer), 4, d_ispacer }, { "Itemlist", sizeof(Itemlist), 4, d_iitemlist }, { "Genattr", sizeof(Genattr), 4, d_genattr }, { "Formfield", sizeof(Formfield), 4, d_formfield }, { "Option", sizeof(Option), 4, d_option }, { "Form", sizeof(Form), 4, d_form }, { "Table", sizeof(Table), 4, d_table }, { "Tablecol", sizeof(Tablecol), 4, d_tablecol }, { "Tablerow", sizeof(Tablerow), 4, d_tablerow }, { "Tablecell", sizeof(Tablecell), 4, d_tablecell }, { "Anchor", sizeof(Anchor), 4, d_anchor }, { "DestAnchor", sizeof(DestAnchor), 4, d_destanchor }, { "Map", sizeof(Map), 4, d_map }, { "Area", sizeof(Area), 4, d_area }, { "Kidinfo", sizeof(Kidinfo), 4, d_kidinfo }, { "Docinfo", sizeof(Docinfo), 4, d_docinfo }, { "Frame", sizeof(Frame), 4, d_frame }, { "Framelist", sizeof(Framelist), 4, d_framelist }, { "Line", sizeof(Line), 4, d_line }, { "Loc", sizeof(Loc), 4, d_loc }, { "Locelem", sizeof(Locelem), 4, d_locelem }, { "Control", 0, 4, d_control }, { "Cbutton", sizeof(Cbutton), 4, d_cbutton }, { "Centry", sizeof(Centry), 4, d_centry }, { "Ccheckbox", sizeof(Ccheckbox), 4, d_ccheckbox }, { "Cselect", sizeof(Cselect), 4, d_cselect }, { "Cscrollbar", sizeof(Cscrollbar), 4, d_cscrollbar }, { "Canimimage", sizeof(Canimimage), 4, d_canimimage }, { "Cprogbox", sizeof(Cprogbox), 4, d_cprogbox }, { "Clabel", sizeof(Clabel), 4, d_clabel }, { "Lay", sizeof(Lay), 4, d_lay }, { "EV", sizeof(EV), 4, d_ev }, { "EVkey", 8, 4, d_evkey }, { "EVmouse", 16, 4, d_evmouse }, { "EVmove", 12, 4, d_evmove }, { "EVresize", 20, 4, d_evresize }, { "EVexpose", 4, 4, d_evexpose }, { "EVhide", 4, 4, d_evhide }, { "EVquit", 4, 4, d_evquit }, { "EVstop", 4, 4, d_evstop }, { "EValert", 12, 4, d_evalert }, { "EVform", 16, 4, d_evform }, { "EVgo", 16, 4, d_evgo }, { "EVanim", 12, 4, d_evanim }, { "EVprogress", 20, 4, d_evprogress }, { "EVdelay", 12, 4, d_evdelay }, { "ScriptEvent", sizeof(ScriptEvent), 4, d_scriptevent }, { "GoSpec", sizeof(GoSpec), 4, d_gospec }, { "DocConfig", sizeof(DocConfig), 4, d_docconfig }, { "HistNode", sizeof(HistNode), 4, d_histnode }, { "HistNode_list", sizeof(HistNode_list), 4, d_histnode_list }, { "History", sizeof(History), 4, d_history }, { "AuthInfo", sizeof(AuthInfo), 4, d_authinfo }, { "CtlLayout", sizeof(CtlLayout), 4, d_ctllayout }, { "ProgLayout", sizeof(ProgLayout), 4, d_proglayout }, { "PopupLayout", sizeof(PopupLayout), 4, d_popuplayout }, { "PopupAns", sizeof(PopupAns), 4, d_popupans }, }; static int calcsizeof(int ty); static void checkgctables(void); // al is power of two. // round n up to nearest multiple of al, if not already one. // assume n >= 0. static int alignto(int n, int al) { ulong m; m = al-1; if((n&m) != 0) n = (n+al)&(~m); return n; } // v should point at a 2-byte count (possibly // a "variable" count, with 255 in first byte). // skip over it, and put pointer to count in *pcnt, // using -1 if variable and putting offset into *poff. // return pointer to just after the type. static uchar* skipcount(uchar* v, int* pcnt, int *poff) { int a, c, o; a = *v++; if(a == 255) { c = -1; o = (signed char)(*v++); assert((o&3)==0); } else { c = (a<<8) | *v++; o = 0; assert(c < 1000); // currently bigger than any static array } *pcnt = c; *poff = o; return v; } // v should point at type (may be variable length). // skip over the type, doing sanity checks, // and return pointer to just after the type. static uchar* skiptype(uchar* v) { int t, t2, c, o; t = *v++; assert(t >= 1 && t < NUMDTS); switch(t) { case DTptr: v = skiptype(v); break; case DTptrnogc: case DTptrnogcnil: break; case DTarray: case DTptrarray: v = skipcount(v, &c, &o); v = skiptype(v); case DTptrarray2d: v = skipcount(v, &c, &o); v = skipcount(v, &c, &o); v = skiptype(v); break; case DTunion: t = *v++; assert(t >= NUMBUILTINDTS && t < NUMDTS); t2 = *v++; assert(t2 > t && t2 < NUMDTS); break; case DTvunion: o = (signed char)(*v++); assert((o&3) == 0); t = *v++; assert(t >= NUMBUILTINDTS && t < NUMDTS); t2 = *v++; assert(t2 > t && t2 < NUMDTS); break; } return v; } // Calculate sizeof one member, whose description // starts at *v. // Put size in *psz (-1 if variable size), and return updated v. static uchar* calcsizeof1(uchar* v, int* psz) { int t, t2, n, c, o; Descr* d; t = *v++; assert(t >= 1 && t < NUMDTS); d = &descr[t]; n = 0; switch(t) { case DTptr: n = d->size; v = skiptype(v); break; case DTptrnogc: case DTptrnogcnil: n = d->size; break; case DTarray: v = skipcount(v, &n, &o); if(n != -1) { v = calcsizeof1(v, &c); if(c == -1) n = -1; else n *= c; } break; case DTptrarray: n = d->size; v = skipcount(v, &c, &o); v = skiptype(v); break; case DTptrarray2d: n = d->size; v = skipcount(v, &c, &o); v = skipcount(v, &c, &o); v = skiptype(v); break; case DTunion: t = *v++; assert(t >= NUMBUILTINDTS && t < NUMDTS); t2 = *v++; assert(t2 > t && t2 < NUMDTS); for( ; t <= t2; t++) { c = calcsizeof(t); assert(c != -1); if(c > n) n = c; } n += sizeof(long); // for tag break; case DTvunion: o = (signed char)(*v++); assert((o&3) == 0); t = *v++; assert(t >= NUMBUILTINDTS && t < NUMDTS); t2 = *v++; assert(t2 > t && t2 < NUMDTS); n = -1; break; default: n = d->size; } *psz = n; return v; } // Calculate sizeof type ty using the information // in the tables. Return -1 if size is variable. // The answer should match the size member of descr. // Also, make various sanity checks. static int calcsizeof(int ty) { int n, k, t; uchar* v; v = descr[ty].members; if(v == nil) return descr[ty].size; n = 0; while(*v != 0) { t = *v; assert(t >= 1 && t < NUMDTS); n = alignto(n, descr[t].align); v = calcsizeof1(v, &k); if(k == -1) return -1; n += k; } return alignto(n, descr[ty].align); } // Do sanity checks on the tables static void checkgctables() { int t, n, numerrs; assert(sizeof(descr)/sizeof(descr[0]) == NUMDTS); numerrs = 0; for(t = NUMBUILTINDTS; t < NUMDTS; t++) { assert(descr[t].align == 4); // no doubles in our structures, for now n = calcsizeof(t); if(!(n == -1 || n == descr[t].size)) { trace("problem with gctable for %s:\n", descr[t].name); trace("calculated size=%d, sizeof=%d\n", n, descr[t].size); numerrs++; } } assert(numerrs == 0); } void gcinit() { if(dbg) checkgctables(); }