home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume23
/
rc
/
part01
/
except.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-10-18
|
2KB
|
87 lines
#include "jbwrap.h"
#include <stdarg.h>
#include "rc.h"
#include "utils.h"
#include "except.h"
#include "status.h"
#include "hash.h"
#include "input.h"
#include "nalloc.h"
/*
a return goes back stack frames to the last return. A break does not. A signal
goes to the last interactive level.
*/
static Estack *estack;
/* add an exception to the input stack. */
void except(enum except e, void *jb, Estack *ex) {
ex->prev = estack;
estack = ex;
switch (estack->e = e) {
case ARENA:
estack->b = newblock();
break;
case ERROR:
case BREAK:
case RETURN:
estack->interactive = interactive;
estack->jb = (jbwrap *) jb;
break;
case VARSTACK:
estack->name = (char *) jb;
break;
}
}
/* remove an exception, restore last interactive value */
void unexcept() {
if (estack->e == ERROR)
interactive = estack->interactive;
else if (estack->e == ARENA)
restoreblock(estack->b);
estack = estack->prev;
}
/*
Raise an exception. The rules are pretty complicated: you can return from a loop inside a
function, but you can't break from a function inside of a loop. On errors, rc_raise() goes back
to the LAST INTERACTIVE stack frame. If no such frame exists, then rc_raise() exits the shell.
This is what happens, say, when there is a syntax error in a noninteractive shell script. While
traversing the exception stack backwards, rc_raise() also removes input sources (closing
file-descriptors, etc.) and pops instances of $* that have been pushed onto the variable stack
(e.g., for a function call).
*/
void rc_raise(enum except e) {
if (e == ERROR && rc_pid != getpid())
exit(1); /* child processes exit on an error/signal */
for (; estack != NULL; estack = estack->prev)
if (estack->e != e) {
if (e == BREAK && estack->e != ARENA)
rc_error("break outside of loop");
else if (e == RETURN && estack->e == ERROR) /* can return from loops inside functions */
rc_error("return outside of function");
if (estack->e == VARSTACK)
varrm(estack->name, TRUE);
else if (estack->e == ARENA)
restoreblock(estack->b);
} else {
if (e == ERROR && !estack->interactive) {
popinput();
} else {
jbwrap *j = estack->jb;
interactive = estack->interactive;
estack = estack->prev;
longjmp(j->j, 1);
}
}
rc_exit(1); /* top of exception stack */
}