Skip to content

Commit 04bc4df

Browse files
author
kalibera
committed
Fix options(show.error.locations) to work with byte-code interpreter and
rationalize supported values. Fix R_GetCurrentSrcref()'s counting of R contexts to be compatible with traceback(). PR#18841, from Duncan Murdoch. git-svn-id: https://svn.r-project.org/R/trunk@87647 00db46b3-68df-0310-9c12-caf00c1e9a41
1 parent 2205457 commit 04bc4df

File tree

4 files changed

+78
-36
lines changed

4 files changed

+78
-36
lines changed

doc/NEWS.Rd

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,14 @@
342342
\code{Rf_*()} as has been documented in
343343
\sQuote{Writing R Extensions} for a while, fixing \PR{18800}
344344
thanks to \I{Mikael Jagan} and \I{Suharto Anggono}.
345+
346+
\item \code{R_GetCurrentSrcref(skip)} now skips calls rather
347+
than \code{srcref}s, consistent with counting items in the
348+
\code{traceback()} display. If \code{skip == NA_INTEGER},
349+
it searches for the first \code{srcref}, starting at
350+
the current evaluation state and proceeding through the
351+
call stack; otherwise, it returns the \code{srcref}
352+
of the requested entry from the call stack.
345353
}
346354
}
347355

@@ -497,7 +505,18 @@
497505
\item \code{summary(<stl>)} (which prints directly) finally gets the
498506
same \code{digits} default as the formatting printing of default
499507
\code{summary()} method results, and it is documented explicitly.
500-
}
508+
509+
\item \code{options(show.error.locations = TRUE)} once
510+
again shows the most recent known location when an
511+
error is reported. Setting its value to \code{"bottom"}
512+
is no longer supported. Numerical values are converted
513+
to logical.
514+
515+
\item C API function \code{R_GetCurrentSrcref(skip)} now
516+
returns \code{srcref} entries correctly. (Note that there
517+
is also a change to the interpretation of \code{skip};
518+
see the C-LEVEL API entry above.)
519+
}
501520
}
502521
}
503522

doc/manual/R-exts.texi

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14342,13 +14342,18 @@ make these available to debuggers running C code:
1434214342
SEXP R_GetCurrentSrcref(int skip);
1434314343
@end example
1434414344

14345-
This function checks @code{R_Srcref} and the current evaluation stack
14346-
for entries that contain source reference information. The
14347-
@code{skip} argument tells how many source references to skip before
14348-
returning the @code{SEXP} of the @code{srcref} object, counting from
14349-
the top of the stack. If @code{skip < 0}, @code{abs(skip)} locations
14350-
are counted up from the bottom of the stack. If too few or no source
14351-
references are found, @code{NULL} is returned.
14345+
This function checks the current evaluation stack
14346+
for entries that contain source reference information. There
14347+
are two modes of operation.
14348+
If @code{skip == NA_INTEGER}, the @code{R_Srcref} entry is checked
14349+
followed by entries in the call stack, until a @code{srcref}
14350+
is found. Otherwise, the @code{skip} argument tells how many
14351+
calls to skip (counting from the top of the stack) before
14352+
returning the @code{SEXP} of the call's @code{srcref} object or
14353+
@code{NULL} if that call did not have one. If @code{skip < 0},
14354+
@code{abs(skip)} locations are counted up from the bottom of the
14355+
stack. If too few or no source references are found, @code{NULL}
14356+
is returned.
1435214357

1435314358
@example
1435414359
SEXP R_GetSrcFilename(SEXP srcref);

src/library/base/man/options.Rd

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -394,13 +394,7 @@ getOption(x, default = NULL)
394394
\item{\code{show.error.locations}:}{Should source locations of
395395
errors be printed? If set to \code{TRUE} or \code{"top"}, the
396396
source location that is highest on the stack (the most recent
397-
call) will be printed. \code{"bottom"} will print the location
398-
of the earliest call found on the stack.
399-
400-
Integer values can select other entries. The value \code{0}
401-
corresponds to \code{"top"} and positive values count down the
402-
stack from there. The value \code{-1} corresponds to
403-
\code{"bottom"} and negative values count up from there.
397+
code with source information) will be printed.
404398
}
405399

406400
\item{\code{show.error.messages}:}{a logical. Should error messages

src/main/errors.c

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* R : A Computer Language for Statistical Data Analysis
3-
* Copyright (C) 1995--2024 The R Core Team.
3+
* Copyright (C) 1995--2025 The R Core Team.
44
*
55
* This program is free software; you can redistribute it and/or modify
66
* it under the terms of the GNU General Public License as published by
@@ -795,22 +795,18 @@ verrorcall_dflt(SEXP call, const char *format, va_list ap)
795795
char *head = _("Error in "), *tail = "\n ";
796796
SEXP srcloc = R_NilValue; // -Wall
797797
size_t len = 0; // indicates if srcloc has been set
798-
int protected = 0, skip = NA_INTEGER;
798+
int protected = 0, show = 0;
799799
SEXP opt = GetOption1(install("show.error.locations"));
800-
if (!isNull(opt)) {
801-
if (TYPEOF(opt) == STRSXP && length(opt) == 1) {
802-
if (pmatch(ScalarString(mkChar("top")), opt, 0)) skip = 0;
803-
else if (pmatch(ScalarString(mkChar("bottom")), opt, 0)) skip = -1;
804-
} else if (TYPEOF(opt) == LGLSXP)
805-
skip = asLogical(opt) == 1 ? 0 : NA_INTEGER;
806-
else
807-
skip = asInteger(opt);
808-
}
800+
if (length(opt) == 1 &&
801+
(asLogical(opt) == 1 ||
802+
(TYPEOF(opt) == STRSXP &&
803+
pmatch(ScalarString(mkChar("top")), opt, 0))))
804+
show = 1;
809805

810806
const char *dcall = CHAR(STRING_ELT(deparse1s(call), 0));
811807
Rsnprintf_mbcs(tmp2, BUFSIZE, "%s", head);
812-
if (skip != NA_INTEGER) {
813-
PROTECT(srcloc = GetSrcLoc(R_GetCurrentSrcref(skip)));
808+
if (show) {
809+
PROTECT(srcloc = GetSrcLoc(R_GetCurrentSrcref(NA_INTEGER)));
814810
protected++;
815811
len = strlen(CHAR(STRING_ELT(srcloc, 0)));
816812
if (len)
@@ -1504,6 +1500,15 @@ static void R_PrintDeferredWarnings(void)
15041500
PrintWarnings();
15051501
}
15061502
}
1503+
1504+
/* if srcref indicates it is in bytecode, it needs a fixup */
1505+
static SEXP fixBCSrcref(SEXP srcref, RCNTXT *c)
1506+
{
1507+
if (srcref == R_InBCInterpreter)
1508+
srcref = R_findBCInterpreterSrcref(c);
1509+
return srcref;
1510+
}
1511+
15071512
/*
15081513
* Return the traceback without deparsing the calls
15091514
*/
@@ -2342,25 +2347,44 @@ SEXP
23422347
R_GetCurrentSrcref(int skip)
23432348
{
23442349
RCNTXT *c = R_GlobalContext;
2345-
SEXP srcref = R_Srcref;
2350+
SEXP srcref;
2351+
int keep_looking = skip == NA_INTEGER;
2352+
if (keep_looking) skip = 0;
23462353
if (skip < 0) { /* to count up from the bottom, we need to count them all first */
23472354
while (c) {
2348-
if (srcref && srcref != R_NilValue)
2355+
if (c->callflag & (CTXT_FUNCTION | CTXT_BUILTIN))
23492356
skip++;
2350-
srcref = c->srcref;
23512357
c = c->nextcontext;
23522358
};
23532359
if (skip < 0) return R_NilValue; /* not enough there */
23542360
c = R_GlobalContext;
2355-
srcref = R_Srcref;
23562361
}
2357-
while (c && (skip || !srcref || srcref == R_NilValue)) {
2358-
if (srcref && srcref != R_NilValue)
2362+
2363+
/* If skip = NA, try current active srcref first. */
2364+
2365+
if (keep_looking) {
2366+
srcref = R_getCurrentSrcref();
2367+
if (srcref && !isNull(srcref))
2368+
return srcref;
2369+
}
2370+
2371+
/* Go to the first call */
2372+
while (c && !(c->callflag & (CTXT_FUNCTION | CTXT_BUILTIN)))
2373+
c = c->nextcontext;
2374+
2375+
/* Now skip enough calls, regardless of srcref presence */
2376+
while (c && skip) {
2377+
if (c->callflag & (CTXT_FUNCTION | CTXT_BUILTIN))
23592378
skip--;
2360-
srcref = c->srcref;
23612379
c = c->nextcontext;
23622380
}
2363-
if (skip || !srcref)
2381+
/* Now get the next srcref. If skip was not NA, don't
2382+
keep looking. */
2383+
do {
2384+
srcref = fixBCSrcref(c->srcref, c);
2385+
c = c->nextcontext;
2386+
} while (keep_looking && c && !(srcref && !isNull(srcref)));
2387+
if (!srcref)
23642388
srcref = R_NilValue;
23652389
return srcref;
23662390
}

0 commit comments

Comments
 (0)