[comp.sources.amiga] v90i140: XScheme 0.20 - an object-oriented scheme, Part02/07

Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (04/15/90)

Submitted-by: rusty@fe2o3.UUCP (Rusty Haddock)
Posting-number: Volume 90, Issue 140
Archive-name: applications/xscheme-0.20/part02

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 7)."
# Contents:  Src/msstuff.c Src/xsimage.c Src/xsint.c Src/xsobj.c
#   Src/xsread.c
# Wrapped by tadguy@xanth on Sat Apr 14 17:07:22 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Src/msstuff.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Src/msstuff.c'\"
else
echo shar: Extracting \"'Src/msstuff.c'\" \(8253 characters\)
sed "s/^X//" >'Src/msstuff.c' <<'END_OF_FILE'
X/* msstuff.c - ms-dos specific routines */
X
X#include <dos.h>
X#include "xscheme.h"
X
X#define LBSIZE 200
X
X/* external variables */
Xextern LVAL s_unbound,true;
Xextern FILE *tfp;
Xextern int errno;
X
X/* local variables */
Xstatic char lbuf[LBSIZE];
Xstatic int lpos[LBSIZE];
Xstatic int lindex;
Xstatic int lcount;
Xstatic int lposition;
Xstatic long rseed = 1L;
X
X/* osinit - initialize */
Xosinit(banner)
X  char *banner;
X{
X    printf("%s\n",banner);
X    lposition = 0;
X    lindex = 0;
X    lcount = 0;
X}
X
X/* osfinish - clean up before returning to the operating system */
Xosfinish()
X{
X}
X
X/* oserror - print an error message */
Xoserror(msg)
X  char *msg;
X{
X    printf("error: %s\n",msg);
X}
X
X/* osrand - return a random number between 0 and n-1 */
Xint osrand(n)
X  int n;
X{
X    long k1;
X
X    /* make sure we don't get stuck at zero */
X    if (rseed == 0L) rseed = 1L;
X
X    /* algorithm taken from Dr. Dobbs Journal, November 1985, page 91 */
X    k1 = rseed / 127773L;
X    if ((rseed = 16807L * (rseed - k1 * 127773L) - k1 * 2836L) < 0L)
X	rseed += 2147483647L;
X
X    /* return a random number between 0 and n-1 */
X    return ((int)(rseed % (long)n));
X}
X
X/* osaopen - open an ascii file */
XFILE *osaopen(name,mode)
X  char *name,*mode;
X{
X    return (fopen(name,mode));
X}
X
X/* osbopen - open a binary file */
XFILE *osbopen(name,mode)
X  char *name,*mode;
X{
X    char bmode[10];
X    strcpy(bmode,mode); strcat(bmode,"b");
X    return (fopen(name,bmode));
X}
X
X/* osclose - close a file */
Xint osclose(fp)
X  FILE *fp;
X{
X    return (fclose(fp));
X}
X
X/* ostell - get the current file position */
Xlong ostell(fp)
X  FILE *fp;
X{
X    return (ftell(fp));
X}
X
X/* osseek - set the current file position */
Xint osseek(fp,offset,whence)
X  FILE *fp; long offset; int whence;
X{
X    return (fseek(fp,offset,whence));
X}
X
X/* osagetc - get a character from an ascii file */
Xint osagetc(fp)
X  FILE *fp;
X{
X    return (getc(fp));
X}
X
X/* osaputc - put a character to an ascii file */
Xint osaputc(ch,fp)
X  int ch; FILE *fp;
X{
X    return (putc(ch,fp));
X}
X
X/* osbgetc - get a character from a binary file */
Xint osbgetc(fp)
X  FILE *fp;
X{
X    return (getc(fp));
X}
X
X/* osbputc - put a character to a binary file */
Xint osbputc(ch,fp)
X  int ch; FILE *fp;
X{
X    return (putc(ch,fp));
X}
X
X/* ostgetc - get a character from the terminal */
Xint ostgetc()
X{
X    int ch;
X
X    /* check for a buffered character */
X    if (lcount--)
X	return (lbuf[lindex++]);
X
X    /* get an input line */
X    for (lcount = 0; ; )
X	switch (ch = xgetc()) {
X	case '\r':
X		lbuf[lcount++] = '\n';
X		xputc('\r'); xputc('\n'); lposition = 0;
X		if (tfp)
X		    for (lindex = 0; lindex < lcount; ++lindex)
X			osaputc(lbuf[lindex],tfp);
X		lindex = 0; lcount--;
X		return (lbuf[lindex++]);
X	case '\010':
X	case '\177':
X		if (lcount) {
X		    lcount--;
X		    while (lposition > lpos[lcount]) {
X			xputc('\010'); xputc(' '); xputc('\010');
X			lposition--;
X		    }
X		}
X		break;
X	case '\032':
X		xflush();
X		return (EOF);
X	default:
X		if (ch == '\t' || (ch >= 0x20 && ch < 0x7F)) {
X		    lbuf[lcount] = ch;
X		    lpos[lcount] = lposition;
X		    if (ch == '\t')
X			do {
X			    xputc(' ');
X			} while (++lposition & 7);
X		    else {
X			xputc(ch); lposition++;
X		    }
X		    lcount++;
X		}
X		else {
X		    xflush();
X		    switch (ch) {
X		    case '\003':	xltoplevel();	/* control-c */
X		    case '\007':	xlcleanup();	/* control-g */
X		    case '\020':	xlcontinue();	/* control-p */
X		    case '\032':	return (EOF);	/* control-z */
X		    default:		return (ch);
X		    }
X		}
X	}
X}
X
X/* ostputc - put a character to the terminal */
Xostputc(ch)
X  int ch;
X{
X    /* check for control characters */
X    oscheck();
X
X    /* output the character */
X    if (ch == '\n') {
X	xputc('\r'); xputc('\n');
X	lposition = 0;
X    }
X    else {
X	xputc(ch);
X	lposition++;
X   }
X
X   /* output the character to the transcript file */
X   if (tfp)
X	osaputc(ch,tfp);
X}
X
X/* osflush - flush the terminal input buffer */
Xosflush()
X{
X    lindex = lcount = lposition = 0;
X}
X
X/* oscheck - check for control characters during execution */
Xoscheck()
X{
X    int ch;
X    if (ch = xcheck())
X	switch (ch) {
X	case '\002':	/* control-b */
X	    xflush();
X	    xlbreak("BREAK",s_unbound);
X	    break;
X	case '\003':	/* control-c */
X	    xflush();
X	    xltoplevel();
X	    break;
X	case '\024':	/* control-t */
X	    xinfo();
X	    break;
X	case '\023':	/* control-s */
X	    while (xcheck() != '\021')
X		;
X	    break;
X	}
X}
X
X/* xinfo - show information on control-t */
Xstatic xinfo()
X{
X/*
X    extern int nfree,gccalls;
X    extern long total;
X    char buf[80];
X    sprintf(buf,"\n[ Free: %d, GC calls: %d, Total: %ld ]",
X	    nfree,gccalls,total);
X    errputstr(buf);
X*/
X}
X
X/* xflush - flush the input line buffer and start a new line */
Xstatic xflush()
X{
X    osflush();
X    ostputc('\n');
X}
X
X/* xgetc - get a character from the terminal without echo */
Xstatic int xgetc()
X{
X    return (bdos(7,0,0) & 0xFF);
X}
X
X/* xputc - put a character to the terminal */
Xstatic xputc(ch)
X  int ch;
X{
X    bdos(6,ch,0);
X}
X
X/* xcheck - check for a character */
Xstatic int xcheck()
X{
X    return (bdos(6,0xFF,0) & 0xFF);
X}
X
X/* xinbyte - read a byte from an input port */
XLVAL xinbyte()
X{
X    int portno;
X    LVAL val;
X    val = xlgafixnum(); portno = (int)getfixnum(val);
X    xllastarg();
X    return (cvfixnum((FIXTYPE)inp(portno)));
X}
X
X/* xoutbyte - write a byte to an output port */
XLVAL xoutbyte()
X{
X    int portno,byte;
X    LVAL val;
X    val = xlgafixnum(); portno = (int)getfixnum(val);
X    val = xlgafixnum(); byte = (int)getfixnum(val);
X    xllastarg();
X    outp(portno,byte);
X    return (NIL);
X}
X
X/* xint86 - invoke a system interrupt */
XLVAL xint86()
X{
X    union REGS inregs,outregs;
X    struct SREGS sregs;
X    LVAL inv,outv,val;
X    int intno;
X
X    /* get the interrupt number and the list of register values */
X    val = xlgafixnum(); intno = (int)getfixnum(val);
X    inv = xlgavector();
X    outv = xlgavector();
X    xllastarg();
X
X    /* check the vector lengths */
X    if (getsize(inv) != 9)
X        xlerror("incorrect vector length",inv);
X    if (getsize(outv) != 9)
X	xlerror("incorrect vector length",outv);
X
X    /* load each register from the input vector */
X    val = getelement(inv,0);
X    inregs.x.ax = (fixp(val) ? (int)getfixnum(val) : 0);
X    val = getelement(inv,1);
X    inregs.x.bx = (fixp(val) ? (int)getfixnum(val) : 0);
X    val = getelement(inv,2);
X    inregs.x.cx = (fixp(val) ? (int)getfixnum(val) : 0);
X    val = getelement(inv,3);
X    inregs.x.dx = (fixp(val) ? (int)getfixnum(val) : 0);
X    val = getelement(inv,4);
X    inregs.x.si = (fixp(val) ? (int)getfixnum(val) : 0);
X    val = getelement(inv,5);
X    inregs.x.di = (fixp(val) ? (int)getfixnum(val) : 0);
X    val = getelement(inv,6);
X    sregs.es = (fixp(val) ? (int)getfixnum(val) : 0);
X    val = getelement(inv,7);
X    sregs.ds = (fixp(val) ? (int)getfixnum(val) : 0);
X    val = getelement(inv,8);
X    inregs.x.cflag = (fixp(val) ? (int)getfixnum(val) : 0);
X
X    /* do the system interrupt */
X    int86x(intno,&inregs,&outregs,&sregs);
X
X    /* store the results in the output vector */
X    setelement(outv,0,cvfixnum((FIXTYPE)outregs.x.ax));
X    setelement(outv,1,cvfixnum((FIXTYPE)outregs.x.bx));
X    setelement(outv,2,cvfixnum((FIXTYPE)outregs.x.cx));
X    setelement(outv,3,cvfixnum((FIXTYPE)outregs.x.dx));
X    setelement(outv,4,cvfixnum((FIXTYPE)outregs.x.si));
X    setelement(outv,5,cvfixnum((FIXTYPE)outregs.x.di));
X    setelement(outv,6,cvfixnum((FIXTYPE)sregs.es));
X    setelement(outv,7,cvfixnum((FIXTYPE)sregs.ds));
X    setelement(outv,8,cvfixnum((FIXTYPE)outregs.x.cflag));
X    
X    /* return the result list */
X    return (outv);
X}
X
X/* getnext - get the next fixnum from a list */
Xstatic int getnext(plist)
X  LVAL *plist;
X{
X    LVAL val;
X    if (consp(*plist)) {
X        val = car(*plist);
X	*plist = cdr(*plist);
X	if (!fixp(val))
X	    xlerror("expecting an integer",val);
X        return ((int)getfixnum(val));
X    }
X    return (0);
X}
X
X/* xsystem - execute a system command */
XLVAL xsystem()
X{
X    char *cmd="COMMAND";
X    if (moreargs())
X	cmd = (char *)getstring(xlgastring());
X    xllastarg();
X    return (system(cmd) == 0 ? true : cvfixnum((FIXTYPE)errno));
X}
X
X/* xgetkey - get a key from the keyboard */
XLVAL xgetkey()
X{
X    xllastarg();
X    return (cvfixnum((FIXTYPE)xgetc()));
X}
X
X/* ossymbols - enter os specific symbols */
Xossymbols()
X{
X}
END_OF_FILE
if test 8253 -ne `wc -c <'Src/msstuff.c'`; then
    echo shar: \"'Src/msstuff.c'\" unpacked with wrong size!
fi
# end of 'Src/msstuff.c'
fi
if test -f 'Src/xsimage.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Src/xsimage.c'\"
else
echo shar: Extracting \"'Src/xsimage.c'\" \(8825 characters\)
sed "s/^X//" >'Src/xsimage.c' <<'END_OF_FILE'
X/* xsimage.c - xscheme memory image save/restore functions */
X/*	Copyright (c) 1988, by David Michael Betz
X	All Rights Reserved
X	Permission is granted for unrestricted non-commercial use	*/
X
X#include "xscheme.h"
X
X/* virtual machine registers */
Xextern LVAL xlfun;		/* current function */
Xextern LVAL xlenv;		/* current environment */
Xextern LVAL xlval;		/* value of most recent instruction */
X
X/* stack limits */
Xextern LVAL *xlstkbase;		/* base of value stack */
Xextern LVAL *xlstktop;		/* top of value stack */
X
X/* node space */
Xextern NSEGMENT *nsegments;	/* list of node segments */
X
X/* vector (and string) space */
Xextern VSEGMENT *vsegments;	/* list of vector segments */
Xextern LVAL *vfree;		/* next free location in vector space */
Xextern LVAL *vtop;		/* top of vector space */
X
X/* global variables */
Xextern LVAL obarray,eof_object,default_object;
Xextern jmp_buf top_level;
Xextern FUNDEF funtab[];
X
X/* local variables */
Xstatic OFFTYPE off,foff;
Xstatic FILE *fp;
X
X/* external routines */
Xextern FILE *osbopen();
X
X/* forward declarations */
XOFFTYPE readptr();
XOFFTYPE cvoptr();
XLVAL cviptr();
X
X/* xlisave - save the memory image */
Xint xlisave(fname)
X  char *fname;
X{
X    unsigned char *cp;
X    NSEGMENT *nseg;
X    int size,n;
X    LVAL p,*vp;
X
X    /* open the output file */
X    if ((fp = osbopen(fname,"w")) == NULL)
X	return (FALSE);
X
X    /* first call the garbage collector to clean up memory */
X    gc();
X
X    /* write out the stack size */
X    writeptr((OFFTYPE)(xlstktop-xlstkbase));
X
X    /* write out the *obarray* symbol and various constants */
X    writeptr(cvoptr(obarray));
X    writeptr(cvoptr(eof_object));
X    writeptr(cvoptr(default_object));
X
X    /* setup the initial file offsets */
X    off = foff = (OFFTYPE)2;
X
X    /* write out all nodes that are still in use */
X    for (nseg = nsegments; nseg != NULL; nseg = nseg->ns_next) {
X	p = &nseg->ns_data[0];
X	n = nseg->ns_size;
X	for (; --n >= 0; ++p, off += sizeof(NODE))
X	    switch (ntype(p)) {
X	    case FREE:
X		break;
X	    case CONS:
X	    case CLOSURE:
X	    case METHOD:
X	    case PROMISE:
X	    case ENV:
X		setoffset();
X		osbputc(p->n_type,fp);
X		writeptr(cvoptr(car(p)));
X		writeptr(cvoptr(cdr(p)));
X		foff += sizeof(NODE);
X		break;
X	    case SYMBOL:
X	    case OBJECT:
X	    case VECTOR:
X	    case CODE:
X	    case CONTINUATION:
X		setoffset();
X		osbputc(p->n_type,fp);
X		size = getsize(p);
X		writeptr((OFFTYPE)size);
X		for (vp = p->n_vdata; --size >= 0; )
X		    writeptr(cvoptr(*vp++));
X		foff += sizeof(NODE);
X		break;
X	    case STRING:
X		setoffset();
X		osbputc(p->n_type,fp);
X		size = getslength(p);
X		writeptr((OFFTYPE)size);
X		for (cp = getstring(p); --size >= 0; )
X		    osbputc(*cp++,fp);
X		foff += sizeof(NODE);
X		break;
X	    default:
X		setoffset();
X		writenode(p);
X		foff += sizeof(NODE);
X		break;
X	    }
X    }
X
X    /* write the terminator */
X    osbputc(FREE,fp);
X    writeptr((OFFTYPE)0);
X
X    /* close the output file */
X    osclose(fp);
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* xlirestore - restore a saved memory image */
Xint xlirestore(fname)
X  char *fname;
X{
X    LVAL *getvspace();
X    unsigned int ssize;
X    unsigned char *cp;
X    int size,type;
X    LVAL p,*vp;
X
X    /* open the file */
X    if ((fp = osbopen(fname,"r")) == NULL)
X	return (FALSE);
X
X    /* free the old memory image */
X    freeimage();
X
X    /* read the stack size */
X    ssize = (unsigned int)readptr();
X
X    /* allocate memory for the workspace */
X    xlminit(ssize);
X
X    /* read the *obarray* symbol and various constants */
X    obarray = cviptr(readptr());
X    eof_object = cviptr(readptr());
X    default_object = cviptr(readptr());
X    
X    /* read each node */
X    for (off = (OFFTYPE)2; (type = osbgetc(fp)) >= 0; )
X	switch (type) {
X	case FREE:
X	    if ((off = readptr()) == (OFFTYPE)0)
X		goto done;
X	    break;
X	case CONS:
X	case CLOSURE:
X	case METHOD:
X	case PROMISE:
X	case ENV:
X	    p = cviptr(off);
X	    p->n_type = type;
X	    rplaca(p,cviptr(readptr()));
X	    rplacd(p,cviptr(readptr()));
X	    off += sizeof(NODE);
X	    break;
X	case SYMBOL:
X	case OBJECT:
X	case VECTOR:
X	case CODE:
X	case CONTINUATION:
X	    p = cviptr(off);
X	    p->n_type = type;
X	    p->n_vsize = size = (int)readptr();
X	    p->n_vdata = getvspace(p,size);
X	    for (vp = p->n_vdata; --size >= 0; )
X		*vp++ = cviptr(readptr());
X	    off += sizeof(NODE);
X	    break;
X	case STRING:
X	    p = cviptr(off);
X	    p->n_type = type;
X	    p->n_vsize = size = (int)readptr();
X	    p->n_vdata = getvspace(p,btow_size(size));
X	    for (cp = getstring(p); --size >= 0; )
X		*cp++ = osbgetc(fp);
X	    off += sizeof(NODE);
X	    break;
X	case PORT:
X	    p = cviptr(off);
X	    readnode(type,p);
X	    setfile(p,NULL);
X	    off += sizeof(NODE);
X	    break;
X	case SUBR:
X	case XSUBR:
X	    p = cviptr(off);
X	    readnode(type,p);
X	    p->n_subr = funtab[getoffset(p)].fd_subr;
X	    off += sizeof(NODE);
X	    break;
X	default:
X	    readnode(type,cviptr(off));
X	    off += sizeof(NODE);
X	    break;
X	}
Xdone:
X
X    /* close the input file */
X    osclose(fp);
X
X    /* collect to initialize the free space */
X    gc();
X
X    /* lookup all of the symbols the interpreter uses */
X    xlsymbols();
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* freeimage - free the current memory image */
XLOCAL freeimage()
X{
X    NSEGMENT *nextnseg;
X    VSEGMENT *nextvseg;
X    FILE *fp;
X    LVAL p;
X    int n;
X
X    /* close all open ports and free each node segment */
X    for (; nsegments != NULL; nsegments = nextnseg) {
X	nextnseg = nsegments->ns_next;
X	p = &nsegments->ns_data[0];
X	n = nsegments->ns_size;
X	for (; --n >= 0; ++p)
X	    switch (ntype(p)) {
X	    case PORT:
X		if ((fp = getfile(p))
X		 && (fp != stdin && fp != stdout && fp != stderr))
X		    osclose(getfile(p));
X		break;
X	    }
X	free(nsegments);
X    }
X
X    /* free each vector segment */
X    for (; vsegments != NULL; vsegments = nextvseg) {
X	nextvseg = vsegments->vs_next;
X	free(vsegments);
X    }
X    
X    /* free the stack */
X    if (xlstkbase)
X	free(xlstkbase);
X}
X
X/* setoffset - output a positioning command if nodes have been skipped */
XLOCAL setoffset()
X{
X    if (off != foff) {
X	osbputc(FREE,fp);
X	writeptr(off);
X	foff = off;
X    }
X}
X
X/* writenode - write a node to a file */
XLOCAL writenode(node)
X  LVAL node;
X{
X    char *p = (char *)&node->n_info;
X    int n = sizeof(union ninfo);
X    osbputc(node->n_type,fp);
X    while (--n >= 0)
X	osbputc(*p++,fp);
X}
X
X/* writeptr - write a pointer to a file */
XLOCAL writeptr(off)
X  OFFTYPE off;
X{
X    char *p = (char *)&off;
X    int n = sizeof(OFFTYPE);
X    while (--n >= 0)
X	osbputc(*p++,fp);
X}
X
X/* readnode - read a node */
XLOCAL readnode(type,node)
X  int type; LVAL node;
X{
X    char *p = (char *)&node->n_info;
X    int n = sizeof(union ninfo);
X    node->n_type = type;
X    while (--n >= 0)
X	*p++ = osbgetc(fp);
X}
X
X/* readptr - read a pointer */
XLOCAL OFFTYPE readptr()
X{
X    OFFTYPE off;
X    char *p = (char *)&off;
X    int n = sizeof(OFFTYPE);
X    while (--n >= 0)
X	*p++ = osbgetc(fp);
X    return (off);
X}
X
X/* cviptr - convert a pointer on input */
XLOCAL LVAL cviptr(o)
X  OFFTYPE o;
X{
X    NSEGMENT *newnsegment(),*nseg;
X    OFFTYPE off = (OFFTYPE)2;
X    OFFTYPE nextoff;
X
X    /* check for nil and small fixnums */
X    if (o == (OFFTYPE)0 || (o & 1) == 1)
X	return ((LVAL)o);
X
X    /* compute a pointer for this offset */
X    for (nseg = nsegments; nseg != NULL; nseg = nseg->ns_next) {
X	nextoff = off + (OFFTYPE)(nseg->ns_size * sizeof(NODE));
X	if (o >= off && o < nextoff)
X	    return ((LVAL)((OFFTYPE)&nseg->ns_data[0] + o - off));
X	off = nextoff;
X    }
X
X    /* create new segments if necessary */
X    for (;;) {
X
X	/* create the next segment */
X	if ((nseg = newnsegment(NSSIZE)) == NULL)
X	    xlfatal("insufficient memory - segment");
X
X	/* check to see if the offset is in this segment */
X	nextoff = off + (OFFTYPE)(nseg->ns_size * sizeof(NODE));
X	if (o >= off && o < nextoff)
X	    return ((LVAL)((OFFTYPE)&nseg->ns_data[0] + o - off));
X	off = nextoff;
X    }
X}
X
X/* cvoptr - convert a pointer on output */
XLOCAL OFFTYPE cvoptr(p)
X  LVAL p;
X{
X    OFFTYPE off = (OFFTYPE)2;
X    NSEGMENT *nseg;
X
X    /* check for nil and small fixnums */
X    if (p == NIL || !ispointer(p))
X	return ((OFFTYPE)p);
X
X    /* compute an offset for this pointer */
X    for (nseg = nsegments; nseg != NULL; nseg = nseg->ns_next) {
X	if (INSEGMENT(p,nseg))
X	    return (off + ((OFFTYPE)p - (OFFTYPE)&nseg->ns_data[0]));
X	off += (OFFTYPE)(nseg->ns_size * sizeof(NODE));
X    }
X
X    /* pointer not within any segment */
X    xlerror("bad pointer found during image save",p);
X}
X
X/* getvspace - allocate vector space */
XLOCAL LVAL *getvspace(node,size)
X  LVAL node; unsigned int size;
X{
X    LVAL *p;
X    ++size; /* space for the back pointer */
X    if (vfree + size >= vtop) {
X	makevmemory(size);
X	if (vfree + size >= vtop)
X	    xlfatal("insufficient vector space");
X    }
X    p = vfree;
X    vfree += size;
X    *p++ = node;
X    return (p);
X}
END_OF_FILE
if test 8825 -ne `wc -c <'Src/xsimage.c'`; then
    echo shar: \"'Src/xsimage.c'\" unpacked with wrong size!
fi
# end of 'Src/xsimage.c'
fi
if test -f 'Src/xsint.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Src/xsint.c'\"
else
echo shar: Extracting \"'Src/xsint.c'\" \(10297 characters\)
sed "s/^X//" >'Src/xsint.c' <<'END_OF_FILE'
X/* xsint.c - xscheme bytecode interpreter */
X/*	Copyright (c) 1988, by David Michael Betz
X	All Rights Reserved
X	Permission is granted for unrestricted non-commercial use	*/
X
X#include "xscheme.h"
X#include "xsbcode.h"
X
X/* sample rate (instructions per sample) */
X#define SRATE	1000
X
X/* macros to get the address of the code string for a code object */
X#define getcodestr(x) ((unsigned char *)getstring(getbcode(x)))
X
X/* globals */
Xint trace=FALSE;	/* trace enable */
Xint xlargc;		/* argument count */
Xjmp_buf bc_dispatch;	/* bytecode dispatcher */
X
X/* external variables */
Xextern LVAL xlfun,xlenv,xlval;
Xextern LVAL s_stdin,s_stdout,s_unbound;
Xextern LVAL s_unassigned,default_object,true;
X
X/* external routines */
Xextern LVAL xadd(),xsub(),xmul(),xdiv(),xlss(),xeql(),xgtr();
X
X/* local variables */
Xstatic unsigned char *base,*pc;
Xstatic int sample=SRATE;
X
X/* xtraceon - built-in function 'trace-on' */
XLVAL xtraceon()
X{
X    xllastarg()
X    trace = TRUE;
X    return (NIL);
X}
X
X/* xtraceoff - built-in function 'trace-off' */
XLVAL xtraceoff()
X{
X    xllastarg()
X    trace = FALSE;
X    return (NIL);
X}
X
X/* xlexecute - execute byte codes */
Xxlexecute(fun)
X  LVAL fun;
X{
X    LVAL findvar(),make_continuation();
X    register LVAL tmp;
X    register unsigned int i;
X    register int k;
X    int off;
X
X    /* initialize the registers */
X    xlfun = getcode(fun);
X    xlenv = getenv(fun);
X    xlval = NIL;
X
X    /* initialize the argument count */
X    xlargc = 0;
X
X    /* set the initial pc */
X    base = pc = getcodestr(xlfun);
X
X    /* setup a target for the error handler */
X    setjmp(bc_dispatch);
X    
X    /* execute the code */
X    for (;;) {
X
X	/* check for control codes */
X	if (--sample <= 0) {
X	    sample = SRATE;
X	    oscheck();
X	}
X
X	/* print the trace information */
X	if (trace)
X	    decode_instruction(curoutput(),xlfun,(int)(pc-base),xlenv);
X
X	/* execute the next bytecode instruction */
X	switch (*pc++) {
X	case OP_BRT:
X		i = *pc++ << 8; i |= *pc++;
X		if (xlval) pc = base + i;
X		break;
X	case OP_BRF:
X		i = *pc++ << 8; i |= *pc++;
X		if (!xlval) pc = base + i;
X		break;
X	case OP_BR:
X		i = *pc++ << 8; i |= *pc++;
X		pc = base + i;
X		break;
X	case OP_LIT:
X		xlval = getelement(xlfun,*pc++);
X		break;
X	case OP_GREF:
X		tmp = getelement(xlfun,*pc++);
X		if ((xlval = getvalue(tmp)) == s_unbound) {
X		    if (xlval = getvalue(xlenter("*UNBOUND-HANDLER*"))) {
X			oscheck();
X			pc -= 2; /* backup the pc */
X			tmp = make_continuation();
X			check(2);
X			push(tmp);
X			push(getelement(xlfun,pc[1]));
X			xlargc = 2;
X			xlapply();
X		    }
X		    else
X			xlerror("unbound variable",tmp);
X		}
X		break;
X	case OP_GSET:
X		setvalue(getelement(xlfun,*pc++),xlval);
X		break;
X	case OP_EREF:
X		k = *pc++;
X		tmp = xlenv;
X		while (--k >= 0) tmp = cdr(tmp);
X		xlval = getelement(car(tmp),*pc++);
X		break;
X	case OP_ESET:
X		k = *pc++;
X		tmp = xlenv;
X		while (--k >= 0) tmp = cdr(tmp);
X		setelement(car(tmp),*pc++,xlval);
X		break;
X	case OP_AREF:
X		i = *pc++;
X		tmp = xlval;
X		if (!envp(tmp)) badargtype(tmp);
X		if ((tmp = findvar(tmp,getelement(xlfun,i),&off)) != NIL)
X		    xlval = getelement(car(tmp),off);
X		else
X		    xlval = s_unassigned;
X		break;
X	case OP_ASET:
X		i = *pc++;
X		tmp = pop();
X		if (!envp(tmp)) badargtype(tmp);
X		if ((tmp = findvar(tmp,getelement(xlfun,i),&off)) == NIL)
X		    xlerror("no binding for variable",getelement(xlfun,i));
X		setelement(car(tmp),off,xlval);
X		break;
X	case OP_SAVE:	/* save a continuation */
X		i = *pc++ << 8; i |= *pc++;
X		check(3);
X		push(cvsfixnum((FIXTYPE)i));
X		push(xlfun);
X		push(xlenv);
X		break;
X	case OP_CALL:	/* call a function (or built-in) */
X		xlargc = *pc++;	/* get argument count */
X		xlapply();	/* apply the function */
X		break;
X	case OP_RETURN:	/* return to the continuation on the stack */
X		xlreturn();
X		break;
X	case OP_FRAME:	/* create an environment frame */
X		i = *pc++;	/* get the frame size */
X		xlenv = newframe(xlenv,i);
X		setelement(car(xlenv),0,getvnames(xlfun));
X		break;
X	case OP_MVARG:	/* move required argument to frame slot */
X		i = *pc++;	/* get the slot number */
X		if (--xlargc < 0)
X		    xlfail("too few arguments");
X		setelement(car(xlenv),i,pop());
X		break;
X	case OP_MVOARG:	/* move optional argument to frame slot */
X		i = *pc++;	/* get the slot number */
X		if (xlargc > 0) {
X		    setelement(car(xlenv),i,pop());
X		    --xlargc;
X		}
X		else
X		    setelement(car(xlenv),i,default_object);
X		break;
X	case OP_MVRARG:	/* build rest argument and move to frame slot */
X		i = *pc++;	/* get the slot number */
X		for (xlval = NIL, k = xlargc; --k >= 0; )
X		    xlval = cons(xlsp[k],xlval);
X		setelement(car(xlenv),i,xlval);
X		drop(xlargc);
X		break;
X	case OP_ALAST:	/* make sure there are no more arguments */
X		if (xlargc > 0)
X		    xlfail("too many arguments");
X		break;
X	case OP_T:
X		xlval = true;
X		break;
X	case OP_NIL:
X		xlval = NIL;
X		break;
X	case OP_PUSH:
X		cpush(xlval);
X		break;
X	case OP_CLOSE:
X		if (!codep(xlval)) badargtype(xlval);
X		xlval = cvclosure(xlval,xlenv);
X		break;
X	case OP_DELAY:
X		if (!codep(xlval)) badargtype(xlval);
X		xlval = cvpromise(xlval,xlenv);
X		break;
X	case OP_ATOM:
X		xlval = (atom(xlval) ? true : NIL);
X		break;
X	case OP_EQ:
X		xlval = (xlval == pop() ? true : NIL);
X		break;
X	case OP_NULL:
X		xlval = (xlval ? NIL : true);
X		break;
X	case OP_CONS:
X		xlval = cons(xlval,pop());
X		break;
X	case OP_CAR:
X		if (!listp(xlval)) badargtype(xlval);
X		xlval = (xlval ? car(xlval) : NIL);
X		break;
X	case OP_CDR:
X		if (!listp(xlval)) badargtype(xlval);
X		xlval = (xlval ? cdr(xlval) : NIL);
X		break;
X	case OP_SETCAR:
X		if (!consp(xlval)) badargtype(xlval);
X		rplaca(xlval,pop());
X		break;
X	case OP_SETCDR:
X		if (!consp(xlval)) badargtype(xlval);
X		rplacd(xlval,pop());
X		break;
X	case OP_ADD:
X		tmp = pop();
X		if (fixp(xlval) && fixp(tmp))
X		    xlval = cvfixnum(getfixnum(xlval) + getfixnum(tmp));
X		else {
X		    push(tmp); push(xlval); xlargc = 2;
X		    xlval = xadd();
X		}
X		break;
X	case OP_SUB:
X		tmp = pop();
X		if (fixp(xlval) && fixp(tmp))
X		    xlval = cvfixnum(getfixnum(xlval) - getfixnum(tmp));
X		else {
X		    push(tmp); push(xlval); xlargc = 2;
X		    xlval = xsub();
X		}
X		break;
X	case OP_MUL:
X		tmp = pop();
X		if (fixp(xlval) && fixp(tmp))
X		    xlval = cvfixnum(getfixnum(xlval) * getfixnum(tmp));
X		else {
X		    push(tmp); push(xlval); xlargc = 2;
X		    xlval = xmul();
X		}
X		break;
X	case OP_QUO:
X		tmp = pop();
X		if (fixp(xlval) && fixp(tmp))
X		    xlval = cvfixnum(getfixnum(xlval) / getfixnum(tmp));
X		else if (fixp(xlval))
X		    badargtype(tmp);
X		else
X		    badargtype(xlval);
X		break;
X	case OP_LSS:
X		tmp = pop();
X		if (fixp(xlval) && fixp(tmp))
X		    xlval = (getfixnum(xlval) < getfixnum(tmp) ? true : NIL);
X		else {
X		    push(tmp); push(xlval); xlargc = 2;
X		    xlval = xlss();
X		}
X		break;
X	case OP_EQL:
X		tmp = pop();
X		if (fixp(xlval) && fixp(tmp))
X		    xlval = (getfixnum(xlval) == getfixnum(tmp) ? true : NIL);
X		else {
X		    push(tmp); push(xlval); xlargc = 2;
X		    xlval = xeql();
X		}
X		break;
X	case OP_GTR:
X		tmp = pop();
X		if (fixp(xlval) && fixp(tmp))
X		    xlval = (getfixnum(xlval) > getfixnum(tmp) ? true : NIL);
X		else {
X		    push(tmp); push(xlval); xlargc = 2;
X		    xlval = xgtr();
X		}
X		break;
X	default:
X		xlerror("bad opcode",cvsfixnum((FIXTYPE)*--pc));
X		break;
X	}
X    }
X}
X
X/* findvar - find a variable in an environment */
XLOCAL LVAL findvar(env,var,poff)
X  LVAL env,var; int *poff;
X{
X    LVAL names;
X    int off;
X    for (; env != NIL; env = cdr(env)) {
X	names = getelement(car(env),0);
X	for (off = 1; names != NIL; ++off, names = cdr(names))
X	    if (var == car(names)) {
X		*poff = off;
X		return (env);
X	    }
X    }
X    return (NIL);
X}
X
X/* xlapply - apply a function to arguments */
X/*	The function should be in xlval and the arguments should
X	be on the stack.  The number of arguments should be in xlargc.
X*/
Xxlapply()
X{
X    LVAL tmp;
X
X    /* check for null function */
X    if (null(xlval))
X	badfuntype(xlval);
X
X    /* dispatch on function type */
X    switch (ntype(xlval)) {
X    case SUBR:
X	xlval = (*getsubr(xlval))();
X	xlreturn();
X	break;
X    case XSUBR:
X	(*getsubr(xlval))();
X	break;
X    case CLOSURE:
X	xlfun = getcode(xlval);
X	xlenv = getenv(xlval);
X	base = pc = getcodestr(xlfun);
X	break;
X    case OBJECT:
X	xlsend(xlval,xlgasymbol());
X	break;
X    case METHOD:
X	xlfun = getcode(xlval);
X	xlenv = cons(top(),getenv(xlval));
X	base = pc = getcodestr(xlfun);
X	break;
X    case CONTINUATION:
X	tmp = xlgetarg();
X	xllastarg();
X	restore_continuation();
X	xlval = tmp;
X	xlreturn();
X	break;
X    default:
X	badfuntype(xlval);
X    }
X}
X
X/* xlreturn - return to a continuation on the stack */
Xxlreturn()
X{
X    LVAL tmp;
X    
X    /* restore the enviroment and the continuation function */
X    xlenv = pop();
X    tmp = pop();
X    
X    /* dispatch on the function type */
X    switch (ntype(tmp)) {
X    case CODE:
X    	xlfun = tmp;
X    	tmp = pop();
X	base = getcodestr(xlfun);
X	pc = base + (int)getsfixnum(tmp);
X	break;
X    case CSUBR:
X	(*getsubr(tmp))();
X	break;
X    default:
X	xlerror("bad continuation",tmp);
X    }
X}
X
X/* make_continuation - make a continuation */
XLOCAL LVAL make_continuation()
X{
X    LVAL cont,*src,*dst;
X    int size;
X
X    /* save a continuation on the stack */
X    check(3);
X    push(cvsfixnum((FIXTYPE)(pc - base)));
X    push(xlfun);
X    push(xlenv);
X
X    /* create and initialize a continuation object */
X    size = (int)(xlstktop - xlsp);
X    cont = newcontinuation(size);
X    for (src = xlsp, dst = &cont->n_vdata[0]; --size >= 0; )
X	*dst++ = *src++;
X    
X    /* return the continuation */
X    return (cont);
X}
X
X/* restore_continuation - restore a continuation to the stack */
X/*	The continuation should be in xlval.
X*/
XLOCAL restore_continuation()
X{
X    LVAL *src;
X    int size;
X    size = getsize(xlval);
X    for (src = &xlval->n_vdata[size], xlsp = xlstktop; --size >= 0; )
X	*--xlsp = *--src;
X}
X
X/* gc_protect - protect the state of the interpreter from the collector */
Xgc_protect(protected_fcn)
X  int (*protected_fcn)();
X{
X    int pcoff;
X    pcoff = pc - base;
X    (*protected_fcn)();
X    if (xlfun) {
X	base = getcodestr(xlfun);
X	pc = base + pcoff;
X    }
X}
X
X/* badfuntype - bad function error */
XLOCAL badfuntype(arg)
X  LVAL arg;
X{
X    xlerror("bad function type",arg);
X}
X
X/* badargtype - bad argument type error */
XLOCAL badargtype(arg)
X  LVAL arg;
X{
X    xlbadtype(arg);
X}
X
X/* xlstkover - value stack overflow */
Xxlstkover()
X{
X    xlabort("value stack overflow");
X}
END_OF_FILE
if test 10297 -ne `wc -c <'Src/xsint.c'`; then
    echo shar: \"'Src/xsint.c'\" unpacked with wrong size!
fi
# end of 'Src/xsint.c'
fi
if test -f 'Src/xsobj.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Src/xsobj.c'\"
else
echo shar: Extracting \"'Src/xsobj.c'\" \(9292 characters\)
sed "s/^X//" >'Src/xsobj.c' <<'END_OF_FILE'
X/* xsobj.c - xscheme object-oriented programming support */
X/*	Copyright (c) 1988, by David Michael Betz
X	All Rights Reserved
X	Permission is granted for unrestricted non-commercial use	*/
X
X#include "xscheme.h"
X
X/* external variables */
Xextern LVAL xlenv,xlval;
Xextern LVAL s_stdout;
X
X/* local variables */
Xstatic LVAL s_self,k_isnew;
Xstatic LVAL class,object;
X
X/* instance variable numbers for the class 'Class' */
X#define MESSAGES	2	/* list of messages */
X#define IVARS		3	/* list of instance variable names */
X#define CVARS		4	/* env containing class variables */
X#define SUPERCLASS	5	/* pointer to the superclass */
X#define IVARCNT		6	/* number of class instance variables */
X#define IVARTOTAL	7	/* total number of instance variables */
X
X/* number of instance variables for the class 'Class' */
X#define CLASSSIZE	6
X
X/* forward declarations */
XFORWARD LVAL entermsg();
XFORWARD LVAL copylists();
X
X/* xlsend - send a message to an object */
Xxlsend(obj,sym)
X  LVAL obj,sym;
X{
X    LVAL msg,cls,p;
X
X    /* look for the message in the class or superclasses */
X    for (cls = getclass(obj); cls; cls = getivar(cls,SUPERCLASS))
X	for (p = getivar(cls,MESSAGES); p; p = cdr(p))
X	    if ((msg = car(p)) && car(msg) == sym) {
X		push(obj); ++xlargc; /* insert 'self' argument */
X		xlval = cdr(msg);    /* get the method */
X		xlapply();	     /* invoke the method */
X		return;
X	    }
X
X    /* message not found */
X    xlerror("no method for this message",sym);
X}
X
X/* xsendsuper - built-in function 'send-super' */
XLVAL xsendsuper()
X{
X    LVAL obj,sym,msg,cls,p;
X
X    /* get the message selector */
X    sym = xlgasymbol();
X    
X    /* find the 'self' object */
X    for (obj = xlenv; obj; obj = cdr(obj))
X	if (ntype(car(obj)) == OBJECT)
X	    goto find_method;
X    xlerror("not in a method",sym);
X
Xfind_method:
X    /* get the message class and the 'self' object */
X    cls = getivar(getelement(car(cdr(obj)),0),SUPERCLASS);
X    obj = car(obj);
X    
X    /* look for the message in the class or superclasses */
X    for (; cls; cls = getivar(cls,SUPERCLASS))
X	for (p = getivar(cls,MESSAGES); p; p = cdr(p))
X	    if ((msg = car(p)) && car(msg) == sym) {
X		push(obj); ++xlargc; /* insert 'self' argument */
X		xlval = cdr(msg);    /* get the method */
X		xlapply();	     /* invoke the method */
X		return;
X	    }
X
X    /* message not found */
X    xlerror("no method for this message",sym);
X}
X
X/* obisnew - default 'isnew' method */
XLVAL obisnew()
X{
X    LVAL self;
X    self = xlgaobject();
X    xllastarg();
X    return (self);
X}
X
X/* obclass - get the class of an object */
XLVAL obclass()
X{
X    LVAL self;
X    self = xlgaobject();
X    xllastarg();
X    return (getclass(self));
X}
X
X/* obshow - show the instance variables of an object */
XLVAL obshow()
X{
X    LVAL self,fptr,cls,names;
X    int maxi,i;
X
X    /* get self and the file pointer */
X    self = xlgaobject();
X    fptr = (moreargs() ? xlgaoport() : getvalue(s_stdout));
X    xllastarg();
X
X    /* get the object's class */
X    cls = getclass(self);
X
X    /* print the object and class */
X    xlputstr(fptr,"Object is ");
X    xlprin1(self,fptr);
X    xlputstr(fptr,", Class is ");
X    xlprin1(cls,fptr);
X    xlterpri(fptr);
X
X    /* print the object's instance variables */
X    names = cdr(getivar(cls,IVARS));
X    maxi = getivcnt(cls,IVARTOTAL)+1;
X    for (i = 2; i <= maxi; ++i) {
X	xlputstr(fptr,"  ");
X	xlprin1(car(names),fptr);
X	xlputstr(fptr," = ");
X	xlprin1(getivar(self,i),fptr);
X	xlterpri(fptr);
X	names = cdr(names);
X    }
X
X    /* return the object */
X    return (self);
X}
X
X/* clnew - create a new object instance */
XLVAL clnew()
X{
X    LVAL self;
X
X    /* create a new object */
X    self = xlgaobject();
X    xlval = newobject(self,getivcnt(self,IVARTOTAL));
X
X    /* send the 'isnew' message */
X    xlsend(xlval,k_isnew);
X}
X
X/* clisnew - initialize a new class */
XLVAL clisnew()
X{
X    LVAL self,ivars,cvars,super;
X    int n;
X
X    /* get self, the ivars, cvars and superclass */
X    self = xlgaobject();
X    ivars = xlgalist();
X    cvars = (moreargs() ? xlgalist() : NIL);
X    super = (moreargs() ? xlgaobject() : object);
X    xllastarg();
X
X    /* create the class variable name list */
X    cpush(cons(xlenter("%%CLASS"),copylists(cvars,NIL)));
X    
X    /* create the class variable environment */
X    xlval = newframe(getivar(super,CVARS),listlength(xlval)+1);
X    setelement(car(xlval),0,pop());
X    setelement(car(xlval),1,self);
X    push(xlval);
X
X    /* store the instance and class variable lists and the superclass */
X    setivar(self,IVARS,copylists(getivar(super,IVARS),ivars));
X    setivar(self,CVARS,pop());
X    setivar(self,SUPERCLASS,super);
X
X    /* compute the instance variable count */
X    n = listlength(ivars);
X    setivar(self,IVARCNT,cvfixnum((FIXTYPE)n));
X    n += getivcnt(super,IVARTOTAL);
X    setivar(self,IVARTOTAL,cvfixnum((FIXTYPE)n));
X
X    /* return the new class object */
X    return (self);
X}
X
X/* clanswer - define a method for answering a message */
XLVAL clanswer()
X{
X    extern LVAL xlfunction();
X    LVAL self,msg,fargs,code,mptr;
X
X    /* message symbol, formal argument list and code */
X    self = xlgaobject();
X    msg = xlgasymbol();
X    fargs = xlgetarg();
X    code = xlgalist();
X    xllastarg();
X
X    /* make a new message list entry */
X    mptr = entermsg(self,msg);
X
X    /* add 'self' to the argument list */
X    cpush(cons(s_self,fargs));
X
X    /* extend the class variable environment with the instance variables */
X    xlval = newframe(getivar(self,CVARS),1);
X    setelement(car(xlval),0,getivar(self,IVARS));
X    
X    /* compile and store the method */
X    xlval = xlfunction(msg,top(),code,xlval);
X    rplacd(mptr,cvmethod(xlval,getivar(self,CVARS)));
X    drop(1);
X
X    /* return the object */
X    return (self);
X}
X
X/* addivar - enter an instance variable */
XLOCAL addivar(cls,var)
X  LVAL cls; char *var;
X{
X    setivar(cls,IVARS,cons(xlenter(var),getivar(cls,IVARS)));
X}
X
X/* addmsg - add a message to a class */
XLOCAL addmsg(cls,msg,fname)
X  LVAL cls; char *msg,*fname;
X{
X    LVAL mptr;
X
X    /* enter the message selector */
X    mptr = entermsg(cls,xlenter(msg));
X
X    /* store the method for this message */
X    rplacd(mptr,getvalue(xlenter(fname)));
X}
X
X/* entermsg - add a message to a class */
XLOCAL LVAL entermsg(cls,msg)
X  LVAL cls,msg;
X{
X    LVAL lptr,mptr;
X
X    /* lookup the message */
X    for (lptr = getivar(cls,MESSAGES); lptr; lptr = cdr(lptr))
X	if (car(mptr = car(lptr)) == msg)
X	    return (mptr);
X
X    /* allocate a new message entry if one wasn't found */
X    cpush(cons(msg,NIL));
X    setivar(cls,MESSAGES,cons(top(),getivar(cls,MESSAGES)));
X
X    /* return the symbol node */
X    return (pop());
X}
X
X/* getivcnt - get the number of instance variables for a class */
XLOCAL int getivcnt(cls,ivar)
X  LVAL cls; int ivar;
X{
X    LVAL cnt;
X    if ((cnt = getivar(cls,ivar)) == NIL || !fixp(cnt))
X	xlerror("bad value for instance variable count",cnt);
X    return ((int)getfixnum(cnt));
X}
X
X/* copylist - make a copy of a list */
XLOCAL LVAL copylists(list1,list2)
X  LVAL list1,list2;
X{
X    LVAL last,next;
X    
X    /* initialize */
X    cpush(NIL); last = NIL;
X    
X    /* copy the first list */
X    for (; consp(list1); list1 = cdr(list1)) {
X	next = cons(car(list1),NIL);
X	if (last) rplacd(last,next);
X	else settop(next);
X	last = next;
X    }
X    
X    /* append the second list */
X    for (; consp(list2); list2 = cdr(list2)) {
X	next = cons(car(list2),NIL);
X	if (last) rplacd(last,next);
X	else settop(next);
X	last = next;
X    }
X    return (pop());
X}
X
X/* listlength - find the length of a list */
XLOCAL int listlength(list)
X  LVAL list;
X{
X    int len;
X    for (len = 0; consp(list); len++)
X	list = cdr(list);
X    return (len);
X}
X
X/* obsymbols - initialize symbols */
Xobsymbols()
X{
X    /* enter the object related symbols */
X    s_self  = xlenter("SELF");
X    k_isnew = xlenter("ISNEW");
X
X    /* get the Object and Class symbol values */
X    object = getvalue(xlenter("OBJECT"));
X    class  = getvalue(xlenter("CLASS"));
X}
X
X/* xloinit - object function initialization routine */
Xxloinit()
X{
X    LVAL sym;
X    
X    /* create the 'Object' object */
X    sym = xlenter("OBJECT");
X    object = newobject(NIL,CLASSSIZE);
X    setvalue(sym,object);
X    setivar(object,IVARS,cons(xlenter("%%CLASS"),NIL));
X    setivar(object,IVARCNT,cvfixnum((FIXTYPE)0));
X    setivar(object,IVARTOTAL,cvfixnum((FIXTYPE)0));
X    addmsg(object,"ISNEW","%OBJECT-ISNEW");
X    addmsg(object,"CLASS","%OBJECT-CLASS");
X    addmsg(object,"SHOW","%OBJECT-SHOW");
X    
X    /* create the 'Class' object */
X    sym = xlenter("CLASS");
X    class = newobject(NIL,CLASSSIZE);
X    setvalue(sym,class);
X    addivar(class,"IVARTOTAL");	/* ivar number 6 */
X    addivar(class,"IVARCNT");	/* ivar number 5 */
X    addivar(class,"SUPERCLASS");/* ivar number 4 */
X    addivar(class,"CVARS");	/* ivar number 3 */
X    addivar(class,"IVARS");	/* ivar number 2 */
X    addivar(class,"MESSAGES");	/* ivar number 1 */
X    setivar(class,IVARS,cons(xlenter("%%CLASS"),getivar(class,IVARS)));
X    setivar(class,IVARCNT,cvfixnum((FIXTYPE)CLASSSIZE));
X    setivar(class,IVARTOTAL,cvfixnum((FIXTYPE)CLASSSIZE));
X    setivar(class,SUPERCLASS,object);
X    addmsg(class,"NEW","%CLASS-NEW");
X    addmsg(class,"ISNEW","%CLASS-ISNEW");
X    addmsg(class,"ANSWER","%CLASS-ANSWER");
X
X    /* patch the class into 'object' and 'class' */
X    setclass(object,class);
X    setclass(class,class);
X}
END_OF_FILE
if test 9292 -ne `wc -c <'Src/xsobj.c'`; then
    echo shar: \"'Src/xsobj.c'\" unpacked with wrong size!
fi
# end of 'Src/xsobj.c'
fi
if test -f 'Src/xsread.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Src/xsread.c'\"
else
echo shar: Extracting \"'Src/xsread.c'\" \(9004 characters\)
sed "s/^X//" >'Src/xsread.c' <<'END_OF_FILE'
X/* xsread.c - xscheme input routines */
X/*	Copyright (c) 1988, by David Michael Betz
X	All Rights Reserved
X	Permission is granted for unrestricted non-commercial use	*/
X
X#include "xscheme.h"
X
X/* external variables */
Xextern LVAL true;
X
X/* external routines */
Xextern double atof();
Xextern ITYPE;
X
X/* forward declarations */
XLVAL read_list(),read_quote(),read_comma(),read_symbol();
XLVAL read_radix(),read_string(),read_special();
X
X/* xlread - read an expression */
Xint xlread(fptr,pval)
X  LVAL fptr,*pval;
X{
X    int ch;
X
X    /* check the next non-blank character */
X    while ((ch = scan(fptr)) != EOF)
X	switch (ch) {
X	case '(':
X	    *pval = read_list(fptr);
X	    return (TRUE);
X	case ')':
X	    xlfail("misplaced right paren");
X	case '\'':
X	    *pval = read_quote(fptr,"QUOTE");
X	    return (TRUE);
X	case '`':
X	    *pval = read_quote(fptr,"QUASIQUOTE");
X	    return (TRUE);
X	case ',':
X	    *pval = read_comma(fptr);
X	    return (TRUE);
X	case '"':
X	    *pval = read_string(fptr);
X	    return (TRUE);
X	case '#':
X	    *pval = read_special(fptr);
X	    return (TRUE);
X	case ';':
X    	    read_comment(fptr);
X    	    break;
X	default:
X	    xlungetc(fptr,ch);
X	    *pval = read_symbol(fptr);
X	    return (TRUE);
X	}
X    return (FALSE);
X}
X
X/* read_list - read a list */
XLOCAL LVAL read_list(fptr)
X  LVAL fptr;
X{
X    LVAL last,val;
X    int ch;
X    
X    cpush(NIL); last = NIL;
X    while ((ch = scan(fptr)) != EOF)
X	switch (ch) {
X	case ';':
X	    read_comment(fptr);
X	    break;
X	case ')':
X	    return (pop());
X	default:
X	    xlungetc(fptr,ch);
X	    if (!xlread(fptr,&val))
X		xlfail("unexpected EOF");
X	    if (val == xlenter(".")) {
X		if (last == NIL)
X		    xlfail("misplaced dot");
X		read_cdr(fptr,last);
X		return (pop());
X	    }
X	    else {
X		val = cons(val,NIL);
X		if (last) rplacd(last,val);
X		else settop(val);
X		last = val;
X	    }
X	    break;
X	}
X    xlfail("unexpected EOF");
X}
X
X/* read_cdr - read the cdr of a dotted pair */
XLOCAL read_cdr(fptr,last)
X  LVAL fptr,last;
X{
X    LVAL val;
X    int ch;
X    
X    /* read the cdr expression */
X    if (!xlread(fptr,&val))
X	xlfail("unexpected EOF");
X    rplacd(last,val);
X    
X    /* check for the close paren */
X    while ((ch = scan(fptr)) == ';')
X	read_comment(fptr);
X    if (ch != ')')
X	xlfail("missing right paren");
X}
X
X/* read_comment - read a comment (to end of line) */
XLOCAL read_comment(fptr)
X  LVAL fptr;
X{
X    int ch;
X    while ((ch = xlgetc(fptr)) != EOF && ch != '\n')
X	;
X    if (ch != EOF) xlungetc(fptr,ch);
X}
X
X/* read_vector - read a vector */
XLOCAL LVAL read_vector(fptr)
X  LVAL fptr;
X{
X    int len=0,ch,i;
X    LVAL last,val;
X    
X    cpush(NIL); last = NIL;
X    while ((ch = scan(fptr)) != EOF)
X	switch (ch) {
X	case ';':
X	    read_comment(fptr);
X	    break;
X	case ')':
X	    val = newvector(len);
X	    for (last = pop(), i = 0; i < len; ++i, last = cdr(last))
X		setelement(val,i,car(last));
X	    return (val);
X	default:
X	    xlungetc(fptr,ch);
X	    if (!xlread(fptr,&val))
X		xlfail("unexpected EOF");
X	    val = cons(val,NIL);
X	    if (last) rplacd(last,val);
X	    else settop(val);
X	    last = val;
X	    ++len;
X	    break;
X	}
X    xlfail("unexpected EOF");
X}
X
X/* read_comma - read a unquote or unquote-splicing expression */
XLOCAL LVAL read_comma(fptr)
X  LVAL fptr;
X{
X    int ch;
X    if ((ch = xlgetc(fptr)) == '@')
X	return (read_quote(fptr,"UNQUOTE-SPLICING"));
X    else {
X	xlungetc(fptr,ch);
X	return (read_quote(fptr,"UNQUOTE"));
X    }
X}
X
X/* read_quote - parse the tail of a quoted expression */
XLOCAL LVAL read_quote(fptr,sym)
X  LVAL fptr; char *sym;
X{
X    LVAL val;
X    if (!xlread(fptr,&val))
X	xlfail("unexpected EOF");
X    cpush(cons(val,NIL));
X    settop(cons(xlenter(sym),top()));
X    return (pop());
X}
X
X/* read_symbol - parse a symbol name (or a number) */
XLOCAL LVAL read_symbol(fptr)
X  LVAL fptr;
X{
X    char buf[STRMAX+1];
X    LVAL val;
X    if (!getsymbol(fptr,buf))
X	xlfail("expecting symbol name");
X    return (isnumber(buf,&val) ? val : xlenter(buf));
X}
X
X/* read_string - parse a string */
XLOCAL LVAL read_string(fptr)
X  LVAL fptr;
X{
X    char buf[STRMAX+1];
X    int ch,i;
X
X    /* get symbol name */
X    for (i = 0; (ch = checkeof(fptr)) != '"'; ) {
X	if (ch == '\\')
X	    ch = checkeof(fptr);
X	if (i < STRMAX)
X	    buf[i++] = ch;
X    }
X    buf[i] = '\0';
X
X    /* return a string */
X    return (cvstring(buf));
X}
X
X/* read_special - parse an atom starting with '#' */
XLOCAL LVAL read_special(fptr)
X  LVAL fptr;
X{
X    char buf[STRMAX+1],buf2[STRMAX+3];
X    int ch;
X    switch (ch = checkeof(fptr)) {
X    case '!':
X	if (getsymbol(fptr,buf)) {
X	    if (strcmp(buf,"TRUE") == 0)
X		return (true);
X	    else if (strcmp(buf,"FALSE") == 0)
X		return (NIL);
X	    else if (strcmp(buf,"NULL") == 0)
X		return (NIL);
X	    else {
X		sprintf(buf2,"#!%s",buf);
X		return (xlenter(buf2));
X	    }
X	}
X	else
X	    xlfail("expecting symbol after '#!'");
X	break;
X    case '\\':
X	ch = checkeof(fptr);	/* get the next character */
X	xlungetc(fptr,ch);	/* but allow getsymbol to get it also */
X	if (getsymbol(fptr,buf)) {
X	    if (strcmp(buf,"NEWLINE") == 0)
X		ch = '\n';
X	    else if (strcmp(buf,"SPACE") == 0)
X		ch = ' ';
X	    else if (strlen(buf) > 1)
X		xlerror("unexpected symbol after '#\\'",cvstring(buf));
X	}
X	else			/* wasn't a symbol, get the character */
X	    ch = checkeof(fptr);
X	return (cvchar(ch));
X    case '(':
X	return (read_vector(fptr));
X    case 'b':
X    case 'B':
X	return (read_radix(fptr,2));
X    case 'o':
X    case 'O':
X	return (read_radix(fptr,8));
X    case 'd':
X    case 'D':
X	return (read_radix(fptr,10));
X    case 'x':
X    case 'X':
X        return (read_radix(fptr,16));
X    default:
X	xlungetc(fptr,ch);
X	if (getsymbol(fptr,buf)) {
X	    if (strcmp(buf,"T") == 0)
X		return (true);
X	    else if (strcmp(buf,"F") == 0)
X		return (NIL);
X	    else
X		xlerror("unexpected symbol after '#'",cvstring(buf));
X	}
X	else
X	    xlerror("unexpected character after '#'",cvchar(xlgetc(fptr)));
X	break;
X    }
X}
X
X/* read_radix - read a number in a specified radix */
XLOCAL LVAL read_radix(fptr,radix)
X  LVAL fptr; int radix;
X{
X    FIXTYPE val;
X    int ch;
X
X    /* get symbol name */
X    for (val = (FIXTYPE)0; (ch = xlgetc(fptr)) != EOF && issym(ch); ) {
X        if (islower(ch)) ch = toupper(ch);
X	if (!isradixdigit(ch,radix))
X	    xlerror("invalid digit",cvchar(ch));
X        val = val * radix + getdigit(ch);
X    }
X
X    /* save the break character */
X    xlungetc(fptr,ch);
X
X    /* return the number */
X    return (cvfixnum(val));
X}
X
X/* isradixdigit - check to see if a character is a digit in a radix */
XLOCAL int isradixdigit(ch,radix)
X  int ch,radix;
X{
X    switch (radix) {
X    case 2:	return (ch >= '0' && ch <= '1');
X    case 8:	return (ch >= '0' && ch <= '7');
X    case 10:	return (ch >= '0' && ch <= '9');
X    case 16:	return ((ch >= '0' && ch <= '9')
X                     || (ch >= 'A' && ch <= 'F'));
X    }
X}
X
X/* getdigit - convert an ascii code to a digit */
XLOCAL int getdigit(ch)
X  int ch;
X{
X    return (ch <= '9' ? ch - '0' : ch - 'A' + 10);
X}
X
X/* getsymbol - get a symbol name */
XLOCAL int getsymbol(fptr,buf)
X  LVAL fptr; char *buf;
X{
X    int ch,i;
X
X    /* get symbol name */
X    for (i = 0; (ch = xlgetc(fptr)) != EOF && issym(ch); )
X	if (i < STRMAX)
X	    buf[i++] = (islower(ch) ? toupper(ch) : ch);
X    buf[i] = '\0';
X
X    /* save the break character */
X    xlungetc(fptr,ch);
X    return (buf[0] != '\0');
X}
X
X/* isnumber - check if this string is a number */
XLOCAL int isnumber(str,pval)
X  char *str; LVAL *pval;
X{
X    int dl,dot,dr;
X    char *p;
X
X    /* initialize */
X    p = str; dl = dot = dr = 0;
X
X    /* check for a sign */
X    if (*p == '+' || *p == '-')
X	p++;
X
X    /* check for a string of digits */
X    while (isdigit(*p))
X	p++, dl++;
X
X    /* check for a decimal point */
X    if (*p == '.') {
X	p++; dot = 1;
X	while (isdigit(*p))
X	    p++, dr++;
X    }
X
X    /* check for an exponent */
X    if ((dl || dr) && *p == 'E') {
X	p++; dot = 1;
X
X	/* check for a sign */
X	if (*p == '+' || *p == '-')
X	    p++;
X
X	/* check for a string of digits */
X	while (isdigit(*p))
X	    p++, dr++;
X    }
X
X    /* make sure there was at least one digit and this is the end */
X    if ((dl == 0 && dr == 0) || *p)
X	return (FALSE);
X
X    /* convert the string to an integer and return successfully */
X    if (pval) {
X	if (*str == '+') ++str;
X	if (str[strlen(str)-1] == '.') str[strlen(str)-1] = 0;
X	*pval = (dot ? cvflonum(atof(str)) : cvfixnum(ICNV(str)));
X    }
X    return (TRUE);
X}
X
X/* scan - scan for the first non-blank character */
XLOCAL int scan(fptr)
X  LVAL fptr;
X{
X    int ch;
X
X    /* look for a non-blank character */
X    while ((ch = xlgetc(fptr)) != EOF && isspace(ch))
X	;
X
X    /* return the character */
X    return (ch);
X}
X
X/* checkeof - get a character and check for end of file */
XLOCAL int checkeof(fptr)
X  LVAL fptr;
X{
X    int ch;
X    if ((ch = xlgetc(fptr)) == EOF)
X	xlfail("unexpected EOF");
X    return (ch);
X}
X
X/* issym - is this a symbol character? */
XLOCAL int issym(ch)
X  int ch;
X{
X    register char *p;
X    if (!isspace(ch)) {
X	for (p = "()';"; *p != '\0'; )
X	    if (*p++ == ch)
X		return (FALSE);
X	return (TRUE);
X    }
X    return (FALSE);
X}
END_OF_FILE
if test 9004 -ne `wc -c <'Src/xsread.c'`; then
    echo shar: \"'Src/xsread.c'\" unpacked with wrong size!
fi
# end of 'Src/xsread.c'
fi
echo shar: End of archive 2 \(of 7\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 6 7 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 7 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
Mail comments to the moderator at <amiga-request@cs.odu.edu>.
Post requests for sources, and general discussion to comp.sys.amiga.