OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [newlib-1.10.0/] [newlib/] [libc/] [stdlib/] [ecvtbuf.c] - Diff between revs 1010 and 1765

Only display areas with differences | Details | Blame | View Log

Rev 1010 Rev 1765
/*
/*
FUNCTION
FUNCTION
<<ecvtbuf>>, <<fcvtbuf>>---double or float to string
<<ecvtbuf>>, <<fcvtbuf>>---double or float to string
 
 
INDEX
INDEX
        ecvtbuf
        ecvtbuf
INDEX
INDEX
        fcvtbuf
        fcvtbuf
 
 
ANSI_SYNOPSIS
ANSI_SYNOPSIS
        #include <stdio.h>
        #include <stdio.h>
 
 
        char *ecvtbuf(double <[val]>, int <[chars]>, int *<[decpt]>,
        char *ecvtbuf(double <[val]>, int <[chars]>, int *<[decpt]>,
                       int *<[sgn]>, char *<[buf]>);
                       int *<[sgn]>, char *<[buf]>);
 
 
        char *fcvtbuf(double <[val]>, int <[decimals]>, int *<[decpt]>,
        char *fcvtbuf(double <[val]>, int <[decimals]>, int *<[decpt]>,
                       int *<[sgn]>, char *<[buf]>);
                       int *<[sgn]>, char *<[buf]>);
 
 
TRAD_SYNOPSIS
TRAD_SYNOPSIS
        #include <stdio.h>
        #include <stdio.h>
 
 
        char *ecvtbuf(<[val]>, <[chars]>, <[decpt]>, <[sgn]>, <[buf]>);
        char *ecvtbuf(<[val]>, <[chars]>, <[decpt]>, <[sgn]>, <[buf]>);
        double <[val]>;
        double <[val]>;
        int <[chars]>;
        int <[chars]>;
        int *<[decpt]>;
        int *<[decpt]>;
        int *<[sgn]>;
        int *<[sgn]>;
        char *<[buf]>;
        char *<[buf]>;
 
 
        char *fcvtbuf(<[val]>, <[decimals]>, <[decpt]>, <[sgn]>, <[buf]>);
        char *fcvtbuf(<[val]>, <[decimals]>, <[decpt]>, <[sgn]>, <[buf]>);
        double <[val]>;
        double <[val]>;
        int <[decimals]>;
        int <[decimals]>;
        int *<[decpt]>;
        int *<[decpt]>;
        int *<[sgn]>;
        int *<[sgn]>;
        char *<[buf]>;
        char *<[buf]>;
 
 
DESCRIPTION
DESCRIPTION
        <<ecvtbuf>> and <<fcvtbuf>> produce (null-terminated) strings
        <<ecvtbuf>> and <<fcvtbuf>> produce (null-terminated) strings
        of digits representating the <<double>> number <[val]>.
        of digits representating the <<double>> number <[val]>.
 
 
        The only difference between <<ecvtbuf>> and <<fcvtbuf>> is the
        The only difference between <<ecvtbuf>> and <<fcvtbuf>> is the
        interpretation of the second argument (<[chars]> or
        interpretation of the second argument (<[chars]> or
        <[decimals]>). For <<ecvtbuf>>, the second argument <[chars]>
        <[decimals]>). For <<ecvtbuf>>, the second argument <[chars]>
        specifies the total number of characters to write (which is
        specifies the total number of characters to write (which is
        also the number of significant digits in the formatted string,
        also the number of significant digits in the formatted string,
        since these two functions write only digits). For <<fcvtbuf>>,
        since these two functions write only digits). For <<fcvtbuf>>,
        the second argument <[decimals]> specifies the number of
        the second argument <[decimals]> specifies the number of
        characters to write after the decimal point; all digits for
        characters to write after the decimal point; all digits for
        the integer part of <[val]> are always included.
        the integer part of <[val]> are always included.
 
 
        Since <<ecvtbuf>> and <<fcvtbuf>> write only digits in the
        Since <<ecvtbuf>> and <<fcvtbuf>> write only digits in the
        output string, they record the location of the decimal point
        output string, they record the location of the decimal point
        in <<*<[decpt]>>>, and the sign of the number in <<*<[sgn]>>>.
        in <<*<[decpt]>>>, and the sign of the number in <<*<[sgn]>>>.
        After formatting a number, <<*<[decpt]>>> contains the number
        After formatting a number, <<*<[decpt]>>> contains the number
        of digits to the left of the decimal point.  <<*<[sgn]>>>
        of digits to the left of the decimal point.  <<*<[sgn]>>>
        contains <<0>> if the number is positive, and <<1>> if it is
        contains <<0>> if the number is positive, and <<1>> if it is
        negative.  For both functions, you supply a pointer <[buf]> to
        negative.  For both functions, you supply a pointer <[buf]> to
        an area of memory to hold the converted string.
        an area of memory to hold the converted string.
 
 
RETURNS
RETURNS
        Both functions return a pointer to <[buf]>, the string
        Both functions return a pointer to <[buf]>, the string
        containing a character representation of <[val]>.
        containing a character representation of <[val]>.
 
 
PORTABILITY
PORTABILITY
        Neither function is ANSI C.
        Neither function is ANSI C.
 
 
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
*/
*/
 
 
#include <_ansi.h>
#include <_ansi.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <reent.h>
#include <reent.h>
#include "mprec.h"
#include "mprec.h"
#include "local.h"
#include "local.h"
 
 
static void
static void
_DEFUN (print_f, (ptr, buf, invalue, ndigit, type, dot, mode),
_DEFUN (print_f, (ptr, buf, invalue, ndigit, type, dot, mode),
        struct _reent *ptr _AND
        struct _reent *ptr _AND
        char *buf _AND
        char *buf _AND
        double invalue _AND
        double invalue _AND
        int ndigit _AND
        int ndigit _AND
        char type _AND
        char type _AND
        int dot _AND
        int dot _AND
        int mode)
        int mode)
{
{
  int decpt;
  int decpt;
  int sign;
  int sign;
  char *p, *start, *end;
  char *p, *start, *end;
 
 
  start = p = _dtoa_r (ptr, invalue, mode, ndigit, &decpt, &sign, &end);
  start = p = _dtoa_r (ptr, invalue, mode, ndigit, &decpt, &sign, &end);
 
 
  if (decpt == 9999)
  if (decpt == 9999)
    {
    {
      strcpy (buf, p);
      strcpy (buf, p);
      return;
      return;
    }
    }
  while (*p && decpt > 0)
  while (*p && decpt > 0)
    {
    {
      *buf++ = *p++;
      *buf++ = *p++;
      decpt--;
      decpt--;
    }
    }
  /* Even if not in buffer */
  /* Even if not in buffer */
  while (decpt > 0)
  while (decpt > 0)
    {
    {
      *buf++ = '0';
      *buf++ = '0';
      decpt--;
      decpt--;
    }
    }
 
 
  if (dot || *p)
  if (dot || *p)
    {
    {
      if (p == start)
      if (p == start)
        *buf++ = '0';
        *buf++ = '0';
      *buf++ = '.';
      *buf++ = '.';
      while (decpt < 0 && ndigit > 0)
      while (decpt < 0 && ndigit > 0)
        {
        {
          *buf++ = '0';
          *buf++ = '0';
          decpt++;
          decpt++;
          ndigit--;
          ndigit--;
        }
        }
 
 
      /* Print rest of stuff */
      /* Print rest of stuff */
      while (*p && ndigit > 0)
      while (*p && ndigit > 0)
        {
        {
          *buf++ = *p++;
          *buf++ = *p++;
          ndigit--;
          ndigit--;
        }
        }
      /* And trailing zeros */
      /* And trailing zeros */
      while (ndigit > 0)
      while (ndigit > 0)
        {
        {
          *buf++ = '0';
          *buf++ = '0';
          ndigit--;
          ndigit--;
        }
        }
    }
    }
  *buf++ = 0;
  *buf++ = 0;
}
}
 
 
/* Print number in e format with width chars after.
/* Print number in e format with width chars after.
 
 
   TYPE is one of 'e' or 'E'.  It may also be one of 'g' or 'G' indicating
   TYPE is one of 'e' or 'E'.  It may also be one of 'g' or 'G' indicating
   that _gcvt is calling us and we should remove trailing zeroes.
   that _gcvt is calling us and we should remove trailing zeroes.
 
 
   WIDTH is the number of digits of precision after the decimal point.  */
   WIDTH is the number of digits of precision after the decimal point.  */
 
 
static void
static void
_DEFUN (print_e, (ptr, buf, invalue, width, type, dot),
_DEFUN (print_e, (ptr, buf, invalue, width, type, dot),
        struct _reent *ptr _AND
        struct _reent *ptr _AND
        char *buf _AND
        char *buf _AND
        double invalue _AND
        double invalue _AND
        int width _AND
        int width _AND
        char type _AND
        char type _AND
        int dot)
        int dot)
{
{
  int sign;
  int sign;
  char *end;
  char *end;
  char *p;
  char *p;
  int decpt;
  int decpt;
  int top;
  int top;
  int ndigit = width;
  int ndigit = width;
 
 
  p = _dtoa_r (ptr, invalue, 2, width + 1, &decpt, &sign, &end);
  p = _dtoa_r (ptr, invalue, 2, width + 1, &decpt, &sign, &end);
 
 
  if (decpt == 9999)
  if (decpt == 9999)
    {
    {
      strcpy (buf, p);
      strcpy (buf, p);
      return;
      return;
    }
    }
 
 
  *buf++ = *p++;
  *buf++ = *p++;
  if (dot || ndigit != 0)
  if (dot || ndigit != 0)
    *buf++ = '.';
    *buf++ = '.';
 
 
  while (*p && ndigit > 0)
  while (*p && ndigit > 0)
    {
    {
      *buf++ = *p++;
      *buf++ = *p++;
      ndigit--;
      ndigit--;
    }
    }
 
 
  /* Add trailing zeroes to fill out to ndigits unless this is 'g' format.
  /* Add trailing zeroes to fill out to ndigits unless this is 'g' format.
     Also, convert g/G to e/E.  */
     Also, convert g/G to e/E.  */
 
 
  if (type == 'g')
  if (type == 'g')
    type = 'e';
    type = 'e';
  else if (type == 'G')
  else if (type == 'G')
    type = 'E';
    type = 'E';
  else
  else
    {
    {
      while (ndigit > 0)
      while (ndigit > 0)
        {
        {
          *buf++ = '0';
          *buf++ = '0';
          ndigit--;
          ndigit--;
        }
        }
    }
    }
 
 
  /* Add the exponent.  */
  /* Add the exponent.  */
 
 
  *buf++ = type;
  *buf++ = type;
  decpt--;
  decpt--;
  if (decpt < 0)
  if (decpt < 0)
    {
    {
      *buf++ = '-';
      *buf++ = '-';
      decpt = -decpt;
      decpt = -decpt;
    }
    }
  else
  else
    {
    {
      *buf++ = '+';
      *buf++ = '+';
    }
    }
  if (decpt > 99)
  if (decpt > 99)
    {
    {
      int top = decpt / 100;
      int top = decpt / 100;
      *buf++ = top + '0';
      *buf++ = top + '0';
      decpt -= top * 100;
      decpt -= top * 100;
    }
    }
  top = decpt / 10;
  top = decpt / 10;
  *buf++ = top + '0';
  *buf++ = top + '0';
  decpt -= top * 10;
  decpt -= top * 10;
  *buf++ = decpt + '0';
  *buf++ = decpt + '0';
 
 
  *buf++ = 0;
  *buf++ = 0;
}
}
 
 
#ifndef _REENT_ONLY
#ifndef _REENT_ONLY
 
 
/* Undocumented behaviour: when given NULL as a buffer, return a
/* Undocumented behaviour: when given NULL as a buffer, return a
   pointer to static space in the rent structure.  This is only to
   pointer to static space in the rent structure.  This is only to
   support ecvt and fcvt, which aren't ANSI anyway.  */
   support ecvt and fcvt, which aren't ANSI anyway.  */
 
 
char *
char *
_DEFUN (fcvtbuf, (invalue, ndigit, decpt, sign, fcvt_buf),
_DEFUN (fcvtbuf, (invalue, ndigit, decpt, sign, fcvt_buf),
        double invalue _AND
        double invalue _AND
        int ndigit _AND
        int ndigit _AND
        int *decpt _AND
        int *decpt _AND
        int *sign _AND
        int *sign _AND
        char *fcvt_buf)
        char *fcvt_buf)
{
{
  char *save;
  char *save;
  char *p;
  char *p;
  char *end;
  char *end;
  int done = 0;
  int done = 0;
 
 
  if (fcvt_buf == NULL)
  if (fcvt_buf == NULL)
    {
    {
      if (_REENT->_cvtlen <= ndigit + 35)
      if (_REENT->_cvtlen <= ndigit + 35)
        {
        {
          if ((fcvt_buf = (char *) _realloc_r (_REENT, _REENT->_cvtbuf,
          if ((fcvt_buf = (char *) _realloc_r (_REENT, _REENT->_cvtbuf,
                                               ndigit + 36)) == NULL)
                                               ndigit + 36)) == NULL)
            return NULL;
            return NULL;
          _REENT->_cvtlen = ndigit + 36;
          _REENT->_cvtlen = ndigit + 36;
          _REENT->_cvtbuf = fcvt_buf;
          _REENT->_cvtbuf = fcvt_buf;
        }
        }
 
 
      fcvt_buf = _REENT->_cvtbuf ;
      fcvt_buf = _REENT->_cvtbuf ;
    }
    }
 
 
  save = fcvt_buf;
  save = fcvt_buf;
 
 
  if (invalue < 1.0 && invalue > -1.0)
  if (invalue < 1.0 && invalue > -1.0)
    {
    {
      p = _dtoa_r (_REENT, invalue, 2, ndigit, decpt, sign, &end);
      p = _dtoa_r (_REENT, invalue, 2, ndigit, decpt, sign, &end);
    }
    }
  else
  else
    {
    {
      p = _dtoa_r (_REENT, invalue, 3, ndigit, decpt, sign, &end);
      p = _dtoa_r (_REENT, invalue, 3, ndigit, decpt, sign, &end);
    }
    }
 
 
  /* Now copy */
  /* Now copy */
 
 
  done = -*decpt;
  done = -*decpt;
  while (p < end)
  while (p < end)
    {
    {
      *fcvt_buf++ = *p++;
      *fcvt_buf++ = *p++;
      done++;
      done++;
    }
    }
  /* And unsuppress the trailing zeroes */
  /* And unsuppress the trailing zeroes */
  while (done < ndigit)
  while (done < ndigit)
    {
    {
      *fcvt_buf++ = '0';
      *fcvt_buf++ = '0';
      done++;
      done++;
    }
    }
  *fcvt_buf++ = 0;
  *fcvt_buf++ = 0;
  return save;
  return save;
}
}
 
 
char *
char *
_DEFUN (ecvtbuf, (invalue, ndigit, decpt, sign, fcvt_buf),
_DEFUN (ecvtbuf, (invalue, ndigit, decpt, sign, fcvt_buf),
        double invalue _AND
        double invalue _AND
        int ndigit _AND
        int ndigit _AND
        int *decpt _AND
        int *decpt _AND
        int *sign _AND
        int *sign _AND
        char *fcvt_buf)
        char *fcvt_buf)
{
{
  char *save;
  char *save;
  char *p;
  char *p;
  char *end;
  char *end;
  int done = 0;
  int done = 0;
 
 
  if (fcvt_buf == NULL)
  if (fcvt_buf == NULL)
    {
    {
      if (_REENT->_cvtlen <= ndigit)
      if (_REENT->_cvtlen <= ndigit)
        {
        {
          if ((fcvt_buf = (char *) _realloc_r (_REENT, _REENT->_cvtbuf,
          if ((fcvt_buf = (char *) _realloc_r (_REENT, _REENT->_cvtbuf,
                                               ndigit + 1)) == NULL)
                                               ndigit + 1)) == NULL)
            return NULL;
            return NULL;
          _REENT->_cvtlen = ndigit + 1;
          _REENT->_cvtlen = ndigit + 1;
          _REENT->_cvtbuf = fcvt_buf;
          _REENT->_cvtbuf = fcvt_buf;
        }
        }
 
 
      fcvt_buf = _REENT->_cvtbuf ;
      fcvt_buf = _REENT->_cvtbuf ;
    }
    }
 
 
  save = fcvt_buf;
  save = fcvt_buf;
 
 
  p = _dtoa_r (_REENT, invalue, 2, ndigit, decpt, sign, &end);
  p = _dtoa_r (_REENT, invalue, 2, ndigit, decpt, sign, &end);
 
 
  /* Now copy */
  /* Now copy */
 
 
  while (p < end)
  while (p < end)
    {
    {
      *fcvt_buf++ = *p++;
      *fcvt_buf++ = *p++;
      done++;
      done++;
    }
    }
  /* And unsuppress the trailing zeroes */
  /* And unsuppress the trailing zeroes */
  while (done < ndigit)
  while (done < ndigit)
    {
    {
      *fcvt_buf++ = '0';
      *fcvt_buf++ = '0';
      done++;
      done++;
    }
    }
  *fcvt_buf++ = 0;
  *fcvt_buf++ = 0;
  return save;
  return save;
}
}
 
 
#endif
#endif
 
 
char *
char *
_DEFUN (_gcvt, (ptr, invalue, ndigit, buf, type, dot),
_DEFUN (_gcvt, (ptr, invalue, ndigit, buf, type, dot),
        struct _reent *ptr _AND
        struct _reent *ptr _AND
        double invalue _AND
        double invalue _AND
        int ndigit _AND
        int ndigit _AND
        char *buf _AND
        char *buf _AND
        char type _AND
        char type _AND
        int dot)
        int dot)
{
{
  char *save = buf;
  char *save = buf;
 
 
  if (invalue < 0)
  if (invalue < 0)
    {
    {
      invalue = -invalue;
      invalue = -invalue;
    }
    }
 
 
  if (invalue == 0)
  if (invalue == 0)
    {
    {
      *buf++ = '0';
      *buf++ = '0';
      *buf = '\0';
      *buf = '\0';
    }
    }
  else
  else
    /* Which one to print ?
    /* Which one to print ?
       ANSI says that anything with more that 4 zeros after the . or more
       ANSI says that anything with more that 4 zeros after the . or more
       than precision digits before is printed in e with the qualification
       than precision digits before is printed in e with the qualification
       that trailing zeroes are removed from the fraction portion.  */
       that trailing zeroes are removed from the fraction portion.  */
 
 
  if (0.0001 >= invalue || invalue >= _mprec_log10 (ndigit))
  if (0.0001 >= invalue || invalue >= _mprec_log10 (ndigit))
    {
    {
      /* We subtract 1 from ndigit because in the 'e' format the precision is
      /* We subtract 1 from ndigit because in the 'e' format the precision is
         the number of digits after the . but in 'g' format it is the number
         the number of digits after the . but in 'g' format it is the number
         of significant digits.
         of significant digits.
 
 
         We defer changing type to e/E so that print_e() can know it's us
         We defer changing type to e/E so that print_e() can know it's us
         calling and thus should remove trailing zeroes.  */
         calling and thus should remove trailing zeroes.  */
 
 
      print_e (ptr, buf, invalue, ndigit - 1, type, dot);
      print_e (ptr, buf, invalue, ndigit - 1, type, dot);
    }
    }
  else
  else
    {
    {
      int decpt;
      int decpt;
      int sign;
      int sign;
      char *end;
      char *end;
      char *p;
      char *p;
 
 
      if (invalue < 1.0)
      if (invalue < 1.0)
        {
        {
          /* what we want is ndigits after the point */
          /* what we want is ndigits after the point */
          p = _dtoa_r (ptr, invalue, 3, ndigit, &decpt, &sign, &end);
          p = _dtoa_r (ptr, invalue, 3, ndigit, &decpt, &sign, &end);
        }
        }
      else
      else
        {
        {
          p = _dtoa_r (ptr, invalue, 2, ndigit, &decpt, &sign, &end);
          p = _dtoa_r (ptr, invalue, 2, ndigit, &decpt, &sign, &end);
        }
        }
 
 
      if (decpt == 9999)
      if (decpt == 9999)
        {
        {
          strcpy (buf, p);
          strcpy (buf, p);
          return save;
          return save;
        }
        }
      while (*p && decpt > 0)
      while (*p && decpt > 0)
        {
        {
          *buf++ = *p++;
          *buf++ = *p++;
          decpt--;
          decpt--;
          ndigit--;
          ndigit--;
        }
        }
      /* Even if not in buffer */
      /* Even if not in buffer */
      while (decpt > 0 && ndigit > 0)
      while (decpt > 0 && ndigit > 0)
        {
        {
          *buf++ = '0';
          *buf++ = '0';
          decpt--;
          decpt--;
          ndigit--;
          ndigit--;
        }
        }
 
 
      if (dot || *p)
      if (dot || *p)
        {
        {
          if (buf == save)
          if (buf == save)
            *buf++ = '0';
            *buf++ = '0';
          *buf++ = '.';
          *buf++ = '.';
          while (decpt < 0 && ndigit > 0)
          while (decpt < 0 && ndigit > 0)
            {
            {
              *buf++ = '0';
              *buf++ = '0';
              decpt++;
              decpt++;
              ndigit--;
              ndigit--;
            }
            }
 
 
          /* Print rest of stuff */
          /* Print rest of stuff */
          while (*p && ndigit > 0)
          while (*p && ndigit > 0)
            {
            {
              *buf++ = *p++;
              *buf++ = *p++;
              ndigit--;
              ndigit--;
            }
            }
          /* And trailing zeros */
          /* And trailing zeros */
          if (dot)
          if (dot)
            {
            {
              while (ndigit > 0)
              while (ndigit > 0)
                {
                {
                  *buf++ = '0';
                  *buf++ = '0';
                  ndigit--;
                  ndigit--;
                }
                }
            }
            }
        }
        }
      *buf++ = 0;
      *buf++ = 0;
    }
    }
 
 
  return save;
  return save;
}
}
 
 
char *
char *
_DEFUN (_dcvt, (ptr, buffer, invalue, precision, width, type, dot),
_DEFUN (_dcvt, (ptr, buffer, invalue, precision, width, type, dot),
        struct _reent *ptr _AND
        struct _reent *ptr _AND
        char *buffer _AND
        char *buffer _AND
        double invalue _AND
        double invalue _AND
        int precision _AND
        int precision _AND
        int width _AND
        int width _AND
        char type _AND
        char type _AND
        int dot)
        int dot)
{
{
  switch (type)
  switch (type)
    {
    {
    case 'f':
    case 'f':
    case 'F':
    case 'F':
      print_f (ptr, buffer, invalue, precision, type, precision == 0 ? dot : 1, 3);
      print_f (ptr, buffer, invalue, precision, type, precision == 0 ? dot : 1, 3);
      break;
      break;
    case 'g':
    case 'g':
    case 'G':
    case 'G':
      if (precision == 0)
      if (precision == 0)
        precision = 1;
        precision = 1;
      _gcvt (ptr, invalue, precision, buffer, type, dot);
      _gcvt (ptr, invalue, precision, buffer, type, dot);
      break;
      break;
    case 'e':
    case 'e':
    case 'E':
    case 'E':
      print_e (ptr, buffer, invalue, precision, type, dot);
      print_e (ptr, buffer, invalue, precision, type, dot);
    }
    }
  return buffer;
  return buffer;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.