home *** CD-ROM | disk | FTP | other *** search
- From sce!mitel!uunet!zephyr.ens.tek.com!tekcrl!tekgvs!toma Sat Sep 16 08:20:18 EDT 1989
- Article: 1 of comp.lang.lisp.x
- Path: cognos!sce!mitel!uunet!zephyr.ens.tek.com!tekcrl!tekgvs!toma
- From: toma@tekgvs.LABS.TEK.COM (Tom Almy)
- Newsgroups: comp.lang.lisp.x
- Subject: XLISP 2.0 BUG(?)
- Message-ID: <5911@tekgvs.LABS.TEK.COM>
- Date: 11 Sep 89 14:34:11 GMT
- Reply-To: toma@tekgvs.LABS.TEK.COM (Tom Almy)
- Organization: Tektronix, Inc., Beaverton, OR.
- Lines: 22
-
-
- Part of my effort to make xlisp more compatible with Common Lisp:
-
- Problem: Functions which take the :end keyword argument do not allow NIL
- to mean "end of list" as in Common Lisp.
-
- Example: (string-downcase "ABC DEF" :start 4 :end NIL) gives an error.
-
- Fix: in function getbounds() in file xlstr.c, change
-
- if (xlgkfixnum(ekey,&arg)) {
- *pend = (int)getfixnum(arg);
-
- to
- if (xlgetkeyarg(ekey, &arg) && arg != NIL) {
- if (!fixp(arg)) xlbadtype(arg);
- *pend = (int)getfixnum(arg);
-
-
- Tom Almy
- toma@tekgvs.labs.tek.com
- Standard Disclaimers Apply
-
-
- From sce!mitel!uunet!zephyr.ens.tek.com!tekcrl!tekgvs!toma Sat Sep 16 08:20:26 EDT 1989
- Article: 2 of comp.lang.lisp.x
- Path: cognos!sce!mitel!uunet!zephyr.ens.tek.com!tekcrl!tekgvs!toma
- From: toma@tekgvs.LABS.TEK.COM (Tom Almy)
- Newsgroups: comp.lang.lisp.x
- Subject: XLISP 2.0 Modifications (1 of 2)
- Message-ID: <5918@tekgvs.LABS.TEK.COM>
- Date: 11 Sep 89 22:25:11 GMT
- Reply-To: toma@tekgvs.LABS.TEK.COM (Tom Almy)
- Organization: Tektronix, Inc., Beaverton, OR.
- Lines: 393
-
- I have recently been adding a few Common Lisp functions to XLISP 2.0, and
- makeing some existing functions more Common-Lisp compatible (particularly
- in making functions that are supposed to take sequence arguments (in XLISP
- that would be lists, arrays, or strings) actually take them.
-
- These changes produce the following consequences:
-
- 1. Functions with names starting with "STRING" will accept a symbol as
- the string argument. The symbols printname string is used.
-
- 2. STRCAT is eliminated (a macro is placed in init.lsp for backwards
- compatibility). The replacement function is CONCATENATE which will
- concatenate sequences of any type(s) into a result sequence of any
- type. It is used: (CONCATENATE <type> <seq1> [<seq2> ...]) where
- type is the result type, one of CONS ARRAY or STRING.
-
- 3. AREF will work on strings as well as arrays.
-
- 4. SUBSEQ REVERSE REMOVE... DELETE... take sequence arguments rather
- than just list arguments.
-
- 5. REMOVE... and DELETE... accept :start and :end keyword arguments.
-
- 6. Added function (ELT <seq> <index>) which combines the functionality
- of AREF and NTH.
-
- 7. Added function (MAP <type> <fcn> <seq1> [<seq2> ...]) a mapping
- function over sequences. The resulting sequence is of type <type>,
- which is one of CONS ARRAY STRING or NIL (meaning no, or NIL, result).
-
- 8. Added functions POSITION-IF, FIND-IF, and COUNT-IF, which work
- analogously to REMOVE-IF, but return the position of the first match,
- the first match, and number of matches, respectively.
-
- 9. Added function (SEARCH <seq1> <seq2> &key :test :test-not :start1
- :end1 :start2 :end2) which returns the index of the first occurance
- of seq1 in seq2. For example (search #(a b c) '(a b a b c d)) returns
- 2.
-
- 10. Added function (COERCE <expr> <type>) which can coerce between
- sequence types and in a limited basis to characters or floating point
- numbers.
-
-
- This is the first of two parts. The final line in this file is "This is
- the end of part 1."
-
-
- Tom Almy
- September 11, 1989
- toma@tekgvs.labs.tek.com
- Standard Disclaimers Apply
-
-
- ***************************************
- The first change reduces the amount of code.
-
- In xlsubr.c, add the following definition:
-
- /* xlbadtype - report a "bad argument type" error */
- LVAL xlbadtype(arg)
- LVAL arg;
- {
- return xlerror("bad argument type",arg);
- }
-
-
- Then replace all occurances of `xlerror("bad argument type",' with
- `xlbadtype(' throughout the program (including xlisp.h).
-
- ***************************************
-
- Add the file xlseq.c to your "makefile" in an appropriate manner.
-
- ***************************************
- Add definition in xlisp.h:
-
- #define xlgastrorsym() (testarg(symbolp(*xlargv) ? getpname(nextarg()) : typearg(stringp)))
-
- Added external declaration in xlisp.h:
- extern LVAL xlbadtype(); /* report "bad argument type" error */
-
-
-
- ***************************************
- Add to init.lsp:
- (unless (fboundp 'strcat) ; backwards compatibility
- (defmacro strcat (&rest str) `(concatenate 'string ,@str)))
-
-
-
- ***************************************
- In xlftab.c, add the following external declaration:
- extern LVAL
- xcoerce(), xconcatenate(), xelt(), xmap(), xsearch(), xpositionif(),
- xcountif(),xfindif();
-
- delete the declaration for xstrcat.
-
- In funtab[], replace the definition for STRCAT with:
-
- { "CONCATENATE", S, xconcatenate }, /* 168 */
-
- Replace NULL definitions at the end of the table with new definitions,
- being sure to keep the table length constant.
-
- { "COUNT-IF", S, xcountif }, /* 287 */
- { "FIND-IF", S, xfindif }, /* 288 */
- { "COERCE", S, xcoerce }, /* 289 */
- { "ELT", S, xelt }, /* 290 */
- { "MAP", S, xmap }, /* 291 */
- { "POSITION-IF", S, xpositionif }, /* 292 */
- { "SEARCH", S, xsearch }, /* 293 */
-
- *******************************
-
- In file xlglob.c, add the following definition:
-
- LVAL s_elt = NIL;
-
- *******************************
-
- In file xlinit.c, add the following external declaration:
-
- extern LVAL s_elt;
-
- in function xlsymbols(), in section "enter setf place specifiers", add
-
- s_elt = xlenter("ELT");
-
- *******************************
-
- In file xlbfun.c, function xaref(), change
-
- array = xlgavector();
-
- to
-
- array = xlgetarg();
-
- Before the section titled "range check the index" add:
-
- if (stringp(array)) { /* extension -- allow fetching chars from string*/
- if (i < 0 || i >= getslength(array)-1)
- xlerror("string index out of bounds",index);
- return (cvchar(array->n_string[i]));
- }
-
- if (!vectorp(array)) xlbadtype(array); /* type must be array */
-
- ******************************
- In xlcont.c, add the following declaration:
-
- extern LVAL s_elt;
-
-
- In function placeform(), replace the fun == s_aref code with:
-
- xlsave1(arg1);
-
- arg1 = evarg(&place); /* allow string argument */
- arg2 = evmatch(FIXNUM,&place); i = getfixnum(arg2);
- if (place) toomany(place);
-
- if (stringp(arg1)) { /* extension for strings */
- if (i < 0 || i >= getslength(arg1)-1)
- xlerror("index out of range",arg2);
- if (!charp(value))
- xlerror("strings only contain characters",value);
- arg1->n_string[i] = getchcode(value);
- }
- else if(vectorp(arg1)) {
- if (i < 0 || i >= getsize(arg1))
- xlerror("index out of range",arg2);
- setelement(arg1,(int)i,value);
- }
- else xlbadtype(arg1);
- xlpop();
-
- Then add the following "case":
-
- else if (fun == s_elt) {
- xlsave1(arg1);
- arg1 = evarg(&place);
- arg2 = evmatch(FIXNUM,&place); i = getfixnum(arg2);
- if (place) toomany(place);
- if (listp(arg1)) {
- for (; i > 0 && consp(arg1); --i)
- arg1 = cdr(arg1);
- if((!consp(arg1)) || i < 0)
- xlerror("index out of range",arg2);
- rplaca(arg1,value);
- }
- else if (ntype(arg1) == STRING) {
- if (i < 0 || i >= getslength(arg1)-1)
- xlerror("index out of range",arg2);
- if (!charp(value))
- xlerror("strings only contain characters",value);
- arg1->n_string[i] = getchcode(value);
- }
- else if (ntype(arg1) == VECTOR) {
- if (i < 0 || i >= getsize(arg1))
- xlerror("index out of range",arg2);
- setelement(arg1,(int)i,value);
- }
- else xlbadtype(arg1);
- xlpop();
- }
-
- ***************************
-
- In xlstr.c, function changecase(), change
-
- src = xlgastring();
-
- to
-
- src = (destructive? xlgastring() : xlgastrorsym());
-
-
- In function strcompare(), change references to xlgastring to xlgastrorsym.
-
- In function trim(), change references to xlgastring to xlgastrorsym.
-
-
- Delete functions xstrcat() and xsubseq(). The latter is rewritten and
- will be in a new file, xlseq.c
-
- ****************************************
- In file xlsys.c, add the following:
-
- int xlcvttype(arg) /* find type of argument and return it */
- LVAL arg;
- {
- if (arg == a_subr) return SUBR;
- if (arg == a_fsubr) return FSUBR;
- if (arg == a_cons) return CONS;
- if (arg == a_symbol) return SYMBOL;
- if (arg == a_fixnum) return FIXNUM;
- if (arg == a_flonum) return FLONUM;
- if (arg == a_string) return STRING;
- if (arg == a_object) return OBJECT;
- if (arg == a_stream) return STREAM;
- if (arg == a_vector) return VECTOR;
- if (arg == a_closure) return CLOSURE;
- if (arg == a_char) return CHAR;
- if (arg == a_ustream) return USTREAM;
- return 0;
- }
-
- LOCAL LVAL listify(arg) /* arg must be vector or string */
- LVAL arg;
- {
- LVAL val;
- int i;
-
- xlsave1(val);
-
- if (ntype(arg) == VECTOR) {
- for (i = getsize(arg); i-- > 0; )
- val = cons(getelement(arg,i),val);
- }
- else { /* a string */
- for (i = getslength(arg)-1; i-- > 0; )
- val = cons(cvchar(arg->n_string[i]),val);
- }
-
- xlpop();
- return (val);
- }
-
- LOCAL LVAL vectify(arg) /* arg must be string or cons */
- LVAL arg;
- {
- LVAL val,temp;
- int i,l;
-
- if (ntype(arg) == STRING) {
- l = getslength(arg)-1;
- val = newvector(l);
- for (i=0; i < l; i++) setelement(val,i,cvchar(arg->n_string[i]));
- }
- else { /* a cons */
- val = arg;
- for (l = 0; consp(val); l++) val = cdr(val); /* get length */
- val = newvector(l);
- temp = arg;
- for (i = 0; i < l; i++) {
- setelement(val,i,car(temp));
- temp = cdr(temp);
- }
- }
- return val;
- }
-
-
- LOCAL LVAL stringify(arg) /* arg must be vector or cons */
- LVAL arg;
- {
- LVAL val,temp;
- int i,l;
-
- if (ntype(arg) == VECTOR) {
- l = getsize(arg);
- val = newstring(l+1);
- for (i=0; i < l; i++) {
- temp = getelement(arg,i);
- if (ntype(temp) != CHAR) goto failed;
- val->n_string[i] = getchcode(temp);
- }
- val->n_string[l] = 0;
- return val;
- }
- else { /* must be cons */
- val = arg;
- for (l = 0; consp(val); l++) {
- if (ntype(car(val)) != CHAR) goto failed;
- val = cdr(val); /* get length */
- }
-
- val = newstring(l+1);
- temp = arg;
- for (i = 0; i < l; i++) {
- val->n_string[i] = getchcode(car(temp));
- temp = cdr(temp);
- }
- val->n_string[l] = 0;
- return val;
- }
- failed:
- xlerror("cannot make into string", arg);
- }
-
-
-
- /* coerce function */
- LVAL xcoerce()
- {
- LVAL type, arg, temp;
- int newtype,oldtype;
-
- arg = xlgetarg();
- type = xlgetarg();
- xllastarg();
-
- if ((newtype = xlcvttype(type)) == 0) goto badconvert;
-
- oldtype = ntype(arg);
- if (oldtype == newtype) return (arg); /* easy case! */
-
- switch (newtype) {
- case CONS: if ((oldtype == STRING)|(oldtype == VECTOR))
- return (listify(arg));
- break;
- case STRING: if ((oldtype == CONS)|(oldtype == VECTOR))
- return (stringify(arg));
- break;
- case VECTOR: if ((oldtype == STRING) | (oldtype == CONS))
- return (vectify(arg));
- break;
- case CHAR:
- if (oldtype == FIXNUM) return cvchar((int)getfixnum(arg));
- else if ((oldtype == STRING) && (getslength(arg) == 2))
- return cvchar(arg->n_string[0]);
- else if (oldtype == SYMBOL) {
- temp = getpname(arg);
- if (getslength(temp) == 2) return cvchar(temp->n_string[0]);
- }
- break;
- case FLONUM:
- if (oldtype == FIXNUM) return (cvflonum(1.0*(int)getfixnum(arg)));
- break;
- }
-
-
- badconvert:
- xlerror("illegal coersion",arg);
-
- }
-
-
- ******************************
-
- In file xllist.c, delete the functions xreverse(), xremove(), remif(),
- xremif(), xremifnot(), xdelete(), delif(), xdelif(), xdelifnot(), dotest1().
- These functions will be in the new file xlseq.c.
-
- Remove any LOCAL atribute to function dotest2().
-
-
- ******************************
-
- This is the end of part 1.
-
-
- From sce!mitel!uunet!zephyr.ens.tek.com!tekcrl!tekgvs!toma Sat Sep 16 08:20:33 EDT 1989
- Article: 3 of comp.lang.lisp.x
- Path: cognos!sce!mitel!uunet!zephyr.ens.tek.com!tekcrl!tekgvs!toma
- From: toma@tekgvs.LABS.TEK.COM (Tom Almy)
- Newsgroups: comp.lang.lisp.x
- Subject: XLISP 2.0 MODIFICATIONS (2 of 2)
- Message-ID: <5919@tekgvs.LABS.TEK.COM>
- Date: 11 Sep 89 22:26:44 GMT
- Reply-To: toma@tekgvs.LABS.TEK.COM (Tom Almy)
- Organization: Tektronix, Inc., Beaverton, OR.
- Lines: 1073
-
- The remainder of the changes consists of the file xlseq.c.
-
-
- Tom Almy
- September 11, 1989
- toma@tekgvs.labs.tek.com
- Standard Disclaimers Apply
-
-
- ******************************
-
- /* xlseq.c - xlisp sequence functions */
- /* Written by Thomas Almy, based on code:
- Copyright (c) 1985, by David Michael Betz
- All Rights Reserved
- Permission is granted for unrestricted non-commercial use */
-
- #include "xlisp.h"
-
- /* external procedures */
- extern int xlcvttype();
- extern int xlgkfixnum();
- extern int xlgetkeyarg();
-
- /* external variables */
- extern LVAL k_start,k_end,k_1start,k_1end,k_2start,k_2end;
-
-
- /* Apologies from the author (Tom Almy):
- :start and :end isn't quite Kosher in
- that it doesn't always signal an error for out of range.
- Fixing it up is left as an exercise for the reader.*/
-
- /* I desparately needed a "MAXINT" or "MAXLONG" constant, so I faked it*/
-
- /* Also, I found it convenient to use "goto" statements to handle non-local
- loop exits and jumps to common error routines. A purist might complain,
- but I think the code is cleaner and easier to follow this way. */
-
- #define MAXSIZE 10000000L /* a lie, but good enough */
-
- LOCAL VOID getseqbounds(start,end,length,startkey,endkey)
- long *start, *end, length;
- LVAL *startkey, *endkey;
- {
- LVAL arg;
-
- if (xlgkfixnum(*startkey,&arg)) {
- *start = (long)getfixnum(arg);
- if (*start < 0 || *start > length ) goto rangeError;
- }
- else *start = 0;
-
- if (xlgetkeyarg(*endkey, &arg) && arg != NIL) {
- if (!fixp(arg)) xlbadtype(arg);
- *end = (long)getfixnum(arg);
- if (*end < 0 || *end > length) goto rangeError;
- }
- else *end = length; /* we need a maxint value! */
-
- if (*start <= *end) return;
- /* else there is a range error */
-
- rangeError:
- xlerror("range error",arg);
- }
-
-
-
- /* dotest1 - call a test function with one argument */
- /* this function was in xllist.c */
- int dotest1(arg,fun)
- LVAL arg,fun;
- {
- LVAL *newfp;
-
- /* create the new call frame */
- newfp = xlsp;
- pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
- pusharg(fun);
- pusharg(cvfixnum((FIXTYPE)1));
- pusharg(arg);
- xlfp = newfp;
-
- /* return the result of applying the test function */
- return (xlapply(1) != NIL);
-
- }
-
-
- /* xelt - sequence reference function */
- LVAL xelt()
- {
- LVAL seq,index;
- FIXTYPE i;
-
- /* get the sequence and the index */
-
- seq = xlgetarg();
-
- index = xlgafixnum(); i = getfixnum(index);
- if (i < 0) goto badindex;
-
- xllastarg();
-
- if (listp(seq)) { /* do like nth, but check for in range */
- /* find the ith element */
- while (consp(seq)) {
- if (i-- == 0) return (car(seq));
- seq = cdr(seq);
- }
- goto badindex; /* end of list reached first */
- }
-
-
- if (ntype(seq) == STRING) {
- if (i >= getslength(seq)-1) goto badindex;
- return (cvchar(seq->n_string[i]));
- }
-
- if (ntype(seq)!=VECTOR) xlbadtype(seq); /* type must be array */
-
- /* range check the index */
- if (i >= getsize(seq)) goto badindex;
-
- /* return the array element */
- return (getelement(seq,(int)i));
-
- badindex:
- xlerror("index out of bounds",index);
- }
-
-
- /* xmap -- map function */
-
- LOCAL long getlength(seq)
- LVAL seq;
- {
- long len;
-
- if (seq == NIL) return 0;
-
- switch (ntype(seq)) {
- case STRING:
- return (long)getslength(seq) - 1;
- case VECTOR:
- return (long)getsize(seq);
- case CONS:
- len = 0;
- while (consp(seq)) {
- len++;
- seq = cdr(seq);
- }
- return len;
- default:
- xlbadtype(seq);
- return (0); /* ha ha */
- }
- }
-
-
- LVAL xmap()
- {
- LVAL *newfp, fun, lists, val, last, x, y;
- long len,temp;
- int argc, typ, i;
-
- /* protect some pointers */
- xlstkcheck(3);
- xlsave(fun);
- xlsave(lists);
- xlsave(val);
-
- /* get the type of resultant */
- if ((last = xlgetarg()) == NIL) { /* nothing is returned */
- typ = 0;
- }
- else if ((typ = xlcvttype(last)) != CONS &&
- typ != STRING && typ != VECTOR) {
- xlerror("invalid result type", last);
- }
-
- /* get the function to apply and argument sequences */
- fun = xlgetarg();
- val = NIL;
- lists = xlgetarg();
- len = getlength(lists);
- argc = 1;
-
- /* build a list of argument lists */
- for (lists = last = consa(lists); moreargs(); last = cdr(last)) {
- val = xlgetarg();
- if ((temp = getlength(val)) < len) len = temp;
- argc++;
- rplacd(last,(cons(val,NIL)));
- }
-
- /* initialize the result list */
- switch (typ) {
- case VECTOR: val = newvector(len); break;
- case STRING: val = newstring(len+1); break;
- default: val = NIL; break;
- }
-
-
- /* loop through each of the argument lists */
- for (i=0;i<len;i++) {
-
- /* build an argument list from the sublists */
- newfp = xlsp;
- pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
- pusharg(fun);
- pusharg(NIL);
- for (x = lists; x != NIL ; x = cdr(x)) {
- y = car(x);
- switch (ntype(y)) {
- case CONS:
- pusharg(car(y));
- rplaca(x,cdr(y));
- break;
- case VECTOR:
- pusharg(getelement(y,i));
- break;
- case STRING:
- pusharg(cvchar(y->n_string[i]));
- break;
- }
- }
-
- /* apply the function to the arguments */
- newfp[2] = cvfixnum((FIXTYPE)argc);
- xlfp = newfp;
- x = xlapply(argc);
-
- switch (typ) {
- case CONS:
- y = consa(x);
- if (val) rplacd(last,y);
- else val = y;
- last = y;
- break;
- case VECTOR:
- setelement(val,i,x);
- break;
- case STRING:
- if (!charp(x))
- xlerror("map function returned non-character",x);
- val->n_string[i] = getchcode(x);
- break;
- }
-
- }
-
- /* restore the stack */
- xlpopn(3);
-
- /* return the last test expression value */
- return (val);
- }
-
-
-
-
- /* xconcatenate - concatenate a bunch of sequences */
- /* replaces (and extends) strcat, now a macro */
- LOCAL int calclength()
- {
- LVAL tmp, *saveargv;
- int saveargc;
- int len;
-
- /* save the argument list */
- saveargv = xlargv;
- saveargc = xlargc;
-
- /* find the length of the new string or vector */
- for (len = 0; moreargs(); ) {
- tmp = xlgetarg();
- len += getlength(tmp);
- if (len < 0) xlerror("too long",tmp);
- }
-
- /* restore the argument list */
- xlargv = saveargv;
- xlargc = saveargc;
-
- return len;
- }
-
-
- LOCAL LVAL cattostring()
- {
- LVAL tmp,temp,val;
- unsigned char *str;
- int len,i;
-
- /* find resulting length -- also validates argument types */
- len = calclength();
-
- /* create the result string */
- val = newstring(len+1);
- str = getstring(val);
-
- /* combine the strings */
- while (moreargs()) {
- tmp = nextarg();
- if (tmp != NIL) switch (ntype(tmp)) {
- case STRING:
- len = getslength(tmp)-1;
- memcpy((char *)str, (char *)getstring(tmp), len);
- str += len;
- break;
- case VECTOR:
- len = getsize(tmp);
- for (i = 0; i < len; i++) {
- temp = getelement(tmp,i);
- if (!charp(temp)) goto failed;
- *str++ = getchcode(temp);
- }
- break;
- case CONS:
- while (consp(tmp)) {
- temp = car(tmp);
- if (!charp(temp)) goto failed;
- *str++ = getchcode(temp);
- tmp = cdr(tmp);
- }
- break;
- }
- }
-
- *str = 0; /* delimit string (why, I don't know!) */
-
- /* return the new string */
- return (val);
-
- failed:
- xlerror("cannot make into string", tmp);
- }
-
- LOCAL LVAL cattovector()
- {
- LVAL tmp,val;
- LVAL *vect;
- int len,i;
-
- /* find resulting length -- also validates argument types */
- len = calclength();
-
- /* create the result vector */
- val = newvector(len);
- vect = &val->n_vdata[0];
-
- /* combine the vectors */
- while (moreargs()) {
- tmp = nextarg();
- if (tmp != NIL) switch (ntype(tmp)) {
- case VECTOR:
- len = getsize(tmp);
- memcpy(vect, &getelement(tmp,0), len*sizeof(LVAL));
- vect += len;
- break;
- case STRING:
- len = getslength(tmp)-1;
- for (i = 0; i < len; i++) {
- *vect++ = cvchar(tmp->n_string[i]);
- }
- break;
- case CONS:
- while (consp(tmp)) {
- *vect++ = car(tmp);
- tmp = cdr(tmp);
- }
- break;
- }
- }
-
- /* return the new vector */
- return (val);
- }
-
- LOCAL LVAL cattocons()
- {
- LVAL val,tmp,next,last=NIL;
- int len,i;
-
- xlsave1(val); /* protect against GC */
-
- /* combine the lists */
- while (moreargs()) {
- tmp = nextarg();
- if (tmp != NIL) switch (ntype(tmp)) {
- case CONS:
- while (consp(tmp)) {
- next = consa(car(tmp));
- if (val) rplacd(last,next);
- else val = next;
- last = next;
- tmp = cdr(tmp);
- }
- break;
- case VECTOR:
- len = getsize(tmp);
- for (i = 0; i<len; i++) {
- next = consa(getelement(tmp,i));
- if (val) rplacd(last,next);
- else val = next;
- last = next;
- }
- break;
- case STRING:
- len = getslength(tmp) - 1;
- for (i = 0; i < len; i++) {
- next = consa(cvchar(tmp->n_string[i]));
- if (val) rplacd(last,next);
- else val = next;
- last = next;
- }
- break;
- default:
- xlbadtype(tmp); break; /* need default because no precheck*/
- }
- }
-
- xlpop();
-
- return (val);
-
- }
-
-
- LVAL xconcatenate()
- {
- LVAL tmp;
-
- switch (xlcvttype(tmp = xlgetarg())) { /* target type of data */
- case CONS: return cattocons();
- case STRING: return cattostring();
- case VECTOR: return cattovector();
- default: xlerror("invalid result type", tmp);
- }
- }
-
- /* xsubseq - return a subsequence -- new version */
-
- LVAL xsubseq()
- {
- int start,end,len;
- int srctype;
- LVAL src,dst;
- LVAL next,last=NIL;
-
- /* get sequence */
- src = xlgetarg();
- if (listp(src)) srctype = CONS;
- else srctype=ntype(src);
-
-
- /* get length */
- switch (srctype) {
- case STRING:
- len = getslength(src) - 1;
- break;
- case VECTOR:
- len = getsize(src);
- break;
- case CONS:
- dst = src; /* use dst as temporary */
- len = 0;
- while (consp(dst)) {len++; dst = cdr(dst);}
- break;
- default:
- xlbadtype(src);
- }
-
- /* get the starting position */
- dst = xlgafixnum(); start = (int)getfixnum(dst);
- if (start < 0 || start > len)
- xlerror("sequence index out of bounds",dst);
-
- /* get the ending position */
- if (moreargs()) {
- dst = xlgafixnum(); end = (int)getfixnum(dst);
- if (end < 0 || end > len)
- xlerror("sequence index out of bounds",dst);
- }
- else
- end = len;
- xllastarg();
-
- len = end - start;
-
- switch (srctype) { /* do the subsequencing */
- case STRING:
- dst = newstring(len+1);
- memcpy(getstring(dst), getstring(src)+start, len);
- dst->n_string[len] = 0;
- break;
- case VECTOR:
- dst = newvector(len);
- memcpy(dst->n_vdata, &src->n_vdata[start], sizeof(LVAL)*len);
- break;
- case CONS:
- xlsave1(dst);
- while (start--) src = cdr(src);
- while (len--) {
- next = consa(car(src));
- if (dst) rplacd(last,next);
- else dst = next;
- last = next;
- src = cdr(src);
- }
- xlpop();
- break;
- }
-
- /* return the substring */
- return (dst);
- }
-
-
- /* xreverse - built-in function reverse -- new version */
- LVAL xreverse()
- {
- LVAL seq,val;
- int i,len;
-
- /* get the sequence to reverse */
- seq = xlgetarg();
- xllastarg();
-
- if (seq == NIL) return (NIL); /* empty argument */
-
- switch (ntype(seq)) {
- case CONS:
- /* protect pointer */
- xlsave1(val);
-
- /* append each element to the head of the result list */
- for (val = NIL; consp(seq); seq = cdr(seq))
- val = cons(car(seq),val);
-
- /* restore the stack */
- xlpop();
- break;
- case VECTOR:
- len = getsize(seq);
- val = newvector(len);
- for (i = 0; i < len; i++)
- setelement(val,i,getelement(seq,len-i-1));
- break;
- case STRING:
- len = getslength(seq) - 1;
- val = newstring(len+1);
- for (i = 0; i < len; i++)
- val->n_string[i] = seq->n_string[len-i-1];
- val->n_string[len] = 0;
- break;
- default:
- xlbadtype(seq); break;
- }
-
- /* return the sequence */
- return (val);
- }
-
-
- /* remif - common code for 'remove', 'remove-if', and 'remove-if-not' */
- LOCAL LVAL remif(tresult,expr)
- int tresult,expr;
- {
- LVAL x,seq,fcn,val,last,next;
- int i,j,l;
- long start,end;
-
- if (expr) {
- /* get the expression to remove and the sequence */
- x = xlgetarg();
- seq = xlgetarg();
- xltest(&fcn,&tresult);
- }
- else {
- /* get the function and the sequence */
- fcn = xlgetarg();
- seq = xlgetarg();
- /* xllastarg(); */
- }
-
- if (seq == NIL) return NIL;
-
- getseqbounds(&start,&end,MAXSIZE,&k_start,&k_end);
-
- /* protect some pointers */
- xlstkcheck(2);
- xlprotect(fcn);
- xlsave(val);
-
- /* remove matches */
-
- switch (ntype(seq)) {
- case CONS:
- end -= start; /* length */
- for (; consp(seq); seq = cdr(seq)) {
-
- /* check to see if this element should be deleted */
- /* force copy if count, as specified by end, is exhausted */
- if (start-- > 0 || end-- <= 0 ||
- (expr?dotest2(x,car(seq),fcn)
- :dotest1(car(seq),fcn)) != tresult) {
- next = consa(car(seq));
- if (val) rplacd(last,next);
- else val = next;
- last = next;
- }
- }
- break;
- case VECTOR:
- val = newvector(l=getlength(seq));
- for (i=j=0; i < l; i++) {
- if (i < start || i >= end || /* copy if out of range */
- (expr?dotest2(x,getelement(seq,i),fcn)
- :dotest1(getelement(seq,i),fcn)) != tresult) {
- setelement(val,j++,getelement(seq,i));
- }
- }
- if (l != j) { /* need new, shorter result -- too bad */
- fcn = val; /* save value in protected cell */
- val = newvector(j);
- memcpy(val->n_vdata, fcn->n_vdata, j*sizeof(LVAL));
- }
- break;
- case STRING:
- l = getslength(seq)-1;
- val = newstring(l+1);
- for (i=j=0; i < l; i++) {
- if (i < start || i >= end || /* copy if out of range */
- (expr?dotest2(x,cvchar(seq->n_string[i]),fcn)
- :dotest1(cvchar(seq->n_string[i]),fcn)) != tresult) {
- val->n_string[j++] = seq->n_string[i];
- }
- }
- if (l != j) { /* need new, shorter result -- too bad */
- fcn = val; /* save value in protected cell */
- val = newstring(j+1);
- memcpy(val->n_string, fcn->n_string, j*sizeof(char));
- val->n_string[j] = 0;
- }
- break;
- default:
- xlbadtype(seq); break;
- }
-
-
- /* restore the stack */
- xlpopn(2);
-
- /* return the updated sequence */
- return (val);
- }
-
- /* xremif - built-in function 'remove-if' -- enhanced version */
- LVAL xremif()
- {
- return (remif(TRUE,FALSE));
- }
-
- /* xremifnot - built-in function 'remove-if-not' -- enhanced version */
- LVAL xremifnot()
- {
- return (remif(FALSE,FALSE));
- }
-
- /* xremove - built-in function 'remove' -- enhanced version */
-
- LVAL xremove()
- {
- return (remif(TRUE,TRUE));
- }
-
-
- /* delif - common code for 'delete', 'delete-if', and 'delete-if-not' */
- LOCAL LVAL delif(tresult,expr)
- int tresult,expr;
- {
- LVAL x,seq,fcn,last,val;
- int i,j,l;
- long start,end;
-
- if (expr) {
- /* get the expression to delete and the sequence */
- x = xlgetarg();
- seq = xlgetarg();
- xltest(&fcn,&tresult);
- }
- else {
- /* get the function and the sequence */
- fcn = xlgetarg();
- seq = xlgetarg();
- /* xllastarg(); */
- }
-
- if (seq == NIL) return NIL;
-
- getseqbounds(&start,&end,MAXSIZE,&k_start,&k_end);
-
- /* protect a pointer */
- xlstkcheck(1);
- xlprotect(fcn);
-
-
- /* delete matches */
-
- switch (ntype(seq)) {
- case CONS:
- end -= start; /* gives length */
- /* delete leading matches */
- while (consp(seq)) {
- if (start-- > 0 || (expr?dotest2(x,car(seq),fcn)
- :dotest1(car(seq),fcn)) != tresult)
- break;
- seq = cdr(seq);
- }
- val = last = seq;
-
- /* delete embedded matches */
- if (consp(seq)) {
-
- /* skip the first non-matching element */
- seq = cdr(seq);
-
- /* look for embedded matches */
- while (consp(seq)) {
-
- /* check to see if this element should be deleted */
- if (start-- <= 0 && end-- > 0 &&
- (expr?dotest2(x,car(seq),fcn)
- :dotest1(car(seq),fcn)) == tresult)
- rplacd(last,cdr(seq));
- else
- last = seq;
-
- /* move to the next element */
- seq = cdr(seq);
- }
- }
- break;
- case VECTOR:
- l = getlength(seq);
- for (i=j=0; i < l; i++) {
- if (i < start || i >= end || /* copy if out of range */
- (expr?dotest2(x,getelement(seq,i),fcn)
- :dotest1(getelement(seq,i),fcn)) != tresult) {
- if (i != j) setelement(seq,j,getelement(seq,i));
- j++;
- }
- }
- if (l != j) { /* need new, shorter result -- too bad */
- fcn = seq; /* save value in protected cell */
- seq = newvector(j);
- memcpy(seq->n_vdata, fcn->n_vdata, j*sizeof(LVAL));
- }
- val = seq;
- break;
- case STRING:
- l = getslength(seq)-1;
- for (i=j=0; i < l; i++) {
- if (i < start || i >= end || /* copy if out of range */
- (expr?dotest2(x,cvchar(seq->n_string[i]),fcn)
- :dotest1(cvchar(seq->n_string[i]),fcn)) != tresult) {
- if (i != j) seq->n_string[j] = seq->n_string[i];
- j++;
- }
- }
- if (l != j) { /* need new, shorter result -- too bad */
- fcn = seq; /* save value in protected cell */
- seq = newstring(j+1);
- memcpy(seq->n_string, fcn->n_string, j*sizeof(char));
- seq->n_string[j] = 0;
- }
- val = seq;
- break;
- default:
- xlbadtype(seq); break;
- }
-
-
- /* restore the stack */
- xlpop();
-
- /* return the updated sequence */
- return (val);
- }
-
- /* xdelif - built-in function 'delete-if' -- enhanced version */
- LVAL xdelif()
- {
- return (delif(TRUE,FALSE));
- }
-
- /* xdelifnot - built-in function 'delete-if-not' -- enhanced version */
- LVAL xdelifnot()
- {
- return (delif(FALSE,FALSE));
- }
-
- /* xdelete - built-in function 'delete' -- enhanced version */
-
- LVAL xdelete()
- {
- return (delif(TRUE,TRUE));
- }
-
- /* xcountif - built-in function 'count-if TAA MOD addition */
- LVAL xcountif()
- {
- FIXTYPE counter=0;
- int i,l;
- long start,end;
- LVAL seq, fcn;
-
-
- /* get the arguments */
- fcn = xlgetarg();
- seq = xlgetarg();
- /* xllastarg(); */
-
- if (seq == NIL) return (cvfixnum(0L));
-
- getseqbounds(&start,&end,MAXSIZE,&k_start,&k_end);
-
- xlstkcheck(1);
- xlprotect(fcn);
-
- /* examine arg and count */
- switch (ntype(seq)) {
- case CONS:
- end -= start;
- for (; consp(seq); seq = cdr(seq))
- if (start-- <= 0 && end-- > 0 &&
- dotest1(car(seq),fcn)) counter++;
- break;
- case VECTOR:
- l = getlength(seq);
- if (end < l) l = end;
- for (i=start; i < l; i++)
- if (dotest1(getelement(seq,i),fcn)) counter++;
- break;
- case STRING:
- l = getslength(seq)-1;
- if (end < l) l = end;
- for (i=start; i < l; i++)
- if (dotest1(cvchar(seq->n_string[i]),fcn)) counter++;
- break;
- default:
- xlbadtype(seq); break;
- }
-
- xlpop();
-
- return (cvfixnum(counter));
- }
-
- /* xfindif - built-in function 'find-if' TAA MOD */
- LVAL xfindif()
- {
- LVAL seq, fcn, val;
- long start,end;
- int i,l;
-
- fcn = xlgetarg();
- seq = xlgetarg();
- /* xllastarg(); */
-
- if (seq == NIL) return NIL;
-
- getseqbounds(&start,&end,MAXSIZE,&k_start,&k_end);
-
- xlstkcheck(1);
- xlprotect(fcn);
-
- switch (ntype(seq)) {
- case CONS:
- end -= start;
- for (; consp(seq); seq = cdr(seq)) {
- if (start-- <= 0 && end-- > 0 &&
- dotest1(val=car(seq), fcn)) goto fin;
- }
- break;
- case VECTOR:
- l = getlength(seq);
- if (end < l) l = end;
- for (i=start; i < l; i++)
- if (dotest1(val=getelement(seq,i),fcn)) goto fin;
- break;
- case STRING:
- l = getslength(seq)-1;
- if (end < l) l = end;
- for (i=start; i < l; i++)
- if (dotest1(val=cvchar(seq->n_string[i]),fcn)) goto fin;
- break;
- default:
- xlbadtype(seq); break;
- }
-
- val = NIL; /* not found */
-
- fin:
- xlpop();
- return (val);
- }
-
- /* xpositionif - built-in function 'position-if' TAA MOD */
- LVAL xpositionif()
- {
- LVAL seq, fcn;
- long start,end;
- FIXTYPE count;
- int i,l;
-
- fcn = xlgetarg();
- seq = xlgetarg();
- /* xllastarg(); */
-
- if (seq == NIL) return NIL;
-
- getseqbounds(&start,&end,MAXSIZE,&k_start,&k_end);
-
- xlstkcheck(1);
- xlprotect(fcn);
-
- switch (ntype(seq)) {
- case CONS:
- end -= start;
- count = 0;
- for (; consp(seq); seq = cdr(seq)) {
- if ((start-- <= 0) && (end-- > 0) &&
- dotest1(car(seq), fcn)) goto fin;
- count++;
- }
- break;
- case VECTOR:
- l = getlength(seq);
- if (end < l) l = end;
- for (i=start; i < l; i++)
- if (dotest1(getelement(seq,i),fcn)) {
- count = i;
- goto fin;
- }
- break;
- case STRING:
- l = getslength(seq)-1;
- if (end < l) l = end;
- for (i=start; i < l; i++)
- if (dotest1(cvchar(seq->n_string[i]),fcn)) {
- count = i;
- goto fin;
- }
- break;
- default:
- xlbadtype(seq); break;
- }
-
- xlpop(); /* not found */
- return(NIL);
-
- fin: /* found */
- xlpop();
- return (cvfixnum(count));
- }
-
- /* xsearch -- search function */
-
- LVAL xsearch()
- {
- LVAL seq1, seq2, fcn, temp1, temp2;
- long start1, start2, end1, end2, len1, len2;
- long i,j;
- int tresult,typ1, typ2;
-
- /* get the sequences */
- seq1 = xlgetarg();
- len1 = getlength(seq1);
- seq2 = xlgetarg();
- len2 = getlength(seq2);
-
- /* test/test-not args? */
- xltest(&fcn,&tresult);
-
- /* check for start/end keys */
- getseqbounds(&start1,&end1,len1,&k_1start,&k_1end);
- getseqbounds(&start2,&end2,len2,&k_2start,&k_2end);
-
- if (end2 - 1 + (start1 - end1) > len2) {
- end2 = len2 + 1 - (start1 - end1);
- if (end2 < start2) end2 = start2;
- }
-
- len1 = end1 - start1; /* calc lengths of sequences to test */
-
- typ1 = ntype(seq1);
- typ2 = ntype(seq2);
-
- xlstkcheck(1);
- xlprotect(fcn);
-
- if (typ1 == CONS) { /* skip leading section of sequence 1 if a cons */
- j = start1;
- while (j--) seq1 = cdr(seq1);
- }
-
- if (typ2 == CONS) { /* second string is cons */
- i = start2; /* skip leading section of string 2 */
- while (start2--) seq2 = cdr(seq2);
-
- for (;i<end2;i++) {
- temp2 = seq2;
- if (typ1 == CONS) {
- temp1 = seq1;
- for (j = start1; j < end1; j++) {
- if (dotest2(car(temp1),car(temp2),fcn) != tresult)
- goto next1;
- temp1 = cdr(temp1);
- temp2 = cdr(temp2);
- }
- }
- else {
- for (j = start1; j < end1; j++) {
- if (dotest2(typ1 == VECTOR ? getelement(seq1,j)
- : cvchar(seq1->n_string[j]),
- car(temp2), fcn) != tresult)
- goto next1;
- temp2 = cdr(temp2);
- }
- }
- xlpop();
- return cvfixnum(i);
- next1: /* continue */
- seq2 = cdr(seq2);
- }
- }
-
- else for (i = start2; i < end2 ; i++) { /* second string is array/string */
- if (typ1 == CONS) {
- temp1 = seq1;
- for (j = 0; j < len1; j++) {
- if (dotest2(car(temp1),
- typ2 == VECTOR ? getelement(seq2,i+j)
- : cvchar(seq2->n_string[i+j]),
- fcn) != tresult)
- goto next2;
- temp1 = cdr(temp1);
- }
- }
- else for (j=start1; j < end1; j++) {
- if (dotest2(typ1 == VECTOR ? getelement(seq1,j)
- : cvchar(seq1->n_string[j]),
- typ2 == VECTOR ? getelement(seq2,i+j-start1)
- : cvchar(seq2->n_string[i+j-start1]),
- fcn) != tresult)
- goto next2;
- }
- xlpop();
- return cvfixnum(i);
- next2:; /* continue */
- }
-
- xlpop();
- return (NIL); /*no match*/
-
- }
-
-
- END OF PART 2
-
-
-