1 /*
2  * This file is part of DGD, https://github.com/dworkin/dgd
3  * Copyright (C) 1993-2010 Dworkin B.V.
4  * Copyright (C) 2010-2012 DGD Authors (see the commit log for details)
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Affero General Public License as
8  * published by the Free Software Foundation, either version 3 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Affero General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 # include "dgd.h"
21 # include "str.h"
22 # include "array.h"
23 # include "object.h"
24 # include "interpret.h"
25 # include "data.h"
26 # include "call_out.h"
27 # include "parse.h"
28 # include "control.h"
29 # include "csupport.h"
30 
31 
32 # define PRIV			0x0001	/* in sinherit->flags */
33 
34 typedef struct {
35     sector nsectors;		/* # sectors in part one */
36     short flags;		/* control flags: compression */
37     short ninherits;		/* # objects in inherit table */
38     uindex imapsz;		/* inherit map size */
39     Uint progsize;		/* size of program code */
40     Uint compiled;		/* time of compilation */
41     unsigned short comphigh;	/* time of compilation high word */
42     unsigned short nstrings;	/* # strings in string constant table */
43     Uint strsize;		/* size of string constant table */
44     char nfuncdefs;		/* # entries in function definition table */
45     char nvardefs;		/* # entries in variable definition table */
46     char nclassvars;		/* # class variables */
47     uindex nfuncalls;		/* # entries in function call table */
48     unsigned short nsymbols;	/* # entries in symbol table */
49     unsigned short nvariables;	/* # variables */
50     unsigned short vmapsize;	/* size of variable map, or 0 for none */
51 } scontrol;
52 
53 static char sc_layout[] = "dssuiissicccusss";
54 
55 typedef struct {
56     sector nsectors;		/* # sectors in part one */
57     short flags;		/* control flags: compression */
58     short ninherits;		/* # objects in inherit table */
59     uindex imapsz;		/* inherit map size */
60     Uint compiled;		/* time of compilation */
61     Uint progsize;		/* size of program code */
62     unsigned short nstrings;	/* # strings in string constant table */
63     Uint strsize;		/* size of string constant table */
64     char nfuncdefs;		/* # entries in function definition table */
65     char nvardefs;		/* # entries in variable definition table */
66     char nclassvars;		/* # class variables */
67     uindex nfuncalls;		/* # entries in function call table */
68     unsigned short nsymbols;	/* # entries in symbol table */
69     unsigned short nvariables;	/* # variables */
70     unsigned short vmapsize;	/* size of variable map, or 0 for none */
71 } tscontrol;
72 
73 static char tsc_layout[] = "dssuiisicccusss";
74 
75 typedef struct {
76     sector nsectors;		/* # sectors in part one */
77     short flags;		/* control flags: compression */
78     short ninherits;		/* # objects in inherit table */
79     Uint compiled;		/* time of compilation */
80     Uint progsize;		/* size of program code */
81     unsigned short nstrings;	/* # strings in string constant table */
82     Uint strsize;		/* size of string constant table */
83     char nfuncdefs;		/* # entries in function definition table */
84     char nvardefs;		/* # entries in variable definition table */
85     char nclassvars;		/* # class variables */
86     uindex nfuncalls;		/* # entries in function call table */
87     unsigned short nsymbols;	/* # entries in symbol table */
88     unsigned short nvariables;	/* # variables */
89     unsigned short vmapsize;	/* size of variable map, or 0 for none */
90 } xscontrol;
91 
92 static char xsc_layout[] = "dssiisicccusss";
93 
94 typedef struct {
95     sector nsectors;		/* # sectors in part one */
96     char flags;			/* control flags: compression */
97     char ninherits;		/* # objects in inherit table */
98     Uint compiled;		/* time of compilation */
99     Uint progsize;		/* size of program code */
100     unsigned short nstrings;	/* # strings in string constant table */
101     Uint strsize;		/* size of string constant table */
102     char nfuncdefs;		/* # entries in function definition table */
103     char nvardefs;		/* # entries in variable definition table */
104     char nclassvars;		/* # class variables */
105     uindex nfuncalls;		/* # entries in function call table */
106     unsigned short nsymbols;	/* # entries in symbol table */
107     unsigned short nvariables;	/* # variables */
108     unsigned short nifdefs;	/* # int/float definitions */
109     unsigned short nvinit;	/* # variables requiring initialization */
110     unsigned short vmapsize;	/* size of variable map, or 0 for none */
111 } ocontrol;
112 
113 static char oc_layout[] = "dcciisicccusssss";
114 
115 typedef struct {
116     sector nsectors;		/* # sectors in part one */
117     char flags;			/* control flags: compression */
118     char ninherits;		/* # objects in inherit table */
119     Uint compiled;		/* time of compilation */
120     Uint progsize;		/* size of program code */
121     unsigned short nstrings;	/* # strings in string constant table */
122     Uint strsize;		/* size of string constant table */
123     char nfuncdefs;		/* # entries in function definition table */
124     char nvardefs;		/* # entries in variable definition table */
125     uindex nfuncalls;		/* # entries in function call table */
126     unsigned short nsymbols;	/* # entries in symbol table */
127     unsigned short nvariables;	/* # variables */
128     unsigned short nifdefs;	/* # int/float definitions */
129     unsigned short nvinit;	/* # variables requiring initialization */
130     unsigned short vmapsize;	/* size of variable map, or 0 for none */
131 } oscontrol;
132 
133 static char os_layout[] = "dcciisiccusssss";
134 
135 typedef struct {
136     uindex oindex;		/* index in object table */
137     uindex progoffset;		/* program offset */
138     uindex funcoffset;		/* function call offset */
139     unsigned short varoffset;	/* variable offset */
140     unsigned short flags;	/* bit flags */
141 } sinherit;
142 
143 static char si_layout[] = "uuuss";
144 
145 typedef struct {
146     uindex oindex;		/* index in object table */
147     uindex funcoffset;		/* function call offset */
148     unsigned short varoffset;	/* variable offset + private bit */
149 } osinherit;
150 
151 static char osi_layout[] = "uus";
152 
153 typedef struct {
154     char class;			/* variable class */
155     char inherit;		/* variable name inherit index */
156     unsigned short index;	/* variable name index */
157     unsigned short type;	/* variable type */
158 } ovardef;
159 
160 # define OV_LAYOUT	"ccss"
161 
162 typedef struct {
163     sector nsectors;		/* number of sectors in data space */
164     short flags;		/* dataspace flags: compression */
165     unsigned short nvariables;	/* number of variables */
166     Uint narrays;		/* number of array values */
167     Uint eltsize;		/* total size of array elements */
168     Uint nstrings;		/* number of strings */
169     Uint strsize;		/* total size of strings */
170     uindex ncallouts;		/* number of callouts */
171     uindex fcallouts;		/* first free callout */
172 } sdataspace;
173 
174 static char sd_layout[] = "dssiiiiuu";
175 
176 struct _svalue_ {
177     char type;			/* object, number, string, array */
178     char pad;			/* 0 */
179     uindex oindex;		/* index in object table */
180     union {
181 	Int number;		/* number */
182 	Uint string;		/* string */
183 	Uint objcnt;		/* object creation count */
184 	Uint array;		/* array */
185     } u;
186 };
187 
188 static char sv_layout[] = "ccui";
189 
190 typedef struct {
191     char type;			/* object, number, string, array */
192     uindex oindex;		/* index in object table */
193     Uint objcnt;		/* number, string, object, array */
194 } osvalue;
195 
196 static char osv_layout[] = "cui";
197 
198 typedef struct {
199     short type;			/* old type */
200     uindex oindex;		/* index in object table */
201     Uint objcnt;		/* number, string, object, array */
202 } oosvalue;
203 
204 static char oosv_layout[] = "sui";
205 
206 typedef struct _sarray_ {
207     Uint index;			/* index in array value table */
208     char type;			/* array type */
209     unsigned short size;	/* size of array */
210     Uint ref;			/* refcount */
211     Uint tag;			/* unique value for each array */
212 } sarray;
213 
214 static char sa_layout[] = "icsii";
215 
216 typedef struct {
217     Uint index;			/* index in array value table */
218     unsigned short size;	/* size of array */
219     Uint ref;			/* refcount */
220     Uint tag;			/* unique value for each array */
221 } osarray;
222 
223 static char osa_layout[] = "isii";
224 
225 typedef struct _sstring_ {
226     Uint index;			/* index in string text table */
227     ssizet len;			/* length of string */
228     Uint ref;			/* refcount */
229 } sstring;
230 
231 static char ss_layout[] = "iti";
232 
233 typedef struct _scallout_ {
234     Uint time;			/* time of call */
235     unsigned short htime;	/* time of call, high word */
236     unsigned short mtime;	/* time of call milliseconds */
237     uindex nargs;		/* number of arguments */
238     svalue val[4];		/* function name, 3 direct arguments */
239 } scallout;
240 
241 static char sco_layout[] = "issu[ccui][ccui][ccui][ccui]";
242 
243 typedef struct {
244     Uint time;			/* time of call */
245     unsigned short mtime;	/* time of call milliseconds */
246     uindex nargs;		/* number of arguments */
247     svalue val[4];		/* function name, 3 direct arguments */
248 } tscallout;
249 
250 static char tco_layout[] = "isu[ccui][ccui][ccui][ccui]";
251 
252 typedef struct {
253     Uint time;			/* time of call */
254     unsigned short mtime;	/* time of call milliseconds */
255     uindex nargs;		/* number of arguments */
256     osvalue val[4];		/* function name, 3 direct arguments */
257 } calloutso;
258 
259 static char cso_layout[] = "isu[cui][cui][cui][cui]";
260 
261 typedef struct {
262     Uint time;			/* time of call */
263     uindex nargs;		/* number of arguments */
264     osvalue val[4];		/* function name, 3 direct arguments */
265 } calloutos;
266 
267 static char cos_layout[] = "iu[cui][cui][cui][cui]";
268 
269 typedef struct {
270     Uint time;			/* time of call */
271     uindex nargs;		/* number of arguments */
272     oosvalue val[4];		/* function name, 3 direct arguments */
273 } socallout;
274 
275 static char soc_layout[] = "iu[sui][sui][sui][sui]";
276 
277 typedef struct {
278     Uint time;			/* time of call */
279     unsigned short nargs;	/* number of arguments */
280     oosvalue val[4];		/* function name, 3 direct arguments */
281 } oscallout;
282 
283 static char osc_layout[] = "is[sui][sui][sui][sui]";
284 
285 typedef struct {
286     Uint narr;				/* # of arrays */
287     Uint nstr;				/* # of strings */
288     Uint arrsize;			/* # of array elements */
289     Uint strsize;			/* total string size */
290     sarray *sarrays;			/* save arrays */
291     svalue *selts;			/* save array elements */
292     sstring *sstrings;			/* save strings */
293     char *stext;			/* save string elements */
294     bool counting;			/* currently counting */
295     array alist;			/* linked list sentinel */
296 } savedata;
297 
298 static control *chead, *ctail;		/* list of control blocks */
299 static dataspace *dhead, *dtail;	/* list of dataspace blocks */
300 static dataspace *gcdata;		/* next dataspace to garbage collect */
301 static sector nctrl;			/* # control blocks */
302 static sector ndata;			/* # dataspace blocks */
303 static bool conv_ctrl1, conv_ctrl2;	/* convert control blocks? */
304 static bool conv_data;			/* convert dataspaces? */
305 static bool conv_co1, conv_co2;		/* convert callouts? */
306 static bool conv_type;			/* convert types? */
307 static bool conv_inherit;		/* convert inherits? */
308 static bool conv_time;			/* convert time? */
309 static bool conv_vm;			/* convert VM? */
310 static bool converted;			/* conversion complete? */
311 
312 
313 /*
314  * NAME:	data->init()
315  * DESCRIPTION:	initialize swapped data handling
316  */
d_init()317 void d_init()
318 {
319     chead = ctail = (control *) NULL;
320     dhead = dtail = (dataspace *) NULL;
321     gcdata = (dataspace *) NULL;
322     nctrl = ndata = 0;
323     conv_ctrl1 = conv_ctrl2 = conv_data = conv_co1 = conv_co2 = conv_type =
324 		 conv_time = conv_vm = FALSE;
325     converted = FALSE;
326 }
327 
328 /*
329  * NAME:	data->init_conv()
330  * DESCRIPTION:	prepare for conversions
331  */
d_init_conv(int ctrl1,int ctrl2,int data,int callout1,int callout2,int type,int inherit,int time,int vm)332 void d_init_conv(int ctrl1, int ctrl2, int data, int callout1, int callout2, int type, int inherit, int time, int vm)
333 {
334     conv_ctrl1 = ctrl1;
335     conv_ctrl2 = ctrl2;
336     conv_data = data;
337     conv_co1 = callout1;
338     conv_co2 = callout2;
339     conv_type = type;
340     conv_inherit = inherit;
341     conv_time = time;
342     conv_vm = vm;
343 }
344 
345 /*
346  * NAME:	data->new_control()
347  * DESCRIPTION:	create a new control block
348  */
d_new_control()349 control *d_new_control()
350 {
351     control *ctrl;
352 
353     ctrl = ALLOC(control, 1);
354     if (chead != (control *) NULL) {
355 	/* insert at beginning of list */
356 	chead->prev = ctrl;
357 	ctrl->prev = (control *) NULL;
358 	ctrl->next = chead;
359 	chead = ctrl;
360     } else {
361 	/* list was empty */
362 	ctrl->prev = ctrl->next = (control *) NULL;
363 	chead = ctail = ctrl;
364     }
365     ctrl->ndata = 0;
366     nctrl++;
367 
368     ctrl->flags = 0;
369 
370     ctrl->nsectors = 0;		/* nothing on swap device yet */
371     ctrl->sectors = (sector *) NULL;
372     ctrl->oindex = UINDEX_MAX;
373     ctrl->ninherits = 0;
374     ctrl->inherits = (dinherit *) NULL;
375     ctrl->imapsz = 0;
376     ctrl->imap = (char *) NULL;
377     ctrl->progindex = 0;
378     ctrl->compiled = 0;
379     ctrl->progsize = 0;
380     ctrl->prog = (char *) NULL;
381     ctrl->nstrings = 0;
382     ctrl->strings = (string **) NULL;
383     ctrl->sstrings = (dstrconst *) NULL;
384     ctrl->stext = (char *) NULL;
385     ctrl->nfuncdefs = 0;
386     ctrl->funcdefs = (dfuncdef *) NULL;
387     ctrl->nvardefs = 0;
388     ctrl->nclassvars = 0;
389     ctrl->vardefs = (dvardef *) NULL;
390     ctrl->cvstrings = (string **) NULL;
391     ctrl->classvars = (char *) NULL;
392     ctrl->nfuncalls = 0;
393     ctrl->funcalls = (char *) NULL;
394     ctrl->nsymbols = 0;
395     ctrl->symbols = (dsymbol *) NULL;
396     ctrl->nvariables = 0;
397     ctrl->vtypes = (char *) NULL;
398     ctrl->vmapsize = 0;
399     ctrl->vmap = (unsigned short *) NULL;
400 
401     return ctrl;
402 }
403 
404 /*
405  * NAME:	data->alloc_dataspace()
406  * DESCRIPTION:	allocate a new dataspace block
407  */
d_alloc_dataspace(object * obj)408 static dataspace *d_alloc_dataspace(object *obj)
409 {
410     dataspace *data;
411 
412     data = ALLOC(dataspace, 1);
413     if (dhead != (dataspace *) NULL) {
414 	/* insert at beginning of list */
415 	dhead->prev = data;
416 	data->prev = (dataspace *) NULL;
417 	data->next = dhead;
418 	dhead = data;
419 	data->gcprev = gcdata->gcprev;
420 	data->gcnext = gcdata;
421 	data->gcprev->gcnext = data;
422 	gcdata->gcprev = data;
423     } else {
424 	/* list was empty */
425 	data->prev = data->next = (dataspace *) NULL;
426 	dhead = dtail = data;
427 	gcdata = data;
428 	data->gcprev = data->gcnext = data;
429     }
430     ndata++;
431 
432     data->iprev = (dataspace *) NULL;
433     data->inext = (dataspace *) NULL;
434     data->flags = 0;
435 
436     data->oindex = obj->index;
437     data->ctrl = (control *) NULL;
438 
439     /* sectors */
440     data->nsectors = 0;
441     data->sectors = (sector *) NULL;
442 
443     /* variables */
444     data->nvariables = 0;
445     data->variables = (value *) NULL;
446     data->svariables = (svalue *) NULL;
447 
448     /* arrays */
449     data->narrays = 0;
450     data->eltsize = 0;
451     data->sarrays = (sarray *) NULL;
452     data->selts = (svalue *) NULL;
453     data->alist.prev = data->alist.next = &data->alist;
454 
455     /* strings */
456     data->nstrings = 0;
457     data->strsize = 0;
458     data->sstrings = (sstring *) NULL;
459     data->stext = (char *) NULL;
460 
461     /* callouts */
462     data->ncallouts = 0;
463     data->fcallouts = 0;
464     data->callouts = (dcallout *) NULL;
465     data->scallouts = (scallout *) NULL;
466 
467     /* value plane */
468     data->base.level = 0;
469     data->base.flags = 0;
470     data->base.schange = 0;
471     data->base.achange = 0;
472     data->base.imports = 0;
473     data->base.alocal.arr = (array *) NULL;
474     data->base.alocal.plane = &data->base;
475     data->base.alocal.data = data;
476     data->base.alocal.state = AR_CHANGED;
477     data->base.arrays = (arrref *) NULL;
478     data->base.strings = (strref *) NULL;
479     data->base.coptab = (struct _coptable_ *) NULL;
480     data->base.prev = (dataplane *) NULL;
481     data->base.plist = (dataplane *) NULL;
482     data->plane = &data->base;
483 
484     /* parse_string data */
485     data->parser = (struct _parser_ *) NULL;
486 
487     return data;
488 }
489 
490 /*
491  * NAME:	data->new_dataspace()
492  * DESCRIPTION:	create a new dataspace block
493  */
d_new_dataspace(object * obj)494 dataspace *d_new_dataspace(object *obj)
495 {
496     dataspace *data;
497 
498     data = d_alloc_dataspace(obj);
499     data->base.flags = MOD_VARIABLE;
500     data->ctrl = o_control(obj);
501     data->ctrl->ndata++;
502     data->nvariables = data->ctrl->nvariables + 1;
503 
504     return data;
505 }
506 
507 /*
508  * NAME:	load_control()
509  * DESCRIPTION:	load a control block
510  */
load_control(object * obj,void (* readv)(char *,sector *,Uint,Uint))511 static control *load_control(object *obj, void (*readv) (char*, sector*, Uint, Uint))
512 {
513     control *ctrl;
514     scontrol header;
515     Uint size;
516 
517     ctrl = d_new_control();
518     ctrl->oindex = obj->index;
519 
520     /* header */
521     (*readv)((char *) &header, &obj->cfirst, (Uint) sizeof(scontrol), (Uint) 0);
522     ctrl->nsectors = header.nsectors;
523     ctrl->sectors = ALLOC(sector, header.nsectors);
524     ctrl->sectors[0] = obj->cfirst;
525     size = header.nsectors * (Uint) sizeof(sector);
526     if (header.nsectors > 1) {
527 	(*readv)((char *) ctrl->sectors, ctrl->sectors, size,
528 		 (Uint) sizeof(scontrol));
529     }
530     size += sizeof(scontrol);
531 
532     ctrl->flags = header.flags;
533 
534     /* inherits */
535     ctrl->ninherits = header.ninherits;
536 
537     if (header.vmapsize != 0) {
538 	/*
539 	 * Control block for outdated issue; only vmap can be loaded.
540 	 * The load offsets will be invalid (and unused).
541 	 */
542 	ctrl->vmapsize = header.vmapsize;
543 	ctrl->vmap = ALLOC(unsigned short, header.vmapsize);
544 	(*readv)((char *) ctrl->vmap, ctrl->sectors,
545 		 header.vmapsize * (Uint) sizeof(unsigned short), size);
546     } else {
547 	int n;
548 	dinherit *inherits;
549 	sinherit *sinherits;
550 
551 	/* load inherits */
552 	n = header.ninherits; /* at least one */
553 	ctrl->inherits = inherits = ALLOC(dinherit, n);
554 	sinherits = ALLOCA(sinherit, n);
555 	(*readv)((char *) sinherits, ctrl->sectors, n * (Uint) sizeof(sinherit),
556 		 size);
557 	size += n * sizeof(sinherit);
558 	do {
559 	    inherits->oindex = sinherits->oindex;
560 	    inherits->progoffset = sinherits->progoffset;
561 	    inherits->funcoffset = sinherits->funcoffset;
562 	    inherits->varoffset = sinherits->varoffset;
563 	    (inherits++)->priv = (sinherits++)->flags;
564 	} while (--n > 0);
565 	AFREE(sinherits - header.ninherits);
566 
567 	/* load iindices */
568 	ctrl->imapsz = header.imapsz;
569 	ctrl->imap = ALLOC(char, header.imapsz);
570 	(*readv)(ctrl->imap, ctrl->sectors, ctrl->imapsz, size);
571 	size += ctrl->imapsz;
572 
573 	if ((header.flags & CTRL_CONVERTED) && header.ninherits > 1) {
574 	    ctrl->progindex = 1;
575 	} else {
576 	    ctrl->progindex = header.ninherits - 1;
577 	}
578     }
579 
580     /* compile time */
581     ctrl->compiled = header.compiled;
582 
583     /* program */
584     ctrl->progoffset = size;
585     ctrl->progsize = header.progsize;
586     size += header.progsize;
587 
588     /* string constants */
589     ctrl->stroffset = size;
590     ctrl->nstrings = header.nstrings;
591     ctrl->strsize = header.strsize;
592     size += header.nstrings * (Uint) sizeof(dstrconst) + header.strsize;
593 
594     /* function definitions */
595     ctrl->funcdoffset = size;
596     ctrl->nfuncdefs = UCHAR(header.nfuncdefs);
597     size += UCHAR(header.nfuncdefs) * (Uint) sizeof(dfuncdef);
598 
599     /* variable definitions */
600     ctrl->vardoffset = size;
601     ctrl->nvardefs = UCHAR(header.nvardefs);
602     ctrl->nclassvars = UCHAR(header.nclassvars);
603     size += UCHAR(header.nvardefs) * (Uint) sizeof(dvardef) +
604 	    UCHAR(header.nclassvars) * (Uint) 3;
605 
606     /* function call table */
607     ctrl->funccoffset = size;
608     ctrl->nfuncalls = header.nfuncalls;
609     size += header.nfuncalls * (Uint) 2;
610 
611     /* symbol table */
612     ctrl->symboffset = size;
613     ctrl->nsymbols = header.nsymbols;
614     size += header.nsymbols * (Uint) sizeof(dsymbol);
615 
616     /* # variables */
617     ctrl->vtypeoffset = size;
618     ctrl->nvariables = header.nvariables;
619 
620     return ctrl;
621 }
622 
623 /*
624  * NAME:	data->load_control()
625  * DESCRIPTION:	load a control block from the swap device
626  */
d_load_control(object * obj)627 control *d_load_control(object *obj)
628 {
629     control *ctrl;
630 
631     if (obj->flags & O_COMPILED) {
632 	ctrl = d_new_control();
633 	ctrl->oindex = obj->index;
634 
635 	/* initialize control block of compiled object */
636 	pc_control(ctrl, obj);
637 	ctrl->flags |= CTRL_COMPILED;
638     } else {
639 	ctrl = load_control(obj, sw_readv);
640     }
641 
642     return ctrl;
643 }
644 
645 /*
646  * NAME:	load_dataspace()
647  * DESCRIPTION:	load the dataspace header block
648  */
load_dataspace(object * obj,void (* readv)(char *,sector *,Uint,Uint))649 static dataspace *load_dataspace(object *obj, void (*readv) (char*, sector*, Uint, Uint))
650 {
651     sdataspace header;
652     dataspace *data;
653     Uint size;
654 
655     data = d_alloc_dataspace(obj);
656     data->ctrl = o_control(obj);
657     data->ctrl->ndata++;
658 
659     /* header */
660     (*readv)((char *) &header, &obj->dfirst, (Uint) sizeof(sdataspace),
661 	     (Uint) 0);
662     data->nsectors = header.nsectors;
663     data->sectors = ALLOC(sector, header.nsectors);
664     data->sectors[0] = obj->dfirst;
665     size = header.nsectors * (Uint) sizeof(sector);
666     if (header.nsectors > 1) {
667 	(*readv)((char *) data->sectors, data->sectors, size,
668 		 (Uint) sizeof(sdataspace));
669     }
670     size += sizeof(sdataspace);
671 
672     data->flags = header.flags;
673 
674     /* variables */
675     data->varoffset = size;
676     data->nvariables = header.nvariables;
677     size += data->nvariables * (Uint) sizeof(svalue);
678 
679     /* arrays */
680     data->arroffset = size;
681     data->narrays = header.narrays;
682     data->eltsize = header.eltsize;
683     size += header.narrays * (Uint) sizeof(sarray) +
684 	    header.eltsize * sizeof(svalue);
685 
686     /* strings */
687     data->stroffset = size;
688     data->nstrings = header.nstrings;
689     data->strsize = header.strsize;
690     size += header.nstrings * sizeof(sstring) + header.strsize;
691 
692     /* callouts */
693     data->cooffset = size;
694     data->ncallouts = header.ncallouts;
695     data->fcallouts = header.fcallouts;
696 
697     return data;
698 }
699 
700 /*
701  * NAME:	data->load_dataspace()
702  * DESCRIPTION:	load the dataspace header block of an object from swap
703  */
d_load_dataspace(object * obj)704 dataspace *d_load_dataspace(object *obj)
705 {
706     dataspace *data;
707 
708     data = load_dataspace(obj, sw_readv);
709 
710     if (!(obj->flags & O_MASTER) && obj->update != OBJ(obj->u_master)->update &&
711 	obj->count != 0) {
712 	d_upgrade_clone(data);
713     }
714 
715     return data;
716 }
717 
718 /*
719  * NAME:	data->ref_control()
720  * DESCRIPTION:	reference control block
721  */
d_ref_control(control * ctrl)722 void d_ref_control(control *ctrl)
723 {
724     if (ctrl != chead) {
725 	/* move to head of list */
726 	ctrl->prev->next = ctrl->next;
727 	if (ctrl->next != (control *) NULL) {
728 	    ctrl->next->prev = ctrl->prev;
729 	} else {
730 	    ctail = ctrl->prev;
731 	}
732 	ctrl->prev = (control *) NULL;
733 	ctrl->next = chead;
734 	chead->prev = ctrl;
735 	chead = ctrl;
736     }
737 }
738 
739 /*
740  * NAME:	data->ref_dataspace()
741  * DESCRIPTION:	reference data block
742  */
d_ref_dataspace(dataspace * data)743 void d_ref_dataspace(dataspace *data)
744 {
745     if (data != dhead) {
746 	/* move to head of list */
747 	data->prev->next = data->next;
748 	if (data->next != (dataspace *) NULL) {
749 	    data->next->prev = data->prev;
750 	} else {
751 	    dtail = data->prev;
752 	}
753 	data->prev = (dataspace *) NULL;
754 	data->next = dhead;
755 	dhead->prev = data;
756 	dhead = data;
757     }
758 }
759 
760 
761 /*
762  * NAME:	compress()
763  * DESCRIPTION:	compress data
764  */
compress(char * data,char * text,Uint size)765 static Uint compress(char *data, char *text, Uint size)
766 {
767     char htab[16384];
768     unsigned short buf, bufsize, x;
769     char *p, *q;
770     Uint cspace;
771 
772     if (size <= 4 + 1) {
773 	/* can't get smaller than this */
774 	return 0;
775     }
776 
777     /* clear the hash table */
778     memset(htab, '\0', sizeof(htab));
779 
780     buf = bufsize = 0;
781     x = 0;
782     p = text;
783     q = data;
784     *q++ = size >> 24;
785     *q++ = size >> 16;
786     *q++ = size >> 8;
787     *q++ = size;
788     cspace = size - 4;
789 
790     while (size != 0) {
791 	if (htab[x] == *p) {
792 	    buf >>= 1;
793 	    bufsize += 1;
794 	} else {
795 	    htab[x] = *p;
796 	    buf = (buf >> 9) + 0x0080 + (UCHAR(*p) << 8);
797 	    bufsize += 9;
798 	}
799 	x = ((x << 3) & 0x3fff) ^ UCHAR(strhashtab[UCHAR(*p++)]);
800 
801 	if (bufsize >= 8) {
802 	    if (bufsize == 16) {
803 		if ((Int) (cspace-=2) <= 0) {
804 		    return 0;	/* out of space */
805 		}
806 		*q++ = buf;
807 		*q++ = buf >> 8;
808 		bufsize = 0;
809 	    } else {
810 		if (--cspace == 0) {
811 		    return 0;	/* out of space */
812 		}
813 		*q++ = buf >> (16 - bufsize);
814 		bufsize -= 8;
815 	    }
816 	}
817 
818 	--size;
819     }
820     if (bufsize != 0) {
821 	if (--cspace == 0) {
822 	    return 0;	/* compression did not reduce size */
823 	}
824 	/* add last incomplete byte */
825 	*q++ = (buf >> (16 - bufsize)) + (0xff << bufsize);
826     }
827 
828     return (intptr_t) q - (intptr_t) data;
829 }
830 
831 /*
832  * NAME:	decompress()
833  * DESCRIPTION:	read and decompress data from the swap file
834  */
decompress(sector * sectors,void (* readv)(char *,sector *,Uint,Uint),Uint size,Uint offset,Uint * dsize)835 static char *decompress(sector *sectors, void (*readv) (char*, sector*, Uint, Uint), Uint size, Uint offset, Uint *dsize)
836 {
837     char buffer[8192], htab[16384];
838     unsigned short buf, bufsize, x;
839     Uint n;
840     char *p, *q;
841 
842     buf = bufsize = 0;
843     x = 0;
844 
845     /* clear the hash table */
846     memset(htab, '\0', sizeof(htab));
847 
848     n = sizeof(buffer);
849     if (n > size) {
850 	n = size;
851     }
852     (*readv)(p = buffer, sectors, n, offset);
853     size -= n;
854     offset += n;
855     *dsize = (UCHAR(p[0]) << 24) | (UCHAR(p[1]) << 16) | (UCHAR(p[2]) << 8) |
856 	     UCHAR(p[3]);
857     q = ALLOC(char, *dsize);
858     p += 4;
859     n -= 4;
860 
861     for (;;) {
862 	for (;;) {
863 	    if (bufsize == 0) {
864 		if (n == 0) {
865 		    break;
866 		}
867 		--n;
868 		buf = UCHAR(*p++);
869 		bufsize = 8;
870 	    }
871 	    if (buf & 1) {
872 		if (n == 0) {
873 		    break;
874 		}
875 		--n;
876 		buf += UCHAR(*p++) << bufsize;
877 
878 		*q = htab[x] = buf >> 1;
879 		buf >>= 9;
880 	    } else {
881 		*q = htab[x];
882 		buf >>= 1;
883 	    }
884 	    --bufsize;
885 
886 	    x = ((x << 3) & 0x3fff) ^ UCHAR(strhashtab[UCHAR(*q++)]);
887 	}
888 
889 	if (size == 0) {
890 	    return q - *dsize;
891 	}
892 	n = sizeof(buffer);
893 	if (n > size) {
894 	    n = size;
895 	}
896 	(*readv)(p = buffer, sectors, n, offset);
897 	size -= n;
898 	offset += n;
899     }
900 }
901 
902 
903 /*
904  * NAME:	get_prog()
905  * DESCRIPTION:	get the program
906  */
get_prog(control * ctrl,void (* readv)(char *,sector *,Uint,Uint))907 static void get_prog(control *ctrl, void (*readv) (char*, sector*, Uint, Uint))
908 {
909     if (ctrl->progsize != 0) {
910 	if (ctrl->flags & CTRL_PROGCMP) {
911 	    ctrl->prog = decompress(ctrl->sectors, readv, ctrl->progsize,
912 				    ctrl->progoffset, &ctrl->progsize);
913 	} else {
914 	    ctrl->prog = ALLOC(char, ctrl->progsize);
915 	    (*readv)(ctrl->prog, ctrl->sectors, ctrl->progsize,
916 		     ctrl->progoffset);
917 	}
918     }
919 }
920 
921 /*
922  * NAME:	data->get_prog()
923  * DESCRIPTION:	get the program
924  */
d_get_prog(control * ctrl)925 char *d_get_prog(control *ctrl)
926 {
927     if (ctrl->prog == (char *) NULL && ctrl->progsize != 0) {
928 	get_prog(ctrl, sw_readv);
929     }
930     return ctrl->prog;
931 }
932 
933 /*
934  * NAME:	get_stext()
935  * DESCRIPTION:	load strings text
936  */
get_stext(control * ctrl,void (* readv)(char *,sector *,Uint,Uint))937 static void get_stext(control *ctrl, void (*readv) (char*, sector*, Uint, Uint))
938 {
939     /* load strings text */
940     if (ctrl->flags & CTRL_STRCMP) {
941 	ctrl->stext = decompress(ctrl->sectors, readv,
942 				 ctrl->strsize,
943 				 ctrl->stroffset +
944 				 ctrl->nstrings * sizeof(dstrconst),
945 				 &ctrl->strsize);
946     } else {
947 	ctrl->stext = ALLOC(char, ctrl->strsize);
948 	(*readv)(ctrl->stext, ctrl->sectors, ctrl->strsize,
949 		 ctrl->stroffset + ctrl->nstrings * (Uint) sizeof(dstrconst));
950     }
951 }
952 
953 /*
954  * NAME:	get_strconsts()
955  * DESCRIPTION:	load string constants
956  */
get_strconsts(control * ctrl,void (* readv)(char *,sector *,Uint,Uint))957 static void get_strconsts(control *ctrl, void (*readv) (char*, sector*, Uint, Uint))
958 {
959     if (ctrl->nstrings != 0) {
960 	/* load strings */
961 	ctrl->sstrings = ALLOC(dstrconst, ctrl->nstrings);
962 	(*readv)((char *) ctrl->sstrings, ctrl->sectors,
963 		 ctrl->nstrings * (Uint) sizeof(dstrconst), ctrl->stroffset);
964 	if (ctrl->strsize > 0 && ctrl->stext == (char *) NULL) {
965 	    get_stext(ctrl, readv);	/* load strings text */
966 	}
967     }
968 }
969 
970 /*
971  * NAME:	data->get_strconst()
972  * DESCRIPTION:	get a string constant
973  */
d_get_strconst(control * ctrl,int inherit,Uint idx)974 string *d_get_strconst(control *ctrl, int inherit, Uint idx)
975 {
976     if (UCHAR(inherit) < ctrl->ninherits - 1) {
977 	/* get the proper control block */
978 	ctrl = o_control(OBJR(ctrl->inherits[UCHAR(inherit)].oindex));
979     }
980 
981     if (ctrl->strings == (string **) NULL) {
982 	/* make string pointer block */
983 	ctrl->strings = ALLOC(string*, ctrl->nstrings);
984 	memset(ctrl->strings, '\0', ctrl->nstrings * sizeof(string *));
985 
986 	if (ctrl->sstrings == (dstrconst *) NULL) {
987 	    get_strconsts(ctrl, sw_readv);
988 	}
989     }
990 
991     if (ctrl->strings[idx] == (string *) NULL) {
992 	string *str;
993 
994 	str = str_alloc(ctrl->stext + ctrl->sstrings[idx].index,
995 			(long) ctrl->sstrings[idx].len);
996 	str_ref(ctrl->strings[idx] = str);
997     }
998 
999     return ctrl->strings[idx];
1000 }
1001 
1002 /*
1003  * NAME:	get_funcdefs()
1004  * DESCRIPTION:	load function definitions
1005  */
get_funcdefs(control * ctrl,void (* readv)(char *,sector *,Uint,Uint))1006 static void get_funcdefs(control *ctrl, void (*readv) (char*, sector*, Uint, Uint))
1007 {
1008     if (ctrl->nfuncdefs != 0) {
1009 	ctrl->funcdefs = ALLOC(dfuncdef, ctrl->nfuncdefs);
1010 	(*readv)((char *) ctrl->funcdefs, ctrl->sectors,
1011 		 ctrl->nfuncdefs * (Uint) sizeof(dfuncdef), ctrl->funcdoffset);
1012     }
1013 }
1014 
1015 /*
1016  * NAME:	data->get_funcdefs()
1017  * DESCRIPTION:	get function definitions
1018  */
d_get_funcdefs(control * ctrl)1019 dfuncdef *d_get_funcdefs(control *ctrl)
1020 {
1021     if (ctrl->funcdefs == (dfuncdef *) NULL && ctrl->nfuncdefs != 0) {
1022 	get_funcdefs(ctrl, sw_readv);
1023     }
1024     return ctrl->funcdefs;
1025 }
1026 
1027 /*
1028  * NAME:	get_vardefs()
1029  * DESCRIPTION:	load variable definitions
1030  */
get_vardefs(control * ctrl,void (* readv)(char *,sector *,Uint,Uint))1031 static void get_vardefs(control *ctrl, void (*readv) (char*, sector*, Uint, Uint))
1032 {
1033     if (ctrl->nvardefs != 0) {
1034 	ctrl->vardefs = ALLOC(dvardef, ctrl->nvardefs);
1035 	(*readv)((char *) ctrl->vardefs, ctrl->sectors,
1036 		 ctrl->nvardefs * (Uint) sizeof(dvardef), ctrl->vardoffset);
1037 	if (ctrl->nclassvars != 0) {
1038 	    ctrl->classvars = ALLOC(char, ctrl->nclassvars * 3);
1039 	    (*readv)(ctrl->classvars, ctrl->sectors, ctrl->nclassvars * 3,
1040 		     ctrl->vardoffset + ctrl->nvardefs * sizeof(dvardef));
1041 	}
1042     }
1043 }
1044 
1045 /*
1046  * NAME:	data->get_vardefs()
1047  * DESCRIPTION:	get variable definitions
1048  */
d_get_vardefs(control * ctrl)1049 dvardef *d_get_vardefs(control *ctrl)
1050 {
1051     if (ctrl->vardefs == (dvardef *) NULL && ctrl->nvardefs != 0) {
1052 	get_vardefs(ctrl, sw_readv);
1053     }
1054     if (ctrl->cvstrings == (string **) NULL && ctrl->nclassvars != 0) {
1055 	char *p;
1056 	dvardef *vars;
1057 	string **strs;
1058 	unsigned short n, inherit, u;
1059 
1060 	ctrl->cvstrings = strs = ALLOC(string*, ctrl->nvardefs);
1061 	memset(strs, '\0', ctrl->nvardefs * sizeof(string*));
1062 	p = ctrl->classvars;
1063 	for (n = ctrl->nclassvars, vars = ctrl->vardefs; n != 0; vars++) {
1064 	    if ((vars->type & T_TYPE) == T_CLASS) {
1065 		inherit = FETCH1U(p);
1066 		str_ref(*strs = d_get_strconst(ctrl, inherit, FETCH2U(p, u)));
1067 		--n;
1068 	    }
1069 	    strs++;
1070 	}
1071     }
1072     return ctrl->vardefs;
1073 }
1074 
1075 /*
1076  * NAME:	get_funcalls()
1077  * DESCRIPTION:	get function call table
1078  */
get_funcalls(control * ctrl,void (* readv)(char *,sector *,Uint,Uint))1079 static void get_funcalls(control *ctrl, void (*readv) (char*, sector*, Uint, Uint))
1080 {
1081     if (ctrl->nfuncalls != 0) {
1082 	ctrl->funcalls = ALLOC(char, 2L * ctrl->nfuncalls);
1083 	(*readv)((char *) ctrl->funcalls, ctrl->sectors,
1084 		 ctrl->nfuncalls * (Uint) 2, ctrl->funccoffset);
1085     }
1086 }
1087 
1088 /*
1089  * NAME:	data->get_funcalls()
1090  * DESCRIPTION:	get function call table
1091  */
d_get_funcalls(control * ctrl)1092 char *d_get_funcalls(control *ctrl)
1093 {
1094     if (ctrl->funcalls == (char *) NULL && ctrl->nfuncalls != 0) {
1095 	get_funcalls(ctrl, sw_readv);
1096     }
1097     return ctrl->funcalls;
1098 }
1099 
1100 /*
1101  * NAME:	get_symbols()
1102  * DESCRIPTION:	get symbol table
1103  */
get_symbols(control * ctrl,void (* readv)(char *,sector *,Uint,Uint))1104 static void get_symbols(control *ctrl, void (*readv) (char*, sector*, Uint, Uint))
1105 {
1106     if (ctrl->nsymbols > 0) {
1107 	ctrl->symbols = ALLOC(dsymbol, ctrl->nsymbols);
1108 	(*readv)((char *) ctrl->symbols, ctrl->sectors,
1109 		 ctrl->nsymbols * (Uint) sizeof(dsymbol), ctrl->symboffset);
1110     }
1111 }
1112 
1113 /*
1114  * NAME:	data->get_symbols()
1115  * DESCRIPTION:	get symbol table
1116  */
d_get_symbols(control * ctrl)1117 dsymbol *d_get_symbols(control *ctrl)
1118 {
1119     if (ctrl->symbols == (dsymbol *) NULL && ctrl->nsymbols > 0) {
1120 	get_symbols(ctrl, sw_readv);
1121     }
1122     return ctrl->symbols;
1123 }
1124 
1125 /*
1126  * NAME:	get_vtypes()
1127  * DESCRIPTION:	get variable types
1128  */
get_vtypes(control * ctrl,void (* readv)(char *,sector *,Uint,Uint))1129 static void get_vtypes(control *ctrl, void (*readv) (char*, sector*, Uint, Uint))
1130 {
1131     if (ctrl->nvariables > ctrl->nvardefs) {
1132 	ctrl->vtypes = ALLOC(char, ctrl->nvariables - ctrl->nvardefs);
1133 	(*readv)(ctrl->vtypes, ctrl->sectors, ctrl->nvariables - ctrl->nvardefs,
1134 		 ctrl->vtypeoffset);
1135     }
1136 }
1137 
1138 /*
1139  * NAME:	data->get_vtypes()
1140  * DESCRIPTION:	get variable types
1141  */
d_get_vtypes(control * ctrl)1142 static char *d_get_vtypes(control *ctrl)
1143 {
1144     if (ctrl->vtypes == (char *) NULL && ctrl->nvariables > ctrl->nvardefs) {
1145 	get_vtypes(ctrl, sw_readv);
1146     }
1147     return ctrl->vtypes;
1148 }
1149 
1150 /*
1151  * NAME:	data->get_progsize()
1152  * DESCRIPTION:	get the size of a control block
1153  */
d_get_progsize(control * ctrl)1154 Uint d_get_progsize(control *ctrl)
1155 {
1156     if (ctrl->progsize != 0 && ctrl->prog == (char *) NULL &&
1157 	(ctrl->flags & CTRL_PROGCMP)) {
1158 	get_prog(ctrl, sw_readv);	/* decompress program */
1159     }
1160     if (ctrl->strsize != 0 && ctrl->stext == (char *) NULL &&
1161 	(ctrl->flags & CTRL_STRCMP)) {
1162 	get_stext(ctrl, sw_readv);	/* decompress strings */
1163     }
1164 
1165     return ctrl->ninherits * sizeof(dinherit) +
1166 	   ctrl->imapsz +
1167 	   ctrl->progsize +
1168 	   ctrl->nstrings * (Uint) sizeof(dstrconst) +
1169 	   ctrl->strsize +
1170 	   ctrl->nfuncdefs * sizeof(dfuncdef) +
1171 	   ctrl->nvardefs * sizeof(dvardef) +
1172 	   ctrl->nclassvars * (Uint) 3 +
1173 	   ctrl->nfuncalls * (Uint) 2 +
1174 	   ctrl->nsymbols * (Uint) sizeof(dsymbol) +
1175 	   ctrl->nvariables - ctrl->nvardefs;
1176 }
1177 
1178 
1179 /*
1180  * NAME:	get_strings()
1181  * DESCRIPTION:	load strings for dataspace
1182  */
get_strings(dataspace * data,void (* readv)(char *,sector *,Uint,Uint))1183 static void get_strings(dataspace *data, void (*readv) (char*, sector*, Uint, Uint))
1184 {
1185     if (data->nstrings != 0) {
1186 	/* load strings */
1187 	data->sstrings = ALLOC(sstring, data->nstrings);
1188 	(*readv)((char *) data->sstrings, data->sectors,
1189 		 data->nstrings * sizeof(sstring), data->stroffset);
1190 	if (data->strsize > 0) {
1191 	    /* load strings text */
1192 	    if (data->flags & DATA_STRCMP) {
1193 		data->stext = decompress(data->sectors, readv, data->strsize,
1194 					 data->stroffset +
1195 					       data->nstrings * sizeof(sstring),
1196 					 &data->strsize);
1197 	    } else {
1198 		data->stext = ALLOC(char, data->strsize);
1199 		(*readv)(data->stext, data->sectors, data->strsize,
1200 			 data->stroffset + data->nstrings * sizeof(sstring));
1201 	    }
1202 	}
1203     }
1204 }
1205 
1206 /*
1207  * NAME:	data->get_string()
1208  * DESCRIPTION:	get a string from the dataspace
1209  */
d_get_string(dataspace * data,Uint idx)1210 static string *d_get_string(dataspace *data, Uint idx)
1211 {
1212     if (data->plane->strings == (strref *) NULL ||
1213 	data->plane->strings[idx].str == (string *) NULL) {
1214 	string *str;
1215 	strref *s;
1216 	dataplane *p;
1217 	Uint i;
1218 
1219 	if (data->sstrings == (sstring *) NULL) {
1220 	    get_strings(data, sw_readv);
1221 	}
1222 
1223 	str = str_alloc(data->stext + data->sstrings[idx].index,
1224 			(long) data->sstrings[idx].len);
1225 	str->ref = 0;
1226 	p = data->plane;
1227 
1228 	do {
1229 	    if (p->strings == (strref *) NULL) {
1230 		/* initialize string pointers */
1231 		s = p->strings = ALLOC(strref, data->nstrings);
1232 		for (i = data->nstrings; i > 0; --i) {
1233 		    (s++)->str = (string *) NULL;
1234 		}
1235 	    }
1236 	    s = &p->strings[idx];
1237 	    str_ref(s->str = str);
1238 	    s->data = data;
1239 	    s->ref = data->sstrings[idx].ref;
1240 	    p = p->prev;
1241 	} while (p != (dataplane *) NULL);
1242 
1243 	str->primary = &data->plane->strings[idx];
1244 	return str;
1245     }
1246     return data->plane->strings[idx].str;
1247 }
1248 
1249 /*
1250  * NAME:	get_arrays()
1251  * DESCRIPTION:	load arrays for dataspace
1252  */
get_arrays(dataspace * data,void (* readv)(char *,sector *,Uint,Uint))1253 static void get_arrays(dataspace *data, void (*readv) (char*, sector*, Uint, Uint))
1254 {
1255     if (data->narrays != 0) {
1256 	/* load arrays */
1257 	data->sarrays = ALLOC(sarray, data->narrays);
1258 	(*readv)((char *) data->sarrays, data->sectors,
1259 		 data->narrays * (Uint) sizeof(sarray), data->arroffset);
1260     }
1261 }
1262 
1263 /*
1264  * NAME:	data->get_array()
1265  * DESCRIPTION:	get an array from the dataspace
1266  */
d_get_array(dataspace * data,Uint idx)1267 static array *d_get_array(dataspace *data, Uint idx)
1268 {
1269     if (data->plane->arrays == (arrref *) NULL ||
1270 	data->plane->arrays[idx].arr == (array *) NULL) {
1271 	array *arr;
1272 	arrref *a;
1273 	dataplane *p;
1274 	Uint i;
1275 
1276 	if (data->sarrays == (sarray *) NULL) {
1277 	    /* load arrays */
1278 	    get_arrays(data, sw_readv);
1279 	}
1280 
1281 	arr = arr_alloc(data->sarrays[idx].size);
1282 	arr->ref = 0;
1283 	arr->tag = data->sarrays[idx].tag;
1284 	p = data->plane;
1285 
1286 	do {
1287 	    if (p->arrays == (arrref *) NULL) {
1288 		/* create array pointers */
1289 		a = p->arrays = ALLOC(arrref, data->narrays);
1290 		for (i = data->narrays; i > 0; --i) {
1291 		    (a++)->arr = (array *) NULL;
1292 		}
1293 	    }
1294 	    a = &p->arrays[idx];
1295 	    arr_ref(a->arr = arr);
1296 	    a->plane = &data->base;
1297 	    a->data = data;
1298 	    a->state = AR_UNCHANGED;
1299 	    a->ref = data->sarrays[idx].ref;
1300 	    p = p->prev;
1301 	} while (p != (dataplane *) NULL);
1302 
1303 	arr->primary = &data->plane->arrays[idx];
1304 	arr->prev = &data->alist;
1305 	arr->next = data->alist.next;
1306 	arr->next->prev = arr;
1307 	data->alist.next = arr;
1308 	return arr;
1309     }
1310     return data->plane->arrays[idx].arr;
1311 }
1312 
1313 /*
1314  * NAME:	data->get_values()
1315  * DESCRIPTION:	get values from the dataspace
1316  */
d_get_values(dataspace * data,svalue * sv,value * v,int n)1317 static void d_get_values(dataspace *data, svalue *sv, value *v, int n)
1318 {
1319     while (n > 0) {
1320 	v->modified = FALSE;
1321 	switch (v->type = sv->type) {
1322 	case T_NIL:
1323 	    v->u.number = 0;
1324 	    break;
1325 
1326 	case T_INT:
1327 	    v->u.number = sv->u.number;
1328 	    break;
1329 
1330 	case T_STRING:
1331 	    str_ref(v->u.string = d_get_string(data, sv->u.string));
1332 	    break;
1333 
1334 	case T_FLOAT:
1335 	case T_OBJECT:
1336 	    v->oindex = sv->oindex;
1337 	    v->u.objcnt = sv->u.objcnt;
1338 	    break;
1339 
1340 	case T_ARRAY:
1341 	case T_MAPPING:
1342 	case T_LWOBJECT:
1343 	    arr_ref(v->u.array = d_get_array(data, sv->u.array));
1344 	    break;
1345 	}
1346 	sv++;
1347 	v++;
1348 	--n;
1349     }
1350 }
1351 
1352 /*
1353  * NAME:	data->new_variables()
1354  * DESCRIPTION:	initialize variables in a dataspace block
1355  */
d_new_variables(control * ctrl,value * val)1356 void d_new_variables(control *ctrl, value *val)
1357 {
1358     unsigned short n;
1359     char *type;
1360     dvardef *var;
1361 
1362     memset(val, '\0', ctrl->nvariables * sizeof(value));
1363     for (n = ctrl->nvariables - ctrl->nvardefs, type = d_get_vtypes(ctrl);
1364 	 n != 0; --n, type++) {
1365 	val->type = *type;
1366 	val++;
1367     }
1368     for (n = ctrl->nvardefs, var = d_get_vardefs(ctrl); n != 0; --n, var++) {
1369 	if (T_ARITHMETIC(var->type)) {
1370 	    val->type = var->type;
1371 	} else {
1372 	    val->type = nil_type;
1373 	}
1374 	val++;
1375     }
1376 }
1377 
1378 /*
1379  * NAME:	get_variables()
1380  * DESCRIPTION:	load variables
1381  */
get_variables(dataspace * data,void (* readv)(char *,sector *,Uint,Uint))1382 static void get_variables(dataspace *data, void (*readv) (char*, sector*, Uint, Uint))
1383 {
1384     data->svariables = ALLOC(svalue, data->nvariables);
1385     (*readv)((char *) data->svariables, data->sectors,
1386 	     data->nvariables * (Uint) sizeof(svalue), data->varoffset);
1387 }
1388 
1389 /*
1390  * NAME:	data->get_variable()
1391  * DESCRIPTION:	get a variable from the dataspace
1392  */
d_get_variable(dataspace * data,unsigned int idx)1393 value *d_get_variable(dataspace *data, unsigned int idx)
1394 {
1395     if (data->variables == (value *) NULL) {
1396 	/* create room for variables */
1397 	data->variables = ALLOC(value, data->nvariables);
1398 	if (data->nsectors == 0 && data->svariables == (svalue *) NULL) {
1399 	    /* new datablock */
1400 	    d_new_variables(data->ctrl, data->variables);
1401 	    data->variables[data->nvariables - 1] = nil_value;	/* extra var */
1402 	} else {
1403 	    /*
1404 	     * variables must be loaded from swap
1405 	     */
1406 	    if (data->svariables == (svalue *) NULL) {
1407 		/* load svalues */
1408 		get_variables(data, sw_readv);
1409 	    }
1410 	    d_get_values(data, data->svariables, data->variables,
1411 			 data->nvariables);
1412 	}
1413     }
1414 
1415     return &data->variables[idx];
1416 }
1417 
1418 /*
1419  * NAME:	get_elts()
1420  * DESCRIPTION:	load elements
1421  */
get_elts(dataspace * data,void (* readv)(char *,sector *,Uint,Uint))1422 static void get_elts(dataspace *data, void (*readv) (char*, sector*, Uint, Uint))
1423 {
1424     if (data->eltsize != 0) {
1425 	/* load array elements */
1426 	data->selts = (svalue *) ALLOC(svalue, data->eltsize);
1427 	(*readv)((char *) data->selts, data->sectors,
1428 		 data->eltsize * sizeof(svalue),
1429 		 data->arroffset + data->narrays * sizeof(sarray));
1430     }
1431 }
1432 
1433 /*
1434  * NAME:	data->get_elts()
1435  * DESCRIPTION:	get the elements of an array
1436  */
d_get_elts(array * arr)1437 value *d_get_elts(array *arr)
1438 {
1439     value *v;
1440 
1441     v = arr->elts;
1442     if (v == (value *) NULL && arr->size != 0) {
1443 	dataspace *data;
1444 	Uint idx;
1445 
1446 	data = arr->primary->data;
1447 	if (data->selts == (svalue *) NULL) {
1448 	    get_elts(data, sw_readv);
1449 	}
1450 	v = arr->elts = ALLOC(value, arr->size);
1451 	idx = data->sarrays[arr->primary - data->plane->arrays].index;
1452 	d_get_values(data, &data->selts[idx], v, arr->size);
1453     }
1454 
1455     return v;
1456 }
1457 
1458 /*
1459  * NAME:	get_callouts()
1460  * DESCRIPTION:	load callouts from swap
1461  */
get_callouts(dataspace * data,void (* readv)(char *,sector *,Uint,Uint))1462 static void get_callouts(dataspace *data, void (*readv) (char*, sector*, Uint, Uint))
1463 {
1464     if (data->ncallouts != 0) {
1465 	data->scallouts = ALLOC(scallout, data->ncallouts);
1466 	(*readv)((char *) data->scallouts, data->sectors,
1467 		 data->ncallouts * (Uint) sizeof(scallout), data->cooffset);
1468     }
1469 }
1470 
1471 /*
1472  * NAME:	data->get_callouts()
1473  * DESCRIPTION:	load callouts from swap
1474  */
d_get_callouts(dataspace * data)1475 void d_get_callouts(dataspace *data)
1476 {
1477     scallout *sco;
1478     dcallout *co;
1479     uindex n;
1480 
1481     if (data->scallouts == (scallout *) NULL) {
1482 	get_callouts(data, sw_readv);
1483     }
1484     sco = data->scallouts;
1485     co = data->callouts = ALLOC(dcallout, data->ncallouts);
1486 
1487     for (n = data->ncallouts; n > 0; --n) {
1488 	co->time = sco->time;
1489 	co->mtime = sco->mtime;
1490 	co->nargs = sco->nargs;
1491 	if (sco->val[0].type == T_STRING) {
1492 	    d_get_values(data, sco->val, co->val,
1493 			 (sco->nargs > 3) ? 4 : sco->nargs + 1);
1494 	} else {
1495 	    co->val[0] = nil_value;
1496 	}
1497 	sco++;
1498 	co++;
1499     }
1500 }
1501 
1502 
1503 /*
1504  * NAME:	data->swapalloc()
1505  * DESCRIPTION:	allocate swapspace for something
1506  */
d_swapalloc(Uint size,sector nsectors,sector ** sectors)1507 static sector d_swapalloc(Uint size, sector nsectors, sector **sectors)
1508 {
1509     sector n, *s;
1510 
1511     s = *sectors;
1512     if (nsectors != 0) {
1513 	/* wipe old sectors */
1514 	sw_wipev(s, nsectors);
1515     }
1516 
1517     n = sw_mapsize(size);
1518     if (nsectors > n) {
1519 	/* too many sectors */
1520 	sw_delv(s + n, nsectors - n);
1521     }
1522 
1523     s = *sectors = REALLOC(*sectors, sector, nsectors, n);
1524     if (nsectors < n) {
1525 	/* not enough sectors */
1526 	sw_newv(s + nsectors, n - nsectors);
1527     }
1528 
1529     return n;
1530 }
1531 
1532 /*
1533  * NAME:	data->save_control()
1534  * DESCRIPTION:	save the control block
1535  */
d_save_control(control * ctrl)1536 static void d_save_control(control *ctrl)
1537 {
1538     scontrol header;
1539     char *prog, *stext, *text;
1540     dstrconst *sstrings;
1541     Uint size, i;
1542     sinherit *sinherits;
1543     dinherit *inherits;
1544 
1545     sstrings = NULL;
1546     prog = stext = text = NULL;
1547 
1548     /*
1549      * Save a control block.
1550      */
1551 
1552     /* create header */
1553     header.flags = ctrl->flags & (CTRL_UNDEFINED | CTRL_CONVERTED | CTRL_OLDVM);
1554     header.ninherits = ctrl->ninherits;
1555     header.imapsz = ctrl->imapsz;
1556     header.compiled = ctrl->compiled;
1557     header.comphigh = 0;
1558     header.progsize = ctrl->progsize;
1559     header.nstrings = ctrl->nstrings;
1560     header.strsize = ctrl->strsize;
1561     header.nfuncdefs = ctrl->nfuncdefs;
1562     header.nvardefs = ctrl->nvardefs;
1563     header.nclassvars = ctrl->nclassvars;
1564     header.nfuncalls = ctrl->nfuncalls;
1565     header.nsymbols = ctrl->nsymbols;
1566     header.nvariables = ctrl->nvariables;
1567     header.vmapsize = ctrl->vmapsize;
1568 
1569     /* create sector space */
1570     if (header.vmapsize != 0) {
1571 	size = sizeof(scontrol) +
1572 	       header.vmapsize * (Uint) sizeof(unsigned short);
1573     } else {
1574 	prog = ctrl->prog;
1575 	if (header.progsize >= CMPLIMIT) {
1576 	    prog = ALLOC(char, header.progsize);
1577 	    size = compress(prog, ctrl->prog, header.progsize);
1578 	    if (size != 0) {
1579 		header.flags |= CMP_PRED;
1580 		header.progsize = size;
1581 	    } else {
1582 		FREE(prog);
1583 		prog = ctrl->prog;
1584 	    }
1585 	}
1586 
1587 	sstrings = ctrl->sstrings;
1588 	stext = ctrl->stext;
1589 	if (header.nstrings > 0 && sstrings == (dstrconst *) NULL) {
1590 	    string **strs;
1591 	    Uint strsize;
1592 	    dstrconst *s;
1593 	    char *t;
1594 
1595 	    sstrings = ALLOCA(dstrconst, header.nstrings);
1596 	    if (header.strsize > 0) {
1597 		stext = ALLOCA(char, header.strsize);
1598 	    }
1599 
1600 	    strs = ctrl->strings;
1601 	    strsize = 0;
1602 	    s = sstrings;
1603 	    t = stext;
1604 	    for (i = header.nstrings; i > 0; --i) {
1605 		s->index = strsize;
1606 		strsize += s->len = (*strs)->len;
1607 		memcpy(t, (*strs++)->text, s->len);
1608 		t += (s++)->len;
1609 	    }
1610 	}
1611 
1612 	text = stext;
1613 	if (header.strsize >= CMPLIMIT) {
1614 	    text = ALLOC(char, header.strsize);
1615 	    size = compress(text, stext, header.strsize);
1616 	    if (size != 0) {
1617 		header.flags |= CMP_PRED << 2;
1618 		header.strsize = size;
1619 	    } else {
1620 		FREE(text);
1621 		text = stext;
1622 	    }
1623 	}
1624 
1625 	size = sizeof(scontrol) +
1626 	       header.ninherits * sizeof(sinherit) +
1627 	       header.imapsz +
1628 	       header.progsize +
1629 	       header.nstrings * (Uint) sizeof(dstrconst) +
1630 	       header.strsize +
1631 	       UCHAR(header.nfuncdefs) * sizeof(dfuncdef) +
1632 	       UCHAR(header.nvardefs) * sizeof(dvardef) +
1633 	       UCHAR(header.nclassvars) * (Uint) 3 +
1634 	       header.nfuncalls * (Uint) 2 +
1635 	       header.nsymbols * (Uint) sizeof(dsymbol) +
1636 	       header.nvariables - UCHAR(header.nvardefs);
1637     }
1638     ctrl->nsectors = header.nsectors = d_swapalloc(size, ctrl->nsectors,
1639 						   &ctrl->sectors);
1640     OBJ(ctrl->oindex)->cfirst = ctrl->sectors[0];
1641 
1642     /*
1643      * Copy everything to the swap device.
1644      */
1645 
1646     /* save header */
1647     sw_writev((char *) &header, ctrl->sectors, (Uint) sizeof(scontrol),
1648 	      (Uint) 0);
1649     size = sizeof(scontrol);
1650 
1651     /* save sector map */
1652     sw_writev((char *) ctrl->sectors, ctrl->sectors,
1653 	      header.nsectors * (Uint) sizeof(sector), size);
1654     size += header.nsectors * (Uint) sizeof(sector);
1655 
1656     if (header.vmapsize != 0) {
1657 	/*
1658 	 * save only vmap
1659 	 */
1660 	sw_writev((char *) ctrl->vmap, ctrl->sectors,
1661 		  header.vmapsize * (Uint) sizeof(unsigned short), size);
1662     } else {
1663 	/* save inherits */
1664 	inherits = ctrl->inherits;
1665 	sinherits = ALLOCA(sinherit, i = header.ninherits);
1666 	do {
1667 	    sinherits->oindex = inherits->oindex;
1668 	    sinherits->progoffset = inherits->progoffset;
1669 	    sinherits->funcoffset = inherits->funcoffset;
1670 	    sinherits->varoffset = inherits->varoffset;
1671 	    sinherits->flags = inherits->priv;
1672 	    inherits++;
1673 	    sinherits++;
1674 	} while (--i > 0);
1675 	sinherits -= header.ninherits;
1676 	sw_writev((char *) sinherits, ctrl->sectors,
1677 		  header.ninherits * (Uint) sizeof(sinherit), size);
1678 	size += header.ninherits * sizeof(sinherit);
1679 	AFREE(sinherits);
1680 
1681 	/* save iindices */
1682 	sw_writev(ctrl->imap, ctrl->sectors, ctrl->imapsz, size);
1683 	size += ctrl->imapsz;
1684 
1685 	/* save program */
1686 	if (header.progsize > 0) {
1687 	    sw_writev(prog, ctrl->sectors, (Uint) header.progsize, size);
1688 	    size += header.progsize;
1689 	    if (prog != ctrl->prog) {
1690 		FREE(prog);
1691 	    }
1692 	}
1693 
1694 	/* save string constants */
1695 	if (header.nstrings > 0) {
1696 	    sw_writev((char *) sstrings, ctrl->sectors,
1697 		      header.nstrings * (Uint) sizeof(dstrconst), size);
1698 	    size += header.nstrings * (Uint) sizeof(dstrconst);
1699 	    if (header.strsize > 0) {
1700 		sw_writev(text, ctrl->sectors, header.strsize, size);
1701 		size += header.strsize;
1702 		if (text != stext) {
1703 		    FREE(text);
1704 		}
1705 		if (stext != ctrl->stext) {
1706 		    AFREE(stext);
1707 		}
1708 	    }
1709 	    if (sstrings != ctrl->sstrings) {
1710 		AFREE(sstrings);
1711 	    }
1712 	}
1713 
1714 	/* save function definitions */
1715 	if (UCHAR(header.nfuncdefs) > 0) {
1716 	    sw_writev((char *) ctrl->funcdefs, ctrl->sectors,
1717 		      UCHAR(header.nfuncdefs) * (Uint) sizeof(dfuncdef), size);
1718 	    size += UCHAR(header.nfuncdefs) * (Uint) sizeof(dfuncdef);
1719 	}
1720 
1721 	/* save variable definitions */
1722 	if (UCHAR(header.nvardefs) > 0) {
1723 	    sw_writev((char *) ctrl->vardefs, ctrl->sectors,
1724 		      UCHAR(header.nvardefs) * (Uint) sizeof(dvardef), size);
1725 	    size += UCHAR(header.nvardefs) * (Uint) sizeof(dvardef);
1726 	    if (UCHAR(header.nclassvars) > 0) {
1727 		sw_writev(ctrl->classvars, ctrl->sectors,
1728 			  UCHAR(header.nclassvars) * (Uint) 3, size);
1729 		size += UCHAR(header.nclassvars) * (Uint) 3;
1730 	    }
1731 	}
1732 
1733 	/* save function call table */
1734 	if (header.nfuncalls > 0) {
1735 	    sw_writev((char *) ctrl->funcalls, ctrl->sectors,
1736 		      header.nfuncalls * (Uint) 2, size);
1737 	    size += header.nfuncalls * (Uint) 2;
1738 	}
1739 
1740 	/* save symbol table */
1741 	if (header.nsymbols > 0) {
1742 	    sw_writev((char *) ctrl->symbols, ctrl->sectors,
1743 		      header.nsymbols * (Uint) sizeof(dsymbol), size);
1744 	    size += header.nsymbols * sizeof(dsymbol);
1745 	}
1746 
1747 	/* save variable types */
1748 	if (header.nvariables > UCHAR(header.nvardefs)) {
1749 	    sw_writev(ctrl->vtypes, ctrl->sectors,
1750 		      header.nvariables - UCHAR(header.nvardefs), size);
1751 	}
1752     }
1753 }
1754 
1755 
1756 static void d_count (savedata*, value*, unsigned int);
1757 
1758 /*
1759  * NAME:	data->arrcount()
1760  * DESCRIPTION:	count the number of arrays and strings in an array
1761  */
d_arrcount(savedata * save,array * arr)1762 static void d_arrcount(savedata *save, array *arr)
1763 {
1764     arr->prev->next = arr->next;
1765     arr->next->prev = arr->prev;
1766     arr->prev = &save->alist;
1767     arr->next = save->alist.next;
1768     arr->next->prev = arr;
1769     save->alist.next = arr;
1770     save->narr++;
1771 
1772     if (!save->counting) {
1773 	save->counting = TRUE;
1774 	do {
1775 	    save->arrsize += arr->size;
1776 	    d_count(save, d_get_elts(arr), arr->size);
1777 	    arr = arr->prev;
1778 	} while (arr != &save->alist);
1779 	save->counting = FALSE;
1780     }
1781 }
1782 
1783 /*
1784  * NAME:	data->count()
1785  * DESCRIPTION:	count the number of arrays and strings in an object
1786  */
d_count(savedata * save,value * v,Uint n)1787 static void d_count(savedata *save, value *v, Uint n)
1788 {
1789     object *obj;
1790     value *elts;
1791     Uint count;
1792 
1793     while (n > 0) {
1794 	switch (v->type) {
1795 	case T_STRING:
1796 	    if (str_put(v->u.string, save->nstr) == save->nstr) {
1797 		save->nstr++;
1798 		save->strsize += v->u.string->len;
1799 	    }
1800 	    break;
1801 
1802 	case T_ARRAY:
1803 	    if (arr_put(v->u.array, save->narr) == save->narr) {
1804 		d_arrcount(save, v->u.array);
1805 	    }
1806 	    break;
1807 
1808 	case T_MAPPING:
1809 	    if (arr_put(v->u.array, save->narr) == save->narr) {
1810 		if (v->u.array->hashmod) {
1811 		    map_compact(v->u.array->primary->data, v->u.array);
1812 		}
1813 		d_arrcount(save, v->u.array);
1814 	    }
1815 	    break;
1816 
1817 	case T_LWOBJECT:
1818 	    elts = d_get_elts(v->u.array);
1819 	    if (elts->type == T_OBJECT) {
1820 		obj = OBJ(elts->oindex);
1821 		count = obj->count;
1822 		if (elts[1].type == T_INT) {
1823 		    /* convert to new LWO type */
1824 		    elts[1].type = T_FLOAT;
1825 		    elts[1].oindex = FALSE;
1826 		}
1827 		if (arr_put(v->u.array, save->narr) == save->narr) {
1828 		    if (elts->u.objcnt == count &&
1829 			elts[1].u.objcnt != obj->update) {
1830 			d_upgrade_lwobj(v->u.array, obj);
1831 			elts = v->u.array->elts;
1832 		    }
1833 		    d_arrcount(save, v->u.array);
1834 		}
1835 	    } else if (arr_put(v->u.array, save->narr) == save->narr) {
1836 		d_arrcount(save, v->u.array);
1837 	    }
1838 	    break;
1839 	}
1840 
1841 	v++;
1842 	--n;
1843     }
1844 }
1845 
1846 /*
1847  * NAME:	data->save()
1848  * DESCRIPTION:	save the values in an object
1849  */
d_save(savedata * save,svalue * sv,value * v,unsigned short n)1850 static void d_save(savedata *save, svalue *sv, value *v, unsigned short n)
1851 {
1852     Uint i;
1853 
1854     while (n > 0) {
1855 	sv->pad = '\0';
1856 	switch (sv->type = v->type) {
1857 	case T_NIL:
1858 	    sv->oindex = 0;
1859 	    sv->u.number = 0;
1860 	    break;
1861 
1862 	case T_INT:
1863 	    sv->oindex = 0;
1864 	    sv->u.number = v->u.number;
1865 	    break;
1866 
1867 	case T_STRING:
1868 	    i = str_put(v->u.string, save->nstr);
1869 	    sv->oindex = 0;
1870 	    sv->u.string = i;
1871 	    if (save->sstrings[i].ref++ == 0) {
1872 		/* new string value */
1873 		save->sstrings[i].index = save->strsize;
1874 		save->sstrings[i].len = v->u.string->len;
1875 		memcpy(save->stext + save->strsize, v->u.string->text,
1876 		       v->u.string->len);
1877 		save->strsize += v->u.string->len;
1878 	    }
1879 	    break;
1880 
1881 	case T_FLOAT:
1882 	case T_OBJECT:
1883 	    sv->oindex = v->oindex;
1884 	    sv->u.objcnt = v->u.objcnt;
1885 	    break;
1886 
1887 	case T_ARRAY:
1888 	case T_MAPPING:
1889 	case T_LWOBJECT:
1890 	    i = arr_put(v->u.array, save->narr);
1891 	    sv->oindex = 0;
1892 	    sv->u.array = i;
1893 	    if (save->sarrays[i].ref++ == 0) {
1894 		/* new array value */
1895 		save->sarrays[i].type = sv->type;
1896 	    }
1897 	    break;
1898 	}
1899 	sv++;
1900 	v++;
1901 	--n;
1902     }
1903 }
1904 
1905 /*
1906  * NAME:	data->put_values()
1907  * DESCRIPTION:	save modified values as svalues
1908  */
d_put_values(dataspace * data,svalue * sv,value * v,unsigned short n)1909 static void d_put_values(dataspace *data, svalue *sv, value *v, unsigned short n)
1910 {
1911     while (n > 0) {
1912 	if (v->modified) {
1913 	    sv->pad = '\0';
1914 	    switch (sv->type = v->type) {
1915 	    case T_NIL:
1916 		sv->oindex = 0;
1917 		sv->u.number = 0;
1918 		break;
1919 
1920 	    case T_INT:
1921 		sv->oindex = 0;
1922 		sv->u.number = v->u.number;
1923 		break;
1924 
1925 	    case T_STRING:
1926 		sv->oindex = 0;
1927 		sv->u.string = v->u.string->primary - data->base.strings;
1928 		break;
1929 
1930 	    case T_FLOAT:
1931 	    case T_OBJECT:
1932 		sv->oindex = v->oindex;
1933 		sv->u.objcnt = v->u.objcnt;
1934 		break;
1935 
1936 	    case T_ARRAY:
1937 	    case T_MAPPING:
1938 	    case T_LWOBJECT:
1939 		sv->oindex = 0;
1940 		sv->u.array = v->u.array->primary - data->base.arrays;
1941 		break;
1942 	    }
1943 	    v->modified = FALSE;
1944 	}
1945 	sv++;
1946 	v++;
1947 	--n;
1948     }
1949 }
1950 
1951 /*
1952  * NAME:	data->free_values()
1953  * DESCRIPTION:	free values in a dataspace block
1954  */
d_free_values(dataspace * data)1955 static void d_free_values(dataspace *data)
1956 {
1957     Uint i;
1958 
1959     /* free parse_string data */
1960     if (data->parser != (struct _parser_ *) NULL) {
1961 	ps_del(data->parser);
1962 	data->parser = (struct _parser_ *) NULL;
1963     }
1964 
1965     /* free variables */
1966     if (data->variables != (value *) NULL) {
1967 	value *v;
1968 
1969 	for (i = data->nvariables, v = data->variables; i > 0; --i, v++) {
1970 	    i_del_value(v);
1971 	}
1972 
1973 	FREE(data->variables);
1974 	data->variables = (value *) NULL;
1975     }
1976 
1977     /* free callouts */
1978     if (data->callouts != (dcallout *) NULL) {
1979 	dcallout *co;
1980 	value *v;
1981 	int j;
1982 
1983 	for (i = data->ncallouts, co = data->callouts; i > 0; --i, co++) {
1984 	    v = co->val;
1985 	    if (v->type == T_STRING) {
1986 		j = 1 + co->nargs;
1987 		if (j > 4) {
1988 		    j = 4;
1989 		}
1990 		do {
1991 		    i_del_value(v++);
1992 		} while (--j > 0);
1993 	    }
1994 	}
1995 
1996 	FREE(data->callouts);
1997 	data->callouts = (dcallout *) NULL;
1998     }
1999 
2000     /* free arrays */
2001     if (data->base.arrays != (arrref *) NULL) {
2002 	arrref *a;
2003 
2004 	for (i = data->narrays, a = data->base.arrays; i > 0; --i, a++) {
2005 	    if (a->arr != (array *) NULL) {
2006 		arr_del(a->arr);
2007 	    }
2008 	}
2009 
2010 	FREE(data->base.arrays);
2011 	data->base.arrays = (arrref *) NULL;
2012     }
2013 
2014     /* free strings */
2015     if (data->base.strings != (strref *) NULL) {
2016 	strref *s;
2017 
2018 	for (i = data->nstrings, s = data->base.strings; i > 0; --i, s++) {
2019 	    if (s->str != (string *) NULL) {
2020 		s->str->primary = (strref *) NULL;
2021 		str_del(s->str);
2022 	    }
2023 	}
2024 
2025 	FREE(data->base.strings);
2026 	data->base.strings = (strref *) NULL;
2027     }
2028 
2029     /* free any left-over arrays */
2030     if (data->alist.next != &data->alist) {
2031 	data->alist.prev->next = data->alist.next;
2032 	data->alist.next->prev = data->alist.prev;
2033 	arr_freelist(data->alist.next);
2034 	data->alist.prev = data->alist.next = &data->alist;
2035     }
2036 }
2037 
2038 /*
2039  * NAME:	data->save_dataspace()
2040  * DESCRIPTION:	save all values in a dataspace block
2041  */
d_save_dataspace(dataspace * data,bool swap)2042 static bool d_save_dataspace(dataspace *data, bool swap)
2043 {
2044     sdataspace header;
2045     Uint n;
2046 
2047     if (data->parser != (struct _parser_ *) NULL &&
2048 	!(OBJ(data->oindex)->flags & O_SPECIAL)) {
2049 	ps_save(data->parser);
2050     }
2051     if (swap && (data->base.flags & MOD_SAVE)) {
2052 	data->base.flags |= MOD_ALL;
2053     } else if (!(data->base.flags & MOD_ALL)) {
2054 	return FALSE;
2055     }
2056 
2057     if (data->svariables != (svalue *) NULL && data->base.achange == 0 &&
2058 	data->base.schange == 0 && !(data->base.flags & MOD_NEWCALLOUT)) {
2059 	bool mod;
2060 
2061 	/*
2062 	 * No strings/arrays added or deleted. Check individual variables and
2063 	 * array elements.
2064 	 */
2065 	if (data->base.flags & MOD_VARIABLE) {
2066 	    /*
2067 	     * variables changed
2068 	     */
2069 	    d_put_values(data, data->svariables, data->variables,
2070 			 data->nvariables);
2071 	    if (swap) {
2072 		sw_writev((char *) data->svariables, data->sectors,
2073 			  data->nvariables * (Uint) sizeof(svalue),
2074 			  data->varoffset);
2075 	    }
2076 	}
2077 	if (data->base.flags & MOD_ARRAYREF) {
2078 	    sarray *sa;
2079 	    arrref *a;
2080 
2081 	    /*
2082 	     * references to arrays changed
2083 	     */
2084 	    sa = data->sarrays;
2085 	    a = data->base.arrays;
2086 	    mod = FALSE;
2087 	    for (n = data->narrays; n > 0; --n) {
2088 		if (a->arr != (array *) NULL && sa->ref != (a->ref & ~ARR_MOD))
2089 		{
2090 		    sa->ref = a->ref & ~ARR_MOD;
2091 		    mod = TRUE;
2092 		}
2093 		sa++;
2094 		a++;
2095 	    }
2096 	    if (mod && swap) {
2097 		sw_writev((char *) data->sarrays, data->sectors,
2098 			  data->narrays * sizeof(sarray), data->arroffset);
2099 	    }
2100 	}
2101 	if (data->base.flags & MOD_ARRAY) {
2102 	    arrref *a;
2103 	    Uint idx;
2104 
2105 	    /*
2106 	     * array elements changed
2107 	     */
2108 	    a = data->base.arrays;
2109 	    for (n = 0; n < data->narrays; n++) {
2110 		if (a->arr != (array *) NULL && (a->ref & ARR_MOD)) {
2111 		    a->ref &= ~ARR_MOD;
2112 		    idx = data->sarrays[n].index;
2113 		    d_put_values(data, &data->selts[idx], a->arr->elts,
2114 				 a->arr->size);
2115 		    if (swap) {
2116 			sw_writev((char *) &data->selts[idx], data->sectors,
2117 				  a->arr->size * (Uint) sizeof(svalue),
2118 				  data->arroffset +
2119 					      data->narrays * sizeof(sarray) +
2120 					      idx * sizeof(svalue));
2121 		    }
2122 		}
2123 		a++;
2124 	    }
2125 	}
2126 	if (data->base.flags & MOD_STRINGREF) {
2127 	    sstring *ss;
2128 	    strref *s;
2129 
2130 	    /*
2131 	     * string references changed
2132 	     */
2133 	    ss = data->sstrings;
2134 	    s = data->base.strings;
2135 	    mod = FALSE;
2136 	    for (n = data->nstrings; n > 0; --n) {
2137 		if (s->str != (string *) NULL && ss->ref != s->ref) {
2138 		    ss->ref = s->ref;
2139 		    mod = TRUE;
2140 		}
2141 		ss++;
2142 		s++;
2143 	    }
2144 	    if (mod && swap) {
2145 		sw_writev((char *) data->sstrings, data->sectors,
2146 			  data->nstrings * sizeof(sstring),
2147 			  data->stroffset);
2148 	    }
2149 	}
2150 	if (data->base.flags & MOD_CALLOUT) {
2151 	    scallout *sco;
2152 	    dcallout *co;
2153 
2154 	    sco = data->scallouts;
2155 	    co = data->callouts;
2156 	    for (n = data->ncallouts; n > 0; --n) {
2157 		sco->time = co->time;
2158 		sco->htime = 0;
2159 		sco->mtime = co->mtime;
2160 		sco->nargs = co->nargs;
2161 		if (co->val[0].type == T_STRING) {
2162 		    co->val[0].modified = TRUE;
2163 		    co->val[1].modified = TRUE;
2164 		    co->val[2].modified = TRUE;
2165 		    co->val[3].modified = TRUE;
2166 		    d_put_values(data, sco->val, co->val,
2167 				 (co->nargs > 3) ? 4 : co->nargs + 1);
2168 		} else {
2169 		    sco->val[0].type = T_NIL;
2170 		}
2171 		sco++;
2172 		co++;
2173 	    }
2174 
2175 	    if (swap) {
2176 		/* save new (?) fcallouts value */
2177 		sw_writev((char *) &data->fcallouts, data->sectors,
2178 			  (Uint) sizeof(uindex),
2179 			  (Uint) ((char *)&header.fcallouts - (char *)&header));
2180 
2181 		/* save scallouts */
2182 		sw_writev((char *) data->scallouts, data->sectors,
2183 			  data->ncallouts * (Uint) sizeof(scallout),
2184 			  data->cooffset);
2185 	    }
2186 	}
2187     } else {
2188 	savedata save;
2189 	char *text;
2190 	Uint size;
2191 	array *arr;
2192 	sarray *sarr;
2193 
2194 	/*
2195 	 * count the number and sizes of strings and arrays
2196 	 */
2197 	arr_merge();
2198 	str_merge();
2199 	save.narr = 0;
2200 	save.nstr = 0;
2201 	save.arrsize = 0;
2202 	save.strsize = 0;
2203 	save.counting = FALSE;
2204 	save.alist.prev = save.alist.next = &save.alist;
2205 
2206 	d_get_variable(data, 0);
2207 	if (data->svariables == (svalue *) NULL) {
2208 	    data->svariables = ALLOC(svalue, data->nvariables);
2209 	}
2210 	d_count(&save, data->variables, data->nvariables);
2211 
2212 	if (data->ncallouts > 0) {
2213 	    dcallout *co;
2214 
2215 	    if (data->callouts == (dcallout *) NULL) {
2216 		d_get_callouts(data);
2217 	    }
2218 	    /* remove empty callouts at the end */
2219 	    for (n = data->ncallouts, co = data->callouts + n; n > 0; --n) {
2220 		if ((--co)->val[0].type == T_STRING) {
2221 		    break;
2222 		}
2223 		if (data->fcallouts == n) {
2224 		    /* first callout in the free list */
2225 		    data->fcallouts = co->co_next;
2226 		} else {
2227 		    /* connect previous to next */
2228 		    data->callouts[co->co_prev - 1].co_next = co->co_next;
2229 		    if (co->co_next != 0) {
2230 			/* connect next to previous */
2231 			data->callouts[co->co_next - 1].co_prev = co->co_prev;
2232 		    }
2233 		}
2234 	    }
2235 	    data->ncallouts = n;
2236 	    if (n == 0) {
2237 		/* all callouts removed */
2238 		FREE(data->callouts);
2239 		data->callouts = (dcallout *) NULL;
2240 	    } else {
2241 		/* process callouts */
2242 		for (co = data->callouts; n > 0; --n, co++) {
2243 		    if (co->val[0].type == T_STRING) {
2244 			d_count(&save, co->val,
2245 				(co->nargs > 3) ? 4 : co->nargs + 1);
2246 		    }
2247 		}
2248 	    }
2249 	}
2250 
2251 	/* fill in header */
2252 	header.flags = 0;
2253 	header.nvariables = data->nvariables;
2254 	header.narrays = save.narr;
2255 	header.eltsize = save.arrsize;
2256 	header.nstrings = save.nstr;
2257 	header.strsize = save.strsize;
2258 	header.ncallouts = data->ncallouts;
2259 	header.fcallouts = data->fcallouts;
2260 
2261 	/*
2262 	 * put everything in a saveable form
2263 	 */
2264 	save.sstrings = data->sstrings =
2265 			REALLOC(data->sstrings, sstring, 0, header.nstrings);
2266 	memset(save.sstrings, '\0', save.nstr * sizeof(sstring));
2267 	save.stext = data->stext =
2268 		     REALLOC(data->stext, char, 0, header.strsize);
2269 	save.sarrays = data->sarrays =
2270 		       REALLOC(data->sarrays, sarray, 0, header.narrays);
2271 	memset(save.sarrays, '\0', save.narr * sizeof(sarray));
2272 	save.selts = data->selts =
2273 		     REALLOC(data->selts, svalue, 0, header.eltsize);
2274 	save.narr = 0;
2275 	save.nstr = 0;
2276 	save.arrsize = 0;
2277 	save.strsize = 0;
2278 	data->scallouts = REALLOC(data->scallouts, scallout, 0,
2279 				  header.ncallouts);
2280 
2281 	d_save(&save, data->svariables, data->variables, data->nvariables);
2282 	if (header.ncallouts > 0) {
2283 	    scallout *sco;
2284 	    dcallout *co;
2285 
2286 	    sco = data->scallouts;
2287 	    co = data->callouts;
2288 	    for (n = data->ncallouts; n > 0; --n) {
2289 		sco->time = co->time;
2290 		sco->htime = 0;
2291 		sco->mtime = co->mtime;
2292 		sco->nargs = co->nargs;
2293 		if (co->val[0].type == T_STRING) {
2294 		    d_save(&save, sco->val, co->val,
2295 			   (co->nargs > 3) ? 4 : co->nargs + 1);
2296 		} else {
2297 		    sco->val[0].type = T_NIL;
2298 		}
2299 		sco++;
2300 		co++;
2301 	    }
2302 	}
2303 	for (arr = save.alist.prev, sarr = save.sarrays; arr != &save.alist;
2304 	     arr = arr->prev, sarr++) {
2305 	    sarr->index = save.arrsize;
2306 	    sarr->size = arr->size;
2307 	    sarr->tag = arr->tag;
2308 	    d_save(&save, save.selts + save.arrsize, arr->elts, arr->size);
2309 	    save.arrsize += arr->size;
2310 	}
2311 	if (arr->next != &save.alist) {
2312 	    data->alist.next->prev = arr->prev;
2313 	    arr->prev->next = data->alist.next;
2314 	    data->alist.next = arr->next;
2315 	    arr->next->prev = &data->alist;
2316 	}
2317 
2318 	/* clear merge tables */
2319 	arr_clear();
2320 	str_clear();
2321 
2322 	if (swap) {
2323 	    text = save.stext;
2324 	    if (header.strsize >= CMPLIMIT) {
2325 		text = ALLOC(char, header.strsize);
2326 		size = compress(text, save.stext, header.strsize);
2327 		if (size != 0) {
2328 		    header.flags |= CMP_PRED;
2329 		    header.strsize = size;
2330 		} else {
2331 		    FREE(text);
2332 		    text = save.stext;
2333 		}
2334 	    }
2335 
2336 	    /* create sector space */
2337 	    size = sizeof(sdataspace) +
2338 		   (header.nvariables + header.eltsize) * sizeof(svalue) +
2339 		   header.narrays * sizeof(sarray) +
2340 		   header.nstrings * sizeof(sstring) +
2341 		   header.strsize +
2342 		   header.ncallouts * (Uint) sizeof(scallout);
2343 	    header.nsectors = d_swapalloc(size, data->nsectors, &data->sectors);
2344 	    data->nsectors = header.nsectors;
2345 	    OBJ(data->oindex)->dfirst = data->sectors[0];
2346 
2347 	    /* save header */
2348 	    size = sizeof(sdataspace);
2349 	    sw_writev((char *) &header, data->sectors, size, (Uint) 0);
2350 	    sw_writev((char *) data->sectors, data->sectors,
2351 		      header.nsectors * (Uint) sizeof(sector), size);
2352 	    size += header.nsectors * (Uint) sizeof(sector);
2353 
2354 	    /* save variables */
2355 	    data->varoffset = size;
2356 	    sw_writev((char *) data->svariables, data->sectors,
2357 		      data->nvariables * (Uint) sizeof(svalue), size);
2358 	    size += data->nvariables * (Uint) sizeof(svalue);
2359 
2360 	    /* save arrays */
2361 	    data->arroffset = size;
2362 	    if (header.narrays > 0) {
2363 		sw_writev((char *) save.sarrays, data->sectors,
2364 			  header.narrays * sizeof(sarray), size);
2365 		size += header.narrays * sizeof(sarray);
2366 		if (header.eltsize > 0) {
2367 		    sw_writev((char *) save.selts, data->sectors,
2368 			      header.eltsize * sizeof(svalue), size);
2369 		    size += header.eltsize * sizeof(svalue);
2370 		}
2371 	    }
2372 
2373 	    /* save strings */
2374 	    data->stroffset = size;
2375 	    if (header.nstrings > 0) {
2376 		sw_writev((char *) save.sstrings, data->sectors,
2377 			  header.nstrings * sizeof(sstring), size);
2378 		size += header.nstrings * sizeof(sstring);
2379 		if (header.strsize > 0) {
2380 		    sw_writev(text, data->sectors, header.strsize, size);
2381 		    size += header.strsize;
2382 		    if (text != save.stext) {
2383 			FREE(text);
2384 		    }
2385 		}
2386 	    }
2387 
2388 	    /* save callouts */
2389 	    data->cooffset = size;
2390 	    if (header.ncallouts > 0) {
2391 		sw_writev((char *) data->scallouts, data->sectors,
2392 			  header.ncallouts * (Uint) sizeof(scallout), size);
2393 	    }
2394 	}
2395 
2396 	d_free_values(data);
2397 
2398 	data->flags = header.flags;
2399 	data->narrays = header.narrays;
2400 	data->eltsize = header.eltsize;
2401 	data->nstrings = header.nstrings;
2402 	data->strsize = save.strsize;
2403 
2404 	data->base.schange = 0;
2405 	data->base.achange = 0;
2406     }
2407 
2408     if (swap) {
2409 	data->base.flags = 0;
2410     } else {
2411 	data->base.flags = MOD_SAVE;
2412     }
2413     return TRUE;
2414 }
2415 
2416 
2417 /*
2418  * NAME:	data->swapout()
2419  * DESCRIPTION:	Swap out a portion of the control and dataspace blocks in
2420  *		memory.  Return the number of dataspace blocks swapped out.
2421  */
d_swapout(unsigned int frag)2422 sector d_swapout(unsigned int frag)
2423 {
2424     sector n, count;
2425     dataspace *data;
2426     control *ctrl;
2427 
2428     count = 0;
2429 
2430     if (frag != 0) {
2431 	/* swap out dataspace blocks */
2432 	data = dtail;
2433 	for (n = ndata / frag, n -= (n > 0 && frag != 1); n > 0; --n) {
2434 	    dataspace *prev;
2435 
2436 	    prev = data->prev;
2437 	    if (d_save_dataspace(data, TRUE)) {
2438 		count++;
2439 	    }
2440 	    OBJ(data->oindex)->data = (dataspace *) NULL;
2441 	    d_free_dataspace(data);
2442 	    data = prev;
2443 	}
2444 
2445 	/* swap out control blocks */
2446 	ctrl = ctail;
2447 	for (n = nctrl / frag; n > 0; --n) {
2448 	    control *prev;
2449 
2450 	    prev = ctrl->prev;
2451 	    if (ctrl->ndata == 0) {
2452 		if ((ctrl->sectors == (sector *) NULL &&
2453 		     !(ctrl->flags & CTRL_COMPILED)) ||
2454 		    (ctrl->flags & CTRL_VARMAP)) {
2455 		    d_save_control(ctrl);
2456 		}
2457 		OBJ(ctrl->oindex)->ctrl = (control *) NULL;
2458 		d_free_control(ctrl);
2459 	    }
2460 	    ctrl = prev;
2461 	}
2462     }
2463 
2464     /* perform garbage collection for one dataspace */
2465     if (gcdata != (dataspace *) NULL) {
2466 	if (d_save_dataspace(gcdata, (frag != 0)) && frag != 0) {
2467 	    count++;
2468 	}
2469 	gcdata = gcdata->gcnext;
2470     }
2471 
2472     return count;
2473 }
2474 
2475 /*
2476  * NAME:	data->upgrade_mem()
2477  * DESCRIPTION:	upgrade all obj and all objects cloned from obj that have
2478  *		dataspaces in memory
2479  */
d_upgrade_mem(object * tmpl,object * newob)2480 void d_upgrade_mem(object *tmpl, object *newob)
2481 {
2482     dataspace *data;
2483     Uint nvar;
2484     unsigned short *vmap;
2485     object *obj;
2486 
2487     nvar = tmpl->ctrl->vmapsize;
2488     vmap = tmpl->ctrl->vmap;
2489 
2490     for (data = dtail; data != (dataspace *) NULL; data = data->prev) {
2491 	obj = OBJ(data->oindex);
2492 	if ((obj == newob ||
2493 	     (!(obj->flags & O_MASTER) && obj->u_master == newob->index)) &&
2494 	    obj->count != 0) {
2495 	    /* upgrade clone */
2496 	    if (nvar != 0) {
2497 		d_upgrade_data(data, nvar, vmap, tmpl);
2498 	    }
2499 	    data->ctrl->ndata--;
2500 	    data->ctrl = newob->ctrl;
2501 	    data->ctrl->ndata++;
2502 	}
2503     }
2504 }
2505 
2506 /*
2507  * NAME:	data->conv()
2508  * DESCRIPTION:	convert something from the snapshot
2509  */
d_conv(char * m,sector * vec,char * layout,Uint n,Uint idx,void (* readv)(char *,sector *,Uint,Uint))2510 static Uint d_conv(char *m, sector *vec, char *layout, Uint n, Uint idx,
2511 		   void (*readv) (char*, sector*, Uint, Uint))
2512 {
2513     Uint bufsize;
2514     char *buf;
2515 
2516     bufsize = (conf_dsize(layout) & 0xff) * n;
2517     buf = ALLOCA(char, bufsize);
2518     (*readv)(buf, vec, bufsize, idx);
2519     conf_dconv(m, buf, layout, n);
2520     AFREE(buf);
2521 
2522     return bufsize;
2523 }
2524 
2525 /*
2526  * NAME:	data->conv_proto()
2527  * DESCRIPTION:	convert a prototype to the new standard
2528  */
d_conv_proto(char ** old,char ** newp)2529 static void d_conv_proto(char **old, char **newp)
2530 {
2531     char *p, *args;
2532     unsigned short i, n, type;
2533     unsigned short tclass, nargs, vargs;
2534     bool varargs;
2535 
2536     p = *old;
2537     tclass = UCHAR(*p++);
2538     type = UCHAR(*p++);
2539     n = UCHAR(*p++);
2540 
2541     varargs = (tclass & C_VARARGS);
2542     tclass &= ~C_VARARGS;
2543     nargs = vargs = 0;
2544     args = &PROTO_FTYPE(*newp);
2545     *args++ = (type & T_TYPE) | ((type >> 1) & T_REF);
2546 
2547     for (i = 0; i < n; i++) {
2548 	if (varargs) {
2549 	    vargs++;
2550 	} else {
2551 	    nargs++;
2552 	}
2553 	type = UCHAR(*p++);
2554 	if (type & T_VARARGS) {
2555 	    if (i == n - 1) {
2556 		tclass |= C_ELLIPSIS;
2557 		if (!varargs) {
2558 		    --nargs;
2559 		    vargs++;
2560 		}
2561 	    }
2562 	    varargs = TRUE;
2563 	}
2564 	*args++ = (type & T_TYPE) | ((type >> 1) & T_REF);
2565     }
2566 
2567     *old = p;
2568     p = *newp;
2569     *newp = args;
2570 
2571     PROTO_CLASS(p) = tclass;
2572     PROTO_NARGS(p) = nargs;
2573     PROTO_VARGS(p) = vargs;
2574     PROTO_HSIZE(p) = (6 + n) >> 8;
2575     PROTO_LSIZE(p) = 6 + n;
2576 }
2577 
2578 /*
2579  * NAME:	data->conv_control()
2580  * DESCRIPTION:	convert control block
2581  */
d_conv_control(object * obj,void (* readv)(char *,sector *,Uint,Uint))2582 static control *d_conv_control(object *obj,
2583 			       void (*readv) (char*, sector*, Uint, Uint))
2584 {
2585     scontrol header;
2586     control *ctrl;
2587     Uint size;
2588     unsigned int n;
2589 
2590     ctrl = d_new_control();
2591     ctrl->oindex = obj->index;
2592 
2593     /*
2594      * restore from snapshot
2595      */
2596     if (conv_ctrl1) {
2597 	oscontrol oheader;
2598 
2599 	size = d_conv((char *) &oheader, &obj->cfirst, os_layout, (Uint) 1,
2600 		      (Uint) 0, readv);
2601 	header.nsectors = oheader.nsectors;
2602 	header.flags = UCHAR(oheader.flags);
2603 	header.ninherits = UCHAR(oheader.ninherits);
2604 	header.imapsz = 0;
2605 	header.compiled = oheader.compiled;
2606 	header.progsize = oheader.progsize;
2607 	header.nstrings = oheader.nstrings;
2608 	header.strsize = oheader.strsize;
2609 	header.nfuncdefs = oheader.nfuncdefs;
2610 	header.nvardefs = oheader.nvardefs;
2611 	header.nclassvars = 0;
2612 	header.nfuncalls = oheader.nfuncalls;
2613 	header.nsymbols = oheader.nsymbols;
2614 	header.nvariables = oheader.nvariables;
2615 	header.vmapsize = oheader.vmapsize;
2616     } else if (conv_ctrl2) {
2617 	ocontrol oheader;
2618 
2619 	size = d_conv((char *) &oheader, &obj->cfirst, oc_layout, (Uint) 1,
2620 		      (Uint) 0, readv);
2621 	header.nsectors = oheader.nsectors;
2622 	header.flags = UCHAR(oheader.flags);
2623 	header.ninherits = UCHAR(oheader.ninherits);
2624 	header.imapsz = 0;
2625 	header.compiled = oheader.compiled;
2626 	header.progsize = oheader.progsize;
2627 	header.nstrings = oheader.nstrings;
2628 	header.strsize = oheader.strsize;
2629 	header.nfuncdefs = oheader.nfuncdefs;
2630 	header.nvardefs = oheader.nvardefs;
2631 	header.nclassvars = oheader.nclassvars;
2632 	header.nfuncalls = oheader.nfuncalls;
2633 	header.nsymbols = oheader.nsymbols;
2634 	header.nvariables = oheader.nvariables;
2635 	header.vmapsize = oheader.vmapsize;
2636     } else if (conv_inherit) {
2637 	xscontrol oheader;
2638 
2639 	size = d_conv((char *) &oheader, &obj->cfirst, xsc_layout, (Uint) 1,
2640 		      (Uint) 0, readv);
2641 	header.nsectors = oheader.nsectors;
2642 	header.flags = oheader.flags;
2643 	header.ninherits = oheader.ninherits;
2644 	header.imapsz = 0;
2645 	header.compiled = oheader.compiled;
2646 	header.progsize = oheader.progsize;
2647 	header.nstrings = oheader.nstrings;
2648 	header.strsize = oheader.strsize;
2649 	header.nfuncdefs = oheader.nfuncdefs;
2650 	header.nvardefs = oheader.nvardefs;
2651 	header.nclassvars = oheader.nclassvars;
2652 	header.nfuncalls = oheader.nfuncalls;
2653 	header.nsymbols = oheader.nsymbols;
2654 	header.nvariables = oheader.nvariables;
2655 	header.vmapsize = oheader.vmapsize;
2656     } else if (conv_time) {
2657 	tscontrol oheader;
2658 
2659 	size = d_conv((char *) &oheader, &obj->cfirst, tsc_layout, (Uint) 1,
2660 		      (Uint) 0, readv);
2661 	header.nsectors = oheader.nsectors;
2662 	header.flags = oheader.flags;
2663 	header.ninherits = oheader.ninherits;
2664 	header.imapsz = oheader.imapsz;
2665 	header.compiled = oheader.compiled;
2666 	header.progsize = oheader.progsize;
2667 	header.nstrings = oheader.nstrings;
2668 	header.strsize = oheader.strsize;
2669 	header.nfuncdefs = oheader.nfuncdefs;
2670 	header.nvardefs = oheader.nvardefs;
2671 	header.nclassvars = oheader.nclassvars;
2672 	header.nfuncalls = oheader.nfuncalls;
2673 	header.nsymbols = oheader.nsymbols;
2674 	header.nvariables = oheader.nvariables;
2675 	header.vmapsize = oheader.vmapsize;
2676     } else {
2677 	size = d_conv((char *) &header, &obj->cfirst, sc_layout, (Uint) 1,
2678 		      (Uint) 0, readv);
2679     }
2680     ctrl->flags = header.flags;
2681     if (conv_vm) {
2682 	ctrl->flags |= CTRL_OLDVM;
2683     }
2684     ctrl->ninherits = header.ninherits;
2685     ctrl->imapsz = header.imapsz;
2686     ctrl->compiled = header.compiled;
2687     ctrl->progsize = header.progsize;
2688     ctrl->nstrings = header.nstrings;
2689     ctrl->strsize = header.strsize;
2690     ctrl->nfuncdefs = UCHAR(header.nfuncdefs);
2691     ctrl->nvardefs = UCHAR(header.nvardefs);
2692     ctrl->nclassvars = UCHAR(header.nclassvars);
2693     ctrl->nfuncalls = header.nfuncalls;
2694     ctrl->nsymbols = header.nsymbols;
2695     ctrl->nvariables = header.nvariables;
2696     ctrl->vmapsize = header.vmapsize;
2697 
2698     /* sectors */
2699     ctrl->sectors = ALLOC(sector, ctrl->nsectors = header.nsectors);
2700     ctrl->sectors[0] = obj->cfirst;
2701     for (n = 0; n < header.nsectors; n++) {
2702 	size += d_conv((char *) (ctrl->sectors + n), ctrl->sectors, "d",
2703 		       (Uint) 1, size, readv);
2704     }
2705 
2706     if (header.vmapsize != 0) {
2707 	/* only vmap */
2708 	ctrl->vmap = ALLOC(unsigned short, header.vmapsize);
2709 	d_conv((char *) ctrl->vmap, ctrl->sectors, "s", (Uint) header.vmapsize,
2710 	       size, readv);
2711     } else {
2712 	dinherit *inherits;
2713 
2714 	/* inherits */
2715 	n = header.ninherits; /* at least one */
2716 	ctrl->inherits = inherits = ALLOC(dinherit, n);
2717 	if (conv_inherit) {
2718 	    osinherit *osinherits;
2719 
2720 	    osinherits = ALLOCA(osinherit, n);
2721 	    size += d_conv((char *) osinherits, ctrl->sectors, osi_layout,
2722 			   (Uint) n, size, readv);
2723 	    do {
2724 		inherits->oindex = osinherits->oindex;
2725 		inherits->progoffset = 0;
2726 		inherits->funcoffset = osinherits->funcoffset;
2727 		inherits->varoffset = osinherits->varoffset & 0x7fff;
2728 		(inherits++)->priv = ((osinherits++)->varoffset & 0x8000) != 0;
2729 	    } while (--n > 0);
2730 	    AFREE(osinherits - header.ninherits);
2731 	} else {
2732 	    sinherit *sinherits;
2733 
2734 	    sinherits = ALLOCA(sinherit, n);
2735 	    size += d_conv((char *) sinherits, ctrl->sectors, si_layout,
2736 			   (Uint) n, size, readv);
2737 	    do {
2738 		inherits->oindex = sinherits->oindex;
2739 		inherits->progoffset = sinherits->progoffset;
2740 		inherits->funcoffset = sinherits->funcoffset;
2741 		inherits->varoffset = sinherits->varoffset;
2742 		(inherits++)->priv = (sinherits++)->flags;
2743 	    } while (--n > 0);
2744 	    AFREE(sinherits - header.ninherits);
2745 
2746 	    ctrl->imap = ALLOC(char, header.imapsz);
2747 	    (*readv)(ctrl->imap, ctrl->sectors, header.imapsz, size);
2748 	    size += header.imapsz;
2749 	}
2750 
2751 	if (header.progsize != 0) {
2752 	    /* program */
2753 	    if (header.flags & CMP_TYPE) {
2754 		ctrl->prog = decompress(ctrl->sectors, readv, header.progsize,
2755 					size, &ctrl->progsize);
2756 	    } else {
2757 		ctrl->prog = ALLOC(char, header.progsize);
2758 		(*readv)(ctrl->prog, ctrl->sectors, header.progsize, size);
2759 	    }
2760 	    size += header.progsize;
2761 	}
2762 
2763 	if (header.nstrings != 0) {
2764 	    /* strings */
2765 	    ctrl->sstrings = ALLOC(dstrconst, header.nstrings);
2766 	    size += d_conv((char *) ctrl->sstrings, ctrl->sectors, DSTR_LAYOUT,
2767 			   (Uint) header.nstrings, size, readv);
2768 	    if (header.strsize != 0) {
2769 		if (header.flags & (CMP_TYPE << 2)) {
2770 		    ctrl->stext = decompress(ctrl->sectors, readv,
2771 					     header.strsize, size,
2772 					     &ctrl->strsize);
2773 		} else {
2774 		    ctrl->stext = ALLOC(char, header.strsize);
2775 		    (*readv)(ctrl->stext, ctrl->sectors, header.strsize, size);
2776 		}
2777 		size += header.strsize;
2778 	    }
2779 	}
2780 
2781 	if (header.nfuncdefs != 0) {
2782 	    /* function definitions */
2783 	    ctrl->funcdefs = ALLOC(dfuncdef, UCHAR(header.nfuncdefs));
2784 	    size += d_conv((char *) ctrl->funcdefs, ctrl->sectors, DF_LAYOUT,
2785 			   (Uint) UCHAR(header.nfuncdefs), size, readv);
2786 	    if (conv_ctrl1) {
2787 		char *prog, *old, *newp;
2788 		Uint offset, funcsize;
2789 
2790 		/*
2791 		 * convert restored program to new prototype standard
2792 		 */
2793 		prog = ALLOC(char, ctrl->progsize + (Uint) 3 * ctrl->nfuncdefs);
2794 		newp = prog;
2795 		for (n = 0; n < ctrl->nfuncdefs; n++) {
2796 		    /* convert prototype */
2797 		    old = ctrl->prog + ctrl->funcdefs[n].offset;
2798 		    ctrl->funcdefs[n].offset = newp - prog;
2799 		    d_conv_proto(&old, &newp);
2800 
2801 		    /* copy program */
2802 		    offset = old - ctrl->prog;
2803 		    if (n < ctrl->nfuncdefs - 1) {
2804 			funcsize = ctrl->funcdefs[n + 1].offset - offset;
2805 		    } else {
2806 			funcsize = ctrl->progsize - offset;
2807 		    }
2808 		    if (funcsize != 0) {
2809 			memcpy(newp, old, funcsize);
2810 			newp += funcsize;
2811 		    }
2812 		}
2813 
2814 		/* replace program */
2815 		FREE(ctrl->prog);
2816 		ctrl->prog = prog;
2817 		ctrl->progsize = newp - prog;
2818 	    }
2819 	}
2820 
2821 	if (header.nvardefs != 0) {
2822 	    /* variable definitions */
2823 	    ctrl->vardefs = ALLOC(dvardef, UCHAR(header.nvardefs));
2824 	    if (conv_vm) {
2825 		ovardef *ov;
2826 
2827 		ov = ALLOC(ovardef, ctrl->nvardefs);
2828 		size += d_conv((char *) ov, ctrl->sectors, OV_LAYOUT,
2829 			       (Uint) ctrl->nvardefs, size, readv);
2830 		for (n = 0; n < ctrl->nvardefs; n++) {
2831 		    ctrl->vardefs[n].class = ov[n].class;
2832 		    ctrl->vardefs[n].type = ov[n].type;
2833 		    ctrl->vardefs[n].inherit = ov[n].inherit;
2834 		    ctrl->vardefs[n].index = ov[n].index;
2835 		}
2836 		FREE(ov);
2837 	    } else {
2838 		size += d_conv((char *) ctrl->vardefs, ctrl->sectors, DV_LAYOUT,
2839 			       (Uint) UCHAR(header.nvardefs), size, readv);
2840 	    }
2841 	    if (conv_ctrl1) {
2842 		unsigned short type;
2843 
2844 		for (n = 0; n < ctrl->nvardefs; n++) {
2845 		    type = ctrl->vardefs[n].type;
2846 		    ctrl->vardefs[n].type =
2847 					(type & T_TYPE) | ((type >> 1) & T_REF);
2848 		}
2849 	    } else if (ctrl->nclassvars != 0) {
2850 		ctrl->classvars = ALLOC(char, ctrl->nclassvars * 3);
2851 		(*readv)(ctrl->classvars, ctrl->sectors,
2852 			 ctrl->nclassvars * (Uint) 3, size);
2853 		size += ctrl->nclassvars * (Uint) 3;
2854 	    }
2855 	}
2856 
2857 	if (header.nfuncalls != 0) {
2858 	    /* function calls */
2859 	    ctrl->funcalls = ALLOC(char, 2 * header.nfuncalls);
2860 	    (*readv)(ctrl->funcalls, ctrl->sectors, header.nfuncalls * (Uint) 2,
2861 		     size);
2862 	    size += header.nfuncalls * (Uint) 2;
2863 	}
2864 
2865 	if (header.nsymbols != 0) {
2866 	    /* symbol table */
2867 	    ctrl->symbols = ALLOC(dsymbol, header.nsymbols);
2868 	    size += d_conv((char *) ctrl->symbols, ctrl->sectors, DSYM_LAYOUT,
2869 			   (Uint) header.nsymbols, size, readv);
2870 	}
2871 
2872 	if (header.nvariables > UCHAR(header.nvardefs)) {
2873 	    /* variable types */
2874 	    if (conv_ctrl2) {
2875 		ctrl_mkvtypes(ctrl);
2876 	    } else {
2877 		ctrl->vtypes = ALLOC(char, header.nvariables -
2878 					   UCHAR(header.nvardefs));
2879 		(*readv)(ctrl->vtypes, ctrl->sectors,
2880 			 header.nvariables - UCHAR(header.nvardefs), size);
2881 	    }
2882 	}
2883 
2884 	if (conv_inherit) {
2885 	    obj->ctrl = ctrl;
2886 	    ctrl_convert(ctrl);
2887 	    ctrl->flags |= CTRL_CONVERTED;
2888 	}
2889 	if (ctrl->flags & CTRL_CONVERTED) {
2890 	    if (header.ninherits > 1) {
2891 		ctrl->progindex = 1;
2892 	    }
2893 	} else {
2894 	    ctrl->progindex = header.ninherits - 1;
2895 	}
2896     }
2897 
2898     return ctrl;
2899 }
2900 
2901 /*
2902  * NAME:	data->copy_osvalues()
2903  * DESCRIPTION:	copy osvalues to svalues
2904  */
d_copy_osvalues(svalue * sv,osvalue * osv,Uint n)2905 static void d_copy_osvalues(svalue *sv, osvalue *osv, Uint n)
2906 {
2907     while (n > 0) {
2908 	sv->type = osv->type;
2909 	sv->pad = '\0';
2910 	sv->oindex = osv->oindex;
2911 	(sv++)->u.objcnt = (osv++)->objcnt;
2912 	--n;
2913     }
2914 }
2915 
2916 /*
2917  * NAME:	data->copy_oosvalues()
2918  * DESCRIPTION:	copy oosvalues to svalues
2919  */
d_copy_oosvalues(svalue * sv,oosvalue * oosv,Uint n)2920 static void d_copy_oosvalues(svalue *sv, oosvalue *oosv, Uint n)
2921 {
2922     while (n > 0) {
2923 	sv->type = oosv->type;
2924 	sv->pad = '\0';
2925 	sv->oindex = oosv->oindex;
2926 	(sv++)->u.objcnt = (oosv++)->objcnt;
2927 	--n;
2928     }
2929 }
2930 
2931 /*
2932  * NAME:	data->conv_osvalues()
2933  * DESCRIPTION:	convert old svalues
2934  */
d_conv_osvalues(svalue * sv,sector * s,Uint n,Uint size)2935 static Uint d_conv_osvalues(svalue *sv, sector *s, Uint n, Uint size)
2936 {
2937     osvalue *osv;
2938 
2939     osv = ALLOCA(osvalue, n);
2940     size = d_conv((char *) osv, s, osv_layout, n, size, &sw_conv);
2941     d_copy_osvalues(sv, osv, n);
2942     AFREE(osv);
2943     return size;
2944 }
2945 
2946 /*
2947  * NAME:	data->conv_oosvalues()
2948  * DESCRIPTION:	convert old old svalues
2949  */
d_conv_oosvalues(svalue * sv,sector * s,Uint n,Uint size)2950 static Uint d_conv_oosvalues(svalue *sv, sector *s, Uint n, Uint size)
2951 {
2952     oosvalue *oosv;
2953 
2954     oosv = ALLOCA(oosvalue, n);
2955     size = d_conv((char *) oosv, s, oosv_layout, n, size, &sw_conv);
2956     d_copy_oosvalues(sv, oosv, n);
2957     AFREE(oosv);
2958     return size;
2959 }
2960 
2961 /*
2962  * NAME:	data->conv_osarrays()
2963  * DESCRIPTION:	convert old sarrays
2964  */
d_conv_osarrays(sarray * sa,sector * s,Uint n,Uint size)2965 static Uint d_conv_osarrays(sarray *sa, sector *s, Uint n, Uint size)
2966 {
2967     osarray *osa;
2968     Uint i;
2969 
2970     osa = ALLOCA(osarray, n);
2971     size = d_conv((char *) osa, s, osa_layout, n, size, &sw_conv);
2972     for (i = 0; i < n; i++) {
2973 	sa->index = osa->index;
2974 	sa->type = 0;	/* filled in later */
2975 	sa->size = osa->size;
2976 	sa->ref = osa->ref;
2977 	(sa++)->tag = (osa++)->tag;
2978     }
2979     AFREE(osa - n);
2980     return size;
2981 }
2982 
2983 /*
2984  * NAME:	data->fixobjs()
2985  * DESCRIPTION:	fix objects in dataspace
2986  */
d_fixobjs(svalue * v,Uint n,Uint * ctab,uindex nobjects)2987 static void d_fixobjs(svalue *v, Uint n, Uint *ctab, uindex nobjects)
2988 {
2989     while (n != 0) {
2990 	if (v->type == T_OBJECT) {
2991 	    if (v->oindex < nobjects && v->u.objcnt == ctab[v->oindex] && OBJ(v->oindex)->count != 0) {
2992 		/* fix object count */
2993 		v->u.objcnt = OBJ(v->oindex)->count;
2994 	    } else {
2995 		/* destructed object; mark as invalid */
2996 		v->oindex = 0;
2997 		v->u.objcnt = 1;
2998 	    }
2999 	}
3000 	v++;
3001 	--n;
3002     }
3003 }
3004 
3005 /*
3006  * NAME:	data->fixdata()
3007  * DESCRIPTION:	fix a dataspace
3008  */
d_fixdata(dataspace * data,Uint * counttab,uindex nobjects)3009 static void d_fixdata(dataspace *data, Uint *counttab, uindex nobjects)
3010 {
3011     scallout *sco;
3012     unsigned int n;
3013 
3014     d_fixobjs(data->svariables, (Uint) data->nvariables, counttab, nobjects);
3015     d_fixobjs(data->selts, data->eltsize, counttab, nobjects);
3016     for (n = data->ncallouts, sco = data->scallouts; n > 0; --n, sco++) {
3017 	if (sco->val[0].type == T_STRING) {
3018 	    if (sco->nargs > 3) {
3019 		d_fixobjs(sco->val, (Uint) 4, counttab, nobjects);
3020 	    } else {
3021 		d_fixobjs(sco->val, sco->nargs + (Uint) 1, counttab, nobjects);
3022 	    }
3023 	}
3024     }
3025 }
3026 
3027 /*
3028  * NAME:	data->conv_datapace()
3029  * DESCRIPTION:	convert dataspace
3030  */
d_conv_dataspace(object * obj,Uint * counttab,void (* readv)(char *,sector *,Uint,Uint))3031 static dataspace *d_conv_dataspace(object *obj, Uint *counttab,
3032 				   void (*readv) (char*, sector*, Uint, Uint))
3033 {
3034     sdataspace header;
3035     dataspace *data;
3036     Uint size;
3037     unsigned int n;
3038 
3039     UNREFERENCED_PARAMETER(counttab);
3040 
3041     data = d_alloc_dataspace(obj);
3042 
3043     /*
3044      * restore from snapshot
3045      */
3046     size = d_conv((char *) &header, &obj->dfirst, sd_layout, (Uint) 1,
3047 		  (Uint) 0, readv);
3048     data->nvariables = header.nvariables;
3049     data->narrays = header.narrays;
3050     data->eltsize = header.eltsize;
3051     data->nstrings = header.nstrings;
3052     data->strsize = header.strsize;
3053     data->ncallouts = header.ncallouts;
3054     data->fcallouts = header.fcallouts;
3055 
3056     /* sectors */
3057     data->sectors = ALLOC(sector, data->nsectors = header.nsectors);
3058     data->sectors[0] = obj->dfirst;
3059     for (n = 0; n < header.nsectors; n++) {
3060 	size += d_conv((char *) (data->sectors + n), data->sectors, "d",
3061 		       (Uint) 1, size, readv);
3062     }
3063 
3064     /* variables */
3065     data->svariables = ALLOC(svalue, header.nvariables);
3066     if (conv_data) {
3067 	size += d_conv_oosvalues(data->svariables, data->sectors,
3068 				 (Uint) header.nvariables, size);
3069     } else if (conv_type) {
3070 	size += d_conv_osvalues(data->svariables, data->sectors,
3071 				(Uint) header.nvariables, size);
3072     } else {
3073 	size += d_conv((char *) data->svariables, data->sectors, sv_layout,
3074 		       (Uint) header.nvariables, size, readv);
3075     }
3076 
3077     if (header.narrays != 0) {
3078 	/* arrays */
3079 	data->sarrays = ALLOC(sarray, header.narrays);
3080 	if (conv_type) {
3081 	    size += d_conv_osarrays(data->sarrays, data->sectors,
3082 				    header.narrays, size);
3083 	} else {
3084 	    size += d_conv((char *) data->sarrays, data->sectors, sa_layout,
3085 			   header.narrays, size, readv);
3086 	}
3087 	if (header.eltsize != 0) {
3088 	    data->selts = ALLOC(svalue, header.eltsize);
3089 	    if (conv_data) {
3090 		size += d_conv_oosvalues(data->selts, data->sectors,
3091 					 header.eltsize, size);
3092 	    } else if (conv_type) {
3093 		size += d_conv_osvalues(data->selts, data->sectors,
3094 					header.eltsize, size);
3095 	    } else {
3096 		size += d_conv((char *) data->selts, data->sectors, sv_layout,
3097 			       header.eltsize, size, readv);
3098 	    }
3099 	}
3100     }
3101 
3102     if (header.nstrings != 0) {
3103 	/* strings */
3104 	data->sstrings = ALLOC(sstring, header.nstrings);
3105 	size += d_conv((char *) data->sstrings, data->sectors, ss_layout,
3106 		       header.nstrings, size, readv);
3107 	if (header.strsize != 0) {
3108 	    if (header.flags & CMP_TYPE) {
3109 		data->stext = decompress(data->sectors, readv, header.strsize,
3110 					 size, &data->strsize);
3111 	    } else {
3112 		data->stext = ALLOC(char, header.strsize);
3113 		(*readv)(data->stext, data->sectors, header.strsize, size);
3114 	    }
3115 	    size += header.strsize;
3116 	}
3117     }
3118 
3119     if (header.ncallouts != 0) {
3120 	scallout *sco;
3121 	unsigned short dummy;
3122 
3123 	/* callouts */
3124 	co_time(&dummy);
3125 	sco = data->scallouts = ALLOC(scallout, header.ncallouts);
3126 	if (conv_co1) {
3127 	    oscallout *osc;
3128 
3129 	    /*
3130 	     * convert old format callouts
3131 	     */
3132 	    osc = ALLOCA(oscallout, header.ncallouts);
3133 	    d_conv((char *) osc, data->sectors, osc_layout,
3134 		   (Uint) header.ncallouts, size, readv);
3135 	    for (n = data->ncallouts; n > 0; --n) {
3136 		if (osc->time >> 24 == 1) {
3137 		    sco->time = co_decode(osc->time, &sco->mtime);
3138 		} else {
3139 		    sco->time = osc->time;
3140 		    sco->mtime = 0xffff;
3141 		}
3142 		sco->htime = 0;
3143 		sco->nargs = osc->nargs;
3144 		d_copy_oosvalues(sco->val, osc->val, 4);
3145 		sco++;
3146 		osc++;
3147 	    }
3148 	    sco -= data->ncallouts;
3149 	    AFREE(osc - data->ncallouts);
3150 	} else if (conv_data) {
3151 	    socallout *soc;
3152 
3153 	    /*
3154 	     * convert callouts with old format svalues
3155 	     */
3156 	    soc = ALLOCA(socallout, header.ncallouts);
3157 	    d_conv((char *) soc, data->sectors, soc_layout,
3158 		   (Uint) header.ncallouts, size, readv);
3159 	    for (n = data->ncallouts; n > 0; --n) {
3160 		if (soc->time >> 24 == 1) {
3161 		    sco->time = co_decode(soc->time, &sco->mtime);
3162 		} else {
3163 		    sco->time = soc->time;
3164 		    sco->mtime = 0xffff;
3165 		}
3166 		sco->htime = 0;
3167 		sco->nargs = soc->nargs;
3168 		d_copy_oosvalues(sco->val, soc->val, 4);
3169 		sco++;
3170 		soc++;
3171 	    }
3172 	    sco -= data->ncallouts;
3173 	    AFREE(soc - data->ncallouts);
3174 	} else if (conv_co2) {
3175 	    calloutos *cos;
3176 
3177 	    /*
3178 	     * convert callouts with encoded millitimes
3179 	     */
3180 	    cos = ALLOCA(calloutos, header.ncallouts);
3181 	    d_conv((char *) cos, data->sectors, cos_layout,
3182 		   (Uint) header.ncallouts, size, readv);
3183 	    for (n = data->ncallouts; n > 0; --n) {
3184 		if (cos->time >> 24 == 1) {
3185 		    sco->time = co_decode(cos->time, &sco->mtime);
3186 		} else {
3187 		    sco->time = cos->time;
3188 		    sco->mtime = 0xffff;
3189 		}
3190 		sco->htime = 0;
3191 		sco->nargs = cos->nargs;
3192 		d_copy_osvalues(sco->val, cos->val, 4);
3193 		sco++;
3194 		cos++;
3195 	    }
3196 	    sco -= data->ncallouts;
3197 	    AFREE(cos - data->ncallouts);
3198 	} else if (conv_type) {
3199 	    calloutso *cso;
3200 
3201 	    /*
3202 	     * convert callouts with encoded millitimes
3203 	     */
3204 	    cso = ALLOCA(calloutso, header.ncallouts);
3205 	    d_conv((char *) cso, data->sectors, cso_layout,
3206 		   (Uint) header.ncallouts, size, readv);
3207 	    for (n = data->ncallouts; n > 0; --n) {
3208 		sco->time = cso->time;
3209 		sco->htime = 0;
3210 		sco->mtime = cso->mtime;
3211 		sco->nargs = cso->nargs;
3212 		d_copy_osvalues(sco->val, cso->val, 4);
3213 		sco++;
3214 		cso++;
3215 	    }
3216 	    sco -= data->ncallouts;
3217 	    AFREE(cso - data->ncallouts);
3218 	} else if (conv_time) {
3219 	    register tscallout *tco;
3220 
3221 	    /*
3222 	     * convert callouts without htime
3223 	     */
3224 	    tco = ALLOCA(tscallout, header.ncallouts);
3225 	    d_conv((char *) tco, data->sectors, tco_layout,
3226 		   (Uint) header.ncallouts, size, readv);
3227 	    for (n = data->ncallouts; n > 0; --n) {
3228 		sco->time = tco->time;
3229 		sco->htime = 0;
3230 		sco->mtime = tco->mtime;
3231 		sco->nargs = tco->nargs;
3232 		memcpy(sco->val, tco->val, 4 * sizeof(svalue));
3233 		sco++;
3234 		tco++;
3235 	    }
3236 	    sco -= data->ncallouts;
3237 	    AFREE(tco - data->ncallouts);
3238 
3239 	} else {
3240 	    d_conv((char *) data->scallouts, data->sectors, sco_layout,
3241 		   (Uint) header.ncallouts, size, readv);
3242 	}
3243     }
3244 
3245     data->ctrl = o_control(obj);
3246     data->ctrl->ndata++;
3247 
3248     return data;
3249 }
3250 
3251 /*
3252  * NAME:	data->restore_ctrl()
3253  * DESCRIPTION:	restore a control block
3254  */
d_restore_ctrl(object * obj,void (* readv)(char *,sector *,Uint,Uint))3255 control *d_restore_ctrl(object *obj, void (*readv) (char*, sector*, Uint, Uint))
3256 {
3257     control *ctrl;
3258 
3259     ctrl = (control *) NULL;
3260     if (obj->flags & O_COMPILED) {
3261 	ctrl = d_new_control();
3262 	ctrl->oindex = obj->index;
3263 	obj->ctrl = ctrl;
3264 	pc_control(ctrl, obj);
3265 	ctrl->flags |= CTRL_COMPILED;
3266     } else if (obj->cfirst != SW_UNUSED) {
3267 	if (!converted) {
3268 	    ctrl = d_conv_control(obj, readv);
3269 	} else {
3270 	    ctrl = load_control(obj, readv);
3271 	    if (ctrl->vmapsize == 0) {
3272 		get_prog(ctrl, readv);
3273 		get_strconsts(ctrl, readv);
3274 		get_funcdefs(ctrl, readv);
3275 		get_vardefs(ctrl, readv);
3276 		get_funcalls(ctrl, readv);
3277 		get_symbols(ctrl, readv);
3278 		get_vtypes(ctrl, readv);
3279 	    }
3280 	}
3281 	d_save_control(ctrl);
3282 	obj->ctrl = ctrl;
3283     }
3284 
3285     return ctrl;
3286 }
3287 
3288 /*
3289  * NAME:	data->restore_data()
3290  * DESCRIPTION:	restore a dataspace
3291  */
d_restore_data(object * obj,Uint * counttab,uindex nobjects,void (* readv)(char *,sector *,Uint,Uint))3292 dataspace *d_restore_data(object *obj, Uint *counttab, uindex nobjects,
3293 			  void (*readv) (char*, sector*, Uint, Uint))
3294 {
3295     dataspace *data;
3296 
3297     data = (dataspace *) NULL;
3298     if (OBJ(obj->index)->count != 0 && OBJ(obj->index)->dfirst != SW_UNUSED) {
3299 	if (!converted) {
3300 	    data = d_conv_dataspace(obj, counttab, readv);
3301 	} else {
3302 	    data = load_dataspace(obj, readv);
3303 	    get_variables(data, readv);
3304 	    get_arrays(data, readv);
3305 	    get_elts(data, readv);
3306 	    get_strings(data, readv);
3307 	    get_callouts(data, readv);
3308 	}
3309 	obj->data = data;
3310 	if (counttab != (Uint *) NULL) {
3311 	    d_fixdata(data, counttab, nobjects);
3312 	}
3313 
3314 	if (!(obj->flags & O_MASTER) &&
3315 	    obj->update != OBJ(obj->u_master)->update) {
3316 	    /* handle object upgrading right away */
3317 	    d_upgrade_clone(data);
3318 	}
3319 	data->base.flags |= MOD_ALL;
3320     }
3321 
3322     return data;
3323 }
3324 
3325 /*
3326  * NAME:	data->restore_obj()
3327  * DESCRIPTION:	restore an object
3328  */
d_restore_obj(object * obj,Uint * counttab,uindex nobjects,bool cactive,bool dactive)3329 void d_restore_obj(object *obj, Uint *counttab, uindex nobjects, bool cactive, bool dactive)
3330 {
3331     control *ctrl;
3332     dataspace *data;
3333 
3334     if (!converted) {
3335 	ctrl = d_restore_ctrl(obj, sw_conv);
3336 	data = d_restore_data(obj, counttab, nobjects, sw_conv);
3337     } else {
3338 	ctrl = d_restore_ctrl(obj, sw_dreadv);
3339 	data = d_restore_data(obj, counttab, nobjects, sw_dreadv);
3340     }
3341 
3342     if (!cactive) {
3343 	/* swap this out first */
3344 	if (ctrl != (control *) NULL && ctrl != ctail) {
3345 	    if (chead == ctrl) {
3346 		chead = ctrl->next;
3347 		chead->prev = (control *) NULL;
3348 	    } else {
3349 		ctrl->prev->next = ctrl->next;
3350 		ctrl->next->prev = ctrl->prev;
3351 	    }
3352 	    ctail->next = ctrl;
3353 	    ctrl->prev = ctail;
3354 	    ctrl->next = (control *) NULL;
3355 	    ctail = ctrl;
3356 	}
3357     }
3358     if (!dactive) {
3359 	/* swap this out first */
3360 	if (data != (dataspace *) NULL && data != dtail) {
3361 	    if (dhead == data) {
3362 		dhead = data->next;
3363 		dhead->prev = (dataspace *) NULL;
3364 	    } else {
3365 		data->prev->next = data->next;
3366 		data->next->prev = data->prev;
3367 	    }
3368 	    dtail->next = data;
3369 	    data->prev = dtail;
3370 	    data->next = (dataspace *) NULL;
3371 	    dtail = data;
3372 	}
3373     }
3374 }
3375 
3376 /*
3377  * NAME:	data->converted()
3378  * DESCRIPTION:	snapshot conversion is complete
3379  */
d_converted()3380 void d_converted()
3381 {
3382     converted = TRUE;
3383 }
3384 
3385 /*
3386  * NAME:	data->free_control()
3387  * DESCRIPTION:	remove the control block from memory
3388  */
d_free_control(control * ctrl)3389 void d_free_control(control *ctrl)
3390 {
3391     string **strs;
3392     unsigned short i;
3393 
3394     /* delete strings */
3395     if (ctrl->strings != (string **) NULL) {
3396 	strs = ctrl->strings;
3397 	for (i = ctrl->nstrings; i > 0; --i) {
3398 	    if (*strs != (string *) NULL) {
3399 		str_del(*strs);
3400 	    }
3401 	    strs++;
3402 	}
3403 	FREE(ctrl->strings);
3404     }
3405     if (ctrl->cvstrings != (string **) NULL) {
3406 	strs = ctrl->cvstrings;
3407 	for (i = ctrl->nvardefs; i > 0; --i) {
3408 	    if (*strs != (string *) NULL) {
3409 		str_del(*strs);
3410 	    }
3411 	    strs++;
3412 	}
3413 	FREE(ctrl->cvstrings);
3414     }
3415 
3416     /* delete vmap */
3417     if (ctrl->vmap != (unsigned short *) NULL) {
3418 	FREE(ctrl->vmap);
3419     }
3420 
3421     if (!(ctrl->flags & CTRL_COMPILED)) {
3422 	/* delete sectors */
3423 	if (ctrl->sectors != (sector *) NULL) {
3424 	    FREE(ctrl->sectors);
3425 	}
3426 
3427 	if (ctrl->inherits != (dinherit *) NULL) {
3428 	    /* delete inherits */
3429 	    FREE(ctrl->inherits);
3430 	}
3431 
3432 	if (ctrl->prog != (char *) NULL) {
3433 	    FREE(ctrl->prog);
3434 	}
3435 
3436 	/* delete inherit indices */
3437 	if (ctrl->imap != (char *) NULL) {
3438 	    FREE(ctrl->imap);
3439 	}
3440 
3441 	/* delete string constants */
3442 	if (ctrl->sstrings != (dstrconst *) NULL) {
3443 	    FREE(ctrl->sstrings);
3444 	}
3445 	if (ctrl->stext != (char *) NULL) {
3446 	    FREE(ctrl->stext);
3447 	}
3448 
3449 	/* delete function definitions */
3450 	if (ctrl->funcdefs != (dfuncdef *) NULL) {
3451 	    FREE(ctrl->funcdefs);
3452 	}
3453 
3454 	/* delete variable definitions */
3455 	if (ctrl->vardefs != (dvardef *) NULL) {
3456 	    FREE(ctrl->vardefs);
3457 	    if (ctrl->classvars != (char *) NULL) {
3458 		FREE(ctrl->classvars);
3459 	    }
3460 	}
3461 
3462 	/* delete function call table */
3463 	if (ctrl->funcalls != (char *) NULL) {
3464 	    FREE(ctrl->funcalls);
3465 	}
3466 
3467 	/* delete symbol table */
3468 	if (ctrl->symbols != (dsymbol *) NULL) {
3469 	    FREE(ctrl->symbols);
3470 	}
3471 
3472 	/* delete variable types */
3473 	if (ctrl->vtypes != (char *) NULL) {
3474 	    FREE(ctrl->vtypes);
3475 	}
3476     }
3477 
3478     if (ctrl != chead) {
3479 	ctrl->prev->next = ctrl->next;
3480     } else {
3481 	chead = ctrl->next;
3482 	if (chead != (control *) NULL) {
3483 	    chead->prev = (control *) NULL;
3484 	}
3485     }
3486     if (ctrl != ctail) {
3487 	ctrl->next->prev = ctrl->prev;
3488     } else {
3489 	ctail = ctrl->prev;
3490 	if (ctail != (control *) NULL) {
3491 	    ctail->next = (control *) NULL;
3492 	}
3493     }
3494     --nctrl;
3495 
3496     FREE(ctrl);
3497 }
3498 
3499 /*
3500  * NAME:	data->free_dataspace()
3501  * DESCRIPTION:	remove the dataspace block from memory
3502  */
d_free_dataspace(dataspace * data)3503 void d_free_dataspace(dataspace *data)
3504 {
3505     /* free values */
3506     d_free_values(data);
3507 
3508     /* delete sectors */
3509     if (data->sectors != (sector *) NULL) {
3510 	FREE(data->sectors);
3511     }
3512 
3513     /* free scallouts */
3514     if (data->scallouts != (scallout *) NULL) {
3515 	FREE(data->scallouts);
3516     }
3517 
3518     /* free sarrays */
3519     if (data->sarrays != (sarray *) NULL) {
3520 	if (data->selts != (svalue *) NULL) {
3521 	    FREE(data->selts);
3522 	}
3523 	FREE(data->sarrays);
3524     }
3525 
3526     /* free sstrings */
3527     if (data->sstrings != (sstring *) NULL) {
3528 	if (data->stext != (char *) NULL) {
3529 	    FREE(data->stext);
3530 	}
3531 	FREE(data->sstrings);
3532     }
3533 
3534     /* free svariables */
3535     if (data->svariables != (svalue *) NULL) {
3536 	FREE(data->svariables);
3537     }
3538 
3539     if (data->ctrl != (control *) NULL) {
3540 	data->ctrl->ndata--;
3541     }
3542 
3543     if (data != dhead) {
3544 	data->prev->next = data->next;
3545     } else {
3546 	dhead = data->next;
3547 	if (dhead != (dataspace *) NULL) {
3548 	    dhead->prev = (dataspace *) NULL;
3549 	}
3550     }
3551     if (data != dtail) {
3552 	data->next->prev = data->prev;
3553     } else {
3554 	dtail = data->prev;
3555 	if (dtail != (dataspace *) NULL) {
3556 	    dtail->next = (dataspace *) NULL;
3557 	}
3558     }
3559     data->gcprev->gcnext = data->gcnext;
3560     data->gcnext->gcprev = data->gcprev;
3561     if (data == gcdata) {
3562 	gcdata = (data != data->gcnext) ? data->gcnext : (dataspace *) NULL;
3563     }
3564     --ndata;
3565 
3566     FREE(data);
3567 }
3568