strtod.c revision 104834
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
1733965Sjdpthe Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
4333965Sjdpextern double atof ();
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
5033965Sjdpstrtod (str, ptr)
5133965Sjdp     char *str;
5233965Sjdp     char **ptr;
5333965Sjdp{
5433965Sjdp  char *p;
5533965Sjdp
5633965Sjdp  if (ptr == (char **)0)
5733965Sjdp    return atof (str);
5833965Sjdp
5933965Sjdp  p = str;
6033965Sjdp
6177298Sobrien  while (ISSPACE (*p))
6233965Sjdp    ++p;
6333965Sjdp
6433965Sjdp  if (*p == '+' || *p == '-')
6533965Sjdp    ++p;
6633965Sjdp
6733965Sjdp  /* INF or INFINITY.  */
6833965Sjdp  if ((p[0] == 'i' || p[0] == 'I')
6933965Sjdp      && (p[1] == 'n' || p[1] == 'N')
7033965Sjdp      && (p[2] == 'f' || p[2] == 'F'))
7133965Sjdp    {
7233965Sjdp      if ((p[3] == 'i' || p[3] == 'I')
7333965Sjdp	  && (p[4] == 'n' || p[4] == 'N')
7433965Sjdp	  && (p[5] == 'i' || p[5] == 'I')
7533965Sjdp	  && (p[6] == 't' || p[6] == 'T')
7633965Sjdp	  && (p[7] == 'y' || p[7] == 'Y'))
7733965Sjdp	{
78104834Sobrien	  *ptr = p + 8;
7933965Sjdp	  return atof (str);
8033965Sjdp	}
8133965Sjdp      else
8233965Sjdp	{
8333965Sjdp	  *ptr = p + 3;
8433965Sjdp	  return atof (str);
8533965Sjdp	}
8633965Sjdp    }
8733965Sjdp
8833965Sjdp  /* NAN or NAN(foo).  */
8933965Sjdp  if ((p[0] == 'n' || p[0] == 'N')
9033965Sjdp      && (p[1] == 'a' || p[1] == 'A')
9133965Sjdp      && (p[2] == 'n' || p[2] == 'N'))
9233965Sjdp    {
9333965Sjdp      p += 3;
9433965Sjdp      if (*p == '(')
9533965Sjdp	{
9633965Sjdp	  ++p;
9733965Sjdp	  while (*p != '\0' && *p != ')')
9833965Sjdp	    ++p;
9933965Sjdp	  if (*p == ')')
10033965Sjdp	    ++p;
10133965Sjdp	}
10233965Sjdp      *ptr = p;
10333965Sjdp      return atof (str);
10433965Sjdp    }
10533965Sjdp
10633965Sjdp  /* digits, with 0 or 1 periods in it.  */
10777298Sobrien  if (ISDIGIT (*p) || *p == '.')
10833965Sjdp    {
10933965Sjdp      int got_dot = 0;
11077298Sobrien      while (ISDIGIT (*p) || (!got_dot && *p == '.'))
11133965Sjdp	{
11233965Sjdp	  if (*p == '.')
11333965Sjdp	    got_dot = 1;
11433965Sjdp	  ++p;
11533965Sjdp	}
11633965Sjdp
11733965Sjdp      /* Exponent.  */
11833965Sjdp      if (*p == 'e' || *p == 'E')
11933965Sjdp	{
12033965Sjdp	  int i;
12133965Sjdp	  i = 1;
12233965Sjdp	  if (p[i] == '+' || p[i] == '-')
12333965Sjdp	    ++i;
12477298Sobrien	  if (ISDIGIT (p[i]))
12533965Sjdp	    {
12677298Sobrien	      while (ISDIGIT (p[i]))
12733965Sjdp		++i;
12833965Sjdp	      *ptr = p + i;
12933965Sjdp	      return atof (str);
13033965Sjdp	    }
13133965Sjdp	}
13233965Sjdp      *ptr = p;
13333965Sjdp      return atof (str);
13433965Sjdp    }
13533965Sjdp  /* Didn't find any digits.  Doesn't look like a number.  */
13633965Sjdp  *ptr = str;
13733965Sjdp  return 0.0;
13833965Sjdp}
139