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