Skip to content

Commit 00e4191

Browse files
author
maechler
committed
prevent options(scipen = NULL) or = 1e99; set and document limits.
git-svn-id: https://svn.r-project.org/R/trunk@87381 00db46b3-68df-0310-9c12-caf00c1e9a41
1 parent 6db6113 commit 00e4191

File tree

5 files changed

+68
-6
lines changed

5 files changed

+68
-6
lines changed

doc/NEWS.Rd

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,12 @@
386386
(non integer) seconds. Fixes \PR{17350}, thanks to new contributions
387387
by \I{LatinR}'s \sQuote{\I{R Dev Day}} participants, \I{Heather
388388
Turner} and \I{Dirk Eddelbuettel}.
389+
390+
\item \code{options(scipen = NULL)} and other invalid values now
391+
signal an error instead of invalidating ops relying on a finite
392+
integer value. Newly, values outside the range -9 .. 9999 are warned
393+
about and set to a respective boundary or to the default \code{0},
394+
e.g., in case of an \code{NA}.
389395
}
390396
}
391397
}

src/include/Print.h

Lines changed: 4 additions & 1 deletion
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) 1997--2021 The R Core Team.
3+
* Copyright (C) 1997--2024 The R Core Team.
44
* Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka
55
*
66
* This program is free software; you can redistribute it and/or modify
@@ -74,9 +74,12 @@ void R_PV(SEXP s);
7474
/* Offset for rowlabels if there are named dimnames */
7575
#define R_MIN_LBLOFF 2
7676

77+
/* Enforced in ../main/options.c : */
7778
#define R_MIN_WIDTH_OPT 10
7879
#define R_MAX_WIDTH_OPT 10000
7980
#define R_MIN_DIGITS_OPT 1
8081
#define R_MAX_DIGITS_OPT 22
82+
#define R_MIN_SCIPEN_OPT -9
83+
#define R_MAX_SCIPEN_OPT 9999
8184

8285
#endif

src/library/base/man/options.Rd

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,13 @@ getOption(x, default = NULL)
366366
when deciding to print numeric values in fixed or exponential
367367
notation. Positive values bias towards fixed and negative towards
368368
scientific notation: fixed notation will be preferred unless it is
369-
more than \code{scipen} digits wider.}
369+
more than \code{scipen} digits wider. The default is \code{0}.
370+
Valid values are between -9 and 9999 where \dQuote{relevant} values
371+
(for double precision accuracy) are in \code{-6:319}.
372+
Some invalid values currently signal a \code{\link{warning}} and are set
373+
to legal boundaries if finite. These may signal an error in a future
374+
version of \R.
375+
}
370376

371377
\item{\code{setWidthOnResize}:}{a logical. If set and \code{TRUE}, \R
372378
run in a terminal using a recent \code{readline} library will set

src/main/options.c

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
* Either accessing and/or setting a global C variable,
4545
* or just accessed by e.g. GetOption1(install("pager"))
4646
*
47-
* A (complete?!) list of these (2) {plus some of 1)}:
47+
* An (incomplete) list of these (2) {plus some of 1)}:
4848
*
4949
* "prompt"
5050
* "continue"
@@ -57,7 +57,6 @@
5757
* "keep.source.pkgs"
5858
* "keep.parse.data"
5959
* "keep.parse.data.pkgs"
60-
* "browserNLdisabled"
6160
6261
* "de.cellwidth" ../unix/X11/ & ../gnuwin32/dataentry.c
6362
* "device"
@@ -78,6 +77,8 @@
7877
* "warning.expression"
7978
* "nwarnings"
8079
80+
* "browserNLdisabled"
81+
8182
* "matprod"
8283
* "PCRE_study"
8384
* "PCRE_use_JIT"
@@ -174,6 +175,34 @@ attribute_hidden int GetOptionDigits(void)
174175
return FixupDigits(GetOption1(install("digits")), iWARN);
175176
}
176177

178+
static
179+
int FixupScipen(SEXP scipen, warn_type warn)
180+
{
181+
if (!isNumeric(scipen) || LENGTH(scipen) != 1)
182+
error(_("invalid 'scipen'"));
183+
int d;
184+
if(TYPEOF(scipen) == REALSXP) { /* preventing warning + error : */
185+
int w = 0;
186+
d = IntegerFromReal(REAL_ELT(scipen, 0), &w);
187+
if(w && d == NA_INTEGER)
188+
error(_("setting scipen=%g is out of range"), REAL_ELT(scipen,0));
189+
} else
190+
d = asInteger(scipen);
191+
if (d == NA_INTEGER || d < R_MIN_SCIPEN_OPT || d > R_MAX_SCIPEN_OPT) {
192+
int dnew = (d == NA_INTEGER) ? 0 :
193+
(d < R_MIN_SCIPEN_OPT) ? R_MIN_SCIPEN_OPT :
194+
/* d > R_MAX_SCIPEN_OPT */ R_MAX_SCIPEN_OPT;
195+
switch(warn) {
196+
case iWARN: warning(_("invalid 'scipen' %d, used %d"), d, dnew);
197+
case iSILENT:
198+
return dnew; // for SILENT and WARN
199+
case iERROR: error(_("invalid 'scipen' %d"), d);
200+
}
201+
}
202+
return d;
203+
}
204+
205+
177206
attribute_hidden
178207
int GetOptionCutoff(void)
179208
{
@@ -561,20 +590,21 @@ attribute_hidden SEXP do_options(SEXP call, SEXP op, SEXP args, SEXP rho)
561590
"width", "deparse.cutoff", "digits", "echo", "verbose",
562591
"check.bounds", "keep.source", "keep.source.pkgs",
563592
"keep.parse.data", "keep.parse.data.pkgs", "warning.length",
564-
"nwarnings", "OutDec", "browserNLdisabled", "CBoundsCheck",
593+
"nwarnings", "OutDec", "CBoundsCheck",
565594
"matprod", "PCRE_study", "PCRE_use_JIT",
566595
"PCRE_limit_recursion", "rl_word_breaks",
567596
"max.contour.segments", "warnPartialMatchDollar",
568597
"warnPartialMatchArgs", "warnPartialMatchAttr",
569598
"showWarnCalls", "showErrorCalls", "showNCalls",
570599
"browserNLdisabled",
571600
/* ^^^ from InitOptions ^^^ */
572-
"warn", "max.print", "show.error.messages",
601+
"warn", "max.print", "show.error.messages", "scipen",
573602
/* ^^^ from Common.R ^^^ */
574603
NULL};
575604
for(int j = 0; mandatory[j] != NULL; j++)
576605
if (streql(CHAR(namei), mandatory[j]))
577606
error(_("option '%s' cannot be deleted"), CHAR(namei));
607+
// "else" :
578608
SET_VECTOR_ELT(value, i, SetOption(tag, R_NilValue));
579609
} else if (streql(CHAR(namei), "width")) {
580610
int k = asInteger(argi);
@@ -684,6 +714,10 @@ attribute_hidden SEXP do_options(SEXP call, SEXP op, SEXP args, SEXP rho)
684714
if (k < 1) error(_("invalid value for '%s'"), CHAR(namei));
685715
SET_VECTOR_ELT(value, i, SetOption(tag, ScalarInteger(k)));
686716
}
717+
else if (streql(CHAR(namei), "scipen")) {
718+
int k = FixupScipen(argi, iWARN); /* to become iERROR in say 2027 */
719+
SET_VECTOR_ELT(value, i, SetOption(tag, ScalarInteger(k)));
720+
}
687721
else if (streql(CHAR(namei), "nwarnings")) {
688722
int k = asInteger(argi);
689723
if (k < 1) error(_("invalid value for '%s'"), CHAR(namei));

tests/reg-tests-1e.R

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,6 +1599,19 @@ stopifnot(exprs = {
15991599
## 2nd debugonce() call failed in R <= 4.4.2
16001600

16011601

1602+
## options(scipen = <invalid>)
1603+
scipenO <- getOption("scipen")
1604+
assertErrV(options(scipen = NULL))# would work (but ..) in R <= 4.2.2
1605+
assertErrV(options(scipen = 1:2)) # would just work
1606+
assertErrV(options(scipen = 1e99))# would "work" w/ 2 warnings and invalid setting
1607+
stopifnot(identical(getOption("scipen"), scipenO))# unchanged
1608+
tools::assertWarning(verbose=TRUE, options(scipen = -100 ))# warns and sets to min = -9
1609+
stopifnot(identical(getOption("scipen"), -9L))
1610+
tools::assertWarning(verbose=TRUE, options(scipen = 100000))# warns and sets to max = 9999
1611+
stopifnot(identical(getOption("scipen"), 9999L))
1612+
## setting to NULL would invalidate as.character(Sys.time())
1613+
1614+
16021615

16031616
## keep at end
16041617
rbind(last = proc.time() - .pt,

0 commit comments

Comments
 (0)