The R Project SVN R

Rev

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

Rev 78125 Rev 79123
Line 46... Line 46...
46
}
46
}
47
 
47
 
48
#ifndef min
48
#ifndef min
49
#define min(a, b) (a<b?a:b)
49
#define min(a, b) (a<b?a:b)
50
#endif
50
#endif
-
 
51
#ifndef max
-
 
52
#define max(a, b) (a>b?a:b)
-
 
53
#endif
51
 
54
 
52
/* Total line length, in chars, before splitting in warnings/errors */
55
/* Total line length, in chars, before splitting in warnings/errors */
53
#define LONGWARN 75
56
#define LONGWARN 75
54
 
57
 
55
/*
58
/*
56
Different values of inError are used to indicate different places
59
Different values of inError are used to indicate different places
57
in the error handling.
60
in the error handling:
-
 
61
inError = 1: In internal error handling, e.g. `verrorcall_dflt`, others.
-
 
62
inError = 2: Writing traceback
-
 
63
inError = 3: In user error handler (i.e. options(error=handler))
58
*/
64
*/
59
static int inError = 0;
65
static int inError = 0;
60
static int inWarning = 0;
66
static int inWarning = 0;
61
static int inPrintWarnings = 0;
67
static int inPrintWarnings = 0;
62
static int immediateWarning = 0;
68
static int immediateWarning = 0;
Line 257... Line 263...
257
{
263
{
258
    R_Warnings = allocVector(VECSXP, R_nwarnings);
264
    R_Warnings = allocVector(VECSXP, R_nwarnings);
259
    setAttrib(R_Warnings, R_NamesSymbol, allocVector(STRSXP, R_nwarnings));
265
    setAttrib(R_Warnings, R_NamesSymbol, allocVector(STRSXP, R_nwarnings));
260
}
266
}
261
 
267
 
262
/* Rvsnprintf: like vsnprintf, but guaranteed to null-terminate and not to
268
/* Rvsnprintf: like vsnprintf, but guaranteed to null-terminate and not to split
-
 
269
   multi-byte characters, except if size is zero in which case the buffer is
263
   split multi-byte characters */
270
   untouched and thus may not be null-terminated.
-
 
271
 
-
 
272
   Dangerous pattern: `Rvsnprintf(buf, size - n, )` with maybe n >= size*/
264
#ifdef Win32
273
#ifdef Win32
265
int trio_vsnprintf(char *buffer, size_t bufferSize, const char *format,
274
int trio_vsnprintf(char *buffer, size_t bufferSize, const char *format,
266
		   va_list args);
275
		   va_list args);
267
 
276
 
268
static int Rvsnprintf(char *buf, size_t size, const char  *format, va_list ap)
277
static int Rvsnprintf(char *buf, size_t size, const char  *format, va_list ap)
269
{
278
{
270
    int val;
279
    int val;
271
    val = trio_vsnprintf(buf, size, format, ap);
280
    val = trio_vsnprintf(buf, size, format, ap);
-
 
281
    if (size) {
-
 
282
	if (val < 0) buf[0] = '\0'; /* not all uses check val < 0 */
272
    buf[size-1] = '\0';
283
	else buf[size-1] = '\0';
273
    if (val >= size)
284
	if (val >= size)
274
	mbcsTruncateToValid(buf);
285
	    mbcsTruncateToValid(buf);
-
 
286
    }
275
    return val;
287
    return val;
276
}
288
}
277
#else
289
#else
278
static int Rvsnprintf(char *buf, size_t size, const char  *format, va_list ap)
290
static int Rvsnprintf(char *buf, size_t size, const char  *format, va_list ap)
279
{
291
{
280
    int val;
292
    int val;
281
    val = vsnprintf(buf, size, format, ap);
293
    val = vsnprintf(buf, size, format, ap);
-
 
294
    if (size) {
-
 
295
	if (val < 0) buf[0] = '\0'; /* not all uses check val < 0 */
282
    buf[size-1] = '\0';
296
	else buf[size-1] = '\0';
283
    if (val >= size)
297
	if (val >= size)
284
	mbcsTruncateToValid(buf);
298
	    mbcsTruncateToValid(buf);
-
 
299
    }
285
    return val;
300
    return val;
286
}
301
}
287
#endif
302
#endif
288
 
303
 
289
/* Rsnprintf: like snprintf, but guaranteed to null-terminate and not to
304
/* Rsnprintf: like snprintf, but guaranteed to null-terminate and not to split
-
 
305
   multi-byte characters, except if size is zero in which case the buffer is
290
   split multi-byte characters */
306
   untouched and thus may not be null-terminated.
-
 
307
 
-
 
308
   Dangerous pattern: `Rsnprintf(buf, size - n, )` with maybe n >= size*/
291
static int Rsnprintf(char *str, size_t size, const char *format, ...)
309
static int Rsnprintf(char *str, size_t size, const char *format, ...)
292
{
310
{
293
    int val;
311
    int val;
294
    va_list ap;
312
    va_list ap;
295
 
313
 
Line 696... Line 714...
696
   overhead due to the checks would be too high, and the program is doing
714
   overhead due to the checks would be too high, and the program is doing
697
   something strange anyway (i.e. running no-segfault tests). The constant
715
   something strange anyway (i.e. running no-segfault tests). The constant
698
   checks in GC and session exit (or .Call) do not have such limit. */
716
   checks in GC and session exit (or .Call) do not have such limit. */
699
static int allowedConstsChecks = 1000;
717
static int allowedConstsChecks = 1000;
700
 
718
 
-
 
719
/* Construct newline terminated error message, write it to global errbuf, and
-
 
720
   possibly display with REprintf. */
701
static void NORET
721
static void NORET
702
verrorcall_dflt(SEXP call, const char *format, va_list ap)
722
verrorcall_dflt(SEXP call, const char *format, va_list ap)
703
{
723
{
704
    if (allowedConstsChecks > 0) {
724
    if (allowedConstsChecks > 0) {
705
	allowedConstsChecks--;
725
	allowedConstsChecks--;
Line 736... Line 756...
736
    cntxt.cend = &restore_inError;
756
    cntxt.cend = &restore_inError;
737
    cntxt.cenddata = &oldInError;
757
    cntxt.cenddata = &oldInError;
738
    oldInError = inError;
758
    oldInError = inError;
739
    inError = 1;
759
    inError = 1;
740
 
760
 
-
 
761
    // For use with Rv?snprintf, which truncates at size - 1, hence the + 1
-
 
762
    size_t msg_len = min(BUFSIZE, R_WarnLength) + 1;
-
 
763
 
741
    if(call != R_NilValue) {
764
    if(call != R_NilValue) {
742
	char tmp[BUFSIZE], tmp2[BUFSIZE];
765
	char tmp[BUFSIZE], tmp2[BUFSIZE];
743
	char *head = _("Error in "), *tail = "\n  ";
766
	char *head = _("Error in "), *tail = "\n  ";
744
	SEXP srcloc = R_NilValue; // -Wall
767
	SEXP srcloc = R_NilValue; // -Wall
745
	size_t len = 0;	// indicates if srcloc has been set
768
	size_t len = 0;	// indicates if srcloc has been set
Line 764... Line 787...
764
	    if (len)
787
	    if (len)
765
		Rsnprintf(tmp2, BUFSIZE,  _("Error in %s (from %s) : "),
788
		Rsnprintf(tmp2, BUFSIZE,  _("Error in %s (from %s) : "),
766
			 dcall, CHAR(STRING_ELT(srcloc, 0)));
789
			 dcall, CHAR(STRING_ELT(srcloc, 0)));
767
	}
790
	}
768
 
791
 
769
	Rvsnprintf(tmp, min(BUFSIZE, R_WarnLength) - strlen(head), format, ap);
792
	Rvsnprintf(tmp, max(msg_len - strlen(head), 0), format, ap);
770
	if (strlen(tmp2) + strlen(tail) + strlen(tmp) < BUFSIZE) {
793
	if (strlen(tmp2) + strlen(tail) + strlen(tmp) < BUFSIZE) {
771
	    if(len) Rsnprintf(errbuf, BUFSIZE,
794
	    if(len) Rsnprintf(errbuf, BUFSIZE,
772
			     _("Error in %s (from %s) : "),
795
			     _("Error in %s (from %s) : "),
773
			     dcall, CHAR(STRING_ELT(srcloc, 0)));
796
			     dcall, CHAR(STRING_ELT(srcloc, 0)));
774
	    else Rsnprintf(errbuf, BUFSIZE,  _("Error in %s : "), dcall);
797
	    else Rsnprintf(errbuf, BUFSIZE,  _("Error in %s : "), dcall);
Line 793... Line 816...
793
		    ERRBUFCAT(tail);
816
		    ERRBUFCAT(tail);
794
	    }
817
	    }
795
	    ERRBUFCAT(tmp);
818
	    ERRBUFCAT(tmp);
796
	} else {
819
	} else {
797
	    Rsnprintf(errbuf, BUFSIZE, _("Error: "));
820
	    Rsnprintf(errbuf, BUFSIZE, _("Error: "));
798
	    ERRBUFCAT(tmp); // FIXME
821
	    ERRBUFCAT(tmp);
799
	}
822
	}
800
	UNPROTECT(protected);
823
	UNPROTECT(protected);
801
    }
824
    }
802
    else {
825
    else {
803
	Rsnprintf(errbuf, BUFSIZE, _("Error: "));
826
	Rsnprintf(errbuf, BUFSIZE, _("Error: "));
804
	p = errbuf + strlen(errbuf);
827
	p = errbuf + strlen(errbuf);
805
	Rvsnprintf(p, min(BUFSIZE, R_WarnLength) - strlen(errbuf), format, ap);
828
	Rvsnprintf(p, max(msg_len - strlen(errbuf), 0), format, ap);
806
    }
829
    }
807
 
-
 
-
 
830
    /* Approximate truncation detection, may produce false positives.  Assumes
-
 
831
       MB_CUR_MAX > 0. Note: approximation is fine, as the string may include
-
 
832
       dots, anyway */
808
    size_t nc = strlen(errbuf);
833
    size_t nc = strlen(errbuf); // > 0, ignoring possibility of failure
809
    if (nc == BUFSIZE - 1) {
834
    if (nc > BUFSIZE - 1 - (MB_CUR_MAX - 1)) {
810
	errbuf[BUFSIZE - 4] = '.';
835
	size_t end = min(nc + 1, (BUFSIZE + 1) - 4); // room for "...\n\0"
811
	errbuf[BUFSIZE - 3] = '.';
836
	for(size_t i = end; i <= BUFSIZE + 1; ++i) errbuf[i - 1] = '\0';
812
	errbuf[BUFSIZE - 2] = '.';
837
	mbcsTruncateToValid(errbuf);
813
	errbuf[BUFSIZE - 1] = '\n';
838
	ERRBUFCAT("...\n");
814
    }
-
 
815
    else {
839
    } else {
816
	p = errbuf + nc - 1;
840
	p = errbuf + nc - 1;
817
	if(*p != '\n') ERRBUFCAT("\n");
841
	if(*p != '\n') {
-
 
842
	    ERRBUFCAT("\n");  // guaranteed to have room for this
818
    }
843
	    ++nc;
819
 
844
	}
820
    if(R_ShowErrorCalls && call != R_NilValue) {  /* assume we want to avoid deparse */
845
	if(R_ShowErrorCalls && call != R_NilValue) {  /* assume we want to avoid deparse */
821
	tr = R_ConciseTraceback(call, 0);
846
	    tr = R_ConciseTraceback(call, 0);
822
	size_t nc = strlen(tr);
847
	    size_t nc_tr = strlen(tr);
-
 
848
	    if (nc_tr) {
-
 
849
		char * call_trans = _("Calls:");
823
	if (nc && nc + strlen(errbuf) + 8 < BUFSIZE) {
850
		if (nc_tr + nc + strlen(call_trans) + 2 < BUFSIZE + 1) {
824
	    ERRBUFCAT(_("Calls:"));
851
		    ERRBUFCAT(call_trans);
825
	    ERRBUFCAT(" ");
852
		    ERRBUFCAT(" ");
826
	    ERRBUFCAT(tr);
853
		    ERRBUFCAT(tr);
827
	    ERRBUFCAT("\n");
854
		    ERRBUFCAT("\n");
-
 
855
		}
-
 
856
	    }
828
	}
857
	}
829
    }
858
    }
830
    if (R_ShowErrorMessages) REprintf("%s", errbuf);
859
    if (R_ShowErrorMessages) REprintf("%s", errbuf);
831
 
860
 
832
    if( R_ShowErrorMessages && R_CollectWarnings ) {
861
    if( R_ShowErrorMessages && R_CollectWarnings ) {
Line 2409... Line 2438...
2409
 
2438
 
2410
SEXP R_withCallingErrorHandler(SEXP (*body)(void *), void *bdata,
2439
SEXP R_withCallingErrorHandler(SEXP (*body)(void *), void *bdata,
2411
			       SEXP (*handler)(SEXP, void *), void *hdata)
2440
			       SEXP (*handler)(SEXP, void *), void *hdata)
2412
{
2441
{
2413
    /* This defines the lambda expression for th handler. The `addr`
2442
    /* This defines the lambda expression for th handler. The `addr`
2414
       variable wil be defined in the closure environment and contain
2443
       variable will be defined in the closure environment and contain
2415
       an external pointer to the callback data. */
2444
       an external pointer to the callback data. */
2416
    static const char* wceh_callback_source =
2445
    static const char* wceh_callback_source =
2417
	"function(cond) .Internal(C_tryCatchHelper(addr, 1L, cond))";
2446
	"function(cond) .Internal(C_tryCatchHelper(addr, 1L, cond))";
2418
 
2447
 
2419
    static SEXP wceh_callback = NULL;
2448
    static SEXP wceh_callback = NULL;