#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();
}
|