133965Sjdp/* Implementation of strtod for systems with atof.
2104834Sobrien   Copyright (C) 1991, 1995, 2002 Free Software Foundation, Inc.
333965Sjdp
433965SjdpThis file is part of the libiberty library.  This library is free
533965Sjdpsoftware; you can redistribute it and/or modify it under the
633965Sjdpterms of the GNU General Public License as published by the
733965SjdpFree Software Foundation; either version 2, or (at your option)
833965Sjdpany later version.
933965Sjdp
1033965SjdpThis library is distributed in the hope that it will be useful,
1133965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of
1233965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1333965SjdpGNU General Public License for more details.
1433965Sjdp
1533965SjdpYou should have received a copy of the GNU General Public License
1633965Sjdpalong with GNU CC; see the file COPYING.  If not, write to
17218822Sdimthe Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
1833965Sjdp
1933965SjdpAs a special exception, if you link this library with files
2033965Sjdpcompiled with a GNU compiler to produce an executable, this does not cause
2133965Sjdpthe resulting executable to be covered by the GNU General Public License.
2233965SjdpThis exception does not however invalidate any other reasons why
2333965Sjdpthe executable file might be covered by the GNU General Public License. */
2433965Sjdp
2589857Sobrien/*
2689857Sobrien
2789857Sobrien@deftypefn Supplemental double strtod (const char *@var{string}, char **@var{endptr})
2889857Sobrien
2989857SobrienThis ISO C function converts the initial portion of @var{string} to a
3089857Sobrien@code{double}.  If @var{endptr} is not @code{NULL}, a pointer to the
3189857Sobriencharacter after the last character used in the conversion is stored in
3289857Sobrienthe location referenced by @var{endptr}.  If no conversion is
3389857Sobrienperformed, zero is returned and the value of @var{string} is stored in
3489857Sobrienthe location referenced by @var{endptr}.
3589857Sobrien
3689857Sobrien@end deftypefn
3789857Sobrien
3889857Sobrien*/
3989857Sobrien
4077298Sobrien#include "ansidecl.h"
4177298Sobrien#include "safe-ctype.h"
4233965Sjdp
43218822Sdimextern double atof (const char *);
4433965Sjdp
4533965Sjdp/* Disclaimer: this is currently just used by CHILL in GDB and therefore
4633965Sjdp   has not been tested well.  It may have been tested for nothing except
4733965Sjdp   that it compiles.  */
4833965Sjdp
4933965Sjdpdouble
50218822Sdimstrtod (char *str, char **ptr)
5133965Sjdp{
5233965Sjdp  char *p;
5333965Sjdp
5433965Sjdp  if (ptr == (char **)0)
5533965Sjdp    return atof (str);
5633965Sjdp
5733965Sjdp  p = str;
5833965Sjdp
5977298Sobrien  while (ISSPACE (*p))
6033965Sjdp    ++p;
6133965Sjdp
6233965Sjdp  if (*p == '+' || *p == '-')
6333965Sjdp    ++p;
6433965Sjdp
6533965Sjdp  /* INF or INFINITY.  */
6633965Sjdp  if ((p[0] == 'i' || p[0] == 'I')
6733965Sjdp      && (p[1] == 'n' || p[1] == 'N')
6833965Sjdp      && (p[2] == 'f' || p[2] == 'F'))
6933965Sjdp    {
7033965Sjdp      if ((p[3] == 'i' || p[3] == 'I')
7133965Sjdp	  && (p[4] == 'n' || p[4] == 'N')
7233965Sjdp	  && (p[5] == 'i' || p[5] == 'I')
7333965Sjdp	  && (p[6] == 't' || p[6] == 'T')
7433965Sjdp	  && (p[7] == 'y' || p[7] == 'Y'))
7533965Sjdp	{
76104834Sobrien	  *ptr = p + 8;
7733965Sjdp	  return atof (str);
7833965Sjdp	}
7933965Sjdp      else
8033965Sjdp	{
8133965Sjdp	  *ptr = p + 3;
8233965Sjdp	  return atof (str);
8333965Sjdp	}
8433965Sjdp    }
8533965Sjdp
8633965Sjdp  /* NAN or NAN(foo).  */
8733965Sjdp  if ((p[0] == 'n' || p[0] == 'N')
8833965Sjdp      && (p[1] == 'a' || p[1] == 'A')
8933965Sjdp      && (p[2] == 'n' || p[2] == 'N'))
9033965Sjdp    {
9133965Sjdp      p += 3;
9233965Sjdp      if (*p == '(')
9333965Sjdp	{
9433965Sjdp	  ++p;
9533965Sjdp	  while (*p != '\0' && *p != ')')
9633965Sjdp	    ++p;
9733965Sjdp	  if (*p == ')')
9833965Sjdp	    ++p;
9933965Sjdp	}
10033965Sjdp      *ptr = p;
10133965Sjdp      return atof (str);
10233965Sjdp    }
10333965Sjdp
10433965Sjdp  /* digits, with 0 or 1 periods in it.  */
10577298Sobrien  if (ISDIGIT (*p) || *p == '.')
10633965Sjdp    {
10733965Sjdp      int got_dot = 0;
10877298Sobrien      while (ISDIGIT (*p) || (!got_dot && *p == '.'))
10933965Sjdp	{
11033965Sjdp	  if (*p == '.')
11133965Sjdp	    got_dot = 1;
11233965Sjdp	  ++p;
11333965Sjdp	}
11433965Sjdp
11533965Sjdp      /* Exponent.  */
11633965Sjdp      if (*p == 'e' || *p == 'E')
11733965Sjdp	{
11833965Sjdp	  int i;
11933965Sjdp	  i = 1;
12033965Sjdp	  if (p[i] == '+' || p[i] == '-')
12133965Sjdp	    ++i;
12277298Sobrien	  if (ISDIGIT (p[i]))
12333965Sjdp	    {
12477298Sobrien	      while (ISDIGIT (p[i]))
12533965Sjdp		++i;
12633965Sjdp	      *ptr = p + i;
12733965Sjdp	      return atof (str);
12833965Sjdp	    }
12933965Sjdp	}
13033965Sjdp      *ptr = p;
13133965Sjdp      return atof (str);
13233965Sjdp    }
13333965Sjdp  /* Didn't find any digits.  Doesn't look like a number.  */
13433965Sjdp  *ptr = str;
13533965Sjdp  return 0.0;
13633965Sjdp}
137