A return goes back stack frames to the last return. A break does
not. A signal goes to the last interactive level. (see below)
/* add an exception to the input stack. */
extern void except(ecodes e
, Edata data
, Estack
*ex
) {
if (e
== eError
|| e
== eBreak
|| e
== eReturn
)
estack
->interactive
= interactive
;
/* remove an exception, restore last interactive value */
interactive
= estack
->interactive
;
restoreblock(estack
->data
.b
);
unlink(estack
->data
.name
);
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 variables
that have been pushed onto the variable stack (e.g., for a function
call (for $*) or a local assignment).
extern void rc_raise(ecodes e
) {
if (e
== eError
&& rc_pid
!= getpid())
exit(1); /* child processes exit on an error/signal */
for (; estack
!= NULL
; estack
= estack
->prev
)
if (e
== eBreak
&& estack
->e
!= eArena
)
rc_error("break outside of loop");
else if (e
== eReturn
&& estack
->e
== eError
) /* can return from loops inside functions */
rc_error("return outside of function");
varrm(estack
->data
.name
, TRUE
);
restoreblock(estack
->data
.b
);
unlink(estack
->data
.name
);
if (e
== eError
&& !estack
->interactive
) {
Jbwrap
*j
= estack
->data
.jb
;
interactive
= estack
->interactive
;
rc_exit(1); /* top of exception stack */
extern bool outstanding_cmdarg() {
return estack
->e
== eFifo
|| estack
->e
== eFd
;
extern void pop_cmdarg(bool remove
) {
for (; estack
!= NULL
; estack
= estack
->prev
)
unlink(estack
->data
.name
);
extern void rc_error(char *s
) {
cond
= FALSE
; /* no longer inside conditional */
extern void sigint(int s
) {
panic("s != SIGINT in sigint catcher");
/* this is the newline you see when you hit ^C while typing a command */