|
|
1.1 root 1: #ifndef lint
2: static char *rcsid =
3: "$Header: error.c,v 1.5 83/09/12 14:17:50 sklower Exp $";
4: #endif
5:
6: /* -[Sun Sep 4 09:06:21 1983 by jkf]-
7: * error.c $Locker: $
8: * error handler
9: *
10: * (c) copyright 1982, Regents of the University of California
11: */
12:
13:
14: #include "global.h"
15: #include "frame.h"
16: #include "catchfram.h"
17:
18: static lispval IEargs[5];
19: static int IElimit;
20:
21: /* error
22: * this routine is always called on a non-fatal error. The first argu-
23: * ment is printed out. The second a boolean flag indicating if the
24: * error routine is permitted to return a pointer to a lisp value if
25: * the "cont" command is executed.
26: */
27:
28: /* error from lisp C code, this temporarily replaces the old error
29: * allowing us to interface with the new errset scheme with minimum
30: * difficulty. We assume that an error which comes to this routine
31: * is of an "undefined error type" ER%misc . Soon all calls to this
32: * routine will be removed.
33: *
34: */
35:
36: lispval
37: error(mesg,contvl)
38: char *mesg;
39: int contvl;
40: {
41: lispval errorh();
42:
43: return(errorh(Vermisc,mesg,nil,contvl,0));
44: }
45:
46:
47: /* new error handler, works with errset
48: *
49: * call is errorh(type,message,valret,contuab) where
50: * type is an atom which classifys the error, and whose clb, if not nil
51: * is the name of a function to call to handle the error.
52: * message is a character string to print to describe the error
53: * valret is the value to return to an errset if one is found,
54: * and contuab is non nil if this error is continuable.
55: */
56:
57:
58: /* VARARGS5 */
59: static lispval
60: Ierrorh(type,message,valret,contuab,uniqid)
61: lispval type,valret;
62: int uniqid,contuab;
63: char *message;
64: {
65: register struct frame *curp, *uwpframe = (struct frame *)0;
66: register lispval handy;
67: lispval *work = IEargs;
68: int limit = IElimit;
69: int pass, curdepth;
70: lispval Lread(), calhan();
71: lispval contatm;
72: lispval handy2;
73: extern struct frame *errp;
74: pbuf pb;
75: Savestack(2);
76:
77: contatm = (contuab == TRUE ? tatom : nil);
78:
79: /* if there is a catch every error handler */
80: if((handy = Verall->a.clb) != nil)
81: {
82: handy = Verall->a.clb;
83: Verall->a.clb = nil; /* turn off before calling */
84: handy = calhan(limit,work,type,uniqid,contatm,message,handy);
85: if(contuab && (TYPE(handy) == DTPR))
86: return(handy->d.car);
87: }
88:
89: if((handy = type->a.clb) != nil) /* if there is an error handler */
90: {
91: handy = calhan(limit,work,type,uniqid,contatm,message,handy);
92: if(contuab && (TYPE(handy) == DTPR))
93: return(handy->d.car);
94: }
95:
96: pass = 1;
97: /* search stack for error catcher */
98: ps2:
99:
100: for (curp = errp ; curp != (struct frame *) 0 ; curp = curp->olderrp)
101: {
102: if(curp->class == F_CATCH)
103: {
104: /*
105: * interesting catch tags are ER%unwind-protect, generated
106: * by unwind-protect and ER%all, generated by errset
107: */
108: if((pass == 1) && (curp->larg1 == Veruwpt))
109: {
110: uwpframe = curp;
111: pass = 2;
112: goto ps2;
113: }
114: else if(curp->larg1 == Verall)
115: {
116: /*
117: * have found an errset to jump to. If there is an
118: * errset handler, first call that.
119: */
120: if((handy=Verrset->a.clb) != nil)
121: {
122: calhan(limit,work,type,uniqid,contatm,message,handy);
123: }
124:
125: /*
126: * if there is an unwind-protect then go to that first.
127: * The unwind protect will return to errorh after
128: * it has processed its cleanup forms.
129: * assert: if pass == 2
130: * then there is a pending unwind-protect
131: */
132: if(uwpframe != (struct frame *)0)
133: {
134: /*
135: * generate form to return to unwind-protect
136: */
137: protect(handy2 = newdot());
138: handy2->d.car = Veruwpt;
139: handy = handy2->d.cdr = newdot();
140: handy->d.car = nil; /* indicates error */
141: handy = handy->d.cdr = newdot();
142: handy->d.car = type;
143: handy = handy->d.cdr = newdot();
144: handy->d.car = matom(message);
145: handy = handy->d.cdr = newdot();
146: handy->d.car = valret;
147: handy = handy->d.cdr = newdot();
148: handy->d.car = inewint(uniqid);
149: handy = handy->d.cdr = newdot();
150: handy->d.car = inewint(contuab);
151: while (limit-- > 0) /* put in optional args */
152: { handy = handy->d.cdr = newdot();
153: handy->d.car = *work++;
154: }
155: lispretval = handy2; /* return this as value */
156: retval = C_THROW;
157: Iretfromfr(uwpframe);
158: /* NOTREACHED */
159: }
160: /*
161: * Will return to errset
162: * print message if flag on this frame is non nil
163: */
164: if(curp->larg2 != nil)
165: {
166: printf("%s ",message);
167: while(limit-->0) {
168: printr(*work++,stdout);
169: fflush(stdout);
170: }
171: fputc('\n',stdout);
172: fflush(stdout);
173: }
174:
175: lispretval = valret;
176: retval = C_THROW; /* looks like a throw */
177: Iretfromfr(curp);
178: }
179: }
180: }
181:
182: /* no one will catch this error, we must see if there is an
183: error-goes-to-top-level catcher */
184:
185: if (Vertpl->a.clb != nil)
186: {
187:
188: handy = calhan(limit,work,type,uniqid,contatm,message,Vertpl->a.clb);
189: if( contuab && (TYPE(handy) == DTPR))
190: return(handy->d.car);
191: }
192:
193: /* at this point, print error message and break, just like
194: the current error scheme */
195: printf("%s ",message);
196: while(limit-->0) {
197: printr(*work++,stdout);
198: fflush(stdout);
199: }
200:
201:
202: /* If automatic-reset is set
203: * we will now jump to top level, calling the reset function
204: * if it exists, or using the c rest function if it does not
205: */
206:
207: if(Sautor)
208: {
209: if ((handy = reseta->a.fnbnd) != nil)
210: {
211: lispval Lapply();
212: lbot = np;
213: protect(reseta);
214: protect(nil);
215: Lapply();
216: }
217: Inonlocalgo(C_RESET,inewint(0),nil);
218: /* NOTREACHED */
219: }
220:
221: /*
222: * no one wants the error. We set up another read-eval-print
223: * loop. The user can get out of this error by typing (return 'val)
224: * if the error is continuable. Normally this code be replaced
225: * by more clever lisp code, when the full lisp is built
226: */
227:
228: errp = Pushframe(F_PROG,nil,nil);
229:
230: if(TYPE(Verdepth->a.clb) != INT)
231: {
232: curdepth = 1;
233: }
234: else curdepth = 1 + Verdepth->a.clb->i;
235: PUSHDOWN(Verdepth,inewint(curdepth));
236:
237: switch(retval) {
238: case C_RET: /*
239: * attempt to return from error
240: */
241: if(!contuab) error("Can't continue from this error",
242: FALSE);
243: popnames(errp->svbnp);
244: errp = Popframe();
245: Restorestack();
246: return(lispretval);
247:
248: case C_GO: /*
249: * this may look like a valid prog, but it really
250: * isn't, since go's are not allowed. Let the
251: * user know.
252: */
253: error("Can't 'go' through an error break",FALSE);
254: /* NOT REACHED */
255:
256: case C_INITIAL: /*
257: * normal case, just fall through into read-eval-print
258: * loop
259: */
260: break;
261: }
262: lbot = np;
263: protect(P(stdin));
264: protect(eofa);
265:
266: while(TRUE) {
267:
268: fprintf(stdout,"\n%d:>",curdepth);
269: dmpport(stdout);
270: vtemp = Lread();
271: if(vtemp == eofa) franzexit(0);
272: printr(eval(vtemp),stdout);
273: }
274: /* NOTREACHED */
275: }
276:
277: lispval
278: errorh(type,message,valret,contuab,uniqid)
279: lispval type,valret;
280: int uniqid,contuab;
281: char *message;
282: {
283: IElimit = 0;
284: Ierrorh(type,message,valret,contuab,uniqid);
285: /* NOTREACHED */
286: }
287:
288: lispval
289: errorh1(type,message,valret,contuab,uniqid,arg1)
290: lispval type,valret,arg1;
291: int uniqid,contuab;
292: char *message;
293: {
294: IElimit = 1;
295: IEargs[0] = arg1;
296: Ierrorh(type,message,valret,contuab,uniqid);
297: /* NOTREACHED */
298: }
299:
300: lispval
301: errorh2(type,message,valret,contuab,uniqid,arg1,arg2)
302: lispval type,valret,arg1,arg2;
303: int uniqid,contuab;
304: char *message;
305: {
306: IElimit = 2;
307: IEargs[0] = arg1;
308: IEargs[1] = arg2;
309: Ierrorh(type,message,valret,contuab,uniqid);
310: /* NOTREACHED */
311: }
312:
313: lispval
314: calhan(limit,work,type,uniqid,contuab,message,handler)
315: register lispval *work;
316: lispval handler,type,contuab;
317: register limit;
318: register char *message;
319: int uniqid;
320: {
321: register lispval handy;
322: Savestack(4);
323: lbot = np;
324: protect(handler); /* funcall the handler */
325: protect(handy = newdot()); /* with a list consisting of */
326: handy->d.car = type; /* type, */
327: handy = (handy->d.cdr = newdot());
328: handy->d.car = inewint(uniqid); /* identifying number, */
329: handy = (handy->d.cdr = newdot());
330: handy->d.car = contuab;
331: handy = (handy->d.cdr = newdot());
332: handy->d.car = matom(message); /* message to be typed out, */
333: while(limit-- > 0)
334: { /* any other args. */
335: handy = handy->d.cdr = newdot();
336: handy->d.car = *work++;
337: }
338: handy->d.cdr = nil;
339:
340: handy = Lfuncal();
341: Restorestack();
342: return(handy);
343: }
344:
345: /* lispend **************************************************************/
346: /* Fatal errors come here, with their epitaph. */
347: lispend(mesg)
348: char mesg[];
349: {
350: dmpport(poport);
351: fprintf(errport,"%s\n",mesg);
352: dmpport(errport);
353: franzexit(0);
354: /* NOT REACHED */
355: }
356:
357: /* namerr ***************************************************************/
358: /* handles namestack overflow, at present by simply giving a message */
359:
360: namerr()
361: {
362: if((nplim = np + NAMINC) > orgnp + NAMESIZE)
363: {
364: printf("Unrecoverable Namestack Overflow, (reset) is forced\n");
365: fflush(stdout);
366: nplim = orgnp + NAMESIZE - 4*NAMINC;
367: lbot = np = nplim - NAMINC;
368: protect(matom("reset"));
369: Lfuncal();
370: }
371: error("NAMESTACK OVERFLOW",FALSE);
372: /* NOT REACHED */
373: }
374:
375: binderr()
376: {
377: bnp -= 10;
378: error("Bindstack overflow.",FALSE);
379: /* NOT REACHED */
380: }
381:
382: rtaberr()
383: {
384: bindfix(Vreadtable,strtab,nil);
385: error("Illegal read table.",FALSE);
386: /* NOT REACHED */
387: }
388: xserr()
389: {
390: error("Ran out of alternate stack",FALSE);
391: }
392: badmem(n)
393: {
394: char errbuf[256], *sprintf();
395:
396: sprintf(errbuf,"Attempt to allocate beyond static structures (%d).",n);
397: error(errbuf,FALSE);
398: /* NOT REACHED */
399: }
400: argerr(msg)
401: char *msg;
402: {
403: errorh1(Vermisc,"incorrect number of args to",
404: nil,FALSE,0,matom(msg));
405: /* NOT REACHED */
406: }
407:
408: lispval Vinterrfcn = nil;
409:
410: /*
411: * wnaerr - wrong number of arguments to a compiled function hander
412: * called with the function name (symbol) and a descriptor of the
413: * number of arguments that were expected. The form of the descriptor
414: * is (considered as a decimal number) xxyy where xx is the minumum
415: * and yy-1 is the maximum. A maximum of -1 means that there is no
416: * maximum.
417: *
418: */
419: wnaerr(fcn,wantargs)
420: lispval fcn;
421: {
422: if (Vinterrfcn == nil)
423: {
424: Vinterrfcn = matom("int:wrong-number-of-args-error");
425: }
426: if (Vinterrfcn->a.fnbnd != nil)
427: {
428: protect(fcn);
429: protect(inewint(wantargs / 1000)); /* min */
430: protect(inewint((wantargs % 1000) - 1)); /* max */
431: Ifuncal(Vinterrfcn);
432: error("wrong number of args function should never return ", FALSE);
433: }
434:
435: errorh1(Vermisc,"wrong number of arguments to ",nil,FALSE,0,fcn);
436: }
437:
438:
439:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.