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