(root)/
coreutils-9.4/
lib/
strtod.c
       1  /* Copyright (C) 1991-1992, 1997, 1999, 2003, 2006, 2008-2023 Free Software
       2     Foundation, Inc.
       3  
       4     This file is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU Lesser General Public License as
       6     published by the Free Software Foundation, either version 3 of the
       7     License, or (at your option) any later version.
       8  
       9     This file is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  #if ! defined USE_LONG_DOUBLE
      18  # include <config.h>
      19  #endif
      20  
      21  /* Specification.  */
      22  #include <stdlib.h>
      23  
      24  #include <ctype.h>      /* isspace() */
      25  #include <errno.h>
      26  #include <float.h>      /* {DBL,LDBL}_{MIN,MAX} */
      27  #include <limits.h>     /* LONG_{MIN,MAX} */
      28  #include <locale.h>     /* localeconv() */
      29  #include <math.h>       /* NAN */
      30  #include <stdio.h>      /* sprintf() */
      31  #include <string.h>     /* strdup() */
      32  #if HAVE_NL_LANGINFO
      33  # include <langinfo.h>
      34  #endif
      35  
      36  #include "c-ctype.h"
      37  
      38  #undef MIN
      39  #undef MAX
      40  #ifdef USE_LONG_DOUBLE
      41  # define STRTOD strtold
      42  # define LDEXP ldexpl
      43  # if defined __hpux && defined __hppa
      44     /* We cannot call strtold on HP-UX/hppa, because its return type is a struct,
      45        not a 'long double'.  */
      46  #  define HAVE_UNDERLYING_STRTOD 0
      47  # elif STRTOLD_HAS_UNDERFLOW_BUG
      48     /* strtold would not set errno=ERANGE upon underflow.  */
      49  #  define HAVE_UNDERLYING_STRTOD 0
      50  # else
      51  #  define HAVE_UNDERLYING_STRTOD HAVE_STRTOLD
      52  # endif
      53  # define DOUBLE long double
      54  # define MIN LDBL_MIN
      55  # define MAX LDBL_MAX
      56  # define L_(literal) literal##L
      57  #else
      58  # define STRTOD strtod
      59  # define LDEXP ldexp
      60  # define HAVE_UNDERLYING_STRTOD 1
      61  # define DOUBLE double
      62  # define MIN DBL_MIN
      63  # define MAX DBL_MAX
      64  # define L_(literal) literal
      65  #endif
      66  
      67  #if (defined USE_LONG_DOUBLE ? HAVE_LDEXPM_IN_LIBC : HAVE_LDEXP_IN_LIBC)
      68  # define USE_LDEXP 1
      69  #else
      70  # define USE_LDEXP 0
      71  #endif
      72  
      73  /* Return true if C is a space in the current locale, avoiding
      74     problems with signed char and isspace.  */
      75  static bool
      76  locale_isspace (char c)
      77  {
      78    unsigned char uc = c;
      79    return isspace (uc) != 0;
      80  }
      81  
      82  /* Determine the decimal-point character according to the current locale.  */
      83  static char
      84  decimal_point_char (void)
      85  {
      86    const char *point;
      87    /* Determine it in a multithread-safe way.  We know nl_langinfo is
      88       multithread-safe on glibc systems and Mac OS X systems, but is not required
      89       to be multithread-safe by POSIX.  sprintf(), however, is multithread-safe.
      90       localeconv() is rarely multithread-safe.  */
      91  #if HAVE_NL_LANGINFO && (__GLIBC__ || defined __UCLIBC__ || (defined __APPLE__ && defined __MACH__))
      92    point = nl_langinfo (RADIXCHAR);
      93  #elif 1
      94    char pointbuf[5];
      95    sprintf (pointbuf, "%#.0f", 1.0);
      96    point = &pointbuf[1];
      97  #else
      98    point = localeconv () -> decimal_point;
      99  #endif
     100    /* The decimal point is always a single byte: either '.' or ','.  */
     101    return (point[0] != '\0' ? point[0] : '.');
     102  }
     103  
     104  #if !USE_LDEXP
     105   #undef LDEXP
     106   #define LDEXP dummy_ldexp
     107   /* A dummy definition that will never be invoked.  */
     108   static DOUBLE LDEXP (_GL_UNUSED DOUBLE x, _GL_UNUSED int exponent)
     109   {
     110     abort ();
     111     return L_(0.0);
     112   }
     113  #endif
     114  
     115  /* Return X * BASE**EXPONENT.  Return an extreme value and set errno
     116     to ERANGE if underflow or overflow occurs.  */
     117  static DOUBLE
     118  scale_radix_exp (DOUBLE x, int radix, long int exponent)
     119  {
     120    /* If RADIX == 10, this code is neither precise nor fast; it is
     121       merely a straightforward and relatively portable approximation.
     122       If N == 2, this code is precise on a radix-2 implementation,
     123       albeit perhaps not fast if ldexp is not in libc.  */
     124  
     125    long int e = exponent;
     126  
     127    if (USE_LDEXP && radix == 2)
     128      return LDEXP (x, e < INT_MIN ? INT_MIN : INT_MAX < e ? INT_MAX : e);
     129    else
     130      {
     131        DOUBLE r = x;
     132  
     133        if (r != 0)
     134          {
     135            if (e < 0)
     136              {
     137                while (e++ != 0)
     138                  {
     139                    r /= radix;
     140                    if (r == 0 && x != 0)
     141                      {
     142                        errno = ERANGE;
     143                        break;
     144                      }
     145                  }
     146              }
     147            else
     148              {
     149                while (e-- != 0)
     150                  {
     151                    if (r < -MAX / radix)
     152                      {
     153                        errno = ERANGE;
     154                        return -HUGE_VAL;
     155                      }
     156                    else if (MAX / radix < r)
     157                      {
     158                        errno = ERANGE;
     159                        return HUGE_VAL;
     160                      }
     161                    else
     162                      r *= radix;
     163                  }
     164              }
     165          }
     166  
     167        return r;
     168      }
     169  }
     170  
     171  /* Parse a number at NPTR; this is a bit like strtol (NPTR, ENDPTR)
     172     except there are no leading spaces or signs or "0x", and ENDPTR is
     173     nonnull.  The number uses a base BASE (either 10 or 16) fraction, a
     174     radix RADIX (either 10 or 2) exponent, and exponent character
     175     EXPCHAR.  BASE is RADIX**RADIX_MULTIPLIER.  */
     176  static DOUBLE
     177  parse_number (const char *nptr,
     178                int base, int radix, int radix_multiplier, char radixchar,
     179                char expchar,
     180                char **endptr)
     181  {
     182    const char *s = nptr;
     183    const char *digits_start;
     184    const char *digits_end;
     185    const char *radixchar_ptr;
     186    long int exponent;
     187    DOUBLE num;
     188  
     189    /* First, determine the start and end of the digit sequence.  */
     190    digits_start = s;
     191    radixchar_ptr = NULL;
     192    for (;; ++s)
     193      {
     194        if (base == 16 ? c_isxdigit (*s) : c_isdigit (*s))
     195          ;
     196        else if (radixchar_ptr == NULL && *s == radixchar)
     197          {
     198            /* Record that we have found the decimal point.  */
     199            radixchar_ptr = s;
     200          }
     201        else
     202          /* Any other character terminates the digit sequence.  */
     203          break;
     204      }
     205    digits_end = s;
     206    /* Now radixchar_ptr == NULL or
     207       digits_start <= radixchar_ptr < digits_end.  */
     208  
     209    if (false)
     210      { /* Unoptimized.  */
     211        exponent =
     212          (radixchar_ptr != NULL
     213           ? - (long int) (digits_end - radixchar_ptr - 1)
     214           : 0);
     215      }
     216    else
     217      { /* Remove trailing zero digits.  This reduces rounding errors for
     218           inputs such as 1.0000000000 or 10000000000e-10.  */
     219        while (digits_end > digits_start)
     220          {
     221            if (digits_end - 1 == radixchar_ptr || *(digits_end - 1) == '0')
     222              digits_end--;
     223            else
     224              break;
     225          }
     226        exponent =
     227          (radixchar_ptr != NULL
     228           ? (digits_end > radixchar_ptr
     229              ? - (long int) (digits_end - radixchar_ptr - 1)
     230              : (long int) (radixchar_ptr - digits_end))
     231           : (long int) (s - digits_end));
     232      }
     233  
     234    /* Then, convert the digit sequence to a number.  */
     235    {
     236      const char *dp;
     237      num = 0;
     238      for (dp = digits_start; dp < digits_end; dp++)
     239        if (dp != radixchar_ptr)
     240          {
     241            int digit;
     242  
     243            /* Make sure that multiplication by BASE will not overflow.  */
     244            if (!(num <= MAX / base))
     245              {
     246                /* The value of the digit and all subsequent digits don't matter,
     247                   since we have already gotten as many digits as can be
     248                   represented in a 'DOUBLE'.  This doesn't necessarily mean that
     249                   the result will overflow: The exponent may reduce it to within
     250                   range.  */
     251                exponent +=
     252                  (digits_end - dp)
     253                  - (radixchar_ptr >= dp && radixchar_ptr < digits_end ? 1 : 0);
     254                break;
     255              }
     256  
     257            /* Eat the next digit.  */
     258            if (c_isdigit (*dp))
     259              digit = *dp - '0';
     260            else if (base == 16 && c_isxdigit (*dp))
     261              digit = c_tolower (*dp) - ('a' - 10);
     262            else
     263              abort ();
     264            num = num * base + digit;
     265          }
     266    }
     267  
     268    exponent = exponent * radix_multiplier;
     269  
     270    /* Finally, parse the exponent.  */
     271    if (c_tolower (*s) == expchar && ! locale_isspace (s[1]))
     272      {
     273        /* Add any given exponent to the implicit one.  */
     274        int saved_errno = errno;
     275        char *end;
     276        long int value = strtol (s + 1, &end, 10);
     277        errno = saved_errno;
     278  
     279        if (s + 1 != end)
     280          {
     281            /* Skip past the exponent, and add in the implicit exponent,
     282               resulting in an extreme value on overflow.  */
     283            s = end;
     284            exponent =
     285              (exponent < 0
     286               ? (value < LONG_MIN - exponent ? LONG_MIN : exponent + value)
     287               : (LONG_MAX - exponent < value ? LONG_MAX : exponent + value));
     288          }
     289      }
     290  
     291    *endptr = (char *) s;
     292    return scale_radix_exp (num, radix, exponent);
     293  }
     294  
     295  /* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0.
     296     ICC 10.0 has a bug when optimizing the expression -zero.
     297     The expression -MIN * MIN does not work when cross-compiling
     298     to PowerPC on Mac OS X 10.5.  */
     299  static DOUBLE
     300  minus_zero (void)
     301  {
     302  #if defined __hpux || defined __sgi || defined __ICC
     303    return -MIN * MIN;
     304  #else
     305    return -0.0;
     306  #endif
     307  }
     308  
     309  /* Convert NPTR to a DOUBLE.  If ENDPTR is not NULL, a pointer to the
     310     character after the last one used in the number is put in *ENDPTR.  */
     311  DOUBLE
     312  STRTOD (const char *nptr, char **endptr)
     313  #if HAVE_UNDERLYING_STRTOD
     314  # ifdef USE_LONG_DOUBLE
     315  #  undef strtold
     316  # else
     317  #  undef strtod
     318  # endif
     319  #else
     320  # undef STRTOD
     321  # define STRTOD(NPTR,ENDPTR) \
     322     parse_number (NPTR, 10, 10, 1, radixchar, 'e', ENDPTR)
     323  #endif
     324  /* From here on, STRTOD refers to the underlying implementation.  It needs
     325     to handle only finite unsigned decimal numbers with non-null ENDPTR.  */
     326  {
     327    char radixchar;
     328    bool negative = false;
     329  
     330    /* The number so far.  */
     331    DOUBLE num;
     332  
     333    const char *s = nptr;
     334    const char *end;
     335    char *endbuf;
     336    int saved_errno = errno;
     337  
     338    radixchar = decimal_point_char ();
     339  
     340    /* Eat whitespace.  */
     341    while (locale_isspace (*s))
     342      ++s;
     343  
     344    /* Get the sign.  */
     345    negative = *s == '-';
     346    if (*s == '-' || *s == '+')
     347      ++s;
     348  
     349    num = STRTOD (s, &endbuf);
     350    end = endbuf;
     351  
     352    if (c_isdigit (s[*s == radixchar]))
     353      {
     354        /* If a hex float was converted incorrectly, do it ourselves.
     355           If the string starts with "0x" but does not contain digits,
     356           consume the "0" ourselves.  If a hex float is followed by a
     357           'p' but no exponent, then adjust the end pointer.  */
     358        if (*s == '0' && c_tolower (s[1]) == 'x')
     359          {
     360            if (! c_isxdigit (s[2 + (s[2] == radixchar)]))
     361              {
     362                end = s + 1;
     363  
     364                /* strtod() on z/OS returns ERANGE for "0x".  */
     365                errno = saved_errno;
     366              }
     367            else if (end <= s + 2)
     368              {
     369                num = parse_number (s + 2, 16, 2, 4, radixchar, 'p', &endbuf);
     370                end = endbuf;
     371              }
     372            else
     373              {
     374                const char *p = s + 2;
     375                while (p < end && c_tolower (*p) != 'p')
     376                  p++;
     377                if (p < end && ! c_isdigit (p[1 + (p[1] == '-' || p[1] == '+')]))
     378                  {
     379                    char *dup = strdup (s);
     380                    errno = saved_errno;
     381                    if (!dup)
     382                      {
     383                        /* Not really our day, is it.  Rounding errors are
     384                           better than outright failure.  */
     385                        num =
     386                          parse_number (s + 2, 16, 2, 4, radixchar, 'p', &endbuf);
     387                      }
     388                    else
     389                      {
     390                        dup[p - s] = '\0';
     391                        num = STRTOD (dup, &endbuf);
     392                        saved_errno = errno;
     393                        free (dup);
     394                        errno = saved_errno;
     395                      }
     396                    end = p;
     397                  }
     398              }
     399          }
     400        else
     401          {
     402            /* If "1e 1" was misparsed as 10.0 instead of 1.0, re-do the
     403               underlying STRTOD on a copy of the original string
     404               truncated to avoid the bug.  */
     405            const char *e = s + 1;
     406            while (e < end && c_tolower (*e) != 'e')
     407              e++;
     408            if (e < end && ! c_isdigit (e[1 + (e[1] == '-' || e[1] == '+')]))
     409              {
     410                char *dup = strdup (s);
     411                errno = saved_errno;
     412                if (!dup)
     413                  {
     414                    /* Not really our day, is it.  Rounding errors are
     415                       better than outright failure.  */
     416                    num = parse_number (s, 10, 10, 1, radixchar, 'e', &endbuf);
     417                  }
     418                else
     419                  {
     420                    dup[e - s] = '\0';
     421                    num = STRTOD (dup, &endbuf);
     422                    saved_errno = errno;
     423                    free (dup);
     424                    errno = saved_errno;
     425                  }
     426                end = e;
     427              }
     428          }
     429  
     430        s = end;
     431      }
     432  
     433    /* Check for infinities and NaNs.  */
     434    else if (c_tolower (*s) == 'i'
     435             && c_tolower (s[1]) == 'n'
     436             && c_tolower (s[2]) == 'f')
     437      {
     438        s += 3;
     439        if (c_tolower (*s) == 'i'
     440            && c_tolower (s[1]) == 'n'
     441            && c_tolower (s[2]) == 'i'
     442            && c_tolower (s[3]) == 't'
     443            && c_tolower (s[4]) == 'y')
     444          s += 5;
     445        num = HUGE_VAL;
     446        errno = saved_errno;
     447      }
     448    else if (c_tolower (*s) == 'n'
     449             && c_tolower (s[1]) == 'a'
     450             && c_tolower (s[2]) == 'n')
     451      {
     452        s += 3;
     453        if (*s == '(')
     454          {
     455            const char *p = s + 1;
     456            while (c_isalnum (*p))
     457              p++;
     458            if (*p == ')')
     459              s = p + 1;
     460          }
     461  
     462        /* If the underlying implementation misparsed the NaN, assume
     463           its result is incorrect, and return a NaN.  Normally it's
     464           better to use the underlying implementation's result, since a
     465           nice implementation populates the bits of the NaN according
     466           to interpreting n-char-sequence as a hexadecimal number.  */
     467        if (s != end || num == num)
     468          num = NAN;
     469        errno = saved_errno;
     470      }
     471    else
     472      {
     473        /* No conversion could be performed.  */
     474        errno = EINVAL;
     475        s = nptr;
     476      }
     477  
     478    if (endptr != NULL)
     479      *endptr = (char *) s;
     480    /* Special case -0.0, since at least ICC miscompiles negation.  We
     481       can't use copysign(), as that drags in -lm on some platforms.  */
     482    if (!num && negative)
     483      return minus_zero ();
     484    return negative ? -num : num;
     485  }