|
|
1.1 root 1: #ifndef lint
2: static char *rcsid =
3: "$Header: lam6.c,v 1.7 85/03/24 11:04:21 sklower Exp $";
4: #endif
5:
6: /* -[Sun Sep 4 08:56:19 1983 by jkf]-
7: * lam6.c $Locker: $
8: * lambda functions
9: *
10: * (c) copyright 1982, Regents of the University of California
11: */
12:
13: #include "global.h"
14: #include "frame.h"
15: #include <signal.h>
16: #include <sys/types.h>
17: #include <sys/times.h>
18: #include "chkrtab.h"
19: #include "chars.h"
20:
21:
22: lispval
23: Lreadli()
24: {
25: register lispval work, handy;
26: register FILE *p;
27: register char *string; char *alloca();
28: FILE *fstopen();
29: lispval Lread();
30: int count;
31: pbuf pb;
32: Savestack(4);
33: #ifdef SPISFP
34: Keepxs();
35: #endif
36:
37: if(lbot->val==nil) { /*effectively, return(matom(""));*/
38: strbuf[0] = 0;
39: return(getatom(FALSE));
40: }
41: chkarg(1,"readlist");
42: count = 1;
43:
44: /* compute length of list */
45: for(work = lbot->val; TYPE(work)==DTPR; work=work->d.cdr)
46: count++;
47: string = alloca(count);
48: p = fstopen(string, count - 1, "r");
49: for(work = lbot->val; TYPE(work)==DTPR; work=work->d.cdr) {
50: handy = work->d.car;
51: switch(TYPE(handy)) {
52: case SDOT:
53: case INT:
54: *string++=handy->i;
55: break;
56: case ATOM:
57: *string++ = *(handy->a.pname);
58: break;
59: case STRNG:
60: *string++ = *(char *)handy;
61: break;
62: default:
63: fclose(p);
64: error("Non atom or int to readlist",FALSE);
65: }
66: }
67: *string = 0;
68: errp = Pushframe(F_CATCH,Veruwpt,nil); /* must unwind protect
69: so can deallocate p
70: */
71: switch(retval) { lispval Lctcherr();
72: case C_THROW:
73: /* an error has occured and we are given a chance
74: to unwind before the control goes higher
75: lispretval contains the error descriptor in
76: it's cdr
77: */
78: fclose(p); /* free port */
79: errp = Popframe();
80: Freexs();
81: lbot = np;
82: protect(lispretval->d.cdr); /* error descriptor */
83: return(Lctcherr()); /* do a I-do-throw */
84:
85: case C_INITIAL:
86: lbot = np;
87: protect(P(p));
88: work = Lread(); /* error could occur here */
89: Freexs();
90: fclose(p); /* whew.. no errors */
91: errp = Popframe(); /* remove unwind-protect */
92: Restorestack();
93: return(work);
94: }
95: /* NOTREACHED */
96: }
97:
98: lispval
99: Lgetenv()
100: {
101: char *getenv(), *strcpy();
102: char *res;
103: chkarg(1,"getenv");
104:
105:
106: if((TYPE(lbot->val))!=ATOM)
107: error("argument to getenv must be atom",FALSE);
108:
109: res = getenv(lbot->val->a.pname);
110: if(res) strcpy(strbuf,res);
111: else strbuf[0] = '\0';
112: return(getatom(FALSE));
113: }
114:
115: lispval
116: Lboundp()
117: {
118: register lispval result, handy;
119:
120: chkarg(1,"boundp");
121:
122: if((TYPE(lbot->val))!=ATOM)
123: error("argument to boundp must be symbol",FALSE);
124: if( (handy = lbot->val)->a.clb==CNIL)
125: result = nil;
126: else
127: (result = newdot())->d.cdr = handy->a.clb;
128: return(result);
129: }
130:
131:
132: lispval
133: Lplist()
134: {
135: register lispval atm;
136: /* get property list of an atom or disembodied property list */
137:
138: chkarg(1,"plist");
139: atm = lbot->val;
140: switch(TYPE(atm)) {
141: case ATOM:
142: case DTPR:
143: break;
144: default:
145: error("Only Atoms and disembodied property lists allowed for plist",FALSE);
146: }
147: if(atm==nil) return(nilplist);
148: return(atm->a.plist);
149: }
150:
151:
152: lispval
153: Lsetpli()
154: { /* set the property list of the given atom to the given list */
155: register lispval atm, vall;
156:
157: chkarg(2,"setplist");
158: atm = lbot->val;
159: if (TYPE(atm) != ATOM)
160: error("setplist: First argument must be an symbol",FALSE);
161: vall = (np-1)->val;
162: if (TYPE(vall)!= DTPR && vall !=nil)
163: error("setplist: Second argument must be a list",FALSE);
164: if (atm==nil)
165: nilplist = vall;
166: else
167: atm->a.plist = vall;
168: return(vall);
169: }
170:
171: lispval
172: Lsignal()
173: {
174: register lispval handy, old, routine;
175: int i;
176: int sginth();
177:
178: switch(np-lbot) {
179:
180: case 1: routine = nil; /* second arg defaults to nil */
181: break;
182:
183: case 2: routine = lbot[1].val;
184: break; /* both args given */
185:
186: default: argerr("signal");
187: }
188:
189: handy = lbot->val;
190: if(TYPE(handy)!=INT)
191: error("First arg to signal must be an int",FALSE);
192: i = handy->i & 15;
193:
194: if(TYPE(routine)!=ATOM)
195: error("Second arg to signal must be an atom",FALSE);
196: old = sigacts[i];
197:
198: if(old==0) old = nil;
199:
200: if(routine==nil)
201: sigacts[i]=((lispval) 0);
202: else
203: sigacts[i]=routine;
204: if(routine == nil)
205: signal(i,SIG_IGN); /* ignore this signals */
206: else if (old == nil)
207: signal(i,sginth); /* look for this signal */
208: if(i == SIGINT) sigintcnt = 0; /* clear memory */
209: return(old);
210: }
211:
212: lispval
213: Lassq()
214: {
215: register lispval work, handy;
216:
217: chkarg(2,"assq");
218:
219: for(work = lbot[1].val, handy = lbot[0].val;
220: (work->d.car->d.car != handy) && (work != nil);
221: work = work->d.cdr);
222: return(work->d.car);
223: }
224:
225: lispval
226: Lkilcopy()
227: {
228: if(fork()==0) {
229: abort();
230: }
231: }
232:
233: lispval
234: Larg()
235: {
236: register lispval handy; register offset, count;
237:
238: handy = lexpr_atom->a.clb;
239: if(handy==CNIL || TYPE(handy)!=DTPR)
240: error("Arg: not in context of Lexpr.",FALSE);
241: count = ((long *)handy->d.cdr) -1 - (long *)handy->d.car;
242: if(np==lbot || lbot->val==nil)
243: return(inewint(count+1));
244: if(TYPE(lbot->val)!=INT || (offset = lbot->val->i - 1) > count || offset < 0 )
245: error("Out of bounds: arg to \"Arg\"",FALSE);
246: return( ((struct argent *)handy->d.car)[offset].val);
247: }
248:
249: lispval
250: Lsetarg()
251: {
252: register lispval handy, work;
253: register limit, index;
254:
255: chkarg(2,"setarg");
256: handy = lexpr_atom->a.clb;
257: if(handy==CNIL || TYPE(handy)!=DTPR)
258: error("Arg: not in context of Lexpr.",FALSE);
259: limit = ((long *)handy->d.cdr) - 1 - (long *)(work = handy->d.car);
260: handy = lbot->val;
261: if(TYPE(handy)!=INT)
262: error("setarg: first argument not integer",FALSE);
263: if((index = handy->i - 1) < 0 || index > limit)
264: error("setarg: index out of range",FALSE);
265: return(((struct argent *) work)[index].val = lbot[1].val);
266: }
267:
268: lispval
269: Lptime(){
270: extern int gctime;
271: int lgctime = gctime;
272: struct tms current;
273: register lispval result, handy;
274: Savestack(2);
275:
276: times(¤t);
277: result = newdot();
278: handy = result;
279: protect(result);
280: result->d.cdr = newdot();
281: result->d.car = inewint(current.tms_utime);
282: handy = result->d.cdr;
283: handy->d.car = inewint(lgctime);
284: handy->d.cdr = nil;
285: if(gctime==0)
286: gctime = 1;
287: Restorestack();
288: return(result);
289: }
290:
291: /* (err-with-message message [value])
292: 'message' is the error message to print.
293: 'value' is the value to return from the errset (if present).
294: it defaults to nil.
295: The message may not be printed if there is an (errset ... nil)
296: pending.
297: */
298:
299: lispval Lerr()
300: {
301: lispval errorh();
302: lispval valret = nil;
303: char *mesg;
304:
305:
306: switch(np-lbot) {
307: case 2: valret = lbot[1].val; /* return non nil */
308: case 1: mesg = (char *)verify(lbot[0].val,
309: "err-with-message: non atom or string arg");
310: break;
311: default: argerr("err-with-message");
312: }
313:
314: return(errorh(Vererr,mesg,valret,FALSE,1));
315: }
316:
317: /*
318: * (tyi ['p_port ['g_eofval]])
319: * normally -1 is return on eof, but g_eofval will be returned if given.
320: */
321: lispval
322: Ltyi()
323: {
324: register FILE *port;
325: register lispval handy;
326: lispval eofval;
327: int val; /* really char but getc returns int on eof */
328: int eofvalgiven;
329:
330: handy = nil; /* default port */
331: eofvalgiven = FALSE; /* assume no eof value given */
332: switch(np-lbot)
333: {
334: case 2: eofval = lbot[1].val;
335: eofvalgiven = TRUE;
336: case 1: handy = lbot[0].val; /* port to read */
337: case 0:
338: break;
339: default: argerr("tyi");
340: }
341:
342: port = okport(handy,okport(Vpiport->a.clb,stdin));
343:
344:
345: fflush(stdout); /* flush any pending output characters */
346: val = getc(port);
347: if(val==EOF)
348: {
349: clearerr(port);
350: if(sigintcnt > 0) sigcall(SIGINT); /* eof might mean int */
351: if(eofvalgiven) return(eofval);
352: else return(inewint(-1));
353: }
354: return(inewint(val));
355: }
356:
357: /* Untyi (added by DNC Feb. '80) - (untyi number port) puts the
358: character with ascii code number in the front of the input buffer of
359: port. Note that this buffer is limited to 1 character. That buffer is
360: also written by tyipeek, so a peek followed by an untyi will result in
361: the loss of the peeked char.
362: */
363:
364: lispval
365: Luntyi()
366: {
367:
368: lispval port,ch;
369:
370: port = nil;
371:
372: switch(np-lbot) {
373: case 2: port = lbot[1].val;
374: case 1: ch = lbot[0].val;
375: break;
376: default:
377: argerr("untyi");
378: }
379:
380: if(TYPE(ch) != INT) {
381: errorh1(Vermisc, "untyi: expects fixnum character ",
382: nil,FALSE,0,ch);
383: }
384:
385: ungetc((int) ch->i,okport(port,okport(Vpiport->a.clb,stdin)));
386: return(ch);
387: }
388:
389: lispval
390: Ltyipeek()
391: {
392: register FILE *port;
393: register lispval handy;
394: int val;
395:
396: switch(np-lbot)
397: {
398: case 0: handy = nil; /* default port */
399: break;
400: case 1: handy = lbot->val;
401: break;
402: default: argerr("tyipeek");
403: }
404:
405: port = okport(handy,okport(Vpiport->a.clb,stdin));
406:
407: fflush(stdout); /* flush any pending output characters */
408: val = getc(port);
409: if(val==EOF)
410: clearerr(port);
411: ungetc(val,port);
412: return(inewint(val));
413: }
414:
415: lispval
416: Ltyo()
417: {
418: register FILE *port;
419: register lispval handy, where;
420: char val;
421:
422: switch(np-lbot)
423: {
424: case 1: where = nil; /* default port */
425: break;
426: case 2: where = lbot[1].val;
427: break;
428: default: argerr("tyo");
429: }
430:
431: handy = lbot->val;
432: if(TYPE(handy)!=INT)
433: error("Tyo demands number for 1st arg",FALSE);
434: val = handy->i;
435:
436: port = (FILE *) okport(where,okport(Vpoport->a.clb,stdout));
437: putc(val,port);
438: return(handy);
439: }
440:
441: lispval
442: Imkrtab(current)
443: {
444: extern struct rtab {
445: unsigned char ctable[132];
446: } initread;
447: register lispval handy; extern lispval lastrtab;
448:
449: static int cycle = 0;
450: static char *nextfree;
451: Savestack(3);
452:
453: if((cycle++)%3==0) {
454: nextfree = (char *) csegment(STRNG,1,FALSE);
455: mrtabspace = (lispval) nextfree;
456: /* need to protect partially allocated read tables
457: from garbage collection. */
458: }
459: handy = newarray();
460: protect(handy);
461:
462: handy->ar.data = nextfree;
463: if(current == 0)
464: *(struct rtab *)nextfree = initread;
465: else
466: {
467: register index = 0; register char *cp = nextfree;
468: lispval c;
469:
470: *(struct rtab *)cp = *(struct rtab *)ctable;
471: for(; index < 128; index++) {
472: switch(synclass(cp[index])) {
473: case CSPL: case CSSPL: case CMAC: case CSMAC:
474: case CINF: case CSINF:
475: strbuf[0] = index;
476: strbuf[1] = 0;
477: c = (getatom(TRUE));
478: Iputprop(c,Iget(c,lastrtab),handy);
479: }
480: }
481: }
482: handy->ar.delta = inewint(4);
483: handy->ar.length = inewint(sizeof(struct rtab)/sizeof(int));
484: handy->ar.accfun = handy->ar.aux = nil;
485: nextfree += sizeof(struct rtab);
486: Restorestack();
487: return(handy);
488: }
489:
490: /* makereadtable - arg : t or nil
491: returns a readtable, t means return a copy of the initial readtable
492:
493: nil means return a copy of the current readtable
494: */
495: lispval
496: Lmakertbl()
497: {
498: lispval handy = Vreadtable->a.clb;
499: lispval value;
500: chkrtab(handy);
501:
502: if(lbot==np) value = nil;
503: else if(TYPE(value=(lbot->val)) != ATOM)
504: error("makereadtable: arg must be atom",FALSE);
505:
506: if(value == nil) return(Imkrtab(1));
507: else return(Imkrtab(0));
508: }
509:
510: lispval
511: Lcpy1()
512: {
513: register lispval handy = lbot->val, result = handy;
514:
515: top:
516: switch(TYPE(handy))
517: {
518: case INT:
519: result = inewint(handy->i);
520: break;
521: case VALUE:
522: (result = newval())->l = handy->l;
523: break;
524: case DOUB:
525: (result = newdoub())->r = handy->r;
526: break;
527: default:
528: lbot->val =
529: errorh1(Vermisc,"Bad arg to cpy1",nil,TRUE,67,handy);
530: goto top;
531: }
532: return(result);
533: }
534:
535: /* copyint* . This returns a copy of its integer argument. The copy will
536: * be a fresh integer cell, and will not point into the read only
537: * small integer table.
538: */
539: lispval
540: Lcopyint()
541: {
542: register lispval handy = lbot->val;
543: register lispval ret;
544:
545: while (TYPE(handy) != INT)
546: { handy=errorh1(Vermisc,"copyint* : non integer arg",nil,TRUE,0,handy);}
547: (ret = newint())->i = handy->i;
548: return(ret);
549: }
550:
551:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.