v10i095: XLisP 2.1 sources 4b (2/2) / 5
Gary Murphy
garym at cognos.UUCP
Tue Feb 27 14:12:56 AEST 1990
Posting-number: Volume 10, Issue 95
Submitted-by: garym at cognos.UUCP (Gary Murphy)
Archive-name: xlisp21/part08
#!/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:
# xlread.c
# xlstr.c
# xlstruct.c
# xlsubr.c
# xlsym.c
# xlsys.c
# This archive created: Sun Feb 18 23:40:39 1990
# By: Gary Murphy ()
export PATH; PATH=/bin:$PATH
echo shar: extracting "'xlread.c'" '(17573 characters)'
if test -f 'xlread.c'
then
echo shar: over-writing existing file "'xlread.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'xlread.c'
X/* xlread - xlisp expression input 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/* symbol parser modes */
X#define DONE 0
X#define NORMAL 1
X#define ESCAPE 2
X
X/* external variables */
Xextern LVAL s_stdout,true,s_dot;
Xextern LVAL s_quote,s_function,s_bquote,s_comma,s_comat;
Xextern LVAL s_rtable,k_wspace,k_const,k_nmacro,k_tmacro;
Xextern LVAL k_sescape,k_mescape;
Xextern char buf[];
X
X/* external routines */
Xextern FILE *osaopen();
Xextern double atof();
Xextern ITYPE;
X
X#define WSPACE "\t \f\r\n"
X#define CONST1 "!$%&*+-./0123456789:<=>?@[]^_{}~"
X#define CONST2 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
X
X/* forward declarations */
XFORWARD LVAL callmacro();
XFORWARD LVAL psymbol(),punintern();
XFORWARD LVAL pnumber(),pquote(),plist(),pvector(),pstruct();
XFORWARD LVAL readlist(),tentry();
X
X/* xlload - load a file of xlisp expressions */
Xint xlload(fname,vflag,pflag)
X char *fname; int vflag,pflag;
X{
X char fullname[STRMAX+1];
X LVAL fptr,expr;
X CONTEXT cntxt;
X FILE *fp;
X int sts;
X
X /* protect some pointers */
X xlstkcheck(2);
X xlsave(fptr);
X xlsave(expr);
X
X /* default the extension */
X if (needsextension(fname)) {
X strcpy(fullname,fname);
X strcat(fullname,".lsp");
X fname = fullname;
X }
X
X /* allocate a file node */
X fptr = cvfile(NULL);
X
X /* open the file */
X if ((fp = osaopen(fname,"r")) == NULL) {
X xlpopn(2);
X return (FALSE);
X }
X setfile(fptr,fp);
X
X /* print the information line */
X if (vflag)
X { sprintf(buf,"; loading \"%s\"\n",fname); stdputstr(buf); }
X
X /* read, evaluate and possibly print each expression in the file */
X xlbegin(&cntxt,CF_ERROR,true);
X if (setjmp(cntxt.c_jmpbuf))
X sts = FALSE;
X else {
X while (xlread(fptr,&expr,FALSE)) {
X expr = xleval(expr);
X if (pflag)
X stdprint(expr);
X }
X sts = TRUE;
X }
X xlend(&cntxt);
X
X /* close the file */
X osclose(getfile(fptr));
X setfile(fptr,NULL);
X
X /* restore the stack */
X xlpopn(2);
X
X /* return status */
X return (sts);
X}
X
X/* xlread - read an xlisp expression */
Xint xlread(fptr,pval,rflag)
X LVAL fptr,*pval; int rflag;
X{
X int sts;
X
X /* read an expression */
X while ((sts = readone(fptr,pval)) == FALSE)
X ;
X
X /* return status */
X return (sts == EOF ? FALSE : TRUE);
X}
X
X/* readone - attempt to read a single expression */
Xint readone(fptr,pval)
X LVAL fptr,*pval;
X{
X LVAL val,type;
X int ch;
X
X /* get a character and check for EOF */
X if ((ch = xlgetc(fptr)) == EOF)
X return (EOF);
X
X /* handle white space */
X if ((type = tentry(ch)) == k_wspace)
X return (FALSE);
X
X /* handle symbol constituents */
X else if (type == k_const) {
X xlungetc(fptr,ch);
X *pval = psymbol(fptr);
X return (TRUE);
X }
X
X /* handle single and multiple escapes */
X else if (type == k_sescape || type == k_mescape) {
X xlungetc(fptr,ch);
X *pval = psymbol(fptr);
X return (TRUE);
X }
X
X /* handle read macros */
X else if (consp(type)) {
X if ((val = callmacro(fptr,ch)) && consp(val)) {
X *pval = car(val);
X return (TRUE);
X }
X else
X return (FALSE);
X }
X
X /* handle illegal characters */
X else
X xlerror("illegal character",cvfixnum((FIXTYPE)ch));
X}
X
X/* rmhash - read macro for '#' */
XLVAL rmhash()
X{
X LVAL fptr,mch,val;
X int escflag,ch;
X
X /* protect some pointers */
X xlsave1(val);
X
X /* get the file and macro character */
X fptr = xlgetfile();
X mch = xlgachar();
X xllastarg();
X
X /* make the return value */
X val = consa(NIL);
X
X /* check the next character */
X switch (ch = xlgetc(fptr)) {
X case '\'':
X rplaca(val,pquote(fptr,s_function));
X break;
X case '(':
X xlungetc(fptr,ch);
X rplaca(val,pvector(fptr));
X break;
X case 'b':
X case 'B':
X rplaca(val,pnumber(fptr,2));
X break;
X case 'o':
X case 'O':
X rplaca(val,pnumber(fptr,8));
X break;
X case 'x':
X case 'X':
X rplaca(val,pnumber(fptr,16));
X break;
X case 's':
X case 'S':
X rplaca(val,pstruct(fptr));
X break;
X case '\\':
X xlungetc(fptr,ch);
X pname(fptr,&escflag);
X ch = buf[0];
X if (strlen(buf) > 1) {
X upcase(buf);
X if (strcmp(buf,"NEWLINE") == 0)
X ch = '\n';
X else if (strcmp(buf,"SPACE") == 0)
X ch = ' ';
X else
X xlerror("unknown character name",cvstring(buf));
X }
X rplaca(val,cvchar(ch));
X break;
X case ':':
X rplaca(val,punintern(fptr));
X break;
X case '|':
X pcomment(fptr);
X val = NIL;
X break;
X default:
X xlerror("illegal character after #",cvfixnum((FIXTYPE)ch));
X }
X
X /* restore the stack */
X xlpop();
X
X /* return the value */
X return (val);
X}
X
X/* rmquote - read macro for '\'' */
XLVAL rmquote()
X{
X LVAL fptr,mch;
X
X /* get the file and macro character */
X fptr = xlgetfile();
X mch = xlgachar();
X xllastarg();
X
X /* parse the quoted expression */
X return (consa(pquote(fptr,s_quote)));
X}
X
X/* rmdquote - read macro for '"' */
XLVAL rmdquote()
X{
X unsigned char buf[STRMAX+1],*p,*sptr;
X LVAL fptr,str,newstr,mch;
X int len,blen,ch,d2,d3;
X
X /* protect some pointers */
X xlsave1(str);
X
X /* get the file and macro character */
X fptr = xlgetfile();
X mch = xlgachar();
X xllastarg();
X
X /* loop looking for a closing quote */
X len = blen = 0; p = buf;
X while ((ch = checkeof(fptr)) != '"') {
X
X /* handle escaped characters */
X switch (ch) {
X case '\\':
X switch (ch = checkeof(fptr)) {
X case 't':
X ch = '\011';
X break;
X case 'n':
X ch = '\012';
X break;
X case 'f':
X ch = '\014';
X break;
X case 'r':
X ch = '\015';
X break;
X default:
X if (ch >= '0' && ch <= '7') {
X d2 = checkeof(fptr);
X d3 = checkeof(fptr);
X if (d2 < '0' || d2 > '7'
X || d3 < '0' || d3 > '7')
X xlfail("invalid octal digit");
X ch -= '0'; d2 -= '0'; d3 -= '0';
X ch = (ch << 6) | (d2 << 3) | d3;
X }
X break;
X }
X }
X
X /* check for buffer overflow */
X if (blen >= STRMAX) {
X newstr = newstring(len + STRMAX + 1);
X sptr = getstring(newstr); *sptr = '\0';
X if (str) strcat(sptr,getstring(str));
X *p = '\0'; strcat(sptr,buf);
X p = buf; blen = 0;
X len += STRMAX;
X str = newstr;
X }
X
X /* store the character */
X *p++ = ch; ++blen;
X }
X
X /* append the last substring */
X if (str == NIL || blen) {
X newstr = newstring(len + blen + 1);
X sptr = getstring(newstr); *sptr = '\0';
X if (str) strcat(sptr,getstring(str));
X *p = '\0'; strcat(sptr,buf);
X str = newstr;
X }
X
X /* restore the stack */
X xlpop();
X
X /* return the new string */
X return (consa(str));
X}
X
X/* rmbquote - read macro for '`' */
XLVAL rmbquote()
X{
X LVAL fptr,mch;
X
X /* get the file and macro character */
X fptr = xlgetfile();
X mch = xlgachar();
X xllastarg();
X
X /* parse the quoted expression */
X return (consa(pquote(fptr,s_bquote)));
X}
X
X/* rmcomma - read macro for ',' */
XLVAL rmcomma()
X{
X LVAL fptr,mch,sym;
X int ch;
X
X /* get the file and macro character */
X fptr = xlgetfile();
X mch = xlgachar();
X xllastarg();
X
X /* check the next character */
X if ((ch = xlgetc(fptr)) == '@')
X sym = s_comat;
X else {
X xlungetc(fptr,ch);
X sym = s_comma;
X }
X
X /* make the return value */
X return (consa(pquote(fptr,sym)));
X}
X
X/* rmlpar - read macro for '(' */
XLVAL rmlpar()
X{
X LVAL fptr,mch;
X
X /* get the file and macro character */
X fptr = xlgetfile();
X mch = xlgachar();
X xllastarg();
X
X /* make the return value */
X return (consa(plist(fptr)));
X}
X
X/* rmrpar - read macro for ')' */
XLVAL rmrpar()
X{
X xlfail("misplaced right paren");
X}
X
X/* rmsemi - read macro for ';' */
XLVAL rmsemi()
X{
X LVAL fptr,mch;
X int ch;
X
X /* get the file and macro character */
X fptr = xlgetfile();
X mch = xlgachar();
X xllastarg();
X
X /* skip to end of line */
X while ((ch = xlgetc(fptr)) != EOF && ch != '\n')
X ;
X
X /* return nil (nothing read) */
X return (NIL);
X}
X
X/* pcomment - parse a comment delimited by #| and |# */
XLOCAL pcomment(fptr)
X LVAL fptr;
X{
X int lastch,ch,n;
X
X /* look for the matching delimiter (and handle nesting) */
X for (n = 1, lastch = -1; n > 0 && (ch = xlgetc(fptr)) != EOF; ) {
X if (lastch == '|' && ch == '#')
X { --n; ch = -1; }
X else if (lastch == '#' && ch == '|')
X { ++n; ch = -1; }
X lastch = ch;
X }
X}
X
X/* pnumber - parse a number */
XLOCAL LVAL pnumber(fptr,radix)
X LVAL fptr; int radix;
X{
X int digit,ch;
X long num;
X
X for (num = 0L; (ch = xlgetc(fptr)) != EOF; ) {
X if (islower(ch)) ch = toupper(ch);
X if (!('0' <= ch && ch <= '9') && !('A' <= ch && ch <= 'F'))
X break;
X if ((digit = (ch <= '9' ? ch - '0' : ch - 'A' + 10)) >= radix)
X break;
X num = num * (long)radix + (long)digit;
X }
X xlungetc(fptr,ch);
X return (cvfixnum((FIXTYPE)num));
X}
X
X/* plist - parse a list */
XLOCAL LVAL plist(fptr)
X LVAL fptr;
X{
X LVAL val,expr,lastnptr,nptr;
X
X /* protect some pointers */
X xlstkcheck(2);
X xlsave(val);
X xlsave(expr);
X
X /* keep appending nodes until a closing paren is found */
X for (lastnptr = NIL; nextch(fptr) != ')'; )
X
X /* get the next expression */
X switch (readone(fptr,&expr)) {
X case EOF:
X badeof(fptr);
X case TRUE:
X
X /* check for a dotted tail */
X if (expr == s_dot) {
X
X /* make sure there's a node */
X if (lastnptr == NIL)
X xlfail("invalid dotted pair");
X
X /* parse the expression after the dot */
X if (!xlread(fptr,&expr,TRUE))
X badeof(fptr);
X rplacd(lastnptr,expr);
X
X /* make sure its followed by a close paren */
X if (nextch(fptr) != ')')
X xlfail("invalid dotted pair");
X }
X
X /* otherwise, handle a normal list element */
X else {
X nptr = consa(expr);
X if (lastnptr == NIL)
X val = nptr;
X else
X rplacd(lastnptr,nptr);
X lastnptr = nptr;
X }
X break;
X }
X
X /* skip the closing paren */
X xlgetc(fptr);
X
X /* restore the stack */
X xlpopn(2);
X
X /* return successfully */
X return (val);
X}
X
X/* pvector - parse a vector */
XLOCAL LVAL pvector(fptr)
X LVAL fptr;
X{
X LVAL list,val;
X int len,i;
X
X /* protect some pointers */
X xlsave1(list);
X
X /* read the list */
X list = readlist(fptr,&len);
X
X /* make a vector of the appropriate length */
X val = newvector(len);
X
X /* copy the list into the vector */
X for (i = 0; i < len; ++i, list = cdr(list))
X setelement(val,i,car(list));
X
X /* restore the stack */
X xlpop();
X
X /* return successfully */
X return (val);
X}
X
X/* pstruct - parse a structure */
XLOCAL LVAL pstruct(fptr)
X LVAL fptr;
X{
X extern LVAL xlrdstruct();
X LVAL list,val;
X int len;
X
X /* protect some pointers */
X xlsave1(list);
X
X /* read the list */
X list = readlist(fptr,&len);
X
X /* make the structure */
X val = xlrdstruct(list);
X
X /* restore the stack */
X xlpop();
X
X /* return successfully */
X return (val);
X}
X
X/* pquote - parse a quoted expression */
XLOCAL LVAL pquote(fptr,sym)
X LVAL fptr,sym;
X{
X LVAL val,p;
X
X /* protect some pointers */
X xlsave1(val);
X
X /* allocate two nodes */
X val = consa(sym);
X rplacd(val,consa(NIL));
X
X /* initialize the second to point to the quoted expression */
X if (!xlread(fptr,&p,TRUE))
X badeof(fptr);
X rplaca(cdr(val),p);
X
X /* restore the stack */
X xlpop();
X
X /* return the quoted expression */
X return (val);
X}
X
X/* psymbol - parse a symbol name */
XLOCAL LVAL psymbol(fptr)
X LVAL fptr;
X{
X int escflag;
X LVAL val;
X pname(fptr,&escflag);
X return (escflag || !isnumber(buf,&val) ? xlenter(buf) : val);
X}
X
X/* punintern - parse an uninterned symbol */
XLOCAL LVAL punintern(fptr)
X LVAL fptr;
X{
X int escflag;
X pname(fptr,&escflag);
X return (xlmakesym(buf));
X}
X
X/* pname - parse a symbol/package name */
XLOCAL int pname(fptr,pescflag)
X LVAL fptr; int *pescflag;
X{
X int mode,ch,i;
X LVAL type;
X
X /* initialize */
X *pescflag = FALSE;
X mode = NORMAL;
X i = 0;
X
X /* accumulate the symbol name */
X while (mode != DONE) {
X
X /* handle normal mode */
X while (mode == NORMAL)
X if ((ch = xlgetc(fptr)) == EOF)
X mode = DONE;
X else if ((type = tentry(ch)) == k_sescape) {
X i = storech(buf,i,checkeof(fptr));
X *pescflag = TRUE;
X }
X else if (type == k_mescape) {
X *pescflag = TRUE;
X mode = ESCAPE;
X }
X else if (type == k_const
X || (consp(type) && car(type) == k_nmacro))
X i = storech(buf,i,islower(ch) ? toupper(ch) : ch);
X else
X mode = DONE;
X
X /* handle multiple escape mode */
X while (mode == ESCAPE)
X if ((ch = xlgetc(fptr)) == EOF)
X badeof(fptr);
X else if ((type = tentry(ch)) == k_sescape)
X i = storech(buf,i,checkeof(fptr));
X else if (type == k_mescape)
X mode = NORMAL;
X else
X i = storech(buf,i,ch);
X }
X buf[i] = 0;
X
X /* check for a zero length name */
X if (i == 0)
X xlerror("zero length name");
X
X /* unget the last character and return it */
X xlungetc(fptr,ch);
X return (ch);
X}
X
X/* readlist - read a list terminated by a ')' */
XLOCAL LVAL readlist(fptr,plen)
X LVAL fptr; int *plen;
X{
X LVAL list,expr,lastnptr,nptr;
X int ch;
X
X /* protect some pointers */
X xlstkcheck(2);
X xlsave(list);
X xlsave(expr);
X
X /* get the open paren */
X if ((ch = nextch(fptr)) != '(')
X xlfail("expecting an open paren");
X xlgetc(fptr);
X
X /* keep appending nodes until a closing paren is found */
X for (lastnptr = NIL, *plen = 0; (ch = nextch(fptr)) != ')'; ) {
X
X /* check for end of file */
X if (ch == EOF)
X badeof(fptr);
X
X /* get the next expression */
X switch (readone(fptr,&expr)) {
X case EOF:
X badeof(fptr);
X case TRUE:
X nptr = consa(expr);
X if (lastnptr == NIL)
X list = nptr;
X else
X rplacd(lastnptr,nptr);
X lastnptr = nptr;
X ++(*plen);
X break;
X }
X }
X
X /* skip the closing paren */
X xlgetc(fptr);
X
X /* restore the stack */
X xlpopn(2);
X
X /* return the list */
X return (list);
X}
X
X/* storech - store a character in the print name buffer */
XLOCAL int storech(buf,i,ch)
X char *buf; int i,ch;
X{
X if (i < STRMAX)
X buf[i++] = ch;
X return (i);
X}
X
X/* tentry - get a readtable entry */
XLVAL tentry(ch)
X int ch;
X{
X LVAL rtable;
X rtable = getvalue(s_rtable);
X if (!vectorp(rtable) || ch < 0 || ch >= getsize(rtable))
X return (NIL);
X return (getelement(rtable,ch));
X}
X
X/* nextch - look at the next non-blank character */
XLOCAL int nextch(fptr)
X LVAL fptr;
X{
X int ch;
X
X /* return and save the next non-blank character */
X while ((ch = xlgetc(fptr)) != EOF && isspace(ch))
X ;
X xlungetc(fptr,ch);
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
X if ((ch = xlgetc(fptr)) == EOF)
X badeof(fptr);
X return (ch);
X}
X
X/* badeof - unexpected eof */
XLOCAL badeof(fptr)
X LVAL fptr;
X{
X xlgetc(fptr);
X xlfail("unexpected EOF");
X}
X
X/* isnumber - check if this string is a number */
Xint isnumber(str,pval)
X char *str; LVAL *pval;
X{
X int dl,dr;
X char *p;
X
X /* initialize */
X p = str; dl = 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++;
X while (isdigit(*p))
X p++, dr++;
X }
X
X /* check for an exponent */
X if ((dl || dr) && *p == 'E') {
X p++;
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 = (dr ? cvflonum(atof(str)) : cvfixnum(ICNV(str)));
X }
X return (TRUE);
X}
X
X/* defmacro - define a read macro */
Xdefmacro(ch,type,offset)
X int ch; LVAL type; int offset;
X{
X extern FUNDEF funtab[];
X LVAL subr;
X subr = cvsubr(funtab[offset].fd_subr,funtab[offset].fd_type,offset);
X setelement(getvalue(s_rtable),ch,cons(type,subr));
X}
X
X/* callmacro - call a read macro */
XLVAL callmacro(fptr,ch)
X LVAL fptr; int ch;
X{
X LVAL *newfp;
X
X /* create the new call frame */
X newfp = xlsp;
X pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
X pusharg(cdr(getelement(getvalue(s_rtable),ch)));
X pusharg(cvfixnum((FIXTYPE)2));
X pusharg(fptr);
X pusharg(cvchar(ch));
X xlfp = newfp;
X return (xlapply(2));
X}
X
X/* upcase - translate a string to upper case */
XLOCAL upcase(str)
X unsigned char *str;
X{
X for (; *str != '\0'; ++str)
X if (islower(*str))
X *str = toupper(*str);
X}
X
X/* xlrinit - initialize the reader */
Xxlrinit()
X{
X LVAL rtable;
X char *p;
X int ch;
X
X /* create the read table */
X rtable = newvector(256);
X setvalue(s_rtable,rtable);
X
X /* initialize the readtable */
X for (p = WSPACE; ch = *p++; )
X setelement(rtable,ch,k_wspace);
X for (p = CONST1; ch = *p++; )
X setelement(rtable,ch,k_const);
X for (p = CONST2; ch = *p++; )
X setelement(rtable,ch,k_const);
X
X /* setup the escape characters */
X setelement(rtable,'\\',k_sescape);
X setelement(rtable,'|', k_mescape);
X
X /* install the read macros */
X defmacro('#', k_nmacro,FT_RMHASH);
X defmacro('\'',k_tmacro,FT_RMQUOTE);
X defmacro('"', k_tmacro,FT_RMDQUOTE);
X defmacro('`', k_tmacro,FT_RMBQUOTE);
X defmacro(',', k_tmacro,FT_RMCOMMA);
X defmacro('(', k_tmacro,FT_RMLPAR);
X defmacro(')', k_tmacro,FT_RMRPAR);
X defmacro(';', k_tmacro,FT_RMSEMI);
X}
X
SHAR_EOF
if test 17573 -ne "`wc -c 'xlread.c'`"
then
echo shar: error transmitting "'xlread.c'" '(should have been 17573 characters)'
fi
echo shar: extracting "'xlstr.c'" '(13099 characters)'
if test -f 'xlstr.c'
then
echo shar: over-writing existing file "'xlstr.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'xlstr.c'
X/* xlstr - xlisp string and character built-in 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/* local definitions */
X#define fix(n) cvfixnum((FIXTYPE)(n))
X#define TLEFT 1
X#define TRIGHT 2
X
X/* external variables */
Xextern LVAL k_start,k_end,k_1start,k_1end,k_2start,k_2end;
Xextern LVAL true;
Xextern char buf[];
X
X/* external procedures */
Xextern char *strcat();
X
X/* forward declarations */
XFORWARD LVAL strcompare();
XFORWARD LVAL chrcompare();
XFORWARD LVAL changecase();
XFORWARD LVAL trim();
X
X/* string comparision functions */
XLVAL xstrlss() { return (strcompare('<',FALSE)); } /* string< */
XLVAL xstrleq() { return (strcompare('L',FALSE)); } /* string<= */
XLVAL xstreql() { return (strcompare('=',FALSE)); } /* string= */
XLVAL xstrneq() { return (strcompare('#',FALSE)); } /* string/= */
XLVAL xstrgeq() { return (strcompare('G',FALSE)); } /* string>= */
XLVAL xstrgtr() { return (strcompare('>',FALSE)); } /* string> */
X
X/* string comparison functions (not case sensitive) */
XLVAL xstrilss() { return (strcompare('<',TRUE)); } /* string-lessp */
XLVAL xstrileq() { return (strcompare('L',TRUE)); } /* string-not-greaterp */
XLVAL xstrieql() { return (strcompare('=',TRUE)); } /* string-equal */
XLVAL xstrineq() { return (strcompare('#',TRUE)); } /* string-not-equal */
XLVAL xstrigeq() { return (strcompare('G',TRUE)); } /* string-not-lessp */
XLVAL xstrigtr() { return (strcompare('>',TRUE)); } /* string-greaterp */
X
X/* strcompare - compare strings */
XLOCAL LVAL strcompare(fcn,icase)
X int fcn,icase;
X{
X int start1,end1,start2,end2,ch1,ch2;
X unsigned char *p1,*p2;
X LVAL str1,str2;
X
X /* get the strings */
X str1 = xlgastring();
X str2 = xlgastring();
X
X /* get the substring specifiers */
X getbounds(str1,k_1start,k_1end,&start1,&end1);
X getbounds(str2,k_2start,k_2end,&start2,&end2);
X
X /* setup the string pointers */
X p1 = &getstring(str1)[start1];
X p2 = &getstring(str2)[start2];
X
X /* compare the strings */
X for (; start1 < end1 && start2 < end2; ++start1,++start2) {
X ch1 = *p1++;
X ch2 = *p2++;
X if (icase) {
X if (isupper(ch1)) ch1 = tolower(ch1);
X if (isupper(ch2)) ch2 = tolower(ch2);
X }
X if (ch1 != ch2)
X switch (fcn) {
X case '<': return (ch1 < ch2 ? fix(start1) : NIL);
X case 'L': return (ch1 <= ch2 ? fix(start1) : NIL);
X case '=': return (NIL);
X case '#': return (fix(start1));
X case 'G': return (ch1 >= ch2 ? fix(start1) : NIL);
X case '>': return (ch1 > ch2 ? fix(start1) : NIL);
X }
X }
X
X /* check the termination condition */
X switch (fcn) {
X case '<': return (start1 >= end1 && start2 < end2 ? fix(start1) : NIL);
X case 'L': return (start1 >= end1 ? fix(start1) : NIL);
X case '=': return (start1 >= end1 && start2 >= end2 ? true : NIL);
X case '#': return (start1 >= end1 && start2 >= end2 ? NIL : fix(start1));
X case 'G': return (start2 >= end2 ? fix(start1) : NIL);
X case '>': return (start2 >= end2 && start1 < end1 ? fix(start1) : NIL);
X }
X}
X
X/* case conversion functions */
XLVAL xupcase() { return (changecase('U',FALSE)); }
XLVAL xdowncase() { return (changecase('D',FALSE)); }
X
X/* destructive case conversion functions */
XLVAL xnupcase() { return (changecase('U',TRUE)); }
XLVAL xndowncase() { return (changecase('D',TRUE)); }
X
X/* changecase - change case */
XLOCAL LVAL changecase(fcn,destructive)
X int fcn,destructive;
X{
X unsigned char *srcp,*dstp;
X int start,end,len,ch,i;
X LVAL src,dst;
X
X /* get the string */
X src = xlgastring();
X
X /* get the substring specifiers */
X getbounds(src,k_start,k_end,&start,&end);
X len = getslength(src) - 1;
X
X /* make a destination string */
X dst = (destructive ? src : newstring(len+1));
X
X /* setup the string pointers */
X srcp = getstring(src);
X dstp = getstring(dst);
X
X /* copy the source to the destination */
X for (i = 0; i < len; ++i) {
X ch = *srcp++;
X if (i >= start && i < end)
X switch (fcn) {
X case 'U': if (islower(ch)) ch = toupper(ch); break;
X case 'D': if (isupper(ch)) ch = tolower(ch); break;
X }
X *dstp++ = ch;
X }
X *dstp = '\0';
X
X /* return the new string */
X return (dst);
X}
X
X/* trim functions */
XLVAL xtrim() { return (trim(TLEFT|TRIGHT)); }
XLVAL xlefttrim() { return (trim(TLEFT)); }
XLVAL xrighttrim() { return (trim(TRIGHT)); }
X
X/* trim - trim character from a string */
XLOCAL LVAL trim(fcn)
X int fcn;
X{
X unsigned char *leftp,*rightp,*dstp;
X LVAL bag,src,dst;
X
X /* get the bag and the string */
X bag = xlgastring();
X src = xlgastring();
X xllastarg();
X
X /* setup the string pointers */
X leftp = getstring(src);
X rightp = leftp + getslength(src) - 2;
X
X /* trim leading characters */
X if (fcn & TLEFT)
X while (leftp <= rightp && inbag(*leftp,bag))
X ++leftp;
X
X /* trim character from the right */
X if (fcn & TRIGHT)
X while (rightp >= leftp && inbag(*rightp,bag))
X --rightp;
X
X /* make a destination string and setup the pointer */
X dst = newstring((int)(rightp-leftp+2));
X dstp = getstring(dst);
X
X /* copy the source to the destination */
X while (leftp <= rightp)
X *dstp++ = *leftp++;
X *dstp = '\0';
X
X /* return the new string */
X return (dst);
X}
X
X/* getbounds - get the start and end bounds of a string */
XLOCAL getbounds(str,skey,ekey,pstart,pend)
X LVAL str,skey,ekey; int *pstart,*pend;
X{
X LVAL arg;
X int len;
X
X /* get the length of the string */
X len = getslength(str) - 1;
X
X /* get the starting index */
X if (xlgkfixnum(skey,&arg)) {
X *pstart = (int)getfixnum(arg);
X if (*pstart < 0 || *pstart > len)
X xlerror("string index out of bounds",arg);
X }
X else
X *pstart = 0;
X
X /* get the ending index */
X if (xlgkfixnum(ekey,&arg)) {
X *pend = (int)getfixnum(arg);
X if (*pend < 0 || *pend > len)
X xlerror("string index out of bounds",arg);
X }
X else
X *pend = len;
X
X /* make sure the start is less than or equal to the end */
X if (*pstart > *pend)
X xlerror("starting index error",cvfixnum((FIXTYPE)*pstart));
X}
X
X/* inbag - test if a character is in a bag */
XLOCAL int inbag(ch,bag)
X int ch; LVAL bag;
X{
X unsigned char *p;
X for (p = getstring(bag); *p != '\0'; ++p)
X if (*p == ch)
X return (TRUE);
X return (FALSE);
X}
X
X/* xstrcat - concatenate a bunch of strings */
XLVAL xstrcat()
X{
X LVAL *saveargv,tmp,val;
X unsigned char *str;
X int saveargc,len;
X
X /* save the argument list */
X saveargv = xlargv;
X saveargc = xlargc;
X
X /* find the length of the new string */
X for (len = 0; moreargs(); ) {
X tmp = xlgastring();
X len += (int)getslength(tmp) - 1;
X }
X
X /* create the result string */
X val = newstring(len+1);
X str = getstring(val);
X
X /* restore the argument list */
X xlargv = saveargv;
X xlargc = saveargc;
X
X /* combine the strings */
X for (*str = '\0'; moreargs(); ) {
X tmp = nextarg();
X strcat(str,getstring(tmp));
X }
X
X /* return the new string */
X return (val);
X}
X
X/* xsubseq - return a subsequence */
XLVAL xsubseq()
X{
X unsigned char *srcp,*dstp;
X int start,end,len;
X LVAL src,dst;
X
X /* get string and starting and ending positions */
X src = xlgastring();
X
X /* get the starting position */
X dst = xlgafixnum(); start = (int)getfixnum(dst);
X if (start < 0 || start > getslength(src) - 1)
X xlerror("string index out of bounds",dst);
X
X /* get the ending position */
X if (moreargs()) {
X dst = xlgafixnum(); end = (int)getfixnum(dst);
X if (end < 0 || end > getslength(src) - 1)
X xlerror("string index out of bounds",dst);
X }
X else
X end = getslength(src) - 1;
X xllastarg();
X
X /* setup the source pointer */
X srcp = getstring(src) + start;
X len = end - start;
X
X /* make a destination string and setup the pointer */
X dst = newstring(len+1);
X dstp = getstring(dst);
X
X /* copy the source to the destination */
X while (--len >= 0)
X *dstp++ = *srcp++;
X *dstp = '\0';
X
X /* return the substring */
X return (dst);
X}
X
X/* xstring - return a string consisting of a single character */
XLVAL xstring()
X{
X LVAL arg;
X
X /* get the argument */
X arg = xlgetarg();
X xllastarg();
X
X /* make sure its not NIL */
X if (null(arg))
X xlbadtype(arg);
X
X /* check the argument type */
X switch (ntype(arg)) {
X case STRING:
X return (arg);
X case SYMBOL:
X return (getpname(arg));
X case CHAR:
X buf[0] = (int)getchcode(arg);
X buf[1] = '\0';
X return (cvstring(buf));
X default:
X xlbadtype(arg);
X }
X}
X
X/* xchar - extract a character from a string */
XLVAL xchar()
X{
X LVAL str,num;
X int n;
X
X /* get the string and the index */
X str = xlgastring();
X num = xlgafixnum();
X xllastarg();
X
X /* range check the index */
X if ((n = (int)getfixnum(num)) < 0 || n >= getslength(str) - 1)
X xlerror("index out of range",num);
X
X /* return the character */
X return (cvchar(getstring(str)[n]));
X}
X
X/* xcharint - convert an integer to a character */
XLVAL xcharint()
X{
X LVAL arg;
X arg = xlgachar();
X xllastarg();
X return (cvfixnum((FIXTYPE)getchcode(arg)));
X}
X
X/* xintchar - convert a character to an integer */
XLVAL xintchar()
X{
X LVAL arg;
X arg = xlgafixnum();
X xllastarg();
X return (cvchar((int)getfixnum(arg)));
X}
X
X/* xuppercasep - built-in function 'upper-case-p' */
XLVAL xuppercasep()
X{
X int ch;
X ch = getchcode(xlgachar());
X xllastarg();
X return (isupper(ch) ? true : NIL);
X}
X
X/* xlowercasep - built-in function 'lower-case-p' */
XLVAL xlowercasep()
X{
X int ch;
X ch = getchcode(xlgachar());
X xllastarg();
X return (islower(ch) ? true : NIL);
X}
X
X/* xbothcasep - built-in function 'both-case-p' */
XLVAL xbothcasep()
X{
X int ch;
X ch = getchcode(xlgachar());
X xllastarg();
X return (isupper(ch) || islower(ch) ? true : NIL);
X}
X
X/* xdigitp - built-in function 'digit-char-p' */
XLVAL xdigitp()
X{
X int ch;
X ch = getchcode(xlgachar());
X xllastarg();
X return (isdigit(ch) ? cvfixnum((FIXTYPE)(ch - '0')) : NIL);
X}
X
X/* xcharcode - built-in function 'char-code' */
XLVAL xcharcode()
X{
X int ch;
X ch = getchcode(xlgachar());
X xllastarg();
X return (cvfixnum((FIXTYPE)ch));
X}
X
X/* xcodechar - built-in function 'code-char' */
XLVAL xcodechar()
X{
X LVAL arg;
X int ch;
X arg = xlgafixnum(); ch = getfixnum(arg);
X xllastarg();
X return (ch >= 0 && ch <= 127 ? cvchar(ch) : NIL);
X}
X
X/* xchupcase - built-in function 'char-upcase' */
XLVAL xchupcase()
X{
X LVAL arg;
X int ch;
X arg = xlgachar(); ch = getchcode(arg);
X xllastarg();
X return (islower(ch) ? cvchar(toupper(ch)) : arg);
X}
X
X/* xchdowncase - built-in function 'char-downcase' */
XLVAL xchdowncase()
X{
X LVAL arg;
X int ch;
X arg = xlgachar(); ch = getchcode(arg);
X xllastarg();
X return (isupper(ch) ? cvchar(tolower(ch)) : arg);
X}
X
X/* xdigitchar - built-in function 'digit-char' */
XLVAL xdigitchar()
X{
X LVAL arg;
X int n;
X arg = xlgafixnum(); n = getfixnum(arg);
X xllastarg();
X return (n >= 0 && n <= 9 ? cvchar(n + '0') : NIL);
X}
X
X/* xalphanumericp - built-in function 'alphanumericp' */
XLVAL xalphanumericp()
X{
X int ch;
X ch = getchcode(xlgachar());
X xllastarg();
X return (isupper(ch) || islower(ch) || isdigit(ch) ? true : NIL);
X}
X
X/* character comparision functions */
XLVAL xchrlss() { return (chrcompare('<',FALSE)); } /* char< */
XLVAL xchrleq() { return (chrcompare('L',FALSE)); } /* char<= */
XLVAL xchreql() { return (chrcompare('=',FALSE)); } /* char= */
XLVAL xchrneq() { return (chrcompare('#',FALSE)); } /* char/= */
XLVAL xchrgeq() { return (chrcompare('G',FALSE)); } /* char>= */
XLVAL xchrgtr() { return (chrcompare('>',FALSE)); } /* char> */
X
X/* character comparision functions (case insensitive) */
XLVAL xchrilss() { return (chrcompare('<',TRUE)); } /* char-lessp */
XLVAL xchrileq() { return (chrcompare('L',TRUE)); } /* char-not-greaterp */
XLVAL xchrieql() { return (chrcompare('=',TRUE)); } /* char-equalp */
XLVAL xchrineq() { return (chrcompare('#',TRUE)); } /* char-not-equalp */
XLVAL xchrigeq() { return (chrcompare('G',TRUE)); } /* char-not-lessp */
XLVAL xchrigtr() { return (chrcompare('>',TRUE)); } /* char-greaterp */
X
X/* chrcompare - compare characters */
XLOCAL LVAL chrcompare(fcn,icase)
X int fcn,icase;
X{
X int ch1,ch2,icmp;
X LVAL arg;
X
X /* get the characters */
X arg = xlgachar(); ch1 = getchcode(arg);
X
X /* convert to lowercase if case insensitive */
X if (icase && isupper(ch1))
X ch1 = tolower(ch1);
X
X /* handle each remaining argument */
X for (icmp = TRUE; icmp && moreargs(); ch1 = ch2) {
X
X /* get the next argument */
X arg = xlgachar(); ch2 = getchcode(arg);
X
X /* convert to lowercase if case insensitive */
X if (icase && isupper(ch2))
X ch2 = tolower(ch2);
X
X /* compare the characters */
X switch (fcn) {
X case '<': icmp = (ch1 < ch2); break;
X case 'L': icmp = (ch1 <= ch2); break;
X case '=': icmp = (ch1 == ch2); break;
X case '#': icmp = (ch1 != ch2); break;
X case 'G': icmp = (ch1 >= ch2); break;
X case '>': icmp = (ch1 > ch2); break;
X }
X }
X
X /* return the result */
X return (icmp ? true : NIL);
X}
X
SHAR_EOF
if test 13099 -ne "`wc -c 'xlstr.c'`"
then
echo shar: error transmitting "'xlstr.c'" '(should have been 13099 characters)'
fi
echo shar: extracting "'xlstruct.c'" '(10906 characters)'
if test -f 'xlstruct.c'
then
echo shar: over-writing existing file "'xlstruct.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'xlstruct.c'
X/* xlstruct.c - the defstruct facility */
X/* Copyright (c) 1988, 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;
Xextern LVAL s_lambda,s_quote,lk_key,true;
Xextern char buf[];
X
X/* local variables */
Xstatic prefix[STRMAX+1];
X
X/* xmkstruct - the '%make-struct' function */
XLVAL xmkstruct()
X{
X LVAL type,val;
X int i;
X
X /* get the structure type */
X type = xlgasymbol();
X
X /* make the structure */
X val = newstruct(type,xlargc);
X
X /* store each argument */
X for (i = 1; moreargs(); ++i)
X setelement(val,i,nextarg());
X xllastarg();
X
X /* return the structure */
X return (val);
X}
X
X/* xcpystruct - the '%copy-struct' function */
XLVAL xcpystruct()
X{
X LVAL str,val;
X int size,i;
X str = xlgastruct();
X xllastarg();
X size = getsize(str);
X val = newstruct(getelement(str,0),size-1);
X for (i = 1; i < size; ++i)
X setelement(val,i,getelement(str,i));
X return (val);
X}
X
X/* xstrref - the '%struct-ref' function */
XLVAL xstrref()
X{
X LVAL str,val;
X int i;
X str = xlgastruct();
X val = xlgafixnum(); i = (int)getfixnum(val);
X xllastarg();
X return (getelement(str,i));
X}
X
X/* xstrset - the '%struct-set' function */
XLVAL xstrset()
X{
X LVAL str,val;
X int i;
X str = xlgastruct();
X val = xlgafixnum(); i = (int)getfixnum(val);
X val = xlgetarg();
X xllastarg();
X setelement(str,i,val);
X return (val);
X}
X
X/* xstrtypep - the '%struct-type-p' function */
XLVAL xstrtypep()
X{
X LVAL type,val;
X type = xlgasymbol();
X val = xlgetarg();
X xllastarg();
X return (structp(val) && getelement(val,0) == type ? true : NIL);
X}
X
X/* xdefstruct - the 'defstruct' special form */
XLVAL xdefstruct()
X{
X LVAL structname,slotname,defexpr,sym,tmp,args,body;
X LVAL options,oargs,slots;
X char *pname;
X int slotn;
X
X /* protect some pointers */
X xlstkcheck(6);
X xlsave(structname);
X xlsave(slotname);
X xlsave(defexpr);
X xlsave(args);
X xlsave(body);
X xlsave(tmp);
X
X /* initialize */
X args = body = NIL;
X slotn = 0;
X
X /* get the structure name */
X tmp = xlgetarg();
X if (symbolp(tmp)) {
X structname = tmp;
X strcpy(prefix,getstring(getpname(structname)));
X strcat(prefix,"-");
X }
X
X /* get the structure name and options */
X else if (consp(tmp) && symbolp(car(tmp))) {
X structname = car(tmp);
X strcpy(prefix,getstring(getpname(structname)));
X strcat(prefix,"-");
X
X /* handle the list of options */
X for (options = cdr(tmp); consp(options); options = cdr(options)) {
X
X /* get the next argument */
X tmp = car(options);
X
X /* handle options that don't take arguments */
X if (symbolp(tmp)) {
X pname = getstring(getpname(tmp));
X xlerror("unknown option",tmp);
X }
X
X /* handle options that take arguments */
X else if (consp(tmp) && symbolp(car(tmp))) {
X pname = getstring(getpname(car(tmp)));
X oargs = cdr(tmp);
X
X /* check for the :CONC-NAME keyword */
X if (strcmp(pname,":CONC-NAME") == 0) {
X
X /* get the name of the structure to include */
X if (!consp(oargs) || !symbolp(car(oargs)))
X xlerror("expecting a symbol",oargs);
X
X /* save the prefix */
X strcpy(prefix,getstring(getpname(car(oargs))));
X }
X
X /* check for the :INCLUDE keyword */
X else if (strcmp(pname,":INCLUDE") == 0) {
X
X /* get the name of the structure to include */
X if (!consp(oargs) || !symbolp(car(oargs)))
X xlerror("expecting a structure name",oargs);
X tmp = car(oargs);
X oargs = cdr(oargs);
X
X /* add each slot from the included structure */
X slots = xlgetprop(tmp,xlenter("*STRUCT-SLOTS*"));
X for (; consp(slots); slots = cdr(slots)) {
X if (consp(car(slots)) && consp(cdr(car(slots)))) {
X
X /* get the next slot description */
X tmp = car(slots);
X
X /* create the slot access functions */
X addslot(car(tmp),car(cdr(tmp)),++slotn,&args,&body);
X }
X }
X
X /* handle slot initialization overrides */
X for (; consp(oargs); oargs = cdr(oargs)) {
X tmp = car(oargs);
X if (symbolp(tmp)) {
X slotname = tmp;
X defexpr = NIL;
X }
X else if (consp(tmp) && symbolp(car(tmp))) {
X slotname = car(tmp);
X defexpr = (consp(cdr(tmp)) ? car(cdr(tmp)) : NIL);
X }
X else
X xlerror("bad slot description",tmp);
X updateslot(args,slotname,defexpr);
X }
X }
X else
X xlerror("unknown option",tmp);
X }
X else
X xlerror("bad option syntax",tmp);
X }
X }
X
X /* get each of the structure members */
X while (moreargs()) {
X
X /* get the slot name and default value expression */
X tmp = xlgetarg();
X if (symbolp(tmp)) {
X slotname = tmp;
X defexpr = NIL;
X }
X else if (consp(tmp) && symbolp(car(tmp))) {
X slotname = car(tmp);
X defexpr = (consp(cdr(tmp)) ? car(cdr(tmp)) : NIL);
X }
X else
X xlerror("bad slot description",tmp);
X
X /* create a closure for non-trival default expressions */
X if (defexpr != NIL) {
X tmp = newclosure(NIL,s_lambda,xlenv,xlfenv);
X setbody(tmp,cons(defexpr,NIL));
X tmp = cons(tmp,NIL);
X defexpr = tmp;
X }
X
X /* create the slot access functions */
X addslot(slotname,defexpr,++slotn,&args,&body);
X }
X
X /* store the slotnames and default expressions */
X xlputprop(structname,args,xlenter("*STRUCT-SLOTS*"));
X
X /* enter the MAKE-xxx symbol */
X sprintf(buf,"MAKE-%s",getstring(getpname(structname)));
X sym = xlenter(buf);
X
X /* make the MAKE-xxx function */
X args = cons(lk_key,args);
X tmp = cons(structname,NIL);
X tmp = cons(s_quote,tmp);
X body = cons(tmp,body);
X body = cons(xlenter("%MAKE-STRUCT"),body);
X body = cons(body,NIL);
X setfunction(sym,
X xlclose(sym,s_lambda,args,body,xlenv,xlfenv));
X
X /* enter the xxx-P symbol */
X sprintf(buf,"%s-P",getstring(getpname(structname)));
X sym = xlenter(buf);
X
X /* make the xxx-P function */
X args = cons(xlenter("X"),NIL);
X body = cons(xlenter("X"),NIL);
X tmp = cons(structname,NIL);
X tmp = cons(s_quote,tmp);
X body = cons(tmp,body);
X body = cons(xlenter("%STRUCT-TYPE-P"),body);
X body = cons(body,NIL);
X setfunction(sym,
X xlclose(sym,s_lambda,args,body,NIL,NIL));
X
X /* enter the COPY-xxx symbol */
X sprintf(buf,"COPY-%s",getstring(getpname(structname)));
X sym = xlenter(buf);
X
X /* make the COPY-xxx function */
X args = cons(xlenter("X"),NIL);
X body = cons(xlenter("X"),NIL);
X body = cons(xlenter("%COPY-STRUCT"),body);
X body = cons(body,NIL);
X setfunction(sym,
X xlclose(sym,s_lambda,args,body,NIL,NIL));
X
X /* restore the stack */
X xlpopn(6);
X
X /* return the structure name */
X return (structname);
X}
X
X/* xlrdstruct - convert a list to a structure (used by the reader) */
XLVAL xlrdstruct(list)
X LVAL list;
X{
X LVAL structname,sym,slotname,expr,last,val;
X
X /* protect the new structure */
X xlsave1(expr);
X
X /* get the structure name */
X if (!consp(list) || !symbolp(car(list)))
X xlerror("bad structure initialization list",list);
X structname = car(list);
X list = cdr(list);
X
X /* enter the MAKE-xxx symbol */
X sprintf(buf,"MAKE-%s",getstring(getpname(structname)));
X
X /* initialize the MAKE-xxx function call expression */
X expr = cons(xlenter(buf),NIL);
X last = expr;
X
X /* turn the rest of the initialization list into keyword arguments */
X while (consp(list) && consp(cdr(list))) {
X
X /* get the slot keyword name */
X slotname = car(list);
X if (!symbolp(slotname))
X xlerror("expecting a slot name",slotname);
X sprintf(buf,":%s",getstring(getpname(slotname)));
X
X /* add the slot keyword */
X rplacd(last,cons(xlenter(buf),NIL));
X last = cdr(last);
X list = cdr(list);
X
X /* add the value expression */
X rplacd(last,cons(car(list),NIL));
X last = cdr(last);
X list = cdr(list);
X }
X
X /* make sure all of the initializers were used */
X if (consp(list))
X xlerror("bad structure initialization list",list);
X
X /* invoke the creation function */
X val = xleval(expr);
X
X /* restore the stack */
X xlpop();
X
X /* return the new structure */
X return (val);
X}
X
X/* xlprstruct - print a structure (used by printer) */
Xxlprstruct(fptr,vptr,flag)
X LVAL fptr,vptr; int flag;
X{
X LVAL next;
X int i,n;
X xlputc(fptr,'#'); xlputc(fptr,'S'); xlputc(fptr,'(');
X xlprint(fptr,getelement(vptr,0),flag);
X next = xlgetprop(getelement(vptr,0),xlenter("*STRUCT-SLOTS*"));
X for (i = 1, n = getsize(vptr) - 1; i <= n && consp(next); ++i) {
X if (consp(car(next))) { /* should always succeed */
X xlputc(fptr,' ');
X xlprint(fptr,car(car(next)),flag);
X xlputc(fptr,' ');
X xlprint(fptr,getelement(vptr,i),flag);
X }
X next = cdr(next);
X }
X xlputc(fptr,')');
X}
X
X/* addslot - make the slot access functions */
XLOCAL addslot(slotname,defexpr,slotn,pargs,pbody)
X LVAL slotname,defexpr; int slotn; LVAL *pargs,*pbody;
X{
X LVAL sym,args,body,tmp;
X
X /* protect some pointers */
X xlstkcheck(4);
X xlsave(sym);
X xlsave(args);
X xlsave(body);
X xlsave(tmp);
X
X /* construct the update function name */
X sprintf(buf,"%s%s",prefix,getstring(getpname(slotname)));
X sym = xlenter(buf);
X
X /* make the access function */
X args = cons(xlenter("S"),NIL);
X body = cons(cvfixnum((FIXTYPE)slotn),NIL);
X body = cons(xlenter("S"),body);
X body = cons(xlenter("%STRUCT-REF"),body);
X body = cons(body,NIL);
X setfunction(sym,
X xlclose(sym,s_lambda,args,body,NIL,NIL));
X
X /* make the update function */
X args = cons(xlenter("V"),NIL);
X args = cons(xlenter("S"),args);
X body = cons(xlenter("V"),NIL);
X body = cons(cvfixnum((FIXTYPE)slotn),body);
X body = cons(xlenter("S"),body);
X body = cons(xlenter("%STRUCT-SET"),body);
X body = cons(body,NIL);
X xlputprop(sym,
X xlclose(NIL,s_lambda,args,body,NIL,NIL),
X xlenter("*SETF*"));
X
X /* add the slotname to the make-xxx keyword list */
X tmp = cons(defexpr,NIL);
X tmp = cons(slotname,tmp);
X tmp = cons(tmp,NIL);
X if ((args = *pargs) == NIL)
X *pargs = tmp;
X else {
X while (cdr(args) != NIL)
X args = cdr(args);
X rplacd(args,tmp);
X }
X
X /* add the slotname to the %make-xxx argument list */
X tmp = cons(slotname,NIL);
X if ((body = *pbody) == NIL)
X *pbody = tmp;
X else {
X while (cdr(body) != NIL)
X body = cdr(body);
X rplacd(body,tmp);
X }
X
X /* restore the stack */
X xlpopn(4);
X}
X
X/* updateslot - update a slot definition */
XLOCAL updateslot(args,slotname,defexpr)
X LVAL args,slotname,defexpr;
X{
X LVAL tmp;
X for (; consp(args); args = cdr(args))
X if (slotname == car(car(args))) {
X if (defexpr != NIL) {
X xlsave1(tmp);
X tmp = newclosure(NIL,s_lambda,xlenv,xlfenv);
X setbody(tmp,cons(defexpr,NIL));
X tmp = cons(tmp,NIL);
X defexpr = tmp;
X xlpop();
X }
X rplaca(cdr(car(args)),defexpr);
X break;
X }
X if (args == NIL)
X xlerror("unknown slot name",slotname);
X}
X
SHAR_EOF
if test 10906 -ne "`wc -c 'xlstruct.c'`"
then
echo shar: error transmitting "'xlstruct.c'" '(should have been 10906 characters)'
fi
echo shar: extracting "'xlsubr.c'" '(3858 characters)'
if test -f 'xlsubr.c'
then
echo shar: over-writing existing file "'xlsubr.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'xlsubr.c'
X/* xlsubr - xlisp builtin function support 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 LVAL k_test,k_tnot,s_eql;
X
X/* xlsubr - define a builtin function */
XLVAL xlsubr(sname,type,fcn,offset)
X char *sname; int type; LVAL (*fcn)(); int offset;
X{
X LVAL sym;
X sym = xlenter(sname);
X setfunction(sym,cvsubr(fcn,type,offset));
X return (sym);
X}
X
X/* xlgetkeyarg - get a keyword argument */
Xint xlgetkeyarg(key,pval)
X LVAL key,*pval;
X{
X LVAL *argv=xlargv;
X int argc=xlargc;
X for (argv = xlargv, argc = xlargc; (argc -= 2) >= 0; argv += 2) {
X if (*argv == key) {
X *pval = *++argv;
X return (TRUE);
X }
X }
X return (FALSE);
X}
X
X/* xlgkfixnum - get a fixnum keyword argument */
Xint xlgkfixnum(key,pval)
X LVAL key,*pval;
X{
X if (xlgetkeyarg(key,pval)) {
X if (!fixp(*pval))
X xlbadtype(*pval);
X return (TRUE);
X }
X return (FALSE);
X}
X
X/* xltest - get the :test or :test-not keyword argument */
Xxltest(pfcn,ptresult)
X LVAL *pfcn; int *ptresult;
X{
X if (xlgetkeyarg(k_test,pfcn)) /* :test */
X *ptresult = TRUE;
X else if (xlgetkeyarg(k_tnot,pfcn)) /* :test-not */
X *ptresult = FALSE;
X else {
X *pfcn = getfunction(s_eql);
X *ptresult = TRUE;
X }
X}
X
X/* xlgetfile - get a file or stream */
XLVAL xlgetfile()
X{
X LVAL arg;
X
X /* get a file or stream (cons) or nil */
X if (arg = xlgetarg()) {
X if (streamp(arg)) {
X if (getfile(arg) == NULL)
X xlfail("file not open");
X }
X else if (!ustreamp(arg))
X xlerror("bad argument type",arg);
X }
X return (arg);
X}
X
X/* xlgetfname - get a filename */
XLVAL xlgetfname()
X{
X LVAL name;
X
X /* get the next argument */
X name = xlgetarg();
X
X /* get the filename string */
X if (symbolp(name))
X name = getpname(name);
X else if (!stringp(name))
X xlerror("bad argument type",name);
X
X /* return the name */
X return (name);
X}
X
X/* needsextension - check if a filename needs an extension */
Xint needsextension(name)
X char *name;
X{
X char *p;
X
X /* check for an extension */
X for (p = &name[strlen(name)]; --p >= &name[0]; )
X if (*p == '.')
X return (FALSE);
X else if (!islower(*p) && !isupper(*p) && !isdigit(*p))
X return (TRUE);
X
X /* no extension found */
X return (TRUE);
X}
X
X/* xlbadtype - report a "bad argument type" error */
XLVAL xlbadtype(arg)
X LVAL arg;
X{
X xlerror("bad argument type",arg);
X}
X
X/* xltoofew - report a "too few arguments" error */
XLVAL xltoofew()
X{
X xlfail("too few arguments");
X}
X
X/* xltoomany - report a "too many arguments" error */
Xxltoomany()
X{
X xlfail("too many arguments");
X}
X
X/* eq - internal eq function */
Xint eq(arg1,arg2)
X LVAL arg1,arg2;
X{
X return (arg1 == arg2);
X}
X
X/* eql - internal eql function */
Xint eql(arg1,arg2)
X LVAL arg1,arg2;
X{
X /* compare the arguments */
X if (arg1 == arg2)
X return (TRUE);
X else if (arg1) {
X switch (ntype(arg1)) {
X case FIXNUM:
X return (fixp(arg2) ? getfixnum(arg1)==getfixnum(arg2) : FALSE);
X case FLONUM:
X return (floatp(arg2) ? getflonum(arg1)==getflonum(arg2) : FALSE);
X default:
X return (FALSE);
X }
X }
X else
X return (FALSE);
X}
X
X/* equal - internal equal function */
Xint equal(arg1,arg2)
X LVAL arg1,arg2;
X{
X /* compare the arguments */
X if (arg1 == arg2)
X return (TRUE);
X else if (arg1) {
X switch (ntype(arg1)) {
X case FIXNUM:
X return (fixp(arg2) ? getfixnum(arg1)==getfixnum(arg2) : FALSE);
X case FLONUM:
X return (floatp(arg2) ? getflonum(arg1)==getflonum(arg2) : FALSE);
X case STRING:
X return (stringp(arg2) ? strcmp(getstring(arg1),
X getstring(arg2)) == 0 : FALSE);
X case CONS:
X return (consp(arg2) ? equal(car(arg1),car(arg2))
X && equal(cdr(arg1),cdr(arg2)) : FALSE);
X default:
X return (FALSE);
X }
X }
X else
X return (FALSE);
X}
SHAR_EOF
if test 3858 -ne "`wc -c 'xlsubr.c'`"
then
echo shar: error transmitting "'xlsubr.c'" '(should have been 3858 characters)'
fi
echo shar: extracting "'xlsym.c'" '(5057 characters)'
if test -f 'xlsym.c'
then
echo shar: over-writing existing file "'xlsym.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'xlsym.c'
X/* xlsym - symbol handling 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 LVAL obarray,s_unbound;
Xextern LVAL xlenv,xlfenv,xldenv;
X
X/* forward declarations */
XFORWARD LVAL findprop();
X
X/* xlenter - enter a symbol into the obarray */
XLVAL xlenter(name)
X char *name;
X{
X LVAL sym,array;
X int i;
X
X /* check for nil */
X if (strcmp(name,"NIL") == 0)
X return (NIL);
X
X /* check for symbol already in table */
X array = getvalue(obarray);
X i = hash(name,HSIZE);
X for (sym = getelement(array,i); sym; sym = cdr(sym))
X if (strcmp(name,getstring(getpname(car(sym)))) == 0)
X return (car(sym));
X
X /* make a new symbol node and link it into the list */
X xlsave1(sym);
X sym = consd(getelement(array,i));
X rplaca(sym,xlmakesym(name));
X setelement(array,i,sym);
X xlpop();
X
X /* return the new symbol */
X return (car(sym));
X}
X
X/* xlmakesym - make a new symbol node */
XLVAL xlmakesym(name)
X char *name;
X{
X LVAL sym;
X sym = cvsymbol(name);
X if (*name == ':')
X setvalue(sym,sym);
X return (sym);
X}
X
X/* xlgetvalue - get the value of a symbol (with check) */
XLVAL xlgetvalue(sym)
X LVAL sym;
X{
X LVAL val;
X
X /* look for the value of the symbol */
X while ((val = xlxgetvalue(sym)) == s_unbound)
X xlunbound(sym);
X
X /* return the value */
X return (val);
X}
X
X/* xlxgetvalue - get the value of a symbol */
XLVAL xlxgetvalue(sym)
X LVAL sym;
X{
X register LVAL fp,ep;
X LVAL val;
X
X /* check the environment list */
X for (fp = xlenv; fp; fp = cdr(fp))
X
X /* check for an instance variable */
X if ((ep = car(fp)) && objectp(car(ep))) {
X if (xlobgetvalue(ep,sym,&val))
X return (val);
X }
X
X /* check an environment stack frame */
X else {
X for (; ep; ep = cdr(ep))
X if (sym == car(car(ep)))
X return (cdr(car(ep)));
X }
X
X /* return the global value */
X return (getvalue(sym));
X}
X
X/* xlsetvalue - set the value of a symbol */
Xxlsetvalue(sym,val)
X LVAL sym,val;
X{
X register LVAL fp,ep;
X
X /* look for the symbol in the environment list */
X for (fp = xlenv; fp; fp = cdr(fp))
X
X /* check for an instance variable */
X if ((ep = car(fp)) && objectp(car(ep))) {
X if (xlobsetvalue(ep,sym,val))
X return;
X }
X
X /* check an environment stack frame */
X else {
X for (; ep; ep = cdr(ep))
X if (sym == car(car(ep))) {
X rplacd(car(ep),val);
X return;
X }
X }
X
X /* store the global value */
X setvalue(sym,val);
X}
X
X/* xlgetfunction - get the functional value of a symbol (with check) */
XLVAL xlgetfunction(sym)
X LVAL sym;
X{
X LVAL val;
X
X /* look for the functional value of the symbol */
X while ((val = xlxgetfunction(sym)) == s_unbound)
X xlfunbound(sym);
X
X /* return the value */
X return (val);
X}
X
X/* xlxgetfunction - get the functional value of a symbol */
XLVAL xlxgetfunction(sym)
X LVAL sym;
X{
X register LVAL fp,ep;
X
X /* check the environment list */
X for (fp = xlfenv; fp; fp = cdr(fp))
X for (ep = car(fp); ep; ep = cdr(ep))
X if (sym == car(car(ep)))
X return (cdr(car(ep)));
X
X /* return the global value */
X return (getfunction(sym));
X}
X
X/* xlsetfunction - set the functional value of a symbol */
Xxlsetfunction(sym,val)
X LVAL sym,val;
X{
X register LVAL fp,ep;
X
X /* look for the symbol in the environment list */
X for (fp = xlfenv; fp; fp = cdr(fp))
X for (ep = car(fp); ep; ep = cdr(ep))
X if (sym == car(car(ep))) {
X rplacd(car(ep),val);
X return;
X }
X
X /* store the global value */
X setfunction(sym,val);
X}
X
X/* xlgetprop - get the value of a property */
XLVAL xlgetprop(sym,prp)
X LVAL sym,prp;
X{
X LVAL p;
X return ((p = findprop(sym,prp)) ? car(p) : NIL);
X}
X
X/* xlputprop - put a property value onto the property list */
Xxlputprop(sym,val,prp)
X LVAL sym,val,prp;
X{
X LVAL pair;
X if (pair = findprop(sym,prp))
X rplaca(pair,val);
X else
X setplist(sym,cons(prp,cons(val,getplist(sym))));
X}
X
X/* xlremprop - remove a property from a property list */
Xxlremprop(sym,prp)
X LVAL sym,prp;
X{
X LVAL last,p;
X last = NIL;
X for (p = getplist(sym); consp(p) && consp(cdr(p)); p = cdr(last)) {
X if (car(p) == prp)
X if (last)
X rplacd(last,cdr(cdr(p)));
X else
X setplist(sym,cdr(cdr(p)));
X last = cdr(p);
X }
X}
X
X/* findprop - find a property pair */
XLOCAL LVAL findprop(sym,prp)
X LVAL sym,prp;
X{
X LVAL p;
X for (p = getplist(sym); consp(p) && consp(cdr(p)); p = cdr(cdr(p)))
X if (car(p) == prp)
X return (cdr(p));
X return (NIL);
X}
X
X/* hash - hash a symbol name string */
Xint hash(str,len)
X char *str;
X{
X int i;
X for (i = 0; *str; )
X i = (i << 2) ^ *str++;
X i %= len;
X return (i < 0 ? -i : i);
X}
X
X/* xlsinit - symbol initialization routine */
Xxlsinit()
X{
X LVAL array,p;
X
X /* initialize the obarray */
X obarray = xlmakesym("*OBARRAY*");
X array = newvector(HSIZE);
X setvalue(obarray,array);
X
X /* add the symbol *OBARRAY* to the obarray */
X p = consa(obarray);
X setelement(array,hash("*OBARRAY*",HSIZE),p);
X}
SHAR_EOF
if test 5057 -ne "`wc -c 'xlsym.c'`"
then
echo shar: error transmitting "'xlsym.c'" '(should have been 5057 characters)'
fi
echo shar: extracting "'xlsys.c'" '(3335 characters)'
if test -f 'xlsys.c'
then
echo shar: over-writing existing file "'xlsys.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'xlsys.c'
X/* xlsys.c - xlisp builtin system 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 jmp_buf top_level;
Xextern FILE *tfp;
X
X/* external symbols */
Xextern LVAL a_subr,a_fsubr,a_cons,a_symbol;
Xextern LVAL a_fixnum,a_flonum,a_string,a_object,a_stream;
Xextern LVAL a_vector,a_closure,a_char,a_ustream;
Xextern LVAL k_verbose,k_print;
Xextern LVAL true;
X
X/* external routines */
Xextern FILE *osaopen();
X
X/* xload - read and evaluate expressions from a file */
XLVAL xload()
X{
X unsigned char *name;
X int vflag,pflag;
X LVAL arg;
X
X /* get the file name */
X name = getstring(xlgetfname());
X
X /* get the :verbose flag */
X if (xlgetkeyarg(k_verbose,&arg))
X vflag = (arg != NIL);
X else
X vflag = TRUE;
X
X /* get the :print flag */
X if (xlgetkeyarg(k_print,&arg))
X pflag = (arg != NIL);
X else
X pflag = FALSE;
X
X /* load the file */
X return (xlload(name,vflag,pflag) ? true : NIL);
X}
X
X/* xtranscript - open or close a transcript file */
XLVAL xtranscript()
X{
X unsigned char *name;
X
X /* get the transcript file name */
X name = (moreargs() ? getstring(xlgetfname()) : NULL);
X xllastarg();
X
X /* close the current transcript */
X if (tfp) osclose(tfp);
X
X /* open the new transcript */
X tfp = (name ? osaopen(name,"w") : NULL);
X
X /* return T if a transcript is open, NIL otherwise */
X return (tfp ? true : NIL);
X}
X
X/* xtype - return type of a thing */
XLVAL xtype()
X{
X LVAL arg;
X
X if (!(arg = xlgetarg()))
X return (NIL);
X
X switch (ntype(arg)) {
X case SUBR: return (a_subr);
X case FSUBR: return (a_fsubr);
X case CONS: return (a_cons);
X case SYMBOL: return (a_symbol);
X case FIXNUM: return (a_fixnum);
X case FLONUM: return (a_flonum);
X case STRING: return (a_string);
X case OBJECT: return (a_object);
X case STREAM: return (a_stream);
X case VECTOR: return (a_vector);
X case CLOSURE: return (a_closure);
X case CHAR: return (a_char);
X case USTREAM: return (a_ustream);
X case STRUCT: return (getelement(arg,0));
X default: xlfail("bad node type");
X }
X}
X
X/* xbaktrace - print the trace back stack */
XLVAL xbaktrace()
X{
X LVAL num;
X int n;
X
X if (moreargs()) {
X num = xlgafixnum();
X n = getfixnum(num);
X }
X else
X n = -1;
X xllastarg();
X xlbaktrace(n);
X return (NIL);
X}
X
X/* xexit - get out of xlisp */
XLVAL xexit()
X{
X xllastarg();
X wrapup();
X}
X
X/* xpeek - peek at a location in memory */
XLVAL xpeek()
X{
X LVAL num;
X int *adr;
X
X /* get the address */
X num = xlgafixnum(); adr = (int *)getfixnum(num);
X xllastarg();
X
X /* return the value at that address */
X return (cvfixnum((FIXTYPE)*adr));
X}
X
X/* xpoke - poke a value into memory */
XLVAL xpoke()
X{
X LVAL val;
X int *adr;
X
X /* get the address and the new value */
X val = xlgafixnum(); adr = (int *)getfixnum(val);
X val = xlgafixnum();
X xllastarg();
X
X /* store the new value */
X *adr = (int)getfixnum(val);
X
X /* return the new value */
X return (val);
X}
X
X/* xaddrs - get the address of an XLISP node */
XLVAL xaddrs()
X{
X LVAL val;
X
X /* get the node */
X val = xlgetarg();
X xllastarg();
X
X /* return the address of the node */
X return (cvfixnum((FIXTYPE)val));
X}
X
SHAR_EOF
if test 3335 -ne "`wc -c 'xlsys.c'`"
then
echo shar: error transmitting "'xlsys.c'" '(should have been 3335 characters)'
fi
# End of shell archive
exit 0
--
Gary Murphy uunet!mitel!sce!cognos!garym
(garym%cognos.uucp at 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
More information about the Comp.sources.misc
mailing list