home *** CD-ROM | disk | FTP | other *** search
- /* xlimage - xlisp memory image save/restore functions */
- /* Copyright (c) 1985, by David Michael Betz
- All Rights Reserved
- Permission is granted for unrestricted non-commercial use */
- /* modified so that offset is in sizeof(node) units TAA */
- #include "xlisp.h"
-
- #ifdef SAVERESTORE
-
- #define FILENIL ((OFFTYPE)0) /* value of NIL in a file */
-
- /* external variables */
- extern LVAL obarray,xlenv,xlfenv,xldenv,s_gchook,s_gcflag;
- extern long nnodes,nfree,total;
- extern int anodes,nsegs,gccalls;
- extern struct segment XFAR *segs, XFAR *lastseg, XFAR *fixseg, XFAR *charseg;
- extern CONTEXT *xlcontext;
- extern LVAL fnodes;
- extern int ftabsize; /* TAA MOD -- added validity check */
-
- /* external functions */
- #ifdef ANSI
- extern int scanvmemory(int size);
- extern void newvsegment(unsigned int n); /* really returns structure we
- don't care about */
- #endif
-
- /* For vector memory management */
- #define btow_size(n) (((n) + sizeof(LVAL) - 1) / sizeof(LVAL))
-
- typedef struct vsegment {
- struct vsegment XFAR *vs_next; /* next vector segment */
- LVAL XFAR *vs_free; /* next free location in this segment */
- LVAL XFAR *vs_top; /* top of segment (plus one) */
- LVAL vs_data[1]; /* segment data */
- } VSEGMENT;
-
- extern VSEGMENT XFAR *vsegments; /* list of vector segments */
- extern VSEGMENT XFAR *vscurrent; /* current vector segment */
- extern int vscount; /* number of vector segments */
- extern LVAL XFAR *vfree; /* next free location in vector space */
- extern LVAL XFAR *vtop; /* top of vector space */
-
- /* local variables */
- static OFFTYPE off,foff;
- static FILEP fp;
-
- /* forward declarations */
- #ifdef ANSI
- OFFTYPE XNEAR readptr(void);
- OFFTYPE XNEAR cvoptr(LVAL p);
- LVAL XNEAR cviptr(OFFTYPE o);
- #ifdef SERVER
- void freeimage(void);
- #else
- void XNEAR freeimage(void);
- #endif
- void XNEAR setoffset(void);
- void XNEAR writenode(LVAL node);
- void XNEAR writeptr(OFFTYPE off);
- void XNEAR readnode(int type, LVAL node);
- LVAL XFAR * XNEAR getvspace(LVAL node, unsigned int size);
- #else
- OFFTYPE readptr();
- OFFTYPE cvoptr();
- LVAL cviptr();
- VOID freeimage();
- VOID setoffset();
- VOID writenode();
- VOID writeptr();
- VOID readnode();
- LVAL *getvspace();
- #endif
-
- /* xlisave - save the memory image */
- int xlisave(fname)
- char *fname;
- {
- char fullname[STRMAX+1];
- SEGMENT XFAR *seg;
- int n;
- unsigned i,max;
- LVAL p;
-
- /* default the extension */
- if (needsextension(fname)) {
- strcpy(fullname,fname);
- strcat(fullname,".wks");
- fname = fullname;
- }
-
- /* open the output file */
-
- if ((fp = OSBOPEN(fname,CREATE_WR)) == CLOSED)
- return (FALSE);
-
- /* first call the garbage collector to clean up memory */
- gc();
-
- /* write out size of ftab (used as validity check) TAA MOD */
- writeptr((OFFTYPE)(ftabsize+1));
-
- /* write out the pointer to the *obarray* symbol */
- writeptr(cvoptr(obarray));
-
- /* write out components of NIL other than value, which must be NIL */
- writeptr(cvoptr(getfunction(NIL)));
- writeptr(cvoptr(getplist(NIL)));
- writeptr(cvoptr(getpname(NIL)));
-
- /* setup the initial file offsets */
- off = foff = (OFFTYPE)2;
-
- /* write out all nodes that are still in use */
- for (seg = segs; seg != NULL; seg = seg->sg_next) {
- p = &seg->sg_nodes[0];
- for (n = seg->sg_size; --n >= 0; ++p, off++)
- switch (ntype(p)) {
- case FREE:
- break;
- case CONS:
- case USTREAM:
- setoffset();
- OSPUTC(p->n_type,fp);
- writeptr(cvoptr(car(p)));
- writeptr(cvoptr(cdr(p)));
- foff++;
- break;
- default:
- setoffset();
- writenode(p);
- break;
- }
- }
-
- /* write the terminator */
- OSPUTC(FREE,fp);
- writeptr((OFFTYPE)0);
-
- /* write out data portion of SYMBOL/VECTOR/OBJECT/STRING/CLOSURE nodes */
- for (seg = segs; seg != NULL; seg = seg->sg_next) {
- p = &seg->sg_nodes[0];
- for (n = seg->sg_size; --n >= 0; ++p)
- switch (ntype(p)) {
- case SYMBOL:
- case OBJECT:
- case VECTOR:
- case CLOSURE:
- case STRUCT:
- #ifdef COMPLX
- case COMPLEX:
- #endif
- max = getsize(p);
- for (i = 0; i < max; ++i)
- writeptr(cvoptr(getelement(p,i)));
- break;
- case STRING:
- #ifdef MEDMEM
- { /* UGLY, but we gotta do it */
- char XFAR *strp= getstring(p);
- max = getslength(p)+1;
- while (max--) OSPUTC(*strp++, fp);
- break;
- }
- #else
- max = getslength(p)+1;
- OSWRITE(getstring(p),1,max,fp);
- break;
- #endif
- #ifdef FILETABLE
- case STREAM:
- if (getfile(p) > CONSOLE ) {
- OSWRITE(filetab[getfile(p)].tname,1,FNAMEMAX,fp);
- *(long *)buf = OSTELL(getfile(p));
- OSWRITE(buf,1,sizeof(long),fp);
- }
- break;
- #endif
- }
- }
-
- /* close the output file */
- OSCLOSE(fp);
-
- /* return successfully */
- return (TRUE);
- }
-
- /* xlirestore - restore a saved memory image */
- int xlirestore(fname)
- char *fname;
- {
- extern FUNDEF funtab[];
- char fullname[STRMAX+1];
- int n,type;
- unsigned i,max;
- SEGMENT XFAR *seg;
- LVAL p;
-
- /* default the extension */
- if (needsextension(fname)) {
- strncpy(fullname,fname,STRMAX-4);
- strcat(fullname,".wks");
- fname = fullname;
- }
-
- /* open the file */
- #ifdef PATHNAMES
- if ((fp = ospopen(fname,FALSE)) == CLOSED)
- #else
- if ((fp = OSBOPEN(fname,OPEN_RO)) == CLOSED)
- #endif
- return (FALSE);
-
- /* Check for file validity TAA MOD */
- if (readptr() != (OFFTYPE) (ftabsize+1)) {
- OSCLOSE(fp); /* close it -- we failed */
- return (FALSE);
- }
-
- /* free the old memory image */
- freeimage();
-
- /* initialize */
- off = (OFFTYPE)2;
- total = nnodes = nfree = 0L;
- fnodes = NIL;
- segs = lastseg = NULL;
- vsegments = vscurrent = NULL;
- vfree = vtop = NULL;
- vscount = 0;
- nsegs = gccalls = 0;
- xlenv = xlfenv = xldenv = s_gchook = s_gcflag = NIL;
- xlstack = xlstkbase + EDEPTH;
- xlfp = xlsp = xlargstkbase;
- *xlsp++ = NIL;
- xlcontext = NULL;
-
- /* create the fixnum segment */
- if ((fixseg = newsegment(SFIXSIZE)) == NULL)
- xlfatal("insufficient memory - fixnum segment");
-
- /* create the character segment */
- if ((charseg = newsegment(CHARSIZE)) == NULL)
- xlfatal("insufficient memory - character segment");
-
- /* read the pointer to the *obarray* symbol */
- obarray = cviptr(readptr());
-
- /* read components of NIL other than value, which must be NIL */
- NIL->n_vdata = getvspace(NIL,SYMSIZE); /* realocate array portion */
- setvalue(NIL, NIL);
- setfunction(NIL, cviptr(readptr()));
- setplist(NIL, cviptr(readptr()));
- setpname(NIL, cviptr(readptr()));
-
-
- /* read each node */
- while ((type = OSGETC(fp)) >= 0)
- switch (type) {
- case FREE:
- if ((off = readptr()) == (OFFTYPE)0)
- goto done;
- break;
- case CONS:
- case USTREAM:
- p = cviptr(off);
- p->n_type = type;
- rplaca(p,cviptr(readptr()));
- rplacd(p,cviptr(readptr()));
- off++;
- break;
- default:
- readnode(type,cviptr(off));
- off++;
- break;
- }
- done:
-
-
- /* read the data portion of SYMBOL/VECTOR/OBJECT/STRING/CLOSURE nodes */
- for (seg = segs; seg != NULL; seg = seg->sg_next) {
- p = &seg->sg_nodes[0];
- for (n = seg->sg_size; --n >= 0; ++p)
- switch (ntype(p)) {
- case SYMBOL:
- case OBJECT:
- case VECTOR:
- case CLOSURE:
- case STRUCT:
- #ifdef COMPLX
- case COMPLEX:
- #endif
- max = getsize(p);
- p->n_vdata = getvspace(p,max);
- for (i = 0; i < max; ++i)
- setelement(p,i,cviptr(readptr()));
- break;
- case STRING:
- #ifdef MEDMEM
- {
- char XFAR *chp; int ch;
- max = getslength(p)+1;
- p->n_string = (char XFAR*)getvspace(p,btow_size(max));
- chp = getstring(p);
- while (max--) {
- if ((ch = OSGETC(fp)) != EOF) *chp++ = ch;
- else xlfatal("image file corrupted");
- }
- break;
- }
- #else
- max = getslength(p)+1;
- p->n_string = (char *)getvspace(p,btow_size(max));
- if (OSREAD(getstring(p),1,max,fp)!=max)
- xlfatal("image file corrupted");
- break;
- #endif
- case STREAM:
- #ifdef FILETABLE
- if (getfile(p) > CONSOLE) { /* actual file to modify */
- unsigned long fpos;
- FILEP f;
-
- if (OSREAD(buf, 1, FNAMEMAX, fp) != FNAMEMAX ||
- OSREAD(&fpos, 1, sizeof(long), fp) != sizeof(long))
- xlfatal("image file corrupted");
- /* open file in same type, file must exist to succeed */
- f = ((p->n_sflags & S_BINARY)? OSBOPEN : OSAOPEN)
- (buf, (p->n_sflags&S_FORWRITING)? OPEN_UPDATE: OPEN_RO);
- setfile(p, f);
- if (f != CLOSED) {/* position to same point,
- or end if file too short */
- OSSEEKEND(f);
- if (OSTELL(f) > fpos) OSSEEK(f, fpos);
- }
- }
- break;
- #else
- setfile(p, CLOSED);
- break;
- #endif
- case SUBR:
- case FSUBR:
- p->n_subr = funtab[getoffset(p)].fd_subr;
- break;
- }
- }
-
- if (OSREAD(buf, 1, 1, fp) != 0) /* file too long! */
- xlfatal("image file corrupted--too long");
-
- /* close the input file */
- OSCLOSE(fp);
-
- /* collect to initialize the free space */
- gc();
-
-
- /* lookup all of the symbols the interpreter uses */
- xlsymbols();
-
-
- /* return successfully */
- return (TRUE);
- }
-
- /* freeimage - free the current memory image */
- #ifdef SERVER
- VOID freeimage()
- #else
- LOCAL VOID XNEAR freeimage()
- #endif
- {
- SEGMENT XFAR *seg, XFAR *next;
- VSEGMENT XFAR *vseg, XFAR *nextv;
- FILEP fp;
- LVAL p;
- int n;
-
- /* make sure any streams are closed before deleteing segments */
- for (seg = segs; seg != NULL; seg = next) {
- p = &seg->sg_nodes[0];
- for (n = seg->sg_size; --n >= 0; ++p)
- if (ntype(p) == STREAM) {
- if (((fp = getfile(p)) != CLOSED) &&
- (fp != STDIN && fp != STDOUT && fp != CONSOLE)) /*TAA Fix*/
- OSCLOSE(fp);
- }
- next = seg->sg_next;
- MFREE(seg);
- }
-
- for (vseg = vsegments; vseg !=NULL; vseg = nextv) {
- nextv = vseg->vs_next;
- MFREE(vseg);
- }
- }
-
- /* setoffset - output a positioning command if nodes have been skipped */
- LOCAL VOID XNEAR setoffset()
- {
- if (off != foff) {
- OSPUTC(FREE,fp);
- writeptr(off);
- foff = off;
- }
- }
-
- /* writenode - write a node to a file */
- LOCAL VOID XNEAR writenode(node)
- LVAL node;
- {
- #ifdef MEDMEM
- char buf[sizeof(union ninfo)];
- MEMCPY(buf, &node->n_info, sizeof(union ninfo));
- #endif
- OSPUTC(node->n_type,fp);
- #ifdef MEDMEM
- OSWRITE(buf, sizeof(union ninfo), 1, fp);
- #else
- OSWRITE(&node->n_info, sizeof(union ninfo), 1, fp);
- #endif
- #ifdef ALIGN32
- if (node->n_type == SYMBOL) OSPUTC(node->n_spflags,fp);
- #endif
- foff++;
- }
-
- /* writeptr - write a pointer to a file */
- LOCAL VOID XNEAR writeptr(off)
- OFFTYPE off;
- {
- OSWRITE(&off, sizeof(OFFTYPE), 1, fp);
- }
-
- /* readnode - read a node */
- LOCAL VOID XNEAR readnode(type,node)
- int type; LVAL node;
- {
- #ifdef MEDMEM
- char buf[sizeof(union ninfo)];
- #endif
-
- node->n_type = type;
- #ifdef MEDMEM
- if (OSREAD(buf, sizeof(union ninfo), 1, fp) != 1)
- xlfatal("image file corrupted");
- MEMCPY(&node->n_info, buf, sizeof(union ninfo));
- #else
- if (OSREAD(&node->n_info, sizeof(union ninfo), 1, fp) != 1)
- xlfatal("image file corrupted");
- #endif
- #ifdef ALIGN32
- if (type == SYMBOL) node->n_spflags = OSGETC(fp);
- #endif
- }
-
- /* readptr - read a pointer */
- LOCAL OFFTYPE XNEAR readptr()
- {
- OFFTYPE off;
- if (OSREAD(&off, sizeof(OFFTYPE), 1, fp) != 1)
- xlfatal("image file corrupted");
- return (off);
- }
-
- /* cviptr - convert a pointer on input */
- LOCAL LVAL XNEAR cviptr(o)
- OFFTYPE o;
- {
- OFFTYPE off = (OFFTYPE)2;
- SEGMENT XFAR *seg;
-
- /* check for nil */
- if (o == FILENIL)
- return (NIL);
-
- /* compute a pointer for this offset */
- for (seg = segs; seg != NULL; seg = seg->sg_next) {
- if (o < off + (OFFTYPE)seg->sg_size)
- return (seg->sg_nodes + (unsigned int)(o - off));
- off += (OFFTYPE)seg->sg_size;
- }
-
- /* create new segments if necessary */
- for (;;) {
-
- /* create the next segment */
- if ((seg = newsegment(anodes)) == NULL)
- xlfatal("insufficient memory - segment");
-
- /* check to see if the offset is in this segment */
- if (o < off + (OFFTYPE)seg->sg_size)
- return (seg->sg_nodes + (unsigned int)(o - off));
- off += (OFFTYPE)seg->sg_size;
- }
- }
- /* cvoptr - convert a pointer on output */
- LOCAL OFFTYPE XNEAR cvoptr(p)
- LVAL p;
- {
- OFFTYPE off = (OFFTYPE)2;
- SEGMENT XFAR *seg;
- OFFTYPE np = CVPTR(p);
-
- /* check for nil */
- if (null(p))
- return (FILENIL);
-
- /* compute an offset for this pointer */
- for (seg = segs; seg != NULL; seg = seg->sg_next) {
- if (np >= CVPTR(&seg->sg_nodes[0]) &&
- np < CVPTR(&seg->sg_nodes[seg->sg_size]))
- return (off+ ((np-CVPTR(seg->sg_nodes))/sizeof(struct node)));
- off += (OFFTYPE)seg->sg_size;
- }
-
- /* pointer not within any segment */
- xlerror("bad pointer found during image save",p);
- return (0); /* fake out compiler warning */
- }
-
-
- /* getvspace - allocate vector space */
- LOCAL LVAL XFAR * XNEAR getvspace(node,size)
- LVAL node; unsigned int size;
- {
- LVAL XFAR *p;
- ++size; /* space for the back pointer */
- if ((unsigned)vtop-(unsigned)vfree < size*sizeof(LVAL XFAR *) &&
- !scanvmemory(size)) {
- newvsegment(size);
- if ((unsigned)vtop-(unsigned)vfree<size*sizeof(LVAL XFAR *))
- xlfatal("insufficient vector space");
- }
- p = vfree;
- vfree += size;
- *p++ = node;
- return (p);
- }
- #endif
-
-