BSD 4_4 development
[unix-history] / usr / src / old / lisp / franz / fex1.c
CommitLineData
73350edc
C
1#ifndef lint
2static char *rcsid =
3 "$Header: fex1.c,v 1.5 85/03/24 11:03:51 sklower Exp $";
4#endif
5
6/* -[Sat Mar 5 19:50:28 1983 by layer]-
7 * fex1.c $Locker: $
8 * nlambda functions
9 *
10 * (c) copyright 1982, Regents of the University of California
11 */
12
13
14#include "global.h"
15#include "frame.h"
16
17/* Nprog ****************************************************************/
18/* This first sets the local variables to nil while saving their old */
19/* values on the name stack. Then, pointers to various things are */
20/* saved as this function may be returned to by an "Ngo" or by a */
21/* "Lreturn". At the end is the loop that cycles through the contents */
22/* of the prog. */
23
24lispval
25Nprog() {
26 register lispval where, temp;
27 struct nament *savedbnp = bnp;
28 extern struct frame *errp;
29 pbuf pb;
30 extern int retval;
31 extern lispval lispretval;
32
33 if((np-lbot) < 1) chkarg(1,"prog");
34
35 /* shallow bind the local variables to nil */
36 if(lbot->val->d.car != nil)
37 {
38 for( where = lbot->val->d.car ; where != nil; where = where->d.cdr )
39 {
40 if(TYPE(where) != DTPR || TYPE(temp=where->d.car) != ATOM)
41 errorh1(Vermisc,
42 "Illegal local variable list in prog ",nil,FALSE,
43 1,where);
44 PUSHDOWN(temp,nil);
45 }
46 }
47
48 /* put a frame on the stack which can be 'return'ed to or 'go'ed to */
49 errp = Pushframe(F_PROG,nil,nil);
50
51 where = lbot->val->d.cdr; /* first thing in the prog body */
52
53 switch (retval) {
54 case C_RET: /*
55 * returning from this prog, value to return
56 * is in lispretval
57 */
58 errp = Popframe();
59 popnames(savedbnp);
60 return(lispretval);
61
62 case C_GO: /*
63 * going to a certain label, label to go to in
64 * in lispretval
65 */
66 where = (lbot->val)->d.cdr;
67 while ((TYPE(where) == DTPR)
68 && (where->d.car != lispretval))
69 where = where->d.cdr;
70 if (where->d.car == lispretval) {
71 popnames(errp->svbnp);
72 break;
73 }
74 /* label not found in this prog, must
75 * go up to higher prog
76 */
77 errp = Popframe(); /* go to next frame */
78 Inonlocalgo(C_GO,lispretval,nil);
79
80 /* NOT REACHED */
81
82 case C_INITIAL: break;
83
84 }
85
86 while (TYPE(where) == DTPR)
87 {
88 temp = where->d.car;
89 if((TYPE(temp))!=ATOM) eval(temp);
90 where = where->d.cdr;
91 }
92 if((where != nil) && (TYPE(where) != DTPR))
93 errorh1(Vermisc,"Illegal form in prog body ", nil,FALSE,0,where);
94 errp = Popframe();
95 popnames(savedbnp); /* pop off locals */
96 return(nil);
97}
98
99lispval globtag;
100/*
101 Ncatch is now linked to the lisp symbol *catch , which has the form
102 (*catch tag form)
103 tag is evaluated and then the catch entry is set up.
104 then form is evaluated
105 finally the catch entry is removed.
106
107 *catch is still an nlambda since its arguments should not be evaluated
108 before this routine is called.
109
110 (catch form [tag]) is translated to (*catch 'tag form) by a macro.
111 */
112lispval
113Ncatch()
114{
115 register lispval tag;
116 pbuf pb;
117 Savestack(3); /* save stack pointers */
118
119 if((TYPE(lbot->val))!=DTPR) return(nil);
120 protect(tag = eval(lbot->val->d.car)); /* protect tag from gc */
121
122 errp = Pushframe(F_CATCH,tag,nil);
123
124 switch(retval) {
125
126 case C_THROW: /*
127 * value thrown is in lispretval
128 */
129 break;
130
131 case C_INITIAL: /*
132 * calculate value of expression
133 */
134 lispretval = eval(lbot->val->d.cdr->d.car);
135 }
136
137
138 errp = Popframe();
139 Restorestack();
140 return(lispretval);
141}
142/* (errset form [flag])
143 if present, flag determines if the error message will be printed
144 if an error reaches the errset.
145 if no error occurs, errset returns a list of one element, the
146 value returned from form.
147 if an error occurs, nil is usually returned although it could
148 be non nil if err threw a non nil value
149 */
150
151lispval Nerrset()
152{
153 lispval temp,flag;
154 pbuf pb;
155 Savestack(0);
156
157 if(TYPE(lbot->val) != DTPR) return(nil); /* no form */
158
159 /* evaluate and save flag first */
160 flag = lbot->val->d.cdr;
161 if(TYPE(flag) == DTPR) flag = eval(flag->d.car);
162 else flag = tatom; /* if not present , assume t */
163 protect(flag);
164
165 errp = Pushframe(F_CATCH,Verall,flag);
166
167 switch(retval) {
168
169 case C_THROW: /*
170 * error thrown to this routine, value thrown is
171 * in lispretval
172 */
173 break;
174
175 case C_INITIAL: /*
176 * normally just evaluate expression and listify it.
177 */
178 temp = eval(lbot->val->d.car);
179 protect(temp);
180 (lispretval = newdot())->d.car = temp;
181 break;
182 }
183
184 errp = Popframe();
185 Restorestack();
186 return(lispretval);
187}
188
189/* this was changed from throw to *throw 21nov79
190 it is now a lambda and really should be called Lthrow
191*/
192lispval
193Nthrow()
194{
195 switch(np-lbot) {
196 case 0:
197 protect(nil);
198 case 1:
199 protect(nil);
200 case 2: break;
201 default:
202 argerr("throw");
203 }
204 Inonlocalgo(C_THROW,lbot->val,(lbot+1)->val);
205 /* NOT REACHED */
206}
207
208
209
210/* Ngo ******************************************************************/
211/* First argument only is checked - and must be an atom or evaluate */
212/* to one. */
213lispval
214Ngo()
215{
216 register lispval temp;
217 chkarg(1,"go");
218
219 temp = (lbot->val)->d.car;
220 if (TYPE(temp) != ATOM)
221 {
222 temp = eval(temp);
223 while(TYPE(temp) != ATOM)
224 temp = errorh1(Vermisc,"Illegal tag to go to",nil,TRUE, 0,lbot->val);
225 }
226 Inonlocalgo(C_GO,temp,nil);
227 /* NOT REACHED */
228}
229
230
231/* Nreset ***************************************************************/
232/* All arguments are ignored. This just returns-from-break to depth 0. */
233lispval
234Nreset()
235{
236 Inonlocalgo(C_RESET,inewint(0),nil);
237}
238
239
240
241/* Nbreak ***************************************************************/
242/* If first argument is not nil, this is evaluated and printed. Then */
243/* error is called with the "breaking" message. */
244
245lispval
246Nbreak()
247{
248 register lispval hold; register FILE *port;
249 port = okport(Vpoport->a.clb,stdout);
250 fprintf(port,"Breaking:");
251
252 if ((hold = lbot->val) != nil && ((hold = hold->d.car) != nil))
253 {
254 printr(hold,port);
255 }
256 putc('\n',port);
257 dmpport(port);
258 return(errorh(Verbrk,"",nil,TRUE,0));
259}
260
261
262/* Nexit ****************************************************************/
263/* Just calls lispend with no message. */
264Nexit()
265 {
266 lispend("");
267 }
268
269
270/* Nsys *****************************************************************/
271/* Just calls lispend with no message. */
272
273lispval
274Nsys()
275 {
276 lispend("");
277 }
278
279
280
281
282lispval
283Ndef() {
284 register lispval arglist, body, name, form;
285
286 form = lbot->val;
287 name = form->d.car;
288 body = form->d.cdr->d.car;
289 arglist = body->d.cdr->d.car;
290 if((TYPE(arglist))!=DTPR && arglist != nil)
291 error("Warning: defining function with nonlist of args",
292 TRUE);
293 name->a.fnbnd = body;
294 return(name);
295}
296
297
298lispval
299Nquote()
300{
301 return((lbot->val)->d.car);
302}
303
304
305lispval
306Nsetq()
307{ register lispval handy, where, value;
308 register int lefttype;
309
310 value = nil;
311
312 for(where = lbot->val; where != nil; where = handy->d.cdr) {
313 handy = where->d.cdr;
314 if((TYPE(handy))!=DTPR)
315 error("odd number of args to setq",FALSE);
316 if((lefttype=TYPE(where->d.car))==ATOM) {
317 if(where->d.car==nil)
318 error("Attempt to set nil",FALSE);
319 where->d.car->a.clb = value = eval(handy->d.car);
320 }else if(lefttype==VALUE)
321 where->d.car->l = value = eval(handy->d.car);
322 else errorh1(Vermisc,
323 "Can only setq atoms or values",nil,FALSE,0,
324 where->d.car);
325 }
326 return(value);
327}
328
329
330lispval
331Ncond()
332{
333 register lispval where, last;
334
335 where = lbot->val;
336 last = nil;
337 for(;;) {
338 if ((TYPE(where))!=DTPR)
339 break;
340 if ((TYPE(where->d.car))!=DTPR)
341 break;
342 if ((last=eval((where->d.car)->d.car)) != nil)
343 break;
344 where = where->d.cdr;
345 }
346
347 if ((TYPE(where)) != DTPR)
348 return(nil);
349 where = (where->d.car)->d.cdr;
350 while ((TYPE(where))==DTPR) {
351 last = eval(where->d.car);
352 where = where->d.cdr;
353 }
354 return(last);
355}
356
357lispval
358Nand()
359{
360 register lispval current, temp;
361
362 current = lbot->val;
363 temp = tatom;
364 while (current != nil)
365 if ( (temp = current->d.car)!=nil && (temp = eval(temp))!=nil)
366 current = current->d.cdr;
367 else {
368 current = nil;
369 temp = nil;
370 }
371 return(temp);
372}
373
374
375lispval
376Nor()
377{
378 register lispval current, temp;
379
380 current = lbot->val;
381 temp = nil;
382 while (current != nil)
383 if ( (temp = eval(current->d.car)) == nil)
384 current = current->d.cdr;
385 else
386 break;
387 return(temp);
388}