/* 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 */ #include "xlisp.h" #include #include #ifdef SAVERESTORE /* 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 *segs,*lastseg,*fixseg,*charseg; extern CONTEXT *xlcontext; extern LVAL fnodes; /* local variables */ static OFFTYPE off,foff; static FILE *fp; /* forward declarations */ #ifdef ANSI OFFTYPE readptr(void); OFFTYPE cvoptr(LVAL p); LVAL cviptr(OFFTYPE o); void freeimage(void); void setoffset(void); void writenode(LVAL node); void writeptr(OFFTYPE off); void readnode(int type, LVAL node); #else OFFTYPE readptr(); OFFTYPE cvoptr(); LVAL cviptr(); VOID freeimage(); VOID setoffset(); VOID writenode(); VOID writeptr(); VOID readnode(); #endif /* xlisave - save the memory image */ int xlisave(fname) char *fname; { char fullname[STRMAX+1]; SEGMENT *seg; int n,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,"w")) == NULL) return (FALSE); /* first call the garbage collector to clean up memory */ gc(); /* write out the pointer to the *obarray* symbol */ writeptr(cvoptr(obarray)); /* 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(); fputc(p->n_type,fp); writeptr(cvoptr(car(p))); writeptr(cvoptr(cdr(p))); foff++; break; default: setoffset(); writenode(p); break; } } /* write the terminator */ fputc(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: #ifdef STRUCTS case STRUCT: #endif max = getsize(p); for (i = 0; i < max; ++i) writeptr(cvoptr(getelement(p,i))); break; case STRING: max = getslength(p); fwrite(getstring(p),1,max,fp); break; } } /* 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,i,max,type; SEGMENT *seg; LVAL p; /* default the extension */ if (needsextension(fname)) { strcpy(fullname,fname); strcat(fullname,".wks"); fname = fullname; } /* open the file */ if ((fp = osbopen(fname,"r")) == NULL) return (FALSE); /* free the old memory image */ freeimage(); /* initialize */ off = (OFFTYPE)2; total = nnodes = nfree = 0L; fnodes = NIL; segs = lastseg = NULL; 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 each node */ while ((type = fgetc(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; #ifndef JGC p->n_flags = 0; #endif 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: #ifdef STRUCTS case STRUCT: #endif max = getsize(p); if ((p->n_vdata = (LVAL *)malloc(max * sizeof(LVAL))) == NULL) xlfatal("insufficient memory - vector"); total += (long)(max * sizeof(LVAL)); for (i = 0; i < max; ++i) setelement(p,i,cviptr(readptr())); break; case STRING: max = getslength(p); if ((p->n_string = malloc(max)) == NULL) xlfatal("insufficient memory - string"); total += (long)max; fread(getstring(p),1,max,fp); break; case STREAM: setfile(p,NULL); break; case SUBR: case FSUBR: p->n_subr = funtab[getoffset(p)].fd_subr; break; } } /* 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 */ LOCAL VOID freeimage() { SEGMENT *seg,*next; FILE *fp; LVAL p; int n; /* free the data portion of SYMBOL/VECTOR/OBJECT/STRING nodes */ for (seg = segs; seg != NULL; seg = 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: #ifdef STRUCTS case STRUCT: #endif if (p->n_vsize) free(p->n_vdata); break; case STRING: if (getslength(p)) free(getstring(p)); break; case STREAM: if (((fp = getfile(p)) != 0) && (fp != stdin && fp != stdout && fp != stderr)) /* TAA BUG FIX */ osclose(fp); break; } next = seg->sg_next; free(seg); } } /* setoffset - output a positioning command if nodes have been skipped */ LOCAL VOID setoffset() { if (off != foff) { fputc(FREE,fp); writeptr(off); foff = off; } } /* writenode - write a node to a file */ LOCAL VOID writenode(node) LVAL node; { fputc(node->n_type,fp); fwrite(&node->n_info, sizeof(union ninfo), 1, fp); foff++; } /* writeptr - write a pointer to a file */ LOCAL VOID writeptr(off) OFFTYPE off; { fwrite(&off, sizeof(OFFTYPE), 1, fp); } /* readnode - read a node */ LOCAL VOID readnode(type,node) int type; LVAL node; { node->n_type = type; #ifndef JGC node->n_flags = 0; #endif fread(&node->n_info, sizeof(union ninfo), 1, fp); } /* readptr - read a pointer */ LOCAL OFFTYPE readptr() { OFFTYPE off; fread(&off, sizeof(OFFTYPE), 1, fp); return (off); } /* cviptr - convert a pointer on input */ LOCAL LVAL cviptr(o) OFFTYPE o; { OFFTYPE off = (OFFTYPE)2; SEGMENT *seg; /* check for nil */ if (o == (OFFTYPE)0) return ((LVAL)o); /* compute a pointer for this offset */ for (seg = segs; seg != NULL; seg = seg->sg_next) { if (o >= off && o < off + (OFFTYPE)seg->sg_size) return (seg->sg_nodes + 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 && o < off + (OFFTYPE)seg->sg_size) return (seg->sg_nodes + o - off); off += (OFFTYPE)seg->sg_size; } } #ifdef __ZTC__ /* Special version for Zortech C */ /* cvoptr - convert a pointer on output */ LOCAL OFFTYPE cvoptr(p) LVAL p; { OFFTYPE off = (OFFTYPE)2; SEGMENT *seg; OFFTYPE np = CVPTR(p); LVAL min1,max1; OFFTYPE min,max; /* check for nil and small fixnums */ if (p == NIL) return ((OFFTYPE)p); /* compute an offset for this pointer */ for (seg = segs; seg != NULL; seg = seg->sg_next) { min1 = &seg->sg_nodes[0]; max1 = &seg->sg_nodes[seg->sg_size]; min = CVPTR(min1); max = CVPTR(max1); if (np >= min && np < max) return (off+ ((np-min)/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 */ } #else /* cvoptr - convert a pointer on output */ LOCAL OFFTYPE cvoptr(p) LVAL p; { OFFTYPE off = (OFFTYPE)2; SEGMENT *seg; OFFTYPE np = CVPTR(p); /* check for nil and small fixnums */ if (p == NIL) return ((OFFTYPE)p); /* 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 */ } #endif #endif