|
|
1.1 root 1: #ifndef lint
2: static char *rcsid =
3: "$Header: lam8.c,v 1.17 87/12/14 18:48:09 sklower Exp $";
4: #endif
5:
6: /* -[Thu Sep 29 22:24:10 1983 by jkf]-
7: * lam8.c $Locker: $
8: * lambda functions
9: *
10: * (c) copyright 1982, Regents of the University of California
11: */
12:
13: #include "global.h"
14: #include <sys/types.h>
15: #include <sys/stat.h>
16: #include "frame.h"
17:
18: /* various functions from the c math library */
19: double sin(),cos(),asin(),acos(),atan2(),sqrt(), log(), exp();
20: extern int current;
21:
22: lispval Imath(func)
23: double (*func)();
24: {
25: register lispval handy;
26: register double res;
27: chkarg(1,"Math functions");
28:
29: switch(TYPE(handy=lbot->val)) {
30: case INT: res = func((double)handy->i);
31: break;
32:
33: case DOUB: res = func(handy->r);
34: break;
35:
36: default: error("Non fixnum or flonum to math function",FALSE);
37: }
38: handy = newdoub();
39: handy->r = res;
40: return(handy);
41: }
42: lispval Lsin()
43: {
44: return(Imath(sin));
45: }
46:
47: lispval Lcos()
48: {
49: return(Imath(cos));
50: }
51:
52: lispval Lasin()
53: {
54: return(Imath(asin));
55: }
56:
57: lispval Lacos()
58: {
59: return(Imath(acos));
60: }
61:
62: lispval Lsqrt()
63: {
64: return(Imath(sqrt));
65: }
66: lispval Lexp()
67: {
68: return(Imath(exp));
69: }
70:
71: lispval Llog()
72: {
73: return(Imath(log));
74: }
75:
76: /* although we call this atan, it is really atan2 to the c-world,
77: that is, it takes two args
78: */
79: lispval Latan()
80: {
81: register lispval arg;
82: register double arg1v;
83: register double res;
84: chkarg(2,"arctan");
85:
86: switch(TYPE(arg=lbot->val)) {
87:
88: case INT: arg1v = (double) arg->i;
89: break;
90:
91: case DOUB: arg1v = arg->r;
92: break;
93:
94: default: error("Non fixnum or flonum arg to atan2",FALSE);
95: }
96:
97: switch(TYPE(arg = (lbot+1)->val)) {
98:
99: case INT: res = atan2(arg1v,(double) arg->i);
100: break;
101:
102: case DOUB: res = atan2(arg1v, arg->r);
103: break;
104:
105: default: error("Non fixnum or flonum to atan2",FALSE);
106: }
107: arg = newdoub();
108: arg->r = res;
109: return(arg);
110: }
111:
112: /* (random) returns a fixnum in the range -2**30 to 2**30 -1
113: (random fixnum) returns a fixnum in the range 0 to fixnum-1
114: */
115: lispval
116: Lrandom()
117: {
118: register int curval;
119: float pow();
120:
121: curval = rand(); /* get numb from 0 to 2**31-1 */
122:
123: if(np==lbot) return(inewint(curval-(int)pow((double)2,(double)30)));
124:
125: if((TYPE(lbot->val) != INT)
126: || (lbot->val->i <= 0)) errorh1(Vermisc,"random: non fixnum arg:",
127: nil, FALSE, 0, lbot->val);
128:
129: return(inewint(curval % lbot->val->i ));
130:
131: }
132: lispval
133: Lmakunb()
134: {
135: register lispval work;
136:
137: chkarg(1,"makunbound");
138: work = lbot->val;
139: if(work==nil || (TYPE(work)!=ATOM))
140: return(work);
141: work->a.clb = CNIL;
142: return(work);
143: }
144:
145: lispval
146: Lfseek()
147: {
148:
149: FILE *f;
150: long offset, whence;
151: lispval retp;
152:
153: chkarg(3,"fseek"); /* Make sure there are three arguments*/
154:
155: f = lbot->val->p; /* Get first argument into f */
156: if (TYPE(lbot->val)!=PORT) /* Check type of first */
157: error("fseek: First argument must be a port.",FALSE);
158:
159: offset = lbot[1].val->i; /* Get second argument */
160: if (TYPE(lbot[1].val)!=INT)
161: error("fseek: Second argument must be an integer.",FALSE);
162:
163: whence = lbot[2].val->i; /* Get last arg */
164: if (TYPE(lbot[2].val)!=INT)
165: error("fseek: Third argument must be an integer.",FALSE);
166:
167: if (fseek(f, offset, (int)whence) == -1)
168: error("fseek: Illegal parameters.",FALSE);
169:
170: retp = inewint(ftell(f));
171:
172: return((lispval) retp);
173: }
174:
175: /* function hashtabstat : return list of number of members in each bucket */
176: lispval Lhashst()
177: {
178: register lispval handy,cur;
179: register struct atom *pnt;
180: int i,cnt;
181: extern int hashtop;
182: Savestack(3);
183:
184: handy = newdot();
185: protect(handy);
186: cur = handy;
187: for(i = 0; i < hashtop; i++)
188: {
189: pnt = hasht[i];
190: for(cnt = 0; pnt != (struct atom *) CNIL ; pnt=pnt->hshlnk , cnt++);
191: cur->d.cdr = newdot();
192: cur = cur->d.cdr;
193: cur->d.car = inewint(cnt);
194: }
195: cur->d.cdr = nil;
196: Restorestack();
197: return(handy->d.cdr);
198: }
199:
200:
201: /* Lctcherr
202: this routine should only be called by the unwind protect simulation
203: lisp code
204: It is called after an unwind-protect frame has been entered and
205: evalated and we want to get on with the error or throw
206: We only handle the case where there are 0 to 2 extra arguments to the
207: error call.
208: */
209: lispval
210: Lctcherr()
211: {
212: register lispval handy;
213: lispval type,messg,valret,contuab,uniqid,datum1,datum2;
214:
215: chkarg(1,"I-throw-err");
216:
217: handy = lbot->val;
218:
219: if(TYPE(handy->d.car) == INT)
220: { /* continuing a non error (throw,reset, etc) */
221: Inonlocalgo((int)handy->d.car->i,
222: handy->d.cdr->d.car,
223: handy->d.cdr->d.cdr->d.car);
224: /* NOT REACHED */
225: }
226:
227: if(handy->d.car != nil)
228: {
229: errorh1(Vermisc,"I-do-throw: first element not fixnum or nil",
230: nil,FALSE,0,handy);
231: }
232:
233: /* decode the arg list */
234: handy = handy->d.cdr;
235: type = handy->d.car;
236: handy = handy->d.cdr;
237: messg = handy->d.car;
238: handy = handy->d.cdr;
239: valret = handy->d.car;
240: handy = handy->d.cdr;
241: contuab = handy->d.car;
242: handy = handy->d.cdr;
243: uniqid = handy->d.car;
244: handy = handy->d.cdr;
245:
246: /* if not extra args */
247: if(handy == nil)
248: {
249: errorh(type,messg->a.pname,valret,(int)contuab->i,(int)uniqid->i);
250: }
251: datum1 = handy->d.car;
252: handy = handy->d.cdr;
253:
254: /* if one extra arg */
255: if(handy == nil)
256: {
257: errorh1(type,messg->a.pname,valret,(int)contuab->i,(int)uniqid->i,datum1);
258: }
259:
260: /* if two or more extra args, just use first 2 */
261: datum2 = handy->d.car;
262: errorh2(type,messg->a.pname,valret,(int)contuab->i,(int)uniqid->i,datum1,datum2);
263: }
264:
265: /*
266: * (*makhunk '<fixnum>)
267: * <fixnum>
268: * Create a hunk of size 2 . <fixnum> must be between 0 and 6.
269: *
270: */
271:
272: lispval
273: LMakhunk()
274: {
275: register int hsize, hcntr;
276: register lispval result;
277:
278: chkarg(1,"Makehunk");
279: if (TYPE(lbot->val)==INT)
280: {
281: hsize = lbot->val->i; /* size of hunk (0-6) */
282: if ((hsize >= 0) && (hsize <= 6))
283: {
284: result = newhunk(hsize);
285: hsize = 2 << hsize; /* size of hunk (2-128) */
286: for (hcntr = 0; hcntr < hsize; hcntr++)
287: result->h.hunk[hcntr] = hunkfree;
288: }
289: else
290: error("*makhunk: Illegal hunk size", FALSE);
291: return(result);
292: }
293: else
294: error("*makhunk: First arg must be an fixnum",FALSE);
295: /* NOTREACHED */
296: }
297:
298: /*
299: * (cxr '<fixnum> '<hunk>)
300: * Returns the <fixnum>'th element of <hunk>
301: *
302: */
303: lispval
304: Lcxr()
305: {
306: register lispval temp;
307:
308: chkarg(2,"cxr");
309: if (TYPE(lbot->val)!=INT)
310: error("cxr: First arg must be a fixnum", FALSE);
311: else
312: {
313: if (! HUNKP(lbot[1].val))
314: error("cxr: Second arg must be a hunk", FALSE);
315: else
316: if ( (lbot->val->i >= 0) &&
317: (lbot->val->i < (2 << HUNKSIZE(lbot[1].val))) )
318: {
319: temp = lbot[1].val->h.hunk[lbot->val->i];
320: if (temp != hunkfree)
321: return(temp);
322: else
323: error("cxr: Arg outside of hunk range",
324: FALSE);
325: }
326: else
327: error("cxr: Arg outside of hunk range", FALSE);
328: }
329: /* NOTREACHED */
330: }
331:
332: /*
333: * (rplacx '<fixnum> '<hunk> '<expr>)
334: * Replaces the <fixnum>'th element of <hunk> with <expr>.
335: *
336: */
337: lispval
338: Lrplcx()
339: {
340: lispval *handy;
341: chkarg(3,"rplacx");
342: if (TYPE(lbot->val)!=INT)
343: error("rplacx: First arg must be a fixnum", FALSE);
344: else
345: {
346: if (! HUNKP(lbot[1].val))
347: error("rplacx: Second arg must be a hunk", FALSE);
348: else
349: {
350: if ( (lbot->val->i >= 0) &&
351: (lbot->val->i < (2 << HUNKSIZE(lbot[1].val))) )
352: {
353: if (*(handy = &(lbot[1].val->h.hunk[lbot->val->i]))
354: != hunkfree)
355: *handy = lbot[2].val;
356: else
357: error("rplacx: Arg outside hunk range", FALSE);
358: }
359: else
360: error("rplacx: Arg outside hunk range", FALSE);
361: }
362: }
363: return(lbot[1].val);
364: }
365:
366: /*
367: * (*rplacx '<fixnum> '<hunk> '<expr>)
368: * Replaces the <fixnum>'th element of <hunk> with <expr>. This is the
369: * same as (rplacx ...) except with this function you can replace EMPTY's.
370: *
371: */
372: lispval
373: Lstarrpx()
374: {
375: chkarg(3,"*rplacx");
376: if (TYPE(lbot->val)!=INT)
377: error("*rplacx: First arg must be a fixnum", FALSE);
378: else
379: {
380: if (! HUNKP(lbot[1].val))
381: error("*rplacx: Second arg must be a hunk", FALSE);
382: else
383: {
384: if ( (lbot->val->i >= 0) &&
385: (lbot->val->i < (2 << HUNKSIZE(lbot[1].val))) )
386: lbot[1].val->h.hunk[lbot->val->i] = lbot[2].val;
387: else
388: error("*rplacx: Arg outside hunk range", FALSE);
389: }
390: }
391: return(lbot[1].val);
392: }
393:
394: /*
395: * (hunksize '<hunk>)
396: * Returns the size of <hunk>
397: *
398: */
399: lispval
400: Lhunksize()
401: {
402: register int size,i;
403:
404: chkarg(1,"hunksize");
405: if (HUNKP(lbot->val))
406: {
407: size = 2 << HUNKSIZE(lbot->val);
408: for (i = size-1; i >= 0; i--)
409: {
410: if (lbot->val->h.hunk[i] != hunkfree)
411: {
412: size = i + 1;
413: break;
414: }
415: }
416: return( inewint(size) );
417: }
418: else
419: error("hunksize: First argument must me a hunk", FALSE);
420: /* NOTREACHED */
421: }
422:
423: /*
424: * (hunk-to-list 'hunk) returns a list of the hunk elements
425: */
426: lispval
427: Lhtol()
428: {
429: register lispval handy,retval,last;
430: register int i;
431: int size;
432: Savestack(4);
433:
434: chkarg(1,"hunk-to-list");
435: handy = lbot->val;
436: if(!(HUNKP(handy)))
437: errorh1(Vermisc,"hunk-to-list: non hunk argument: ", nil,0,FALSE,
438: handy);
439: size = 2 << HUNKSIZE(handy);
440: retval = nil;
441: for(i=0 ; i < size ; i++)
442: {
443: if(handy->h.hunk[i] != hunkfree)
444: {
445: if(retval==nil)
446: {
447: protect(retval=newdot());
448: last = retval;
449: }
450: else {
451: last = (last->d.cdr = newdot());
452: }
453: last->d.car = handy->h.hunk[i];
454: }
455: else break;
456: }
457: Restorestack();
458: return(retval);
459: }
460:
461: /*
462: * (fileopen filename mode)
463: * open a file for read, write, or append the arguments can be either
464: * strings or atoms.
465: */
466: lispval
467: Lfileopen()
468: {
469: FILE *port;
470: register lispval name;
471: register lispval mode;
472: register char *namech;
473: register char *modech;
474:
475: chkarg(2,"fileopen");
476: name = lbot->val;
477: mode = lbot[1].val;
478:
479: namech = (char *) verify(name,"fileopen:args must be atoms or strings");
480: modech = (char *) verify(mode,"fileopen:args must be atoms or strings");
481:
482: while (modech[0] != 'r' && modech[0] != 'w' && modech[0] != 'a')
483: {
484: mode = errorh(Vermisc,"Modes are only r, w, a.",nil,TRUE,31);
485: modech = (char *) verify(mode,"fileopen:args must be atoms or strings");
486: }
487:
488: while ((port = fopen(namech, modech)) == NULL)
489: {
490: name = errorh1(Vermisc,"Unable to open file.",nil,TRUE,31,name);
491: namech = (char *) verify(name,"fileopen:args must be atoms or strings");
492: }
493: /* xports is a FILE *, cc complains about adding pointers */
494:
495: ioname[PN(port)] = (lispval) inewstr(namech); /* remember name */
496: return(P(port));
497: }
498:
499: /*
500: * (*invmod '<number> '<modulus>)
501: * This function returns the inverse of <number>
502: * mod <modulus> in balanced representation
503: * It is used in vaxima as a speed enhancement.
504: */
505:
506: static lispval
507: Ibalmod(invmodp)
508: {
509: register long mod_div_2, number, modulus;
510:
511: chkarg(2,"*mod");
512: if ((TYPE(lbot->val) == INT) && (TYPE(lbot[1].val) == INT))
513: {
514: modulus = lbot[1].val->i;
515: if(invmodp) number = invmod(lbot->val->i , modulus);
516: else number = lbot->val->i % modulus;
517: mod_div_2 = modulus / 2;
518: if (number < 0)
519: {
520: if (number < (-mod_div_2))
521: number += modulus;
522: }
523: else
524: {
525: if (number > mod_div_2)
526: number -= modulus;
527: }
528: return( inewint(number) );
529: }
530: else
531: error("*mod: Arguments must be fixnums", FALSE);
532: /* NOTREACHED */
533: }
534:
535: invmod (n,modulus)
536: long n , modulus;
537:
538: {
539: long a1,a2,a3,y1,y2,y3,q;
540:
541: a1 = modulus;
542: a2 = n;
543: y1 = 0;
544: y2= 1;
545: goto step3;
546: step2:
547: q = a1 /a2; /*truncated quotient */
548: a3= mmuladd(modulus-a2,q,a1,modulus);
549: y3= mmuladd(modulus-y2,q,y1,modulus);
550: a1 = a2;
551: a2= a3;
552: y1=y2;
553: y2=y3;
554: step3:
555: if (a2==0) error("invmod: inverse of zero divisor",TRUE);
556: else if (a2 != 1) goto step2;
557: else return (y2);
558: /* NOTREACHED */
559: }
560:
561: lispval
562: Lstarinvmod()
563: {
564: return(Ibalmod(TRUE));
565: }
566:
567: /*
568: * (*mod '<number> '<modulus>)
569: * This function returns <number> mod <modulus> (for balanced modulus).
570: * It is used in vaxima as a speed enhancement.
571: */
572: lispval
573: LstarMod()
574: {
575: return(Ibalmod(FALSE));
576: }
577:
578: lispval
579: Llsh()
580: {
581: register struct argent *mylbot = lbot;
582: int val,shift;
583:
584: chkarg(2,"lsh");
585: if((TYPE(mylbot->val) != INT) || (TYPE(mylbot[1].val) != INT))
586: errorh2(Vermisc,
587: "Non ints to lsh",
588: nil,FALSE,0,mylbot->val,mylbot[1].val);
589: val = mylbot[0].val->i;
590: shift = mylbot[1].val->i;
591: if(shift < -32 || shift > 32)
592: return(inewint(0));
593: if (shift < 0)
594: val = val >> -shift;
595: else
596: val = val << shift;
597: if((val < 0) && (shift < 0))
598: { /* special case: the vax doesn't have a logical shift
599: instruction, so we must zero out the ones which
600: will propogate from the sign position
601: */
602: return(inewint ( val & ~(0x80000000 >> -(shift+1))));
603: }
604: else return( inewint(val));
605: }
606:
607: /* very temporary function to test the validity of the bind stack */
608:
609: bndchk()
610: {
611: register struct nament *npt;
612: register lispval in2;
613:
614: in2 = inewint(200);
615: for(npt=orgbnp; npt < bnp; npt++)
616: { if((int) npt->atm < (int) in2) abort();
617: }
618: }
619:
620: /*
621: * formatted printer for lisp data
622: * use: (cprintf formatstring datum [port])
623: */
624: lispval
625: Lcprintf()
626: {
627: FILE *p;
628: char *fstrng;
629: lispval v;
630: if(np-lbot == 2) protect(nil); /* write to standard output port */
631: chkarg(3,"cprintf");
632:
633: fstrng = (char *)verify(lbot->val,"cprintf: first arg not string or symbol");
634:
635: p = okport(lbot[2].val,okport(Vpoport->a.clb,poport));
636:
637: switch(TYPE(v=lbot[1].val)) {
638:
639: case INT: fprintf(p,fstrng,v->i);
640: break;
641:
642: case DOUB: fprintf(p,fstrng,v->r);
643: break;
644:
645: case ATOM: fprintf(p,fstrng,v->a.pname);
646: break;
647:
648: case STRNG:fprintf(p,fstrng,v);
649: break;
650:
651: default: error("cprintf: Illegal second argument",FALSE);
652: };
653:
654: return(lbot[1].val);
655: }
656:
657:
658: /*
659: * C style sprintf: (sprintf "format" {<arg-list>})
660: *
661: * This function stacks the arguments onto the C stack in reverse
662: * order and then calls sprintf with one argument...This is what the
663: * C compiler does, so it works just fine. The return value is the
664: * string that is the result of the sprintf.
665: */
666: lispval
667: Lsprintf()
668: {
669: register struct argent *argp;
670: register int j;
671: char sbuf[600]; /* better way? */
672: Keepxs();
673:
674: if (np-lbot == 0) {
675: argerr("sprintf");
676: }
677: if (TYPE(lbot->val)==STRNG || TYPE(lbot->val)==INT) {
678: for (argp = np-1; argp >= lbot; argp--) {
679: switch(TYPE(argp->val)) {
680: case ATOM:
681: stack((long)argp->val->a.pname);
682: break;
683:
684: case DOUB:
685: #ifndef SPISFP
686: stack(argp->val->r);
687: #else
688: {double rr = argp->val->r;
689: stack(((long *)&rr)[1]);
690: stack(((long *)&rr)[0]);}
691: #endif
692: break;
693:
694: case INT:
695: stack(argp->val->i);
696: break;
697:
698: case STRNG:
699: stack((long)argp->val);
700: break;
701:
702: default:
703: error("sprintf: Bad data type to sprintf",
704: FALSE);
705: }
706: }
707: sprintf(sbuf);
708: for (j = 0; j < np-lbot; j++)
709: unstack();
710: } else
711: error("sprintf: First arg must be an atom or string", FALSE);
712: Freexs();
713: return ((lispval) inewstr(sbuf));
714: }
715:
716: lispval
717: Lprobef()
718: {
719: char *name;
720: chkarg(1,"probef");
721:
722: name = (char *)verify(lbot->val,"probef: not symbol or string arg ");
723:
724: if(access(name,0) == 0) return(tatom);
725: else return(nil);
726: }
727:
728: lispval
729: Lsubstring()
730: { register char *name;
731: register lispval index,length;
732: int restofstring = FALSE;
733: int len,ind,reallen;
734:
735: switch (np-lbot)
736: {
737: case 2: restofstring = TRUE;
738: break;
739:
740: case 3: break;
741:
742: default: chkarg(3,"substring");
743: }
744:
745: name = (char *)verify(lbot[0].val,"substring: not symbol or string arg ");
746:
747: while (TYPE(index = lbot[1].val) != INT)
748: { lbot[1].val = errorh1(Vermisc,"substring: non integer index ",nil,
749: TRUE,0,index);
750: }
751:
752: len = strlen(name);
753: ind = index->i;
754:
755: if(ind < 0) ind = len+1 + ind;
756:
757: if(ind < 1 || ind > len) return(nil); /*index out of bounds*/
758: if(restofstring) return((lispval)inewstr(name+ind-1));
759:
760: while (TYPE(length = lbot[2].val) != INT)
761: { lbot[2].val = errorh1(Vermisc,"substring: not integer length ",nil,
762: TRUE,0,length);
763: }
764:
765: if((reallen = length->i ) < 0 || (reallen + ind) > len)
766: return((lispval)inewstr(name+ind-1));
767:
768: strncpy(strbuf,name+ind-1,reallen);
769: strbuf[reallen] = '\0';
770: return((lispval)newstr(0));
771: }
772:
773: /*
774: * This is substringn
775: */
776: lispval
777: Lsstrn()
778: {
779: register char *name;
780: register int len,ind,reallen;
781: lispval index,length;
782: int restofstring = FALSE;
783: Savestack(4);
784:
785: if((np-lbot) == 2) restofstring = TRUE;
786: else { chkarg(3,"substringn");}
787:
788: name = (char *) verify(lbot[0].val,"substringn: non symbol or string arg ");
789:
790: while (TYPE(index = lbot[1].val) != INT)
791: { lbot[1].val = errorh1(Vermisc,"substringn: non integer index ",nil,
792: TRUE,0,index);
793: }
794:
795: if(!restofstring)
796: {
797: while (TYPE(length = lbot[2].val) != INT)
798: { lbot[2].val = errorh1(Vermisc,"substringn: not integer length ",
799: nil, TRUE,0,length);
800: }
801: reallen = length->i;
802: }
803: else reallen = -1;
804:
805: len = strlen(name);
806: ind = index->i;
807: if(ind < 0) ind = len + 1 + ind;
808: if( ind < 1 || ind > len) return(nil);
809:
810: if(reallen == 0)
811: return((lispval)inewint(*(name + ind - 1)));
812: else {
813: char *pnt = name + ind - 1;
814: char *last = name + len -1;
815: lispval cur,start;
816:
817: protect(cur = start = newdot());
818: cur->d.car = inewint(*pnt);
819: while(++pnt <= last && --reallen != 0)
820: {
821: cur->d.cdr = newdot();
822: cur = cur->d.cdr;
823: cur->d.car = inewint(*pnt);
824: }
825: Restorestack();
826: return(start);
827: }
828:
829: }
830:
831:
832: /*
833: * (character-index 'string 'char)
834: * return the index of char in the string.
835: * return nil if not present
836: * char can be a fixnum (representing a character)
837: * a symbol or string (in which case the first char is used)
838: *
839: */
840:
841: #if os_unix_ts
842: #define index strchr
843: #endif
844: lispval
845: Lcharindex()
846: {
847: register char *string;
848: register char ch;
849: char *str2;
850:
851: chkarg(2,"character-index");
852:
853:
854: string = (char *)verify(lbot[0].val,"character-index: non symbol or string arg ");
855: if(TYPE(lbot[1].val) == INT)
856: ch = (char) lbot[1].val->i;
857: else {
858: str2 = (char *) verify(lbot[1].val,"character-index: bad first argument ");
859: ch = *str2; /* grab the first character */
860: }
861:
862: if((str2 = (char *) index(string,ch)) == 0) return(nil); /* not there */
863: /* return 1-based index of character */
864: return(inewint(str2-string+1));
865: }
866:
867:
868: lispval Ipurcopy();
869:
870:
871: lispval
872: Lpurcopy()
873: {
874: chkarg(1,"purcopy");
875: return(Ipurcopy(lbot[0].val));
876: }
877:
878: lispval
879: Ipurcopy(handy)
880: lispval handy;
881: {
882: extern int *beginsweep;
883: register lispval retv, curv, lv;
884: int i,size;
885:
886: switch(TYPE(handy)) {
887:
888: case DTPR:
889: retv = curv = pnewdot();
890: lv = handy;
891: while(TRUE)
892: {
893: curv->d.car = Ipurcopy(lv->d.car);
894: if(TYPE(lv = lv->d.cdr) == DTPR)
895: {
896: curv->d.cdr = pnewdot();
897: curv = curv->d.cdr;
898: }
899: else {
900: curv->d.cdr = Ipurcopy(lv);
901: break;
902: }
903: }
904: return(retv);
905:
906: case SDOT:
907: retv = curv = pnewsdot();
908: lv = handy;
909: while(TRUE)
910: {
911: curv->s.I = lv->s.I;
912: if(lv->s.CDR == (lispval) 0) break;
913: lv = lv->s.CDR;
914: curv->s.CDR = pnewdot();
915: curv = curv->s.CDR;
916: }
917: curv->s.CDR = 0;
918: return(retv);
919:
920: case INT:
921: if((int *)handy < beginsweep) return(handy);
922: retv = pnewint();
923: retv->i = handy->i;
924: return(retv);
925:
926: case DOUB:
927: retv = pnewdb();
928: retv->r = handy->r;
929: return(retv);
930:
931: case HUNK2:
932: i = 0;
933: goto hunkit;
934:
935: case HUNK4:
936: i = 1;
937: goto hunkit;
938:
939: case HUNK8:
940: i = 2;
941: goto hunkit;
942:
943: case HUNK16:
944: i = 3;
945: goto hunkit;
946:
947: case HUNK32:
948: i = 4;
949: goto hunkit;
950:
951: case HUNK64:
952: i = 5;
953: goto hunkit;
954:
955: case HUNK128:
956: i = 6;
957:
958: hunkit:
959: retv = pnewhunk(i);
960: size = 2 << i ; /* number of elements to copy over */
961: for( i = 0; i < size ; i++)
962: {
963: retv->h.hunk[i] = Ipurcopy(handy->h.hunk[i]);
964: }
965: return(retv);
966:
967:
968:
969: case STRNG:
970: #ifdef GCSTRINGS
971: { extern char purepage[];
972:
973: if(purepage[((int)handy)>>9]==0)
974: return((lispval)pinewstr((char *)handy));}
975:
976: #endif
977: case ATOM:
978: case BCD:
979: case PORT:
980: return(handy); /* We don't want to purcopy these, yet
981: * it won't hurt if we don't mark them
982: * since they either aren't swept or
983: * will be marked in a special way
984: */
985: case ARRAY:
986: error("purcopy: can't purcopy array structures",FALSE);
987:
988: default:
989: error(" bad type to purcopy ",FALSE);
990: /* NOTREACHED */
991: }
992: }
993:
994: /*
995: * Lpurep returns t if the given arg is in pure space
996: */
997: lispval
998: Lpurep()
999: {
1000: lispval Ipurep();
1001:
1002: chkarg(1,"purep");
1003: return(Ipurep(lbot->val));
1004: }
1005:
1006:
1007:
1008: /* vector functions */
1009: lispval newvec(), nveci(), Inewvector();
1010:
1011: /* vector creation and initialization functions */
1012: lispval
1013: Lnvec()
1014: {
1015: return(Inewvector(3));
1016: }
1017:
1018: lispval
1019: Lnvecb()
1020: {
1021: return(Inewvector(0));
1022: }
1023:
1024: lispval
1025: Lnvecw()
1026: {
1027: return(Inewvector(1));
1028: }
1029:
1030: lispval
1031: Lnvecl()
1032: {
1033: return(Inewvector(2));
1034: }
1035:
1036: /*
1037: * (new-vector 'x_size ['g_fill] ['g_prop])
1038: * class = 0: byte \
1039: * = 1: word > immediate
1040: * = 2: long /
1041: * = 3: long
1042: */
1043: lispval
1044: Inewvector(class)
1045: {
1046: register int i;
1047: register lispval handy;
1048: register lispval *handy2;
1049: char *chandy;
1050: short *whandy;
1051: long *lhandy;
1052: lispval sizearg, fillarg, proparg;
1053: int size, vsize;
1054:
1055: fillarg = proparg = nil;
1056:
1057: switch(np-lbot) {
1058: case 3: proparg = lbot[2].val;
1059: case 2: fillarg = lbot[1].val;
1060: case 1: sizearg = lbot[0].val;
1061: break;
1062: default: argerr("new-vector");
1063: }
1064:
1065: while((TYPE(sizearg) != INT) || sizearg->i < 0)
1066: sizearg = errorh1(Vermisc,"new-vector: bad size for vector ",nil,
1067: TRUE,0,sizearg);
1068: size = sizearg->i;
1069: switch(class)
1070: {
1071: case 0: vsize = size * sizeof(char);
1072: break;
1073: case 1: vsize = size * sizeof(short);
1074: break;
1075: default: vsize = size * sizeof(long);
1076: break;
1077: }
1078:
1079: if(class != 3) handy = nveci(vsize);
1080: else handy = newvec(vsize);
1081:
1082: switch(class)
1083: {
1084: case 0: chandy = (char *)handy;
1085: for(i = 0 ; i < size ; i++) *chandy++ = (char) (fillarg->i);
1086: break;
1087:
1088: case 1: whandy = (short *)handy;
1089: for(i = 0 ; i < size ; i++) *whandy++ = (short) (fillarg->i);
1090: break;
1091:
1092: case 2: lhandy = (long *)handy;
1093: for(i = 0 ; i < size ; i++) *lhandy++ = (fillarg->i);
1094: break;
1095:
1096: case 3: handy2 = (lispval *)handy;
1097: for(i = 0 ; i < size ; i++) *handy2++ = fillarg;
1098: break;
1099: }
1100: handy->v.vector[-1] = proparg;
1101: return(handy);
1102: }
1103:
1104: lispval
1105: Lvectorp()
1106: {
1107: chkarg(1,"vectorp");
1108: if(TYPE(lbot->val) == VECTOR) return(tatom);
1109: else return(nil);
1110: }
1111:
1112: lispval
1113: Lpvp()
1114: {
1115: chkarg(1,"vectorip");
1116: if(TYPE(lbot->val) == VECTORI) return(tatom);
1117: else return(nil);
1118: }
1119:
1120: /*
1121: * int:vref vector[i] index class
1122: * class = 0: byte immed, 1: word immed, 2: long immed, 3: long
1123: *
1124: * also do C style dereferencing of pointers. This is a temporary
1125: * hack until we decide if we can live without it:
1126: * class = 4: char, 5: short, 6: long, 7: float, 8: double
1127: */
1128: lispval
1129: LIvref()
1130: {
1131: register lispval vect;
1132: register int index;
1133: int class;
1134: double value;
1135:
1136: chkarg(3,"int:vref");
1137: vect = lbot[0].val;
1138: index = lbot[1].val->i;
1139: class = lbot[2].val->i;
1140: switch(class)
1141: {
1142: case 0: return(inewint(vect->vb.vectorb[index]));
1143: case 1: return(inewint(vect->vw.vectorw[index]));
1144: case 2: return(inewint(vect->vl.vectorl[index]));
1145: case 3: return(vect->v.vector[index]);
1146: case 4: return(inewint(*(char *)(vect->i+index)));
1147: case 5: return(inewint(*(short *)(vect->i+index)));
1148: case 6: return(inewint(*(long *)(vect->i+index)));
1149: case 7: value = *(float *) (vect->i+index);
1150: vect = newdoub();
1151: vect->r = value;
1152: return(vect);
1153: case 8: value = *(double *) (vect->i+index);
1154: vect = newdoub();
1155: vect->r = value;
1156: return(vect);
1157: }
1158: error("int:vref: impossible class detected",FALSE);
1159: /* NOTREACHED */
1160: }
1161:
1162: /*
1163: * int:vset vector[i] index value class
1164: * class = 0: byte immed, 1: word immed, 2: long immed, 3: long
1165: */
1166: lispval
1167: LIvset()
1168: {
1169: register lispval vect,value;
1170: register int index;
1171: int class;
1172:
1173: chkarg(4,"int:vset");
1174: vect = lbot[0].val;
1175: index = lbot[1].val->i;
1176: value = lbot[2].val;
1177: class = lbot[3].val->i;
1178: switch(class)
1179: {
1180: case 0: vect->vb.vectorb[index] = (char)value->i;
1181: break;
1182: case 1: vect->vw.vectorw[index] = (short)value->i;
1183: break;
1184: case 2: vect->vl.vectorl[index] = value->i;
1185: break;
1186: case 3: vect->v.vector[index] = value;
1187: break;
1188: case 4: *(char *) (vect->i+index) = value->i;
1189: break;
1190: case 5: *(short *) (vect->i+index) = value->i;
1191: break;
1192: case 6: *(long *) (vect->i+index) = value->i;
1193: break;
1194: case 7: *(float *) (vect->i+index) = value->r;
1195: break;
1196: case 8: *(double *) (vect->i+index) = value->r;
1197: break;
1198: default:
1199: error("int:vref: impossible class detected",FALSE);
1200: }
1201: return(value);
1202: }
1203:
1204: /*
1205: * LIvsize == (int:vsize 'vector 'x_shift)
1206: * return the vsize field of the vector shifted right by x_shift
1207: */
1208: lispval
1209: LIvsize()
1210: {
1211: int typ;
1212:
1213: chkarg(2,"int:vsize");
1214: return(inewint((lbot[0].val->vl.vectorl[VSizeOff]) >> lbot[1].val->i));
1215: }
1216:
1217: lispval
1218: Lvprop()
1219: {
1220: int typ;
1221: chkarg(1,"vprop");
1222:
1223: if(((typ = TYPE(lbot->val)) != VECTOR) && (typ != VECTORI))
1224: errorh1(Vermisc,"vprop: non vector argument: ", nil, FALSE,0,
1225: lbot->val);
1226: return(lbot[0].val->v.vector[VPropOff]);
1227: }
1228:
1229:
1230: lispval
1231: Lvsp()
1232: {
1233: int typ;
1234: lispval vector, property;
1235: chkarg(2,"vsetprop");
1236:
1237: vector = lbot->val;
1238: property = lbot[1].val;
1239: typ = TYPE(vector);
1240:
1241: if(typ != VECTOR && typ !=VECTORI)
1242: errorh1(Vermisc,"vsetprop: non vector argument: ",
1243: nil,FALSE,0,vector);
1244: vector->v.vector[VPropOff] = property;
1245: return(property);
1246: }
1247:
1248:
1249: /* vecequal
1250: * check if the two vector arguments are 'equal'
1251: * this is called by equal which has already checked that
1252: * the arguments are vector
1253: */
1254: vecequal(v,w)
1255: lispval v,w;
1256: {
1257: int i;
1258: lispval vv, ww, ret;
1259: int vsize = (int) v->v.vector[VSizeOff];
1260: int wsize = (int) w->v.vector[VSizeOff];
1261: struct argent *oldlbot = lbot;
1262: lispval Lequal();
1263:
1264: if(vsize != wsize) return(FALSE);
1265:
1266: vsize /= sizeof(int); /* determine number of entries */
1267:
1268: for(i = 0 ; i < vsize ; i++)
1269: {
1270: vv = v->v.vector[i];
1271: ww = w->v.vector[i];
1272: /* avoid calling equal if they are eq */
1273: if(vv != ww)
1274: {
1275: lbot = np;
1276: protect(vv);
1277: protect(ww);
1278: ret = Lequal();
1279: np = lbot;
1280: lbot = oldlbot;
1281: if(ret == nil) return(FALSE);
1282: }
1283: }
1284: return(TRUE);
1285: }
1286:
1287: /* veciequal
1288: * check if the two vectori arguments are 'equal'
1289: * this is called by equal which has already checked that
1290: * the arguments are vector
1291: * Note: this would run faster if we did as many 'longword'
1292: * comparisons as possible and then did byte comparisons.
1293: * or if we used pointers instead of indexing.
1294: */
1295: veciequal(v,w)
1296: lispval v,w;
1297: {
1298: char vv, ww;
1299: int i;
1300: int vsize = (int) v->v.vector[VSizeOff];
1301: int wsize = (int) w->v.vector[VSizeOff];
1302:
1303: if(vsize != wsize) return(FALSE);
1304:
1305:
1306: for(i = 0 ; i < vsize ; i++)
1307: {
1308: if(v->vb.vectorb[i] != w->vb.vectorb[i]) return(FALSE);
1309: }
1310: return(TRUE);
1311: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.