xref: /openbsd-src/gnu/lib/libiberty/src/strtod.c (revision 150b7e42cfa21e6546d96ae514ca23e80d970ac7)
100bf4279Sespie /* Implementation of strtod for systems with atof.
237c53322Sespie    Copyright (C) 1991, 1995, 2002 Free Software Foundation, Inc.
300bf4279Sespie 
400bf4279Sespie This file is part of the libiberty library.  This library is free
500bf4279Sespie software; you can redistribute it and/or modify it under the
600bf4279Sespie terms of the GNU General Public License as published by the
700bf4279Sespie Free Software Foundation; either version 2, or (at your option)
800bf4279Sespie any later version.
900bf4279Sespie 
1000bf4279Sespie This library is distributed in the hope that it will be useful,
1100bf4279Sespie but WITHOUT ANY WARRANTY; without even the implied warranty of
1200bf4279Sespie MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1300bf4279Sespie GNU General Public License for more details.
1400bf4279Sespie 
1500bf4279Sespie You should have received a copy of the GNU General Public License
1600bf4279Sespie along with GNU CC; see the file COPYING.  If not, write to
17*150b7e42Smiod the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
1800bf4279Sespie 
1900bf4279Sespie As a special exception, if you link this library with files
2000bf4279Sespie compiled with a GNU compiler to produce an executable, this does not cause
2100bf4279Sespie the resulting executable to be covered by the GNU General Public License.
2200bf4279Sespie This exception does not however invalidate any other reasons why
2300bf4279Sespie the executable file might be covered by the GNU General Public License. */
2400bf4279Sespie 
2537c53322Sespie /*
2637c53322Sespie 
2737c53322Sespie @deftypefn Supplemental double strtod (const char *@var{string}, char **@var{endptr})
2837c53322Sespie 
2937c53322Sespie This ISO C function converts the initial portion of @var{string} to a
3037c53322Sespie @code{double}.  If @var{endptr} is not @code{NULL}, a pointer to the
3137c53322Sespie character after the last character used in the conversion is stored in
3237c53322Sespie the location referenced by @var{endptr}.  If no conversion is
3337c53322Sespie performed, zero is returned and the value of @var{string} is stored in
3437c53322Sespie the location referenced by @var{endptr}.
3537c53322Sespie 
3637c53322Sespie @end deftypefn
3737c53322Sespie 
3837c53322Sespie */
3937c53322Sespie 
4037c53322Sespie #include "ansidecl.h"
4137c53322Sespie #include "safe-ctype.h"
4200bf4279Sespie 
43*150b7e42Smiod extern double atof (const char *);
4400bf4279Sespie 
4500bf4279Sespie /* Disclaimer: this is currently just used by CHILL in GDB and therefore
4600bf4279Sespie    has not been tested well.  It may have been tested for nothing except
4700bf4279Sespie    that it compiles.  */
4800bf4279Sespie 
4900bf4279Sespie double
strtod(char * str,char ** ptr)50*150b7e42Smiod strtod (char *str, char **ptr)
5100bf4279Sespie {
5200bf4279Sespie   char *p;
5300bf4279Sespie 
5400bf4279Sespie   if (ptr == (char **)0)
5500bf4279Sespie     return atof (str);
5600bf4279Sespie 
5700bf4279Sespie   p = str;
5800bf4279Sespie 
5937c53322Sespie   while (ISSPACE (*p))
6000bf4279Sespie     ++p;
6100bf4279Sespie 
6200bf4279Sespie   if (*p == '+' || *p == '-')
6300bf4279Sespie     ++p;
6400bf4279Sespie 
6500bf4279Sespie   /* INF or INFINITY.  */
6600bf4279Sespie   if ((p[0] == 'i' || p[0] == 'I')
6700bf4279Sespie       && (p[1] == 'n' || p[1] == 'N')
6800bf4279Sespie       && (p[2] == 'f' || p[2] == 'F'))
6900bf4279Sespie     {
7000bf4279Sespie       if ((p[3] == 'i' || p[3] == 'I')
7100bf4279Sespie 	  && (p[4] == 'n' || p[4] == 'N')
7200bf4279Sespie 	  && (p[5] == 'i' || p[5] == 'I')
7300bf4279Sespie 	  && (p[6] == 't' || p[6] == 'T')
7400bf4279Sespie 	  && (p[7] == 'y' || p[7] == 'Y'))
7500bf4279Sespie 	{
7637c53322Sespie 	  *ptr = p + 8;
7700bf4279Sespie 	  return atof (str);
7800bf4279Sespie 	}
7900bf4279Sespie       else
8000bf4279Sespie 	{
8100bf4279Sespie 	  *ptr = p + 3;
8200bf4279Sespie 	  return atof (str);
8300bf4279Sespie 	}
8400bf4279Sespie     }
8500bf4279Sespie 
8600bf4279Sespie   /* NAN or NAN(foo).  */
8700bf4279Sespie   if ((p[0] == 'n' || p[0] == 'N')
8800bf4279Sespie       && (p[1] == 'a' || p[1] == 'A')
8900bf4279Sespie       && (p[2] == 'n' || p[2] == 'N'))
9000bf4279Sespie     {
9100bf4279Sespie       p += 3;
9200bf4279Sespie       if (*p == '(')
9300bf4279Sespie 	{
9400bf4279Sespie 	  ++p;
9500bf4279Sespie 	  while (*p != '\0' && *p != ')')
9600bf4279Sespie 	    ++p;
9700bf4279Sespie 	  if (*p == ')')
9800bf4279Sespie 	    ++p;
9900bf4279Sespie 	}
10000bf4279Sespie       *ptr = p;
10100bf4279Sespie       return atof (str);
10200bf4279Sespie     }
10300bf4279Sespie 
10400bf4279Sespie   /* digits, with 0 or 1 periods in it.  */
10537c53322Sespie   if (ISDIGIT (*p) || *p == '.')
10600bf4279Sespie     {
10700bf4279Sespie       int got_dot = 0;
10837c53322Sespie       while (ISDIGIT (*p) || (!got_dot && *p == '.'))
10900bf4279Sespie 	{
11000bf4279Sespie 	  if (*p == '.')
11100bf4279Sespie 	    got_dot = 1;
11200bf4279Sespie 	  ++p;
11300bf4279Sespie 	}
11400bf4279Sespie 
11500bf4279Sespie       /* Exponent.  */
11600bf4279Sespie       if (*p == 'e' || *p == 'E')
11700bf4279Sespie 	{
11800bf4279Sespie 	  int i;
11900bf4279Sespie 	  i = 1;
12000bf4279Sespie 	  if (p[i] == '+' || p[i] == '-')
12100bf4279Sespie 	    ++i;
12237c53322Sespie 	  if (ISDIGIT (p[i]))
12300bf4279Sespie 	    {
12437c53322Sespie 	      while (ISDIGIT (p[i]))
12500bf4279Sespie 		++i;
12600bf4279Sespie 	      *ptr = p + i;
12700bf4279Sespie 	      return atof (str);
12800bf4279Sespie 	    }
12900bf4279Sespie 	}
13000bf4279Sespie       *ptr = p;
13100bf4279Sespie       return atof (str);
13200bf4279Sespie     }
13300bf4279Sespie   /* Didn't find any digits.  Doesn't look like a number.  */
13400bf4279Sespie   *ptr = str;
13500bf4279Sespie   return 0.0;
13600bf4279Sespie }
137