[comp.sources.misc] v10i094: XLisP 2.1 sources 4a

garym@cognos.UUCP (Gary Murphy) (02/27/90)

Posting-number: Volume 10, Issue 94
Submitted-by: garym@cognos.UUCP (Gary Murphy)
Archive-name: xlisp21/part07

#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	xljump.c
#	xllist.c
#	xlmath.c
#	xlobj.c
#	xlpp.c
#	xlprin.c
# This archive created: Sun Feb 18 23:40:11 1990
# By:	Gary Murphy ()
export PATH; PATH=/bin:$PATH
echo shar: extracting "'xljump.c'" '(3889 characters)'
if test -f 'xljump.c'
then
	echo shar: over-writing existing file "'xljump.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'xljump.c'
X/* xljump - execution context routines */
X/*	Copyright (c) 1985, by David Michael Betz
X	All Rights Reserved
X	Permission is granted for unrestricted non-commercial use	*/
X
X#include "xlisp.h"
X
X/* external variables */
Xextern CONTEXT *xlcontext,*xltarget;
Xextern LVAL xlvalue,xlenv,xlfenv,xldenv;
Xextern int xlmask;
X
X/* xlbegin - beginning of an execution context */
Xxlbegin(cptr,flags,expr)
X  CONTEXT *cptr; int flags; LVAL expr;
X{
X    cptr->c_flags = flags;
X    cptr->c_expr = expr;
X    cptr->c_xlstack = xlstack;
X    cptr->c_xlenv = xlenv;
X    cptr->c_xlfenv = xlfenv;
X    cptr->c_xldenv = xldenv;
X    cptr->c_xlcontext = xlcontext;
X    cptr->c_xlargv = xlargv;
X    cptr->c_xlargc = xlargc;
X    cptr->c_xlfp = xlfp;
X    cptr->c_xlsp = xlsp;
X    xlcontext = cptr;
X}
X
X/* xlend - end of an execution context */
Xxlend(cptr)
X  CONTEXT *cptr;
X{
X    xlcontext = cptr->c_xlcontext;
X}
X
X/* xlgo - go to a label */
Xxlgo(label)
X  LVAL label;
X{
X    CONTEXT *cptr;
X    LVAL *argv;
X    int argc;
X
X    /* find a tagbody context */
X    for (cptr = xlcontext; cptr; cptr = cptr->c_xlcontext)
X	if (cptr->c_flags & CF_GO) {
X	    argc = cptr->c_xlargc;
X	    argv = cptr->c_xlargv;
X	    while (--argc >= 0)
X		if (*argv++ == label) {
X		    cptr->c_xlargc = argc;
X		    cptr->c_xlargv = argv;
X		    xljump(cptr,CF_GO,NIL);
X		}
X	}
X    xlfail("no target for GO");
X}
X
X/* xlreturn - return from a block */
Xxlreturn(name,val)
X  LVAL name,val;
X{
X    CONTEXT *cptr;
X
X    /* find a block context */
X    for (cptr = xlcontext; cptr; cptr = cptr->c_xlcontext)
X	if (cptr->c_flags & CF_RETURN && cptr->c_expr == name)
X	    xljump(cptr,CF_RETURN,val);
X    xlfail("no target for RETURN");
X}
X
X/* xlthrow - throw to a catch */
Xxlthrow(tag,val)
X  LVAL tag,val;
X{
X    CONTEXT *cptr;
X
X    /* find a catch context */
X    for (cptr = xlcontext; cptr; cptr = cptr->c_xlcontext)
X	if ((cptr->c_flags & CF_THROW) && cptr->c_expr == tag)
X	    xljump(cptr,CF_THROW,val);
X    xlfail("no target for THROW");
X}
X
X/* xlsignal - signal an error */
Xxlsignal(emsg,arg)
X  char *emsg; LVAL arg;
X{
X    CONTEXT *cptr;
X
X    /* find an error catcher */
X    for (cptr = xlcontext; cptr; cptr = cptr->c_xlcontext)
X	if (cptr->c_flags & CF_ERROR) {
X	    if (cptr->c_expr && emsg)
X		xlerrprint("error",NULL,emsg,arg);
X	    xljump(cptr,CF_ERROR,NIL);
X	}
X}
X
X/* xltoplevel - go back to the top level */
Xxltoplevel()
X{
X    stdputstr("[ back to top level ]\n");
X    findandjump(CF_TOPLEVEL,"no top level");
X}
X
X/* xlbrklevel - go back to the previous break level */
Xxlbrklevel()
X{
X    findandjump(CF_BRKLEVEL,"no previous break level");
X}
X
X/* xlcleanup - clean-up after an error */
Xxlcleanup()
X{
X    stdputstr("[ back to previous break level ]\n");
X    findandjump(CF_CLEANUP,"not in a break loop");
X}
X
X/* xlcontinue - continue from an error */
Xxlcontinue()
X{
X    findandjump(CF_CONTINUE,"not in a break loop");
X}
X
X/* xljump - jump to a saved execution context */
Xxljump(target,mask,val)
X  CONTEXT *target; int mask; LVAL val;
X{
X    /* unwind the execution stack */
X    for (; xlcontext != target; xlcontext = xlcontext->c_xlcontext)
X
X	/* check for an UNWIND-PROTECT */
X	if ((xlcontext->c_flags & CF_UNWIND)) {
X	    xltarget = target;
X	    xlmask = mask;
X	    break;
X	}
X	   
X    /* restore the state */
X    xlstack = xlcontext->c_xlstack;
X    xlenv = xlcontext->c_xlenv;
X    xlfenv = xlcontext->c_xlfenv;
X    xlunbind(xlcontext->c_xldenv);
X    xlargv = xlcontext->c_xlargv;
X    xlargc = xlcontext->c_xlargc;
X    xlfp = xlcontext->c_xlfp;
X    xlsp = xlcontext->c_xlsp;
X    xlvalue = val;
X
X    /* call the handler */
X    longjmp(xlcontext->c_jmpbuf,mask);
X}
X
X/* findandjump - find a target context frame and jump to it */
XLOCAL findandjump(mask,error)
X  int mask; char *error;
X{
X    CONTEXT *cptr;
X
X    /* find a block context */
X    for (cptr = xlcontext; cptr; cptr = cptr->c_xlcontext)
X	if (cptr->c_flags & mask)
X	    xljump(cptr,mask,NIL);
X    xlabort(error);
X}
X
SHAR_EOF
if test 3889 -ne "`wc -c 'xljump.c'`"
then
	echo shar: error transmitting "'xljump.c'" '(should have been 3889 characters)'
fi
echo shar: extracting "'xllist.c'" '(18761 characters)'
if test -f 'xllist.c'
then
	echo shar: over-writing existing file "'xllist.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'xllist.c'
X/* xllist.c - xlisp built-in list functions */
X/*	Copyright (c) 1985, by David Michael Betz
X	All Rights Reserved
X	Permission is granted for unrestricted non-commercial use	*/
X
X#include "xlisp.h"
X
X/* forward declarations */
XFORWARD LVAL cxr();
XFORWARD LVAL nth(),assoc();
XFORWARD LVAL subst(),sublis(),map();
X
X/* xcar - take the car of a cons cell */
XLVAL xcar()
X{
X    LVAL list;
X    list = xlgalist();
X    xllastarg();
X    return (list ? car(list) : NIL);
X}
X
X/* xcdr - take the cdr of a cons cell */
XLVAL xcdr()
X{
X    LVAL list;
X    list = xlgalist();
X    xllastarg();
X    return (list ? cdr(list) : NIL);
X}
X
X/* cxxr functions */
XLVAL xcaar() { return (cxr("aa")); }
XLVAL xcadr() { return (cxr("da")); }
XLVAL xcdar() { return (cxr("ad")); }
XLVAL xcddr() { return (cxr("dd")); }
X
X/* cxxxr functions */
XLVAL xcaaar() { return (cxr("aaa")); }
XLVAL xcaadr() { return (cxr("daa")); }
XLVAL xcadar() { return (cxr("ada")); }
XLVAL xcaddr() { return (cxr("dda")); }
XLVAL xcdaar() { return (cxr("aad")); }
XLVAL xcdadr() { return (cxr("dad")); }
XLVAL xcddar() { return (cxr("add")); }
XLVAL xcdddr() { return (cxr("ddd")); }
X
X/* cxxxxr functions */
XLVAL xcaaaar() { return (cxr("aaaa")); }
XLVAL xcaaadr() { return (cxr("daaa")); }
XLVAL xcaadar() { return (cxr("adaa")); }
XLVAL xcaaddr() { return (cxr("ddaa")); }
XLVAL xcadaar() { return (cxr("aada")); }
XLVAL xcadadr() { return (cxr("dada")); }
XLVAL xcaddar() { return (cxr("adda")); }
XLVAL xcadddr() { return (cxr("ddda")); }
XLVAL xcdaaar() { return (cxr("aaad")); }
XLVAL xcdaadr() { return (cxr("daad")); }
XLVAL xcdadar() { return (cxr("adad")); }
XLVAL xcdaddr() { return (cxr("ddad")); }
XLVAL xcddaar() { return (cxr("aadd")); }
XLVAL xcddadr() { return (cxr("dadd")); }
XLVAL xcdddar() { return (cxr("addd")); }
XLVAL xcddddr() { return (cxr("dddd")); }
X
X/* cxr - common car/cdr routine */
XLOCAL LVAL cxr(adstr)
X  char *adstr;
X{
X    LVAL list;
X
X    /* get the list */
X    list = xlgalist();
X    xllastarg();
X
X    /* perform the car/cdr operations */
X    while (*adstr && consp(list))
X	list = (*adstr++ == 'a' ? car(list) : cdr(list));
X
X    /* make sure the operation succeeded */
X    if (*adstr && list)
X	xlfail("bad argument");
X
X    /* return the result */
X    return (list);
X}
X
X/* xcons - construct a new list cell */
XLVAL xcons()
X{
X    LVAL arg1,arg2;
X
X    /* get the two arguments */
X    arg1 = xlgetarg();
X    arg2 = xlgetarg();
X    xllastarg();
X
X    /* construct a new list element */
X    return (cons(arg1,arg2));
X}
X
X/* xlist - built a list of the arguments */
XLVAL xlist()
X{
X    LVAL last,next,val;
X
X    /* protect some pointers */
X    xlsave1(val);
X
X    /* add each argument to the list */
X    for (val = NIL; moreargs(); ) {
X
X	/* append this argument to the end of the list */
X	next = consa(nextarg());
X	if (val) rplacd(last,next);
X	else val = next;
X	last = next;
X    }
X
X    /* restore the stack */
X    xlpop();
X
X    /* return the list */
X    return (val);
X}
X
X/* xappend - built-in function append */
XLVAL xappend()
X{
X    LVAL list,last,next,val;
X
X    /* protect some pointers */
X    xlsave1(val);
X
X    /* initialize */
X    val = NIL;
X    
X    /* append each argument */
X    if (moreargs()) {
X	while (xlargc > 1) {
X
X	    /* append each element of this list to the result list */
X	    for (list = nextarg(); consp(list); list = cdr(list)) {
X		next = consa(car(list));
X		if (val) rplacd(last,next);
X		else val = next;
X		last = next;
X	    }
X	}
X
X	/* handle the last argument */
X	if (val) rplacd(last,nextarg());
X	else val = nextarg();
X    }
X
X    /* restore the stack */
X    xlpop();
X
X    /* return the list */
X    return (val);
X}
X
X/* xreverse - built-in function reverse */
XLVAL xreverse()
X{
X    LVAL list,val;
X
X    /* protect some pointers */
X    xlsave1(val);
X
X    /* get the list to reverse */
X    list = xlgalist();
X    xllastarg();
X
X    /* append each element to the head of the result list */
X    for (val = NIL; consp(list); list = cdr(list))
X	val = cons(car(list),val);
X
X    /* restore the stack */
X    xlpop();
X
X    /* return the list */
X    return (val);
X}
X
X/* xlast - return the last cons of a list */
XLVAL xlast()
X{
X    LVAL list;
X
X    /* get the list */
X    list = xlgalist();
X    xllastarg();
X
X    /* find the last cons */
X    while (consp(list) && cdr(list))
X	list = cdr(list);
X
X    /* return the last element */
X    return (list);
X}
X
X/* xmember - built-in function 'member' */
XLVAL xmember()
X{
X    LVAL x,list,fcn,val;
X    int tresult;
X
X    /* protect some pointers */
X    xlsave1(fcn);
X
X    /* get the expression to look for and the list */
X    x = xlgetarg();
X    list = xlgalist();
X    xltest(&fcn,&tresult);
X
X    /* look for the expression */
X    for (val = NIL; consp(list); list = cdr(list))
X	if (dotest2(x,car(list),fcn) == tresult) {
X	    val = list;
X	    break;
X	}
X
X    /* restore the stack */
X    xlpop();
X
X    /* return the result */
X    return (val);
X}
X
X/* xassoc - built-in function 'assoc' */
XLVAL xassoc()
X{
X    LVAL x,alist,fcn,pair,val;
X    int tresult;
X
X    /* protect some pointers */
X    xlsave1(fcn);
X
X    /* get the expression to look for and the association list */
X    x = xlgetarg();
X    alist = xlgalist();
X    xltest(&fcn,&tresult);
X
X    /* look for the expression */
X    for (val = NIL; consp(alist); alist = cdr(alist))
X	if ((pair = car(alist)) && consp(pair))
X	    if (dotest2(x,car(pair),fcn) == tresult) {
X		val = pair;
X		break;
X	    }
X
X    /* restore the stack */
X    xlpop();
X
X    /* return result */
X    return (val);
X}
X
X/* xsubst - substitute one expression for another */
XLVAL xsubst()
X{
X    LVAL to,from,expr,fcn,val;
X    int tresult;
X
X    /* protect some pointers */
X    xlsave1(fcn);
X
X    /* get the to value, the from value and the expression */
X    to = xlgetarg();
X    from = xlgetarg();
X    expr = xlgetarg();
X    xltest(&fcn,&tresult);
X
X    /* do the substitution */
X    val = subst(to,from,expr,fcn,tresult);
X
X    /* restore the stack */
X    xlpop();
X
X    /* return the result */
X    return (val);
X}
X
X/* subst - substitute one expression for another */
XLOCAL LVAL subst(to,from,expr,fcn,tresult)
X  LVAL to,from,expr,fcn; int tresult;
X{
X    LVAL carval,cdrval;
X
X    if (dotest2(expr,from,fcn) == tresult)
X	return (to);
X    else if (consp(expr)) {
X	xlsave1(carval);
X	carval = subst(to,from,car(expr),fcn,tresult);
X	cdrval = subst(to,from,cdr(expr),fcn,tresult);
X	xlpop();
X	return (cons(carval,cdrval));
X    }
X    else
X	return (expr);
X}
X
X/* xsublis - substitute using an association list */
XLVAL xsublis()
X{
X    LVAL alist,expr,fcn,val;
X    int tresult;
X
X    /* protect some pointers */
X    xlsave1(fcn);
X
X    /* get the assocation list and the expression */
X    alist = xlgalist();
X    expr = xlgetarg();
X    xltest(&fcn,&tresult);
X
X    /* do the substitution */
X    val = sublis(alist,expr,fcn,tresult);
X
X    /* restore the stack */
X    xlpop();
X
X    /* return the result */
X    return (val);
X}
X
X/* sublis - substitute using an association list */
XLOCAL LVAL sublis(alist,expr,fcn,tresult)
X  LVAL alist,expr,fcn; int tresult;
X{
X    LVAL carval,cdrval,pair;
X
X    if (pair = assoc(expr,alist,fcn,tresult))
X	return (cdr(pair));
X    else if (consp(expr)) {
X	xlsave1(carval);
X	carval = sublis(alist,car(expr),fcn,tresult);
X	cdrval = sublis(alist,cdr(expr),fcn,tresult);
X	xlpop();
X	return (cons(carval,cdrval));
X    }
X    else
X	return (expr);
X}
X
X/* assoc - find a pair in an association list */
XLOCAL LVAL assoc(expr,alist,fcn,tresult)
X  LVAL expr,alist,fcn; int tresult;
X{
X    LVAL pair;
X
X    for (; consp(alist); alist = cdr(alist))
X	if ((pair = car(alist)) && consp(pair))
X	    if (dotest2(expr,car(pair),fcn) == tresult)
X		return (pair);
X    return (NIL);
X}
X
X/* xremove - built-in function 'remove' */
XLVAL xremove()
X{
X    LVAL x,list,fcn,val,last,next;
X    int tresult;
X
X    /* protect some pointers */
X    xlstkcheck(2);
X    xlsave(fcn);
X    xlsave(val);
X
X    /* get the expression to remove and the list */
X    x = xlgetarg();
X    list = xlgalist();
X    xltest(&fcn,&tresult);
X
X    /* remove matches */
X    for (; consp(list); list = cdr(list))
X
X	/* check to see if this element should be deleted */
X	if (dotest2(x,car(list),fcn) != tresult) {
X	    next = consa(car(list));
X	    if (val) rplacd(last,next);
X	    else val = next;
X	    last = next;
X	}
X
X    /* restore the stack */
X    xlpopn(2);
X
X    /* return the updated list */
X    return (val);
X}
X
X/* xremif - built-in function 'remove-if' */
XLVAL xremif()
X{
X    LVAL remif();
X    return (remif(TRUE));
X}
X
X/* xremifnot - built-in function 'remove-if-not' */
XLVAL xremifnot()
X{
X    LVAL remif();
X    return (remif(FALSE));
X}
X
X/* remif - common code for 'remove-if' and 'remove-if-not' */
XLOCAL LVAL remif(tresult)
X  int tresult;
X{
X    LVAL list,fcn,val,last,next;
X
X    /* protect some pointers */
X    xlstkcheck(2);
X    xlsave(fcn);
X    xlsave(val);
X
X    /* get the expression to remove and the list */
X    fcn = xlgetarg();
X    list = xlgalist();
X    xllastarg();
X
X    /* remove matches */
X    for (; consp(list); list = cdr(list))
X
X	/* check to see if this element should be deleted */
X	if (dotest1(car(list),fcn) != tresult) {
X	    next = consa(car(list));
X	    if (val) rplacd(last,next);
X	    else val = next;
X	    last = next;
X	}
X
X    /* restore the stack */
X    xlpopn(2);
X
X    /* return the updated list */
X    return (val);
X}
X
X/* dotest1 - call a test function with one argument */
Xint dotest1(arg,fun)
X  LVAL arg,fun;
X{
X    LVAL *newfp;
X
X    /* create the new call frame */
X    newfp = xlsp;
X    pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
X    pusharg(fun);
X    pusharg(cvfixnum((FIXTYPE)1));
X    pusharg(arg);
X    xlfp = newfp;
X
X    /* return the result of applying the test function */
X    return (xlapply(1) != NIL);
X
X}
X
X/* dotest2 - call a test function with two arguments */
Xint dotest2(arg1,arg2,fun)
X  LVAL arg1,arg2,fun;
X{
X    LVAL *newfp;
X
X    /* create the new call frame */
X    newfp = xlsp;
X    pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
X    pusharg(fun);
X    pusharg(cvfixnum((FIXTYPE)2));
X    pusharg(arg1);
X    pusharg(arg2);
X    xlfp = newfp;
X
X    /* return the result of applying the test function */
X    return (xlapply(2) != NIL);
X
X}
X
X/* xnth - return the nth element of a list */
XLVAL xnth()
X{
X    return (nth(TRUE));
X}
X
X/* xnthcdr - return the nth cdr of a list */
XLVAL xnthcdr()
X{
X    return (nth(FALSE));
X}
X
X/* nth - internal nth function */
XLOCAL LVAL nth(carflag)
X  int carflag;
X{
X    LVAL list,num;
X    FIXTYPE n;
X
X    /* get n and the list */
X    num = xlgafixnum();
X    list = xlgacons();
X    xllastarg();
X
X    /* make sure the number isn't negative */
X    if ((n = getfixnum(num)) < 0)
X	xlfail("bad argument");
X
X    /* find the nth element */
X    while (consp(list) && --n >= 0)
X	list = cdr(list);
X
X    /* return the list beginning at the nth element */
X    return (carflag && consp(list) ? car(list) : list);
X}
X
X/* xlength - return the length of a list or string */
XLVAL xlength()
X{
X    FIXTYPE n;
X    LVAL arg;
X
X    /* get the list or string */
X    arg = xlgetarg();
X    xllastarg();
X
X    /* find the length of a list */
X    if (listp(arg))
X	for (n = 0; consp(arg); n++)
X	    arg = cdr(arg);
X
X    /* find the length of a string */
X    else if (stringp(arg))
X	n = (FIXTYPE)getslength(arg)-1;
X
X    /* find the length of a vector */
X    else if (vectorp(arg))
X	n = (FIXTYPE)getsize(arg);
X
X    /* otherwise, bad argument type */
X    else
X	xlerror("bad argument type",arg);
X
X    /* return the length */
X    return (cvfixnum(n));
X}
X
X/* xmapc - built-in function 'mapc' */
XLVAL xmapc()
X{
X    return (map(TRUE,FALSE));
X}
X
X/* xmapcar - built-in function 'mapcar' */
XLVAL xmapcar()
X{
X    return (map(TRUE,TRUE));
X}
X
X/* xmapl - built-in function 'mapl' */
XLVAL xmapl()
X{
X    return (map(FALSE,FALSE));
X}
X
X/* xmaplist - built-in function 'maplist' */
XLVAL xmaplist()
X{
X    return (map(FALSE,TRUE));
X}
X
X/* map - internal mapping function */
XLOCAL LVAL map(carflag,valflag)
X  int carflag,valflag;
X{
X    LVAL *newfp,fun,lists,val,last,p,x,y;
X    int argc;
X
X    /* protect some pointers */
X    xlstkcheck(3);
X    xlsave(fun);
X    xlsave(lists);
X    xlsave(val);
X
X    /* get the function to apply and the first list */
X    fun = xlgetarg();
X    lists = xlgalist();
X
X    /* initialize the result list */
X    val = (valflag ? NIL : lists);
X
X    /* build a list of argument lists */
X    for (lists = last = consa(lists); moreargs(); last = cdr(last))
X	rplacd(last,cons(xlgalist(),NIL));
X
X    /* loop through each of the argument lists */
X    for (;;) {
X
X	/* build an argument list from the sublists */
X	newfp = xlsp;
X	pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
X	pusharg(fun);
X	pusharg(NIL);
X	argc = 0;
X	for (x = lists; x && (y = car(x)) && consp(y); x = cdr(x)) {
X	    pusharg(carflag ? car(y) : y);
X	    rplaca(x,cdr(y));
X	    ++argc;
X	}
X
X	/* quit if any of the lists were empty */
X	if (x) {
X	    xlsp = newfp;
X	    break;
X	}
X
X	/* apply the function to the arguments */
X	newfp[2] = cvfixnum((FIXTYPE)argc);
X	xlfp = newfp;
X	if (valflag) {
X	    p = consa(xlapply(argc));
X	    if (val) rplacd(last,p);
X	    else val = p;
X	    last = p;
X	}
X	else
X	    xlapply(argc);
X    }
X
X    /* restore the stack */
X    xlpopn(3);
X
X    /* return the last test expression value */
X    return (val);
X}
X
X/* xrplca - replace the car of a list node */
XLVAL xrplca()
X{
X    LVAL list,newcar;
X
X    /* get the list and the new car */
X    list = xlgacons();
X    newcar = xlgetarg();
X    xllastarg();
X
X    /* replace the car */
X    rplaca(list,newcar);
X
X    /* return the list node that was modified */
X    return (list);
X}
X
X/* xrplcd - replace the cdr of a list node */
XLVAL xrplcd()
X{
X    LVAL list,newcdr;
X
X    /* get the list and the new cdr */
X    list = xlgacons();
X    newcdr = xlgetarg();
X    xllastarg();
X
X    /* replace the cdr */
X    rplacd(list,newcdr);
X
X    /* return the list node that was modified */
X    return (list);
X}
X
X/* xnconc - destructively append lists */
XLVAL xnconc()
X{
X    LVAL next,last,val;
X
X    /* initialize */
X    val = NIL;
X    
X    /* concatenate each argument */
X    if (moreargs()) {
X	while (xlargc > 1) {
X
X	    /* ignore everything except lists */
X	    if ((next = nextarg()) && consp(next)) {
X
X		/* concatenate this list to the result list */
X		if (val) rplacd(last,next);
X		else val = next;
X
X		/* find the end of the list */
X		while (consp(cdr(next)))
X		    next = cdr(next);
X		last = next;
X	    }
X	}
X
X	/* handle the last argument */
X	if (val) rplacd(last,nextarg());
X	else val = nextarg();
X    }
X
X    /* return the list */
X    return (val);
X}
X
X/* xdelete - built-in function 'delete' */
XLVAL xdelete()
X{
X    LVAL x,list,fcn,last,val;
X    int tresult;
X
X    /* protect some pointers */
X    xlsave1(fcn);
X
X    /* get the expression to delete and the list */
X    x = xlgetarg();
X    list = xlgalist();
X    xltest(&fcn,&tresult);
X
X    /* delete leading matches */
X    while (consp(list)) {
X	if (dotest2(x,car(list),fcn) != tresult)
X	    break;
X	list = cdr(list);
X    }
X    val = last = list;
X
X    /* delete embedded matches */
X    if (consp(list)) {
X
X	/* skip the first non-matching element */
X	list = cdr(list);
X
X	/* look for embedded matches */
X	while (consp(list)) {
X
X	    /* check to see if this element should be deleted */
X	    if (dotest2(x,car(list),fcn) == tresult)
X		rplacd(last,cdr(list));
X	    else
X		last = list;
X
X	    /* move to the next element */
X	    list = cdr(list);
X 	}
X    }
X
X    /* restore the stack */
X    xlpop();
X
X    /* return the updated list */
X    return (val);
X}
X
X/* xdelif - built-in function 'delete-if' */
XLVAL xdelif()
X{
X    LVAL delif();
X    return (delif(TRUE));
X}
X
X/* xdelifnot - built-in function 'delete-if-not' */
XLVAL xdelifnot()
X{
X    LVAL delif();
X    return (delif(FALSE));
X}
X
X/* delif - common routine for 'delete-if' and 'delete-if-not' */
XLOCAL LVAL delif(tresult)
X  int tresult;
X{
X    LVAL list,fcn,last,val;
X
X    /* protect some pointers */
X    xlsave1(fcn);
X
X    /* get the expression to delete and the list */
X    fcn = xlgetarg();
X    list = xlgalist();
X    xllastarg();
X
X    /* delete leading matches */
X    while (consp(list)) {
X	if (dotest1(car(list),fcn) != tresult)
X	    break;
X	list = cdr(list);
X    }
X    val = last = list;
X
X    /* delete embedded matches */
X    if (consp(list)) {
X
X	/* skip the first non-matching element */
X	list = cdr(list);
X
X	/* look for embedded matches */
X	while (consp(list)) {
X
X	    /* check to see if this element should be deleted */
X	    if (dotest1(car(list),fcn) == tresult)
X		rplacd(last,cdr(list));
X	    else
X		last = list;
X
X	    /* move to the next element */
X	    list = cdr(list);
X 	}
X    }
X
X    /* restore the stack */
X    xlpop();
X
X    /* return the updated list */
X    return (val);
X}
X
X/* xsort - built-in function 'sort' */
XLVAL xsort()
X{
X    LVAL sortlist();
X    LVAL list,fcn;
X
X    /* protect some pointers */
X    xlstkcheck(2);
X    xlsave(list);
X    xlsave(fcn);
X
X    /* get the list to sort and the comparison function */
X    list = xlgalist();
X    fcn = xlgetarg();
X    xllastarg();
X
X    /* sort the list */
X    list = sortlist(list,fcn);
X
X    /* restore the stack and return the sorted list */
X    xlpopn(2);
X    return (list);
X}
X
X/*
X    This sorting algorithm is based on a Modula-2 sort written by
X    Richie Bielak and published in the February 1988 issue of
X    "Computer Language" magazine in a letter to the editor.
X*/
X
X/* sortlist - sort a list using quicksort */
XLOCAL LVAL sortlist(list,fcn)
X  LVAL list,fcn;
X{
X    LVAL gluelists();
X    LVAL smaller,pivot,larger;
X    
X    /* protect some pointers */
X    xlstkcheck(3);
X    xlsave(smaller);
X    xlsave(pivot);
X    xlsave(larger);
X    
X    /* lists with zero or one element are already sorted */
X    if (consp(list) && consp(cdr(list))) {
X	pivot = list; list = cdr(list);
X	splitlist(pivot,list,&smaller,&larger,fcn);
X	smaller = sortlist(smaller,fcn);
X	larger = sortlist(larger,fcn);
X	list = gluelists(smaller,pivot,larger);
X    }
X
X    /* cleanup the stack and return the sorted list */
X    xlpopn(3);
X    return (list);
X}
X
X/* splitlist - split the list around the pivot */
XLOCAL splitlist(pivot,list,psmaller,plarger,fcn)
X  LVAL pivot,list,*psmaller,*plarger,fcn;
X{
X    LVAL next;
X    
X    /* initialize the result lists */
X    *psmaller = *plarger = NIL;
X    
X    /* split the list */
X    for (; consp(list); list = next) {
X	next = cdr(list);
X	if (dotest2(car(list),car(pivot),fcn)) {
X	    rplacd(list,*psmaller);
X	    *psmaller = list;
X	}
X	else {
X	    rplacd(list,*plarger);
X	    *plarger = list;
X	}
X    }
X}
X
X/* gluelists - glue the smaller and larger lists with the pivot */
XLOCAL LVAL gluelists(smaller,pivot,larger)
X  LVAL smaller,pivot,larger;
X{
X    LVAL last;
X    
X    /* larger always goes after the pivot */
X    rplacd(pivot,larger);
X
X    /* if the smaller list is empty, we're done */
X    if (null(smaller))
X	return (pivot);
X
X    /* append the smaller to the front of the resulting list */
X    for (last = smaller; consp(cdr(last)); last = cdr(last))
X	;
X    rplacd(last,pivot);
X    return (smaller);
X}
SHAR_EOF
if test 18761 -ne "`wc -c 'xllist.c'`"
then
	echo shar: error transmitting "'xllist.c'" '(should have been 18761 characters)'
fi
echo shar: extracting "'xlmath.c'" '(9993 characters)'
if test -f 'xlmath.c'
then
	echo shar: over-writing existing file "'xlmath.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'xlmath.c'
X/* xlmath - xlisp built-in arithmetic functions */
X/*	Copyright (c) 1985, by David Michael Betz
X	All Rights Reserved
X	Permission is granted for unrestricted non-commercial use	*/
X
X#include "xlisp.h"
X#include <math.h>
X
X/* external variables */
Xextern LVAL true;
X
X/* forward declarations */
XFORWARD LVAL unary();
XFORWARD LVAL binary();
XFORWARD LVAL predicate();
XFORWARD LVAL compare();
X
X/* binary functions */
XLVAL xadd()    { return (binary('+')); } /* + */
XLVAL xsub()    { return (binary('-')); } /* - */
XLVAL xmul()    { return (binary('*')); } /* * */
XLVAL xdiv()    { return (binary('/')); } /* / */
XLVAL xrem()    { return (binary('%')); } /* rem */
XLVAL xmin()    { return (binary('m')); } /* min */
XLVAL xmax()    { return (binary('M')); } /* max */
XLVAL xexpt()   { return (binary('E')); } /* expt */
XLVAL xlogand() { return (binary('&')); } /* logand */
XLVAL xlogior() { return (binary('|')); } /* logior */
XLVAL xlogxor() { return (binary('^')); } /* logxor */
X
X/* xgcd - greatest common divisor */
XLVAL xgcd()
X{
X    FIXTYPE m,n,r;
X    LVAL arg;
X
X    if (!moreargs())			/* check for identity case */
X	return (cvfixnum((FIXTYPE)0));
X    arg = xlgafixnum();
X    n = getfixnum(arg);
X    if (n < (FIXTYPE)0) n = -n;		/* absolute value */
X    while (moreargs()) {
X	arg = xlgafixnum();
X	m = getfixnum(arg);
X	if (m < (FIXTYPE)0) m = -m;	/* absolute value */
X	for (;;) {			/* euclid's algorithm */
X	    r = m % n;
X	    if (r == (FIXTYPE)0)
X		break;
X	    m = n;
X	    n = r;
X	}
X    }
X    return (cvfixnum(n));
X}
X
X/* binary - handle binary operations */
XLOCAL LVAL binary(fcn)
X  int fcn;
X{
X    FIXTYPE ival,iarg;
X    FLOTYPE fval,farg;
X    LVAL arg;
X    int mode;
X
X    /* get the first argument */
X    arg = xlgetarg();
X
X    /* set the type of the first argument */
X    if (fixp(arg)) {
X	ival = getfixnum(arg);
X	mode = 'I';
X    }
X    else if (floatp(arg)) {
X	fval = getflonum(arg);
X	mode = 'F';
X    }
X    else
X	xlerror("bad argument type",arg);
X
X    /* treat a single argument as a special case */
X    if (!moreargs()) {
X	switch (fcn) {
X	case '-':
X	    switch (mode) {
X	    case 'I':
X		ival = -ival;
X		break;
X	    case 'F':
X		fval = -fval;
X		break;
X	    }
X	    break;
X	case '/':
X	    switch (mode) {
X	    case 'I':
X		checkizero(ival);
X		ival = 1 / ival;
X		break;
X	    case 'F':
X		checkfzero(fval);
X		fval = 1.0 / fval;
X		break;
X	    }
X	}
X    }
X
X    /* handle each remaining argument */
X    while (moreargs()) {
X
X	/* get the next argument */
X	arg = xlgetarg();
X
X	/* check its type */
X	if (fixp(arg)) {
X	    switch (mode) {
X	    case 'I':
X	        iarg = getfixnum(arg);
X	        break;
X	    case 'F':
X	        farg = (FLOTYPE)getfixnum(arg);
X		break;
X	    }
X	}
X	else if (floatp(arg)) {
X	    switch (mode) {
X	    case 'I':
X	        fval = (FLOTYPE)ival;
X		farg = getflonum(arg);
X		mode = 'F';
X		break;
X	    case 'F':
X	        farg = getflonum(arg);
X		break;
X	    }
X	}
X	else
X	    xlerror("bad argument type",arg);
X
X	/* accumulate the result value */
X	switch (mode) {
X	case 'I':
X	    switch (fcn) {
X	    case '+':	ival += iarg; break;
X	    case '-':	ival -= iarg; break;
X	    case '*':	ival *= iarg; break;
X	    case '/':	checkizero(iarg); ival /= iarg; break;
X	    case '%':	checkizero(iarg); ival %= iarg; break;
X	    case 'M':	if (iarg > ival) ival = iarg; break;
X	    case 'm':	if (iarg < ival) ival = iarg; break;
X	    case '&':	ival &= iarg; break;
X	    case '|':	ival |= iarg; break;
X	    case '^':	ival ^= iarg; break;
X	    default:	badiop();
X	    }
X	    break;
X	case 'F':
X	    switch (fcn) {
X	    case '+':	fval += farg; break;
X	    case '-':	fval -= farg; break;
X	    case '*':	fval *= farg; break;
X	    case '/':	checkfzero(farg); fval /= farg; break;
X	    case 'M':	if (farg > fval) fval = farg; break;
X	    case 'm':	if (farg < fval) fval = farg; break;
X	    case 'E':	fval = pow(fval,farg); break;
X	    default:	badfop();
X	    }
X    	    break;
X	}
X    }
X
X    /* return the result */
X    switch (mode) {
X    case 'I':	return (cvfixnum(ival));
X    case 'F':	return (cvflonum(fval));
X    }
X}
X
X/* checkizero - check for integer division by zero */
Xcheckizero(iarg)
X  FIXTYPE iarg;
X{
X    if (iarg == 0)
X	xlfail("division by zero");
X}
X
X/* checkfzero - check for floating point division by zero */
Xcheckfzero(farg)
X  FLOTYPE farg;
X{
X    if (farg == 0.0)
X	xlfail("division by zero");
X}
X
X/* checkfneg - check for square root of a negative number */
Xcheckfneg(farg)
X  FLOTYPE farg;
X{
X    if (farg < 0.0)
X	xlfail("square root of a negative number");
X}
X
X/* unary functions */
XLVAL xlognot() { return (unary('~')); } /* lognot */
XLVAL xabs()    { return (unary('A')); } /* abs */
XLVAL xadd1()   { return (unary('+')); } /* 1+ */
XLVAL xsub1()   { return (unary('-')); } /* 1- */
XLVAL xsin()    { return (unary('S')); } /* sin */
XLVAL xcos()    { return (unary('C')); } /* cos */
XLVAL xtan()    { return (unary('T')); } /* tan */
XLVAL xasin()   { return (unary('s')); } /* asin */
XLVAL xacos()   { return (unary('c')); } /* acos */
XLVAL xatan()   { return (unary('t')); } /* atan */
XLVAL xexp()    { return (unary('E')); } /* exp */
XLVAL xsqrt()   { return (unary('R')); } /* sqrt */
XLVAL xfix()    { return (unary('I')); } /* truncate */
XLVAL xfloat()  { return (unary('F')); } /* float */
XLVAL xrand()   { return (unary('?')); } /* random */
X
X/* unary - handle unary operations */
XLOCAL LVAL unary(fcn)
X  int fcn;
X{
X    FLOTYPE fval;
X    FIXTYPE ival;
X    LVAL arg;
X
X    /* get the argument */
X    arg = xlgetarg();
X    xllastarg();
X
X    /* check its type */
X    if (fixp(arg)) {
X	ival = getfixnum(arg);
X	switch (fcn) {
X	case '~':	ival = ~ival; break;
X	case 'A':	ival = (ival < 0 ? -ival : ival); break;
X	case '+':	ival++; break;
X	case '-':	ival--; break;
X	case 'I':	break;
X	case 'F':	return (cvflonum((FLOTYPE)ival));
X	case '?':	ival = (FIXTYPE)osrand((int)ival); break;
X	default:	badiop();
X	}
X	return (cvfixnum(ival));
X    }
X    else if (floatp(arg)) {
X	fval = getflonum(arg);
X	switch (fcn) {
X	case 'A':	fval = (fval < 0.0 ? -fval : fval); break;
X	case '+':	fval += 1.0; break;
X	case '-':	fval -= 1.0; break;
X	case 'S':	fval = sin(fval); break;
X	case 'C':	fval = cos(fval); break;
X	case 'T':	fval = tan(fval); break;
X	case 's':	fval = asin(fval); break;
X	case 'c':	fval = acos(fval); break;
X	case 't':	fval = atan(fval); break;
X	case 'E':	fval = exp(fval); break;
X	case 'R':	checkfneg(fval); fval = sqrt(fval); break;
X	case 'I':	return (cvfixnum((FIXTYPE)fval));
X	case 'F':	break;
X	default:	badfop();
X	}
X	return (cvflonum(fval));
X    }
X    else
X	xlerror("bad argument type",arg);
X}
X
X/* unary predicates */
XLVAL xminusp() { return (predicate('-')); } /* minusp */
XLVAL xzerop()  { return (predicate('Z')); } /* zerop */
XLVAL xplusp()  { return (predicate('+')); } /* plusp */
XLVAL xevenp()  { return (predicate('E')); } /* evenp */
XLVAL xoddp()   { return (predicate('O')); } /* oddp */
X
X/* predicate - handle a predicate function */
XLOCAL LVAL predicate(fcn)
X  int fcn;
X{
X    FLOTYPE fval;
X    FIXTYPE ival;
X    LVAL arg;
X
X    /* get the argument */
X    arg = xlgetarg();
X    xllastarg();
X
X    /* check the argument type */
X    if (fixp(arg)) {
X	ival = getfixnum(arg);
X	switch (fcn) {
X	case '-':	ival = (ival < 0); break;
X	case 'Z':	ival = (ival == 0); break;
X	case '+':	ival = (ival > 0); break;
X	case 'E':	ival = ((ival & 1) == 0); break;
X	case 'O':	ival = ((ival & 1) != 0); break;
X	default:	badiop();
X	}
X    }
X    else if (floatp(arg)) {
X	fval = getflonum(arg);
X	switch (fcn) {
X	case '-':	ival = (fval < 0); break;
X	case 'Z':	ival = (fval == 0); break;
X	case '+':	ival = (fval > 0); break;
X	default:	badfop();
X	}
X    }
X    else
X	xlerror("bad argument type",arg);
X
X    /* return the result value */
X    return (ival ? true : NIL);
X}
X
X/* comparison functions */
XLVAL xlss() { return (compare('<')); } /* < */
XLVAL xleq() { return (compare('L')); } /* <= */
XLVAL xequ() { return (compare('=')); } /* = */
XLVAL xneq() { return (compare('#')); } /* /= */
XLVAL xgeq() { return (compare('G')); } /* >= */
XLVAL xgtr() { return (compare('>')); } /* > */
X
X/* compare - common compare function */
XLOCAL LVAL compare(fcn)
X  int fcn;
X{
X    FIXTYPE icmp,ival,iarg;
X    FLOTYPE fcmp,fval,farg;
X    LVAL arg;
X    int mode;
X
X    /* get the first argument */
X    arg = xlgetarg();
X
X    /* set the type of the first argument */
X    if (fixp(arg)) {
X	ival = getfixnum(arg);
X	mode = 'I';
X    }
X    else if (floatp(arg)) {
X	fval = getflonum(arg);
X	mode = 'F';
X    }
X    else
X	xlerror("bad argument type",arg);
X
X    /* handle each remaining argument */
X    for (icmp = TRUE; icmp && moreargs(); ival = iarg, fval = farg) {
X
X	/* get the next argument */
X	arg = xlgetarg();
X
X	/* check its type */
X	if (fixp(arg)) {
X	    switch (mode) {
X	    case 'I':
X	        iarg = getfixnum(arg);
X	        break;
X	    case 'F':
X	        farg = (FLOTYPE)getfixnum(arg);
X		break;
X	    }
X	}
X	else if (floatp(arg)) {
X	    switch (mode) {
X	    case 'I':
X	        fval = (FLOTYPE)ival;
X		farg = getflonum(arg);
X		mode = 'F';
X		break;
X	    case 'F':
X	        farg = getflonum(arg);
X		break;
X	    }
X	}
X	else
X	    xlerror("bad argument type",arg);
X
X	/* compute result of the compare */
X	switch (mode) {
X	case 'I':
X	    icmp = ival - iarg;
X	    switch (fcn) {
X	    case '<':	icmp = (icmp < 0); break;
X	    case 'L':	icmp = (icmp <= 0); break;
X	    case '=':	icmp = (icmp == 0); break;
X	    case '#':	icmp = (icmp != 0); break;
X	    case 'G':	icmp = (icmp >= 0); break;
X	    case '>':	icmp = (icmp > 0); break;
X	    }
X	    break;
X	case 'F':
X	    fcmp = fval - farg;
X	    switch (fcn) {
X	    case '<':	icmp = (fcmp < 0.0); break;
X	    case 'L':	icmp = (fcmp <= 0.0); break;
X	    case '=':	icmp = (fcmp == 0.0); break;
X	    case '#':	icmp = (fcmp != 0.0); break;
X	    case 'G':	icmp = (fcmp >= 0.0); break;
X	    case '>':	icmp = (fcmp > 0.0); break;
X	    }
X	    break;
X	}
X    }
X
X    /* return the result */
X    return (icmp ? true : NIL);
X}
X
X/* badiop - bad integer operation */
XLOCAL badiop()
X{
X    xlfail("bad integer operation");
X}
X
X/* badfop - bad floating point operation */
XLOCAL badfop()
X{
X    xlfail("bad floating point operation");
X}
SHAR_EOF
if test 9993 -ne "`wc -c 'xlmath.c'`"
then
	echo shar: error transmitting "'xlmath.c'" '(should have been 9993 characters)'
fi
echo shar: extracting "'xlobj.c'" '(11545 characters)'
if test -f 'xlobj.c'
then
	echo shar: over-writing existing file "'xlobj.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'xlobj.c'
X/* xlobj - xlisp object functions */
X/*	Copyright (c) 1985, by David Michael Betz
X	All Rights Reserved
X	Permission is granted for unrestricted non-commercial use	*/
X
X#include "xlisp.h"
X
X/* external variables */
Xextern LVAL xlenv,xlfenv,xlvalue;
Xextern LVAL s_stdout,s_lambda;
X
X/* local variables */
Xstatic LVAL s_self,k_new,k_isnew;
Xstatic LVAL class,object;
X
X/* instance variable numbers for the class 'Class' */
X#define MESSAGES	0	/* list of messages */
X#define IVARS		1	/* list of instance variable names */
X#define CVARS		2	/* list of class variable names */
X#define CVALS		3	/* list of class variable values */
X#define SUPERCLASS	4	/* pointer to the superclass */
X#define IVARCNT		5	/* number of class instance variables */
X#define IVARTOTAL	6	/* total number of instance variables */
X
X/* number of instance variables for the class 'Class' */
X#define CLASSSIZE	7
X
X/* forward declarations */
XFORWARD LVAL entermsg();
XFORWARD LVAL sendmsg();
XFORWARD LVAL evmethod();
X
X/* xsend - send a message to an object */
XLVAL xsend()
X{
X    LVAL obj;
X    obj = xlgaobject();
X    return (sendmsg(obj,getclass(obj),xlgasymbol()));
X}
X
X/* xsendsuper - send a message to the superclass of an object */
XLVAL xsendsuper()
X{
X    LVAL env,p;
X    for (env = xlenv; env; env = cdr(env))
X	if ((p = car(env)) && objectp(car(p)))
X	    return (sendmsg(car(p),
X			    getivar(cdr(p),SUPERCLASS),
X			    xlgasymbol()));
X    xlfail("not in a method");
X}
X
X/* xlclass - define a class */
XLVAL xlclass(name,vcnt)
X  char *name; int vcnt;
X{
X    LVAL sym,cls;
X
X    /* create the class */
X    sym = xlenter(name);
X    cls = newobject(class,CLASSSIZE);
X    setvalue(sym,cls);
X
X    /* set the instance variable counts */
X    setivar(cls,IVARCNT,cvfixnum((FIXTYPE)vcnt));
X    setivar(cls,IVARTOTAL,cvfixnum((FIXTYPE)vcnt));
X
X    /* set the superclass to 'Object' */
X    setivar(cls,SUPERCLASS,object);
X
X    /* return the new class */
X    return (cls);
X}
X
X/* xladdivar - enter an instance variable */
Xxladdivar(cls,var)
X  LVAL cls; char *var;
X{
X    setivar(cls,IVARS,cons(xlenter(var),getivar(cls,IVARS)));
X}
X
X/* xladdmsg - add a message to a class */
Xxladdmsg(cls,msg,offset)
X  LVAL cls; char *msg; int offset;
X{
X    extern FUNDEF funtab[];
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,cvsubr(funtab[offset].fd_subr,funtab[offset].fd_type,offset));
X}
X
X/* xlobgetvalue - get the value of an instance variable */
Xint xlobgetvalue(pair,sym,pval)
X  LVAL pair,sym,*pval;
X{
X    LVAL cls,names;
X    int ivtotal,n;
X
X    /* find the instance or class variable */
X    for (cls = cdr(pair); objectp(cls); cls = getivar(cls,SUPERCLASS)) {
X
X	/* check the instance variables */
X	names = getivar(cls,IVARS);
X	ivtotal = getivcnt(cls,IVARTOTAL);
X	for (n = ivtotal - getivcnt(cls,IVARCNT); n < ivtotal; ++n) {
X	    if (car(names) == sym) {
X		*pval = getivar(car(pair),n);
X		return (TRUE);
X	    }
X	    names = cdr(names);
X	}
X
X	/* check the class variables */
X	names = getivar(cls,CVARS);
X	for (n = 0; consp(names); ++n) {
X	    if (car(names) == sym) {
X		*pval = getelement(getivar(cls,CVALS),n);
X		return (TRUE);
X	    }
X	    names = cdr(names);
X	}
X    }
X
X    /* variable not found */
X    return (FALSE);
X}
X
X/* xlobsetvalue - set the value of an instance variable */
Xint xlobsetvalue(pair,sym,val)
X  LVAL pair,sym,val;
X{
X    LVAL cls,names;
X    int ivtotal,n;
X
X    /* find the instance or class variable */
X    for (cls = cdr(pair); objectp(cls); cls = getivar(cls,SUPERCLASS)) {
X
X	/* check the instance variables */
X	names = getivar(cls,IVARS);
X	ivtotal = getivcnt(cls,IVARTOTAL);
X	for (n = ivtotal - getivcnt(cls,IVARCNT); n < ivtotal; ++n) {
X	    if (car(names) == sym) {
X		setivar(car(pair),n,val);
X		return (TRUE);
X	    }
X	    names = cdr(names);
X	}
X
X	/* check the class variables */
X	names = getivar(cls,CVARS);
X	for (n = 0; consp(names); ++n) {
X	    if (car(names) == sym) {
X		setelement(getivar(cls,CVALS),n,val);
X		return (TRUE);
X	    }
X	    names = cdr(names);
X	}
X    }
X
X    /* variable not found */
X    return (FALSE);
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 ivtotal,n;
X
X    /* get self and the file pointer */
X    self = xlgaobject();
X    fptr = (moreargs() ? xlgetfile() : 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    xlprint(fptr,self,TRUE);
X    xlputstr(fptr,", Class is ");
X    xlprint(fptr,cls,TRUE);
X    xlterpri(fptr);
X
X    /* print the object's instance variables */
X    for (; cls; cls = getivar(cls,SUPERCLASS)) {
X	names = getivar(cls,IVARS);
X	ivtotal = getivcnt(cls,IVARTOTAL);
X	for (n = ivtotal - getivcnt(cls,IVARCNT); n < ivtotal; ++n) {
X	    xlputstr(fptr,"  ");
X	    xlprint(fptr,car(names),TRUE);
X	    xlputstr(fptr," = ");
X	    xlprint(fptr,getivar(self,n),TRUE);
X	    xlterpri(fptr);
X	    names = cdr(names);
X	}
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    self = xlgaobject();
X    return (newobject(self,getivcnt(self,IVARTOTAL)));
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    /* store the instance and class variable lists and the superclass */
X    setivar(self,IVARS,ivars);
X    setivar(self,CVARS,cvars);
X    setivar(self,CVALS,(cvars ? newvector(listlength(cvars)) : NIL));
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    LVAL self,msg,fargs,code,mptr;
X
X    /* message symbol, formal argument list and code */
X    self = xlgaobject();
X    msg = xlgasymbol();
X    fargs = xlgalist();
X    code = xlgalist();
X    xllastarg();
X
X    /* make a new message list entry */
X    mptr = entermsg(self,msg);
X
X    /* setup the message node */
X    xlprot1(fargs);
X    fargs = cons(s_self,fargs); /* add 'self' as the first argument */
X    rplacd(mptr,xlclose(msg,s_lambda,fargs,code,NIL,NIL));
X    xlpop();
X
X    /* return the object */
X    return (self);
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    xlsave1(mptr);
X    mptr = consa(msg);
X    setivar(cls,MESSAGES,cons(mptr,getivar(cls,MESSAGES)));
X    xlpop();
X
X    /* return the symbol node */
X    return (mptr);
X}
X
X/* sendmsg - send a message to an object */
XLOCAL LVAL sendmsg(obj,cls,sym)
X  LVAL obj,cls,sym;
X{
X    LVAL msg,msgcls,method,val,p;
X
X    /* look for the message in the class or superclasses */
X    for (msgcls = cls; msgcls; ) {
X
X	/* lookup the message in this class */
X	for (p = getivar(msgcls,MESSAGES); p; p = cdr(p))
X	    if ((msg = car(p)) && car(msg) == sym)
X		goto send_message;
X
X	/* look in class's superclass */
X	msgcls = getivar(msgcls,SUPERCLASS);
X    }
X
X    /* message not found */
X    xlerror("no method for this message",sym);
X
Xsend_message:
X
X    /* insert the value for 'self' (overwrites message selector) */
X    *--xlargv = obj;
X    ++xlargc;
X    
X    /* invoke the method */
X    if ((method = cdr(msg)) == NULL)
X	xlerror("bad method",method);
X    switch (ntype(method)) {
X    case SUBR:
X	val = (*getsubr(method))();
X	break;
X    case CLOSURE:
X	if (gettype(method) != s_lambda)
X	    xlerror("bad method",method);
X	val = evmethod(obj,msgcls,method);
X	break;
X    default:
X	xlerror("bad method",method);
X    }
X
X    /* after creating an object, send it the ":isnew" message */
X    if (car(msg) == k_new && val) {
X	xlprot1(val);
X	sendmsg(val,getclass(val),k_isnew);
X	xlpop();
X    }
X    
X    /* return the result value */
X    return (val);
X}
X
X/* evmethod - evaluate a method */
XLOCAL LVAL evmethod(obj,msgcls,method)
X  LVAL obj,msgcls,method;
X{
X    LVAL oldenv,oldfenv,cptr,name,val;
X    CONTEXT cntxt;
X
X    /* protect some pointers */
X    xlstkcheck(3);
X    xlsave(oldenv);
X    xlsave(oldfenv);
X    xlsave(cptr);
X
X    /* create an 'object' stack entry and a new environment frame */
X    oldenv = xlenv;
X    oldfenv = xlfenv;
X    xlenv = cons(cons(obj,msgcls),getenv(method));
X    xlenv = xlframe(xlenv);
X    xlfenv = getfenv(method);
X
X    /* bind the formal parameters */
X    xlabind(method,xlargc,xlargv);
X
X    /* setup the implicit block */
X    if (name = getname(method))
X	xlbegin(&cntxt,CF_RETURN,name);
X
X    /* execute the block */
X    if (name && setjmp(cntxt.c_jmpbuf))
X	val = xlvalue;
X    else
X	for (cptr = getbody(method); consp(cptr); cptr = cdr(cptr))
X	    val = xleval(car(cptr));
X
X    /* finish the block context */
X    if (name)
X	xlend(&cntxt);
X
X    /* restore the environment */
X    xlenv = oldenv;
X    xlfenv = oldfenv;
X
X    /* restore the stack */
X    xlpopn(3);
X
X    /* return the result value */
X    return (val);
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	xlfail("bad value for instance variable count");
X    return ((int)getfixnum(cnt));
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_new   = xlenter(":NEW");
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    /* create the 'Class' object */
X    class = xlclass("CLASS",CLASSSIZE);
X    setelement(class,0,class);
X
X    /* create the 'Object' object */
X    object = xlclass("OBJECT",0);
X
X    /* finish initializing 'class' */
X    setivar(class,SUPERCLASS,object);
X    xladdivar(class,"IVARTOTAL");	/* ivar number 6 */
X    xladdivar(class,"IVARCNT");		/* ivar number 5 */
X    xladdivar(class,"SUPERCLASS");	/* ivar number 4 */
X    xladdivar(class,"CVALS");		/* ivar number 3 */
X    xladdivar(class,"CVARS");		/* ivar number 2 */
X    xladdivar(class,"IVARS");		/* ivar number 1 */
X    xladdivar(class,"MESSAGES");	/* ivar number 0 */
X    xladdmsg(class,":NEW",FT_CLNEW);
X    xladdmsg(class,":ISNEW",FT_CLISNEW);
X    xladdmsg(class,":ANSWER",FT_CLANSWER);
X
X    /* finish initializing 'object' */
X    setivar(object,SUPERCLASS,NIL);
X    xladdmsg(object,":ISNEW",FT_OBISNEW);
X    xladdmsg(object,":CLASS",FT_OBCLASS);
X    xladdmsg(object,":SHOW",FT_OBSHOW);
X}
X
SHAR_EOF
if test 11545 -ne "`wc -c 'xlobj.c'`"
then
	echo shar: error transmitting "'xlobj.c'" '(should have been 11545 characters)'
fi
echo shar: extracting "'xlpp.c'" '(2111 characters)'
if test -f 'xlpp.c'
then
	echo shar: over-writing existing file "'xlpp.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'xlpp.c'
X/* xlpp.c - xlisp pretty printer */
X/*	Copyright (c) 1985, by David Betz
X	All Rights Reserved			*/
X
X#include "xlisp.h"
X
X/* external variables */
Xextern LVAL s_stdout;
Xextern int xlfsize;
X
X/* local variables */
Xstatic int pplevel,ppmargin,ppmaxlen;
Xstatic LVAL ppfile;
X
X/* xpp - pretty-print an expression */
XLVAL xpp()
X{
X    LVAL expr;
X
X    /* get expression to print and file pointer */
X    expr = xlgetarg();
X    ppfile = (moreargs() ? xlgetfile() : getvalue(s_stdout));
X    xllastarg();
X
X    /* pretty print the expression */
X    pplevel = ppmargin = 0; ppmaxlen = 40;
X    pp(expr); ppterpri(ppfile);
X
X    /* return nil */
X    return (NIL);
X}
X
X/* pp - pretty print an expression */
XLOCAL pp(expr)
X  LVAL expr;
X{
X    if (consp(expr))
X	pplist(expr);
X    else
X	ppexpr(expr);
X}
X
X/* pplist - pretty print a list */
XLOCAL pplist(expr)
X  LVAL expr;
X{
X    int n;
X
X    /* if the expression will fit on one line, print it on one */
X    if ((n = flatsize(expr)) < ppmaxlen) {
X	xlprint(ppfile,expr,TRUE);
X	pplevel += n;
X    }
X
X    /* otherwise print it on several lines */
X    else {
X	n = ppmargin;
X	ppputc('(');
X	if (atom(car(expr))) {
X	    ppexpr(car(expr));
X	    ppputc(' ');
X	    ppmargin = pplevel;
X	    expr = cdr(expr);
X	}
X	else
X	    ppmargin = pplevel;
X	for (; consp(expr); expr = cdr(expr)) {
X	    pp(car(expr));
X	    if (consp(cdr(expr)))
X		ppterpri();
X	}
X	if (expr != NIL) {
X	    ppputc(' '); ppputc('.'); ppputc(' ');
X	    ppexpr(expr);
X	}
X	ppputc(')');
X	ppmargin = n;
X    }
X}
X
X/* ppexpr - print an expression and update the indent level */
XLOCAL ppexpr(expr)
X  LVAL expr;
X{
X    xlprint(ppfile,expr,TRUE);
X    pplevel += flatsize(expr);
X}
X
X/* ppputc - output a character and update the indent level */
XLOCAL ppputc(ch)
X  int ch;
X{
X    xlputc(ppfile,ch);
X    pplevel++;
X}
X
X/* ppterpri - terminate the print line and indent */
XLOCAL ppterpri()
X{
X    xlterpri(ppfile);
X    for (pplevel = 0; pplevel < ppmargin; pplevel++)
X	xlputc(ppfile,' ');
X}
X
X/* flatsize - compute the flat size of an expression */
XLOCAL int flatsize(expr)
X  LVAL expr;
X{
X    xlfsize = 0;
X    xlprint(NIL,expr,TRUE);
X    return (xlfsize);
X}
SHAR_EOF
if test 2111 -ne "`wc -c 'xlpp.c'`"
then
	echo shar: error transmitting "'xlpp.c'" '(should have been 2111 characters)'
fi
echo shar: extracting "'xlprin.c'" '(7244 characters)'
if test -f 'xlprin.c'
then
	echo shar: over-writing existing file "'xlprin.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'xlprin.c'
X/* xlprint - xlisp print routine */
X/*	Copyright (c) 1985, by David Michael Betz
X	All Rights Reserved
X	Permission is granted for unrestricted non-commercial use	*/
X
X#include "xlisp.h"
X
X/* external variables */
Xextern LVAL tentry();
Xextern LVAL s_printcase,k_downcase,k_const,k_nmacro;
Xextern LVAL s_ifmt,s_ffmt;
Xextern FUNDEF funtab[];
Xextern char buf[];
X
X/* xlprint - print an xlisp value */
Xxlprint(fptr,vptr,flag)
X  LVAL fptr,vptr; int flag;
X{
X    LVAL nptr,next;
X    int n,i;
X
X    /* print nil */
X    if (vptr == NIL) {
X	putsymbol(fptr,"NIL",flag);
X	return;
X    }
X
X    /* check value type */
X    switch (ntype(vptr)) {
X    case SUBR:
X	    putsubr(fptr,"Subr",vptr);
X	    break;
X    case FSUBR:
X	    putsubr(fptr,"FSubr",vptr);
X	    break;
X    case CONS:
X	    xlputc(fptr,'(');
X	    for (nptr = vptr; nptr != NIL; nptr = next) {
X	        xlprint(fptr,car(nptr),flag);
X		if (next = cdr(nptr))
X		    if (consp(next))
X			xlputc(fptr,' ');
X		    else {
X			xlputstr(fptr," . ");
X			xlprint(fptr,next,flag);
X			break;
X		    }
X	    }
X	    xlputc(fptr,')');
X	    break;
X    case SYMBOL:
X	    putsymbol(fptr,getstring(getpname(vptr)),flag);
X	    break;
X    case FIXNUM:
X	    putfixnum(fptr,getfixnum(vptr));
X	    break;
X    case FLONUM:
X	    putflonum(fptr,getflonum(vptr));
X	    break;
X    case CHAR:
X	    putchcode(fptr,getchcode(vptr),flag);
X	    break;
X    case STRING:
X	    if (flag)
X		putqstring(fptr,vptr);
X	    else
X		putstring(fptr,vptr);
X	    break;
X    case STREAM:
X	    putatm(fptr,"File-Stream",vptr);
X	    break;
X    case USTREAM:
X	    putatm(fptr,"Unnamed-Stream",vptr);
X	    break;
X    case OBJECT:
X	    putatm(fptr,"Object",vptr);
X	    break;
X    case VECTOR:
X	    xlputc(fptr,'#'); xlputc(fptr,'(');
X	    for (i = 0, n = getsize(vptr) - 1; i <= n; ++i) {
X		xlprint(fptr,getelement(vptr,i),flag);
X		if (i != n) xlputc(fptr,' ');
X	    }
X	    xlputc(fptr,')');
X	    break;
X    case STRUCT:
X	    xlprstruct(fptr,vptr,flag);
X	    break;
X    case CLOSURE:
X	    putclosure(fptr,vptr);
X	    break;
X    case FREE:
X	    putatm(fptr,"Free",vptr);
X	    break;
X    default:
X	    putatm(fptr,"Foo",vptr);
X	    break;
X    }
X}
X
X/* xlterpri - terminate the current print line */
Xxlterpri(fptr)
X  LVAL fptr;
X{
X    xlputc(fptr,'\n');
X}
X
X/* xlputstr - output a string */
Xxlputstr(fptr,str)
X  LVAL fptr; char *str;
X{
X    while (*str)
X	xlputc(fptr,*str++);
X}
X
X/* putsymbol - output a symbol */
XLOCAL putsymbol(fptr,str,escflag)
X  LVAL fptr; char *str; int escflag;
X{
X    int downcase,ch;
X    LVAL type;
X    char *p;
X
X    /* check for printing without escapes */
X    if (!escflag) {
X	xlputstr(fptr,str);
X	return;
X    }
X
X    /* check to see if symbol needs escape characters */
X    if (tentry(*str) == k_const) {
X	for (p = str; *p; ++p)
X	    if (islower(*p)
X	    ||  ((type = tentry(*p)) != k_const
X	      && (!consp(type) || car(type) != k_nmacro))) {
X		xlputc(fptr,'|');
X		while (*str) {
X		    if (*str == '\\' || *str == '|')
X			xlputc(fptr,'\\');
X		    xlputc(fptr,*str++);
X		}
X		xlputc(fptr,'|');
X		return;
X	    }
X    }
X
X    /* get the case translation flag */
X    downcase = (getvalue(s_printcase) == k_downcase);
X
X    /* check for the first character being '#' */
X    if (*str == '#' || *str == '.' || isnumber(str,NULL))
X	xlputc(fptr,'\\');
X
X    /* output each character */
X    while ((ch = *str++) != '\0') {
X	/* don't escape colon until we add support for packages */
X	if (ch == '\\' || ch == '|' /* || ch == ':' */)
X	    xlputc(fptr,'\\');
X	xlputc(fptr,(downcase && isupper(ch) ? tolower(ch) : ch));
X    }
X}
X
X/* putstring - output a string */
XLOCAL putstring(fptr,str)
X  LVAL fptr,str;
X{
X    unsigned char *p;
X    int ch;
X
X    /* output each character */
X    for (p = getstring(str); (ch = *p) != '\0'; ++p)
X	xlputc(fptr,ch);
X}
X
X/* putqstring - output a quoted string */
XLOCAL putqstring(fptr,str)
X  LVAL fptr,str;
X{
X    unsigned char *p;
X    int ch;
X
X    /* get the string pointer */
X    p = getstring(str);
X
X    /* output the initial quote */
X    xlputc(fptr,'"');
X
X    /* output each character in the string */
X    for (p = getstring(str); (ch = *p) != '\0'; ++p)
X
X	/* check for a control character */
X	if (ch < 040 || ch == '\\' || ch > 0176) {
X	    xlputc(fptr,'\\');
X	    switch (ch) {
X	    case '\011':
X		    xlputc(fptr,'t');
X		    break;
X	    case '\012':
X		    xlputc(fptr,'n');
X		    break;
X	    case '\014':
X		    xlputc(fptr,'f');
X		    break;
X	    case '\015':
X		    xlputc(fptr,'r');
X		    break;
X	    case '\\':
X		    xlputc(fptr,'\\');
X		    break;
X	    default:
X		    putoct(fptr,ch);
X		    break;
X	    }
X	}
X
X	/* output a normal character */
X	else
X	    xlputc(fptr,ch);
X
X    /* output the terminating quote */
X    xlputc(fptr,'"');
X}
X
X/* putatm - output an atom */
XLOCAL putatm(fptr,tag,val)
X  LVAL fptr; char *tag; LVAL val;
X{
X    sprintf(buf,"#<%s: #",tag); xlputstr(fptr,buf);
X    sprintf(buf,AFMT,val); xlputstr(fptr,buf);
X    xlputc(fptr,'>');
X}
X
X/* putsubr - output a subr/fsubr */
XLOCAL putsubr(fptr,tag,val)
X  LVAL fptr; char *tag; LVAL val;
X{
X    sprintf(buf,"#<%s-%s: #",tag,funtab[getoffset(val)].fd_name);
X    xlputstr(fptr,buf);
X    sprintf(buf,AFMT,val); xlputstr(fptr,buf);
X    xlputc(fptr,'>');
X}
X
X/* putclosure - output a closure */
XLOCAL putclosure(fptr,val)
X  LVAL fptr,val;
X{
X    LVAL name;
X    if (name = getname(val))
X	sprintf(buf,"#<Closure-%s: #",getstring(getpname(name)));
X    else
X	strcpy(buf,"#<Closure: #");
X    xlputstr(fptr,buf);
X    sprintf(buf,AFMT,val); xlputstr(fptr,buf);
X    xlputc(fptr,'>');
X/*
X    xlputstr(fptr,"\nName:   "); xlprint(fptr,getname(val),TRUE);
X    xlputstr(fptr,"\nType:   "); xlprint(fptr,gettype(val),TRUE);
X    xlputstr(fptr,"\nLambda: "); xlprint(fptr,getlambda(val),TRUE);
X    xlputstr(fptr,"\nArgs:   "); xlprint(fptr,getargs(val),TRUE);
X    xlputstr(fptr,"\nOargs:  "); xlprint(fptr,getoargs(val),TRUE);
X    xlputstr(fptr,"\nRest:   "); xlprint(fptr,getrest(val),TRUE);
X    xlputstr(fptr,"\nKargs:  "); xlprint(fptr,getkargs(val),TRUE);
X    xlputstr(fptr,"\nAargs:  "); xlprint(fptr,getaargs(val),TRUE);
X    xlputstr(fptr,"\nBody:   "); xlprint(fptr,getbody(val),TRUE);
X    xlputstr(fptr,"\nEnv:    "); xlprint(fptr,getenv(val),TRUE);
X    xlputstr(fptr,"\nFenv:   "); xlprint(fptr,getfenv(val),TRUE);
X*/
X}
X
X/* putfixnum - output a fixnum */
XLOCAL putfixnum(fptr,n)
X  LVAL fptr; FIXTYPE n;
X{
X    unsigned char *fmt;
X    LVAL val;
X    fmt = ((val = getvalue(s_ifmt)) && stringp(val) ? getstring(val)
X						    : (unsigned char *)IFMT);
X    sprintf(buf,fmt,n);
X    xlputstr(fptr,buf);
X}
X
X/* putflonum - output a flonum */
XLOCAL putflonum(fptr,n)
X  LVAL fptr; FLOTYPE n;
X{
X    unsigned char *fmt;
X    LVAL val;
X    fmt = ((val = getvalue(s_ffmt)) && stringp(val) ? getstring(val)
X						    : (unsigned char *)"%g");
X    sprintf(buf,fmt,n);
X    xlputstr(fptr,buf);
X}
X
X/* putchcode - output a character */
XLOCAL putchcode(fptr,ch,escflag)
X  LVAL fptr; int ch,escflag;
X{
X    if (escflag) {
X	switch (ch) {
X	case '\n':
X	    xlputstr(fptr,"#\\Newline");
X	    break;
X	case ' ':
X	    xlputstr(fptr,"#\\Space");
X	    break;
X	default:
X	    sprintf(buf,"#\\%c",ch);
X	    xlputstr(fptr,buf);
X	    break;
X	}
X    }
X    else
X	xlputc(fptr,ch);
X}
X
X/* putoct - output an octal byte value */
XLOCAL putoct(fptr,n)
X  LVAL fptr; int n;
X{
X    sprintf(buf,"%03o",n);
X    xlputstr(fptr,buf);
X}
SHAR_EOF
if test 7244 -ne "`wc -c 'xlprin.c'`"
then
	echo shar: error transmitting "'xlprin.c'" '(should have been 7244 characters)'
fi
#	End of shell archive
exit 0
-- 
Gary Murphy                   uunet!mitel!sce!cognos!garym
                              (garym%cognos.uucp@uunet.uu.net)
(613) 738-1338 x5537          Cognos Inc. P.O. Box 9707 Ottawa K1G 3N3
"There are many things which do not concern the process" - Joan of Arc