static void NORET jumpfun(RCNTXT * cptr, int mask, SEXP val) { Rboolean savevis = R_Visible; /* run onexit/cend code for all contexts down to but not including the jump target */ PROTECT(val); cptr->returnValue = val;/* in case the on.exit code wants to see it */ R_run_onexits(cptr); UNPROTECT(1); R_Visible = savevis; R_ReturnedValue = val; R_GlobalContext = cptr; /* this used to be set to cptr->nextcontext for non-toplevel jumps (with the context set back at the SETJMP for restarts). Changing this to always using cptr as the new global context should simplify some code and perhaps allow loops to be handled with fewer SETJMP's. LT */ R_restore_globals(R_GlobalContext); LONGJMP(cptr->cjmpbuf, mask); }
static int ParseBrowser(SEXP CExpr, SEXP rho) { int rval = 0; if (isSymbol(CExpr)) { const char *expr = CHAR(PRINTNAME(CExpr)); if (!strcmp(expr, "c") || !strcmp(expr, "cont")) { rval = 1; SET_RDEBUG(rho, 0); } else if (!strcmp(expr, "f")) { rval = 1; RCNTXT *cntxt = R_GlobalContext; while (cntxt != R_ToplevelContext && !(cntxt->callflag & (CTXT_RETURN | CTXT_LOOP))) { cntxt = cntxt->nextcontext; } cntxt->browserfinish = 1; SET_RDEBUG(rho, 1); R_BrowserLastCommand = 'f'; } else if (!strcmp(expr, "help")) { rval = 2; printBrowserHelp(); } else if (!strcmp(expr, "n")) { rval = 1; SET_RDEBUG(rho, 1); R_BrowserLastCommand = 'n'; } else if (!strcmp(expr, "Q")) { /* Run onexit/cend code for everything above the target. The browser context is still on the stack, so any error will drop us back to the current browser. Not clear this is a good thing. Also not clear this should still be here now that jump_to_toplevel is used for the jump. */ R_run_onexits(R_ToplevelContext); /* this is really dynamic state that should be managed as such */ SET_RDEBUG(rho, 0); /*PR#1721*/ jump_to_toplevel(); } else if (!strcmp(expr, "s")) { rval = 1; SET_RDEBUG(rho, 1); R_BrowserLastCommand = 's'; } else if (!strcmp(expr, "where")) { rval = 2; printwhere(); /* SET_RDEBUG(rho, 1); */ } } return rval; }