|
|
1.1 root 1: #ifndef lint
2: static char *rcsid =
3: "$Header: lam8.c,v 1.9 83/09/12 14:16:52 sklower Exp $";
4: #endif
5:
6: /* -[Fri Aug 12 07:54:00 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: Lrplacx()
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( (lispval) (xports + (port - _iob)));
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], *sprintf(); /* 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: lispval Ipurcopy();
832:
833:
834: lispval
835: Lpurcopy()
836: {
837: chkarg(1,"purcopy");
838: return(Ipurcopy(lbot[0].val));
839: }
840:
841: lispval
842: Ipurcopy(handy)
843: lispval handy;
844: {
845: extern int *beginsweep;
846: register lispval retv, curv, lv;
847: int i,size;
848:
849: switch(TYPE(handy)) {
850:
851: case DTPR:
852: retv = curv = pnewdot();
853: lv = handy;
854: while(TRUE)
855: {
856: curv->d.car = Ipurcopy(lv->d.car);
857: if(TYPE(lv = lv->d.cdr) == DTPR)
858: {
859: curv->d.cdr = pnewdot();
860: curv = curv->d.cdr;
861: }
862: else {
863: curv->d.cdr = Ipurcopy(lv);
864: break;
865: }
866: }
867: return(retv);
868:
869: case SDOT:
870: retv = curv = pnewsdot();
871: lv = handy;
872: while(TRUE)
873: {
874: curv->s.I = lv->s.I;
875: if(lv->s.CDR == (lispval) 0) break;
876: lv = lv->s.CDR;
877: curv->s.CDR = pnewdot();
878: curv = curv->s.CDR;
879: }
880: curv->s.CDR = 0;
881: return(retv);
882:
883: case INT:
884: if((int *)handy < beginsweep) return(handy);
885: retv = pnewint();
886: retv->i = handy->i;
887: return(retv);
888:
889: case DOUB:
890: retv = pnewdoub();
891: retv->r = handy->r;
892: return(retv);
893:
894: case HUNK2:
895: i = 0;
896: goto hunkit;
897:
898: case HUNK4:
899: i = 1;
900: goto hunkit;
901:
902: case HUNK8:
903: i = 2;
904: goto hunkit;
905:
906: case HUNK16:
907: i = 3;
908: goto hunkit;
909:
910: case HUNK32:
911: i = 4;
912: goto hunkit;
913:
914: case HUNK64:
915: i = 5;
916: goto hunkit;
917:
918: case HUNK128:
919: i = 6;
920:
921: hunkit:
922: retv = pnewhunk(i);
923: size = 2 << i ; /* number of elements to copy over */
924: for( i = 0; i < size ; i++)
925: {
926: retv->h.hunk[i] = Ipurcopy(handy->h.hunk[i]);
927: }
928: return(retv);
929:
930:
931:
932: case STRNG:
933: #ifdef GCSTRINGS
934: { extern char purepage[];
935:
936: if(purepage[((int)handy)>>9]==0)
937: return((lispval)pinewstr((char *)handy));}
938:
939: #endif
940: case ATOM:
941: case BCD:
942: case PORT:
943: return(handy); /* We don't want to purcopy these, yet
944: * it won't hurt if we don't mark them
945: * since they either aren't swept or
946: * will be marked in a special way
947: */
948: case ARRAY:
949: error("purcopy: can't purcopy array structures",FALSE);
950:
951: default:
952: error(" bad type to purcopy ",FALSE);
953: /* NOTREACHED */
954: }
955: }
956:
957: /*
958: * Lpurep returns t if the given arg is in pure space
959: */
960: lispval
961: Lpurep()
962: {
963: lispval Ipurep();
964:
965: chkarg(1,"purep");
966: return(Ipurep(lbot->val));
967: }
968:
969:
970:
971: /* vector functions */
972: lispval newvec(), nveci(), Inewvector();
973:
974: /* vector creation and initialization functions */
975: lispval
976: Lnvec()
977: {
978: return(Inewvector(3));
979: }
980:
981: lispval
982: Lnvecb()
983: {
984: return(Inewvector(0));
985: }
986:
987: lispval
988: Lnvecw()
989: {
990: return(Inewvector(1));
991: }
992:
993: lispval
994: Lnvecl()
995: {
996: return(Inewvector(2));
997: }
998:
999: /*
1000: * (new-vector 'x_size ['g_fill] ['g_prop])
1001: * class = 0: byte \
1002: * = 1: word > immediate
1003: * = 2: long /
1004: * = 3: long
1005: */
1006: lispval
1007: Inewvector(class)
1008: {
1009: register int i;
1010: register lispval handy;
1011: register lispval *handy2;
1012: char *chandy;
1013: short *whandy;
1014: long *lhandy;
1015: lispval sizearg, fillarg, proparg;
1016: int size, vsize;
1017:
1018: fillarg = proparg = nil;
1019:
1020: switch(np-lbot) {
1021: case 3: proparg = lbot[2].val;
1022: case 2: fillarg = lbot[1].val;
1023: case 1: sizearg = lbot[0].val;
1024: break;
1025: default: argerr("new-vector");
1026: }
1027:
1028: while((TYPE(sizearg) != INT) || sizearg->i < 0)
1029: sizearg = errorh1(Vermisc,"new-vector: bad size for vector ",nil,
1030: TRUE,0,sizearg);
1031: size = sizearg->i;
1032: switch(class)
1033: {
1034: case 0: vsize = size * sizeof(char);
1035: break;
1036: case 1: vsize = size * sizeof(short);
1037: break;
1038: default: vsize = size * sizeof(long);
1039: break;
1040: }
1041:
1042: if(class != 3) handy = nveci(vsize);
1043: else handy = newvec(vsize);
1044:
1045: switch(class)
1046: {
1047: case 0: chandy = (char *)handy;
1048: for(i = 0 ; i < size ; i++) *chandy++ = (char) (fillarg->i);
1049: break;
1050:
1051: case 1: whandy = (short *)handy;
1052: for(i = 0 ; i < size ; i++) *whandy++ = (short) (fillarg->i);
1053: break;
1054:
1055: case 2: lhandy = (long *)handy;
1056: for(i = 0 ; i < size ; i++) *lhandy++ = (fillarg->i);
1057: break;
1058:
1059: case 3: handy2 = (lispval *)handy;
1060: for(i = 0 ; i < size ; i++) *handy2++ = fillarg;
1061: break;
1062: }
1063: handy->v.vector[-1] = proparg;
1064: return(handy);
1065: }
1066:
1067: lispval
1068: Lvectorp()
1069: {
1070: chkarg(1,"vectorp");
1071: if(TYPE(lbot->val) == VECTOR) return(tatom);
1072: else return(nil);
1073: }
1074:
1075: lispval
1076: Lpvp()
1077: {
1078: chkarg(1,"vectorip");
1079: if(TYPE(lbot->val) == VECTORI) return(tatom);
1080: else return(nil);
1081: }
1082:
1083: /*
1084: * int:vref vector[i] index class
1085: * class = 0: byte immed, 1: word immed, 2: long immed, 3: long
1086: */
1087: lispval
1088: LIvref()
1089: {
1090: register lispval vect;
1091: register int index;
1092: int class;
1093:
1094: chkarg(3,"int:vref");
1095: vect = lbot[0].val;
1096: index = lbot[1].val->i;
1097: class = lbot[2].val->i;
1098: switch(class)
1099: {
1100: case 0: return(inewint(vect->vb.vectorb[index]));
1101: case 1: return(inewint(vect->vw.vectorw[index]));
1102: case 2: return(inewint(vect->vl.vectorl[index]));
1103: case 3: return(vect->v.vector[index]);
1104: }
1105: error("int:vref: impossible class detected",FALSE);
1106: /* NOTREACHED */
1107: }
1108:
1109: /*
1110: * int:vset vector[i] index value class
1111: * class = 0: byte immed, 1: word immed, 2: long immed, 3: long
1112: */
1113: lispval
1114: LIvset()
1115: {
1116: register lispval vect,value;
1117: register int index;
1118: int class;
1119:
1120: chkarg(4,"int:vset");
1121: vect = lbot[0].val;
1122: index = lbot[1].val->i;
1123: value = lbot[2].val;
1124: class = lbot[3].val->i;
1125: switch(class)
1126: {
1127: case 0: vect->vb.vectorb[index] = (char)value->i;
1128: break;
1129: case 1: vect->vw.vectorw[index] = (short)value->i;
1130: break;
1131: case 2: vect->vl.vectorl[index] = value->i;
1132: break;
1133: case 3: vect->v.vector[index] = value;
1134: break;
1135: }
1136: return(value);
1137: }
1138:
1139: /*
1140: * LIvsize == (int:vsize 'vector 'x_shift)
1141: * return the vsize field of the vector shifted right by x_shift
1142: */
1143: lispval
1144: LIvsize()
1145: {
1146: int typ;
1147:
1148: chkarg(2,"int:vsize");
1149: return(inewint((lbot[0].val->vl.vectorl[VSizeOff]) >> lbot[1].val->i));
1150: }
1151:
1152: lispval
1153: Lvprop()
1154: {
1155: int typ;
1156: chkarg(1,"vprop");
1157:
1158: if(((typ = TYPE(lbot->val)) != VECTOR) && (typ != VECTORI))
1159: errorh1(Vermisc,"vprop: non vector argument: ", nil, FALSE,0,
1160: lbot->val);
1161: return(lbot[0].val->v.vector[VPropOff]);
1162: }
1163:
1164:
1165: lispval
1166: Lvsp()
1167: {
1168: int typ;
1169: lispval vector, property;
1170: chkarg(2,"vsetprop");
1171:
1172: vector = lbot->val;
1173: property = lbot[1].val;
1174: typ = TYPE(vector);
1175:
1176: if(typ != VECTOR && typ !=VECTORI)
1177: errorh1(Vermisc,"vsetprop: non vector argument: ",
1178: nil,FALSE,0,vector);
1179: vector->v.vector[VPropOff] = property;
1180: return(property);
1181: }
1182:
1183:
1184: /* vecequal
1185: * check if the two vector arguments are 'equal'
1186: * this is called by equal which has already checked that
1187: * the arguments are vector
1188: */
1189: vecequal(v,w)
1190: lispval v,w;
1191: {
1192: int i;
1193: lispval vv, ww, ret;
1194: int vsize = (int) v->v.vector[VSizeOff];
1195: int wsize = (int) w->v.vector[VSizeOff];
1196: struct argent *oldlbot = lbot;
1197: lispval Lequal();
1198:
1199: if(vsize != wsize) return(FALSE);
1200:
1201: vsize /= sizeof(int); /* determine number of entries */
1202:
1203: for(i = 0 ; i < vsize ; i++)
1204: {
1205: vv = v->v.vector[i];
1206: ww = w->v.vector[i];
1207: /* avoid calling equal if they are eq */
1208: if(vv != ww)
1209: {
1210: lbot = np;
1211: protect(vv);
1212: protect(ww);
1213: ret = Lequal();
1214: np = lbot;
1215: lbot = oldlbot;
1216: if(ret == nil) return(FALSE);
1217: }
1218: }
1219: return(TRUE);
1220: }
1221:
1222: /* veciequal
1223: * check if the two vectori arguments are 'equal'
1224: * this is called by equal which has already checked that
1225: * the arguments are vector
1226: * Note: this would run faster if we did as many 'longword'
1227: * comparisons as possible and then did byte comparisons.
1228: * or if we used pointers instead of indexing.
1229: */
1230: veciequal(v,w)
1231: lispval v,w;
1232: {
1233: char vv, ww;
1234: int i;
1235: int vsize = (int) v->v.vector[VSizeOff];
1236: int wsize = (int) w->v.vector[VSizeOff];
1237:
1238: if(vsize != wsize) return(FALSE);
1239:
1240:
1241: for(i = 0 ; i < vsize ; i++)
1242: {
1243: if(v->vb.vectorb[i] != w->vb.vectorb[i]) return(FALSE);
1244: }
1245: return(TRUE);
1246: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.