|
|
1.1 root 1: #ifndef lint
2: static char *rcsid =
3: "$Header: /na/franz/franz/RCS/lam2.c,v 1.3 83/08/06 08:37:23 jkf 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: char *sprintf();
252: register struct argent *temnp;
253: register int atmlen; /* Passt auf! atmlen in the external
254: sense calculated by newstr */
255: lispval cur;
256:
257: atmlen = 0 ;
258: strbuf[0] = NULL_CHAR ;
259:
260: /* loop for each argument */
261: for(temnp = lbot + AD ; temnp < np ; temnp++)
262: {
263: cur = temnp->val;
264: loop: if(atmlen > 512) error("concat: string buffer overflow",FALSE);
265: switch(TYPE(cur))
266: {
267: case ATOM:
268: strcpy(&strbuf[atmlen], ((struct atom *) cur) -> pname) ;
269: break;
270:
271: case STRNG:
272: strcpy(&strbuf[atmlen], (char *) cur);
273: break;
274:
275: case INT:
276: sprintf(&strbuf[atmlen],"%d",cur->i);
277: break;
278:
279: case DOUB:
280: sprintf(&strbuf[atmlen],"%f",cur->f);
281: break;
282:
283: case SDOT: {
284: struct _iobuf _myiob;
285:
286: _myiob._flag = _IOWRT+_IOSTRG;
287: _myiob._ptr = &strbuf[atmlen];
288: _myiob._cnt = STRBLEN - 1 - atmlen;
289:
290: pbignum(cur,&_myiob);
291: putc(0,&_myiob);
292: break; }
293:
294: default:
295: cur = error("Non atom or number to concat",TRUE);
296: goto loop; /* if returns value, try it */
297: }
298: atmlen = strlen(strbuf);
299:
300: }
301:
302: if(unintern)
303: return( (lispval) newatom(FALSE)); /* uninterned atoms may
304: have printname gc'd*/
305: else
306: return( (lispval) getatom(FALSE)) ;
307: }
308: lispval
309: Lconcat(){
310: return(Iconcat(FALSE));
311: }
312: lispval
313: Luconcat(){
314: return(Iconcat(TRUE));
315: }
316:
317: lispval
318: Lputprop()
319: {
320: lispval Iputprop();
321: chkarg(3,"putprop");
322: return(Iputprop(lbot->val,lbot[1].val,lbot[2].val));
323: }
324:
325: /*
326: * Iputprop :internal version of putprop used by some C functions
327: * note: prop and ind are lisp values but are not protected (by this
328: * function) from gc. The caller should protect them!!
329: */
330: lispval
331: Iputprop(atm,prop,ind)
332: register lispval prop, ind, atm;
333: {
334: register lispval pptr;
335: lispval *tack; /* place to begin property list */
336: lispval pptr2;
337: lispval errorh();
338: Savestack(4);
339:
340: top:
341: switch (TYPE(atm)) {
342: case ATOM:
343: if(atm == nil) tack = &nilplist;
344: else tack = &(atm->a.plist);
345: break;
346: case DTPR:
347: for (pptr = atm->d.cdr ; pptr != nil ; pptr = pptr->d.cdr->d.cdr)
348: if(TYPE(pptr) != DTPR || TYPE(pptr->d.cdr) != DTPR) break;
349: if(pptr != nil)
350: { atm = errorh1(Vermisc,
351: "putprop: bad disembodied property list",
352: nil,TRUE,0,atm);
353: goto top;
354: }
355: tack = (lispval *) &(atm->d.cdr);
356: break;
357: default:
358: errorh1(Vermisc,"putprop: Bad first argument: ",nil,FALSE,0,atm);
359: }
360: pptr = *tack; /* start of property list */
361: /*findit:*/
362: for (pptr = *tack ; pptr != nil ; pptr = pptr->d.cdr->d.cdr)
363: if (pptr->d.car == ind) {
364: (pptr->d.cdr)->d.car = prop;
365: Restorestack();
366: return(prop);
367: }
368: /* not found, add to front
369: be careful, a gc could occur before the second newdot() */
370:
371: pptr = newdot();
372: pptr->d.car = prop;
373: pptr->d.cdr = *tack;
374: protect(pptr);
375: pptr2 = newdot();
376: pptr2->d.car = ind;
377: pptr2->d.cdr = pptr;
378: *tack = pptr2;
379: Restorestack();
380: return(prop);
381: }
382:
383: /* get from property list
384: * there are three routines to accomplish this
385: * Lget - lisp callable, the first arg can be a symbol or a disembodied
386: * property list. In the latter case we check to make sure it
387: * is a real one (as best we can).
388: * Iget - internal routine, the first arg must be a symbol, no disembodied
389: * plists allowed
390: * Igetplist - internal routine, the first arg is the plist to search.
391: */
392: lispval
393: Lget()
394: {
395: register lispval ind, atm;
396: register lispval dum1;
397: lispval Igetplist();
398:
399: chkarg(2,"get");
400: ind = lbot[1].val;
401: atm = lbot[0].val;
402: top:
403: switch(TYPE(atm)) {
404: case ATOM:
405: if(atm==nil) atm = nilplist;
406: else atm = atm->a.plist;
407: break;
408:
409: case DTPR:
410: for (dum1 = atm->d.cdr; dum1 != nil; dum1 = dum1->d.cdr->d.cdr)
411: if((TYPE(dum1) != DTPR) ||
412: (TYPE(dum1->d.cdr) != DTPR)) break; /* bad prop list */
413: if(dum1 != nil)
414: { atm = errorh1(Vermisc,
415: "get: bad disembodied property list",
416: nil,TRUE,0,atm);
417: goto top;
418: }
419: atm = atm->d.cdr;
420: break;
421: default:
422: /* remove since maclisp doesnt treat
423: this as an error, ugh
424: return(errorh1(Vermisc,"get: bad first argument: ",
425: nil,FALSE,0,atm));
426: */
427: return(nil);
428: }
429:
430: while (atm != nil)
431: {
432: if (atm->d.car == ind)
433: return ((atm->d.cdr)->d.car);
434: atm = (atm->d.cdr)->d.cdr;
435: }
436: return(nil);
437: }
438: /*
439: * Iget - the first arg must be a symbol.
440: */
441:
442: lispval
443: Iget(atm,ind)
444: register lispval atm, ind;
445: {
446: lispval Igetplist();
447:
448: if(atm==nil)
449: atm = nilplist;
450: else
451: atm = atm->a.plist;
452: return(Igetplist(atm,ind));
453: }
454:
455: /*
456: * Igetplist
457: * pptr is a plist
458: * ind is the indicator
459: */
460:
461: lispval
462: Igetplist(pptr,ind)
463: register lispval pptr,ind;
464: {
465: while (pptr != nil)
466: {
467: if (pptr->d.car == ind)
468: return ((pptr->d.cdr)->d.car);
469: pptr = (pptr->d.cdr)->d.cdr;
470: }
471: return(nil);
472: }
473: lispval
474: Lgetd()
475: {
476: register lispval typ;
477:
478: chkarg(1,"getd");
479: typ = lbot->val;
480: if (TYPE(typ) != ATOM)
481: errorh1(Vermisc,
482: "getd: Only symbols have function definitions",
483: nil,
484: FALSE,
485: 0,
486: typ);
487: return(typ->a.fnbnd);
488: }
489: lispval
490: Lputd()
491: {
492: register lispval atom, list;
493:
494: chkarg(2,"putd");
495: list = lbot[1].val;
496: atom = lbot->val;
497: if (TYPE(atom) != ATOM) error("only symbols have function definitions",
498: FALSE);
499: atom->a.fnbnd = list;
500: return(list);
501: }
502:
503: /* ===========================================================
504: - mapping functions which return a list of the answers
505: - mapcar applies the given function to successive elements
506: - maplist applies the given function to successive sublists
507: - ===========================================================*/
508:
509: lispval
510: Lmapcrx(maptyp,join)
511: int maptyp; /* 0 = mapcar, 1 = maplist */
512: int join; /* 0 = the above, 1 = s/car/can/ */
513: {
514: register struct argent *namptr;
515: register index;
516: register lispval temp;
517: register lispval current;
518:
519: struct argent *first, *last;
520: int count;
521: lispval lists[25], result;
522: Savestack(4);
523:
524: namptr = lbot + 1;
525: count = np - namptr;
526: if (count <= 0) return (nil);
527: result = current = (lispval) np;
528: protect(nil); /* set up space for returned list */
529: protect(lbot->val); /*copy funarg for call to funcall */
530: lbot = np -1;
531: first = np;
532: last = np += count;
533: for(index = 0; index < count; index++) {
534: temp =(namptr++)->val;
535: if (TYPE (temp ) != DTPR && temp!=nil)
536: error ( "bad list argument to map",FALSE);
537: lists[index] = temp;
538: }
539: for(;;) {
540: for(namptr=first,index=0; index<count; index++) {
541: temp = lists[index];
542: if(temp==nil) goto done;
543:
544: if(maptyp==0) (namptr++)->val = temp->d.car;
545: else (namptr++)->val = temp;
546:
547: lists[index] = temp->d.cdr;
548: }
549: if (join == 0) {
550: current->l = newdot();
551: current->l->d.car = Lfuncal();
552: current = (lispval) ¤t->l->d.cdr;
553: } else {
554: current->l = Lfuncal();
555: if ( TYPE ( current -> l) != DTPR && current->l != nil)
556: error("bad type returned from funcall inside map",FALSE);
557: else while ( current -> l != nil )
558: current = (lispval) & (current ->l ->d.cdr);
559: }
560: np = last;
561: }
562: done: if (join == 0)current->l = nil;
563: Restorestack();
564: return(result->l);
565: }
566:
567: /* ============================
568: -
569: - Lmapcar
570: - =============================*/
571:
572: lispval
573: Lmapcar()
574: {
575: return(Lmapcrx(0,0)); /* call general routine */
576: }
577:
578:
579: /* ============================
580: -
581: -
582: - Lmaplist
583: - ==============================*/
584:
585: lispval
586: Lmaplist()
587: {
588: return(Lmapcrx(1,0)); /* call general routine */
589: }
590:
591:
592: /* ================================================
593: - mapping functions which return the value of the last function application.
594: - mapc and map
595: - ===================================================*/
596:
597: lispval
598: Lmapcx(maptyp)
599: int maptyp; /* 0= mapc , 1= map */
600: {
601: register struct argent *namptr;
602: register index;
603: register lispval temp;
604: register lispval result;
605:
606: int count;
607: struct argent *first;
608: lispval lists[25], errorh();
609: Savestack(4);
610:
611: namptr = lbot + 1;
612: count = np - namptr;
613: if(count <= 0) return(nil);
614: result = lbot[1].val; /*This is what macsyma wants so ... */
615: /*copy funarg for call to funcall */
616: lbot = np; protect((namptr - 1)->val);
617: first = np; np += count;
618:
619: for(index = 0; index < count; index++) {
620: temp = (namptr++)->val;
621: while(temp!=nil && TYPE(temp)!=DTPR)
622: temp = errorh1(Vermisc,"Inappropriate list argument to mapc",nil,TRUE,0,temp);
623: lists[index] = temp;
624: }
625: for(;;) {
626: for(namptr=first,index=0; index<count; index++) {
627: temp = lists[index];
628: if(temp==nil)
629: goto done;
630: if(maptyp==0)
631: (namptr++)->val = temp->d.car;
632: else
633: (namptr++)->val = temp;
634: lists[index] = temp->d.cdr;
635: }
636: Lfuncal();
637: }
638: done:
639: Restorestack();
640: return(result);
641: }
642:
643:
644: /* ==================================
645: -
646: - mapc map the car of the lists
647: -
648: - ==================================*/
649:
650: lispval
651: Lmapc()
652: { return( Lmapcx(0) ); }
653:
654:
655: /* =================================
656: -
657: - map map the cdr of the lists
658: -
659: - ===================================*/
660:
661: lispval
662: Lmap()
663: { return( Lmapcx(1) ); }
664:
665:
666: lispval
667: Lmapcan()
668: {
669: lispval Lmapcrx();
670:
671: return ( Lmapcrx ( 0,1 ) );
672: }
673:
674: lispval
675: Lmapcon()
676: {
677: lispval Lmapcrx();
678:
679: return ( Lmapcrx ( 1,1 ) );
680: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.