|
|
1.1 root 1: #ifndef lint
2: static char *rcsid =
3: "$Header: lam5.c,v 1.7 83/12/09 16:36:12 sklower Exp $";
4: #endif
5:
6: /* -[Fri Aug 5 12:49:06 1983 by jkf]-
7: * lam5.c $Locker: $
8: * lambda functions
9: *
10: * (c) copyright 1982, Regents of the University of California
11: */
12:
13: #include "global.h"
14: #include "chkrtab.h"
15: #include <ctype.h>
16: char *strcpy(), *sprintf();
17:
18: /*===========================================
19: -
20: - explode functions: aexplode , aexplodec, aexploden
21: - The following function partially implement the explode functions for atoms.
22: - The full explode functions are written in lisp and call these for atom args.
23: -
24: -===========================================*/
25:
26: #include "chars.h"
27: lispval
28: Lexpldx(kind,slashify)
29: int kind, slashify; /* kind = 0 => explode to characters
30: = 1 => explode to fixnums (aexploden)
31: slashify = 0 => do not quote bizarre characters
32: = 1 => quote bizarre characters
33: */
34: {
35: int typ, i;
36: char ch, *strb, strbb[BUFSIZ], *alloca(); /* temporary string buffer */
37: register lispval last, handy;
38: extern int uctolc;
39: register char *cp;
40: Savestack(3); /* kludge register save mask */
41: #ifdef SPISFP
42: Keepxs();
43: #endif
44:
45: chkarg(1,"expldx");
46:
47: handy = Vreadtable->a.clb;
48: chkrtab(handy);
49: handy = lbot->val;
50: *strbuf = 0;
51: typ=TYPE(handy); /* we only work for a few types */
52:
53:
54: /* put the characters to return in the string buffer strb */
55:
56: switch(typ) {
57: case STRNG:
58: if(slashify && !Xsdc)
59: errorh1(Vermisc,"Can't explode without string delimiter",nil
60: ,FALSE,0,handy);
61:
62: strb = strbb;
63: if(slashify) *strb++ = Xsdc;
64: /* copy string into buffer, escape only occurances of the
65: double quoting character if in slashify mode
66: */
67: for(cp = (char *) handy; *cp; cp++)
68: {
69: if(slashify &&
70: (*cp == Xsdc || synclass(ctable[*cp])==CESC))
71: *strb++ = Xesc;
72: *strb++ = *cp;
73: }
74: if(slashify) *strb++ = Xsdc;
75: *strb = NULL_CHAR ;
76: strb = strbb;
77: break;
78:
79: case ATOM:
80: strb = handy->a.pname;
81: if(slashify && (strb[0]==0)) {
82: strb = strbb;
83: strbb[0] = Xdqc;
84: strbb[1] = Xdqc;
85: strbb[2] = 0;
86: } else
87: /*common:*/
88: if(slashify != 0)
89: {
90: char *out = strbb;
91: unsigned char code;
92:
93: cp = strb;
94: strb = strbb;
95: code = ctable[(*cp)&0177];
96: switch(synclass(code)) {
97: case CNUM:
98: *out++ = Xesc;
99: break;
100: case CCHAR:
101: if(uctolc && isupper((*cp)&0177)) {
102: *out++ = Xesc;
103: }
104: break;
105: default:
106: switch(code&QUTMASK) {
107: case QWNUNIQ:
108: if (cp[1]==0) *out++ = Xesc;
109: break;
110: case QALWAYS:
111: case QWNFRST:
112: *out++ = Xesc;
113: }
114: }
115: *out++ = *cp++;
116: for(; *cp; cp++)
117: {
118: if(((ctable[*cp]&QUTMASK)==QALWAYS) ||
119: (uctolc && isupper(*cp)))
120: *out++ = Xesc;
121: *out++ = *cp;
122: }
123: *out = 0;
124: }
125: break;
126:
127: case INT:
128: strb = strbb;
129: sprintf(strb, "%d", lbot->val->i);
130: break;
131: case DOUB:
132: strb = strbb;
133: lfltpr(strb, lbot->val->r);
134: break;
135: case SDOT:
136: {
137: struct _iobuf _strbuf;
138: int count;
139: for((handy = lbot->val), count = 12;
140: handy->s.CDR!=(lispval) 0;
141: (handy = handy->s.CDR), count += 12);
142: strb = alloca(count);
143:
144: _strbuf._flag = _IOWRT+_IOSTRG;
145: _strbuf._ptr = strb;
146: _strbuf._cnt = count;
147: pbignum(lbot->val,&_strbuf);
148: putc(0,&_strbuf);
149: break;
150: }
151: default:
152: errorh1(Vermisc,"EXPLODE ARG MUST BE STRING, SYMBOL, FIXNUM, OR FLONUM",nil,FALSE,0,handy);
153: Restorestack();
154: Freexs();
155: return(nil);
156: }
157:
158:
159: if( strb[0] != NULL_CHAR ) /* if there is something to do */
160: {
161: lispval prev;
162:
163: protect(handy = last = newdot());
164: strbuf[1] = NULL_CHAR ; /* set up for getatom */
165: atmlen = 2;
166:
167: for(i=0; ch = strb[i++]; ) {
168: switch(kind) {
169:
170: case 0: strbuf[0] = hash = ch; /* character explode */
171: last->d.car = (lispval) getatom(TRUE); /* look in oblist */
172: break;
173:
174: case 1:
175: last->d.car = inewint(ch);
176: break;
177: }
178:
179: /* advance pointers */
180: prev = last;
181: last->d.cdr = newdot();
182: last = last->d.cdr;
183: }
184:
185: /* end list with a nil pointer */
186: prev->d.cdr = nil;
187: Freexs();
188: Restorestack();
189: return(handy);
190: }
191: Freexs();
192: Restorestack();
193: return(nil); /* return nil if no characters */
194: }
195:
196: /*===========================
197: -
198: - (aexplodec 'atm) returns (a t m)
199: - (aexplodec 234) returns (\2 \3 \4)
200: -===========================*/
201:
202: lispval
203: Lxpldc()
204: { return(Lexpldx(0,0)); }
205:
206:
207: /*===========================
208: -
209: - (aexploden 'abc) returns (65 66 67)
210: - (aexploden 123) returns (49 50 51)
211: -=============================*/
212:
213:
214: lispval
215: Lxpldn()
216: { return(Lexpldx(1,0)); }
217:
218: /*===========================
219: -
220: - (aexplode "123") returns (\\ \1 \2 \3);
221: - (aexplode 123) returns (\1 \2 \3);
222: -=============================*/
223:
224: lispval
225: Lxplda()
226: { return(Lexpldx(0,1)); }
227:
228: /*
229: * (argv) returns how many arguments where on the command line which invoked
230: * lisp; (argv i) returns the i'th argument made into an atom;
231: */
232:
233: lispval
234: Largv()
235: {
236: register lispval handy;
237: extern int Xargc;
238: extern char **Xargv;
239:
240: if(lbot-np==0)handy = nil;
241: else handy = lbot->val;
242:
243: if(TYPE(handy)==INT && handy->i>=0 && handy->i<Xargc) {
244: strcpy(strbuf,Xargv[handy->i]);
245: return(getatom(FALSE));
246: } else {
247: return(inewint(Xargc));
248: }
249: }
250: /*
251: * (chdir <atom>) executes a chdir command
252: * if successful, return t otherwise returns nil
253: */
254: lispval Lchdir(){
255: register char *filenm;
256:
257: chkarg(1,"chdir");
258: filenm = (char *) verify(lbot->val,"chdir - non symbol or string arg");
259: if(chdir(filenm)>=0)
260: return(tatom);
261: else
262: return(nil);
263: }
264:
265: /* ==========================================================
266: -
267: - ascii - convert from number to ascii character
268: -
269: - form:(ascii number)
270: -
271: - the number is checked so that it is in the range 0-255
272: - then it is made a character and returned
273: - =========================================================*/
274:
275: lispval
276: Lascii()
277: {
278: register lispval handy;
279:
280: handy = lbot->val; /* get argument */
281:
282: if(TYPE(handy) != INT) /* insure that it is an integer */
283: { error("argument not an integer",FALSE);
284: return(nil);
285: }
286:
287: if(handy->i < 0 || handy->i > 0377) /* insure that it is in range*/
288: { error("argument is out of ascii range",FALSE);
289: return(nil);
290: }
291:
292: strbuf[0] = handy->i ; /* ok value, make into a char */
293: strbuf[1] = NULL_CHAR;
294:
295: /* lookup and possibly intern the atom given in strbuf */
296:
297: return( (lispval) getatom(TRUE) );
298: }
299:
300: /*
301: * boole - maclisp bitwise boolean function
302: * (boole k x y) where k determines which of 16 possible bitwise
303: * truth tables may be applied. Common values are 1 (and) 6 (xor) 7 (or)
304: * the result is mapped over each pair of bits on input
305: */
306: lispval
307: Lboole(){
308: register x, y;
309: register struct argent *mynp;
310: int k;
311:
312: if(np - lbot < 3)
313: error("Boole demands at least 3 args",FALSE);
314: mynp = lbot+AD;
315: k = mynp->val->i & 15;
316: x = (mynp+1)->val->i;
317: for(mynp += 2; mynp < np; mynp++) {
318: y = mynp->val->i;
319: switch(k) {
320:
321: case 0: x = 0;
322: break;
323: case 1: x = x & y;
324: break;
325: case 2: x = y & ~x;
326: break;
327: case 3: x = y;
328: break;
329: case 4: x = x & ~y;
330: break;
331: /* case 5: x = x; break; */
332: case 6: x = x ^ y;
333: break;
334: case 7: x = x | y;
335: break;
336: case 8: x = ~(x | y);
337: break;
338: case 9: x = ~(x ^ y);
339: break;
340: case 10: x = ~x;
341: break;
342: case 11: x = ~x | y;
343: break;
344: case 12: x = ~y;
345: break;
346: case 13: x = x | ~y;
347: break;
348: case 14: x = ~x | ~y;
349: break;
350: case 15: x = -1;
351: }
352: }
353: return(inewint(x));
354: }
355: lispval
356: Lfact()
357: {
358: register lispval result, handy;
359: register itemp;
360: Savestack(3); /* fixup entry mask */
361:
362: result = lbot->val;
363: if(TYPE(result)!=INT) error("Factorial of Non-fixnum. If you want me\
364: to calculate fact of > 2^30 We will be here till doomsday!.",FALSE);
365: itemp = result->i;
366: protect(result = newsdot());
367: result->s.CDR=(lispval)0;
368: result->i = 1;
369: for(; itemp > 1; itemp--)
370: dmlad(result,(long)itemp,0L);
371: if(result->s.CDR)
372: {
373: Restorestack();
374: return(result);
375: }
376: handy = inewint(result->s.I);
377: pruneb(result);
378: Restorestack();
379: return(handy);
380: }
381: /*
382: * fix -- maclisp floating to fixnum conversion
383: * for the moment, mereley convert floats to ints.
384: * eventual convert to bignum if too big to fit.
385: */
386: lispval Lfix()
387: {
388: register lispval handy;
389: double floor();
390:
391: chkarg(1,"fix");
392: handy = lbot->val;
393: switch(TYPE(handy)) {
394: default:
395: error("innaproriate arg to fix.",FALSE);
396: case INT:
397: case SDOT:
398: return(handy);
399: case DOUB:
400: return(inewint((int)floor(handy->r)));
401: }
402: }
403: /*
404: * (frexp <real no>)
405: * returns a dotted pair (<exponent>. <bignum>)
406: * such that bignum is 56 bits long, and if you think of the binary
407: * point occuring after the high order bit, <real no> = 2^<exp> * <bignum>
408: *
409: * myfrexp is an assembly language routine found in bigmath.s to do exactly
410: * what is necessary to accomplish this.
411: * this routine is horribly vax specific.
412: *
413: * Lfix should probably be rewritten to take advantage of myfrexp
414: */
415: lispval
416: Lfrexp()
417: {
418: register lispval handy, result;
419: int exp, hi, lo;
420:
421: Savestack(2);
422: chkarg(1,"frexp");
423:
424: myfrexp(lbot->val->r, &exp, &hi, &lo);
425: if(lo < 0) {
426: /* normalize for bignum */
427: lo &= ~ 0xC0000000;
428: hi += 1;
429: }
430: result = handy = newdot();
431: protect(handy);
432: handy->d.car = inewint(exp);
433: if(hi==0&&lo==0) {
434: handy->d.cdr = inewint(0);
435: } else {
436: handy = handy->d.cdr = newsdot();
437: handy->s.I = lo;
438: handy = handy->s.CDR = newdot();
439: handy->s.I = hi;
440: handy->s.CDR = 0;
441: }
442: np--;
443: Restorestack();
444: return(result);
445: }
446:
447: #define SIGFPE 8
448: #define B 1073741824.0
449: static double table[] = { 1.0, B, B*B, B*B*B, B*B*B*B, 0.0};
450:
451: lispval
452: Lfloat()
453: {
454: register lispval handy,result;
455: register double sum = 0;
456: register int count;
457: chkarg(1,"float");
458: handy = lbot->val;
459: switch(TYPE(handy))
460: {
461: case DOUB: return(handy);
462:
463:
464: case INT: result = newdoub();
465: result->r = (double) handy->i;
466: return(result);
467: case SDOT:
468: {
469: for(handy = lbot->val, count = 0;
470: count < 5;
471: count++, handy = handy->s.CDR) {
472: sum += handy->s.I * table[count];
473: if(handy->s.CDR==(lispval)0) goto done;
474: }
475: kill(getpid(),SIGFPE);
476: done:
477: result = newdoub();
478: result->r = sum;
479: return(result);
480: }
481: default: errorh1(Vermisc,"Bad argument to float",nil,FALSE,0,handy);
482: /* NOTREACHED */
483: }
484: }
485: double
486: Ifloat(handy)
487: register lispval handy;
488: {
489: register double sum = 0.0; register int count=0;
490: for(; count < 5; count++, handy = handy->s.CDR) {
491: sum += handy->s.I * table[count];
492: if(handy->s.CDR==(lispval)0) goto done;
493: }
494: kill(getpid(),SIGFPE);
495: done:
496: return(sum);
497: }
498:
499: /* Lbreak ***************************************************************/
500: /* If first argument is not nil, this is evaluated and printed. Then */
501: /* error is called with the "breaking" message. */
502: lispval Lbreak() {
503:
504: if (np > lbot) {
505: printr(lbot->val,poport);
506: dmpport(poport);
507: }
508: return(error("",TRUE));
509: }
510:
511:
512: lispval
513: LDivide() {
514: register lispval result, work;
515: register struct argent *mynp;
516: lispval quo, rem, arg1, arg2; struct sdot dummy, dum2;
517: Savestack(3);
518:
519: chkarg(2,"Divide");
520: mynp = lbot;
521: work = mynp++->val;
522: switch(TYPE(work)) {
523: case INT:
524: arg1 = (lispval) &dummy;
525: dummy.I = work->i;
526: dummy.CDR = (lispval) 0;
527: break;
528: case SDOT:
529: arg1 = work;
530: break;
531: urk:
532: default:
533: error("First arg to divide neither a bignum nor int.",FALSE);
534: }
535: work = mynp->val;
536: switch(TYPE(work)) {
537: case INT:
538: arg2 = (lispval) &dum2;
539: dum2.I = work->i;
540: dum2.CDR = (lispval) 0;
541: break;
542: case SDOT:
543: arg2 = work;
544: break;
545: default:
546: goto urk;
547: }
548: divbig(arg1,arg2, &quo, &rem);
549: protect(quo);
550: if(rem==((lispval)&dummy))
551: rem = inewint(dummy.I);
552: protect(rem);
553: protect(result = work = newdot());
554: work->d.car = quo;
555: (work->d.cdr = newdot())->d.car = rem;
556: Restorestack();
557: return(result);
558: }
559:
560: lispval LEmuldiv(){
561: register struct argent * mynp = lbot+AD;
562: register lispval work, result;
563: int quo, rem;
564: Savestack(3); /* fix register mask */
565:
566: /* (Emuldiv mul1 mult2 add quo) =>
567: temp = mul1 + mul2 + sext(add);
568: result = (list temp/quo temp%quo);
569: to mix C and lisp a bit */
570:
571: Imuldiv(mynp[0].val->i, mynp[1].val->i, mynp[2].val->i,
572: mynp[3].val->i, &quo, &rem);
573: protect(result=newdot());
574: (result->d.car=inewint(quo));
575: work = result->d.cdr = newdot();
576: (work->d.car=inewint(rem));
577: Restorestack();
578: return(result);
579: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.