# define INCLUDE_FILE_IO # include "dgd.h" # include "str.h" # include "array.h" # include "object.h" # include "xfloat.h" # include "interpret.h" # include "data.h" # include "path.h" # include "editor.h" # include "call_out.h" # include "comm.net.h" # include "version.h" # include "macro.h" # include "token.h" # include "ppcontrol.h" # include "node.h" # include "parser.h" # include "compile.h" # include "csupport.h" # include "table.h" typedef struct { char *name; /* name of the option */ short type; /* option type */ bool set; /* TRUE if option is set */ Uint low, high; /* lower and higher bound, for numeric values */ union { long num; /* numeric value */ char *str; /* string value */ } u; } config; static config conf[] = { # define ARRAY_SIZE 0 { "array_size", INT_CONST, FALSE, 1, USHRT_MAX / 2 }, # define AUTO_OBJECT 1 { "auto_object", STRING_CONST, FALSE }, # define BINARY_PORT 2 { "binary_port", INT_CONST, FALSE, 0, USHRT_MAX }, # define CACHE_SIZE 3 { "cache_size", INT_CONST, FALSE, 2, UINDEX_MAX }, # define CALL_OUTS 4 { "call_outs", INT_CONST, FALSE, 0, UINDEX_MAX }, # define CREATE 5 { "create", STRING_CONST, FALSE }, # define DIRECTORY 6 { "directory", STRING_CONST, FALSE }, # define DRIVER_OBJECT 7 { "driver_object", STRING_CONST, FALSE }, # define DUMP_FILE 8 { "dump_file", STRING_CONST, FALSE }, # define DYNAMIC_CHUNK 9 { "dynamic_chunk", INT_CONST, FALSE }, # define ED_TMPFILE 10 { "ed_tmpfile", STRING_CONST, FALSE }, # define EDITORS 11 { "editors", INT_CONST, FALSE, 0, UCHAR_MAX }, # define INCLUDE_DIRS 12 { "include_dirs", '(', FALSE }, # define INCLUDE_FILE 13 { "include_file", STRING_CONST, FALSE }, # define OBJECTS 14 { "objects", INT_CONST, FALSE, 2, UINDEX_MAX }, # define SECTOR_SIZE 15 { "sector_size", INT_CONST, FALSE, 512, 8192 }, # define STATIC_CHUNK 16 { "static_chunk", INT_CONST, FALSE }, # define SWAP_FILE 17 { "swap_file", STRING_CONST, FALSE }, # define SWAP_FRAGMENT 18 { "swap_fragment", INT_CONST, FALSE }, # define SWAP_SIZE 19 { "swap_size", INT_CONST, FALSE, 1024, SW_UNUSED }, # define TELNET_PORT 20 { "telnet_port", INT_CONST, FALSE, 0, USHRT_MAX }, # define TYPECHECKING 21 { "typechecking", INT_CONST, FALSE, 0, 1 }, # define USERS 22 { "users", INT_CONST, FALSE, 1, UCHAR_MAX }, # define NR_OPTIONS 23 }; typedef struct { char fill; char c; } alignc; typedef struct { char fill; short s; } aligns; typedef struct { char fill; Int i; } aligni; typedef struct { char fill; char *p; } alignp; typedef struct { char c; } alignz; typedef char dumpinfo[28]; # define FORMAT_VERSION 2 # define DUMP_VALID 0 /* valud dump flag */ # define DUMP_VERSION 1 /* dump file version number */ # define DUMP_DRIVER 2 /* 0: vanilla DGD, 1: iChat DGD */ # define DUMP_TYPECHECK 3 /* global typechecking */ # define DUMP_SECSIZE 4 /* sector size */ # define DUMP_TYPE 4 /* first XX bytes, dump type */ # define DUMP_STARTTIME 20 /* start time */ # define DUMP_ELAPSED 24 /* elapsed time */ static dumpinfo header; /* dumpfile header */ # define s0 (header[ 6]) /* short, msb */ # define s1 (header[ 7]) /* short, lsb */ # define i0 (header[ 8]) /* Int, msb */ # define i1 (header[ 9]) # define i2 (header[10]) # define i3 (header[11]) /* Int, lsb */ # define usize (header[12]) /* sizeof(uindex) */ # define dsize (header[13]) /* sizeof(sector) */ # define psize (header[14]) /* sizeof(char*) */ # define calign (header[15]) /* align(char) */ # define salign (header[16]) /* align(short) */ # define ialign (header[17]) /* align(Int) */ # define palign (header[18]) /* align(char*) */ # define zalign (header[19]) /* align(struct) */ static int ualign; /* align(uindex) */ static int dalign; /* align(sector) */ static dumpinfo rheader; /* restored header */ # define rs0 (rheader[ 6]) /* short, msb */ # define rs1 (rheader[ 7]) /* short, lsb */ # define ri0 (rheader[ 8]) /* Int, msb */ # define ri1 (rheader[ 9]) # define ri2 (rheader[10]) # define ri3 (rheader[11]) /* Int, lsb */ # define rusize (rheader[12]) /* sizeof(uindex) */ # define rdsize (rheader[13]) /* sizeof(sector) */ # define rpsize (rheader[14]) /* sizeof(char*) */ # define rcalign (rheader[15]) /* align(char) */ # define rsalign (rheader[16]) /* align(short) */ # define rialign (rheader[17]) /* align(Int) */ # define rpalign (rheader[18]) /* align(char*) */ # define rzalign (rheader[19]) /* align(struct) */ static int rualign; /* align(uindex) */ static int rdalign; /* align(sector) */ static Uint starttime; /* start time */ static Uint elapsed; /* elapsed time */ static Uint boottime; /* boot time */ /* * NAME: conf->dumpinit() * DESCRIPTION: initialize dump file information */ static void conf_dumpinit() { short s; Int i; alignc cdummy; aligns sdummy; aligni idummy; alignp pdummy; header[DUMP_VALID] = TRUE; /* valid dump flag */ header[DUMP_VERSION] = FORMAT_VERSION; /* dump file version number */ header[DUMP_DRIVER] = 0; /* vanilla DGD */ header[DUMP_TYPECHECK] = conf[TYPECHECKING].u.num; header[DUMP_SECSIZE + 0] = conf[SECTOR_SIZE].u.num >> 8; header[DUMP_SECSIZE + 1] = conf[SECTOR_SIZE].u.num; starttime = boottime = P_time(); s = 0x1234; i = 0x12345678L; s0 = strchr((char *) &s, 0x12) - (char *) &s; s1 = strchr((char *) &s, 0x34) - (char *) &s; i0 = strchr((char *) &i, 0x12) - (char *) &i; i1 = strchr((char *) &i, 0x34) - (char *) &i; i2 = strchr((char *) &i, 0x56) - (char *) &i; i3 = strchr((char *) &i, 0x78) - (char *) &i; usize = sizeof(uindex); dsize = sizeof(sector); psize = sizeof(char*); calign = (char *) &cdummy.c - (char *) &cdummy.fill; salign = (char *) &sdummy.s - (char *) &sdummy.fill; ialign = (char *) &idummy.i - (char *) &idummy.fill; palign = (char *) &pdummy.p - (char *) &pdummy.fill; zalign = sizeof(alignz); ualign = (usize == sizeof(short)) ? salign : ialign; dalign = (dsize == sizeof(short)) ? salign : ialign; } /* * NAME: conf->dump() * DESCRIPTION: dump system state on file */ void conf_dump() { int fd; Uint etime; header[DUMP_TYPECHECK] = conf[TYPECHECKING].u.num; header[DUMP_STARTTIME + 0] = starttime >> 24; header[DUMP_STARTTIME + 1] = starttime >> 16; header[DUMP_STARTTIME + 2] = starttime >> 8; header[DUMP_STARTTIME + 3] = starttime; etime = elapsed + P_time() - boottime; header[DUMP_ELAPSED + 0] = etime >> 24; header[DUMP_ELAPSED + 1] = etime >> 16; header[DUMP_ELAPSED + 2] = etime >> 8; header[DUMP_ELAPSED + 3] = etime; fd = sw_dump(conf[DUMP_FILE].u.str); if (!kf_dump(fd)) { fatal("failed to dump kfun table"); } if (!o_dump(fd)) { fatal("failed to dump object table"); } if (!pc_dump(fd)) { fatal("failed to dump precompiled objects"); } if (!co_dump(fd)) { fatal("failed to dump callout table"); } lseek(fd, 0L, SEEK_SET); write(fd, header, sizeof(dumpinfo)); } /* * NAME: conf->restore() * DESCRIPTION: restore system state from file */ static void conf_restore(fd) int fd; { unsigned int secsize; long posn; if (read(fd, rheader, sizeof(dumpinfo)) != sizeof(dumpinfo) || memcmp(header, rheader, DUMP_TYPE) != 0) { error("Bad or incompatible restore file header"); } starttime = (UCHAR(rheader[DUMP_STARTTIME + 0]) << 24) | (UCHAR(rheader[DUMP_STARTTIME + 1]) << 16) | (UCHAR(rheader[DUMP_STARTTIME + 2]) << 8) | UCHAR(rheader[DUMP_STARTTIME + 3]); elapsed = (UCHAR(rheader[DUMP_ELAPSED + 0]) << 24) | (UCHAR(rheader[DUMP_ELAPSED + 1]) << 16) | (UCHAR(rheader[DUMP_ELAPSED + 2]) << 8) | UCHAR(rheader[DUMP_ELAPSED + 3]); rualign = (rusize == sizeof(short)) ? rsalign : rialign; rdalign = (rdsize == sizeof(short)) ? rsalign : rialign; if (usize < rusize || dsize < rdsize) { error("Cannot restore uindex or sector of greater width"); } secsize = (UCHAR(rheader[DUMP_SECSIZE + 0]) << 8) | UCHAR(rheader[DUMP_SECSIZE + 1]); if (secsize > conf[SECTOR_SIZE].u.num) { error("Cannot restore bigger sector size"); } sw_restore(fd, secsize); kf_restore(fd); o_restore(fd); posn = lseek(fd, 0L, SEEK_CUR); /* preserve current file position */ o_conv(); /* convert all objects */ lseek(fd, posn, SEEK_SET); /* restore file position */ pc_restore(fd); boottime = P_time(); co_restore(fd, boottime); } /* * NAME: conf->dsize() * DESCRIPTION: compute the size and alignment of a struct * 0x000000ff size in dump file * 0x0000ff00 alignment in dump file * 0x00ff0000 size * 0xff000000 alignment */ Uint conf_dsize(layout) char *layout; { register char *p; register Uint sz, rsz, al, ral; register Uint size, rsize, align, ralign; p = layout; size = rsize = 0; align = ralign = 1; for (;;) { switch (*p++) { case 'c': /* character */ sz = rsz = sizeof(char); al = calign; ral = rcalign; break; case 's': /* short */ sz = rsz = sizeof(short); al = salign; ral = rsalign; break; case 'u': /* uindex */ sz = usize; rsz = rusize; al = ualign; ral = rualign; break; case 'i': /* Int */ sz = rsz = sizeof(Int); al = ialign; ral = rialign; break; case 'd': /* sector */ sz = dsize; rsz = rdsize; al = dalign; ral = rdalign; break; case 'p': /* pointer */ sz = psize; rsz = rpsize; al = palign; ral = rpalign; break; case 'x': /* hte */ size = ALGN(size, zalign); size = ALGN(size, palign); size += psize; size = ALGN(size, palign); size += psize; size = ALGN(size, zalign); rsize = ALGN(rsize, rzalign); rsize = ALGN(rsize, rpalign); rsize += rpsize; rsize = ALGN(rsize, rpalign); rsize += rpsize; rsize = ALGN(rsize, rzalign); align = ALGN(align, palign); ralign = ALGN(ralign, rpalign); continue; case '[': /* struct */ sz = conf_dsize(p); al = (sz >> 8) & 0xff; rsz = (sz >> 16) & 0xff; ral = sz >> 24; sz &= 0xff; p = strchr(p, ']') + 1; break; case ']': case '\0': /* end of layout */ if (p != layout + 2) { /* a stuct and not an array element */ align = ALGN(align, zalign); ralign = ALGN(ralign, rzalign); } return ALGN(rsize, ralign) | (ralign << 8) | (ALGN(size, align) << 16) | (align << 24); } size = ALGN(size, al) + sz; rsize = ALGN(rsize, ral) + rsz; align = ALGN(align, al); ralign = ALGN(ralign, ral); } } /* * NAME: conf_dconv() * DESCRIPTION: convert structs from dumpfile format */ Uint conf_dconv(buf, rbuf, layout, n) register char *buf, *rbuf; char *layout; Uint n; { register Uint i, ri, j, size, rsize; register char *p; rsize = conf_dsize(layout); size = (rsize >> 16) & 0xff; rsize &= 0xff; while (n > 0) { i = ri = 0; for (p = layout; *p != '\0' && *p != ']'; p++) { switch (*p) { case 'c': i = ALGN(i, calign); ri = ALGN(ri, rcalign); buf[i] = rbuf[ri]; i += sizeof(char); ri += sizeof(char); break; case 's': i = ALGN(i, salign); ri = ALGN(ri, rsalign); buf[i + s0] = rbuf[ri + rs0]; buf[i + s1] = rbuf[ri + rs1]; i += sizeof(short); ri += sizeof(short); break; case 'u': i = ALGN(i, ualign); ri = ALGN(ri, rualign); if (usize == rusize) { if (usize == sizeof(short)) { buf[i + s0] = rbuf[ri + rs0]; buf[i + s1] = rbuf[ri + rs1]; i += sizeof(short); ri += sizeof(short); } else { buf[i + i0] = rbuf[ri + ri0]; buf[i + i1] = rbuf[ri + ri1]; buf[i + i2] = rbuf[ri + ri2]; buf[i + i3] = rbuf[ri + ri3]; i += sizeof(Int); ri += sizeof(Int); } } else { j = (UCHAR(rbuf[ri + rs0] & rbuf[ri + rs1]) == 0xff) ? -1 : 0; buf[i + i0] = j; buf[i + i1] = j; buf[i + i2] = rbuf[ri + rs0]; buf[i + i3] = rbuf[ri + rs1]; i += sizeof(Int); ri += sizeof(short); } break; case 'i': i = ALGN(i, ialign); ri = ALGN(ri, rialign); buf[i + i0] = rbuf[ri + ri0]; buf[i + i1] = rbuf[ri + ri1]; buf[i + i2] = rbuf[ri + ri2]; buf[i + i3] = rbuf[ri + ri3]; i += sizeof(Int); ri += sizeof(Int); break; case 'd': i = ALGN(i, dalign); ri = ALGN(ri, rdalign); if (dsize == rdsize) { if (dsize == sizeof(short)) { buf[i + s0] = rbuf[ri + rs0]; buf[i + s1] = rbuf[ri + rs1]; i += sizeof(short); ri += sizeof(short); } else { buf[i + i0] = rbuf[ri + ri0]; buf[i + i1] = rbuf[ri + ri1]; buf[i + i2] = rbuf[ri + ri2]; buf[i + i3] = rbuf[ri + ri3]; i += sizeof(Int); ri += sizeof(Int); } } else { j = (UCHAR(rbuf[ri + rs0] & rbuf[ri + rs1]) == 0xff) ? -1 : 0; buf[i + i0] = j; buf[i + i1] = j; buf[i + i2] = rbuf[ri + rs0]; buf[i + i3] = rbuf[ri + rs1]; i += sizeof(Int); ri += sizeof(short); } break; case 'p': i = ALGN(i, palign); ri = ALGN(ri, rpalign); for (j = psize; j > 0; --j) { buf[i++] = 0; } ri += rpsize; break; case '[': j = conf_dsize(++p); i = ALGN(i, j >> 24); ri = ALGN(ri, (j >> 8) & 0xff); j = conf_dconv(buf + i, rbuf + ri, p, (Uint) 1); i += (j >> 16) & 0xff; ri += j & 0xff; p = strchr(p, ']'); break; case 'x': i = ALGN(i, zalign); i = ALGN(i, palign); for (j = psize; j > 0; --j) { buf[i++] = 0; } i = ALGN(i, palign); for (j = psize; j > 0; --j) { buf[i++] = 0; } ri = ALGN(ri, rzalign); ri = ALGN(ri, rpalign); ri += rpsize; ri = ALGN(ri, rpalign); for (j = rpsize; j > 0; --j) { if (rbuf[ri] != 0) { buf[i - 1] = 1; break; } ri++; } ri += j; i = ALGN(i, zalign); ri = ALGN(ri, rzalign); break; } } buf += size; rbuf += rsize; --n; } return (size << 16) | rsize; } /* * NAME: conf->dread() * DESCRIPTION: read from dumpfile */ void conf_dread(fd, buf, layout, n) int fd; char *buf, *layout; register Uint n; { char buffer[16384]; register unsigned int i, size, rsize; Uint tmp; tmp = conf_dsize(layout); size = (tmp >> 16) & 0xff; rsize = tmp & 0xff; while (n != 0) { i = sizeof(buffer) / rsize; if (i > n) { i = n; } if (read(fd, buffer, i * rsize) != i * rsize) { fatal("cannot read from dump file"); } conf_dconv(buf, buffer, layout, (Uint) i); buf += size * i; n -= i; } } # define MAX_DIRS 32 static char *dirs[MAX_DIRS]; /* * NAME: conferr() * DESCRIPTION: error during the configuration phase */ static void conferr(err) char *err; { message("Config error, line %u: %s\012", tk_line(), err); /* LF */ } /* * NAME: config->config() * DESCRIPTION: read config file */ static bool conf_config() { register char *p; register int h, l, m, c; for (h = NR_OPTIONS; h > 0; ) { conf[--h].u.num = 0; } memset(dirs, '\0', sizeof(dirs)); while ((c=pp_gettok()) != EOF) { if (c != IDENTIFIER) { conferr("option expected"); return FALSE; } l = 0; h = NR_OPTIONS; for (;;) { c = strcmp(yytext, conf[m = (l + h) >> 1].name); if (c == 0) { break; /* found */ } else if (c < 0) { h = m; /* search in lower half */ } else { l = m + 1; /* search in upper half */ } if (l >= h) { conferr("unknown option"); return FALSE; } } if (pp_gettok() != '=') { conferr("'=' expected"); return FALSE; } if ((c=pp_gettok()) != conf[m].type) { if (c != INT_CONST && c != STRING_CONST && c != '(') { conferr("syntax error"); return FALSE; } else { conferr("bad value type"); return FALSE; } } switch (c) { case INT_CONST: if (yylval.number < conf[m].low || (conf[m].high != 0 && yylval.number > conf[m].high)) { conferr("int value out of range"); return FALSE; } conf[m].u.num = yylval.number; break; case STRING_CONST: p = (m == AUTO_OBJECT || m == DRIVER_OBJECT || m == INCLUDE_FILE) ? path_resolve(yytext) : yytext; l = strlen(p); if (l >= STRINGSZ) { l = STRINGSZ - 1; p[l] = '\0'; } m_static(); conf[m].u.str = strcpy(REALLOC(conf[m].u.str, char, 0, l + 1), p); m_dynamic(); break; case '(': if (pp_gettok() != '{') { conferr("'{' expected"); return FALSE; } l = 0; for (;;) { if (pp_gettok() != STRING_CONST) { conferr("string expected"); return FALSE; } if (l == MAX_DIRS - 1) { conferr("too many include directories"); return FALSE; } m_static(); dirs[l] = strcpy(REALLOC(dirs[l], char, 0, strlen(yytext) + 1), yytext); l++; m_dynamic(); if ((c=pp_gettok()) == '}') { break; } if (c != ',') { conferr("',' expected"); return FALSE; } } if (pp_gettok() != ')') { conferr("')' expected"); return FALSE; } dirs[l] = (char *) NULL; break; } conf[m].set = TRUE; if (pp_gettok() != ';') { conferr("';' expected"); return FALSE; } } for (l = 0; l < NR_OPTIONS; l++) { if (!conf[l].set) { char buffer[64]; sprintf(buffer, "unspecified option %s", conf[l].name); conferr(buffer); return FALSE; } } } static char *fname; /* file name */ static int fd; /* file descriptor */ static char *obuf; /* output buffer */ static unsigned int bufsz; /* buffer size */ /* * NAME: config->open() * DESCRIPTION: create a new file */ static bool copen(file) char *file; { if ((file=path_file(fname=path_resolve(file))) == (char *) NULL || (fd=open(file, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0644)) < 0) { message("Config error: cannot create \"/%s\"\012", fname); /* LF */ return FALSE; } bufsz = 0; return TRUE; } /* * NAME: config->put() * DESCRIPTION: write a string to a file */ static void cputs(str) register char *str; { register unsigned int len, chunk; len = strlen(str); while (bufsz + len > BUF_SIZE) { chunk = BUF_SIZE - bufsz; memcpy(obuf + bufsz, str, chunk); write(fd, obuf, BUF_SIZE); str += chunk; len -= chunk; bufsz = 0; } if (len > 0) { memcpy(obuf + bufsz, str, len); bufsz += len; } } /* * NAME: config->close() * DESCRIPTION: close a file */ static bool cclose() { if (bufsz > 0 && write(fd, obuf, bufsz) != bufsz) { message("Config error: cannot write \"/%s\"\012", fname); /* LF */ close(fd); return FALSE; } close(fd); return TRUE; } /* * NAME: config->includes() * DESCRIPTION: create include files */ static bool conf_includes() { char buf[BUF_SIZE], buffer[STRINGSZ]; /* create status.h file */ obuf = buf; sprintf(buffer, "%s/status.h", dirs[0]); if (!copen(buffer)) { return FALSE; } cputs("/*\012 * This file defines the fields of the array returned "); cputs("by the\012 * status() kfun. It is automatically generated "); cputs("by DGD on startup.\012 */\012\012"); cputs("# define ST_VERSION\t0\t/* driver version */\012"); cputs("# define ST_STARTTIME\t1\t/* system start time */\012"); cputs("# define ST_BOOTTIME\t2\t/* system reboot time */\012"); cputs("# define ST_UPTIME\t3\t/* system virtual uptime */\012"); cputs("# define ST_SWAPSIZE\t4\t/* # sectors on swap device */\012"); cputs("# define ST_SWAPUSED\t5\t/* # sectors allocated */\012"); cputs("# define ST_SECTORSIZE\t6\t/* size of swap sector */\012"); cputs("# define ST_SWAPRATE1\t7\t/* # objects swapped out per minute */\012"); cputs("# define ST_SWAPRATE5\t8\t/* # objects swapped out per five minutes */\012"); cputs("# define ST_SMEMSIZE\t9\t/* static memory allocated */\012"); cputs("# define ST_SMEMUSED\t10\t/* static memory in use */\012"); cputs("# define ST_DMEMSIZE\t11\t/* dynamic memory allocated */\012"); cputs("# define ST_DMEMUSED\t12\t/* dynamic memory in use */\012"); cputs("# define ST_OTABSIZE\t13\t/* object table size */\012"); cputs("# define ST_NOBJECTS\t14\t/* # objects in the system */\012"); cputs("# define ST_COTABSIZE\t15\t/* callouts table size */\012"); cputs("# define ST_NCOSHORT\t16\t/* # short-term callouts */\012"); cputs("# define ST_NCOLONG\t17\t/* # long-term callouts */\012"); cputs("# define ST_UTABSIZE\t18\t/* user table size */\012"); cputs("# define ST_ETABSIZE\t19\t/* editor table size */\012"); cputs("# define ST_STRSIZE\t20\t/* max string size */\012"); cputs("# define ST_ARRAYSIZE\t21\t/* max array/mapping size */\012"); cputs("# define ST_STACKDEPTH\t22\t/* remaining stack depth */\012"); cputs("# define ST_TICKS\t23\t/* remaining ticks */\012"); cputs("# define ST_PRECOMPILED\t24\t/* precompiled objects */\012"); cputs("\012# define O_COMPILETIME\t0\t/* time of compilation */\012"); cputs("# define O_PROGSIZE\t1\t/* program size of object */\012"); cputs("# define O_DATASIZE\t2\t/* # variables in object */\012"); cputs("# define O_NSECTORS\t3\t/* # sectors used by object */\012"); cputs("# define O_CALLOUTS\t4\t/* callouts in object */\012"); cputs("# define O_INDEX\t5\t/* unique ID for master object */\012"); cputs("\012# define CO_HANDLE\t0\t/* callout handle */\012"); cputs("# define CO_FUNCTION\t1\t/* function name */\012"); cputs("# define CO_DELAY\t2\t/* delay */\012"); cputs("# define CO_FIRSTXARG\t3\t/* first extra argument */\012"); if (!cclose()) { return FALSE; } /* create type.h file */ sprintf(buffer, "%s/type.h", dirs[0]); if (!copen(buffer)) { return FALSE; } cputs("/*\012 * This file gives definitions for the value returned "); cputs("by the\012 * typeof() kfun. It is automatically generated "); cputs("by DGD on startup.\012 */\012\012"); sprintf(buffer, "# define T_INT\t\t%d\012", T_INT); cputs(buffer); sprintf(buffer, "# define T_FLOAT\t%d\012", T_FLOAT); cputs(buffer); sprintf(buffer, "# define T_STRING\t%d\012", T_STRING); cputs(buffer); sprintf(buffer, "# define T_OBJECT\t%d\012", T_OBJECT); cputs(buffer); sprintf(buffer, "# define T_ARRAY\t%d\012", T_ARRAY); cputs(buffer); sprintf(buffer, "# define T_MAPPING\t%d\012", T_MAPPING); cputs(buffer); if (!cclose()) { return FALSE; } /* create limits.h file */ sprintf(buffer, "%s/limits.h", dirs[0]); if (!copen(buffer)) { return FALSE; } cputs("/*\012 * This file defines some basic sizes of datatypes and "); cputs("resources.\012 * It is automatically generated by DGD on "); cputs("startup.\012 */\012\012"); cputs("# define CHAR_BIT\t\t8\t\t/* # bits in character */\012"); cputs("# define CHAR_MIN\t\t0\t\t/* min character value */\012"); cputs("# define CHAR_MAX\t\t255\t\t/* max character value */\012\012"); cputs("# define INT_MIN\t\t0x80000000\t/* -2147483648 */\012"); cputs("# define INT_MAX\t\t2147483647\t/* max integer value */\012\012"); sprintf(buffer, "# define MAX_STRING_SIZE\t%u\t\t/* max string size */\012", USHRT_MAX); cputs(buffer); if (!cclose()) { return FALSE; } /* create float.h file */ sprintf(buffer, "%s/float.h", dirs[0]); if (!copen(buffer)) { return FALSE; } cputs("/*\012 * This file describes the floating point type. It is "); cputs("automatically\012 * generated by DGD on startup.\012 */\012\012"); cputs("# define FLT_RADIX\t2\t\t\t/* binary */\012"); cputs("# define FLT_ROUNDS\t1\t\t\t/* round to nearest */\012"); cputs("# define FLT_EPSILON\t7.2759576142E-12\t/* smallest x: 1.0 + x != 1.0 */\012"); cputs("# define FLT_DIG\t10\t\t\t/* decimal digits of precision*/\012"); cputs("# define FLT_MANT_DIG\t36\t\t\t/* binary digits of precision */\012"); cputs("# define FLT_MIN\t2.22507385851E-308\t/* positive minimum */\012"); cputs("# define FLT_MIN_EXP\t(-1021)\t\t\t/* minimum binary exponent */\012"); cputs("# define FLT_MIN_10_EXP\t(-307)\t\t\t/* minimum decimal exponent */\012"); cputs("# define FLT_MAX\t1.79769313485E+308\t/* positive maximum */\012"); cputs("# define FLT_MAX_EXP\t1024\t\t\t/* maximum binary exponent */\012"); cputs("# define FLT_MAX_10_EXP\t308\t\t\t/* maximum decimal exponent */\012"); if (!cclose()) { return FALSE; } /* create trace.h file */ sprintf(buffer, "%s/trace.h", dirs[0]); if (!copen(buffer)) { return FALSE; } cputs("/*\012 * This file describes the fields of the array returned for "); cputs("every stack\012 * frame by the call_trace() function. It is "); cputs("automatically generated by DGD\012 * on startup.\012 */\012\012"); cputs("# define TRACE_OBJNAME\t0\t/* name of the object */\012"); cputs("# define TRACE_PROGNAME\t1\t/* name of the object the function is in */\012"); cputs("# define TRACE_FUNCTION\t2\t/* function name */\012"); cputs("# define TRACE_LINE\t3\t/* line number */\012"); cputs("# define TRACE_EXTERNAL\t4\t/* external call flag */\012"); cputs("# define TRACE_FIRSTARG\t5\t/* first argument to function */\012"); return cclose(); } /* * NAME: config->init() * DESCRIPTION: initialize the driver */ bool conf_init(configfile, fd) char *configfile; int fd; { bool init; /* * process config file */ if (!pp_init(configfile, (char **) NULL, 0)) { message("Config error: cannot open config file\012"); /* LF */ m_finish(); return FALSE; } init = conf_config(); pp_clear(); if (!init) { m_finish(); return FALSE; } /* change directory */ if (chdir(conf[DIRECTORY].u.str) < 0) { message("Config error: bad base directory \"%s\"\012", /* LF */ conf[DIRECTORY].u.str); m_finish(); return FALSE; } m_static(); /* initialize strings */ str_init(); /* initialize arrays */ arr_init((int) conf[ARRAY_SIZE].u.num); /* initialize objects */ o_init((uindex) conf[OBJECTS].u.num); /* initialize swap device */ sw_init(conf[SWAP_FILE].u.str, (sector) conf[SWAP_SIZE].u.num, (sector) conf[CACHE_SIZE].u.num, (unsigned int) conf[SECTOR_SIZE].u.num); /* initialize swapped data handler */ d_init(); /* initalize editor */ ed_init(conf[ED_TMPFILE].u.str, (int) conf[EDITORS].u.num); /* initialize call_outs */ co_init((uindex) conf[CALL_OUTS].u.num, (int) conf[SWAP_FRAGMENT].u.num); /* initialize kfuns */ kf_init(); /* initialize interpreter */ i_init(conf[CREATE].u.str); /* initialize compiler */ c_init(conf[AUTO_OBJECT].u.str, conf[DRIVER_OBJECT].u.str, conf[INCLUDE_FILE].u.str, dirs); m_dynamic(); if (!init) { comm_finish(); m_finish(); return FALSE; } /* initialize memory manager */ m_init((size_t) conf[STATIC_CHUNK].u.num, (size_t) conf[DYNAMIC_CHUNK].u.num); /* initialize communications */ m_static(); comm_init((int) conf[USERS].u.num); m_dynamic(); /* * create include files */ if (!conf_includes()) { comm_finish(); m_finish(); return FALSE; } /* preload compiled objects */ pc_preload(conf[AUTO_OBJECT].u.str, conf[DRIVER_OBJECT].u.str); /* initialize dumpfile header */ conf_dumpinit(); if (ec_push((ec_ftn) NULL)) { endthread(); message((char *) NULL); message("Config error: initialization failed\012"); /* LF */ comm_finish(); ed_finish(); m_finish(); return FALSE; } if (fd < 0) { /* initialize mudlib */ call_driver_object(cframe, "initialize", 0); } else { /* restore dump file */ conf_restore(fd); /* notify mudlib */ call_driver_object(cframe, "restored", 0); } ec_pop(); i_del_value(cframe->sp++); endthread(); return TRUE; } /* * NAME: config->base_dir() * DESCRIPTION: return the driver base directory */ char *conf_base_dir() { return conf[DIRECTORY].u.str; } /* * NAME: config->driver() * DESCRIPTION: return the driver object name */ char *conf_driver() { return conf[DRIVER_OBJECT].u.str; } /* * NAME: config->typechecking() * DESCRIPTION: return the global typechecking flag */ bool conf_typechecking() { return (bool) conf[TYPECHECKING].u.num; } /* * NAME: config->array_size() * DESCRIPTION: return the maximum array size */ unsigned short conf_array_size() { return conf[ARRAY_SIZE].u.num; } /* * NAME: config->statusi() * DESCRIPTION: return resource usage information */ bool conf_statusi(f, idx, v) frame *f; Int idx; register value *v; { char *version; allocinfo *mstat; uindex ncoshort, ncolong; switch (idx) { case 0: /* ST_VERSION */ v->type = T_STRING; version = VERSION; str_ref(v->u.string = str_new(version, (long) strlen(version))); break; case 1: /* ST_STARTTIME */ v->type = T_INT; v->u.number = starttime; break; case 2: /* ST_BOOTTIME */ v->type = T_INT; v->u.number = boottime; break; case 3: /* ST_UPTIME */ v->type = T_INT; v->u.number = elapsed + P_time() - boottime; break; case 4: /* ST_SWAPSIZE */ v->type = T_INT; v->u.number = conf[SWAP_SIZE].u.num; break; case 5: /* ST_SWAPUSED */ v->type = T_INT; v->u.number = sw_count(); break; case 6: /* ST_SECTORSIZE */ v->type = T_INT; v->u.number = conf[SECTOR_SIZE].u.num; break; case 7: /* ST_SWAPRATE1 */ v->type = T_INT; v->u.number = co_swaprate1(); break; case 8: /* ST_SWAPRATE5 */ v->type = T_INT; v->u.number = co_swaprate5(); break; case 9: /* ST_SMEMSIZE */ mstat = m_info(); v->type = T_INT; v->u.number = mstat->smemsize; break; case 10: /* ST_SMEMUSED */ mstat = m_info(); v->type = T_INT; v->u.number = mstat->smemused; break; case 11: /* ST_DMEMSIZE */ mstat = m_info(); v->type = T_INT; v->u.number = mstat->dmemsize; break; case 12: /* ST_DMEMUSED */ mstat = m_info(); v->type = T_INT; v->u.number = mstat->dmemused; break; case 13: /* ST_OTABSIZE */ v->type = T_INT; v->u.number = conf[OBJECTS].u.num; break; case 14: /* ST_NOBJECTS */ v->type = T_INT; v->u.number = o_count(); break; case 15: /* ST_COTABSIZE */ v->type = T_INT; v->u.number = conf[CALL_OUTS].u.num; break; case 16: /* ST_NCOSHORT */ co_info(&ncoshort, &ncolong); v->type = T_INT; v->u.number = ncoshort; break; case 17: /* ST_NCOLONG */ co_info(&ncoshort, &ncolong); v->type = T_INT; v->u.number = ncolong; break; case 18: /* ST_UTABSIZE */ v->type = T_INT; v->u.number = conf[USERS].u.num; break; case 19: /* ST_ETABSIZE */ v->type = T_INT; v->u.number = conf[EDITORS].u.num; break; case 20: /* ST_STRSIZE */ v->type = T_INT; v->u.number = USHRT_MAX; break; case 21: /* ST_ARRAYSIZE */ v->type = T_INT; v->u.number = conf[ARRAY_SIZE].u.num; break; case 22: /* ST_STACKDEPTH */ v->type = T_INT; v->u.number = i_get_depth(f); break; case 23: /* ST_TICKS */ v->type = T_INT; v->u.number = i_get_ticks(f); break; case 24: /* ST_PRECOMPILED */ v->type = T_ARRAY; arr_ref(v->u.array = pc_list(f->data)); break; default: return FALSE; } return TRUE; } /* * NAME: config->status() * DESCRIPTION: return an array with information about resource usage */ array *conf_status(f) register frame *f; { register value *v; register Int i; array *a; a = arr_new(f->data, 25L); for (i = 0, v = a->elts; i < 25; i++, v++) { conf_statusi(f, i, v); } return a; } /* * NAME: config->objecti() * DESCRIPTION: return object resource usage information */ bool conf_objecti(data, obj, idx, v) dataspace *data; register object *obj; Int idx; register value *v; { register control *ctrl; object *prog; prog = (obj->flags & O_MASTER) ? obj : &otable[obj->u_master]; ctrl = (O_UPGRADING(prog)) ? otable[prog->prev].ctrl : o_control(prog); switch (idx) { case 0: /* O_COMPILETIME */ v->type = T_INT; v->u.number = ctrl->compiled; break; case 1: /* O_PROGSIZE */ v->type = T_INT; v->u.number = d_get_progsize(ctrl); break; case 2: /* O_DATASIZE */ v->type = T_INT; v->u.number = ctrl->nvariables; break; case 3: /* O_NSECTORS */ v->type = T_INT; v->u.number = (obj->flags & O_CREATED) ? o_dataspace(obj)->nsectors : 0; if (obj->flags & O_MASTER) { v->u.number += ctrl->nsectors; } break; case 4: /* O_CALLOUTS */ v->type = T_ARRAY; arr_ref(v->u.array = (obj->flags & O_CREATED) ? co_list(data, obj) : arr_new(data, 0L)); break; case 5: /* O_INDEX */ v->type = T_INT; v->u.number = (obj->flags & O_MASTER) ? (Uint) obj->index : obj->u_master; break; default: return FALSE; } return TRUE; } /* * NAME: config->object() * DESCRIPTION: return resource usage of an object */ array *conf_object(data, obj) register dataspace *data; register object *obj; { register value *v; register Int i; array *a; a = arr_new(data, 6L); for (i = 0, v = a->elts; i < 6; i++, v++) { conf_objecti(data, obj, i, v); } return a; }