@@ -2093,9 +2093,9 @@ int attribute_hidden Rf_AdobeSymbol2ucs2(int n)
20932093 R_strtod5 is used by type_convert(numerals=) (utils/src/io.c)
20942094
20952095 The parser uses R_atof (and handles non-numeric strings itself).
2096- That is the same as R_strtod but ignores endptr.
2097- Also used by gnuwin32/windlgs/src/ttest.c,
2098- exported and in Utils.h (but not in R-exts).
2096+ That is the same as R_strtod but ignores endptr. Also used by
2097+ gnuwin32/windlgs/src/ttest.c, exported and in Utils.h (and
2098+ documeented in R-exts only since R 4.4.1 )
20992099*/
21002100
21012101double R_strtod5 (const char * str , char * * endptr , char dec ,
@@ -2138,6 +2138,12 @@ double R_strtod5(const char *str, char **endptr, char dec,
21382138
21392139 int n , expn = 0 ;
21402140 if (strlen (p ) > 2 && p [0 ] == '0' && (p [1 ] == 'x' || p [1 ] == 'X' )) { // Hexadecimal "0x....."
2141+ /* Prior to 4.5.0 this did not allow forms such as 0x1.234
2142+ without an exponent.: C99 allow this and implictly
2143+ appends "p0"".
2144+
2145+ Changed following PR£18805
2146+ */
21412147 int exph = -1 ;
21422148
21432149 /* This will overflow to Inf if appropriate */
@@ -2162,16 +2168,18 @@ double R_strtod5(const char *str, char **endptr, char dec,
21622168 } \
21632169 }
21642170 strtod_EXACT_CLAUSE ;
2171+ /* Binary exponent, if any */
21652172 if (* p == 'p' || * p == 'P' ) {
21662173 int expsign = 1 ;
2167- double p2 = 2.0 ;
21682174 switch (* ++ p ) {
21692175 case '-' : expsign = -1 ;
21702176 case '+' : p ++ ;
21712177 default : ;
21722178 }
21732179#define MAX_EXPONENT_PREFIX 9999
2174- /* exponents beyond ca +1024/-1076 over/underflow */
2180+ /* exponents beyond ca +1024/-1076 over/underflow
2181+ Limit exponsent from PR#16358.
2182+ */
21752183 int ndig = 0 ;
21762184 for (n = 0 ; * p >= '0' && * p <= '9' ; p ++ , ndig ++ )
21772185 n = (n < MAX_EXPONENT_PREFIX ) ? n * 10 + (* p - '0' ) : n ;
@@ -2180,28 +2188,29 @@ double R_strtod5(const char *str, char **endptr, char dec,
21802188 p = str ; /* back out */
21812189 goto done ;
21822190 }
2183- if (ans != 0.0 ) { /* PR#15976: allow big exponents on 0 */
2184- LDOUBLE fac = 1.0 ;
2185- expn += expsign * n ;
2186- if (exph > 0 ) {
2187- if (expn - exph < -122 ) { /* PR#17199: fac may overflow below if expn - exph is too small.
2188- 2^-122 is a bit bigger than 1E-37, so should be fine on all systems */
2189- for (n = exph , fac = 1.0 ; n ; n >>= 1 , p2 *= p2 )
2190- if (n & 1 ) fac *= p2 ;
2191- ans /= fac ;
2192- p2 = 2.0 ;
2193- } else
2194- expn -= exph ;
2195- }
2196- if (expn < 0 ) {
2197- for (n = - expn , fac = 1.0 ; n ; n >>= 1 , p2 *= p2 )
2191+ expn += expsign * n ;
2192+ }
2193+ if (ans != 0.0 ) { /* PR#15976: allow big exponents on 0 */
2194+ LDOUBLE fac = 1.0 ;
2195+ double p2 = 2.0 ;
2196+ if (exph > 0 ) {
2197+ if (expn - exph < -122 ) { /* PR#17199: fac may overflow below if expn - exph is too small.
2198+ 2^-122 is a bit bigger than 1E-37, so should be fine on all systems */
2199+ for (n = exph , fac = 1.0 ; n ; n >>= 1 , p2 *= p2 )
21982200 if (n & 1 ) fac *= p2 ;
21992201 ans /= fac ;
2200- } else {
2201- for (n = expn , fac = 1.0 ; n ; n >>= 1 , p2 *= p2 )
2202- if (n & 1 ) fac *= p2 ;
2203- ans *= fac ;
2204- }
2202+ p2 = 2.0 ;
2203+ } else
2204+ expn -= exph ;
2205+ }
2206+ if (expn < 0 ) {
2207+ for (n = - expn , fac = 1.0 ; n ; n >>= 1 , p2 *= p2 )
2208+ if (n & 1 ) fac *= p2 ;
2209+ ans /= fac ;
2210+ } else {
2211+ for (n = expn , fac = 1.0 ; n ; n >>= 1 , p2 *= p2 )
2212+ if (n & 1 ) fac *= p2 ;
2213+ ans *= fac ;
22052214 }
22062215 }
22072216 goto done ;
0 commit comments