The R Project SVN R

Rev

Rev 78071 | Rev 78125 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 78071 Rev 78073
Line 1741... Line 1741...
1741
static void vsignalError(SEXP call, const char *format, va_list ap)
1741
static void vsignalError(SEXP call, const char *format, va_list ap)
1742
{
1742
{
1743
    char localbuf[BUFSIZE];
1743
    char localbuf[BUFSIZE];
1744
    SEXP list, oldstack;
1744
    SEXP list, oldstack;
1745
 
1745
 
1746
    oldstack = R_HandlerStack;
1746
    PROTECT(oldstack = R_HandlerStack);
1747
    Rvsnprintf(localbuf, BUFSIZE - 1, format, ap);
1747
    Rvsnprintf(localbuf, BUFSIZE - 1, format, ap);
1748
    while ((list = findSimpleErrorHandler()) != R_NilValue) {
1748
    while ((list = findSimpleErrorHandler()) != R_NilValue) {
1749
	char *buf = errbuf;
1749
	char *buf = errbuf;
1750
	SEXP entry = CAR(list);
1750
	SEXP entry = CAR(list);
1751
	R_HandlerStack = CDR(list);
1751
	R_HandlerStack = CDR(list);
Line 1778... Line 1778...
1778
	    }
1778
	    }
1779
	}
1779
	}
1780
	else gotoExitingHandler(R_NilValue, call, entry);
1780
	else gotoExitingHandler(R_NilValue, call, entry);
1781
    }
1781
    }
1782
    R_HandlerStack = oldstack;
1782
    R_HandlerStack = oldstack;
-
 
1783
    UNPROTECT(1); /* oldstack */
1783
}
1784
}
1784
 
1785
 
1785
static SEXP findConditionHandler(SEXP cond)
1786
static SEXP findConditionHandler(SEXP cond)
1786
{
1787
{
1787
    int i;
1788
    int i;
Line 2338... Line 2339...
2338
	.fdata = fdata,
2339
	.fdata = fdata,
2339
	.suspended = R_interrupts_suspended
2340
	.suspended = R_interrupts_suspended
2340
    };
2341
    };
2341
 
2342
 
2342
    /* Interrupts are suspended while in the infrastructure R code and
2343
    /* Interrupts are suspended while in the infrastructure R code and
2343
       enabled, if they were on entry to R_TryCatch, while calling the
2344
       enabled, if they were on entry to R_tryCatch, while calling the
2344
       body function in do_tryCatchHelper */
2345
       body function in do_tryCatchHelper */
2345
 
2346
 
2346
    R_interrupts_suspended = TRUE;
2347
    R_interrupts_suspended = TRUE;
2347
 
2348
 
2348
    if (conds == NULL) conds = allocVector(STRSXP, 0);
2349
    if (conds == NULL) conds = allocVector(STRSXP, 0);
Line 2394... Line 2395...
2394
	return R_NilValue;
2395
	return R_NilValue;
2395
    default: return R_NilValue; /* should not happen */
2396
    default: return R_NilValue; /* should not happen */
2396
    }
2397
    }
2397
}
2398
}
2398
 
2399
 
-
 
2400
 
-
 
2401
/* R_withCallingErrorHandler establishes a calling handler for
-
 
2402
   conditions inheriting from class 'error'. The handler is
-
 
2403
   established without calling back into the R implementation. This
-
 
2404
   should therefore be much more efficient than the current R_tryCatch
-
 
2405
   implementation. */
-
 
2406
 
-
 
2407
SEXP R_withCallingErrorHandler(SEXP (*body)(void *), void *bdata,
-
 
2408
			       SEXP (*handler)(SEXP, void *), void *hdata)
-
 
2409
{
-
 
2410
    /* This defines the lambda expression for th handler. The `addr`
-
 
2411
       variable wil be defined in the closure environment and contain
-
 
2412
       an external pointer to the callback data. */
-
 
2413
    static const char* wceh_callback_source =
-
 
2414
	"function(cond) .Internal(C_tryCatchHelper(addr, 1L, cond))";
-
 
2415
 
-
 
2416
    static SEXP wceh_callback = NULL;
-
 
2417
    static SEXP wceh_class = NULL;
-
 
2418
    static SEXP addr_sym = NULL;
-
 
2419
 
-
 
2420
    if (body == NULL) error("must supply a body function");
-
 
2421
 
-
 
2422
    if (wceh_callback == NULL) {
-
 
2423
	wceh_callback = R_ParseEvalString(wceh_callback_source,
-
 
2424
					  R_BaseNamespace);
-
 
2425
	R_PreserveObject(wceh_callback);
-
 
2426
	wceh_class = mkChar("error");
-
 
2427
	R_PreserveObject(wceh_class);
-
 
2428
	addr_sym = install("addr");
-
 
2429
    }
-
 
2430
 
-
 
2431
    /* record the C-level handler information */
-
 
2432
    tryCatchData_t tcd = {
-
 
2433
	.handler = handler != NULL ? handler : default_tryCatch_handler,
-
 
2434
	.hdata = hdata
-
 
2435
    };
-
 
2436
    SEXP tcdptr = R_MakeExternalPtr(&tcd, R_NilValue, R_NilValue);
-
 
2437
 
-
 
2438
    /* create the R handler function closure */
-
 
2439
    SEXP env = CONS(tcdptr, R_NilValue);
-
 
2440
    SET_TAG(env, addr_sym);
-
 
2441
    env = NewEnvironment(R_NilValue, env, R_BaseNamespace);
-
 
2442
    PROTECT(env);
-
 
2443
    SEXP h = duplicate(wceh_callback);
-
 
2444
    SET_CLOENV(h, env);
-
 
2445
    UNPROTECT(1); /* env */
-
 
2446
 
-
 
2447
    /* push the handler on the handler stack */
-
 
2448
    SEXP oldstack = R_HandlerStack;
-
 
2449
    PROTECT(oldstack);
-
 
2450
    PROTECT(h);
-
 
2451
    SEXP entry = mkHandlerEntry(wceh_class, R_GlobalEnv, h, R_NilValue,
-
 
2452
				R_NilValue, /* OK for a calling handler */
-
 
2453
				TRUE);
-
 
2454
    R_HandlerStack = CONS(entry, R_HandlerStack);
-
 
2455
    UNPROTECT(1); /* h */
-
 
2456
 
-
 
2457
    SEXP val = body(bdata);
-
 
2458
 
-
 
2459
    /* restore the handler stack */
-
 
2460
    R_HandlerStack = oldstack;
-
 
2461
    UNPROTECT(1); /* oldstack */
-
 
2462
 
-
 
2463
    return val;
-
 
2464
}
-
 
2465
 
2399
SEXP attribute_hidden do_addGlobHands(SEXP call, SEXP op,SEXP args, SEXP rho)
2466
SEXP attribute_hidden do_addGlobHands(SEXP call, SEXP op,SEXP args, SEXP rho)
2400
{
2467
{
2401
    SEXP oldstk = R_ToplevelContext->handlerstack;
2468
    SEXP oldstk = R_ToplevelContext->handlerstack;
2402
 
2469
 
2403
    R_HandlerStack = R_NilValue;
2470
    R_HandlerStack = R_NilValue;