The R Project SVN R

Rev

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

Rev 25517 Rev 25523
Line 188... Line 188...
188
}
188
}
189
 
189
 
190
/* temporary hook to allow experimenting with alternate warning mechanisms */
190
/* temporary hook to allow experimenting with alternate warning mechanisms */
191
static void (*R_WarningHook)(SEXP, char *) = NULL;
191
static void (*R_WarningHook)(SEXP, char *) = NULL;
192
 
192
 
-
 
193
#ifdef NEW_CONDITION_HANDLING
-
 
194
/* declarations for internal condition handling */
-
 
195
 
-
 
196
static void vsignalException(SEXP call, const char *format, va_list ap);
-
 
197
static void vsignalWarning(SEXP call, const char *format, va_list ap);
-
 
198
static void invokeRestart(SEXP, SEXP);
-
 
199
#endif
-
 
200
 
193
static void reset_inWarning(void *data)
201
static void reset_inWarning(void *data)
194
{
202
{
195
    inWarning = 0;
203
    inWarning = 0;
196
}
204
}
197
 
205
 
198
void warningcall(SEXP call, const char *format, ...)
206
static void vwarningcall_dflt(SEXP call, const char *format, va_list ap)
199
{
207
{
200
    int w;
208
    int w;
201
    SEXP names, s;
209
    SEXP names, s;
202
    char *dcall, buf[BUFSIZE];
210
    char *dcall, buf[BUFSIZE];
203
    RCNTXT *cptr;
211
    RCNTXT *cptr;
204
    RCNTXT cntxt;
212
    RCNTXT cntxt;
205
 
213
 
206
    if (inWarning)
214
    if (inWarning)
207
	return;
215
	return;
208
    
216
    
209
    if (R_WarningHook != NULL) {
-
 
210
	va_list(ap);
-
 
211
	va_start(ap, format);
-
 
212
	Rvsnprintf(buf, min(BUFSIZE, R_WarnLength), format, ap);
-
 
213
	va_end(ap);
-
 
214
	R_WarningHook(call, buf);
-
 
215
	return;
-
 
216
    }
-
 
217
 
-
 
218
    s = GetOption(install("warning.expression"), R_NilValue);
217
    s = GetOption(install("warning.expression"), R_NilValue);
219
    if( s!= R_NilValue ) {
218
    if( s!= R_NilValue ) {
220
	if( !isLanguage(s) &&  ! isExpression(s) )
219
	if( !isLanguage(s) &&  ! isExpression(s) )
221
	    error("invalid option \"warning.expression\"");
220
	    error("invalid option \"warning.expression\"");
222
	cptr = R_GlobalContext;
221
	cptr = R_GlobalContext;
Line 241... Line 240...
241
    cntxt.cend = &reset_inWarning;
240
    cntxt.cend = &reset_inWarning;
242
 
241
 
243
    inWarning = 1;
242
    inWarning = 1;
244
 
243
 
245
    if(w >= 2) { /* make it an error */
244
    if(w >= 2) { /* make it an error */
246
	va_list(ap);
-
 
247
	va_start(ap, format);
-
 
248
	Rvsnprintf(buf, min(BUFSIZE, R_WarnLength), format, ap);
245
	Rvsnprintf(buf, min(BUFSIZE, R_WarnLength), format, ap);
249
	va_end(ap);
-
 
250
	inWarning = 0; /* PR#1570 */
246
	inWarning = 0; /* PR#1570 */
251
	errorcall(call, "(converted from warning) %s", buf);
247
	errorcall(call, "(converted from warning) %s", buf);
252
    }
248
    }
253
    else if(w == 1) {	/* print as they happen */
249
    else if(w == 1) {	/* print as they happen */
254
	va_list(ap);
-
 
255
	if( call != R_NilValue ) {
250
	if( call != R_NilValue ) {
256
	    dcall = CHAR(STRING_ELT(deparse1(call, 0), 0));
251
	    dcall = CHAR(STRING_ELT(deparse1(call, 0), 0));
257
	    REprintf("Warning in %s : ", dcall);
252
	    REprintf("Warning in %s : ", dcall);
258
	    if (strlen(dcall) > LONGCALL) REprintf("\n	 ");
253
	    if (strlen(dcall) > LONGCALL) REprintf("\n	 ");
259
	}
254
	}
260
	else
255
	else
261
	    REprintf("Warning: ");
256
	    REprintf("Warning: ");
262
	va_start(ap, format);
-
 
263
	Rvsnprintf(buf, min(BUFSIZE, R_WarnLength), format, ap);
257
	Rvsnprintf(buf, min(BUFSIZE, R_WarnLength), format, ap);
264
	va_end(ap);
-
 
265
	REprintf("%s\n", buf);
258
	REprintf("%s\n", buf);
266
    }
259
    }
267
    else if(w == 0) {	/* collect them */
260
    else if(w == 0) {	/* collect them */
268
	va_list(ap);
-
 
269
	va_start(ap, format);
-
 
270
	if(!R_CollectWarnings)
261
	if(!R_CollectWarnings)
271
	    setupwarnings();
262
	    setupwarnings();
272
	if( R_CollectWarnings > 49 )
263
	if( R_CollectWarnings > 49 )
273
	    return;
264
	    return;
274
	SET_VECTOR_ELT(R_Warnings, R_CollectWarnings, call);
265
	SET_VECTOR_ELT(R_Warnings, R_CollectWarnings, call);
275
	Rvsnprintf(buf, min(BUFSIZE, R_WarnLength), format, ap);
266
	Rvsnprintf(buf, min(BUFSIZE, R_WarnLength), format, ap);
276
	va_end(ap);
-
 
277
	names = CAR(ATTRIB(R_Warnings));
267
	names = CAR(ATTRIB(R_Warnings));
278
	SET_STRING_ELT(names, R_CollectWarnings++, mkChar(buf));
268
	SET_STRING_ELT(names, R_CollectWarnings++, mkChar(buf));
279
    }
269
    }
280
    /* else:  w <= -1 */
270
    /* else:  w <= -1 */
281
    endcontext(&cntxt);
271
    endcontext(&cntxt);
282
    inWarning = 0;
272
    inWarning = 0;
283
}
273
}
284
 
274
 
-
 
275
static void warningcall_dflt(SEXP call, const char *format,...)
-
 
276
{
-
 
277
    va_list(ap);
-
 
278
 
-
 
279
    va_start(ap, format);
-
 
280
    vwarningcall_dflt(call, format, ap);
-
 
281
    va_end(ap);
-
 
282
}
-
 
283
 
-
 
284
void warningcall(SEXP call, const char *format, ...)
-
 
285
{
-
 
286
    va_list(ap);
-
 
287
#ifdef NEW_CONDITION_HANDLING
-
 
288
    va_start(ap, format);
-
 
289
    vsignalWarning(call, format, ap);
-
 
290
    va_end(ap);
-
 
291
#else
-
 
292
    if (R_WarningHook != NULL) {
-
 
293
	char buf[BUFSIZE];
-
 
294
	va_start(ap, format);
-
 
295
	Rvsnprintf(buf, min(BUFSIZE, R_WarnLength), format, ap);
-
 
296
	va_end(ap);
-
 
297
	R_WarningHook(call, buf);
-
 
298
	return;
-
 
299
    }
-
 
300
 
-
 
301
    va_start(ap, format);
-
 
302
    vwarningcall_dflt(call, format, ap);
-
 
303
    va_end(ap);
-
 
304
#endif
-
 
305
}
-
 
306
 
285
static void cleanup_PrintWarnings(void *data)
307
static void cleanup_PrintWarnings(void *data)
286
{
308
{
287
    if (R_CollectWarnings) {
309
    if (R_CollectWarnings) {
288
	R_CollectWarnings = 0;
310
	R_CollectWarnings = 0;
289
	R_Warnings = R_NilValue;
311
	R_Warnings = R_NilValue;
Line 372... Line 394...
372
{
394
{
373
    int *poldval = data;
395
    int *poldval = data;
374
    inError = *poldval;
396
    inError = *poldval;
375
}
397
}
376
 
398
 
377
void errorcall(SEXP call, const char *format,...)
399
static void verrorcall_dflt(SEXP call, const char *format, va_list ap)
378
{
400
{
379
    RCNTXT cntxt;
401
    RCNTXT cntxt;
380
    char *p, *dcall;
402
    char *p, *dcall;
381
    int oldInError;
403
    int oldInError;
382
 
404
 
383
    va_list(ap);
-
 
384
 
-
 
385
    if (R_ErrorHook != NULL) {
-
 
386
	char buf[BUFSIZE];
-
 
387
	void (*hook)(SEXP, char *) = R_ErrorHook;
-
 
388
	R_ErrorHook = NULL; /* to avoid recursion */
-
 
389
	va_start(ap, format);
-
 
390
	Rvsnprintf(buf, min(BUFSIZE, R_WarnLength), format, ap);
-
 
391
	va_end(ap);
-
 
392
	hook(call, buf);
-
 
393
    }
-
 
394
 
-
 
395
    if (inError) {
405
    if (inError) {
396
	/* fail-safe handler for recursive errors */
406
	/* fail-safe handler for recursive errors */
397
	if(inError == 3) {
407
	if(inError == 3) {
398
	     /* Can REprintf generate an error? If so we should guard for it */
408
	     /* Can REprintf generate an error? If so we should guard for it */
399
	    REprintf("Error during wrapup: ");
409
	    REprintf("Error during wrapup: ");
400
	    /* this does NOT try to print the call since that could
410
	    /* this does NOT try to print the call since that could
401
               cause a cascade of error calls */
411
               cause a cascade of error calls */
402
	    va_start(ap, format);
-
 
403
	    Rvsnprintf(errbuf, sizeof(errbuf), format, ap);
412
	    Rvsnprintf(errbuf, sizeof(errbuf), format, ap);
404
	    va_end(ap);
-
 
405
	    REprintf("%s\n", errbuf);
413
	    REprintf("%s\n", errbuf);
406
	}
414
	}
407
	if (R_Warnings != R_NilValue) {
415
	if (R_Warnings != R_NilValue) {
408
	    R_CollectWarnings = 0;
416
	    R_CollectWarnings = 0;
409
	    R_Warnings = R_NilValue;
417
	    R_Warnings = R_NilValue;
Line 436... Line 444...
436
    }
444
    }
437
    else
445
    else
438
	sprintf(errbuf, "Error: ");
446
	sprintf(errbuf, "Error: ");
439
 
447
 
440
    p = errbuf + strlen(errbuf);
448
    p = errbuf + strlen(errbuf);
441
    va_start(ap, format);
-
 
442
    Rvsnprintf(p, min(BUFSIZE, R_WarnLength) - strlen(errbuf), format, ap);
449
    Rvsnprintf(p, min(BUFSIZE, R_WarnLength) - strlen(errbuf), format, ap);
443
    va_end(ap);
-
 
444
    p = errbuf + strlen(errbuf) - 1;
450
    p = errbuf + strlen(errbuf) - 1;
445
    if(*p != '\n') strcat(errbuf, "\n");
451
    if(*p != '\n') strcat(errbuf, "\n");
446
    if (R_ShowErrorMessages) REprintf("%s", errbuf);
452
    if (R_ShowErrorMessages) REprintf("%s", errbuf);
447
 
453
 
448
    if( R_ShowErrorMessages && R_CollectWarnings ) {
454
    if( R_ShowErrorMessages && R_CollectWarnings ) {
Line 455... Line 461...
455
    /* not reached */
461
    /* not reached */
456
    endcontext(&cntxt);
462
    endcontext(&cntxt);
457
    inError = oldInError;
463
    inError = oldInError;
458
}
464
}
459
 
465
 
-
 
466
static void errorcall_dflt(SEXP call, const char *format,...)
-
 
467
{
-
 
468
    va_list(ap);
-
 
469
 
-
 
470
    va_start(ap, format);
-
 
471
    verrorcall_dflt(call, format, ap);
-
 
472
    va_end(ap);
-
 
473
}
-
 
474
 
-
 
475
void errorcall(SEXP call, const char *format,...)
-
 
476
{
-
 
477
    va_list(ap);
-
 
478
 
-
 
479
#ifdef NEW_CONDITION_HANDLING
-
 
480
    va_start(ap, format);
-
 
481
    vsignalException(call, format, ap);
-
 
482
    va_end(ap);
-
 
483
#endif
-
 
484
 
-
 
485
    if (R_ErrorHook != NULL) {
-
 
486
	char buf[BUFSIZE];
-
 
487
	void (*hook)(SEXP, char *) = R_ErrorHook;
-
 
488
	R_ErrorHook = NULL; /* to avoid recursion */
-
 
489
	va_start(ap, format);
-
 
490
	Rvsnprintf(buf, min(BUFSIZE, R_WarnLength), format, ap);
-
 
491
	va_end(ap);
-
 
492
	hook(call, buf);
-
 
493
    }
-
 
494
 
-
 
495
    va_start(ap, format);
-
 
496
    verrorcall_dflt(call, format, ap);
-
 
497
    va_end(ap);
-
 
498
}
-
 
499
 
460
SEXP do_geterrmessage(SEXP call, SEXP op, SEXP args, SEXP env)
500
SEXP do_geterrmessage(SEXP call, SEXP op, SEXP args, SEXP env)
461
{
501
{
462
    SEXP res;
502
    SEXP res;
463
 
503
 
464
    checkArity(op, args);
504
    checkArity(op, args);
Line 481... Line 521...
481
	      R_GlobalContext->call : R_NilValue, "%s", buf);
521
	      R_GlobalContext->call : R_NilValue, "%s", buf);
482
}
522
}
483
 
523
 
484
static void try_jump_to_restart(void)
524
static void try_jump_to_restart(void)
485
{
525
{
-
 
526
#ifdef NEW_CONDITION_HANDLING
-
 
527
    SEXP list;
-
 
528
 
-
 
529
    for (list = R_RestartStack; list != R_NilValue; list = CDR(list)) {
-
 
530
	SEXP restart = CAR(list);
-
 
531
	if (TYPEOF(restart) == VECSXP && LENGTH(restart) > 1) {
-
 
532
	    SEXP name = VECTOR_ELT(restart, 0);
-
 
533
	    if (TYPEOF(name) == STRSXP && LENGTH(name) == 1) {
-
 
534
		char *cname = CHAR(STRING_ELT(name, 0));
-
 
535
		if (! strcmp(cname, "browser") ||
-
 
536
		    ! strcmp(cname, "tryRestart") ||
-
 
537
		    ! strcmp(cname, "abort")) /**** move abort eventually? */
-
 
538
		    invokeRestart(restart, R_NilValue);
-
 
539
	    }
-
 
540
	}
-
 
541
    }
-
 
542
#else
486
    RCNTXT *c;
543
    RCNTXT *c;
487
 
544
 
488
    for (c = R_GlobalContext; c; c = c->nextcontext) {
545
    for (c = R_GlobalContext; c; c = c->nextcontext) {
489
	if (IS_RESTART_BIT_SET(c->callflag)) {
546
	if (IS_RESTART_BIT_SET(c->callflag)) {
490
	    inError=0;
547
	    inError=0;
491
	    findcontext(CTXT_RESTART, c->cloenv, R_RestartToken);
548
	    findcontext(CTXT_RESTART, c->cloenv, R_RestartToken);
492
	}
549
	}
493
	if (c->callflag == CTXT_TOPLEVEL)
550
	if (c->callflag == CTXT_TOPLEVEL)
494
	    break;
551
	    break;
495
    }
552
    }
-
 
553
#endif
496
}
554
}
497
 
555
 
498
/* Unwind the call stack in an orderly fashion */
556
/* Unwind the call stack in an orderly fashion */
499
/* calling the code installed by on.exit along the way */
557
/* calling the code installed by on.exit along the way */
500
/* and finally longjmping to the innermost TOPLEVEL context */
558
/* and finally longjmping to the innermost TOPLEVEL context */
Line 664... Line 722...
664
	else
722
	else
665
	    warningcall(c_call, "%s", CHAR(STRING_ELT(CAR(args), 0)));
723
	    warningcall(c_call, "%s", CHAR(STRING_ELT(CAR(args), 0)));
666
    }
724
    }
667
    else
725
    else
668
	warningcall(c_call, "");
726
	warningcall(c_call, "");
-
 
727
 
-
 
728
    /* need to set R_Visible since it may have been changed by a callback */
-
 
729
    R_Visible = 0;
669
    return CAR(args);
730
    return CAR(args);
670
}
731
}
671
 
732
 
672
/* Error recovery for incorrect argument count error. */
733
/* Error recovery for incorrect argument count error. */
673
void WrongArgCount(const char *s)
734
void WrongArgCount(const char *s)
Line 822... Line 883...
822
        REprintf("In addition: ");
883
        REprintf("In addition: ");
823
        PrintWarnings();
884
        PrintWarnings();
824
    }
885
    }
825
}    
886
}    
826
 
887
 
827
/* doesn't stop at TOPLEVEL--should once browser is changed to use RESTART */
-
 
828
SEXP R_GetTraceback(int skip)
888
SEXP R_GetTraceback(int skip)
829
{
889
{
830
    int nback = 0, ns;
890
    int nback = 0, ns;
831
    RCNTXT *c;
891
    RCNTXT *c;
832
    SEXP s, t;
892
    SEXP s, t;
Line 856... Line 916...
856
	}
916
	}
857
    UNPROTECT(1);
917
    UNPROTECT(1);
858
    return s;
918
    return s;
859
}
919
}
860
 
920
 
-
 
921
#ifdef NEW_CONDITION_HANDLING
-
 
922
static SEXP mkHandlerEntry(SEXP class, SEXP parentenv, SEXP handler, SEXP rho,
-
 
923
			   SEXP result, int calling)
-
 
924
{
-
 
925
    SEXP entry = allocVector(VECSXP, 5);
-
 
926
    SET_VECTOR_ELT(entry, 0, class);
-
 
927
    SET_VECTOR_ELT(entry, 1, parentenv);
-
 
928
    SET_VECTOR_ELT(entry, 2, handler);
-
 
929
    SET_VECTOR_ELT(entry, 3, rho);
-
 
930
    SET_VECTOR_ELT(entry, 4, result);
-
 
931
    SETLEVELS(entry, calling);
-
 
932
    return entry;
-
 
933
}
-
 
934
 
-
 
935
/**** rename these??*/
-
 
936
#define IS_CALLING_ENTRY(e) LEVELS(e)
-
 
937
#define ENTRY_CLASS(e) VECTOR_ELT(e, 0)
-
 
938
#define ENTRY_CALLING_ENVIR(e) VECTOR_ELT(e, 1)
-
 
939
#define ENTRY_HANDLER(e) VECTOR_ELT(e, 2)
-
 
940
#define ENTRY_TARGET_ENVIR(e) VECTOR_ELT(e, 3)
-
 
941
#define ENTRY_RETURN_RESULT(e) VECTOR_ELT(e, 4)
-
 
942
 
-
 
943
#define RESULT_SIZE 3
-
 
944
 
-
 
945
SEXP do_addCondHands(SEXP call, SEXP op, SEXP args, SEXP rho)
-
 
946
{
-
 
947
    SEXP classes, handlers, parentenv, target, oldstack, newstack, result;
-
 
948
    int calling, i, n;
-
 
949
    PROTECT_INDEX osi;
-
 
950
 
-
 
951
    checkArity(op, args);
-
 
952
 
-
 
953
    classes = CAR(args); args = CDR(args);
-
 
954
    handlers = CAR(args); args = CDR(args);
-
 
955
    parentenv = CAR(args); args = CDR(args);
-
 
956
    target = CAR(args); args = CDR(args);
-
 
957
    calling = asLogical(CAR(args));
-
 
958
 
-
 
959
    if (classes == R_NilValue || handlers == R_NilValue)
-
 
960
	return R_HandlerStack;
-
 
961
 
-
 
962
    if (TYPEOF(classes) != STRSXP || TYPEOF(handlers) != VECSXP ||
-
 
963
	LENGTH(classes) != LENGTH(handlers))
-
 
964
	error("bad handler data");
-
 
965
 
-
 
966
    n = LENGTH(handlers);
-
 
967
    oldstack = R_HandlerStack;
-
 
968
 
-
 
969
    PROTECT(result = allocVector(VECSXP, RESULT_SIZE));
-
 
970
    PROTECT_WITH_INDEX(newstack = oldstack, &osi);
-
 
971
 
-
 
972
    for (i = n - 1; i >= 0; i--) {
-
 
973
	SEXP class = STRING_ELT(classes, i);
-
 
974
	SEXP handler = VECTOR_ELT(handlers, i);
-
 
975
	SEXP entry = mkHandlerEntry(class, parentenv, handler, target, result,
-
 
976
				    calling);
-
 
977
	REPROTECT(newstack = CONS(entry, newstack), osi);
-
 
978
    }
-
 
979
 
-
 
980
    R_HandlerStack = newstack;
-
 
981
    UNPROTECT(2);
-
 
982
 
-
 
983
    return oldstack;
-
 
984
}
-
 
985
 
-
 
986
SEXP do_resetCondHands(SEXP call, SEXP op, SEXP args, SEXP rho)
-
 
987
{
-
 
988
    checkArity(op, args);
-
 
989
    R_HandlerStack = CAR(args);
-
 
990
    return R_NilValue;
-
 
991
}
-
 
992
 
-
 
993
static SEXP findSimpleExceptionHandler()
-
 
994
{
-
 
995
    SEXP list;
-
 
996
    for (list = R_HandlerStack; list != R_NilValue; list = CDR(list)) {
-
 
997
	SEXP entry = CAR(list);
-
 
998
	if (! strcmp(CHAR(ENTRY_CLASS(entry)), "simpleException") ||
-
 
999
	    ! strcmp(CHAR(ENTRY_CLASS(entry)), "exception") ||
-
 
1000
	    ! strcmp(CHAR(ENTRY_CLASS(entry)), "condition"))
-
 
1001
	    return list;
-
 
1002
    }
-
 
1003
    return R_NilValue;
-
 
1004
}
-
 
1005
 
-
 
1006
static void vsignalWarning(SEXP call, const char *format, va_list ap)
-
 
1007
{
-
 
1008
    char buf[BUFSIZE];
-
 
1009
    SEXP hooksym, quotesym, hcall, qcall;
-
 
1010
 
-
 
1011
    hooksym = install(".signalSimpleWarning");
-
 
1012
    quotesym = install("quote");
-
 
1013
    if (SYMVALUE(hooksym) != R_UnboundValue &&
-
 
1014
	SYMVALUE(quotesym) != R_UnboundValue) {
-
 
1015
	PROTECT(qcall = LCONS(quotesym, LCONS(call, R_NilValue)));
-
 
1016
	PROTECT(hcall = LCONS(qcall, R_NilValue));
-
 
1017
	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
-
 
1018
	hcall = LCONS(ScalarString(mkChar(buf)), hcall);
-
 
1019
	PROTECT(hcall = LCONS(hooksym, hcall));
-
 
1020
	eval(hcall, R_GlobalEnv);
-
 
1021
	UNPROTECT(3);
-
 
1022
    }
-
 
1023
    else vwarningcall_dflt(call, format, ap);
-
 
1024
}
-
 
1025
 
-
 
1026
static void gotoExitingHandler(SEXP cond, SEXP call, SEXP entry)
-
 
1027
{
-
 
1028
    SEXP rho = ENTRY_TARGET_ENVIR(entry);
-
 
1029
    SEXP result = ENTRY_RETURN_RESULT(entry);
-
 
1030
    SET_VECTOR_ELT(result, 0, cond);
-
 
1031
    SET_VECTOR_ELT(result, 1, call);
-
 
1032
    SET_VECTOR_ELT(result, 2, ENTRY_HANDLER(entry));
-
 
1033
    findcontext(CTXT_FUNCTION, rho, result);
-
 
1034
}
-
 
1035
 
-
 
1036
static void vsignalException(SEXP call, const char *format, va_list ap)
-
 
1037
{
-
 
1038
    SEXP list, oldstack;
-
 
1039
 
-
 
1040
    PROTECT(oldstack = R_HandlerStack);
-
 
1041
    while ((list = findSimpleExceptionHandler()) != R_NilValue) {
-
 
1042
	char *buf = errbuf;
-
 
1043
	SEXP entry = CAR(list);
-
 
1044
	R_HandlerStack = CDR(list);
-
 
1045
	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
-
 
1046
	buf[BUFSIZE - 1] = 0;
-
 
1047
	if (IS_CALLING_ENTRY(entry)) {
-
 
1048
	    if (ENTRY_HANDLER(entry) == R_RestartToken) {
-
 
1049
		UNPROTECT(1);
-
 
1050
		return; /* go to default error handling; do not reset stack */
-
 
1051
	    }
-
 
1052
	    else {
-
 
1053
		SEXP hooksym, quotesym, hcall, qcall;
-
 
1054
		hooksym = install(".handleSimpleException");
-
 
1055
		quotesym = install("quote");
-
 
1056
		PROTECT(qcall = LCONS(quotesym, LCONS(call, R_NilValue)));
-
 
1057
		PROTECT(hcall = LCONS(qcall, R_NilValue));
-
 
1058
		hcall = LCONS(ScalarString(mkChar(buf)), hcall);
-
 
1059
		hcall = LCONS(ENTRY_HANDLER(entry), hcall);
-
 
1060
		PROTECT(hcall = LCONS(hooksym, hcall));
-
 
1061
		eval(hcall, R_GlobalEnv);
-
 
1062
		UNPROTECT(3);
-
 
1063
	    }
-
 
1064
	}
-
 
1065
	else gotoExitingHandler(R_NilValue, call, entry);
-
 
1066
    }
-
 
1067
    R_HandlerStack = oldstack;
-
 
1068
    UNPROTECT(1);
-
 
1069
}
-
 
1070
 
-
 
1071
static SEXP findConditionHandler(SEXP cond)
-
 
1072
{
-
 
1073
    int i;
-
 
1074
    SEXP list;
-
 
1075
    SEXP classes = getAttrib(cond, R_ClassSymbol);
-
 
1076
 
-
 
1077
    if (TYPEOF(classes) != STRSXP)
-
 
1078
	return R_NilValue;
-
 
1079
    
-
 
1080
    /**** need some changes here to allow exceptions to be S4 classes */
-
 
1081
    for (list = R_HandlerStack; list != R_NilValue; list = CDR(list)) {
-
 
1082
	SEXP entry = CAR(list);
-
 
1083
	for (i = 0; i < LENGTH(classes); i++)
-
 
1084
	    if (! strcmp(CHAR(ENTRY_CLASS(entry)),
-
 
1085
			 CHAR(STRING_ELT(classes, i))))
-
 
1086
		return list;
-
 
1087
    }
-
 
1088
    return R_NilValue;
-
 
1089
}
-
 
1090
 
-
 
1091
SEXP do_signalCondition(SEXP call, SEXP op, SEXP args, SEXP rho)
-
 
1092
{
-
 
1093
    SEXP list, cond, msg, ecall;
-
 
1094
 
-
 
1095
    checkArity(op, args);
-
 
1096
 
-
 
1097
    cond = CAR(args);
-
 
1098
    msg = CADR(args);
-
 
1099
    ecall = CADDR(args);
-
 
1100
 
-
 
1101
    while ((list = findConditionHandler(cond)) != R_NilValue) {
-
 
1102
	SEXP entry = CAR(list);
-
 
1103
	R_HandlerStack = CDR(list);
-
 
1104
	if (IS_CALLING_ENTRY(entry)) {
-
 
1105
	    SEXP h = ENTRY_HANDLER(entry);
-
 
1106
	    if (h == R_RestartToken) {
-
 
1107
		char *msgstr = NULL;
-
 
1108
		if (TYPEOF(msg) == STRSXP && LENGTH(msg) > 0)
-
 
1109
		    msgstr = CHAR(STRING_ELT(msg, 0));
-
 
1110
		else error("error message not a strring");
-
 
1111
		errorcall_dflt(ecall, "%s", msgstr);
-
 
1112
	    }
-
 
1113
	    else {
-
 
1114
		SEXP hcall = LCONS(h, LCONS(cond, R_NilValue));
-
 
1115
		PROTECT(hcall);
-
 
1116
		eval(hcall, R_GlobalEnv);
-
 
1117
		UNPROTECT(1);
-
 
1118
	    }
-
 
1119
	}
-
 
1120
	else gotoExitingHandler(cond, call, entry);
-
 
1121
    }
-
 
1122
    return R_NilValue;
-
 
1123
}
-
 
1124
 
-
 
1125
void R_InsertRestartHandlers(RCNTXT *cptr, Rboolean browser)
-
 
1126
{
-
 
1127
    SEXP class, rho, entry, name;
-
 
1128
 
-
 
1129
    if ((cptr->handlerstack != R_HandlerStack ||
-
 
1130
	 cptr->handlerstack != R_HandlerStack)) {
-
 
1131
	if (IS_RESTART_BIT_SET(cptr->callflag))
-
 
1132
	    return;
-
 
1133
	else
-
 
1134
	    error("handler or restart stack mismatch in old restart");
-
 
1135
    }
-
 
1136
 
-
 
1137
    /**** need more here to keep recursive errors in browser? */
-
 
1138
    rho = cptr->cloenv;
-
 
1139
    PROTECT(class = mkChar("exception"));
-
 
1140
    entry = mkHandlerEntry(class, rho, R_RestartToken, rho, R_NilValue, TRUE);
-
 
1141
    R_HandlerStack = CONS(entry, R_HandlerStack);
-
 
1142
    UNPROTECT(1);
-
 
1143
    PROTECT(name = ScalarString(mkChar(browser ? "browser" : "tryRestart")));
-
 
1144
    entry = allocVector(VECSXP, 2);
-
 
1145
    SET_VECTOR_ELT(entry, 0, name);
-
 
1146
    SET_VECTOR_ELT(entry, 1, R_MakeExternalPtr(cptr, R_NilValue, R_NilValue));
-
 
1147
    setAttrib(entry, R_ClassSymbol, ScalarString(mkChar("restart")));
-
 
1148
    R_RestartStack = CONS(entry, R_RestartStack);
-
 
1149
    UNPROTECT(1);
-
 
1150
}
-
 
1151
 
-
 
1152
SEXP do_dfltWarn(SEXP call, SEXP op, SEXP args, SEXP rho)
-
 
1153
{
-
 
1154
    char *msg;
-
 
1155
    SEXP ecall;
-
 
1156
 
-
 
1157
    checkArity(op, args);
-
 
1158
 
-
 
1159
    if (TYPEOF(CAR(args)) != STRSXP || LENGTH(CAR(args)) != 1)
-
 
1160
	error("bad error message");
-
 
1161
    msg = CHAR(STRING_ELT(CAR(args), 0));
-
 
1162
    ecall = CADR(args);
-
 
1163
 
-
 
1164
    warningcall_dflt(ecall, "%s", msg);
-
 
1165
    return R_NilValue;
-
 
1166
}
-
 
1167
 
-
 
1168
SEXP do_dfltStop(SEXP call, SEXP op, SEXP args, SEXP rho)
-
 
1169
{
-
 
1170
    char *msg;
-
 
1171
    SEXP ecall;
-
 
1172
 
-
 
1173
    checkArity(op, args);
-
 
1174
 
-
 
1175
    if (TYPEOF(CAR(args)) != STRSXP || LENGTH(CAR(args)) != 1)
-
 
1176
	error("bad error message");
-
 
1177
    msg = CHAR(STRING_ELT(CAR(args), 0));
-
 
1178
    ecall = CADR(args);
-
 
1179
 
-
 
1180
    errorcall_dflt(ecall, "%s", msg);
-
 
1181
    return R_NilValue; /* not reached */
-
 
1182
}
-
 
1183
 
-
 
1184
 
-
 
1185
/*
-
 
1186
 * Restart Handling
-
 
1187
 */
-
 
1188
 
-
 
1189
SEXP do_getRestart(SEXP call, SEXP op, SEXP args, SEXP rho)
-
 
1190
{
-
 
1191
    int i;
-
 
1192
    SEXP list;
-
 
1193
    checkArity(op, args);
-
 
1194
    i = asInteger(CAR(args));
-
 
1195
    for (list = R_RestartStack;
-
 
1196
	 list != R_NilValue && i > 1;
-
 
1197
	 list = CDR(list), i--);
-
 
1198
    if (list != R_NilValue)
-
 
1199
	return CAR(list);
-
 
1200
    else if (i == 1) {
-
 
1201
	/**** need to pre-allocate */
-
 
1202
	SEXP name, entry;
-
 
1203
	PROTECT(name = ScalarString(mkChar("abort")));
-
 
1204
	entry = allocVector(VECSXP, 2);
-
 
1205
	SET_VECTOR_ELT(entry, 0, name);
-
 
1206
	SET_VECTOR_ELT(entry, 1, R_NilValue);
-
 
1207
	setAttrib(entry, R_ClassSymbol, ScalarString(mkChar("restart")));
-
 
1208
	UNPROTECT(1);
-
 
1209
	return entry;
-
 
1210
    }
-
 
1211
    else return R_NilValue;
-
 
1212
}
-
 
1213
 
-
 
1214
/* very minimal error checking --just enough to avoid a segfault */
-
 
1215
#define CHECK_RESTART(r) do { \
-
 
1216
    SEXP __r__ = (r); \
-
 
1217
    if (TYPEOF(__r__) != VECSXP || LENGTH(__r__) < 2) \
-
 
1218
	error("bad restart"); \
-
 
1219
} while (0)
-
 
1220
 
-
 
1221
SEXP do_addRestart(SEXP call, SEXP op, SEXP args, SEXP rho)
-
 
1222
{
-
 
1223
    checkArity(op, args);
-
 
1224
    CHECK_RESTART(CAR(args));
-
 
1225
    R_RestartStack = CONS(CAR(args), R_RestartStack);
-
 
1226
    return R_NilValue;
-
 
1227
}
-
 
1228
 
-
 
1229
#define RESTART_EXIT(r) VECTOR_ELT(r, 1)
-
 
1230
 
-
 
1231
static void invokeRestart(SEXP r, SEXP arglist)
-
 
1232
{
-
 
1233
    SEXP exit = RESTART_EXIT(r);
-
 
1234
 
-
 
1235
    if (exit == R_NilValue) {
-
 
1236
	R_RestartStack = R_NilValue;
-
 
1237
	jump_to_toplevel();
-
 
1238
    }
-
 
1239
    else {
-
 
1240
	for (; R_RestartStack != R_NilValue;
-
 
1241
	     R_RestartStack = CDR(R_RestartStack))
-
 
1242
	    if (exit == RESTART_EXIT(CAR(R_RestartStack))) {
-
 
1243
		R_RestartStack = CDR(R_RestartStack);
-
 
1244
		if (TYPEOF(exit) == EXTPTRSXP) {
-
 
1245
		    RCNTXT *c = R_ExternalPtrAddr(exit);
-
 
1246
		    R_JumpToContext(c, CTXT_RESTART, R_RestartToken);
-
 
1247
		}
-
 
1248
		else findcontext(CTXT_FUNCTION, exit, arglist);
-
 
1249
	    }
-
 
1250
	error("restart not on stack");
-
 
1251
    }
-
 
1252
}
-
 
1253
 
-
 
1254
SEXP do_invokeRestart(SEXP call, SEXP op, SEXP args, SEXP rho)
-
 
1255
{
-
 
1256
    checkArity(op, args);
-
 
1257
    CHECK_RESTART(CAR(args));
-
 
1258
    invokeRestart(CAR(args), CADR(args));
-
 
1259
    return R_NilValue; /* not reached */
-
 
1260
}
-
 
1261
#endif
-
 
1262
 
861
SEXP do_addTryHandlers(SEXP call, SEXP op, SEXP args, SEXP rho)
1263
SEXP do_addTryHandlers(SEXP call, SEXP op, SEXP args, SEXP rho)
862
{
1264
{
863
    checkArity(op, args);
1265
    checkArity(op, args);
864
    if (R_GlobalContext == R_ToplevelContext ||
1266
    if (R_GlobalContext == R_ToplevelContext ||
865
	! R_GlobalContext->callflag & CTXT_FUNCTION)
1267
	! R_GlobalContext->callflag & CTXT_FUNCTION)
866
	errorcall(call, "not in a try context");
1268
	errorcall(call, "not in a try context");
867
    SET_RESTART_BIT_ON(R_GlobalContext->callflag);
1269
    SET_RESTART_BIT_ON(R_GlobalContext->callflag);
-
 
1270
#ifdef NEW_CONDITION_HANDLING
-
 
1271
    R_InsertRestartHandlers(R_GlobalContext, FALSE);
-
 
1272
#endif
868
    return R_NilValue;
1273
    return R_NilValue;
869
}
1274
}