Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
emacs
emacs
Commits
d78050d6
Commit
d78050d6
authored
Apr 21, 2011
by
Paul Eggert
Browse files
* lread.c (string_to_number): Use strtoumax, to convert more integers without overflow.
parent
452f4150
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
34 additions
and
33 deletions
+34
-33
src/ChangeLog
src/ChangeLog
+5
-2
src/lread.c
src/lread.c
+29
-31
No files found.
src/ChangeLog
View file @
d78050d6
...
...
@@ -11,7 +11,8 @@
parsing non-base-10 numbers, as the documentation specifies.
* lisp.h (string_to_number): New decl, replacing ...
(isfloat_string): Remove.
* lread.c (read1): Do not accept +. and -. as integers; this
* lread.c: Include <inttypes.h>, for uintmax_t and strtoimax.
(read1): Do not accept +. and -. as integers; this
appears to have been a coding error. Similarly, do not accept
strings like +-1e0 as floating point numbers. Do not report
overflow for integer overflows unless the base is not 10 which
...
...
@@ -25,7 +26,9 @@
(string_to_number): New function, replacing isfloat_string.
This function checks for valid syntax and produces the resulting
Lisp float number too. Rework it so that string-to-number
no longer mishandles examples like "1.0e+".
no longer mishandles examples like "1.0e+". Use strtoimax,
so that overflow for non-base-10 numbers is reported only when
there's no portable and simple way to convert to floating point.
2011-04-20 Paul Eggert <eggert@cs.ucla.edu>
...
...
src/lread.c
View file @
d78050d6
...
...
@@ -19,6 +19,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <inttypes.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
...
...
@@ -3226,7 +3227,6 @@ string_to_number (char const *string, int base, int ignore_trailing)
++
cp
;
while
(
0
<=
digit_to_number
(
*
cp
,
base
));
}
if
(
*
cp
==
'.'
)
{
state
|=
DOT_CHAR
;
...
...
@@ -3300,47 +3300,45 @@ string_to_number (char const *string, int base, int ignore_trailing)
:
(
!*
cp
&&
((
state
&
~
DOT_CHAR
)
==
LEAD_INT
||
float_syntax
))))
return
Qnil
;
/* If the number
do
es
not use
float syntax, and
fit
s in
to a fixnum, return
the
fixnum. */
/* If the number
us
es
integer and not
float syntax, and
i
s in
C-language
range, use its value, preferably as a
fixnum. */
if
(
0
<=
leading_digit
&&
!
float_syntax
)
{
/* Convert string to EMACS_INT. Do not use strtol, to avoid assuming
that EMACS_INT is no wider than 'long', and because when BASE is 16
strtol might accept numbers like "0x1" that are not allowed here. */
EMACS_INT
n
=
leading_digit
;
EMACS_INT
abs_bound
=
(
negative
?
-
MOST_NEGATIVE_FIXNUM
:
MOST_POSITIVE_FIXNUM
);
EMACS_INT
abs_bound_over_base
=
abs_bound
/
base
;
for
(
cp
=
string
+
signedp
+
1
;
;
cp
++
)
uintmax_t
n
;
/* Fast special case for single-digit integers. This also avoids a
glitch when BASE is 16 and IGNORE_TRAILING is nonzero, because in that
case some versions of strtoumax accept numbers like "0x1" that Emacs
does not allow. */
if
(
digit_to_number
(
string
[
signedp
+
1
],
base
)
<
0
)
return
make_number
(
negative
?
-
leading_digit
:
leading_digit
);
errno
=
0
;
n
=
strtoumax
(
string
+
signedp
,
NULL
,
base
);
if
(
errno
==
ERANGE
)
{
int
d
=
digit_to_number
(
*
cp
,
base
);
if
(
d
<
0
)
{
if
(
n
<=
abs_bound
)
return
make_number
(
negative
?
-
n
:
n
);
break
;
}
if
(
abs_bound_over_base
<
n
)
break
;
n
=
base
*
n
+
d
;
/* Unfortunately there's no simple and accurate way to convert
non-base-10 numbers that are out of C-language range. */
if
(
base
!=
10
)
xsignal
(
Qoverflow_error
,
list1
(
build_string
(
string
)));
}
/* Unfortunately there's no simple and reliable way to convert
non-base-10 to floating point. */
if
(
base
!=
10
)
xsignal
(
Qoverflow_error
,
list1
(
build_string
(
string
)));
else
if
(
n
<=
(
negative
?
-
MOST_NEGATIVE_FIXNUM
:
MOST_POSITIVE_FIXNUM
))
{
EMACS_INT
signed_n
=
n
;
return
make_number
(
negative
?
-
signed_n
:
signed_n
);
}
else
value
=
n
;
}
/* Either the number uses float syntax, or it does not fit into a fixnum.
Convert it from string to floating point, unless the value is already
known because it is an infinity or a NAN. */
known because it is an infinity, a NAN, or its absolute value fits in
uintmax_t. */
if
(
!
value
)
value
=
atof
(
string
+
signedp
);
if
(
negative
)
value
=
-
value
;
return
make_float
(
value
);
return
make_float
(
negative
?
-
value
:
value
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment