pike.git / src / stralloc.c

version» Context lines:

pike.git/src/stralloc.c:2601:    free_string(Pike_sp[-1].u.string);    Pike_sp[-1] = r;       return i;   }      /* Convert PCHARP to a double. If ENDPTR is not NULL, a pointer to the    character after the last one used in the number is put in *ENDPTR. */   PMOD_EXPORT double STRTOD_PCHARP(const PCHARP nptr, PCHARP *endptr)   { -  /* Note: Code duplication in strtod. */ +  /* Note: Code duplication in STRTOLD_PCHARP. */    -  PCHARP s; +  PCHARP s, sdigits, sdigitsend;    short int sign;    -  /* The number so far. */ +  /* The number. */    double num;    -  int got_dot; /* Found a decimal point. */ -  int got_digit; /* Seen any digits. */ -  int precision_loss;/* No more digits fit in mantissa */ +  int got_dot; /* Found a decimal point. */ +  size_t got_digits; /* Number of digits seen. */       /* The exponent of the number. */    long int exponent;    -  +  /* Narrow string buffer */ +  char *buf, *p; +  size_t buf_len; +  int free_buf; +     if (nptr.ptr == NULL)    {    errno = EINVAL;    goto noconv;    }       s = nptr;       /* Eat whitespace. */    while (wide_isspace(EXTRACT_PCHARP(s))) INC_PCHARP(s,1);       /* Get the sign. */    sign = EXTRACT_PCHARP(s) == '-' ? -1 : 1;    if (EXTRACT_PCHARP(s) == '-' || EXTRACT_PCHARP(s) == '+')    INC_PCHARP(s,1);    -  num = 0.0; +     got_dot = 0; -  got_digit = 0; +  got_digits = 0;    exponent = 0; -  precision_loss = 0; +  sdigits = s;    for (;; INC_PCHARP(s,1))    {    if (WIDE_ISDIGIT (EXTRACT_PCHARP(s)))    { -  got_digit = 1; +  got_digits ++;    -  /* Make sure that multiplication by 10 will not overflow. */ -  if (precision_loss || num > DBL_MAX * 0.1) -  /* The value of the digit doesn't matter, since we have already -  gotten as many digits as can be represented in a `double'. -  This doesn't necessarily mean the result will overflow. -  The exponent may reduce it to within range. -  -  We just need to record that there was another -  digit so that we can multiply by 10 later. */ -  ++exponent; -  else { -  int v = EXTRACT_PCHARP(s) - '0'; -  num *= 10.0; -  if (v != 0) { -  double check = num; -  num += v; -  if (num == check) -  precision_loss = 1; -  } -  } -  +     /* Keep track of the number of digits after the decimal point.    If we just divided by 10 here, we would lose precision. */    if (got_dot)    --exponent;    }    else if (!got_dot && (char) EXTRACT_PCHARP(s) == '.')    /* Record that we have found the decimal point. */    got_dot = 1;    else    /* Any other character terminates the number. */    break;    }    -  if (!got_digit) +  if (!got_digits)    goto noconv;    -  +  sdigitsend = s; +     if (EXTRACT_PCHARP(s) == 'E' || EXTRACT_PCHARP(s) == 'e')    {    /* Get the exponent specified after the `e' or `E'. */    int save = errno;    PCHARP end;    long int exp;       errno = 0;    INC_PCHARP(s,1);    exp = STRTOL_PCHARP(s, &end, 10);
pike.git/src/stralloc.c:2722:    end = ADD_PCHARP(s,-1);    errno = save;    s = end;    exponent += exp;    }       if(got_dot && INDEX_PCHARP(s,-1)=='.') INC_PCHARP(s,-1);    if (endptr != NULL)    *endptr = s;    -  if (num == 0.0) -  return 0.0; +  /* Allocate enough for all digits, the exponent, the exponent sign, +  the letter 'E' and the trailing NUL */ +  buf_len = got_digits + (3 + (sizeof(exponent) * CHAR_BIT + 2) / 3);    -  /* Multiply NUM by 10 to the EXPONENT power, -  checking for overflow and underflow. */ +  if (buf_len > 100) { +  buf = xalloc(buf_len); +  free_buf = 1; +  } else { +  buf = alloca(buf_len); +  free_buf = 0; +  }    -  if (exponent < 0) +  p = buf; +  for (; COMPARE_PCHARP(sdigits,<,sdigitsend); INC_PCHARP(sdigits,1))    { -  if (num < DBL_MIN * pow(10.0, (double) -exponent)) -  goto underflow; +  char ch = EXTRACT_PCHARP(sdigits); +  if (ch != '.') +  *p++ = ch;    } -  else if (exponent > 0) -  { -  if (num > DBL_MAX * pow(10.0, (double) -exponent)) -  goto overflow; -  } +  sprintf(p, "E%ld", exponent);    -  if(exponent < 0 && exponent >-100) /* make sure we don't underflow */ -  num /= pow(10.0, (double) -exponent); -  else -  num *= pow(10.0, (double) exponent); +  num = strtod(buf, NULL); +  if (free_buf) +  free (buf);       return num * sign;       overflow:    /* Return an overflow error. */    errno = ERANGE;    return HUGE_VAL * sign;       underflow:    /* Return an underflow error. */
pike.git/src/stralloc.c:2768:    if (endptr != NULL)    *endptr = nptr;    return 0.0;   }      #if SIZEOF_FLOAT_TYPE > SIZEOF_DOUBLE   /* Convert PCHARP to a long double. If ENDPTR is not NULL, a pointer to the    character after the last one used in the number is put in *ENDPTR. */   PMOD_EXPORT long double STRTOLD_PCHARP(const PCHARP nptr, PCHARP *endptr)   { -  /* Note: Code duplication in strtod. */ +  /* Note: Code duplication in STRTOD_PCHARP. */    -  PCHARP s; +  PCHARP s, sdigits, sdigitsend;    short int sign;    -  /* The number so far. */ +  /* The number. */    long double num;    -  int got_dot; /* Found a decimal point. */ -  int got_digit; /* Seen any digits. */ -  int precision_loss;/* No more digits fit in mantissa */ +  int got_dot; /* Found a decimal point. */ +  size_t got_digits; /* Number of digits seen. */       /* The exponent of the number. */    long int exponent;    -  +  /* Narrow string buffer */ +  char *buf, *p; +  size_t buf_len; +  int free_buf; +     if (nptr.ptr == NULL)    {    errno = EINVAL;    goto noconv;    }       s = nptr;       /* Eat whitespace. */    while (wide_isspace(EXTRACT_PCHARP(s))) INC_PCHARP(s,1);       /* Get the sign. */    sign = EXTRACT_PCHARP(s) == '-' ? -1 : 1;    if (EXTRACT_PCHARP(s) == '-' || EXTRACT_PCHARP(s) == '+')    INC_PCHARP(s,1);    -  num = 0.0; +     got_dot = 0; -  got_digit = 0; +  got_digits = 0;    exponent = 0; -  precision_loss = 0; +  sdigits = s;    for (;; INC_PCHARP(s,1))    {    if (WIDE_ISDIGIT (EXTRACT_PCHARP(s)))    { -  got_digit = 1; +  got_digits ++;    -  /* Make sure that multiplication by 10 will not overflow. */ -  if (precision_loss || num > LDBL_MAX * 0.1) -  /* The value of the digit doesn't matter, since we have already -  gotten as many digits as can be represented in a `long double'. -  This doesn't necessarily mean the result will overflow. -  The exponent may reduce it to within range. -  -  We just need to record that there was another -  digit so that we can multiply by 10 later. */ -  ++exponent; -  else { -  int v = EXTRACT_PCHARP(s) - '0'; -  num *= 10.0; -  if (v != 0) { -  long double check = num; -  num += v; -  if (num == check) -  precision_loss = 1; -  } -  } -  +     /* Keep track of the number of digits after the decimal point.    If we just divided by 10 here, we would lose precision. */    if (got_dot)    --exponent;    }    else if (!got_dot && (char) EXTRACT_PCHARP(s) == '.')    /* Record that we have found the decimal point. */    got_dot = 1;    else    /* Any other character terminates the number. */    break;    }    -  if (!got_digit) +  if (!got_digits)    goto noconv;    -  +  sdigitsend = s; +     if (EXTRACT_PCHARP(s) == 'E' || EXTRACT_PCHARP(s) == 'e')    {    /* Get the exponent specified after the `e' or `E'. */    int save = errno;    PCHARP end;    long int exp;       errno = 0;    INC_PCHARP(s,1);    exp = STRTOL_PCHARP(s, &end, 10);
pike.git/src/stralloc.c:2889: Inside #if SIZEOF_FLOAT_TYPE > SIZEOF_DOUBLE
   end = ADD_PCHARP(s,-1);    errno = save;    s = end;    exponent += exp;    }       if(got_dot && INDEX_PCHARP(s,-1)=='.') INC_PCHARP(s,-1);    if (endptr != NULL)    *endptr = s;    -  if (num == 0.0) -  return 0.0; +  /* Allocate enough for all digits, the exponent, the exponent sign, +  the letter 'E' and the trailing NUL */ +  buf_len = got_digits + (3 + (sizeof(exponent) * CHAR_BIT + 2) / 3);    -  /* Multiply NUM by 10 to the EXPONENT power, -  checking for overflow and underflow. */ +  if (buf_len > 100) { +  buf = xalloc(buf_len); +  free_buf = 1; +  } else { +  buf = alloca(buf_len); +  free_buf = 0; +  }    -  if (exponent < 0) +  p = buf; +  for (; COMPARE_PCHARP(sdigits,<,sdigitsend); INC_PCHARP(sdigits,1))    { -  if (num < LDBL_MIN * pow(10.0, (double) -exponent)) -  goto underflow; +  char ch = EXTRACT_PCHARP(sdigits); +  if (ch != '.') +  *p++ = ch;    } -  else if (exponent > 0) -  { -  if (num > LDBL_MAX * pow(10.0, (double) -exponent)) -  goto overflow; -  } +  sprintf(p, "E%ld", exponent);    -  if(exponent < 0 && exponent >-100) /* make sure we don't underflow */ -  num /= powl(10.0, (long double) -exponent); -  else -  num *= powl(10.0, (long double) exponent); +  num = strtold(buf, NULL); +  if (free_buf) +  free (buf);       return num * sign;       overflow:    /* Return an overflow error. */    errno = ERANGE;    return HUGE_VALL * sign;       underflow:    /* Return an underflow error. */