|
|
1.1 root 1: #ifndef lint
2: static char *rcsid =
3: "$Header: lam2.c,v 1.5 83/12/09 16:35:49 sklower Exp $";
4: #endif
5:
6: /* -[Fri Aug 5 12:46:16 1983 by jkf]-
7: * lam2.c $Locker: $
8: * lambda functions
9: *
10: * (c) copyright 1982, Regents of the University of California
11: */
12:
13: # include "global.h"
14: # include <signal.h>
15: # include "structs.h"
16: # include "chars.h"
17: # include "chkrtab.h"
18: /*
19: * (flatc 'thing ['max]) returns the smaller of max and the number of chars
20: * required to print thing linearly.
21: * if max argument is not given, we assume the second arg is infinity
22: */
23: static flen; /*Internal to this module, used as a running counter of flatsize*/
24: static fmax; /*used for maximum for quick reference */
25: char *strcpy();
26:
27: lispval
28: Lflatsi()
29: {
30: register lispval current;
31: Savestack(1); /* fixup entry mask */
32:
33: fmax = 0x7fffffff; /* biggest integer by default */
34: switch(np-lbot)
35: {
36: case 2: current = lbot[1].val;
37: while(TYPE(current) != INT)
38: current = errorh1(Vermisc,
39: "flatsize: second arg not integer",
40: nil,TRUE,0,current);
41: fmax = current->i;
42: case 1: break;
43: default: argerr("flatsize");
44: }
45:
46: flen = 0;
47: current = lbot->val;
48: protect(nil); /*create space for argument to pntlen*/
49: Iflatsi(current);
50: Restorestack();
51: return(inewint(flen));
52: }
53: /*
54: * Iflatsi does the real work of the calculation for flatc
55: */
56: Iflatsi(current)
57: register lispval current;
58: {
59:
60: if(flen > fmax) return;
61: switch(TYPE(current)) {
62:
63: patom:
64: case INT: case ATOM: case DOUB: case STRNG:
65: np[-1].val = current;
66: flen += Ipntlen();
67: return;
68:
69: pthing:
70: case DTPR:
71: flen++;
72: Iflatsi(current->d.car);
73: current = current->d.cdr;
74: if(current == nil) {
75: flen++;
76: return;
77: }
78: if(flen > fmax) return;
79: switch(TYPE(current)) {
80: case INT: case ATOM: case DOUB:
81: flen += 4;
82: goto patom;
83: case DTPR:
84: goto pthing;
85: }
86: }
87: }
88:
89:
90: #define EADC -1
91: #define EAD -2
92: lispval
93: Lread()
94: { return (r(EAD)); }
95:
96: lispval
97: Lratom()
98: { return (r(ATOM)); }
99:
100: lispval
101: Lreadc()
102: { return (r(EADC)); }
103:
104:
105: extern unsigned char *ctable;
106: /* r *********************************************************************/
107: /* this function maps the desired read function into the system-defined */
108: /* reading functions after testing for a legal port. */
109: lispval
110: r(op)
111: int op;
112: {
113: unsigned char c; register lispval result;
114: register cc;
115: int orlevel; extern int rlevel;
116: FILE *ttemp;
117: struct nament *oldbnp = bnp;
118: Savestack(2);
119:
120: switch(np-lbot) {
121: case 0:
122: protect(nil);
123: case 1:
124: protect(nil);
125: case 2: break;
126: default:
127: argerr("read or ratom or readc");
128: }
129: result = Vreadtable->a.clb;
130: chkrtab(result);
131: orlevel = rlevel;
132: rlevel = 0;
133: ttemp = okport(Vpiport->a.clb,stdin);
134: ttemp = okport(lbot->val,ttemp);
135: /*printf("entering switch\n");*/
136: if(ttemp == stdin) fflush(stdout); /* flush any pending
137: * characters if reading stdin
138: * there should be tests to see
139: * if this is a tty or pipe
140: */
141:
142: switch (op)
143: {
144: case EADC: rlevel = orlevel;
145: cc = getc(ttemp);
146: c = cc;
147: if(cc == EOF)
148: {
149: Restorestack();
150: return(lbot[1].val);
151: } else {
152: strbuf[0] = hash = (c & 0177);
153: strbuf[1] = 0;
154: atmlen = 2;
155: Restorestack();
156: return((lispval)getatom(TRUE));
157: }
158:
159: case ATOM: rlevel = orlevel;
160: result = (ratomr(ttemp));
161: goto out;
162:
163: case EAD: PUSHDOWN(Vpiport,P(ttemp)); /* rebind Vpiport */
164: result = readr(ttemp);
165: out: if(result==eofa)
166: {
167: if(sigintcnt > 0) sigcall(SIGINT);
168: result = lbot[1].val;
169: }
170: rlevel = orlevel;
171: popnames(oldbnp); /* unwind bindings */
172: Restorestack();
173: return(result);
174: }
175: /* NOTREACHED */
176: }
177:
178: /* Lload *****************************************************************/
179: /* Reads in and executes forms from the specified file. This should */
180: /* really be an nlambda taking multiple arguments, but the error */
181: /* handling gets funny in that case (one file out of several not */
182: /* openable, for instance). */
183: lispval
184: Lload()
185: {
186: register FILE *port;
187: register char *p, *ttemp; register lispval vtemp;
188: struct nament *oldbnp = bnp;
189: int orlevel,typ;
190: char longname[100];
191: char *shortname, *end2, *Ilibdir();
192: /*Savestack(4); not necessary because np not altered */
193:
194: chkarg(1,"load");
195: if((typ = TYPE(lbot->val)) == ATOM)
196: ttemp = lbot->val->a.pname ; /* ttemp will point to name */
197: else if(typ == STRNG)
198: ttemp = (char *) lbot->val;
199: else
200: return(error("FILENAME MUST BE ATOMIC",FALSE));
201: strcpy(longname, Ilibdir());
202: for(p = longname; *p; p++);
203: *p++ = '/'; *p = 0;
204: shortname = p;
205: strcpy(p,ttemp);
206: for(; *p; p++);
207: end2 = p;
208: strcpy(p,".l");
209: if ((port = fopen(shortname,"r")) == NULL &&
210: (port = fopen(longname, "r")) == NULL) {
211: *end2 = 0;
212: if ((port = fopen(shortname,"r")) == NULL &&
213: (port = fopen(longname, "r")) == NULL)
214: errorh1(Vermisc,"Can't open file: ",
215: nil,FALSE,0,lbot->val);
216: }
217: orlevel = rlevel;
218: rlevel = 0;
219:
220: if(ISNIL(copval(gcload,CNIL)) &&
221: loading->a.clb != tatom &&
222: ISNIL(copval(gcdis,CNIL)))
223: gc((struct types *)CNIL); /* do a gc if gc will be off */
224:
225: /* shallow bind the value of lisp atom piport */
226: /* so readmacros will work */
227: PUSHDOWN(Vpiport,P(port));
228: PUSHDOWN(loading,tatom); /* set indication of loading status */
229:
230: while ((vtemp = readr(port)) != eofa) {
231: eval(vtemp);
232: }
233: popnames(oldbnp); /* unbind piport, loading */
234:
235: rlevel = orlevel;
236: fclose(port);
237: return(nil);
238: }
239:
240: /* concat **************************************************
241: -
242: - use: (concat arg1 arg2 ... )
243: -
244: - concatenates the print names of all of its arguments.
245: - the arguments may be atoms, integers or real numbers.
246: -
247: - *********************************************************/
248: lispval
249: Iconcat(unintern)
250: {
251: register struct argent *temnp;
252: register char *cp = strbuf;
253: register lispval cur;
254: int n;
255: char *sprintf(), *atomtoolong();
256: lispval Lhau();
257:
258: *cp = NULL_CHAR ;
259:
260: /* loop for each argument */
261: for(temnp = lbot + AD ; temnp < np ; temnp++)
262: {
263: cur = temnp->val;
264: switch(TYPE(cur))
265: {
266: case ATOM:
267: n = strlen(cur->a.pname);
268: while(n + cp >= endstrb) cp = atomtoolong(cp);
269: strcpy(cp, cur->a.pname);
270: cp += n;
271: break;
272:
273: case STRNG:
274: n = strlen( (char *) cur);
275: while(n + cp >= endstrb) cp = atomtoolong(cp);
276: strcpy(cp, (char *) cur);
277: cp += n;
278: break;
279:
280: case INT:
281: if(15 + cp >= endstrb) cp = atomtoolong(cp);
282: sprintf(cp,"%d",cur->i);
283: while(*cp) cp++;
284: break;
285:
286: case DOUB:
287: if(15 + cp >= endstrb) cp = atomtoolong(cp);
288: sprintf(cp,"%f",cur->f);
289: while(*cp) cp++;
290: break;
291:
292: case SDOT: {
293: struct _iobuf _myiob;
294: register lispval handy = cur;
295:
296: for(n = 12; handy->s.CDR!=(lispval) 0; handy = handy->s.CDR)
297: n += 12;
298:
299: while(n + cp >= endstrb) cp = atomtoolong(cp);
300:
301: _myiob._flag = _IOWRT+_IOSTRG;
302: _myiob._ptr = cp;
303: _myiob._cnt = endstrb - cp - 1;
304:
305: pbignum(cur,&_myiob);
306: cp = _myiob._ptr;
307: *cp = 0;
308: break; }
309:
310: default:
311: cur = error("Non atom or number to concat",TRUE);
312: continue; /* if returns value, try it */
313: }
314:
315: }
316:
317: if(unintern)
318: return( (lispval) newatom(FALSE)); /* uninterned atoms may
319: have printname gc'd*/
320: else
321: return( (lispval) getatom(FALSE)) ;
322: }
323: lispval
324: Lconcat(){
325: return(Iconcat(FALSE));
326: }
327: lispval
328: Luconcat(){
329: return(Iconcat(TRUE));
330: }
331:
332: lispval
333: Lputprop()
334: {
335: lispval Iputprop();
336: chkarg(3,"putprop");
337: return(Iputprop(lbot->val,lbot[1].val,lbot[2].val));
338: }
339:
340: /*
341: * Iputprop :internal version of putprop used by some C functions
342: * note: prop and ind are lisp values but are not protected (by this
343: * function) from gc. The caller should protect them!!
344: */
345: lispval
346: Iputprop(atm,prop,ind)
347: register lispval prop, ind, atm;
348: {
349: register lispval pptr;
350: lispval *tack; /* place to begin property list */
351: lispval pptr2;
352: lispval errorh();
353: Savestack(4);
354:
355: top:
356: switch (TYPE(atm)) {
357: case ATOM:
358: if(atm == nil) tack = &nilplist;
359: else tack = &(atm->a.plist);
360: break;
361: case DTPR:
362: for (pptr = atm->d.cdr ; pptr != nil ; pptr = pptr->d.cdr->d.cdr)
363: if(TYPE(pptr) != DTPR || TYPE(pptr->d.cdr) != DTPR) break;
364: if(pptr != nil)
365: { atm = errorh1(Vermisc,
366: "putprop: bad disembodied property list",
367: nil,TRUE,0,atm);
368: goto top;
369: }
370: tack = (lispval *) &(atm->d.cdr);
371: break;
372: default:
373: errorh1(Vermisc,"putprop: Bad first argument: ",nil,FALSE,0,atm);
374: }
375: pptr = *tack; /* start of property list */
376: /*findit:*/
377: for (pptr = *tack ; pptr != nil ; pptr = pptr->d.cdr->d.cdr)
378: if (pptr->d.car == ind) {
379: (pptr->d.cdr)->d.car = prop;
380: Restorestack();
381: return(prop);
382: }
383: /* not found, add to front
384: be careful, a gc could occur before the second newdot() */
385:
386: pptr = newdot();
387: pptr->d.car = prop;
388: pptr->d.cdr = *tack;
389: protect(pptr);
390: pptr2 = newdot();
391: pptr2->d.car = ind;
392: pptr2->d.cdr = pptr;
393: *tack = pptr2;
394: Restorestack();
395: return(prop);
396: }
397:
398: /* get from property list
399: * there are three routines to accomplish this
400: * Lget - lisp callable, the first arg can be a symbol or a disembodied
401: * property list. In the latter case we check to make sure it
402: * is a real one (as best we can).
403: * Iget - internal routine, the first arg must be a symbol, no disembodied
404: * plists allowed
405: * Igetplist - internal routine, the first arg is the plist to search.
406: */
407: lispval
408: Lget()
409: {
410: register lispval ind, atm;
411: register lispval dum1;
412: lispval Igetplist();
413:
414: chkarg(2,"get");
415: ind = lbot[1].val;
416: atm = lbot[0].val;
417: top:
418: switch(TYPE(atm)) {
419: case ATOM:
420: if(atm==nil) atm = nilplist;
421: else atm = atm->a.plist;
422: break;
423:
424: case DTPR:
425: for (dum1 = atm->d.cdr; dum1 != nil; dum1 = dum1->d.cdr->d.cdr)
426: if((TYPE(dum1) != DTPR) ||
427: (TYPE(dum1->d.cdr) != DTPR)) break; /* bad prop list */
428: if(dum1 != nil)
429: { atm = errorh1(Vermisc,
430: "get: bad disembodied property list",
431: nil,TRUE,0,atm);
432: goto top;
433: }
434: atm = atm->d.cdr;
435: break;
436: default:
437: /* remove since maclisp doesnt treat
438: this as an error, ugh
439: return(errorh1(Vermisc,"get: bad first argument: ",
440: nil,FALSE,0,atm));
441: */
442: return(nil);
443: }
444:
445: while (atm != nil)
446: {
447: if (atm->d.car == ind)
448: return ((atm->d.cdr)->d.car);
449: atm = (atm->d.cdr)->d.cdr;
450: }
451: return(nil);
452: }
453: /*
454: * Iget - the first arg must be a symbol.
455: */
456:
457: lispval
458: Iget(atm,ind)
459: register lispval atm, ind;
460: {
461: lispval Igetplist();
462:
463: if(atm==nil)
464: atm = nilplist;
465: else
466: atm = atm->a.plist;
467: return(Igetplist(atm,ind));
468: }
469:
470: /*
471: * Igetplist
472: * pptr is a plist
473: * ind is the indicator
474: */
475:
476: lispval
477: Igetplist(pptr,ind)
478: register lispval pptr,ind;
479: {
480: while (pptr != nil)
481: {
482: if (pptr->d.car == ind)
483: return ((pptr->d.cdr)->d.car);
484: pptr = (pptr->d.cdr)->d.cdr;
485: }
486: return(nil);
487: }
488: lispval
489: Lgetd()
490: {
491: register lispval typ;
492:
493: chkarg(1,"getd");
494: typ = lbot->val;
495: if (TYPE(typ) != ATOM)
496: errorh1(Vermisc,
497: "getd: Only symbols have function definitions",
498: nil,
499: FALSE,
500: 0,
501: typ);
502: return(typ->a.fnbnd);
503: }
504: lispval
505: Lputd()
506: {
507: register lispval atom, list;
508:
509: chkarg(2,"putd");
510: list = lbot[1].val;
511: atom = lbot->val;
512: if (TYPE(atom) != ATOM) error("only symbols have function definitions",
513: FALSE);
514: atom->a.fnbnd = list;
515: return(list);
516: }
517:
518: /* ===========================================================
519: - mapping functions which return a list of the answers
520: - mapcar applies the given function to successive elements
521: - maplist applies the given function to successive sublists
522: - ===========================================================*/
523:
524: lispval
525: Lmapcrx(maptyp,join)
526: int maptyp; /* 0 = mapcar, 1 = maplist */
527: int join; /* 0 = the above, 1 = s/car/can/ */
528: {
529: register struct argent *namptr;
530: register index;
531: register lispval temp;
532: register lispval current;
533:
534: struct argent *first, *last;
535: int count;
536: lispval lists[25], result;
537: Savestack(4);
538:
539: namptr = lbot + 1;
540: count = np - namptr;
541: if (count <= 0) return (nil);
542: result = current = (lispval) np;
543: protect(nil); /* set up space for returned list */
544: protect(lbot->val); /*copy funarg for call to funcall */
545: lbot = np -1;
546: first = np;
547: last = np += count;
548: for(index = 0; index < count; index++) {
549: temp =(namptr++)->val;
550: if (TYPE (temp ) != DTPR && temp!=nil)
551: error ( "bad list argument to map",FALSE);
552: lists[index] = temp;
553: }
554: for(;;) {
555: for(namptr=first,index=0; index<count; index++) {
556: temp = lists[index];
557: if(temp==nil) goto done;
558:
559: if(maptyp==0) (namptr++)->val = temp->d.car;
560: else (namptr++)->val = temp;
561:
562: lists[index] = temp->d.cdr;
563: }
564: if (join == 0) {
565: current->l = newdot();
566: current->l->d.car = Lfuncal();
567: current = (lispval) ¤t->l->d.cdr;
568: } else {
569: current->l = Lfuncal();
570: if ( TYPE ( current -> l) != DTPR && current->l != nil)
571: error("bad type returned from funcall inside map",FALSE);
572: else while ( current -> l != nil )
573: current = (lispval) & (current ->l ->d.cdr);
574: }
575: np = last;
576: }
577: done: if (join == 0)current->l = nil;
578: Restorestack();
579: return(result->l);
580: }
581:
582: /* ============================
583: -
584: - Lmapcar
585: - =============================*/
586:
587: lispval
588: Lmpcar()
589: {
590: return(Lmapcrx(0,0)); /* call general routine */
591: }
592:
593:
594: /* ============================
595: -
596: -
597: - Lmaplist
598: - ==============================*/
599:
600: lispval
601: Lmaplist()
602: {
603: return(Lmapcrx(1,0)); /* call general routine */
604: }
605:
606:
607: /* ================================================
608: - mapping functions which return the value of the last function application.
609: - mapc and map
610: - ===================================================*/
611:
612: lispval
613: Lmapcx(maptyp)
614: int maptyp; /* 0= mapc , 1= map */
615: {
616: register struct argent *namptr;
617: register index;
618: register lispval temp;
619: register lispval result;
620:
621: int count;
622: struct argent *first;
623: lispval lists[25], errorh();
624: Savestack(4);
625:
626: namptr = lbot + 1;
627: count = np - namptr;
628: if(count <= 0) return(nil);
629: result = lbot[1].val; /*This is what macsyma wants so ... */
630: /*copy funarg for call to funcall */
631: lbot = np; protect((namptr - 1)->val);
632: first = np; np += count;
633:
634: for(index = 0; index < count; index++) {
635: temp = (namptr++)->val;
636: while(temp!=nil && TYPE(temp)!=DTPR)
637: temp = errorh1(Vermisc,"Inappropriate list argument to mapc",nil,TRUE,0,temp);
638: lists[index] = temp;
639: }
640: for(;;) {
641: for(namptr=first,index=0; index<count; index++) {
642: temp = lists[index];
643: if(temp==nil)
644: goto done;
645: if(maptyp==0)
646: (namptr++)->val = temp->d.car;
647: else
648: (namptr++)->val = temp;
649: lists[index] = temp->d.cdr;
650: }
651: Lfuncal();
652: }
653: done:
654: Restorestack();
655: return(result);
656: }
657:
658:
659: /* ==================================
660: -
661: - mapc map the car of the lists
662: -
663: - ==================================*/
664:
665: lispval
666: Lmapc()
667: { return( Lmapcx(0) ); }
668:
669:
670: /* =================================
671: -
672: - map map the cdr of the lists
673: -
674: - ===================================*/
675:
676: lispval
677: Lmap()
678: { return( Lmapcx(1) ); }
679:
680:
681: lispval
682: Lmapcan()
683: {
684: lispval Lmapcrx();
685:
686: return ( Lmapcrx ( 0,1 ) );
687: }
688:
689: lispval
690: Lmapcon()
691: {
692: lispval Lmapcrx();
693:
694: return ( Lmapcrx ( 1,1 ) );
695: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.