|
|
1.1 root 1:
2: # include "global.h"
3: # include <sgtty.h>
4: # include "chkrtab.h"
5: /**************************************************************************/
6: /* */
7: /* file: ccdfns.i */
8: /* contents: LISP functions coded in C */
9: /* */
10: /* These include LISP primitives, numeric and boolean functions and */
11: /* predicates, some list-processing functions, i/o support functions */
12: /* and control flow functions (e.g. cont, break). */
13: /* There are two types of functions: lambda (prefixed "L") and nlambda */
14: /* (prefixed "N"). */
15: /* Lambda's all call chkarg to insure that at least the minimum number */
16: /* of necessary arguments are on the namestack. */
17: /* All functions take their arguments from the namestack in a read- */
18: /* only manner, and return their results via the normal C value */
19: /* return mechanism. */
20: /* */
21:
22:
23:
24: lispval
25: Leval()
26: {
27: register lispval temp;
28:
29: chkarg(1);
30: temp = lbot->val;
31: return(eval(temp));
32: }
33:
34: lispval
35: Lxcar()
36: { register int typ;
37: register lispval temp, result;
38:
39: chkarg(1);
40: temp = lbot->val;
41: if (((typ = TYPE(temp)) == DTPR) || (typ == ATOM))
42: return(temp -> car);
43: else if(typ == SDOT) {
44: result = inewint(temp->i);
45: return(result);
46: } else if(Schainp!=nil && typ==ATOM)
47: return(nil);
48: else
49: return(error("BAD ARG TO CAR",FALSE));
50:
51: }
52:
53: lispval
54: Lxcdr()
55: { register int typ;
56: register lispval temp, result;
57:
58: chkarg(1);
59: temp = lbot->val;
60: if(temp==nil) return (nil);
61:
62: if ((typ = TYPE(temp)) == DTPR)
63: return(temp -> cdr);
64: else if(typ==SDOT) {
65: if(temp->CDR==0) return(nil);
66: return(temp->CDR);
67: } else if(Schainp!=nil && typ==ATOM)
68: return(nil);
69: else
70: return(error("BAD ARG TO CDR",FALSE));
71: }
72:
73: lispval
74: cxxr(as,ds)
75: register int as,ds;
76: {
77:
78: register lispval temp, temp2;
79: int i, typ;
80: lispval errorh();
81:
82: chkarg(1);
83: temp = lbot->val;
84:
85: for( i=0 ; i<ds ; i++)
86: {
87: if( temp != nil)
88: {
89: if ((typ = TYPE(temp)) == DTPR)
90: temp = temp -> cdr;
91: else if(typ==SDOT) {
92: if(temp->CDR==0) temp = nil;
93: else temp = temp->CDR;
94: }
95: else if(Schainp!=nil && typ==ATOM)
96: return(nil);
97: else
98: return(errorh(Vermisc,"BAD ARG TO CDR",nil,FALSE,5,temp));
99: }
100: }
101:
102: for( i=0 ; i<as ; i++)
103: {
104: if( temp != nil )
105: {
106: if ((typ = TYPE(temp)) == DTPR)
107: temp = temp -> car;
108: else if(typ == SDOT)
109: temp2 = inewint(temp->i), temp = temp2;
110: else if(Schainp!=nil && typ==ATOM)
111: return(nil);
112: else
113: return(errorh(Vermisc,"BAD ARG TO CAR",nil,FALSE,5,temp));
114: }
115: }
116:
117: return(temp);
118: }
119:
120:
121: lispval
122: Lcar()
123: { return(cxxr(1,0));
124: }
125:
126: lispval
127: Lcdr()
128: { return(cxxr(0,1));
129: }
130:
131: lispval
132: Lcadr()
133: { return(cxxr(1,1));
134: }
135:
136: lispval
137: Lcaar()
138: { return(cxxr(2,0));
139: }
140:
141: lispval
142: Lc02r()
143: { return(cxxr(0,2)); /* cddr */
144: }
145:
146: lispval
147: Lc12r()
148: { return(cxxr(1,2)); /* caddr */
149: }
150:
151: lispval
152: Lc03r()
153: { return(cxxr(0,3)); /* cdddr */
154: }
155:
156: lispval
157: Lc13r()
158: { return(cxxr(1,3)); /* cadddr */
159: }
160:
161: lispval
162: Lc04r()
163: { return(cxxr(0,4)); /* cddddr */
164: }
165:
166: lispval
167: Lc14r()
168: { return(cxxr(1,4)); /* caddddr */
169: }
170:
171: /*************************
172: *
173: * (nthelem num list)
174: * returns the num'th element of the list, by doing a caddddd...ddr
175: * where there are num-1 d's
176: * if num<=0 or greater than the length of the list, we return nil
177: ******************************************************/
178:
179: lispval
180: Lnthelem()
181: {
182: register lispval temp;
183: register int i;
184:
185: chkarg(2);
186:
187: if( TYPE(temp = lbot->val) != INT)
188: return (error ("First arg to nthelem must be a fixnum",FALSE));
189:
190: i = temp->i; /* pick up the first arg */
191:
192: if( i <= 0) return(nil);
193:
194: ++lbot; /* fix lbot for call to cxxr() 'cadddd..r' */
195: temp = cxxr(1,i-1);
196: --lbot;
197:
198: return(temp);
199: }
200:
201:
202:
203:
204:
205: lispval
206: Lscons()
207: {
208: register struct argent *argp = lbot;
209: register lispval retp, handy;
210: register int typ;
211:
212: chkarg(2);
213: retp = newsdot();
214: handy = (argp) -> val;
215: if(TYPE(handy)!=INT)
216: error("First arg to scons must be an int.",FALSE);
217: retp->I = handy->i;
218: handy = (argp+1)->val;
219: if(handy==nil)
220: retp->CDR = (lispval) 0;
221: else {
222: if(TYPE(handy)!=SDOT)
223: error("Currently you may only link sdots to sdots.",FALSE);
224: retp->CDR = handy;
225: }
226: return(retp);
227: }
228: lispval
229: Lcons()
230: { register struct argent *argp;
231: lispval retp;
232:
233: chkarg(2);
234: retp = newdot();
235: retp -> cdr = ((argp = np-1) -> val);
236: retp -> car = (--argp) -> val;
237: return(retp);
238: }
239: #define CA 0
240: #define CD 1
241:
242: lispval
243: rpla(what)
244: int what;
245: { register struct argent *argp;
246: register int typ; register lispval first, second;
247:
248: chkarg(2);
249: argp = np-1;
250: first = (argp-1)->val;
251: while(first==nil)
252: first = error("Attempt to rplac[ad] nil.",TRUE);
253: second = argp->val;
254: if (((typ = TYPE(first)) == DTPR) || (typ == ATOM)) {
255: if (what == CA)
256: first->car = second;
257: else
258: first->cdr = second;
259: return(first);
260: }
261: if (typ==SDOT) {
262: if(what == CA) {
263: typ = TYPE(second);
264: if(typ!=INT) error("Rplacca of a bignum will only replace INTS",FALSE);
265: first->i = second->i;
266: } else {
267: if(second==nil)
268: first->CDR = (lispval) 0;
269: else
270: first->CDR = second;
271: }
272: return(first);
273: }
274: return(error("BAD ARG TO RPLA",FALSE));
275: }
276: lispval
277: Lrplaca()
278: { return(rpla(CA)); }
279:
280: lispval
281: Lrplacd()
282: { return(rpla(CD)); }
283:
284:
285: lispval
286: Leq()
287: {
288: register struct argent *mynp = lbot + AD;
289: int itemp, flag;
290:
291: chkarg(2);
292: if(mynp->val==(mynp+1)->val) return(tatom);
293: return(nil);
294: }
295:
296:
297:
298: lispval
299: Lnull()
300: { chkarg(1);
301: return ((lbot->val == nil) ? tatom : nil);
302: }
303:
304:
305:
306: /* Lreturn **************************************************************/
307: /* Returns the first argument - which is nill if not specified. */
308: Lreturn()
309: {
310: chkarg(1);
311: contval = lbot->val;
312: reset(BRRETN);
313: }
314:
315:
316: /* Lretbrk **************************************************************/
317: /* The first argument must be an integer and must be in the range */
318: /* -1 .. -depth. */
319: lispval
320: Lretbrk()
321: {
322: lispval number;
323: register level;
324:
325:
326: chkarg(1);
327: number = lbot->val;
328: if (TYPE(number) != INT)
329: level = -1;
330: else
331: level = number->i;
332: if(level < 0)
333: level += depth;
334: contval = (lispval) level;
335: if (level < depth)
336: reset(BRRETB);
337: return(nil);
338: }
339:
340:
341:
342: lispval
343: Linfile()
344: {
345: FILE *port;
346: register lispval name;
347: snpand(1);
348:
349: chkarg(1);
350: name = lbot->val;
351: while (TYPE(name)!=ATOM)
352: name = error("Please supply atom name for port.",TRUE);
353: /* return nil if file couldnt be opened
354: if ((port = fopen(name->pname,"r")) == NULL) return(nil); */
355:
356: while ((port = fopen(name->pname,"r")) == NULL)
357: name = errorh(Vermisc,"Unable to open file for reading.",nil,TRUE,31,name);
358:
359: return((lispval)(xports + (port - _iob)));
360: }
361:
362: lispval
363: Loutfile()
364: {
365: FILE *port; register lispval name;
366:
367: chkarg(1);
368: name = lbot->val;
369: while (TYPE(name)!=ATOM)
370: name = error("Please supply atom name for port.",TRUE);
371: while ((port = fopen(name->pname,"w")) == NULL)
372: name = errorh(Vermisc,"Unable to open file for writing.",nil,TRUE,31,name);
373: return((lispval)(xports + (port - _iob)));
374: }
375: lispval
376: Lterpr()
377: {
378: FILE *port;
379:
380: chkarg(1);
381: port = okport(lbot->val,okport(Vpoport->clb,stdout));
382: putc('\n',port);
383: fflush(port);
384: return(nil);
385: }
386: lispval
387: Lclose()
388: {
389: lispval port;
390:
391: if(lbot==np)
392: port = error("Close requires one argument of type port",TRUE);
393: port = lbot->val;
394: if((TYPE(port))==PORT) fclose(port->p);
395: return(tatom);
396: }
397:
398: lispval
399: Lnwritn()
400: {
401: register FILE *port;
402: register value;
403:
404: chkarg(1);
405: port = okport(lbot->val,okport(Vpoport->clb,stdout));
406: value = port->_ptr - port->_base;
407: return(inewint(value));
408: }
409:
410: lispval
411: Ldrain()
412: {
413: register FILE *port;
414: register int iodes;
415: struct sgttyb arg;
416:
417: chkarg(1);
418: port = okport(lbot->val, okport(Vpoport->clb,stdout));
419: if(port->_flag & _IOWRT) {
420: fflush(port);
421: return(nil);
422: }
423: if(! port->_flag & _IOREAD) return(nil);
424: port->_cnt = 0;
425: port->_ptr = port->_base;
426: iodes = fileno(port);
427: if(gtty(iodes,&arg) != -1) stty(iodes,&arg);
428: return((lispval)(xports + (port - _iob)));
429: }
430: lispval
431: Llist()
432: {
433: /* added for the benefit of mapping functions. */
434: register struct argent *ulim, *namptr;
435: register lispval temp, result;
436: register struct argent *lbot, *np;
437:
438: ulim = np;
439: namptr = lbot + AD;
440: temp = result = (lispval) np;
441: protect(nil);
442: for(; namptr < ulim;) {
443: temp = temp->l = newdot();
444: temp->car = (namptr++)->val;
445: }
446: temp->l = nil;
447: return(result->l);
448: }
449:
450: lispval
451: Lnumberp()
452: {
453: chkarg(1);
454: switch(TYPE(lbot->val)) {
455: case INT: case DOUB: case SDOT:
456: return(tatom);
457: }
458: return(nil);
459: }
460:
461: lispval
462: Latom()
463: {
464: chkarg(1);
465: if(TYPE(lbot->val)==DTPR)
466: return(nil);
467: else
468: return(tatom);
469: }
470: lispval
471: Ltype()
472: {
473: chkarg(1);
474: switch(TYPE(lbot->val)) {
475: case INT:
476: return(int_name);
477: case ATOM:
478: return(atom_name);
479: case SDOT:
480: return(sdot_name);
481: case DOUB:
482: return(doub_name);
483: case DTPR:
484: return(dtpr_name);
485: case STRNG:
486: return(str_name);
487: case ARRAY:
488: return(array_name);
489: case BCD:
490: return(funct_name);
491: case VALUE:
492: return(val_name);
493: case PORT:
494: return(matom("port")); /* fix this when name exists */
495: }
496: return(nil);
497: }
498:
499: lispval
500: Ldtpr()
501: {
502: chkarg(1);
503: return(typred(DTPR,lbot->val));
504: }
505:
506: lispval
507: Lbcdp()
508: {
509: chkarg(1);
510: return(typred(BCD,lbot->val));
511: }
512:
513: lispval
514: Lportp()
515: {
516: chkarg(1);
517: return(typred(PORT,lbot->val));
518: }
519:
520: lispval
521: Larrayp()
522: {
523: chkarg(1);
524: return(typred(ARRAY,lbot->val));
525: }
526: lispval
527: Lset()
528: {
529: lispval varble;
530: snpand(0);
531:
532: chkarg(2);
533: varble = lbot->val;
534: switch(TYPE(varble))
535: {
536: case ATOM: return(varble->clb = lbot[1].val);
537:
538: case VALUE: return(varble->l = lbot[1].val);
539: }
540:
541: error("IMPROPER USE OF SET",FALSE);
542: }
543: lispval
544: Lequal()
545: {
546: chkarg(2);
547:
548: if( lbot[1].val == lbot->val ) return(tatom);
549: if(Iequal(lbot[1].val,lbot->val)) return(tatom); else return(nil);
550: }
551:
552: Iequal(first,second)
553: register lispval first, second;
554: {
555: register type1, type2;
556: register struct argent *lbot, *np;
557: lispval Lsub(),Lzerop();
558:
559: if(first==second)
560: return(1);
561: type1=TYPE(first);
562: type2=TYPE(second);
563: if(type1!=type2) {
564: if((type1==SDOT&&type2==INT)||(type1==INT&&type2==SDOT))
565: goto dosub;
566: return(0);
567: }
568: switch(type1) {
569: case DTPR:
570: return(
571: Iequal(first->car,second->car) &&
572: Iequal(first->cdr,second->cdr) );
573: case DOUB:
574: return(first->r==second->r);
575: case INT:
576: return( (first->i==second->i));
577: dosub:
578: case SDOT:
579: lbot = np;
580: np++->val = first;
581: np++->val = second;
582: lbot->val = Lsub();
583: np = lbot + 1;
584: return(Lzerop()!=nil);
585: case VALUE:
586: return( first->l==second->l );
587: case STRNG:
588: return(strcmp(first,second)==0);
589: }
590: return(0);
591: }
592:
593: lispval
594: Lprint()
595: {
596: chkarg(2);
597: chkrtab(Vreadtable->clb);
598: printr(lbot->val,okport(lbot[1].val,okport(Vpoport->clb,poport)));
599: return(nil);
600: }
601:
602: FILE *
603: okport(arg,proper)
604: lispval arg;
605: FILE *proper;
606: {
607: if(TYPE(arg)!=PORT)
608: return(proper);
609: else
610: return(arg->p);
611: }
612: lispval
613: Lpatom()
614: {
615: register lispval temp;
616: FILE *port;
617:
618: chkarg(2);
619: temp = Vreadtable->clb;
620: chkrtab(temp);
621: port = okport(lbot[1].val, okport(Vpoport->clb,stdout));
622: if ((TYPE((temp = (lbot)->val)))!=ATOM)
623: printr(temp, port);
624: else
625: fputs(temp->pname, port);
626: return(temp);
627: }
628:
629: /*
630: * (pntlen thing) returns the length it takes to print out
631: * an atom or number.
632: */
633:
634: lispval
635: Lpntlen()
636: {
637: register lispval temp;
638: return(inewint(Ipntlen()));
639: }
640: Ipntlen()
641: {
642: register lispval temp;
643: register char *handy;
644:
645: temp = np[-1].val;
646: loop: switch(TYPE(temp)) {
647:
648: case ATOM:
649: handy = temp->pname;
650: break;
651:
652: case INT:
653: sprintf(strbuf,"%d",temp->i);
654: handy =strbuf;
655: break;
656:
657: case DOUB:
658: sprintf(strbuf,"%g",temp->r);
659: handy =strbuf;
660: break;
661:
662: default:
663: temp = error("Non atom or number to pntlen\n",TRUE);
664: goto loop;
665: }
666:
667: return( strlen(handy));
668: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.