ftp.nice.ch/pub/next/unix/audio/fugue.s.tar.gz#/fugue/xlimage.c

This is xlimage.c in view mode; [Download] [Up]

/* 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	*/

#include "xlisp.h"
#include "debug.h"

#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;
extern struct xtype_desc_struct desc_table[NTYPES];

/* local variables */
static OFFTYPE off,foff;
static FILE *fp;

/* external procedures */
extern SEGMENT *newsegment();
extern FILE *osbopen();
extern char *malloc();

/* forward declarations */
OFFTYPE readptr();
OFFTYPE cvoptr();
LVAL cviptr();

/* xlisave - save the memory image */
int xlisave(fname)
  char *fname;
{
    char fullname[STRMAX+1];
    unsigned char *cp;
    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 += 2)
	    switch (ntype(p)) {
	    case FREE:
		break;
	    case CONS:
	    case USTREAM:
		setoffset();
		osbputc(p->n_type,fp);
		writeptr(cvoptr(car(p)));
		writeptr(cvoptr(cdr(p)));
		foff += 2;
		break;
	    case EXTERN:
		setoffset();
		osbputc(EXTERN, fp);
/*		printf("saving EXTERN p = %x, desc %x\n", p, getdesc(p)); fflush(stdout);*/
		writeptr((OFFTYPE) (getdesc(p) - desc_table)); /* write type index */
		writeptr((OFFTYPE) 0); /* pointer gets reconstructed on input */
		foff += 2;
		break;
	    default:
		setoffset();
		writenode(p);
		break;
	    }
    }

    /* write the terminator */
    osbputc(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:
		max = getsize(p);
		for (i = 0; i < max; ++i)
		    writeptr(cvoptr(getelement(p,i)));
		break;
	    case STRING:
		max = getslength(p);
		for (cp = getstring(p); --max >= 0; )
		    osbputc(*cp++,fp);
		break;
	    case EXTERN:
/*		printf("saving extern data for p = %x\n", p);*/
		(getdesc(p)->save_meth)(fp, getinst(p));
		break;
	    }
    }

    /* close the output file */
    osclose(fp);

    /* return successfully */
    return (TRUE);
}

int dbgflg = FALSE;
int flag1;

/* xlirestore - restore a saved memory image */
int xlirestore(fname)
  char *fname;
{
    extern FUNDEF funtab[];
    char fullname[STRMAX+1];
    unsigned char *cp;
    int n,i,max,type;
    SEGMENT *seg;
    LVAL p;

/*    printf("stdin %x, stdout %x, stderr %x\n", stdin, stdout, stderr);*/

/*    if (flag1 = (lastseg == dbgsg))
 *    { LVAL p = dbgnode;
 *      printf("starting restore %x: type is %d, file is %x\n", p, ntype(p),
 *      getfile(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);

    dbgflg = TRUE;

    /* free the old memory image */
/*    { LVAL p = dbgnode;
 *	printf("before freeimage, %x: type is %d, file is %x\n", p, ntype(p),
 *	    getfile(p));
 *    }
 */
    freeimage();
/*    printf("freeimage returns\n");*/
/*    { LVAL p = dbgnode;
 *	printf("now, %x: type is %d, file is %x\n", p, ntype(p),
 *	    getfile(p));
 *    }
 */
    /* 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;
    xlcontext = NULL;

    /* create the fixnum segment */
    if ((fixseg = newsegment(SFIXSIZE)) == NULL)
	xlfatal("insufficient memory - fixnum segment");
/*    printf("newsegment returns\n");*/

    /* create the character segment */
    if ((charseg = newsegment(CHARSIZE)) == NULL)
	xlfatal("insufficient memory - character segment");
/*    printf("newsegment returns\n");*/

/*    printf("call readptr(1) or read a char(2) or getc(3) or peek(4) or reopen(5)?");
 *{
 *    int c;
 *    while (TRUE) {
 *	c = ostgetc();
 *        if (c == '2') {
 *	    printf("got %d from FILE %x\n", osbgetc(fp), fp);
 *            break;
 *	} else if (c == '1') break;
 * 	else if (c == '3') {
 *	    printf("got %d from FILE %x\n", getc(fp), fp);
 *	    break;
 *	} else if (c == '4') {
 *	    printf("fp is %x\n", fp); fflush(stdout);
 *	    c = getc(fp);
 *	    printf("first char of FILE %x is %d\n", fp, c);
 *	    ungetc(c, fp);
 *	    c = 0;
 *	} else if (c == '5') {
 *	    fp = osbopen(fname, "r");
 *	    printf("FILE is now %x\n", fp);
 *	} else if (c == '0') exit(0);
 *    }
 *}
 *    printf("reading obarray ptr\n");
 */
    /* read the pointer to the *obarray* symbol */
    obarray = cviptr(readptr());
/*    printf("done\n");*/
    dbgflg = FALSE;

    /* read each node */
    while ((type = osbgetc(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;
	    p->n_flags = 0;
	    rplaca(p,cviptr(readptr()));
	    rplacd(p,cviptr(readptr()));
	    off += 2;
	    break;
	case EXTERN:
	    p = cviptr(off);
/*	    printf("reading extern node p = %x\n", p);*/
	    p->n_type = EXTERN;
	    setdesc(p, desc_table + (int) readptr());
/*	    printf("type desc is %x\n", getdesc(p));*/
	    setinst(p, (unsigned char *) readptr());
/*	    printf("initial inst is %x\n", getinst(p));*/
	    off += 2;
	    break;
	default:
	    readnode(type,cviptr(off));
	    off += 2;
	    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:
		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 = (unsigned char *)malloc(max)) == NULL)
		    xlfatal("insufficient memory - string");
		total += (long)max;
		for (cp = getstring(p); --max >= 0; )
		    *cp++ = osbgetc(fp);
		break;
	    case STREAM:
/*		printf("nulling FILE %x in node %x\n", getfile(p), p);*/
		setfile(p,NULL);
/*		printf("now getfile(%x) is %x\n", p, getfile(p));*/
		break;
	    case SUBR:
	    case FSUBR:
		p->n_subr = funtab[getoffset(p)].fd_subr;
		break;
	    case EXTERN:
/*		printf("restoring extern %x\n", p); fflush(stdout); */
		setinst(p, (getdesc(p)->restore_meth)(fp));
		break;
	    }
	    if (p == dbgnode) {
/*		printf("got node %x: type is %d, file is %x\n", p, ntype(p),
		    getfile(p));*/
	    }
	}
    }

    /* close the input file */
    osclose(fp);

/*    printf("closed input file\n"); fflush(stdout); */

/*    printf("type something:");
    printf("got %d\n", ostgetc());

    fp = osbopen(fname, "r");
    printf("reopened %s, first byte is %d\n", fname, osbgetc(fp)); fflush(stdout);
    printf("fp is %x\n", fp); fflush(stdout);
    osclose(fp);
    printf("closed input file again\n"); fflush(stdout);

    printf("type something:");
    printf("got %d\n", ostgetc());

    fp = osbopen(fname, "r");
    printf("reopened %s, first byte is %d\n", fname, osbgetc(fp)); fflush(stdout);
    printf("fp is %x\n", fp); fflush(stdout);
    osclose(fp);
    printf("closed input file again\n"); fflush(stdout);

    printf("type something:");
    printf("got %d\n", ostgetc());

    fp = osbopen(fname, "r");
    printf("reopened %s, first byte is %d\n", fname, osbgetc(fp)); fflush(stdout);
    printf("fp is %x\n", fp); fflush(stdout);
    osclose(fp);
    printf("closed input file again\n"); fflush(stdout);
*/
/*    if (flag1)
 *    { LVAL p = dbgnode;
 *      printf("before gc: type of %x is %d, file is %x\n", p, ntype(p),
 *	    getfile(p));
 *    } 
 */
    /* collect to initialize the free space */
    gc();

/*     if (flag1)
 *    { LVAL p = dbgnode;
 *      printf("before ival_Caches: type of %x is %d, file is %x\n", p, ntype(p),
 *	    getfile(p));
 *    } 
 */
    /* invalidate extern type descriptor symbol caches */
    inval_caches();	

/*    if (flag1)
 *    { LVAL p = dbgnode;
 *      printf("before xlsymbols: type of %x is %d, file is %x\n", p, ntype(p),
 *	    getfile(p));
 *    } 
 */
    /* lookup all of the symbols the interpreter uses */
    xlsymbols();

/*    if (flag1)
 *    { LVAL p = dbgnode;
 *      printf("after restore: type of %x is %d, file is %x\n", p, ntype(p),
 *	    getfile(p));
 *    } 
 */
    /* return successfully */
    return (TRUE);
}

/* freeimage - free the current memory image */
LOCAL freeimage()
{
    SEGMENT *seg,*next;
    FILE *fp;
    LVAL p;
    int n;

/*    printf("starting freeimage\n");*/
    /* free the data portion of SYMBOL/VECTOR/OBJECT/STRING nodes */
    for (seg = segs; seg != NULL; seg = next) {
/*	printf("FREEING SEG %x:%x, ", seg, &seg->sg_nodes[seg->sg_size]);*/
	p = &seg->sg_nodes[0];
	for (n = seg->sg_size; --n >= 0; ++p)
	    switch (ntype(p)) {
	    case SYMBOL:
	    case OBJECT:
	    case VECTOR:
	    case CLOSURE:
		if (p->n_vsize)
		    free(p->n_vdata);
		break;
	    case STRING:
		if (getslength(p))
		    free(getstring(p));
		break;
	    case STREAM:
		if ((fp = getfile(p)) &&
		    (fp != stdin && fp != stdout && fp != stderr)) {
/*		    printf("closing file of node %x in freeimage\n", p);*/
		    osclose(getfile(p));
		}
		break;
	    }
	next = seg->sg_next;
	free(seg);
    }
}

/* setoffset - output a positioning command if nodes have been skipped */
LOCAL setoffset()
{
    if (off != foff) {
	osbputc(FREE,fp);
	writeptr(off);
	foff = off;
    }
}

/* writenode - write a node to a file */
LOCAL writenode(node)
  LVAL node;
{
    char *p = (char *)&node->n_info;
    int n = sizeof(union ninfo);
    osbputc(node->n_type,fp);
    while (--n >= 0)
	osbputc(*p++,fp);
    foff += 2;
}

/* writeptr - write a pointer to a file */
LOCAL writeptr(off)
  OFFTYPE off;
{
    char *p = (char *)&off;
    int n = sizeof(OFFTYPE);
    while (--n >= 0)
	osbputc(*p++,fp);
}

/* readnode - read a node */
LOCAL readnode(type,node)
  int type; LVAL node;
{
    char *p = (char *)&node->n_info;
    int n = sizeof(union ninfo);
    node->n_type = type;
    node->n_flags = 0;
    while (--n >= 0)
	*p++ = osbgetc(fp);
    if (ntype(node) == STREAM) {
/*	printf("readnode: FILE of node %x is %x\n", node, getfile(node));*/
    }
}

/* readptr - read a pointer */
LOCAL OFFTYPE readptr()
{
    OFFTYPE off;
    char *p = (char *)&off;
    int n = sizeof(OFFTYPE);
/*    int v; */
    while (--n >= 0) {
	*p++ = /* v = */osbgetc(fp);
/*   	if (dbgflg) printf("in readptr, got %d\n", v);*/
    }
    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);

/*    if (dbgflg) printf("cviptr(%x) ", 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 << 1))
	    return (seg->sg_nodes + ((int)(o - off) >> 1));
	off += (OFFTYPE)(seg->sg_size << 1);
    }

    /* create new segments if necessary */
    for (;;) {
	/* create the next segment */
	if ((seg = newsegment(anodes)) == NULL)
	    xlfatal("insufficient memory - segment");

/*	printf("CREATED SEG %x:%x, ", seg, &seg->sg_nodes[seg->sg_size]);*/
	/* check to see if the offset is in this segment */
	if (o >= off && o < off + (OFFTYPE)(seg->sg_size << 1))
	    return (seg->sg_nodes + ((int)(o - off) >> 1));
	off += (OFFTYPE)(seg->sg_size << 1);
    }
}

/* cvoptr - convert a pointer on output */
LOCAL OFFTYPE cvoptr(p)
  LVAL p;
{
    OFFTYPE off = (OFFTYPE)2;
    SEGMENT *seg;

    /* 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 (CVPTR(p) >= CVPTR(&seg->sg_nodes[0]) &&
	    CVPTR(p) <  CVPTR(&seg->sg_nodes[0] + seg->sg_size))
	    return (off + (OFFTYPE)((p - seg->sg_nodes) << 1));
	off += (OFFTYPE)(seg->sg_size << 1);
    }

    /* pointer not within any segment */
    xlerror("bad pointer found during image save",p);
}

#endif

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.