home *** CD-ROM | disk | FTP | other *** search
- /* common - Additional Common Lisp functions not yet included in */
- /* Xlisp 2.1. */
- /* XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney */
- /* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz */
- /* You may give out copies of this software; for conditions see the */
- /* file COPYING included with this distribution. */
-
- #include <string.h>
- #include <stdio.h>
- #include "xlisp.h"
- #include "osdef.h"
- #ifdef ANSI
- #include "xlproto.h"
- #include "xlsproto.h"
- #include "osproto.h"
- #else
- #include "xlfun.h"
- #include "xlsfun.h"
- #include "osfun.h"
- #endif ANSI
- #include "xlvar.h"
- #include "xlsvar.h"
-
- /* forward declarations */
- #ifdef ANSI
- LVAL apropos(int),getstroutput(LVAL), getargument(LVAL,int),xscomplex(void),
- xsconjugate(void),xsrealpart(void),xsimagpart(void),equaltest(int),
- makeseq(LVAL,int),next_elt(LVAL *,int),every_some(int,int),set_op(int);
- void get_format_data(char **,char *,int *,int *),set_next_elt(LVAL *,int,LVAL),
- badseq(LVAL),badindex(LVAL),badcomplex(LVAL),
- pushnextargs(LVAL,int,LVAL,int);
- int strck(char *,char *,int),is_sub_str(char *,char *),findrlen(LVAL),
- is_member(LVAL,LVAL),sequence_length(LVAL),reslength(LVAL),
- apply_member(LVAL,LVAL,LVAL);
- #else
- LVAL apropos(),getstroutput(), getargument(),xscomplex(),
- xsconjugate(),xsrealpart(),xsimagpart(),equaltest(),
- makeseq(),next_elt(),every_some(),set_op();
- void get_format_data(),set_next_elt(),badseq(),badindex(),badcomplex(),
- pushnextargs();
- int strck(),is_sub_str(),findrlen(),
- is_member(),sequence_length(),reslength(),
- apply_member();
- #endif ANSI
-
- /****************************************************************************/
- /****************************************************************************/
- /** **/
- /** Common Lisp Functions **/
- /** **/
- /****************************************************************************/
- /****************************************************************************/
-
- /****************************************************************************/
- /** APROPOS and APROPOS-LIST **/
- /****************************************************************************/
-
- /* internal version of APROPOS */
- static LVAL apropos(print)
- int print;
- {
- LVAL str, array, list, element, result;
- unsigned char *s1, *s2;
- int i, n;
-
- str = xlgetarg();
- xllastarg();
-
- if (stringp(str)) s1 = getstring(str);
- else if (symbolp(str)) s1 = getstring(getpname(str));
- else xlbadtype(str);
-
- array = getvalue(obarray);
- n = getsize(array);
-
- /* protect some pointers */
- xlsave1(result);
-
- /* result = NIL; in macro JKL */
- for (i = 0; i < n; i++) {
- list = getelement(array, i);
- if (listp(list)) {
- for (; consp(list); list = cdr(list)) {
- element = car(list);
- if (symbolp(element) && element != s_unbound) {
- s2 = getstring(getpname(element));
- if (is_sub_str(s1, s2) == 0) {
- if (print) stdprint(element);
- else result = cons(element, result);
- }
- }
- }
- }
- }
- /* restore the stack and return the result */
- xlpop();
-
- return(result);
- }
-
- /* Common Lisp APROPOS function */
- LVAL xsapropos() { return(apropos(TRUE)); }
-
- /* Common Lisp APROPOS-LIST function */
- LVAL xsaproposlist() { return(apropos(FALSE)); }
-
- /* check if s1 is a substring of s2; case insensitive */
- static int is_sub_str(s1, s2)
- char *s1, *s2;
- {
- int n, m, i;
-
- m = strlen(s1);
- n = strlen(s2) - m;
-
- for (i = 0; i <= n; i++)
- if (strck(s1, &s2[i], m)) return (0);
- return(1);
- }
-
- /* check if s1 and s2 agree up to character m; case insensitive */
- static int strck(s1, s2, m)
- char *s1, *s2;
- int m;
- {
- char ch1, ch2;
-
- while (m-- > 0) {
- ch1 = isupper(*s1) ? tolower(*s1) : *s1;
- ch2 = isupper(*s2) ? tolower(*s2) : *s2;
- if (ch1 != ch2) return(0);
- s1++;
- s2++;
- }
- return(1);
- }
-
- /*************************************************************************/
- /** IDENTITY, MAKE-LIST, ADJOIN and FILE-POSITION functions **/
- /*************************************************************************/
-
- /* Common Lisp IDENTITY function */
- LVAL xsidentity()
- {
- LVAL x;
-
- x = xlgetarg();
- xllastarg();
- return(x);
- }
-
- /* Internal version of MAKE-LIST */
- LVAL mklist(n, elem)
- int n;
- LVAL elem;
- {
- LVAL result = NIL, next;
-
- xlsave1(result);
- while (n-- > 0)
- result = cons(NIL, result);
- if (elem != NIL)
- for (next = result; consp(next); next = cdr(next))
- rplaca(next, elem);
- xlpop();
- return(result);
- }
-
- /* Common Lisp MAKE-LIST function */
- LVAL xsmklist()
- {
- int n;
- LVAL elem = NIL;
-
- n = getfixnum(xlgafixnum());
- xlgetkeyarg(s_ielement, &elem);
-
- return(mklist(n, elem));
- }
-
- /* Common Lisp ADJOIN function */
- LVAL xsadjoin()
- {
- LVAL x, list;
- if (xlargc < 2) xltoofew();
- x = xlargv[0];
- list = xlargv[1];
- if (xmember()) return(list);
- else return(cons(x, list));
- }
-
- /* Common Lisp FILE-POSITION function */
- LVAL xsfileposition()
- {
- LVAL fptr;
- long pos;
-
- /* get file pointer */
- fptr = xlgetfile();
-
- /* make sure the file exists */
- if (getfile(fptr) == NULL) xlfail("file not open");
-
- if (moreargs()) {
- pos = getfixnum(xlgafixnum());
- xllastarg();
- fseek(getfile(fptr), pos, 0);
- return(s_true);
- }
- else {
- return(cvfixnum((FIXTYPE) ftell(getfile(fptr))));
- }
- }
-
- /****************************************************************************/
- /** Common Lisp FORMAT function **/
- /** (Includes integer and floating point formatting) **/
- /****************************************************************************/
-
- /* getstroutput - get the output stream string (internal) */
- static LVAL getstroutput(stream)
- LVAL stream;
- {
- unsigned char *str;
- LVAL next,val;
- int len,ch;
-
- /* compute the length of the stream */
- for (len = 0, next = gethead(stream); next != NIL; next = cdr(next))
- ++len;
- if (len - 1 > STRMAX) xlfail("string is too long");
-
- /* create a new string */
- val = newstring(len + 1);
-
- /* copy the characters into the new string */
- str = getstring(val);
- while ((ch = xlgetc(stream)) != EOF)
- *str++ = ch;
- *str = '\0';
-
- /* return the string */
- return (val);
- }
-
- /* parser for format directives (internal) */
- static void get_format_data(fmt, dir, nargs, fargs)
- char **fmt, *dir;
- int *nargs, *fargs;
- {
- (*fmt)++;
- *nargs = 0;
- while ((isdigit(**fmt) || **fmt == ',' || **fmt == 'v' || **fmt == 'V')
- && *nargs < 2) {
- #ifdef AMIGA
- *dir = **fmt; /* dummy line needed for bug in Lattice 5.05 JKL */
- #endif AMIGA
- if (isdigit(**fmt)) {
- (*nargs)++;
- sscanf(*fmt, "%d", fargs++);
- while (isdigit(**fmt))
- (*fmt)++;
- if (**fmt == ',') (*fmt)++;
- }
- else if ( **fmt == ',') {
- (*fmt)++;
- (*nargs)++;
- *fargs++ = -1;
- }
- else {
- (*fmt)++;
- (*nargs)++;
- *fargs++ = getfixnum(xlgafixnum());
- if (**fmt == ',') (*fmt)++;
- }
- }
- *dir = **fmt;
- }
-
- LVAL xsformat()
- {
- LVAL stream, val, arg;
- unsigned char *fmt, dir, contr[50];
- int nargs, fargs[2], i;
-
- xlsave1(stream);
-
- /* get the stream and format string */
- stream = xlgetarg();
- if (stream == NIL)
- val = stream = newustream();
- else {
- if (stream == s_true)
- stream = getvalue(s_stdout);
- else if (streamp(stream)) {
- if (getfile(stream) == NULL)
- xlfail("file not open");
- }
- else if (!ustreamp(stream))
- xlbadtype(stream);
- val = NIL;
- }
- fmt = getstring(xlgastring());
-
- for (; *fmt != '\0'; fmt++) {
- if (*fmt != '~') xlputc(stream, *fmt);
- else {
- get_format_data(&fmt, &dir, &nargs, fargs);
- switch (dir) {
- case 'A':
- case 'a':
- xlfsize = 0;
- xlprint(stream, xlgetarg(), FALSE);
- if (nargs > 0)
- for (; xlfsize < fargs[0]; /*xlfsize++*/) xlputc(stream, ' ');
- break;
- case 'S':
- case 's':
- xlfsize = 0;
- xlprint(stream, xlgetarg(), TRUE);
- if (nargs > 0)
- for (; xlfsize < fargs[0]; /*xlfsize++*/) xlputc(stream, ' ');
- break;
- case 'D':
- case 'd':
- arg = xlgetarg();
- if (fixp(arg)) {
- if (nargs == 0) {
- sprintf(buf, "%ld", (long) getfixnum(arg));
- xlputstr(stream, buf);
- }
- else {
- sprintf(contr, "%%%dld", fargs[0]);
- sprintf(buf, contr, (long) getfixnum(arg));
- xlputstr(stream, buf);
- }
- }
- else
- xlprint(stream, arg, FALSE);
- break;
- case 'E':
- case 'e':
- case 'F':
- case 'f':
- case 'G':
- case 'g':
- dir = (isupper(dir)) ? tolower(dir) : dir;
- arg = xlgetarg();
- if (floatp(arg)) {
- switch (nargs) {
- case 0:
- sprintf(contr, "%%l%c", dir);
- break;
- case 1:
- sprintf(contr, "%%%dl%c", fargs[0], dir);
- break;
- case 2:
- if (fargs[0] > 0)
- sprintf(contr, "%%%d.%dl%c", fargs[0], fargs[1], dir);
- else
- sprintf(contr, "%%.%dl%c", fargs[1], dir);
- break;
- default:
- xlfail("too many arguments for format directive");
- }
- sprintf(buf, contr, (double) getflonum(arg));
- xlputstr(stream, buf);
- }
- else
- xlprint(stream, arg, FALSE);
- break;
- case '~':
- if (nargs == 0) xlputc(stream, '~');
- else if (nargs == 1) {
- /* if (fargs[0] < 0) fargs[0] = 0; line does nothing JKL */
- for (i = 0; i < fargs[0]; i++)
- xlputc(stream, '~');
- }
- break;
- case '%':
- if (nargs == 0) xlterpri(stream);
- else if (nargs == 1) {
- /* if (fargs[0] < 0) fargs[0] = 0; line does nothing JKL */
- for (i = 0; i < fargs[0]; i++)
- xlterpri(stream);
- }
- break;
- case '\n':
- while (isspace(*fmt)) fmt++;
- fmt--; /* set back because fmt will be advanced in the outer loop */
- break;
- default:
- xlfail("unknown format directive");
- }
- }
- }
- if (val != NIL) val = getstroutput(val);
- xlpop();
-
- /* return the value */
- return (val);
- }
-
- LVAL xsforce_output()
- {
- #ifdef MACINTOSH
- TtyFlush();
- #else
- fflush(stdout);
- #endif MACINTOSH
- return(NIL);
- }
-
- /****************************************************************************/
- /** Sequence Copying Functions **/
- /****************************************************************************/
-
- /* Common Lisp COPY-LIST function */
- LVAL xscopylist()
- {
- LVAL list;
-
- list = xlgalist();
- xllastarg();
-
- return(copylist(list));
- }
-
- /* Common Lisp COPY-SEQ function */
- LVAL xscopyseq()
- {
- if (! moreargs()) xltoofew();
- return((vectorp(xlargv[0])) ? xscopyvector() : xscopylist());
- }
-
- /***********************************************************************/
- /** REDUCE and MAP functions **/
- /***********************************************************************/
-
- /* Common Lisp REDUCE function (internal version) */
- LVAL reduce(fcn, sequence, has_init, initial_value)
- LVAL fcn, sequence, initial_value;
- int has_init;
- {
- LVAL next, result;
- int i, n;
-
- /* protect some pointers */
- xlstkcheck(3);
- xlsave(next);
- xlsave(result);
- xlprotect(fcn);
-
- if (consp(sequence)) {
- next = sequence;
- if (has_init) result = initial_value;
- else {
- result = car(next);
- next = cdr(next);
- }
- for (; consp(next); next = cdr(next))
- result = xsfuncall2(fcn, result, car(next));
- }
- else if (vectorp(sequence)) {
- n = getsize(sequence);
- i = 0;
- if (has_init) result = initial_value;
- else {
- result = getelement(sequence, 0);
- i = 1;
- }
- for (; i < n; i++)
- result = xsfuncall2(fcn, result, getelement(sequence, i));
- }
- else badseq(sequence);
-
- /* restore the stack frame */
- xlpopn(3);
-
- return(result);
- }
-
- /* Common Lisp REDUCE function */
- LVAL xsreduce()
- {
- LVAL fcn, sequence, initial_value;
- int has_init;
-
- fcn = xlgetarg();
- sequence = xlgetarg();
- has_init = xlgetkeyarg(s_ivalue, &initial_value);
-
- return(reduce(fcn, sequence, has_init, initial_value));
- }
-
- /* #define seqlen(x) ((vectorp(x)) ? getsize(x) : llength(x)) in xlsdef.h JKL */
- #define makeresult(type, n) ((type == s_vector) ? newvector(n) : mklist(n, NIL))
-
- /* compute the length of the result sequence */
- LOCAL int findrlen(args)
- LVAL args;
- {
- LVAL next;
- int len, rlen;
-
- for (rlen = -1, next = args; consp(next); next = cdr(next)) {
- if (! sequencep(car(next))) badseq(car(next));
- len = seqlen(car(next));
- if (rlen == -1) rlen = len;
- else rlen = (len < rlen) ? len : rlen;
- }
- return(rlen);
- }
-
- LOCAL void pushnextargs(fcn, n, args, i)
- LVAL fcn, args;
- int n, i;
- {
- LVAL *newfp, next, value;
-
- /* build a new argument stack frame */
- newfp = xlsp;
- pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
- pusharg(fcn);
- pusharg(cvfixnum((FIXTYPE)n));
-
- /* push the arguments and shift the list pointers */
- for (next = args; consp(next); next = cdr(next)) {
- if (vectorp(car(next))) value = getelement(car(next), i);
- else {
- value = car(car(next));
- rplaca(next, cdr(car(next)));
- }
- pusharg(value);
- }
-
- /* establish the new stack frame */
- xlfp = newfp;
- }
-
- /* Internal version of Common Lisp MAP function */
- LVAL map(type, fcn, args, rlen)
- LVAL type, fcn, args;
- int rlen;
- {
- LVAL nextr, result;
- int nargs, i;
-
- /* protect some pointers */
- xlstkcheck(2);
- xlsave(result);
- xlprotect(fcn);
-
- if (rlen < 0) rlen = findrlen(args);
- result = makeresult(type, rlen);
- nargs = llength(args);
-
- for (i = 0, nextr = result; i < rlen; i++) {
- pushnextargs(fcn, nargs, args, i);
- setnextelement(&nextr, i, xlapply(nargs));
- }
-
- /* restore the stack frame */
- xlpopn(2);
-
- return(result);
- }
-
- /* Common Lisp MAP function */
- LVAL xsmap()
- {
- LVAL fcn, type, args, result;
-
- /* protect some pointers */
- xlstkcheck(2);
- xlsave(fcn);
- xlsave(args);
-
- type = xlgasymbol();
- fcn = xlgetarg();
- if (type != s_list && type != s_vector)
- xlerror("Not a valid sequence type", type);
- args = makearglist(xlargc, xlargv);
-
- result = map(type, fcn, args, -1);
-
- /* restore the stack frame */
- xlpopn(2);
- return(result);
- }
-
- /***********************************************************************/
- /** ELT and COERCE **/
- /***********************************************************************/
-
- /* Common Lisp ELT function */
- LVAL xselt()
- {
- LVAL x, index;
- int i;
-
- x = xlgetarg();
- index = xlgafixnum();
- xllastarg();
-
- i = getfixnum(index);
- if (simplevectorp(x)) {
- if (i < 0 || i >= getsize(x)) badindex(index);
- else return(getelement(x, i));
- }
- else if (listp(x)) {
- if (i < 0) badindex(index);
- else
- for (; consp(x) && i > 0; x = cdr(x), i--)
- ;
- if (! consp(x)) badindex(index);
- else return(car(x));
- }
- else if (stringp(x)) {
- if (i < 0 || i >= strlen(getstring(x))) badindex(index);
- else return(cvchar(getstring(x)[i]));
- }
- else badseq(x);
- }
-
- /* Setf method for Common Lisp ELT function */
- void set_elt(x, index, val)
- LVAL x, index, val;
- {
- int i;
-
- i = getfixnum(index);
- if (simplevectorp(x)) {
- if (i < 0 || i >= getsize(x)) badindex(index);
- else setelement(x, i, val);
- }
- else if (listp(x)) {
- if (i < 0) badindex(index);
- else
- for (; consp(x) && i > 0; x = cdr(x), i--)
- ;
- if (! consp(x)) badindex(index);
- else rplaca(x, val);
- }
- else if (stringp(x)) {
- if (! charp(val)) xlerror("not a character", val);
- if (i < 0 || i >= strlen(getstring(x))) badindex(index);
- getstring(x)[i] = getchcode(val);
- }
- else badseq(x);
- }
-
- /* Common Lisp COERCE function */
- LVAL xscoerce()
- {
- LVAL x, result, type;
- static char str[]="can't coerce this object to this type"; /* added JKL */
-
- x = xlgetarg();
- type = xlgasymbol();
- xllastarg();
-
- /* protect the result pointer */
- xlsave1(result);
-
- if (stringp(x) || type == a_string) {
- if (stringp(x) && type == a_string) result = x;
- else result = xscallsubr2(xsconcatenate, type, x);
- }
- else if (type == a_flonum || type == a_float) {
- if (fixp(x)) result = cvflonum((FLOTYPE) getfixnum(x));
- else if (floatp(x)) result = x;
- else xlfail(str/*"can't coerce this object to this type"*/);
- }
- else if (type == a_complex) {
- if (fixp(x)) result = newicomplex(getfixnum(x), (FIXTYPE) 0);
- else if (floatp(x)) result = newdcomplex(getflonum(x), (FLOTYPE) 0.0);
- else if (complexp(x)) result = x;
- else xlfail(str/*"can't coerce this object to this type"*/);
- }
- else if (type == a_cons || type == s_list)
- result = coerce_to_list(x);
- else if (type == s_vector)
- result = coerce_to_vector(x);
- else if (type == s_true)
- result = x;
- else
- xlfail(str/*"can't coerce this object to this type"*/);
-
- /* restore the stack frame */
- xlpop();
-
- return(result);
- }
-
- /***********************************************************************/
- /** **/
- /** Modified APPLY and EVAL functions **/
- /** **/
- /***********************************************************************/
-
- /* Common Lisp APPLY function. Modified to cons arguments onto last one */
- LVAL xsapply()
- {
- LVAL *newfp, last;
- int argc;
-
- /* build a new argument stack frame */
- newfp = xlsp;
- pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
- pusharg(xlgetarg());
- pusharg(NIL); /* will be argc */
-
- /* push all but the last argument */
- last = xlgetarg();
- for (argc = 0; moreargs(); argc++) {
- pusharg(last);
- last = nextarg();
- }
-
- /* push all elements of the last argument */
- if (! listp(last)) xlerror("not a list", last);
- for (; consp(last); last = cdr(last), argc++)
- pusharg(car(last));
-
- /* establish the new stack frame */
- newfp[2] = cvfixnum((FIXTYPE)argc);
- xlfp = newfp;
-
- /* apply the function to the arguments */
- return (xlapply(argc));
- }
-
- /* Common Lisp EVAL function. Modified to use null lexical environment */
- LVAL xseval()
- {
- LVAL expr, result, oldenv, oldfenv;
-
- /* set the lexical environment to null */
- xlstkcheck(3);
- xlsave(oldenv); /* oldenv and oldfenv set redundantly to NIL in macros JKL */
- xlsave(oldfenv);
- xlsave(expr);
- oldenv = xlenv; xlenv = NIL;
- oldfenv = xlfenv; xlfenv = NIL;
-
- /* get the expression to evaluate */
- expr = xlgetarg();
- xllastarg();
-
- /* evaluate the expression */
- result = xleval(expr);
-
- /* reset the environment */
- xlenv = oldenv;
- xlfenv = oldfenv;
- xlpopn(3);
-
- return(result);
- }
-
- /* Common Lisp LOAD function. Modified to use null lexical environment */
-
- LVAL xsload()
- {
- LVAL result, oldenv, oldfenv;
-
- /* set the lexical environment to null */
- xlstkcheck(2);
- xlsave(oldenv); /* oldenv and oldfenv set redundantly to NIL in macros JKL */
- xlsave(oldfenv);
- oldenv = xlenv; xlenv = NIL;
- oldfenv = xlfenv; xlfenv = NIL;
-
- /* evaluate the expression */
- result = xload();
-
- /* reset the environment */
- xlenv = oldenv;
- xlfenv = oldfenv;
- xlpopn(2);
-
- return(result);
- }
-
- /***********************************************************************/
- /** **/
- /** Complex Number Functions **/
- /** **/
- /***********************************************************************/
-
- LVAL xsgetreal()
- {
- LVAL arg = xlgetarg();
- if (! numberp(arg)) xlerror("not a real number", arg);
- return(arg);
- }
-
- LVAL newicomplex(real, imag)
- FIXTYPE real, imag;
- {
- LVAL val;
-
- if (imag == 0) val = cvfixnum(real);
- else {
- xlsave1(val);
- val = newvector(2);
- val->n_type = COMPLEX;
- setelement(val, 0, cvfixnum(real));
- setelement(val, 1, cvfixnum(imag));
- xlpop();
- }
- return(val);
- }
-
- LVAL newdcomplex(real, imag)
- double real, imag;
- {
- LVAL val;
-
- xlsave1(val);
- val = newvector(2);
- val->n_type = COMPLEX;
- setelement(val, 0, cvflonum((FLOTYPE) real));
- setelement(val, 1, cvflonum((FLOTYPE) imag));
- xlpop();
- return(val);
- }
-
- /* newcomplex - allocate and initialize a new object */
- LVAL newcomplex(real,imag)
- LVAL real,imag;
- {
- if (fixp(real) && fixp(imag))
- return(newicomplex(getfixnum(real), getfixnum(imag)));
- else
- return(newdcomplex(makedouble(real), makedouble(imag)));
- }
-
- LVAL xscomplexp()
- {
- LVAL arg = xlgetarg();
- xllastarg();
-
- return((complexp(arg)) ? s_true : NIL);
- }
-
- LVAL realpart(x)
- LVAL x;
- {
- if (! complexp(x)) badcomplex(x);
- return(getelement(x, 0));
- }
-
- LVAL imagpart(x)
- LVAL x;
- {
- if (! complexp(x)) badcomplex(x);
- return(getelement(x, 1));
- }
-
- static LVAL xscomplex()
- {
- LVAL real, imag;
-
- real = xsgetreal();
- if (! moreargs()) return(real);
- else {
- imag = xsgetreal();
- return(newcomplex(real, imag));
- }
- }
-
- static LVAL xsconjugate()
- {
- LVAL arg = xlgetarg();
-
- xllastarg();
- if (numberp(arg)) return(arg);
- if (fixp(realpart(arg)) && fixp(imagpart(arg)))
- return(newicomplex(getfixnum(realpart(arg)), -getfixnum(imagpart(arg))));
- else
- return(newdcomplex(makedouble(realpart(arg)), -makedouble(imagpart(arg))));
- }
-
- static LVAL xsrealpart()
- {
- LVAL arg = xlgetarg();
-
- xllastarg();
- if (fixp(arg) || floatp(arg)) return(arg);
- else return(realpart(arg));
- }
-
- static LVAL xsimagpart()
- {
- LVAL arg = xlgetarg();
-
- xllastarg();
- if (fixp(arg)) return(cvfixnum((FIXTYPE) 0));
- else if (floatp(arg)) return(cvflonum((FLOTYPE) 0.0));
- else return(imagpart(arg));
- }
-
- LVAL xsrcomplex() { return (recursive_subr_map_elements(xscomplex, xsrcomplex)); }
- LVAL xsrconjugate() { return (recursive_subr_map_elements(xsconjugate, xsrconjugate)); }
- LVAL xsrrealpart() { return (recursive_subr_map_elements(xsrealpart, xsrrealpart)); }
- LVAL xsrimagpart() { return (recursive_subr_map_elements(xsimagpart, xsrimagpart)); }
-
- static LVAL equaltest(use_eql)
- int use_eql;
- {
- LVAL arg1, arg2, r1, r2, i1, i2;
-
- if (! complexp(peekarg(0))) return((use_eql) ? xeql() : xequal());
- else {
- arg1 = xlgetarg();
- arg2 = xlgetarg();
- xllastarg();
-
- if (! complexp(arg2)) return(NIL);
-
- r1 = realpart(arg1);
- i1 = imagpart(arg1);
- r2 = realpart(arg2);
- i2 = imagpart(arg2);
-
- if (fixp(r1) && fixp(i1) && fixp(r2) && fixp(i2)
- && getfixnum(r1) == getfixnum(r2)
- && getfixnum(i1) == getfixnum(i2))
- return(s_true);
- else if (floatp(r1) && floatp(i1) && floatp(r2) && floatp(i2)
- && getflonum(r1) == getflonum(r2)
- && getflonum(i1) == getflonum(i2))
- return(s_true);
- else return(NIL);
- }
- }
-
- LVAL xseql() { return(equaltest(TRUE)); }
- LVAL xsequal() { return(equaltest(FALSE)); }
-
- /***********************************************************************/
- /** **/
- /** Global Variable Declaration Function **/
- /** **/
- /***********************************************************************/
-
- void defconstant(sym, val)
- LVAL sym, val;
- {
- setvalue(sym, val);
- setconstant(sym, TRUE);
- }
-
- LVAL defsym(which)
- int which;
- {
- LVAL sym, val, doc;
-
- sym = xlgasymbol();
- if (which == 'C' && isconstant(sym)) xlfail("can't assign to a constant");
- switch (which) {
- case 'C':
- case 'P': val = xlgetarg(); break;
- case 'V': val = (moreargs()) ? xlgetarg() : NIL; break;
- }
- doc = (moreargs()) ? xlgastring() : NIL;
- xllastarg();
-
- switch (which) {
- case 'C': defconstant(sym, xleval(val)); break;
- case 'P': setvalue(sym, xleval(val)); break;
- case 'V': if (getvalue(sym) == s_unbound) setvalue(sym, xleval(val)); break;
- }
- if (doc != NIL)
- set_variable_docstring(sym, doc);
- return(sym);
- }
-
- LVAL xsdefconstant() { return(defsym('C')); }
- LVAL xsdefparameter() { return(defsym('P')); }
- LVAL xsdefvar() { return(defsym('V')); }
-
- LVAL xsmakunbound()
- {
- LVAL sym;
-
- sym = xlgasymbol();
- xllastarg();
-
- setvalue(sym, s_unbound);
- setconstant(sym, FALSE);
- return(sym);
- }
-
- LVAL xsfmakunbound()
- {
- LVAL sym;
-
- sym = xlgasymbol();
- xllastarg();
-
- setfunction(sym,s_unbound);
- return(sym);
- }
-
- int keep_doc_strings()
- {
- return(getvalue(xlenter("*KEEP-DOCUMENTATION-STRINGS*")) != NIL);
- }
-
- void set_function_docstring(sym, str)
- LVAL sym, str;
- {
- if (keep_doc_strings())
- xlputprop(sym, str, s_function_documentation);
- }
-
- void set_variable_docstring(sym, str)
- LVAL sym, str;
- {
- if (keep_doc_strings())
- xlputprop(sym, str, s_variable_documentation);
- }
-
- /***********************************************************************/
- /** **/
- /** Features Maintenance Functions **/
- /** **/
- /***********************************************************************/
-
- static int is_member(x, list)
- LVAL x, list;
- {
- int result = FALSE;
-
- for (; ! result && consp(list); list = cdr(list))
- if (equal(x, car(list))) result = TRUE;
- return(result);
- }
-
- int checkfeatures(arg, which)
- LVAL arg;
- int which;
- {
- int has_feature;
- LVAL features = getvalue(s_features);
-
- if (consp(arg)) {
- if (car(arg) == s_and)
- for (has_feature = TRUE, arg = cdr(arg);
- consp(arg) && has_feature;
- arg = cdr(arg)) {
- has_feature = has_feature && checkfeatures(car(arg), which);
- }
- else if (car(arg) == s_or)
- for (has_feature = FALSE, arg = cdr(arg);
- consp(arg) && ! has_feature;
- arg = cdr(arg)) {
- has_feature = has_feature || checkfeatures(car(arg), which);
- }
- else if (car(arg) == s_not && consp(cdr(arg)))
- has_feature = ! checkfeatures(car(cdr(arg)), which);
- else xlerror("bad feature", arg);
- }
- else has_feature = is_member(arg, features);
-
- if (which == '-') has_feature = ! has_feature;
- return(has_feature);
- }
-
- /***********************************************************************/
- /** **/
- /** Time and Environment Functions **/
- /** **/
- /***********************************************************************/
-
- LVAL xstime()
- {
- LVAL result;
- unsigned long tm;
- double dtm;
-
- tm = run_tick_count();
- result = xeval();
- #ifndef AMIGA
- tm = run_tick_count() - tm;
- dtm = (tm > 0) ? tm : -tm;
- #else
- dtm = run_tick_count() - tm; /* changed due to bug in Lattice C v5.05 JKL */
- dtm = (dtm > 0) ? dtm : -dtm;
- #endif AMIGA
-
- sprintf(buf, "The evaluation took %.2f seconds\n", dtm / ticks_per_second());
- stdputstr(buf);
- return(result);
- }
-
- LVAL xs_get_internal_run_time() { return(cvfixnum((FIXTYPE) run_tick_count())); }
-
- LVAL xs_get_internal_real_time() { return(cvfixnum((FIXTYPE) real_tick_count())); }
-
- LVAL xsgetenv()
- {
- xllastarg();
- return(list3(xlenv, xlfenv, xldenv));
- }
-
- /***********************************************************************/
- /** **/
- /** Concatenate Function **/
- /** **/
- /***********************************************************************/
-
- static int sequence_length(x)
- LVAL x;
- {
- if (simplevectorp(x)) return(getsize(x));
- else if (listp(x)) return(llength(x));
- else if (stringp(x)) return(strlen(getstring(x)));
- else badseq(x);
- }
-
- static int reslength(x)
- LVAL x;
- {
- int n;
-
- for (n = 0; consp(x); x = cdr(x)) n += sequence_length(car(x));
- return(n);
- }
-
- static LVAL makeseq(type, n)
- LVAL type;
- int n;
- {
- LVAL result;
- int i;
-
- if (type == s_list) result = mklist(n, NIL);
- else if (type == s_vector) result = newvector(n);
- else if (type == a_string) {
- result = newstring(n + 1);
- for (i = 0; i < n; i++) getstring(result)[i] = ' ';
- getstring(result)[n] = '\0';
- }
- else xlerror("bad sequence type", type);
- return(result);
- }
-
- static LVAL next_elt(x, i)
- LVAL *x;
- int i;
- {
- LVAL result;
-
- if (consp(*x)) {
- result = car(*x);
- *x = cdr(*x);
- }
- else if (simplevectorp(*x)) result = getelement(*x, i);
- else if (stringp(*x)) result = cvchar(getstring(*x)[i]);
- else badseq(*x);
-
- return(result);
- }
-
- static void set_next_elt(x, i, val)
- LVAL *x, val;
- int i;
- {
- if (consp(*x)) {
- rplaca(*x, val);
- *x = cdr(*x);
- }
- else if (simplevectorp(*x)) setelement(*x, i, val);
- else if (stringp(*x)) {
- if (! charp(val)) xlerror("not a character", val);
- getstring(*x)[i] = getchcode(val);
- }
- else badseq(*x);
- }
-
- LVAL concatenate(type, sequences)
- LVAL type, sequences;
- {
- LVAL result, next, seq, x;
- int i, j, n, m;
-
- xlstkcheck(3);
- xlprotect(sequences);
- xlsave(result);
- xlsave(x);
-
- n = reslength(sequences);
- result = makeseq(type, n);
- next = result;
-
- for (i = 0; consp(sequences); sequences = cdr(sequences)) {
- seq = car(sequences);
- m = sequence_length(seq);
- for (j = 0; j < m; i++, j++) {
- x = next_elt(&seq, j);
- set_next_elt(&next, i, x);
- }
- }
-
- xlpopn(3);
- return(result);
- }
-
- LVAL xsconcatenate()
- {
- LVAL type, sequences, result;
-
- xlsave1(sequences);
- type = xlgasymbol();
- sequences = makearglist(xlargc, xlargv);
- result = concatenate(type, sequences);
- xlpop();
- return(result);
- }
-
- /***********************************************************************/
- /** **/
- /** SOME and EVERY Functions **/
- /** **/
- /***********************************************************************/
-
- static LVAL every_some(which, negate)
- int which, negate;
- {
- LVAL fcn, args, result;
- int nargs, i, rlen;
-
- /* protect some pointers */
- xlstkcheck(2);
- xlsave(args);
- xlsave(fcn);
-
- fcn = xlgetarg();
- args = makearglist(xlargc, xlargv);
- rlen = findrlen(args);
- nargs = llength(args);
-
- result = NIL;
- for (i = 0; i < rlen; i++) {
- pushnextargs(fcn, nargs, args, i);
- result = xlapply(nargs);
- if (which == 'A') {
- if (result != NIL) break;
- }
- else if (result == NIL) break;
- }
- if (negate) result = (result == NIL) ? s_true : NIL;
-
- /* restore the stack frame */
- xlpopn(3);
-
- return(result);
- }
-
- LVAL xssome() { return(every_some('A', FALSE)); }
- LVAL xsevery() { return(every_some('E', FALSE)); }
- LVAL xsnotany() { return(every_some('A', TRUE)); }
- LVAL xsnotevery() { return(every_some('E', TRUE)); }
-
- /***********************************************************************/
- /** **/
- /** Set Functions **/
- /** **/
- /***********************************************************************/
-
- /* apply MEMBER function, allowing for extra arguments. args should */
- /* contain two postitons for x and list arguments, and should be */
- /* protected from garbage collection before the call. */
- static int apply_member(x, list, args)
- LVAL x, list, args;
- {
- /* LVAL result; slightly rewritten below JKL */
-
- if (consp(args) && consp(cdr(args))) {
- rplaca(args, x);
- rplaca(cdr(args), list);
- }
- /* result = xsapplysubr(xmember, args); */
- return(/*result*/ xsapplysubr(xmember, args) != NIL ? TRUE : FALSE);
- }
-
- static LVAL set_op(which)
- int which;
- {
- LVAL x, list1, list2, rest, result;
-
- xlstkcheck(2);
- xlsave(rest);
- xlsave(result);
-
- list1 = xlgalist();
- list2 = xlgalist();
- rest = makearglist(xlargc, xlargv);
- rest = cons(NIL, rest);
- rest = cons(NIL, rest);
-
- switch(which) {
- case 'U':
- for (result = list1; consp(list2); list2 = cdr(list2)) {
- x = car(list2);
- if (! apply_member(x, list1, rest)) result = cons(x, result);
- }
- break;
- case 'I':
- for (result = NIL; consp(list2); list2 = cdr(list2)) {
- x = car(list2);
- if (apply_member(x, list1, rest)) result = cons(x, result);
- }
- break;
- case 'D':
- for (result = NIL; consp(list1); list1 = cdr(list1)) {
- x = car(list1);
- if (! apply_member(x, list2, rest)) result = cons(x, result);
- }
- break;
- case 'S':
- for (result = s_true; consp(list1); list1 = cdr(list1)) {
- x = car(list1);
- if (!apply_member(x, list2, rest)) {
- result = NIL;
- break;
- }
- }
- break;
- }
-
- xlpopn(2);
- return(result);
- }
-
- LVAL xsunion() { return(set_op('U')); }
- LVAL xsintersection() { return(set_op('I')); }
- LVAL xsset_difference() { return(set_op('D')); }
- LVAL xssubsetp() { return(set_op('S')); }
-
- LVAL xsremove_duplicates()
- {
- LVAL x, list, rest, result, tail;
-
- xlstkcheck(2);
- xlsave(rest);
- xlsave(result);
-
- list = xlgalist();
- rest = makearglist(xlargc, xlargv);
- rest = cons(NIL, rest);
- rest = cons(NIL, rest);
-
- for (result = NIL; consp(list); list = cdr(list)) {
- x = car(list);
- if (! apply_member(x, result, rest)) {
- if (result == NIL) {
- result = consa(x);
- tail = result;
- }
- else {
- rplacd(tail, consa(x));
- tail = cdr(tail);
- }
- }
- }
- xlpopn(2);
- return(result);
- }
-
- LVAL xsbutlast()
- {
- LVAL x, next;
- int n, k;
-
- xlsave1(x);
- x = xlgalist();
- k = (moreargs()) ? getfixnum(xlgafixnum()) : 1;
- xllastarg();
-
- x = copylist(x);
- n = llength(x) - k;
- if (n <= 0) x = NIL;
- else if (k >= 1) {
- for (next = x; consp(next) && consp(cdr(next)) && n > 1; next = cdr(next), n--);
- rplacd(next, NIL);
- }
-
- xlpop();
- return(x);
- }
-
- static void badseq(s)
- LVAL s;
- {
- xlerror("not a sequence", s);
- }
-
- static void badindex(i)
- LVAL i;
- {
- xlerror("not a valid index", i);
- }
-
- static void badcomplex(c)
- LVAL c;
- {
- xlerror("not a valid complex number", c);
- }
-
- LVAL xsmake_string()
- {
- int n, i;
- char c = ' ';
- LVAL arg, result;
-
- n = getfixnum(xlgafixnum());
- if (xlgetkeyarg(s_ielement, &arg)) {
- if (! charp(arg)) xlerror("not a character", arg);
- c = getchcode(arg);
- }
- result = newstring(n + 1);
- for (i = 0; i < n; i++)
- getstring(result)[i] = c;
- getstring(result)[n] = '\0';
- return(result);
- }
-
- /***********************************************************************/
- /** **/
- /** FIND and POSITION **/
- /** **/
- /***********************************************************************/
-
- LVAL xsfind()
- {
- LVAL result = xmember();
- return(consp(result) ? car(result) : NIL);
- }
-
- LVAL xsposition()
- {
- int n;
- LVAL result;
-
- if (xlargc < 2 || ! listp(peekarg(1))) xlfail("bad arguments");
- n = llength(peekarg(1));
- result = xmember();
- n -= consp(result) ? llength(result) : 0;
- return(consp(result) ? cvfixnum((FIXTYPE) n) : NIL);
- }
-
- /***********************************************************************/
- /** **/
- /** ERROR and BREAK **/
- /** **/
- /***********************************************************************/
-
- LVAL xserror()
- {
- LVAL result;
-
- xlprot1(result);
- result = makearglist(xlargc, xlargv);
- result = cons(NIL, result);
- result = xsapplysubr(xsformat, result);
- result = consa(result);
- result = xsapplysubr(xerror, result);
- xlpop();
-
- return(result);
- }
-
- LVAL xsbreak()
- {
- LVAL result;
-
- if (moreargs()) {
- xlprot1(result);
- result = makearglist(xlargc, xlargv);
- result = cons(NIL, result);
- result = xsapplysubr(xsformat, result);
- result = consa(result);
- result = xsapplysubr(xbreak, result);
- xlpop();
- }
- else result = xbreak();
- return(result);
- }
-