Listing 4 (xstod.c)

/* _Stod function */
#include <ctype.h>
#include <float.h>
#include <limits.h>
#include <locale.h>
#include <stdlib.h>
#include "xmath.h"

#define SIG_MAX 32

double _Stod(const char *s, char **endptr)
   {  /* convert string to double, with checking */
   const char point = localeconv()->decimal_point[0];
   const char *sc;
   char buf[SIG_MAX], sign;
   double x;
   int ndigit, nsig, nzero, olead, opoint;

   for (sc = s; isspace(*sc); ++sc)
      ;
   sign = *sc == '-' || *sc =='+' ? *sc++ : '+';
   olead = -1, opoint = -1;
   for (ndigit = 0, nsig = 0, nzero= 0; ; ++sc)
      if (*sc == point)
         if (0 <= opoint)
            break; /* already seen point */
         else
            opoint = ndigit;
      else if (*sc == '0')
         ++nzero, ++ndigit;
      else if (!isdigit(*sc))
         break;
      else
         {   /* got a nonzero digit */
         if (olead < 0)
            olead = nzero;
         else   /* deliver zeros */
            for (; 0 < nzero && nsig < SIG_MAX; -nzero)
               buf[nsig++] = 0;
         ++ndigit;
         if (nsig < SIG_MAX)  /* deliver digit */
            buf[nsig++] = *sc- '0';
         }
   if (ndigit == 0)
      {  /* set endptr */
      if (endptr)
         *endptr = (char *)s;
      return (0.0);
      }
   for (; 0 < nsig && buf[nsig - 1] == 0; -nsig)
      ;  /* skip trailing digits */
   {  /* compute significand */
   const char *pc = buf;
   int n;
   long lo[SIG_MAX/8+1];
   long *pl = &lo[nsig >> 3];
   static double fac[] = {0, 1e8, 1e16, 1e24, 1e32};

   for (*pl = 0, n = nsig; 0 < n; -n)
      if ((n & 07) == 0)   /* start new sum */
         *-pl = *pc++;
      else
         *pl = *pl * 10 + *pc++;
   for (x = (double)lo[0], n = 0; ++n <= (nsig >> 3); )
      if (lo[n] != 0)
         x += fac[n] * (double)lo[n];
    }
    {  /* fold in any explicit exponent */
   long lexp = 0;
   short sexp;

   if (*sc == 'e' || *sc == 'E')
      {  /* parse exponent */
      const char *scsav = sc;
      const char esign = *++sc == '+' || *sc == '-'
         ? *sc++ : '+';

      if (!isdigit(*sc))
         sc = scsav;   /* ill-formed exponent */
      else
         {  /* exponent looks valid */
         for (; isdigit(*sc); ++sc)
            if (lexp < 100000)   /* else overflow */
               lexp = lexp * 10 + *sc - '0';
         if (esign == '-')
            lexp = -lexp;
         }
      }
   if (endptr)
      *endptr = (char *)sc;
   if (opoint < 0)
      lexp += ndigit - nsig;
   else
      lexp += opoint - olead - nsig;
   sexp = lexp < SHRT_MIN ? SHRT_MIN : lexp < SHRT_MAX
      ? (short)lexp : SHRT_MAX;
   x = _Dtento(x, sexp);
   return (sign == '-' ? -x : x);
    }
   }

/* End of File */