# include "dgd.h"
# include "str.h"
# include "array.h"
# include "object.h"
# include "interpret.h"
# include "data.h"
# include "call_out.h"
# include "parse.h"
# include "control.h"
# include "csupport.h"
# define CMPLIMIT 2048 /* compress if >= CMPLIMIT */
# define PRIV 0x8000 /* in sinherit->varoffset */
typedef struct {
sector nsectors; /* # sectors in part one */
char flags; /* control flags: compression */
char ninherits; /* # objects in inherit table */
Uint compiled; /* time of compilation */
Uint progsize; /* size of program code */
unsigned short nstrings; /* # strings in string constant table */
Uint strsize; /* size of string constant table */
char nfuncdefs; /* # entries in function definition table */
char nvardefs; /* # entries in variable definition table */
char nclassvars; /* # class variables */
uindex nfuncalls; /* # entries in function call table */
unsigned short nsymbols; /* # entries in symbol table */
unsigned short nvariables; /* # variables */
unsigned short nifdefs; /* # int/float definitions */
unsigned short nvinit; /* # variables requiring initialization */
unsigned short vmapsize; /* size of variable map, or 0 for none */
} scontrol;
static char sc_layout[] = "dcciisicccusssss";
typedef struct {
sector nsectors; /* # sectors in part one */
char flags; /* control flags: compression */
char ninherits; /* # objects in inherit table */
Uint compiled; /* time of compilation */
Uint progsize; /* size of program code */
unsigned short nstrings; /* # strings in string constant table */
Uint strsize; /* size of string constant table */
char nfuncdefs; /* # entries in function definition table */
char nvardefs; /* # entries in variable definition table */
uindex nfuncalls; /* # entries in function call table */
unsigned short nsymbols; /* # entries in symbol table */
unsigned short nvariables; /* # variables */
unsigned short nifdefs; /* # int/float definitions */
unsigned short nvinit; /* # variables requiring initialization */
unsigned short vmapsize; /* size of variable map, or 0 for none */
} oscontrol;
static char os_layout[] = "dcciisiccusssss";
typedef struct {
uindex oindex; /* index in object table */
uindex funcoffset; /* function call offset */
unsigned short varoffset; /* variable offset + private bit */
} sinherit;
static char si_layout[] = "uus";
typedef struct {
sector nsectors; /* number of sectors in data space */
short flags; /* dataspace flags: compression */
unsigned short nvariables; /* number of variables */
Uint narrays; /* number of array values */
Uint eltsize; /* total size of array elements */
Uint nstrings; /* number of strings */
Uint strsize; /* total size of strings */
uindex ncallouts; /* number of callouts */
uindex fcallouts; /* first free callout */
} sdataspace;
static char sd_layout[] = "dssiiiiuu";
struct _svalue_ {
short type; /* object, number, string, array */
uindex oindex; /* index in object table */
union {
Int number; /* number */
Uint string; /* string */
Uint objcnt; /* object creation count */
Uint array; /* array */
} u;
};
static char sv_layout[] = "sui";
typedef struct _sarray_ {
Uint index; /* index in array value table */
unsigned short size; /* size of array */
Uint ref; /* refcount */
Uint tag; /* unique value for each array */
} sarray;
static char sa_layout[] = "isii";
typedef struct _sstring_ {
Uint index; /* index in string text table */
ssizet len; /* length of string */
Uint ref; /* refcount */
} sstring;
static char ss_layout[] = "iti";
typedef struct _scallout_ {
Uint time; /* time of call */
uindex nargs; /* number of arguments */
svalue val[4]; /* function name, 3 direct arguments */
} scallout;
static char sco_layout[] = "iu[sui][sui][sui][sui]";
typedef struct {
Uint time; /* time of call */
unsigned short nargs; /* number of arguments */
svalue val[4]; /* function name, 3 direct arguments */
} oscallout;
static char osc_layout[] = "is[sui][sui][sui][sui]";
typedef struct {
arrmerge *amerge; /* array merge table */
strmerge *smerge; /* string merge table */
Uint narr; /* # of arrays */
Uint nstr; /* # of strings */
Uint arrsize; /* # of array elements */
Uint strsize; /* total string size */
sarray *sarrays; /* save arrays */
svalue *selts; /* save array elements */
sstring *sstrings; /* save strings */
char *stext; /* save string elements */
Uint *counttab; /* object count table */
bool counting; /* currently counting */
array alist; /* linked list sentinel */
} savedata;
static control *chead, *ctail; /* list of control blocks */
static dataspace *dhead, *dtail; /* list of dataspace blocks */
static dataspace *gcdata; /* next dataspace to garbage collect */
static sector nctrl; /* # control blocks */
static sector ndata; /* # dataspace blocks */
static bool nilisnot0; /* nil != int 0 */
/*
* NAME: data->init()
* DESCRIPTION: initialize swapped data handling
*/
void d_init(flag)
int flag;
{
chead = ctail = (control *) NULL;
dhead = dtail = (dataspace *) NULL;
gcdata = (dataspace *) NULL;
nctrl = ndata = 0;
nilisnot0 = flag;
}
/*
* NAME: data->new_control()
* DESCRIPTION: create a new control block
*/
control *d_new_control()
{
register control *ctrl;
ctrl = ALLOC(control, 1);
if (chead != (control *) NULL) {
/* insert at beginning of list */
chead->prev = ctrl;
ctrl->prev = (control *) NULL;
ctrl->next = chead;
chead = ctrl;
} else {
/* list was empty */
ctrl->prev = ctrl->next = (control *) NULL;
chead = ctail = ctrl;
}
ctrl->ndata = 0;
nctrl++;
ctrl->flags = 0;
ctrl->nsectors = 0; /* nothing on swap device yet */
ctrl->sectors = (sector *) NULL;
ctrl->oindex = UINDEX_MAX;
ctrl->ninherits = 0;
ctrl->inherits = (dinherit *) NULL;
ctrl->compiled = 0;
ctrl->progsize = 0;
ctrl->prog = (char *) NULL;
ctrl->nstrings = 0;
ctrl->strings = (string **) NULL;
ctrl->sstrings = (dstrconst *) NULL;
ctrl->stext = (char *) NULL;
ctrl->nfuncdefs = 0;
ctrl->funcdefs = (dfuncdef *) NULL;
ctrl->nvardefs = 0;
ctrl->nclassvars = 0;
ctrl->vardefs = (dvardef *) NULL;
ctrl->cvstrings = (string **) NULL;
ctrl->classvars = (char *) NULL;
ctrl->nfuncalls = 0;
ctrl->funcalls = (char *) NULL;
ctrl->nsymbols = 0;
ctrl->symbols = (dsymbol *) NULL;
ctrl->nvariables = 0;
ctrl->nifdefs = 0;
ctrl->nvinit = 0;
ctrl->vmapsize = 0;
ctrl->vmap = (unsigned short *) NULL;
return ctrl;
}
/*
* NAME: data->alloc_dataspace()
* DESCRIPTION: allocate a new dataspace block
*/
static dataspace *d_alloc_dataspace(obj)
object *obj;
{
register dataspace *data;
data = ALLOC(dataspace, 1);
if (dhead != (dataspace *) NULL) {
/* insert at beginning of list */
dhead->prev = data;
data->prev = (dataspace *) NULL;
data->next = dhead;
dhead = data;
data->gcprev = gcdata->gcprev;
data->gcnext = gcdata;
data->gcprev->gcnext = data;
gcdata->gcprev = data;
} else {
/* list was empty */
data->prev = data->next = (dataspace *) NULL;
dhead = dtail = data;
gcdata = data;
data->gcprev = data->gcnext = data;
}
ndata++;
data->iprev = (dataspace *) NULL;
data->inext = (dataspace *) NULL;
data->flags = 0;
data->oindex = obj->index;
data->ctrl = (control *) NULL;
/* sectors */
data->nsectors = 0;
data->sectors = (sector *) NULL;
/* variables */
data->nvariables = 0;
data->variables = (value *) NULL;
data->svariables = (svalue *) NULL;
/* arrays */
data->narrays = 0;
data->eltsize = 0;
data->sarrays = (sarray *) NULL;
data->selts = (svalue *) NULL;
data->alist.prev = data->alist.next = &data->alist;
/* strings */
data->nstrings = 0;
data->strsize = 0;
data->sstrings = (sstring *) NULL;
data->stext = (char *) NULL;
/* callouts */
data->ncallouts = 0;
data->fcallouts = 0;
data->callouts = (dcallout *) NULL;
data->scallouts = (scallout *) NULL;
/* value plane */
data->base.level = 0;
data->base.flags = 0;
data->base.schange = 0;
data->base.achange = 0;
data->base.imports = 0;
data->base.alocal.arr = (array *) NULL;
data->base.alocal.plane = &data->base;
data->base.alocal.data = data;
data->base.alocal.state = AR_CHANGED;
data->base.arrays = (arrref *) NULL;
data->base.strings = (strref *) NULL;
data->base.coptab = (struct _coptable_ *) NULL;
data->base.prev = (dataplane *) NULL;
data->base.plist = (dataplane *) NULL;
data->plane = &data->base;
/* parse_string data */
data->parser = (struct _parser_ *) NULL;
return data;
}
/*
* NAME: data->new_dataspace()
* DESCRIPTION: create a new dataspace block
*/
dataspace *d_new_dataspace(obj)
object *obj;
{
register dataspace *data;
data = d_alloc_dataspace(obj);
data->base.flags = MOD_VARIABLE;
data->ctrl = o_control(obj);
data->ctrl->ndata++;
data->nvariables = data->ctrl->nvariables + 1;
return data;
}
/*
* NAME: data->load_control()
* DESCRIPTION: load a control block from the swap device
*/
control *d_load_control(obj)
register object *obj;
{
register control *ctrl;
ctrl = d_new_control();
ctrl->oindex = obj->index;
if (obj->flags & O_COMPILED) {
/* initialize control block of compiled object */
pc_control(ctrl, obj);
ctrl->flags |= CTRL_COMPILED;
} else {
scontrol header;
register Uint size;
/* header */
sw_readv((char *) &header, &obj->cfirst, (Uint) sizeof(scontrol),
(Uint) 0);
ctrl->nsectors = header.nsectors;
ctrl->sectors = ALLOC(sector, header.nsectors);
ctrl->sectors[0] = obj->cfirst;
size = header.nsectors * (Uint) sizeof(sector);
if (header.nsectors > 1) {
sw_readv((char *) ctrl->sectors, ctrl->sectors, size,
(Uint) sizeof(scontrol));
}
size += sizeof(scontrol);
ctrl->flags = header.flags;
/* inherits */
ctrl->ninherits = UCHAR(header.ninherits);
if (header.vmapsize != 0) {
/*
* Control block for outdated issue; only vmap can be loaded.
* The load offsets will be invalid (and unused).
*/
ctrl->vmapsize = header.vmapsize;
ctrl->vmap = ALLOC(unsigned short, header.vmapsize);
sw_readv((char *) ctrl->vmap, ctrl->sectors,
header.vmapsize * (Uint) sizeof(unsigned short), size);
} else {
register int n;
register dinherit *inherits;
register sinherit *sinherits;
/* load inherits */
n = UCHAR(header.ninherits); /* at least one */
ctrl->inherits = inherits = ALLOC(dinherit, n);
sinherits = ALLOCA(sinherit, n);
sw_readv((char *) sinherits, ctrl->sectors,
n * (Uint) sizeof(sinherit), size);
size += n * sizeof(sinherit);
do {
inherits->oindex = sinherits->oindex;
inherits->funcoffset = sinherits->funcoffset;
inherits->varoffset = sinherits->varoffset & ~PRIV;
(inherits++)->priv = (((sinherits++)->varoffset & PRIV) != 0);
} while (--n > 0);
AFREE(sinherits - UCHAR(header.ninherits));
}
/* compile time */
ctrl->compiled = header.compiled;
/* program */
ctrl->progoffset = size;
ctrl->progsize = header.progsize;
size += header.progsize;
/* string constants */
ctrl->stroffset = size;
ctrl->nstrings = header.nstrings;
ctrl->strsize = header.strsize;
size += header.nstrings * (Uint) sizeof(dstrconst) + header.strsize;
/* function definitions */
ctrl->funcdoffset = size;
ctrl->nfuncdefs = UCHAR(header.nfuncdefs);
size += UCHAR(header.nfuncdefs) * (Uint) sizeof(dfuncdef);
/* variable definitions */
ctrl->vardoffset = size;
ctrl->nvardefs = UCHAR(header.nvardefs);
ctrl->nclassvars = UCHAR(header.nclassvars);
size += UCHAR(header.nvardefs) * (Uint) sizeof(dvardef) +
UCHAR(header.nclassvars) * (Uint) 3;
/* function call table */
ctrl->funccoffset = size;
ctrl->nfuncalls = header.nfuncalls;
size += header.nfuncalls * (Uint) 2;
/* symbol table */
ctrl->symboffset = size;
ctrl->nsymbols = header.nsymbols;
/* # variables */
ctrl->nvariables = header.nvariables;
ctrl->nifdefs = header.nifdefs;
ctrl->nvinit = header.nvinit;
}
return ctrl;
}
/*
* NAME: data->load_dataspace()
* DESCRIPTION: load the dataspace header block of an object from the swap
*/
dataspace *d_load_dataspace(obj)
object *obj;
{
sdataspace header;
register dataspace *data;
register Uint size;
data = d_alloc_dataspace(obj);
data->ctrl = o_control(obj);
data->ctrl->ndata++;
/* header */
sw_readv((char *) &header, &obj->dfirst, (Uint) sizeof(sdataspace),
(Uint) 0);
data->nsectors = header.nsectors;
data->sectors = ALLOC(sector, header.nsectors);
data->sectors[0] = obj->dfirst;
size = header.nsectors * (Uint) sizeof(sector);
if (header.nsectors > 1) {
sw_readv((char *) data->sectors, data->sectors, size,
(Uint) sizeof(sdataspace));
}
size += sizeof(sdataspace);
data->flags = header.flags;
/* variables */
data->varoffset = size;
data->nvariables = header.nvariables;
size += data->nvariables * (Uint) sizeof(svalue);
/* arrays */
data->arroffset = size;
data->narrays = header.narrays;
data->eltsize = header.eltsize;
size += header.narrays * (Uint) sizeof(sarray) +
header.eltsize * sizeof(svalue);
/* strings */
data->stroffset = size;
data->nstrings = header.nstrings;
data->strsize = header.strsize;
size += header.nstrings * sizeof(sstring) + header.strsize;
/* callouts */
data->cooffset = size;
data->ncallouts = header.ncallouts;
data->fcallouts = header.fcallouts;
if (!(obj->flags & O_MASTER) && obj->update != OBJ(obj->u_master)->update &&
obj->count != 0) {
d_upgrade_clone(data);
}
return data;
}
/*
* NAME: data->ref_control()
* DESCRIPTION: reference control block
*/
void d_ref_control(ctrl)
register control *ctrl;
{
if (ctrl != chead) {
/* move to head of list */
ctrl->prev->next = ctrl->next;
if (ctrl->next != (control *) NULL) {
ctrl->next->prev = ctrl->prev;
} else {
ctail = ctrl->prev;
}
ctrl->prev = (control *) NULL;
ctrl->next = chead;
chead->prev = ctrl;
chead = ctrl;
}
}
/*
* NAME: data->ref_dataspace()
* DESCRIPTION: reference data block
*/
void d_ref_dataspace(data)
register dataspace *data;
{
if (data != dhead) {
/* move to head of list */
data->prev->next = data->next;
if (data->next != (dataspace *) NULL) {
data->next->prev = data->prev;
} else {
dtail = data->prev;
}
data->prev = (dataspace *) NULL;
data->next = dhead;
dhead->prev = data;
dhead = data;
}
}
/*
* NAME: compress()
* DESCRIPTION: compress data
*/
static Uint compress(data, text, size)
char *data, *text;
register Uint size;
{
char htab[16384];
register unsigned short buf, bufsize, x;
register char *p, *q;
register Uint cspace;
if (size <= 4 + 1) {
/* can't get smaller than this */
return 0;
}
/* clear the hash table */
memset(htab, '\0', sizeof(htab));
buf = bufsize = 0;
x = 0;
p = text;
q = data;
*q++ = size >> 24;
*q++ = size >> 16;
*q++ = size >> 8;
*q++ = size;
cspace = size - 4;
while (size != 0) {
if (htab[x] == *p) {
buf >>= 1;
bufsize += 1;
} else {
htab[x] = *p;
buf = (buf >> 9) + 0x0080 + (UCHAR(*p) << 8);
bufsize += 9;
}
x = ((x << 3) & 0x3fff) ^ UCHAR(strhashtab[UCHAR(*p++)]);
if (bufsize >= 8) {
if (bufsize == 16) {
if ((Int) (cspace-=2) <= 0) {
return 0; /* out of space */
}
*q++ = buf;
*q++ = buf >> 8;
bufsize = 0;
} else {
if (--cspace == 0) {
return 0; /* out of space */
}
*q++ = buf >> (16 - bufsize);
bufsize -= 8;
}
}
--size;
}
if (bufsize != 0) {
if (--cspace == 0) {
return 0; /* compression did not reduce size */
}
/* add last incomplete byte */
*q++ = (buf >> (16 - bufsize)) + (0xff << bufsize);
}
return (long) q - (long) data;
}
/*
* NAME: decompress()
* DESCRIPTION: read and decompress data from the swap file
*/
static char *decompress(sectors, readv, size, offset, dsize)
sector *sectors;
void (*readv) P((char*, sector*, Uint, Uint));
Uint size, offset;
Uint *dsize;
{
char buffer[8192], htab[16384];
register unsigned short buf, bufsize, x;
register Uint n;
register char *p, *q;
buf = bufsize = 0;
x = 0;
/* clear the hash table */
memset(htab, '\0', sizeof(htab));
n = sizeof(buffer);
if (n > size) {
n = size;
}
(*readv)(p = buffer, sectors, n, offset);
size -= n;
offset += n;
*dsize = (UCHAR(p[0]) << 24) | (UCHAR(p[1]) << 16) | (UCHAR(p[2]) << 8) |
UCHAR(p[3]);
q = ALLOC(char, *dsize);
p += 4;
n -= 4;
for (;;) {
for (;;) {
if (bufsize == 0) {
if (n == 0) {
break;
}
--n;
buf = UCHAR(*p++);
bufsize = 8;
}
if (buf & 1) {
if (n == 0) {
break;
}
--n;
buf += UCHAR(*p++) << bufsize;
*q = htab[x] = buf >> 1;
buf >>= 9;
} else {
*q = htab[x];
buf >>= 1;
}
--bufsize;
x = ((x << 3) & 0x3fff) ^ UCHAR(strhashtab[UCHAR(*q++)]);
}
if (size == 0) {
return q - *dsize;
}
n = sizeof(buffer);
if (n > size) {
n = size;
}
(*readv)(p = buffer, sectors, n, offset);
size -= n;
offset += n;
}
}
/*
* NAME: data->get_prog()
* DESCRIPTION: get the program
*/
char *d_get_prog(ctrl)
register control *ctrl;
{
if (ctrl->prog == (char *) NULL && ctrl->progsize != 0) {
if (ctrl->flags & CTRL_PROGCMP) {
ctrl->prog = decompress(ctrl->sectors, sw_readv, ctrl->progsize,
ctrl->progoffset, &ctrl->progsize);
} else {
ctrl->prog = ALLOC(char, ctrl->progsize);
sw_readv(ctrl->prog, ctrl->sectors, ctrl->progsize,
ctrl->progoffset);
}
}
return ctrl->prog;
}
/*
* NAME: data->get_stext()
* DESCRIPTION: load strings text
*/
static void d_get_stext(ctrl)
register control *ctrl;
{
/* load strings text */
if (ctrl->flags & CTRL_STRCMP) {
ctrl->stext = decompress(ctrl->sectors, sw_readv,
ctrl->strsize,
ctrl->stroffset +
ctrl->nstrings * sizeof(dstrconst),
&ctrl->strsize);
} else {
ctrl->stext = ALLOC(char, ctrl->strsize);
sw_readv(ctrl->stext, ctrl->sectors, ctrl->strsize,
ctrl->stroffset + ctrl->nstrings * (Uint) sizeof(dstrconst));
}
}
/*
* NAME: data->get_strconst()
* DESCRIPTION: get a string constant
*/
string *d_get_strconst(ctrl, inherit, idx)
register control *ctrl;
register int inherit;
unsigned int idx;
{
if (UCHAR(inherit) < ctrl->ninherits - 1) {
/* get the proper control block */
ctrl = o_control(OBJR(ctrl->inherits[UCHAR(inherit)].oindex));
}
if (ctrl->strings == (string **) NULL) {
/* make string pointer block */
ctrl->strings = ALLOC(string*, ctrl->nstrings);
memset(ctrl->strings, '\0', ctrl->nstrings * sizeof(string *));
if (ctrl->sstrings == (dstrconst *) NULL) {
/* load strings */
ctrl->sstrings = ALLOC(dstrconst, ctrl->nstrings);
sw_readv((char *) ctrl->sstrings, ctrl->sectors,
ctrl->nstrings * (Uint) sizeof(dstrconst),
ctrl->stroffset);
if (ctrl->strsize > 0 && ctrl->stext == (char *) NULL) {
d_get_stext(ctrl); /* load strings text */
}
}
}
if (ctrl->strings[idx] == (string *) NULL) {
register string *str;
str = str_alloc(ctrl->stext + ctrl->sstrings[idx].index,
(long) ctrl->sstrings[idx].len);
str_ref(ctrl->strings[idx] = str);
}
return ctrl->strings[idx];
}
/*
* NAME: data->get_funcdefs()
* DESCRIPTION: get function definitions
*/
dfuncdef *d_get_funcdefs(ctrl)
register control *ctrl;
{
if (ctrl->funcdefs == (dfuncdef *) NULL && ctrl->nfuncdefs != 0) {
ctrl->funcdefs = ALLOC(dfuncdef, ctrl->nfuncdefs);
sw_readv((char *) ctrl->funcdefs, ctrl->sectors,
ctrl->nfuncdefs * (Uint) sizeof(dfuncdef), ctrl->funcdoffset);
}
return ctrl->funcdefs;
}
/*
* NAME: data->get_vardefs()
* DESCRIPTION: get variable definitions
*/
dvardef *d_get_vardefs(ctrl)
register control *ctrl;
{
if (ctrl->vardefs == (dvardef *) NULL && ctrl->nvardefs != 0) {
ctrl->vardefs = ALLOC(dvardef, ctrl->nvardefs);
sw_readv((char *) ctrl->vardefs, ctrl->sectors,
ctrl->nvardefs * (Uint) sizeof(dvardef), ctrl->vardoffset);
if (ctrl->nclassvars != 0) {
register char *p;
register dvardef *vars;
register string **strs;
register unsigned short n, inherit, u;
ctrl->classvars = ALLOC(char, ctrl->nclassvars * 3);
sw_readv(ctrl->classvars, ctrl->sectors, ctrl->nclassvars * 3,
ctrl->vardoffset + ctrl->nvardefs * sizeof(dvardef));
ctrl->cvstrings = strs = ALLOC(string*, ctrl->nvardefs);
memset(strs, '\0', ctrl->nvardefs * sizeof(string*));
p = ctrl->classvars;
for (n = ctrl->nclassvars, vars = ctrl->vardefs; n != 0; vars++) {
if ((vars->type & T_TYPE) == T_CLASS) {
inherit = FETCH1U(p);
str_ref(*strs = d_get_strconst(ctrl, inherit,
FETCH2U(p, u)));
--n;
}
strs++;
}
}
}
return ctrl->vardefs;
}
/*
* NAME: data->get_funcalls()
* DESCRIPTION: get function call table
*/
char *d_get_funcalls(ctrl)
register control *ctrl;
{
if (ctrl->funcalls == (char *) NULL && ctrl->nfuncalls != 0) {
ctrl->funcalls = ALLOC(char, 2L * ctrl->nfuncalls);
sw_readv((char *) ctrl->funcalls, ctrl->sectors,
ctrl->nfuncalls * (Uint) 2, ctrl->funccoffset);
}
return ctrl->funcalls;
}
/*
* NAME: data->get_symbols()
* DESCRIPTION: get symbol table
*/
dsymbol *d_get_symbols(ctrl)
register control *ctrl;
{
if (ctrl->symbols == (dsymbol *) NULL && ctrl->nsymbols > 0) {
ctrl->symbols = ALLOC(dsymbol, ctrl->nsymbols);
sw_readv((char *) ctrl->symbols, ctrl->sectors,
ctrl->nsymbols * (Uint) sizeof(dsymbol), ctrl->symboffset);
}
return ctrl->symbols;
}
/*
* NAME: data->get_progsize()
* DESCRIPTION: get the size of a control block
*/
Uint d_get_progsize(ctrl)
register control *ctrl;
{
if (ctrl->progsize != 0 && ctrl->prog == (char *) NULL &&
(ctrl->flags & CTRL_PROGCMP)) {
d_get_prog(ctrl); /* decompress program */
}
if (ctrl->strsize != 0 && ctrl->stext == (char *) NULL &&
(ctrl->flags & CTRL_STRCMP)) {
d_get_stext(ctrl); /* decompress strings */
}
return ctrl->ninherits * sizeof(dinherit) +
ctrl->progsize +
ctrl->nstrings * (Uint) sizeof(dstrconst) +
ctrl->strsize +
ctrl->nfuncdefs * sizeof(dfuncdef) +
ctrl->nvardefs * sizeof(dvardef) +
ctrl->nclassvars * (Uint) 3 +
ctrl->nfuncalls * (Uint) 2 +
ctrl->nsymbols * (Uint) sizeof(dsymbol);
}
/*
* NAME: data->get_string()
* DESCRIPTION: get a string from the dataspace
*/
static string *d_get_string(data, idx)
register dataspace *data;
register Uint idx;
{
if (data->plane->strings == (strref *) NULL ||
data->plane->strings[idx].str == (string *) NULL) {
register string *str;
register strref *s;
register dataplane *p;
register Uint i;
if (data->sstrings == (sstring *) NULL) {
/* load strings */
data->sstrings = ALLOC(sstring, data->nstrings);
sw_readv((char *) data->sstrings, data->sectors,
data->nstrings * sizeof(sstring), data->stroffset);
if (data->strsize > 0) {
/* load strings text */
if (data->flags & DATA_STRCMP) {
data->stext = decompress(data->sectors, sw_readv,
data->strsize,
data->stroffset +
data->nstrings * sizeof(sstring),
&data->strsize);
} else {
data->stext = ALLOC(char, data->strsize);
sw_readv(data->stext, data->sectors, data->strsize,
data->stroffset +
data->nstrings * sizeof(sstring));
}
}
}
str = str_alloc(data->stext + data->sstrings[idx].index,
(long) data->sstrings[idx].len);
str->ref = 0;
p = data->plane;
do {
if (p->strings == (strref *) NULL) {
/* initialize string pointers */
s = p->strings = ALLOC(strref, data->nstrings);
for (i = data->nstrings; i > 0; --i) {
(s++)->str = (string *) NULL;
}
}
s = &p->strings[idx];
str_ref(s->str = str);
s->data = data;
s->ref = data->sstrings[idx].ref;
p = p->prev;
} while (p != (dataplane *) NULL);
str->primary = &data->plane->strings[idx];
return str;
}
return data->plane->strings[idx].str;
}
/*
* NAME: data->get_array()
* DESCRIPTION: get an array from the dataspace
*/
static array *d_get_array(data, idx)
register dataspace *data;
register Uint idx;
{
if (data->plane->arrays == (arrref *) NULL ||
data->plane->arrays[idx].arr == (array *) NULL) {
register array *arr;
register arrref *a;
register dataplane *p;
register Uint i;
if (data->sarrays == (sarray *) NULL) {
/* load arrays */
data->sarrays = ALLOC(sarray, data->narrays);
sw_readv((char *) data->sarrays, data->sectors,
data->narrays * (Uint) sizeof(sarray), data->arroffset);
}
arr = arr_alloc(data->sarrays[idx].size);
arr->ref = 0;
arr->tag = data->sarrays[idx].tag;
p = data->plane;
do {
if (p->arrays == (arrref *) NULL) {
/* create array pointers */
a = p->arrays = ALLOC(arrref, data->narrays);
for (i = data->narrays; i > 0; --i) {
(a++)->arr = (array *) NULL;
}
}
a = &p->arrays[idx];
arr_ref(a->arr = arr);
a->plane = &data->base;
a->data = data;
a->state = AR_UNCHANGED;
a->ref = data->sarrays[idx].ref;
p = p->prev;
} while (p != (dataplane *) NULL);
arr->primary = &data->plane->arrays[idx];
arr->prev = &data->alist;
arr->next = data->alist.next;
arr->next->prev = arr;
data->alist.next = arr;
return arr;
}
return data->plane->arrays[idx].arr;
}
/*
* NAME: data->get_values()
* DESCRIPTION: get values from the dataspace
*/
static void d_get_values(data, sv, v, n)
register dataspace *data;
register svalue *sv;
register value *v;
register int n;
{
while (n > 0) {
v->modified = FALSE;
switch (v->type = sv->type) {
case T_NIL:
v->u.number = 0;
break;
case T_INT:
v->u.number = sv->u.number;
break;
case T_STRING:
str_ref(v->u.string = d_get_string(data, sv->u.string));
break;
case T_FLOAT:
case T_OBJECT:
v->oindex = sv->oindex;
v->u.objcnt = sv->u.objcnt;
break;
case T_ARRAY:
case T_MAPPING:
case T_LWOBJECT:
arr_ref(v->u.array = d_get_array(data, sv->u.array));
break;
}
sv++;
v++;
--n;
}
}
/*
* NAME: data->new_variables()
* DESCRIPTION: initialize variables in a dataspace block
*/
void d_new_variables(ctrl, variables)
register control *ctrl;
register value *variables;
{
register unsigned short nifdefs, nvars, nvinit;
register dvardef *var;
register dinherit *inh;
/*
* first, initialize all variables to nil
*/
for (nvars = ctrl->nvariables, variables += nvars; nvars > 0; --nvars) {
*--variables = nil_value;
}
if (ctrl->nvinit != 0) {
/*
* explicitly initialize some variables
*/
nvars = 0;
for (nvinit = ctrl->nvinit, inh = ctrl->inherits; nvinit > 0; inh++) {
if (inh->varoffset == nvars) {
ctrl = o_control(OBJR(inh->oindex));
if (ctrl->nifdefs != 0) {
nvinit -= ctrl->nifdefs;
for (nifdefs = ctrl->nifdefs, var = d_get_vardefs(ctrl);
nifdefs > 0; var++) {
if (var->type == T_INT && nilisnot0) {
variables[nvars] = zero_int;
--nifdefs;
} else if (var->type == T_FLOAT) {
variables[nvars] = zero_float;
--nifdefs;
}
nvars++;
}
}
nvars = inh->varoffset + ctrl->nvardefs;
}
}
}
}
/*
* NAME: data->get_variable()
* DESCRIPTION: get a variable from the dataspace
*/
value *d_get_variable(data, idx)
register dataspace *data;
register unsigned int idx;
{
if (data->variables == (value *) NULL) {
/* create room for variables */
data->variables = ALLOC(value, data->nvariables);
if (data->nsectors == 0 && data->svariables == (svalue *) NULL) {
/* new datablock */
d_new_variables(data->ctrl, data->variables);
data->variables[data->nvariables - 1] = nil_value; /* extra var */
} else {
/*
* variables must be loaded from swap
*/
if (data->svariables == (svalue *) NULL) {
/* load svalues */
data->svariables = ALLOC(svalue, data->nvariables);
sw_readv((char *) data->svariables, data->sectors,
data->nvariables * (Uint) sizeof(svalue),
data->varoffset);
}
d_get_values(data, data->svariables, data->variables,
data->nvariables);
}
}
return &data->variables[idx];
}
/*
* NAME: data->get_elts()
* DESCRIPTION: get the elements of an array
*/
value *d_get_elts(arr)
register array *arr;
{
register value *v;
v = arr->elts;
if (v == (value *) NULL && arr->size != 0) {
register dataspace *data;
Uint idx;
data = arr->primary->data;
if (data->selts == (svalue *) NULL) {
/* load array elements */
data->selts = (svalue *) ALLOC(svalue, data->eltsize);
sw_readv((char *) data->selts, data->sectors,
data->eltsize * sizeof(svalue),
data->arroffset + data->narrays * sizeof(sarray));
}
v = arr->elts = ALLOC(value, arr->size);
idx = data->sarrays[arr->primary - data->plane->arrays].index;
d_get_values(data, &data->selts[idx], v, arr->size);
}
return v;
}
/*
* NAME: data->get_callouts()
* DESCRIPTION: load callouts from swap
*/
void d_get_callouts(data)
register dataspace *data;
{
register scallout *sco;
register dcallout *co;
register uindex n;
if (data->scallouts == (scallout *) NULL) {
data->scallouts = ALLOC(scallout, data->ncallouts);
sw_readv((char *) data->scallouts, data->sectors,
data->ncallouts * (Uint) sizeof(scallout), data->cooffset);
}
sco = data->scallouts;
co = data->callouts = ALLOC(dcallout, data->ncallouts);
for (n = data->ncallouts; n > 0; --n) {
co->time = sco->time;
co->nargs = sco->nargs;
if (sco->val[0].type == T_STRING) {
d_get_values(data, sco->val, co->val,
(sco->nargs > 3) ? 4 : sco->nargs + 1);
} else {
co->val[0] = nil_value;
}
sco++;
co++;
}
}
/*
* NAME: data->swapalloc()
* DESCRIPTION: allocate swapspace for something
*/
static sector d_swapalloc(size, nsectors, sectors)
Uint size;
register sector nsectors, **sectors;
{
register sector n, *s;
s = *sectors;
if (nsectors != 0) {
/* wipe old sectors */
sw_wipev(s, nsectors);
}
n = sw_mapsize(size);
if (nsectors > n) {
/* too many sectors */
sw_delv(s + n, nsectors - n);
}
s = *sectors = REALLOC(*sectors, sector, nsectors, n);
if (nsectors < n) {
/* not enough sectors */
sw_newv(s + nsectors, n - nsectors);
}
return n;
}
/*
* NAME: data->save_control()
* DESCRIPTION: save the control block
*/
static void d_save_control(ctrl)
register control *ctrl;
{
scontrol header;
char *prog, *stext, *text;
dstrconst *sstrings;
register Uint size, i;
register sinherit *sinherits;
register dinherit *inherits;
/*
* Save a control block.
*/
/* create header */
header.flags = ctrl->flags & CTRL_UNDEFINED;
header.ninherits = ctrl->ninherits;
header.compiled = ctrl->compiled;
header.progsize = ctrl->progsize;
header.nstrings = ctrl->nstrings;
header.strsize = ctrl->strsize;
header.nfuncdefs = ctrl->nfuncdefs;
header.nvardefs = ctrl->nvardefs;
header.nclassvars = ctrl->nclassvars;
header.nfuncalls = ctrl->nfuncalls;
header.nsymbols = ctrl->nsymbols;
header.nvariables = ctrl->nvariables;
header.nifdefs = ctrl->nifdefs;
header.nvinit = ctrl->nvinit;
header.vmapsize = ctrl->vmapsize;
/* create sector space */
if (header.vmapsize != 0) {
size = sizeof(scontrol) +
header.vmapsize * (Uint) sizeof(unsigned short);
} else {
prog = ctrl->prog;
if (header.progsize >= CMPLIMIT) {
prog = ALLOCA(char, header.progsize);
size = compress(prog, ctrl->prog, header.progsize);
if (size != 0) {
header.flags |= CMP_PRED;
header.progsize = size;
} else {
AFREE(prog);
prog = ctrl->prog;
}
}
sstrings = ctrl->sstrings;
stext = ctrl->stext;
if (header.nstrings > 0 && sstrings == (dstrconst *) NULL) {
register string **strs;
register Uint strsize;
register dstrconst *s;
register char *t;
sstrings = ALLOCA(dstrconst, header.nstrings);
if (header.strsize > 0) {
stext = ALLOCA(char, header.strsize);
}
strs = ctrl->strings;
strsize = 0;
s = sstrings;
t = stext;
for (i = header.nstrings; i > 0; --i) {
s->index = strsize;
strsize += s->len = (*strs)->len;
memcpy(t, (*strs++)->text, s->len);
t += (s++)->len;
}
}
text = stext;
if (header.strsize >= CMPLIMIT) {
text = ALLOCA(char, header.strsize);
size = compress(text, stext, header.strsize);
if (size != 0) {
header.flags |= CMP_PRED << 2;
header.strsize = size;
} else {
AFREE(text);
text = stext;
}
}
size = sizeof(scontrol) +
UCHAR(header.ninherits) * sizeof(sinherit) +
header.progsize +
header.nstrings * (Uint) sizeof(dstrconst) +
header.strsize +
UCHAR(header.nfuncdefs) * sizeof(dfuncdef) +
UCHAR(header.nvardefs) * sizeof(dvardef) +
UCHAR(header.nclassvars) * (Uint) 3 +
header.nfuncalls * (Uint) 2 +
header.nsymbols * (Uint) sizeof(dsymbol);
}
ctrl->nsectors = header.nsectors = d_swapalloc(size, ctrl->nsectors,
&ctrl->sectors);
OBJ(ctrl->oindex)->cfirst = ctrl->sectors[0];
/*
* Copy everything to the swap device.
*/
/* save header */
sw_writev((char *) &header, ctrl->sectors, (Uint) sizeof(scontrol),
(Uint) 0);
size = sizeof(scontrol);
/* save sector map */
sw_writev((char *) ctrl->sectors, ctrl->sectors,
header.nsectors * (Uint) sizeof(sector), size);
size += header.nsectors * (Uint) sizeof(sector);
if (header.vmapsize != 0) {
/*
* save only vmap
*/
sw_writev((char *) ctrl->vmap, ctrl->sectors,
header.vmapsize * (Uint) sizeof(unsigned short), size);
} else {
/* save inherits */
inherits = ctrl->inherits;
sinherits = ALLOCA(sinherit, i = UCHAR(header.ninherits));
do {
sinherits->oindex = inherits->oindex;
sinherits->funcoffset = inherits->funcoffset;
sinherits->varoffset = inherits->varoffset;
if (inherits->priv) {
sinherits->varoffset |= PRIV;
}
inherits++;
sinherits++;
} while (--i > 0);
sinherits -= UCHAR(header.ninherits);
sw_writev((char *) sinherits, ctrl->sectors,
UCHAR(header.ninherits) * (Uint) sizeof(sinherit), size);
size += UCHAR(header.ninherits) * sizeof(sinherit);
AFREE(sinherits);
/* save program */
if (header.progsize > 0) {
sw_writev(prog, ctrl->sectors, (Uint) header.progsize, size);
size += header.progsize;
if (prog != ctrl->prog) {
AFREE(prog);
}
}
/* save string constants */
if (header.nstrings > 0) {
sw_writev((char *) sstrings, ctrl->sectors,
header.nstrings * (Uint) sizeof(dstrconst), size);
size += header.nstrings * (Uint) sizeof(dstrconst);
if (header.strsize > 0) {
sw_writev(text, ctrl->sectors, header.strsize, size);
size += header.strsize;
if (text != stext) {
AFREE(text);
}
if (stext != ctrl->stext) {
AFREE(stext);
}
}
if (sstrings != ctrl->sstrings) {
AFREE(sstrings);
}
}
/* save function definitions */
if (UCHAR(header.nfuncdefs) > 0) {
sw_writev((char *) ctrl->funcdefs, ctrl->sectors,
UCHAR(header.nfuncdefs) * (Uint) sizeof(dfuncdef), size);
size += UCHAR(header.nfuncdefs) * (Uint) sizeof(dfuncdef);
}
/* save variable definitions */
if (UCHAR(header.nvardefs) > 0) {
sw_writev((char *) ctrl->vardefs, ctrl->sectors,
UCHAR(header.nvardefs) * (Uint) sizeof(dvardef), size);
size += UCHAR(header.nvardefs) * (Uint) sizeof(dvardef);
if (UCHAR(header.nclassvars) > 0) {
sw_writev(ctrl->classvars, ctrl->sectors,
UCHAR(header.nclassvars) * (Uint) 3, size);
size += UCHAR(header.nclassvars) * (Uint) 3;
}
}
/* save function call table */
if (header.nfuncalls > 0) {
sw_writev((char *) ctrl->funcalls, ctrl->sectors,
header.nfuncalls * (Uint) 2, size);
size += header.nfuncalls * (Uint) 2;
}
/* save symbol table */
if (header.nsymbols > 0) {
sw_writev((char *) ctrl->symbols, ctrl->sectors,
header.nsymbols * (Uint) sizeof(dsymbol), size);
}
}
}
static void d_count P((savedata*, value*, unsigned int));
/*
* NAME: data->arrcount()
* DESCRIPTION: count the number of arrays and strings in an array
*/
static void d_arrcount(register savedata *save, register array *arr)
{
arr->prev->next = arr->next;
arr->next->prev = arr->prev;
arr->prev = &save->alist;
arr->next = save->alist.next;
arr->next->prev = arr;
save->alist.next = arr;
save->narr++;
if (!save->counting) {
save->counting = TRUE;
do {
save->arrsize += arr->size;
d_count(save, d_get_elts(arr), arr->size);
arr = arr->prev;
} while (arr != &save->alist);
save->counting = FALSE;
}
}
/*
* NAME: data->count()
* DESCRIPTION: count the number of arrays and strings in an object
*/
static void d_count(save, v, n)
register savedata *save;
register value *v;
register unsigned int n;
{
register object *obj;
register value *elts;
Uint count;
while (n > 0) {
switch (v->type) {
case T_STRING:
if (str_put(save->smerge, v->u.string, save->nstr) == save->nstr) {
save->nstr++;
save->strsize += v->u.string->len;
}
break;
case T_ARRAY:
if (arr_put(save->amerge, v->u.array, save->narr) == save->narr) {
d_arrcount(save, v->u.array);
}
break;
case T_MAPPING:
if (arr_put(save->amerge, v->u.array, save->narr) == save->narr) {
if (v->u.array->hashmod) {
map_compact(v->u.array->primary->data, v->u.array);
}
d_arrcount(save, v->u.array);
}
break;
case T_LWOBJECT:
elts = d_get_elts(v->u.array);
obj = OBJ(elts->oindex);
if (save->counttab != (Uint *) NULL) {
count = save->counttab[elts->oindex];
} else {
count = obj->count;
}
if (elts[1].type == T_INT) {
/* convert to new LWO type */
elts[1].type = T_FLOAT;
elts[1].oindex = FALSE;
}
if (elts->u.objcnt == count) {
if (arr_put(save->amerge, v->u.array, save->narr) == save->narr)
{
if (elts[1].u.objcnt != obj->update) {
d_upgrade_lwobj(v->u.array, obj);
elts = v->u.array->elts;
}
if (save->counttab != (Uint *) NULL) {
elts[1].u.objcnt = 0;
}
d_arrcount(save, v->u.array);
}
} else {
arr_del(v->u.array);
*v = nil_value;
}
break;
}
v++;
--n;
}
}
/*
* NAME: data->save()
* DESCRIPTION: recursively save the values in an object
*/
static void d_save(save, sv, v, n)
register savedata *save;
register svalue *sv;
register value *v;
register unsigned short n;
{
register Uint i;
while (n > 0) {
switch (sv->type = v->type) {
case T_NIL:
sv->oindex = 0;
sv->u.number = 0;
break;
case T_INT:
sv->oindex = 0;
sv->u.number = v->u.number;
break;
case T_STRING:
i = str_put(save->smerge, v->u.string, save->nstr);
sv->oindex = 0;
sv->u.string = i;
if (save->sstrings[i].ref++ == 0) {
/* new string value */
save->sstrings[i].index = save->strsize;
save->sstrings[i].len = v->u.string->len;
memcpy(save->stext + save->strsize, v->u.string->text,
v->u.string->len);
save->strsize += v->u.string->len;
}
break;
case T_FLOAT:
case T_OBJECT:
sv->oindex = v->oindex;
sv->u.objcnt = v->u.objcnt;
break;
case T_ARRAY:
case T_MAPPING:
case T_LWOBJECT:
i = arr_put(save->amerge, v->u.array, save->narr);
sv->oindex = 0;
sv->u.array = i;
save->sarrays[i].ref++;
break;
}
sv++;
v++;
--n;
}
}
/*
* NAME: data->put_values()
* DESCRIPTION: save modified values as svalues
*/
static void d_put_values(data, sv, v, n)
register dataspace *data;
register svalue *sv;
register value *v;
register unsigned short n;
{
while (n > 0) {
if (v->modified) {
switch (sv->type = v->type) {
case T_NIL:
sv->oindex = 0;
sv->u.number = 0;
break;
case T_INT:
sv->oindex = 0;
sv->u.number = v->u.number;
break;
case T_STRING:
sv->oindex = 0;
sv->u.string = v->u.string->primary - data->base.strings;
break;
case T_FLOAT:
case T_OBJECT:
sv->oindex = v->oindex;
sv->u.objcnt = v->u.objcnt;
break;
case T_ARRAY:
case T_MAPPING:
case T_LWOBJECT:
sv->oindex = 0;
sv->u.array = v->u.array->primary - data->base.arrays;
break;
}
v->modified = FALSE;
}
sv++;
v++;
--n;
}
}
/*
* NAME: data->free_values()
* DESCRIPTION: free values in a dataspace block
*/
static void d_free_values(data)
register dataspace *data;
{
register Uint i;
/* free parse_string data */
if (data->parser != (struct _parser_ *) NULL) {
ps_del(data->parser);
data->parser = (struct _parser_ *) NULL;
}
/* free variables */
if (data->variables != (value *) NULL) {
register value *v;
for (i = data->nvariables, v = data->variables; i > 0; --i, v++) {
i_del_value(v);
}
FREE(data->variables);
data->variables = (value *) NULL;
}
/* free callouts */
if (data->callouts != (dcallout *) NULL) {
register dcallout *co;
register value *v;
register int j;
for (i = data->ncallouts, co = data->callouts; i > 0; --i, co++) {
v = co->val;
if (v->type == T_STRING) {
j = 1 + co->nargs;
if (j > 4) {
j = 4;
}
do {
i_del_value(v++);
} while (--j > 0);
}
}
FREE(data->callouts);
data->callouts = (dcallout *) NULL;
}
/* free arrays */
if (data->base.arrays != (arrref *) NULL) {
register arrref *a;
for (i = data->narrays, a = data->base.arrays; i > 0; --i, a++) {
if (a->arr != (array *) NULL) {
arr_del(a->arr);
}
}
FREE(data->base.arrays);
data->base.arrays = (arrref *) NULL;
}
/* free strings */
if (data->base.strings != (strref *) NULL) {
register strref *s;
for (i = data->nstrings, s = data->base.strings; i > 0; --i, s++) {
if (s->str != (string *) NULL) {
s->str->primary = (strref *) NULL;
str_del(s->str);
}
}
FREE(data->base.strings);
data->base.strings = (strref *) NULL;
}
/* free any left-over arrays */
if (data->alist.next != &data->alist) {
data->alist.prev->next = data->alist.next;
data->alist.next->prev = data->alist.prev;
arr_freelist(data->alist.next);
data->alist.prev = data->alist.next = &data->alist;
}
}
/*
* NAME: data->save_dataspace()
* DESCRIPTION: save all values in a dataspace block
*/
static bool d_save_dataspace(data, swap, counttab)
register dataspace *data;
bool swap;
Uint *counttab;
{
sdataspace header;
register Uint n;
if (data->parser != (struct _parser_ *) NULL) {
ps_save(data->parser);
}
if (data->base.flags == 0) {
return FALSE;
}
if ((data->nsectors != 0 || !swap) && data->base.achange == 0 &&
data->base.schange == 0 && !(data->base.flags & MOD_NEWCALLOUT)) {
bool mod;
/*
* No strings/arrays added or deleted. Check individual variables and
* array elements.
*/
if (data->base.flags & MOD_VARIABLE) {
/*
* variables changed
*/
d_put_values(data, data->svariables, data->variables,
data->nvariables);
if (swap) {
sw_writev((char *) data->svariables, data->sectors,
data->nvariables * (Uint) sizeof(svalue),
data->varoffset);
}
}
if (data->base.flags & MOD_ARRAYREF) {
register sarray *sa;
register arrref *a;
/*
* references to arrays changed
*/
sa = data->sarrays;
a = data->base.arrays;
mod = FALSE;
for (n = data->narrays; n > 0; --n) {
if (a->arr != (array *) NULL && sa->ref != (a->ref & ~ARR_MOD))
{
sa->ref = a->ref & ~ARR_MOD;
mod = TRUE;
}
sa++;
a++;
}
if (mod && swap) {
sw_writev((char *) data->sarrays, data->sectors,
data->narrays * sizeof(sarray), data->arroffset);
}
}
if (data->base.flags & MOD_ARRAY) {
register arrref *a;
Uint idx;
/*
* array elements changed
*/
a = data->base.arrays;
for (n = 0; n < data->narrays; n++) {
if (a->arr != (array *) NULL && (a->ref & ARR_MOD)) {
a->ref &= ~ARR_MOD;
idx = data->sarrays[n].index;
d_put_values(data, &data->selts[idx], a->arr->elts,
a->arr->size);
if (swap) {
sw_writev((char *) &data->selts[idx], data->sectors,
a->arr->size * (Uint) sizeof(svalue),
data->arroffset +
data->narrays * sizeof(sarray) +
idx * sizeof(svalue));
}
}
a++;
}
}
if (data->base.flags & MOD_STRINGREF) {
register sstring *ss;
register strref *s;
/*
* string references changed
*/
ss = data->sstrings;
s = data->base.strings;
mod = FALSE;
for (n = data->nstrings; n > 0; --n) {
if (s->str != (string *) NULL && ss->ref != s->ref) {
ss->ref = s->ref;
mod = TRUE;
}
ss++;
s++;
}
if (mod && swap) {
sw_writev((char *) data->sstrings, data->sectors,
data->nstrings * sizeof(sstring),
data->stroffset);
}
}
if (data->base.flags & MOD_CALLOUT) {
register scallout *sco;
register dcallout *co;
sco = data->scallouts;
co = data->callouts;
for (n = data->ncallouts; n > 0; --n) {
sco->time = co->time;
sco->nargs = co->nargs;
if (co->val[0].type == T_STRING) {
co->val[0].modified = TRUE;
co->val[1].modified = TRUE;
co->val[2].modified = TRUE;
co->val[3].modified = TRUE;
d_put_values(data, sco->val, co->val,
(co->nargs > 3) ? 4 : co->nargs + 1);
} else {
sco->val[0].type = T_NIL;
}
sco++;
co++;
}
if (swap) {
/* save new (?) fcallouts value */
sw_writev((char *) &data->fcallouts, data->sectors,
(Uint) sizeof(uindex),
(Uint) ((char *)&header.fcallouts - (char *)&header));
/* save scallouts */
sw_writev((char *) data->scallouts, data->sectors,
data->ncallouts * (Uint) sizeof(scallout),
data->cooffset);
}
}
} else {
savedata save;
char *text;
register Uint size;
register array *arr;
register sarray *sarr;
/*
* count the number and sizes of strings and arrays
*/
save.amerge = arr_merge();
save.smerge = str_merge();
save.narr = 0;
save.nstr = 0;
save.arrsize = 0;
save.strsize = 0;
save.counttab = counttab;
save.counting = FALSE;
save.alist.prev = save.alist.next = &save.alist;
d_get_variable(data, 0);
if (data->svariables == (svalue *) NULL) {
data->svariables = ALLOC(svalue, data->nvariables);
}
d_count(&save, data->variables, data->nvariables);
if (data->ncallouts > 0) {
register dcallout *co;
if (data->callouts == (dcallout *) NULL) {
d_get_callouts(data);
}
/* remove empty callouts at the end */
for (n = data->ncallouts, co = data->callouts + n; n > 0; --n) {
if ((--co)->val[0].type == T_STRING) {
break;
}
if (data->fcallouts == n) {
/* first callout in the free list */
data->fcallouts = co->co_next;
} else {
/* connect previous to next */
data->callouts[co->co_prev - 1].co_next = co->co_next;
if (co->co_next != 0) {
/* connect next to previous */
data->callouts[co->co_next - 1].co_prev = co->co_prev;
}
}
}
data->ncallouts = n;
if (n == 0) {
/* all callouts removed */
FREE(data->callouts);
data->callouts = (dcallout *) NULL;
} else {
/* process callouts */
for (co = data->callouts; n > 0; --n, co++) {
if (co->val[0].type == T_STRING) {
d_count(&save, co->val,
(co->nargs > 3) ? 4 : co->nargs + 1);
}
}
}
}
/* fill in header */
header.flags = 0;
header.nvariables = data->nvariables;
header.narrays = save.narr;
header.eltsize = save.arrsize;
header.nstrings = save.nstr;
header.strsize = save.strsize;
header.ncallouts = data->ncallouts;
header.fcallouts = data->fcallouts;
/*
* put everything in a saveable form
*/
save.sstrings = data->sstrings =
REALLOC(data->sstrings, sstring, 0, header.nstrings);
memset(save.sstrings, '\0', save.nstr * sizeof(sstring));
save.stext = data->stext =
REALLOC(data->stext, char, 0, header.strsize);
save.sarrays = data->sarrays =
REALLOC(data->sarrays, sarray, 0, header.narrays);
memset(save.sarrays, '\0', save.narr * sizeof(sarray));
save.selts = data->selts =
REALLOC(data->selts, svalue, 0, header.eltsize);
save.narr = 0;
save.nstr = 0;
save.arrsize = 0;
save.strsize = 0;
data->scallouts = REALLOC(data->scallouts, scallout, 0,
header.ncallouts);
d_save(&save, data->svariables, data->variables, data->nvariables);
if (header.ncallouts > 0) {
register scallout *sco;
register dcallout *co;
sco = data->scallouts;
co = data->callouts;
for (n = data->ncallouts; n > 0; --n) {
sco->time = co->time;
sco->nargs = co->nargs;
if (co->val[0].type == T_STRING) {
d_save(&save, sco->val, co->val,
(co->nargs > 3) ? 4 : co->nargs + 1);
} else {
sco->val[0].type = T_NIL;
}
sco++;
co++;
}
}
for (arr = save.alist.prev, sarr = save.sarrays; arr != &save.alist;
arr = arr->prev, sarr++) {
sarr->index = save.arrsize;
sarr->size = arr->size;
sarr->tag = arr->tag;
d_save(&save, save.selts + save.arrsize, arr->elts, arr->size);
save.arrsize += arr->size;
}
if (arr->next != &save.alist) {
data->alist.next->prev = arr->prev;
arr->prev->next = data->alist.next;
data->alist.next = arr->next;
arr->next->prev = &data->alist;
}
/* clear merge tables */
arr_clear(save.amerge);
str_clear(save.smerge);
if (swap) {
text = save.stext;
if (header.strsize >= CMPLIMIT) {
text = ALLOCA(char, header.strsize);
size = compress(text, save.stext, header.strsize);
if (size != 0) {
header.flags |= CMP_PRED;
header.strsize = size;
} else {
AFREE(text);
text = save.stext;
}
}
/* create sector space */
size = sizeof(sdataspace) +
(header.nvariables + header.eltsize) * sizeof(svalue) +
header.narrays * sizeof(sarray) +
header.nstrings * sizeof(sstring) +
header.strsize +
header.ncallouts * (Uint) sizeof(scallout);
header.nsectors = d_swapalloc(size, data->nsectors, &data->sectors);
data->nsectors = header.nsectors;
OBJ(data->oindex)->dfirst = data->sectors[0];
/* save header */
size = sizeof(sdataspace);
sw_writev((char *) &header, data->sectors, size, (Uint) 0);
sw_writev((char *) data->sectors, data->sectors,
header.nsectors * (Uint) sizeof(sector), size);
size += header.nsectors * (Uint) sizeof(sector);
/* save variables */
data->varoffset = size;
sw_writev((char *) data->svariables, data->sectors,
data->nvariables * (Uint) sizeof(svalue), size);
size += data->nvariables * (Uint) sizeof(svalue);
/* save arrays */
data->arroffset = size;
if (header.narrays > 0) {
sw_writev((char *) save.sarrays, data->sectors,
header.narrays * sizeof(sarray), size);
size += header.narrays * sizeof(sarray);
if (header.eltsize > 0) {
sw_writev((char *) save.selts, data->sectors,
header.eltsize * sizeof(svalue), size);
size += header.eltsize * sizeof(svalue);
}
}
/* save strings */
data->stroffset = size;
if (header.nstrings > 0) {
sw_writev((char *) save.sstrings, data->sectors,
header.nstrings * sizeof(sstring), size);
size += header.nstrings * sizeof(sstring);
if (header.strsize > 0) {
sw_writev(text, data->sectors, header.strsize, size);
size += header.strsize;
if (text != save.stext) {
AFREE(text);
}
}
}
/* save callouts */
data->cooffset = size;
if (header.ncallouts > 0) {
sw_writev((char *) data->scallouts, data->sectors,
header.ncallouts * (Uint) sizeof(scallout), size);
}
}
d_free_values(data);
data->flags = header.flags;
data->narrays = header.narrays;
data->eltsize = header.eltsize;
data->nstrings = header.nstrings;
data->strsize = save.strsize;
data->base.schange = 0;
data->base.achange = 0;
}
data->base.flags = 0;
return TRUE;
}
/*
* NAME: data->swapout()
* DESCRIPTION: Swap out a portion of the control and dataspace blocks in
* memory. Return the number of dataspace blocks swapped out.
*/
sector d_swapout(frag)
unsigned int frag;
{
register sector n, count;
register dataspace *data;
register control *ctrl;
count = 0;
n = ndata;
/* perform garbage collection for one dataspace */
if (gcdata != (dataspace *) NULL && (frag == 0 || n - 1 >= frag)) {
if (d_save_dataspace(gcdata, (frag != 0), (Uint *) NULL)) {
count++;
if (frag != 1) {
--n;
}
}
gcdata = gcdata->gcnext;
}
if (frag != 0) {
/* swap out dataspace blocks */
data = dtail;
for (n /= frag; n > 0; --n) {
register dataspace *prev;
prev = data->prev;
if (d_save_dataspace(data, TRUE, (Uint *) NULL)) {
count++;
}
OBJ(data->oindex)->data = (dataspace *) NULL;
d_free_dataspace(data);
data = prev;
}
/* swap out control blocks */
ctrl = ctail;
for (n = nctrl / frag; n > 0; --n) {
register control *prev;
prev = ctrl->prev;
if (ctrl->ndata == 0) {
if ((ctrl->sectors == (sector *) NULL &&
!(ctrl->flags & CTRL_COMPILED)) ||
(ctrl->flags & CTRL_VARMAP)) {
d_save_control(ctrl);
}
OBJ(ctrl->oindex)->ctrl = (control *) NULL;
d_free_control(ctrl);
}
ctrl = prev;
}
}
return count;
}
/*
* NAME: data->swapsync()
* DESCRIPTION: Synchronize the swap file with the state of memory, swapping
* out as little as possible.
*/
void d_swapsync()
{
register control *ctrl;
register dataspace *data;
/* save control blocks */
for (ctrl = ctail; ctrl != (control *) NULL; ctrl = ctrl->prev) {
if ((ctrl->sectors == (sector *) NULL &&
!(ctrl->flags & CTRL_COMPILED)) || (ctrl->flags & CTRL_VARMAP)) {
d_save_control(ctrl);
}
}
/* save dataspace blocks */
for (data = dtail; data != (dataspace *) NULL; data = data->prev) {
d_save_dataspace(data, TRUE, (Uint *) NULL);
}
}
/*
* NAME: data->upgrade_mem()
* DESCRIPTION: upgrade all obj and all objects cloned from obj that have
* dataspaces in memory
*/
void d_upgrade_mem(tmpl, new)
register object *tmpl, *new;
{
register dataspace *data;
register unsigned int nvar;
register unsigned short *vmap;
register object *obj;
nvar = tmpl->ctrl->vmapsize;
vmap = tmpl->ctrl->vmap;
for (data = dtail; data != (dataspace *) NULL; data = data->prev) {
obj = OBJ(data->oindex);
if ((obj == new ||
(!(obj->flags & O_MASTER) && obj->u_master == new->index)) &&
obj->count != 0) {
/* upgrade clone */
if (nvar != 0) {
d_upgrade_data(data, nvar, vmap, tmpl);
}
data->ctrl->ndata--;
data->ctrl = new->ctrl;
data->ctrl->ndata++;
}
}
}
/*
* NAME: data->conv()
* DESCRIPTION: convert something from the dump file
*/
static Uint d_conv(m, vec, layout, n, idx)
char *m, *layout;
sector *vec;
Uint n, idx;
{
Uint bufsize;
char *buf;
bufsize = (conf_dsize(layout) & 0xff) * n;
buf = ALLOCA(char, bufsize);
sw_dreadv(buf, vec, bufsize, idx);
conf_dconv(m, buf, layout, n);
AFREE(buf);
return bufsize;
}
/*
* NAME: data->conv_proto()
* DESCRIPTION: convert a prototype to the new standard
*/
static void d_conv_proto(old, new)
char **old, **new;
{
register char *p, *args;
register unsigned short i, n, type;
unsigned short class, nargs, vargs;
bool varargs;
p = *old;
class = UCHAR(*p++);
type = UCHAR(*p++);
n = UCHAR(*p++);
varargs = (class & C_VARARGS);
class &= ~C_VARARGS;
nargs = vargs = 0;
args = &PROTO_FTYPE(*new);
*args++ = (type & T_TYPE) | ((type >> 1) & T_REF);
for (i = 0; i < n; i++) {
if (varargs) {
vargs++;
} else {
nargs++;
}
type = UCHAR(*p++);
if (type & T_VARARGS) {
if (i == n - 1) {
class |= C_ELLIPSIS;
if (!varargs) {
--nargs;
vargs++;
}
}
varargs = TRUE;
}
*args++ = (type & T_TYPE) | ((type >> 1) & T_REF);
}
*old = p;
p = *new;
*new = args;
PROTO_CLASS(p) = class;
PROTO_NARGS(p) = nargs;
PROTO_VARGS(p) = vargs;
PROTO_HSIZE(p) = (6 + n) >> 8;
PROTO_LSIZE(p) = 6 + n;
}
/*
* NAME: data->conv_control()
* DESCRIPTION: convert control block
*/
void d_conv_control(oindex, conv)
unsigned int oindex;
int conv;
{
scontrol header;
register control *ctrl;
register Uint size;
register sector *s;
register unsigned int n;
object *obj;
ctrl = d_new_control();
ctrl->oindex = oindex;
obj = OBJ(oindex);
/*
* restore from dump file
*/
if (conv) {
oscontrol oheader;
size = d_conv((char *) &oheader, &obj->cfirst, os_layout, (Uint) 1,
(Uint) 0);
header.nsectors = oheader.nsectors;
header.flags = oheader.flags;
header.ninherits = oheader.ninherits;
header.compiled = oheader.compiled;
header.progsize = oheader.progsize;
header.nstrings = oheader.nstrings;
header.strsize = oheader.strsize;
header.nfuncdefs = oheader.nfuncdefs;
header.nvardefs = oheader.nvardefs;
header.nclassvars = 0;
header.nfuncalls = oheader.nfuncalls;
header.nsymbols = oheader.nsymbols;
header.nvariables = oheader.nvariables;
header.nifdefs = oheader.nifdefs;
header.nvinit = oheader.nvinit;
header.vmapsize = oheader.vmapsize;
} else {
size = d_conv((char *) &header, &obj->cfirst, sc_layout, (Uint) 1,
(Uint) 0);
}
if (header.nvariables >= PRIV) {
fatal("too many variables in restored object");
}
ctrl->ninherits = UCHAR(header.ninherits);
ctrl->compiled = header.compiled;
ctrl->progsize = header.progsize;
ctrl->nstrings = header.nstrings;
ctrl->strsize = header.strsize;
ctrl->nfuncdefs = UCHAR(header.nfuncdefs);
ctrl->nvardefs = UCHAR(header.nvardefs);
ctrl->nfuncalls = header.nfuncalls;
ctrl->nsymbols = header.nsymbols;
ctrl->nvariables = header.nvariables;
ctrl->nifdefs = header.nifdefs;
ctrl->nvinit = header.nvinit;
ctrl->vmapsize = header.vmapsize;
/* sectors */
s = ALLOCA(sector, header.nsectors);
s[0] = obj->cfirst;
for (n = 0; n < header.nsectors; n++) {
size += d_conv((char *) (s + n), s, "d", (Uint) 1, size);
}
if (header.vmapsize != 0) {
/* only vmap */
ctrl->vmap = ALLOC(unsigned short, header.vmapsize);
d_conv((char *) ctrl->vmap, s, "s", (Uint) header.vmapsize, size);
} else {
register dinherit *inherits;
register sinherit *sinherits;
/* inherits */
n = UCHAR(header.ninherits); /* at least one */
ctrl->inherits = inherits = ALLOC(dinherit, n);
sinherits = ALLOCA(sinherit, n);
size += d_conv((char *) sinherits, s, si_layout, (Uint) n, size);
do {
inherits->oindex = sinherits->oindex;
inherits->funcoffset = sinherits->funcoffset;
inherits->varoffset = sinherits->varoffset & ~PRIV;
(inherits++)->priv = (((sinherits++)->varoffset & PRIV) != 0);
} while (--n > 0);
AFREE(sinherits - UCHAR(header.ninherits));
if (header.progsize != 0) {
/* program */
if (header.flags & CMP_TYPE) {
ctrl->prog = decompress(s, sw_dreadv, header.progsize, size,
&ctrl->progsize);
} else {
ctrl->prog = ALLOC(char, header.progsize);
sw_dreadv(ctrl->prog, s, header.progsize, size);
}
size += header.progsize;
}
if (header.nstrings != 0) {
/* strings */
ctrl->sstrings = ALLOC(dstrconst, header.nstrings);
size += d_conv((char *) ctrl->sstrings, s, DSTR_LAYOUT,
(Uint) header.nstrings, size);
if (header.strsize != 0) {
if (header.flags & (CMP_TYPE << 2)) {
ctrl->stext = decompress(s, sw_dreadv, header.strsize, size,
&ctrl->strsize);
} else {
ctrl->stext = ALLOC(char, header.strsize);
sw_dreadv(ctrl->stext, s, header.strsize, size);
}
size += header.strsize;
}
}
if (header.nfuncdefs != 0) {
/* function definitions */
ctrl->funcdefs = ALLOC(dfuncdef, UCHAR(header.nfuncdefs));
size += d_conv((char *) ctrl->funcdefs, s, DF_LAYOUT,
(Uint) UCHAR(header.nfuncdefs), size);
if (conv) {
char *prog, *old, *new;
Uint offset, funcsize;
/*
* convert restored program to new prototype standard
*/
prog = ALLOC(char, ctrl->progsize + (Uint) 3 * ctrl->nfuncdefs);
new = prog;
for (n = 0; n < ctrl->nfuncdefs; n++) {
/* convert prototype */
old = ctrl->prog + ctrl->funcdefs[n].offset;
ctrl->funcdefs[n].offset = new - prog;
d_conv_proto(&old, &new);
/* copy program */
offset = old - ctrl->prog;
if (n < ctrl->nfuncdefs - 1) {
funcsize = ctrl->funcdefs[n + 1].offset - offset;
} else {
funcsize = ctrl->progsize - offset;
}
if (funcsize != 0) {
memcpy(new, old, funcsize);
new += funcsize;
}
}
/* replace program */
FREE(ctrl->prog);
ctrl->prog = prog;
ctrl->progsize = new - prog;
}
}
if (header.nvardefs != 0) {
/* variable definitions */
ctrl->vardefs = ALLOC(dvardef, UCHAR(header.nvardefs));
size += d_conv((char *) ctrl->vardefs, s, DV_LAYOUT,
(Uint) UCHAR(header.nvardefs), size);
if (conv) {
register unsigned short type;
for (n = 0; n < ctrl->nvardefs; n++) {
type = ctrl->vardefs[n].type;
ctrl->vardefs[n].type =
(type & T_TYPE) | ((type >> 1) & T_REF);
}
}
}
if (header.nfuncalls != 0) {
/* function calls */
ctrl->funcalls = ALLOC(char, 2 * header.nfuncalls);
sw_dreadv(ctrl->funcalls, s, header.nfuncalls * (Uint) 2, size);
size += header.nfuncalls * (Uint) 2;
}
if (header.nsymbols != 0) {
/* symbol table */
ctrl->symbols = ALLOC(dsymbol, header.nsymbols);
d_conv((char *) ctrl->symbols, s, DSYM_LAYOUT,
(Uint) header.nsymbols, size);
}
}
AFREE(s);
d_save_control(ctrl);
OBJ(ctrl->oindex)->ctrl = (control *) NULL;
d_free_control(ctrl);
}
/*
* NAME: data->fixobjs()
* DESCRIPTION: fix objects in dataspace
*/
static void d_fixobjs(v, n, ctab)
register svalue *v;
register Uint n, *ctab;
{
while (n != 0) {
if (v->type == T_OBJECT) {
if (v->u.objcnt == OBJ(v->oindex)->count) {
/* fix object count */
v->u.objcnt = ctab[v->oindex];
} else {
/* destructed object; mark as invalid */
v->u.objcnt = 1;
}
}
v++;
--n;
}
}
/*
* NAME: data->conv_dataspace()
* DESCRIPTION: convert dataspace
*/
void d_conv_dataspace(obj, counttab, convert)
object *obj;
Uint *counttab;
int convert;
{
sdataspace header;
register dataspace *data;
register Uint size;
register sector *s;
register unsigned int n;
data = d_alloc_dataspace(obj);
/*
* restore from dump file
*/
size = d_conv((char *) &header, &obj->dfirst, sd_layout, (Uint) 1,
(Uint) 0);
data->nvariables = header.nvariables;
data->narrays = header.narrays;
data->eltsize = header.eltsize;
data->nstrings = header.nstrings;
data->strsize = header.strsize;
data->ncallouts = header.ncallouts;
data->fcallouts = header.fcallouts;
/* sectors */
s = ALLOCA(sector, header.nsectors);
s[0] = obj->dfirst;
for (n = 0; n < header.nsectors; n++) {
size += d_conv((char *) (s + n), s, "d", (Uint) 1, size);
}
/* variables */
data->svariables = ALLOC(svalue, header.nvariables);
size += d_conv((char *) data->svariables, s, sv_layout,
(Uint) header.nvariables, size);
d_fixobjs(data->svariables, (Uint) header.nvariables, counttab);
if (header.narrays != 0) {
/* arrays */
data->sarrays = ALLOC(sarray, header.narrays);
size += d_conv((char *) data->sarrays, s, sa_layout, header.narrays,
size);
if (header.eltsize != 0) {
data->selts = ALLOC(svalue, header.eltsize);
size += d_conv((char *) data->selts, s, sv_layout, header.eltsize,
size);
d_fixobjs(data->selts, header.eltsize, counttab);
}
}
if (header.nstrings != 0) {
/* strings */
data->sstrings = ALLOC(sstring, header.nstrings);
size += d_conv((char *) data->sstrings, s, ss_layout, header.nstrings,
size);
if (header.strsize != 0) {
if (header.flags & CMP_TYPE) {
data->stext = decompress(s, sw_dreadv, header.strsize, size,
&data->strsize);
} else {
data->stext = ALLOC(char, header.strsize);
sw_dreadv(data->stext, s, header.strsize, size);
}
size += header.strsize;
}
}
if (header.ncallouts != 0) {
register scallout *sco;
register dcallout *co;
/* callouts */
co = data->callouts = ALLOC(dcallout, header.ncallouts);
sco = data->scallouts = ALLOC(scallout, header.ncallouts);
if (convert) {
register oscallout *osc;
/*
* convert old format callouts
*/
osc = ALLOCA(oscallout, header.ncallouts);
d_conv((char *) osc, s, osc_layout, (Uint) header.ncallouts, size);
for (n = data->ncallouts; n > 0; --n) {
sco->time = osc->time;
sco->nargs = osc->nargs;
memcpy(sco->val, osc->val, 4 * sizeof(svalue));
sco++;
osc++;
}
sco -= data->ncallouts;
AFREE(osc - data->ncallouts);
} else {
d_conv((char *) data->scallouts, s, sco_layout,
(Uint) header.ncallouts, size);
}
for (n = data->ncallouts; n > 0; --n) {
co->time = sco->time;
co->nargs = sco->nargs;
if (sco->val[0].type == T_STRING) {
if (sco->nargs > 3) {
d_fixobjs(sco->val, (Uint) 4, counttab);
d_get_values(data, sco->val, co->val, 4);
} else {
d_fixobjs(sco->val, sco->nargs + (Uint) 1, counttab);
d_get_values(data, sco->val, co->val, sco->nargs + 1);
}
} else {
co->val[0] = nil_value;
}
sco++;
co++;
}
}
AFREE(s);
if (!(obj->flags & O_MASTER) && obj->update != OBJ(obj->u_master)->update) {
/* handle object upgrading right away */
data->ctrl = o_control(obj);
data->ctrl->ndata++;
d_upgrade_clone(data);
}
data->base.flags |= MOD_ALL;
d_save_dataspace(data, TRUE, counttab);
OBJ(data->oindex)->data = (dataspace *) NULL;
d_free_dataspace(data);
}
/*
* NAME: data->free_control()
* DESCRIPTION: remove the control block from memory
*/
void d_free_control(ctrl)
register control *ctrl;
{
register string **strs;
register unsigned short i;
/* delete strings */
if (ctrl->strings != (string **) NULL) {
strs = ctrl->strings;
for (i = ctrl->nstrings; i > 0; --i) {
if (*strs != (string *) NULL) {
str_del(*strs);
}
strs++;
}
FREE(ctrl->strings);
}
if (ctrl->cvstrings != (string **) NULL) {
strs = ctrl->cvstrings;
for (i = ctrl->nvardefs; i > 0; --i) {
if (*strs != (string *) NULL) {
str_del(*strs);
}
strs++;
}
FREE(ctrl->cvstrings);
}
/* delete vmap */
if (ctrl->vmap != (unsigned short *) NULL) {
FREE(ctrl->vmap);
}
if (!(ctrl->flags & CTRL_COMPILED)) {
/* delete sectors */
if (ctrl->sectors != (sector *) NULL) {
FREE(ctrl->sectors);
}
if (ctrl->inherits != (dinherit *) NULL) {
/* delete inherits */
FREE(ctrl->inherits);
}
if (ctrl->prog != (char *) NULL) {
FREE(ctrl->prog);
}
/* delete string constants */
if (ctrl->sstrings != (dstrconst *) NULL) {
FREE(ctrl->sstrings);
}
if (ctrl->stext != (char *) NULL) {
FREE(ctrl->stext);
}
/* delete function definitions */
if (ctrl->funcdefs != (dfuncdef *) NULL) {
FREE(ctrl->funcdefs);
}
/* delete variable definitions */
if (ctrl->vardefs != (dvardef *) NULL) {
FREE(ctrl->vardefs);
if (ctrl->classvars != (char *) NULL) {
FREE(ctrl->classvars);
}
}
/* delete function call table */
if (ctrl->funcalls != (char *) NULL) {
FREE(ctrl->funcalls);
}
/* delete symbol table */
if (ctrl->symbols != (dsymbol *) NULL) {
FREE(ctrl->symbols);
}
}
if (ctrl != chead) {
ctrl->prev->next = ctrl->next;
} else {
chead = ctrl->next;
if (chead != (control *) NULL) {
chead->prev = (control *) NULL;
}
}
if (ctrl != ctail) {
ctrl->next->prev = ctrl->prev;
} else {
ctail = ctrl->prev;
if (ctail != (control *) NULL) {
ctail->next = (control *) NULL;
}
}
--nctrl;
FREE(ctrl);
}
/*
* NAME: data->free_dataspace()
* DESCRIPTION: remove the dataspace block from memory
*/
void d_free_dataspace(data)
register dataspace *data;
{
/* free values */
d_free_values(data);
/* delete sectors */
if (data->sectors != (sector *) NULL) {
FREE(data->sectors);
}
/* free scallouts */
if (data->scallouts != (scallout *) NULL) {
FREE(data->scallouts);
}
/* free sarrays */
if (data->sarrays != (sarray *) NULL) {
if (data->selts != (svalue *) NULL) {
FREE(data->selts);
}
FREE(data->sarrays);
}
/* free sstrings */
if (data->sstrings != (sstring *) NULL) {
if (data->stext != (char *) NULL) {
FREE(data->stext);
}
FREE(data->sstrings);
}
/* free svariables */
if (data->svariables != (svalue *) NULL) {
FREE(data->svariables);
}
if (data->ctrl != (control *) NULL) {
data->ctrl->ndata--;
}
if (data != dhead) {
data->prev->next = data->next;
} else {
dhead = data->next;
if (dhead != (dataspace *) NULL) {
dhead->prev = (dataspace *) NULL;
}
}
if (data != dtail) {
data->next->prev = data->prev;
} else {
dtail = data->prev;
if (dtail != (dataspace *) NULL) {
dtail->next = (dataspace *) NULL;
}
}
data->gcprev->gcnext = data->gcnext;
data->gcnext->gcprev = data->gcprev;
if (data == gcdata) {
gcdata = (data != data->gcnext) ? data->gcnext : (dataspace *) NULL;
}
--ndata;
FREE(data);
}