diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2012-10-01 17:35:10 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2012-10-01 17:35:10 -0700 |
commit | 40bae281a56c9e305852905dcbd29125de388b25 (patch) | |
tree | e2f1675ca58161fb791e179acf31c744b64deb63 /lib.c | |
parent | baf80248032cdb8856d9e3217d48e9fd5e9e49c5 (diff) | |
download | txr-40bae281a56c9e305852905dcbd29125de388b25.tar.gz txr-40bae281a56c9e305852905dcbd29125de388b25.tar.bz2 txr-40bae281a56c9e305852905dcbd29125de388b25.zip |
* arith.c (bignum_from_long): New function.
* arith.h (bignum_from_long): Declared.
* lib.c (int_str): Streamlined. Only use mp_read_radix in the case when
wcstol fails, because now we have bignum_from_long to handle all values
of long. Ensure that the bignum is normalized, in case it falls in the
fixnum range (does not happen on our usual platforms).
Diffstat (limited to 'lib.c')
-rw-r--r-- | lib.c | 17 |
1 files changed, 11 insertions, 6 deletions
@@ -2104,11 +2104,11 @@ val int_str(val str, val base) /* TODO: detect if we have wcstoll */ long value = wcstol(wcs, &ptr, b ? b : 10); + if (value == 0 && ptr == wcs) return nil; - if (((value == LONG_MAX || value == LONG_MIN) && errno == ERANGE) || - (value < NUM_MIN || value > NUM_MAX)) - { + + if ((value == LONG_MAX || value == LONG_MIN) && errno == ERANGE) { val bignum = make_bignum(); unsigned char *ucs = utf8_dup_to_uc(wcs); mp_err err = mp_read_radix(mp(bignum), ucs, b); @@ -2118,10 +2118,15 @@ val int_str(val str, val base) if (err != MP_OKAY) return nil; - return bignum; - } + /* If wcstol overflowed, but the range of long is smaller than + that of fixnums, that means that the value might not + actually be a bignum, and so we must normalize. + We do not need this on our usual target platforms, where NUM_MAX is + never larger than LONG_MAX. */ + return (LONG_MAX < NUM_MAX) ? normalize(bignum) : bignum; + } - return num(value); + return bignum_from_long(value); } val flo_str(val str) |