|
|
1 # define INCLUDE_FILE_IO
2 # include "dgd.h"
3 # include "str.h"
4 # include "array.h"
5 # include "object.h"
6 # include "xfloat.h"
7 # include "interpret.h"
8 # include "data.h"
9 # include "path.h"
10 # include "editor.h"
11 # include "call_out.h"
12 # include "comm.h"
13 # include "version.h"
14 # include "macro.h"
15 # include "token.h"
16 # include "ppcontrol.h"
17 # include "node.h"
18 # include "parser.h"
19 # include "compile.h"
20 # include "csupport.h"
21 # include "table.h"
22
23 typedef struct {
24 char *name; /* name of the option */
25 short type; /* option type */
26 bool resolv; /* TRUE if path name must be resolved */
27 bool set; /* TRUE if option is set */
28 Uint low, high; /* lower and higher bound, for numeric values */
29 union {
30 long num; /* numeric value */
31 char *str; /* string value */
32 } u;
33 } config;
34
35 static config conf[] = {
36 # define ARRAY_SIZE 0
37 { "array_size", INT_CONST, FALSE, FALSE,
38 1, USHRT_MAX / 2 },
39 # define AUTO_OBJECT 1
40 { "auto_object", STRING_CONST, TRUE },
41 # define BINARY_PORT 2
42 { "binary_port", INT_CONST, FALSE, FALSE,
43 0, USHRT_MAX },
44 # define CACHE_SIZE 3
45 { "cache_size", INT_CONST, FALSE, FALSE,
46 2, UINDEX_MAX },
47 # define CALL_OUTS 4
48 { "call_outs", INT_CONST, FALSE, FALSE,
49 0, UINDEX_MAX - 1 },
50 # define CREATE 5
51 { "create", STRING_CONST, FALSE },
52 # define DIRECTORY 6
53 { "directory", STRING_CONST, FALSE },
54 # define DRIVER_OBJECT 7
55 { "driver_object", STRING_CONST, TRUE },
56 # define DUMP_FILE 8
57 { "dump_file", STRING_CONST, FALSE },
58 # define DYNAMIC_CHUNK 9
59 { "dynamic_chunk", INT_CONST, FALSE },
60 # define ED_TMPFILE 10
61 { "ed_tmpfile", STRING_CONST, FALSE },
62 # define EDITORS 11
63 { "editors", INT_CONST, FALSE, FALSE,
64 0, EINDEX_MAX },
65 # define INCLUDE_DIRS 12
66 { "include_dirs", '(', FALSE },
67 # define INCLUDE_FILE 13
68 { "include_file", STRING_CONST, TRUE },
69 # define OBJECTS 14
70 { "objects", INT_CONST, FALSE, FALSE,
71 2, UINDEX_MAX },
72 # define SECTOR_SIZE 15
73 { "sector_size", INT_CONST, FALSE, FALSE,
74 512, 8192 },
75 # define STATIC_CHUNK 16
76 { "static_chunk", INT_CONST, FALSE },
77 # define SWAP_FILE 17
78 { "swap_file", STRING_CONST, FALSE },
79 # define SWAP_FRAGMENT 18
80 { "swap_fragment", INT_CONST, FALSE, FALSE,
81 0, SW_UNUSED },
82 # define SWAP_SIZE 19
83 { "swap_size", INT_CONST, FALSE, FALSE,
84 1024, SW_UNUSED },
85 # define TELNET_PORT 20
86 { "telnet_port", INT_CONST, FALSE, FALSE,
87 0, USHRT_MAX },
88 # define TYPECHECKING 21
89 { "typechecking", INT_CONST, FALSE, FALSE,
90 0, 2 },
91 # define USERS 22
92 { "users", INT_CONST, FALSE, FALSE,
93 1, EINDEX_MAX },
94 # define NR_OPTIONS 23
95 };
96
97
98 typedef struct { char fill; char c; } alignc;
99 typedef struct { char fill; short s; } aligns;
100 typedef struct { char fill; Int i; } aligni;
101 typedef struct { char fill; char *p; } alignp;
102 typedef struct { char c; } alignz;
103
104 typedef char dumpinfo[28];
105
106 # define FORMAT_VERSION 2
107
108 # define DUMP_VALID 0 /* valud dump flag */
109 # define DUMP_VERSION 1 /* dump file version number */
110 # define DUMP_DRIVER 2 /* 0: vanilla DGD, 1: iChat DGD */
111 # define DUMP_TYPECHECK 3 /* global typechecking */
112 # define DUMP_SECSIZE 4 /* sector size */
113 # define DUMP_TYPE 4 /* first XX bytes, dump type */
114 # define DUMP_STARTTIME 20 /* start time */
115 # define DUMP_ELAPSED 24 /* elapsed time */
116
117 static dumpinfo header; /* dumpfile header */
118 # define s0 (header[ 6]) /* short, msb */
119 # define s1 (header[ 7]) /* short, lsb */
120 # define i0 (header[ 8]) /* Int, msb */
121 # define i1 (header[ 9])
122 # define i2 (header[10])
123 # define i3 (header[11]) /* Int, lsb */
124 # define utsize (header[12]) /* sizeof(uindex) + sizeof(ssizet) */
125 # define desize (header[13]) /* sizeof(sector) + sizeof(eindex) */
126 # define psize (header[14]) /* sizeof(char*) */
127 # define calign (header[15]) /* align(char) */
128 # define salign (header[16]) /* align(short) */
129 # define ialign (header[17]) /* align(Int) */
130 # define palign (header[18]) /* align(char*) */
131 # define zalign (header[19]) /* align(struct) */
132 static int ualign; /* align(uindex) */
133 static int talign; /* align(ssizet) */
134 static int dalign; /* align(sector) */
135 static int ealign; /* align(eindex) */
136 static dumpinfo rheader; /* restored header */
137 # define rs0 (rheader[ 6]) /* short, msb */
138 # define rs1 (rheader[ 7]) /* short, lsb */
139 # define ri0 (rheader[ 8]) /* Int, msb */
140 # define ri1 (rheader[ 9])
141 # define ri2 (rheader[10])
142 # define ri3 (rheader[11]) /* Int, lsb */
143 # define rutsize (rheader[12]) /* sizeof(uindex) + sizeof(ssizet) */
144 # define rdesize (rheader[13]) /* sizeof(sector) + sizeof(eindex) */
145 # define rpsize (rheader[14]) /* sizeof(char*) */
146 # define rcalign (rheader[15]) /* align(char) */
147 # define rsalign (rheader[16]) /* align(short) */
148 # define rialign (rheader[17]) /* align(Int) */
149 # define rpalign (rheader[18]) /* align(char*) */
150 # define rzalign (rheader[19]) /* align(struct) */
151 static int rusize; /* sizeof(uindex) */
152 static int rtsize; /* sizeof(ssizet) */
153 static int rdsize; /* sizeof(sector) */
154 static int resize; /* sizeof(eindex) */
155 static int rualign; /* align(uindex) */
156 static int rtalign; /* align(ssizet) */
157 static int rdalign; /* align(sector) */
158 static int realign; /* align(eindex) */
159 static Uint starttime; /* start time */
160 static Uint elapsed; /* elapsed time */
161 static Uint boottime; /* boot time */
162
163 /*
164 * NAME: conf->dumpinit()
165 * DESCRIPTION: initialize dump file information
166 */
167 static void conf_dumpinit()
168 {
169 short s;
170 Int i;
171 alignc cdummy;
172 aligns sdummy;
173 aligni idummy;
174 alignp pdummy;
175
176 header[DUMP_VALID] = TRUE; /* valid dump flag */
177 header[DUMP_VERSION] = FORMAT_VERSION; /* dump file version number */
178 header[DUMP_DRIVER] = 0; /* vanilla DGD */
179 header[DUMP_TYPECHECK] = conf[TYPECHECKING].u.num;
180 header[DUMP_SECSIZE + 0] = conf[SECTOR_SIZE].u.num >> 8;
181 header[DUMP_SECSIZE + 1] = conf[SECTOR_SIZE].u.num;
182
183 starttime = boottime = P_time();
184
185 s = 0x1234;
186 i = 0x12345678L;
187 s0 = strchr((char *) &s, 0x12) - (char *) &s;
188 s1 = strchr((char *) &s, 0x34) - (char *) &s;
189 i0 = strchr((char *) &i, 0x12) - (char *) &i;
190 i1 = strchr((char *) &i, 0x34) - (char *) &i;
191 i2 = strchr((char *) &i, 0x56) - (char *) &i;
192 i3 = strchr((char *) &i, 0x78) - (char *) &i;
193 utsize = sizeof(uindex) | (sizeof(ssizet) << 4);
194 desize = sizeof(sector) | (sizeof(eindex) << 4);
195 psize = sizeof(char*);
196 calign = (char *) &cdummy.c - (char *) &cdummy.fill;
197 salign = (char *) &sdummy.s - (char *) &sdummy.fill;
198 ialign = (char *) &idummy.i - (char *) &idummy.fill;
199 palign = (char *) &pdummy.p - (char *) &pdummy.fill;
200 zalign = sizeof(alignz);
201
202 ualign = (sizeof(uindex) == sizeof(short)) ? salign : ialign;
203 talign = (sizeof(ssizet) == sizeof(short)) ? salign : ialign;
204 dalign = (sizeof(sector) == sizeof(short)) ? salign : ialign;
205 switch (sizeof(eindex)) {
206 case sizeof(char): ealign = calign; break;
207 case sizeof(short): ealign = salign; break;
208 case sizeof(Int): ealign = ialign; break;
209 }
210 }
211
212 /*
213 * NAME: conf->dump()
214 * DESCRIPTION: dump system state on file
215 */
216 void conf_dump()
217 {
218 int fd;
219 Uint etime;
220
221 header[DUMP_TYPECHECK] = conf[TYPECHECKING].u.num;
222 header[DUMP_STARTTIME + 0] = starttime >> 24;
223 header[DUMP_STARTTIME + 1] = starttime >> 16;
224 header[DUMP_STARTTIME + 2] = starttime >> 8;
225 header[DUMP_STARTTIME + 3] = starttime;
226 etime = elapsed + P_time() - boottime;
227 header[DUMP_ELAPSED + 0] = etime >> 24;
228 header[DUMP_ELAPSED + 1] = etime >> 16;
229 header[DUMP_ELAPSED + 2] = etime >> 8;
230 header[DUMP_ELAPSED + 3] = etime;
231
232 fd = sw_dump(conf[DUMP_FILE].u.str);
233 if (!kf_dump(fd)) {
234 fatal("failed to dump kfun table");
235 }
236 if (!o_dump(fd)) {
237 fatal("failed to dump object table");
238 }
239 if (!pc_dump(fd)) {
240 fatal("failed to dump precompiled objects");
241 }
242 if (!co_dump(fd)) {
243 fatal("failed to dump callout table");
244 }
245
246 P_lseek(fd, 0L, SEEK_SET);
247 P_write(fd, header, sizeof(dumpinfo));
248 }
249
250 /*
251 * NAME: conf->restore()
252 * DESCRIPTION: restore system state from file
253 */
254 static void conf_restore(fd)
255 int fd;
256 {
257 unsigned int secsize;
258 long posn;
259
260 if (P_read(fd, rheader, sizeof(dumpinfo)) != sizeof(dumpinfo) ||
261 memcmp(header, rheader, DUMP_TYPE) != 0) {
262 error("Bad or incompatible restore file header");
263 }
264
265 starttime = (UCHAR(rheader[DUMP_STARTTIME + 0]) << 24) |
266 (UCHAR(rheader[DUMP_STARTTIME + 1]) << 16) |
267 (UCHAR(rheader[DUMP_STARTTIME + 2]) << 8) |
268 UCHAR(rheader[DUMP_STARTTIME + 3]);
269 elapsed = (UCHAR(rheader[DUMP_ELAPSED + 0]) << 24) |
270 (UCHAR(rheader[DUMP_ELAPSED + 1]) << 16) |
271 (UCHAR(rheader[DUMP_ELAPSED + 2]) << 8) |
272 UCHAR(rheader[DUMP_ELAPSED + 3]);
273 rusize = rutsize & 0xf;
274 rtsize = rutsize >> 4;
275 if (rtsize == 0) {
276 rtsize = sizeof(unsigned short); /* backward compat */
277 }
278 rdsize = rdesize & 0xf;
279 resize = rdesize >> 4;
280 if (resize == 0) {
281 resize = sizeof(char); /* backward compat */
282 }
283 rualign = (rusize == sizeof(short)) ? rsalign : rialign;
284 rtalign = (rtsize == sizeof(short)) ? rsalign : rialign;
285 rdalign = (rdsize == sizeof(short)) ? rsalign : rialign;
286 switch (resize) {
287 case sizeof(char): realign = rcalign; break;
288 case sizeof(short): realign = rsalign; break;
289 case sizeof(Int): realign = rialign; break;
290 }
291 if (sizeof(uindex) < rusize || sizeof(ssizet) < rtsize ||
292 sizeof(sector) < rdsize) {
293 error("Cannot restore uindex, ssizet or sector of greater width");
294 }
295 secsize = (UCHAR(rheader[DUMP_SECSIZE + 0]) << 8) |
296 UCHAR(rheader[DUMP_SECSIZE + 1]);
297 if (secsize > conf[SECTOR_SIZE].u.num) {
298 error("Cannot restore bigger sector size");
299 }
300
301 sw_restore(fd, secsize);
302 kf_restore(fd);
303 o_restore(fd);
304
305 posn = P_lseek(fd, 0L, SEEK_CUR); /* preserve current file position */
306 o_conv(); /* convert all objects */
307 P_lseek(fd, posn, SEEK_SET); /* restore file position */
308
309 pc_restore(fd);
310 boottime = P_time();
311 co_restore(fd, boottime);
312 }
313
314 /*
315 * NAME: conf->dsize()
316 * DESCRIPTION: compute the size and alignment of a struct
317 * 0x000000ff size in dump file
318 * 0x0000ff00 alignment in dump file
319 * 0x00ff0000 size
320 * 0xff000000 alignment
321 */
322 Uint conf_dsize(layout)
323 char *layout;
324 {
325 register char *p;
326 register Uint sz, rsz, al, ral;
327 register Uint size, rsize, align, ralign;
328
329 p = layout;
330 size = rsize = 0;
331 align = ralign = 1;
332
333 for (;;) {
334 switch (*p++) {
335 case 'c': /* character */
336 sz = rsz = sizeof(char);
337 al = calign;
338 ral = rcalign;
339 break;
340
341 case 's': /* short */
342 sz = rsz = sizeof(short);
343 al = salign;
344 ral = rsalign;
345 break;
346
347 case 'u': /* uindex */
348 sz = sizeof(uindex);
349 rsz = rusize;
350 al = ualign;
351 ral = rualign;
352 break;
353
354 case 'i': /* Int */
355 sz = rsz = sizeof(Int);
356 al = ialign;
357 ral = rialign;
358 break;
359
360 case 't': /* ssizet */
361 sz = sizeof(ssizet);
362 rsz = rtsize;
363 al = talign;
364 ral = rtalign;
365 break;
366
367 case 'd': /* sector */
368 sz = sizeof(sector);
369 rsz = rdsize;
370 al = dalign;
371 ral = rdalign;
372 break;
373
374 case 'e': /* eindex */
375 sz = sizeof(eindex);
376 rsz = resize;
377 al = ealign;
378 ral = realign;
379 break;
380
381 case 'p': /* pointer */
382 sz = sizeof(char*);
383 rsz = rpsize;
384 al = palign;
385 ral = rpalign;
386 break;
387
388 case 'x': /* hte */
389 size = ALGN(size, zalign);
390 size = ALGN(size, palign);
391 size += sizeof(char*);
392 size = ALGN(size, palign);
393 size += sizeof(char*);
394 size = ALGN(size, zalign);
395 rsize = ALGN(rsize, rzalign);
396 rsize = ALGN(rsize, rpalign);
397 rsize += rpsize;
398 rsize = ALGN(rsize, rpalign);
399 rsize += rpsize;
400 rsize = ALGN(rsize, rzalign);
401 align = ALGN(align, palign);
402 ralign = ALGN(ralign, rpalign);
403 continue;
404
405 case '[': /* struct */
406 sz = conf_dsize(p);
407 al = (sz >> 8) & 0xff;
408 rsz = (sz >> 16) & 0xff;
409 ral = sz >> 24;
410 sz &= 0xff;
411 p = strchr(p, ']') + 1;
412 break;
413
414 case ']':
415 case '\0': /* end of layout */
416 if (p != layout + 2) {
417 /* a stuct and not an array element */
418 align = ALGN(align, zalign);
419 ralign = ALGN(ralign, rzalign);
420 }
421 return ALGN(rsize, ralign) |
422 (ralign << 8) |
423 (ALGN(size, align) << 16) |
424 (align << 24);
425 }
426
427 size = ALGN(size, al) + sz;
428 rsize = ALGN(rsize, ral) + rsz;
429 align = ALGN(align, al);
430 ralign = ALGN(ralign, ral);
431 }
432 }
433
434 /*
435 * NAME: conf_dconv()
436 * DESCRIPTION: convert structs from dumpfile format
437 */
438 Uint conf_dconv(buf, rbuf, layout, n)
439 register char *buf, *rbuf;
440 char *layout;
441 Uint n;
442 {
443 register Uint i, ri, j, size, rsize;
444 register char *p;
445
446 rsize = conf_dsize(layout);
447 size = (rsize >> 16) & 0xff;
448 rsize &= 0xff;
449 while (n > 0) {
450 i = ri = 0;
451 for (p = layout; *p != '\0' && *p != ']'; p++) {
452 switch (*p) {
453 case 'c':
454 i = ALGN(i, calign);
455 ri = ALGN(ri, rcalign);
456 buf[i] = rbuf[ri];
457 i += sizeof(char);
458 ri += sizeof(char);
459 break;
460
461 case 's':
462 i = ALGN(i, salign);
463 ri = ALGN(ri, rsalign);
464 buf[i + s0] = rbuf[ri + rs0];
465 buf[i + s1] = rbuf[ri + rs1];
466 i += sizeof(short);
467 ri += sizeof(short);
468 break;
469
470 case 'u':
471 i = ALGN(i, ualign);
472 ri = ALGN(ri, rualign);
473 if (sizeof(uindex) == rusize) {
474 if (sizeof(uindex) == sizeof(short)) {
475 buf[i + s0] = rbuf[ri + rs0];
476 buf[i + s1] = rbuf[ri + rs1];
477 } else {
478 buf[i + i0] = rbuf[ri + ri0];
479 buf[i + i1] = rbuf[ri + ri1];
480 buf[i + i2] = rbuf[ri + ri2];
481 buf[i + i3] = rbuf[ri + ri3];
482 }
483 } else {
484 j = (UCHAR(rbuf[ri + rs0] & rbuf[ri + rs1]) == 0xff) ?
485 -1 : 0;
486 buf[i + i0] = j;
487 buf[i + i1] = j;
488 buf[i + i2] = rbuf[ri + rs0];
489 buf[i + i3] = rbuf[ri + rs1];
490 }
491 i += sizeof(uindex);
492 ri += rusize;
493 break;
494
495 case 'i':
496 i = ALGN(i, ialign);
497 ri = ALGN(ri, rialign);
498 buf[i + i0] = rbuf[ri + ri0];
499 buf[i + i1] = rbuf[ri + ri1];
500 buf[i + i2] = rbuf[ri + ri2];
501 buf[i + i3] = rbuf[ri + ri3];
502 i += sizeof(Int);
503 ri += sizeof(Int);
504 break;
505
506 case 't':
507 i = ALGN(i, talign);
508 ri = ALGN(ri, rtalign);
509 if (sizeof(ssizet) == rtsize) {
510 if (sizeof(ssizet) == sizeof(short)) {
511 buf[i + s0] = rbuf[ri + rs0];
512 buf[i + s1] = rbuf[ri + rs1];
513 } else {
514 buf[i + i0] = rbuf[ri + ri0];
515 buf[i + i1] = rbuf[ri + ri1];
516 buf[i + i2] = rbuf[ri + ri2];
517 buf[i + i3] = rbuf[ri + ri3];
518 }
519 } else {
520 buf[i + i0] = 0;
521 buf[i + i1] = 0;
522 buf[i + i2] = rbuf[ri + rs0];
523 buf[i + i3] = rbuf[ri + rs1];
524 }
525 i += sizeof(ssizet);
526 ri += rtsize;
527 break;
528
529 case 'd':
530 i = ALGN(i, dalign);
531 ri = ALGN(ri, rdalign);
532 if (sizeof(sector) == rdsize) {
533 if (sizeof(sector) == sizeof(short)) {
534 buf[i + s0] = rbuf[ri + rs0];
535 buf[i + s1] = rbuf[ri + rs1];
536 } else {
537 buf[i + i0] = rbuf[ri + ri0];
538 buf[i + i1] = rbuf[ri + ri1];
539 buf[i + i2] = rbuf[ri + ri2];
540 buf[i + i3] = rbuf[ri + ri3];
541 }
542 } else {
543 j = (UCHAR(rbuf[ri + rs0] & rbuf[ri + rs1]) == 0xff) ?
544 -1 : 0;
545 buf[i + i0] = j;
546 buf[i + i1] = j;
547 buf[i + i2] = rbuf[ri + rs0];
548 buf[i + i3] = rbuf[ri + rs1];
549 }
550 i += sizeof(sector);
551 ri += rdsize;
552 break;
553
554 case 'e':
555 i = ALGN(i, ealign);
556 ri = ALGN(ri, realign);
557 i += sizeof(eindex);
558 ri += resize;
559 break;
560
561 case 'p':
562 i = ALGN(i, palign);
563 ri = ALGN(ri, rpalign);
564 for (j = sizeof(char*); j > 0; --j) {
565 buf[i++] = 0;
566 }
567 ri += rpsize;
568 break;
569
570 case '[':
571 j = conf_dsize(++p);
572 i = ALGN(i, j >> 24);
573 ri = ALGN(ri, (j >> 8) & 0xff);
574 j = conf_dconv(buf + i, rbuf + ri, p, (Uint) 1);
575 i += (j >> 16) & 0xff;
576 ri += j & 0xff;
577 p = strchr(p, ']');
578 break;
579
580 case 'x':
581 i = ALGN(i, zalign);
582 i = ALGN(i, palign);
583 for (j = sizeof(char*); j > 0; --j) {
584 buf[i++] = 0;
585 }
586 i = ALGN(i, palign);
587 for (j = sizeof(char*); j > 0; --j) {
588 buf[i++] = 0;
589 }
590 ri = ALGN(ri, rzalign);
591 ri = ALGN(ri, rpalign);
592 ri += rpsize;
593 ri = ALGN(ri, rpalign);
594 for (j = rpsize; j > 0; --j) {
595 if (rbuf[ri] != 0) {
596 buf[i - 1] = 1;
597 break;
598 }
599 ri++;
600 }
601 ri += j;
602 i = ALGN(i, zalign);
603 ri = ALGN(ri, rzalign);
604 break;
605 }
606 }
607
608 buf += size;
609 rbuf += rsize;
610 --n;
611 }
612
613 return (size << 16) | rsize;
614 }
615
616 /*
617 * NAME: conf->dread()
618 * DESCRIPTION: read from dumpfile
619 */
620 void conf_dread(fd, buf, layout, n)
621 int fd;
622 char *buf, *layout;
623 register Uint n;
624 {
625 char buffer[16384];
626 register unsigned int i, size, rsize;
627 Uint tmp;
628
629 tmp = conf_dsize(layout);
630 size = (tmp >> 16) & 0xff;
631 rsize = tmp & 0xff;
632 while (n != 0) {
633 i = sizeof(buffer) / rsize;
634 if (i > n) {
635 i = n;
636 }
637 if (P_read(fd, buffer, i * rsize) != i * rsize) {
638 fatal("cannot read from dump file");
639 }
640 conf_dconv(buf, buffer, layout, (Uint) i);
641 buf += size * i;
642 n -= i;
643 }
644 }
645
646
647 # define MAX_DIRS 32
648
649 static char *dirs[MAX_DIRS];
650
651 /*
652 * NAME: conferr()
653 * DESCRIPTION: error during the configuration phase
654 */
655 static void conferr(err)
656 char *err;
657 {
658 message("Config error, line %u: %s\012", tk_line(), err); /* LF */
659 }
660
661 /*
662 * NAME: config->config()
663 * DESCRIPTION: read config file
664 */
665 static bool conf_config()
666 {
667 char buf[STRINGSZ];
668 register char *p;
669 register int h, l, m, c;
670
671 for (h = NR_OPTIONS; h > 0; ) {
672 conf[--h].set = FALSE;
673 }
674 memset(dirs, '\0', sizeof(dirs));
675
676 while ((c=pp_gettok()) != EOF) {
677 if (c != IDENTIFIER) {
678 conferr("option expected");
679 return FALSE;
680 }
681
682 l = 0;
683 h = NR_OPTIONS;
684 for (;;) {
685 c = strcmp(yytext, conf[m = (l + h) >> 1].name);
686 if (c == 0) {
687 break; /* found */
688 } else if (c < 0) {
689 h = m; /* search in lower half */
690 } else {
691 l = m + 1; /* search in upper half */
692 }
693 if (l >= h) {
694 conferr("unknown option");
695 return FALSE;
696 }
697 }
698
699 if (pp_gettok() != '=') {
700 conferr("'=' expected");
701 return FALSE;
702 }
703
704 if ((c=pp_gettok()) != conf[m].type) {
705 if (c != INT_CONST && c != STRING_CONST && c != '(') {
706 conferr("syntax error");
707 return FALSE;
708 } else {
709 conferr("bad value type");
710 return FALSE;
711 }
712 }
713
714 switch (c) {
715 case INT_CONST:
716 if (yylval.number < conf[m].low ||
717 (conf[m].high != 0 && yylval.number > conf[m].high)) {
718 conferr("int value out of range");
719 return FALSE;
720 }
721 conf[m].u.num = yylval.number;
722 break;
723
724 case STRING_CONST:
725 p = (conf[m].resolv) ? path_resolve(buf, yytext) : yytext;
726 l = strlen(p);
727 if (l >= STRINGSZ) {
728 l = STRINGSZ - 1;
729 p[l] = '\0';
730 }
731 m_static();
732 conf[m].u.str = strcpy(ALLOC(char, l + 1), p);
733 m_dynamic();
734 break;
735
736 case '(':
737 if (pp_gettok() != '{') {
738 conferr("'{' expected");
739 return FALSE;
740 }
741 l = 0;
742 for (;;) {
743 if (pp_gettok() != STRING_CONST) {
744 conferr("string expected");
745 return FALSE;
746 }
747 if (l == MAX_DIRS - 1) {
748 conferr("too many include directories");
749 return FALSE;
750 }
751 m_static();
752 dirs[l] = strcpy(ALLOC(char, strlen(yytext) + 1), yytext);
753 l++;
754 m_dynamic();
755 if ((c=pp_gettok()) == '}') {
756 break;
757 }
758 if (c != ',') {
759 conferr("',' expected");
760 return FALSE;
761 }
762 }
763 if (pp_gettok() != ')') {
764 conferr("')' expected");
765 return FALSE;
766 }
767 dirs[l] = (char *) NULL;
768 break;
769 }
770 conf[m].set = TRUE;
771 if (pp_gettok() != ';') {
772 conferr("';' expected");
773 return FALSE;
774 }
775 }
776
777 for (l = 0; l < NR_OPTIONS; l++) {
778 if (!conf[l].set) {
779 char buffer[64];
780
781 sprintf(buffer, "unspecified option %s", conf[l].name);
782 conferr(buffer);
783 return FALSE;
784 }
785 }
786
787 return TRUE;
788 }
789
790 static char *fname; /* file name */
791 static int fd; /* file descriptor */
792 static char *obuf; /* output buffer */
793 static unsigned int bufsz; /* buffer size */
794
795 /*
796 * NAME: config->open()
797 * DESCRIPTION: create a new file
798 */
799 static bool copen(file)
800 char *file;
801 {
802 char fname[STRINGSZ];
803
804 path_resolve(fname, file);
805 if ((fd=P_open(fname, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0644)) < 0) {
806 message("Config error: cannot create \"/%s\"\012", fname); /* LF */
807 return FALSE;
808 }
809 bufsz = 0;
810
811 return TRUE;
812 }
813
814 /*
815 * NAME: config->put()
816 * DESCRIPTION: write a string to a file
817 */
818 static void cputs(str)
819 register char *str;
820 {
821 register unsigned int len, chunk;
822
823 len = strlen(str);
824 while (bufsz + len > BUF_SIZE) {
825 chunk = BUF_SIZE - bufsz;
826 memcpy(obuf + bufsz, str, chunk);
827 P_write(fd, obuf, BUF_SIZE);
828 str += chunk;
829 len -= chunk;
830 bufsz = 0;
831 }
832 if (len > 0) {
833 memcpy(obuf + bufsz, str, len);
834 bufsz += len;
835 }
836 }
837
838 /*
839 * NAME: config->close()
840 * DESCRIPTION: close a file
841 */
842 static bool cclose()
843 {
844 if (bufsz > 0 && P_write(fd, obuf, bufsz) != bufsz) {
845 message("Config error: cannot write \"/%s\"\012", fname); /* LF */
846 P_close(fd);
847 return FALSE;
848 }
849 P_close(fd);
850
851 return TRUE;
852 }
853
854 /*
855 * NAME: config->includes()
856 * DESCRIPTION: create include files
857 */
858 static bool conf_includes()
859 {
860 char buf[BUF_SIZE], buffer[STRINGSZ];
861
862 /* create status.h file */
863 obuf = buf;
864 sprintf(buffer, "%s/status.h", dirs[0]);
865 if (!copen(buffer)) {
866 return FALSE;
867 }
868 cputs("/*\012 * This file defines the fields of the array returned ");
869 cputs("by the\012 * status() kfun. It is automatically generated ");
870 cputs("by DGD on startup.\012 */\012\012");
871 cputs("# define ST_VERSION\t\t/* driver version */\012");
872 cputs("# define ST_STARTTIME\t1\t/* system start time */\012");
873 cputs("# define ST_BOOTTIME\t2\t/* system reboot time */\012");
874 cputs("# define ST_UPTIME\t3\t/* system virtual uptime */\012");
875 cputs("# define ST_SWAPSIZE\t4\t/* # sectors on swap device */\012");
876 cputs("# define ST_SWAPUSED\t5\t/* # sectors in use */\012");
877 cputs("# define ST_SECTORSIZE\t6\t/* size of swap sector */\012");
878 cputs("# define ST_SWAPRATE1\t7\t/* # objects swapped out last minute */\012");
879 cputs("# define ST_SWAPRATE5\t8\t/* # objects swapped out last five minutes */\012");
880 cputs("# define ST_SMEMSIZE\t9\t/* static memory allocated */\012");
881 cputs("# define ST_SMEMUSED\t10\t/* static memory in use */\012");
882 cputs("# define ST_DMEMSIZE\t11\t/* dynamic memory allocated */\012");
883 cputs("# define ST_DMEMUSED\t12\t/* dynamic memory in use */\012");
884 cputs("# define ST_OTABSIZE\t13\t/* object table size */\012");
885 cputs("# define ST_NOBJECTS\t14\t/* # objects in use */\012");
886 cputs("# define ST_COTABSIZE\t15\t/* callouts table size */\012");
887 cputs("# define ST_NCOSHORT\t16\t/* # short-term callouts */\012");
888 cputs("# define ST_NCOLONG\t17\t/* # long-term & millisecond callouts */\012");
889 cputs("# define ST_UTABSIZE\t18\t/* user table size */\012");
890 cputs("# define ST_ETABSIZE\t19\t/* editor table size */\012");
891 cputs("# define ST_STRSIZE\t20\t/* max string size */\012");
892 cputs("# define ST_ARRAYSIZE\t21\t/* max array/mapping size */\012");
893 cputs("# define ST_STACKDEPTH\t22\t/* remaining stack depth */\012");
894 cputs("# define ST_TICKS\t23\t/* remaining ticks */\012");
895 cputs("# define ST_PRECOMPILED\t24\t/* precompiled objects */\012");
896
897 cputs("\012# define O_COMPILETIME\t\t/* time of compilation */\012");
898 cputs("# define O_PROGSIZE\t1\t/* program size of object */\012");
899 cputs("# define O_DATASIZE\t2\t/* # variables in object */\012");
900 cputs("# define O_NSECTORS\t3\t/* # sectors used by object */\012");
901 cputs("# define O_CALLOUTS\t4\t/* callouts in object */\012");
902 cputs("# define O_INDEX\t5\t/* unique ID for master object */\012");
903
904 cputs("\012# define CO_HANDLE\t\t/* callout handle */\012");
905 cputs("# define CO_FUNCTION\t1\t/* function name */\012");
906 cputs("# define CO_DELAY\t2\t/* delay */\012");
907 cputs("# define CO_FIRSTXARG\t3\t/* first extra argument */\012");
908 if (!cclose()) {
909 return FALSE;
910 }
911
912 /* create type.h file */
913 sprintf(buffer, "%s/type.h", dirs[0]);
914 if (!copen(buffer)) {
915 return FALSE;
916 }
917 cputs("/*\012 * This file gives definitions for the value returned ");
918 cputs("by the\012 * typeof() kfun. It is automatically generated ");
919 cputs("by DGD on startup.\012 */\012\012");
920 sprintf(buffer, "# define T_NIL\t\t%d\012", T_NIL);
921 cputs(buffer);
922 sprintf(buffer, "# define T_INT\t\t%d\012", T_INT);
923 cputs(buffer);
924 sprintf(buffer, "# define T_FLOAT\t%d\012", T_FLOAT);
925 cputs(buffer);
926 sprintf(buffer, "# define T_STRING\t%d\012", T_STRING);
927 cputs(buffer);
928 sprintf(buffer, "# define T_OBJECT\t%d\012", T_OBJECT);
929 cputs(buffer);
930 sprintf(buffer, "# define T_ARRAY\t%d\012", T_ARRAY);
931 cputs(buffer);
932 sprintf(buffer, "# define T_MAPPING\t%d\012", T_MAPPING);
933 cputs(buffer);
934 if (!cclose()) {
935 return FALSE;
936 }
937
938 /* create limits.h file */
939 sprintf(buffer, "%s/limits.h", dirs[0]);
940 if (!copen(buffer)) {
941 return FALSE;
942 }
943 cputs("/*\012 * This file defines some basic sizes of datatypes and ");
944 cputs("resources.\012 * It is automatically generated by DGD on ");
945 cputs("startup.\012 */\012\012");
946 cputs("# define CHAR_BIT\t\t8\t\t/* # bits in character */\012");
947 cputs("# define CHAR_MIN\t\t\t\t/* min character value */\012");
948 cputs("# define CHAR_MAX\t\t255\t\t/* max character value */\012\012");
949 cputs("# define INT_MIN\t\t0x80000000\t/* -2147483648 */\012");
950 cputs("# define INT_MAX\t\t2147483647\t/* max integer value */\012\012");
951 sprintf(buffer, "# define MAX_STRING_SIZE\t%u\t\t/* max string size (obsolete) */\012",
952 MAX_STRLEN);
953 cputs(buffer);
954 if (!cclose()) {
955 return FALSE;
956 }
957
958 /* create float.h file */
959 sprintf(buffer, "%s/float.h", dirs[0]);
960 if (!copen(buffer)) {
961 return FALSE;
962 }
963 cputs("/*\012 * This file describes the floating point type. It is ");
964 cputs("automatically\012 * generated by DGD on startup.\012 */\012\012");
965 cputs("# define FLT_RADIX\t2\t\t\t/* binary */\012");
966 cputs("# define FLT_ROUNDS\t1\t\t\t/* round to nearest */\012");
967 cputs("# define FLT_EPSILON\t7.2759576142E-12\t/* smallest x: 1.0 + x != 1.0 */\012");
968 cputs("# define FLT_DIG\t10\t\t\t/* decimal digits of precision*/\012");
969 cputs("# define FLT_MANT_DIG\t36\t\t\t/* binary digits of precision */\012");
970 cputs("# define FLT_MIN\t2.22507385851E-308\t/* positive minimum */\012");
971 cputs("# define FLT_MIN_EXP\t(-1021)\t\t\t/* minimum binary exponent */\012");
972 cputs("# define FLT_MIN_10_EXP\t(-307)\t\t\t/* minimum decimal exponent */\012");
973 cputs("# define FLT_MAX\t1.79769313485E+308\t/* positive maximum */\012");
974 cputs("# define FLT_MAX_EXP\t1024\t\t\t/* maximum binary exponent */\012");
975 cputs("# define FLT_MAX_10_EXP\t308\t\t\t/* maximum decimal exponent */\012");
976 if (!cclose()) {
977 return FALSE;
978 }
979
980 /* create trace.h file */
981 sprintf(buffer, "%s/trace.h", dirs[0]);
982 if (!copen(buffer)) {
983 return FALSE;
984 }
985 cputs("/*\012 * This file describes the fields of the array returned for ");
986 cputs("every stack\012 * frame by the call_trace() function. It is ");
987 cputs("automatically generated by DGD\012 * on startup.\012 */\012\012");
988 cputs("# define TRACE_OBJNAME\t\t/* name of the object */\012");
989 cputs("# define TRACE_PROGNAME\t1\t/* name of the object the function is in */\012");
990 cputs("# define TRACE_FUNCTION\t2\t/* function name */\012");
991 cputs("# define TRACE_LINE\t3\t/* line number */\012");
992 cputs("# define TRACE_EXTERNAL\t4\t/* external call flag */\012");
993 cputs("# define TRACE_FIRSTARG\t5\t/* first argument to function */\012");
994 return cclose();
995 }
996
997
998 # ifdef DGD_EXTENSION
999 extern void extension_init P((void));
1000 # endif
1001
1002 void (*ext_restore) P((object*));
1003 void (*ext_swapout) P((object*));
1004 void (*ext_destruct) P((object*));
1005 bool (*ext_funcall) P((frame*, int, value*, char*));
1006 void (*ext_cleanup) P((void));
1007 void (*ext_finish) P((void));
1008
1009 /*
1010 * NAME: config->init()
1011 * DESCRIPTION: initialize the driver
1012 */
1013 bool conf_init(configfile, dumpfile, fragment)
1014 char *configfile, *dumpfile;
1015 sector *fragment;
1016 {
1017 char buf[STRINGSZ];
1018 int fd;
1019 bool init;
1020
1021 /*
1022 * process config file
1023 */
1024 if (!pp_init(path_native(buf, configfile), (char **) NULL, 0)) {
1025 message("Config error: cannot open config file\012"); /* LF */
1026 m_finish();
1027 return FALSE;
1028 }
1029 init = conf_config();
1030 pp_clear();
1031 if (!init) {
1032 m_finish();
1033 return FALSE;
1034 }
1035 if (dumpfile != (char *) NULL) {
1036 fd = P_open(path_native(buf, dumpfile), O_RDONLY | O_BINARY, 0);
1037 if (fd < 0) {
1038 P_message("Config error: cannot open restore file\012"); /* LF */
1039 return FALSE;
1040 }
1041 }
1042
1043 /* change directory */
1044 if (P_chdir(path_native(buf, conf[DIRECTORY].u.str)) < 0) {
1045 message("Config error: bad base directory \"%s\"\012", /* LF */
1046 conf[DIRECTORY].u.str);
1047 if (dumpfile != (char *) NULL) {
1048 P_close(fd);
1049 }
1050 m_finish();
1051 return FALSE;
1052 }
1053
1054 m_static();
1055
1056 /* initialize communications */
1057 if (!comm_init((int) conf[USERS].u.num,
1058 (unsigned int) conf[TELNET_PORT].u.num,
1059 (unsigned int) conf[BINARY_PORT].u.num)) {
1060 comm_finish();
1061 if (dumpfile != (char *) NULL) {
1062 P_close(fd);
1063 }
1064 m_finish();
1065 return FALSE;
1066 }
1067
1068 /* initialize strings */
1069 str_init();
1070
1071 /* initialize arrays */
1072 arr_init((int) conf[ARRAY_SIZE].u.num);
1073
1074 /* initialize objects */
1075 o_init((uindex) conf[OBJECTS].u.num);
1076
1077 /* initialize swap device */
1078 sw_init(conf[SWAP_FILE].u.str,
1079 (sector) conf[SWAP_SIZE].u.num,
1080 (sector) conf[CACHE_SIZE].u.num,
1081 (unsigned int) conf[SECTOR_SIZE].u.num);
1082
1083 /* initialize swapped data handler */
1084 d_init(conf[TYPECHECKING].u.num == 2);
1085 *fragment = conf[SWAP_FRAGMENT].u.num;
1086
1087 /* initalize editor */
1088 ed_init(conf[ED_TMPFILE].u.str,
1089 (int) conf[EDITORS].u.num);
1090
1091 /* initialize call_outs */
1092 if (!co_init((uindex) conf[CALL_OUTS].u.num)) {
1093 comm_finish();
1094 if (dumpfile != (char *) NULL) {
1095 P_close(fd);
1096 }
1097 m_finish();
1098 return FALSE;
1099 }
1100
1101 ext_restore = (void (*) P((object*))) NULL;
1102 ext_swapout = (void (*) P((object*))) NULL;
1103 ext_destruct = (void (*) P((object*))) NULL;
1104 ext_funcall = (bool (*) P((frame*, int, value*, char*))) NULL;
1105 ext_cleanup = (void (*) P((void))) NULL;
1106 ext_finish = (void (*) P((void))) NULL;
1107
1108 /* remove previously added kfuns */
1109 kf_clear();
1110
1111 # ifdef DGD_EXTENSION
1112 extension_init();
1113 # endif
1114
1115 /* initialize kfuns */
1116 kf_init();
1117
1118 /* initialize interpreter */
1119 i_init(conf[CREATE].u.str, conf[TYPECHECKING].u.num == 2);
1120
1121 /* initialize compiler */
1122 c_init(conf[AUTO_OBJECT].u.str,
1123 conf[DRIVER_OBJECT].u.str,
1124 conf[INCLUDE_FILE].u.str,
1125 dirs,
1126 (int) conf[TYPECHECKING].u.num);
1127
1128 m_dynamic();
1129
1130 /* initialize memory manager */
1131 m_init((size_t) conf[STATIC_CHUNK].u.num,
1132 (size_t) conf[DYNAMIC_CHUNK].u.num);
1133
1134 /*
1135 * create include files
1136 */
1137 if (!conf_includes()) {
1138 comm_finish();
1139 if (dumpfile != (char *) NULL) {
1140 P_close(fd);
1141 }
1142 m_finish();
1143 return FALSE;
1144 }
1145
1146 /* load precompiled objects */
1147 if (!pc_preload(conf[AUTO_OBJECT].u.str, conf[DRIVER_OBJECT].u.str)) {
1148 comm_finish();
1149 if (dumpfile != (char *) NULL) {
1150 P_close(fd);
1151 }
1152 m_finish();
1153 return FALSE;
1154 }
1155
1156 /* initialize dumpfile header */
1157 conf_dumpinit();
1158
1159 m_static(); /* allocate error context statically */
1160 ec_push((ec_ftn) NULL); /* guard error context */
1161 if (ec_push((ec_ftn) NULL)) {
1162 message((char *) NULL);
1163 endthread();
1164 message("Config error: initialization failed\012"); /* LF */
1165 ec_pop(); /* remove guard */
1166
1167 comm_finish();
1168 ed_finish();
1169 if (dumpfile != (char *) NULL) {
1170 P_close(fd);
1171 }
1172 m_finish();
1173 return FALSE;
1174 }
1175 m_dynamic();
1176 if (dumpfile == (char *) NULL) {
1177 /* initialize mudlib */
1178 if (ec_push((ec_ftn) errhandler)) {
1179 error((char *) NULL);
1180 }
1181 call_driver_object(cframe, "initialize", 0);
1182 ec_pop();
1183 } else {
1184 /* restore dump file */
1185 conf_restore(fd);
1186 P_close(fd);
1187
1188 /* notify mudlib */
1189 if (ec_push((ec_ftn) errhandler)) {
1190 error((char *) NULL);
1191 }
1192 call_driver_object(cframe, "restored", 0);
1193 ec_pop();
1194 }
1195 ec_pop();
1196 i_del_value(cframe->sp++);
1197 endthread();
1198 ec_pop(); /* remove guard */
1199
1200 /* start accepting connections */
1201 comm_listen();
1202
1203 return TRUE;
1204 }
1205
1206 /*
1207 * NAME: config->ext_callback()
1208 * DESCRIPTION: initialize callbacks for extension interface
1209 */
1210 void conf_ext_callback(restore, swapout, destruct, funcall, cleanup, finish)
1211 void (*restore) P((object*));
1212 void (*swapout) P((object*));
1213 void (*destruct) P((object*));
1214 bool (*funcall) P((frame*, int, value*, char*));
1215 void (*cleanup) P((void));
1216 void (*finish) P((void));
1217 {
1218 ext_restore = restore;
1219 ext_swapout = swapout;
1220 ext_destruct = destruct;
1221 ext_funcall = funcall;
1222 ext_cleanup = cleanup;
1223 ext_finish = finish;
1224 }
1225
1226 /*
1227 * NAME: config->base_dir()
1228 * DESCRIPTION: return the driver base directory
1229 */
1230 char *conf_base_dir()
1231 {
1232 return conf[DIRECTORY].u.str;
1233 }
1234
1235 /*
1236 * NAME: config->driver()
1237 * DESCRIPTION: return the driver object name
1238 */
1239 char *conf_driver()
1240 {
1241 return conf[DRIVER_OBJECT].u.str;
1242 }
1243
1244 /*
1245 * NAME: config->typechecking()
1246 * DESCRIPTION: return the global typechecking flag
1247 */
1248 int conf_typechecking()
1249 {
1250 return conf[TYPECHECKING].u.num;
1251 }
1252
1253 /*
1254 * NAME: config->array_size()
1255 * DESCRIPTION: return the maximum array size
1256 */
1257 unsigned short conf_array_size()
1258 {
1259 return conf[ARRAY_SIZE].u.num;
1260 }
1261
1262 /*
1263 * NAME: config->statusi()
1264 * DESCRIPTION: return resource usage information
1265 */
1266 bool conf_statusi(f, idx, v)
1267 frame *f;
1268 Int idx;
1269 register value *v;
1270 {
1271 char *version;
1272 uindex ncoshort, ncolong;
1273
1274 switch (idx) {
1275 case 0: /* ST_VERSION */
1276 version = VERSION;
1277 PUT_STRVAL(v, str_new(version, (long) strlen(version)));
1278 break;
1279
1280 case 1: /* ST_STARTTIME */
1281 PUT_INTVAL(v, starttime);
1282 break;
1283
1284 case 2: /* ST_BOOTTIME */
1285 PUT_INTVAL(v, boottime);
1286 break;
1287
1288 case 3: /* ST_UPTIME */
1289 PUT_INTVAL(v, elapsed + P_time() - boottime);
1290 break;
1291
1292 case 4: /* ST_SWAPSIZE */
1293 PUT_INTVAL(v, conf[SWAP_SIZE].u.num);
1294 break;
1295
1296 case 5: /* ST_SWAPUSED */
1297 PUT_INTVAL(v, sw_count());
1298 break;
1299
1300 case 6: /* ST_SECTORSIZE */
1301 PUT_INTVAL(v, conf[SECTOR_SIZE].u.num);
1302 break;
1303
1304 case 7: /* ST_SWAPRATE1 */
1305 PUT_INTVAL(v, co_swaprate1());
1306 break;
1307
1308 case 8: /* ST_SWAPRATE5 */
1309 PUT_INTVAL(v, co_swaprate5());
1310 break;
1311
1312 case 9: /* ST_SMEMSIZE */
1313 PUT_INTVAL(v, m_info()->smemsize);
1314 break;
1315
1316 case 10: /* ST_SMEMUSED */
1317 PUT_INTVAL(v, m_info()->smemused);
1318 break;
1319
1320 case 11: /* ST_DMEMSIZE */
1321 PUT_INTVAL(v, m_info()->dmemsize);
1322 break;
1323
1324 case 12: /* ST_DMEMUSED */
1325 PUT_INTVAL(v, m_info()->dmemused);
1326 break;
1327
1328 case 13: /* ST_OTABSIZE */
1329 PUT_INTVAL(v, conf[OBJECTS].u.num);
1330 break;
1331
1332 case 14: /* ST_NOBJECTS */
1333 PUT_INTVAL(v, o_count());
1334 break;
1335
1336 case 15: /* ST_COTABSIZE */
1337 PUT_INTVAL(v, conf[CALL_OUTS].u.num);
1338 break;
1339
1340 case 16: /* ST_NCOSHORT */
1341 co_info(&ncoshort, &ncolong);
1342 PUT_INTVAL(v, ncoshort);
1343 break;
1344
1345 case 17: /* ST_NCOLONG */
1346 co_info(&ncoshort, &ncolong);
1347 PUT_INTVAL(v, ncolong);
1348 break;
1349
1350 case 18: /* ST_UTABSIZE */
1351 PUT_INTVAL(v, conf[USERS].u.num);
1352 break;
1353
1354 case 19: /* ST_ETABSIZE */
1355 PUT_INTVAL(v, conf[EDITORS].u.num);
1356 break;
1357
1358 case 20: /* ST_STRSIZE */
1359 PUT_INTVAL(v, MAX_STRLEN);
1360 break;
1361
1362 case 21: /* ST_ARRAYSIZE */
1363 PUT_INTVAL(v, conf[ARRAY_SIZE].u.num);
1364 break;
1365
1366 case 22: /* ST_STACKDEPTH */
1367 PUT_INTVAL(v, i_get_depth(f));
1368 break;
1369
1370 case 23: /* ST_TICKS */
1371 PUT_INTVAL(v, i_get_ticks(f));
1372 break;
1373
1374 case 24: /* ST_PRECOMPILED */
1375 PUT_ARRVAL(v, pc_list(f->data));
1376 break;
1377
1378 default:
1379 return FALSE;
1380 }
1381
1382 return TRUE;
1383 }
1384
1385 /*
1386 * NAME: config->status()
1387 * DESCRIPTION: return an array with information about resource usage
1388 */
1389 array *conf_status(f)
1390 register frame *f;
1391 {
1392 register value *v;
1393 register Int i;
1394 array *a;
1395
1396 a = arr_new(f->data, 25L);
1397 for (i = 0, v = a->elts; i < 25; i++, v++) {
1398 conf_statusi(f, i, v);
1399 }
1400 return a;
1401 }
1402
1403 /*
1404 * NAME: config->objecti()
1405 * DESCRIPTION: return object resource usage information
1406 */
1407 bool conf_objecti(data, obj, idx, v)
1408 dataspace *data;
1409 register object *obj;
1410 Int idx;
1411 register value *v;
1412 {
1413 register control *ctrl;
1414 object *prog;
1415
1416 prog = (obj->flags & O_MASTER) ? obj : OBJR(obj->u_master);
1417 ctrl = (O_UPGRADING(prog)) ? OBJR(prog->prev)->ctrl : o_control(prog);
1418
1419 switch (idx) {
1420 case 0: /* O_COMPILETIME */
1421 PUT_INTVAL(v, ctrl->compiled);
1422 break;
1423
1424 case 1: /* O_PROGSIZE */
1425 PUT_INTVAL(v, d_get_progsize(ctrl));
1426 break;
1427
1428 case 2: /* O_DATASIZE */
1429 PUT_INTVAL(v, ctrl->nvariables);
1430 break;
1431
1432 case 3: /* O_NSECTORS */
1433 PUT_INTVAL(v, (obj->flags & O_CREATED) ?
1434 o_dataspace(obj)->nsectors : 0);
1435 if (obj->flags & O_MASTER) {
1436 v->u.number += ctrl->nsectors;
1437 }
1438 break;
1439
1440 case 4: /* O_CALLOUTS */
1441 PUT_ARRVAL(v, (obj->flags & O_CREATED) ?
1442 d_list_callouts(data, o_dataspace(obj)) :
1443 arr_new(data, 0L));
1444 break;
1445
1446 case 5: /* O_INDEX */
1447 PUT_INTVAL(v, (obj->flags & O_MASTER) ?
1448 (Uint) obj->index : obj->u_master);
1449 break;
1450
1451
1452 default:
1453 return FALSE;
1454 }
1455
1456 return TRUE;
1457 }
1458
1459 /*
1460 * NAME: config->object()
1461 * DESCRIPTION: return resource usage of an object
1462 */
1463 array *conf_object(data, obj)
1464 register dataspace *data;
1465 register object *obj;
1466 {
1467 register value *v;
1468 register Int i;
1469 array *a;
1470
1471 a = arr_new(data, 6L);
1472 for (i = 0, v = a->elts; i < 6; i++, v++) {
1473 conf_objecti(data, obj, i, v);
1474 }
1475 return a;
1476 }
1477
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.