home *** CD-ROM | disk | FTP | other *** search
/ linuxmafia.com 2016 / linuxmafia.com.tar / linuxmafia.com / pub / linux / backup / star-1.3.1.tar.gz / star-1.3.1.tar / star-1.3.1 / lib / cvt.c < prev    next >
C/C++ Source or Header  |  2001-02-23  |  5KB  |  242 lines

  1. /* @(#)cvt.c    1.4 01/02/23 Copyright 1998 J. Schilling */
  2. /*
  3.  *    Compatibility routines for 4.4BSD based C-libraries ecvt()/fcvt()
  4.  *    and a working gcvt() that is needed on 4.4BSD and GNU libc systems.
  5.  *
  6.  *    On 4.4BSD, gcvt() is missing, the gcvt() implementation from GNU libc
  7.  *    is not working correctly.
  8.  *
  9.  *    Neither __dtoa() nor [efg]cvt() are MT safe.
  10.  *
  11.  *    Copyright (c) 1998 J. Schilling
  12.  */
  13. /*
  14.  * This program is free software; you can redistribute it and/or modify
  15.  * it under the terms of the GNU General Public License as published by
  16.  * the Free Software Foundation; either version 2, or (at your option)
  17.  * any later version.
  18.  *
  19.  * This program is distributed in the hope that it will be useful,
  20.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22.  * GNU General Public License for more details.
  23.  *
  24.  * You should have received a copy of the GNU General Public License
  25.  * along with this program; see the file COPYING.  If not, write to
  26.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  27.  */
  28.  
  29. #include <stdxlib.h>
  30. #include <utypes.h>
  31. #include <standard.h>
  32.  
  33. #ifdef    HAVE_DTOA    /* 4.4BSD floating point implementation */
  34. #ifdef    HAVE_DTOA_R
  35. extern    char *__dtoa    __PR((double value, int mode, int ndigit, int *decpt, int *sign, char **ep, char **resultp));
  36. #else
  37. extern    char *__dtoa    __PR((double value, int mode, int ndigit, int *decpt, int *sign, char **ep));
  38. #endif
  39. #endif
  40.  
  41. #ifndef    HAVE_ECVT
  42. EXPORT    char *ecvt    __PR((double value, int ndigit, int *decpt, int *sign));
  43. #endif
  44. #ifndef    HAVE_FCVT
  45. EXPORT    char *fcvt    __PR((double value, int ndigit, int *decpt, int *sign));
  46. #endif
  47. #ifndef    HAVE_GCVT
  48. EXPORT    char *gcvt    __PR((double value, int ndigit, char *buf));
  49. #endif
  50.  
  51. #if    !defined(HAVE_ECVT) && defined(HAVE_DTOA)
  52. #define    HAVE_ECVT
  53. char *
  54. ecvt(value, ndigit, decpt, sign)
  55.     double    value;
  56.     int    ndigit;
  57.     int    *decpt;
  58.     int    *sign;
  59. {
  60. static    Uint    bufsize;
  61. static    char    *buf;
  62.     char    *bufend;
  63.     char    *ep;
  64.     char    *bp;
  65. #ifdef    HAVE_DTOA_R
  66. static    char    *result;
  67. #endif
  68.  
  69. #ifdef    HAVE_DTOA_R
  70.     if (result) {
  71.         free(result);
  72.         result = NULL;
  73.     }
  74.     bp = __dtoa(value, 2, ndigit, decpt, sign, &ep, &result);
  75. #else
  76.     bp = __dtoa(value, 2, ndigit, decpt, sign, &ep);
  77. #endif
  78.  
  79.     if (value == 0.0) {
  80.         /*
  81.          * Handle __dtoa()'s deviation from ecvt():
  82.          * 0.0 is converted to "0" instead of 'ndigit' zeroes.
  83.          * The string "0" is not allocated, so
  84.          * we need to allocate buffer to hold 'ndigit' zeroes.
  85.          */
  86.         if (bufsize < ndigit + 1) {
  87.             if (buf != (char *)0)
  88.                 free(buf);
  89.             bufsize = ndigit + 1;
  90.             buf = malloc(bufsize);
  91.         }
  92.         ep = bp = buf;
  93.     }
  94.  
  95.     /*
  96.      * Fill up trailing zeroes suppressed by __dtoa()
  97.      * From an internal __dtoa() comment:
  98.      *    Sufficient space is allocated to the return value
  99.      *    to hold the suppressed trailing zeros.
  100.      */
  101.     for (bufend = &bp[ndigit]; ep < bufend; )
  102.         *ep++ = '0';
  103.     *ep = '\0';
  104.  
  105.     return (bp);
  106. }
  107. #endif
  108.  
  109. #if    !defined(HAVE_FCVT) && defined(HAVE_DTOA)
  110. #define    HAVE_FCVT
  111. char *
  112. fcvt(value, ndigit, decpt, sign)
  113.     double    value;
  114.     int    ndigit;
  115.     int    *decpt;
  116.     int    *sign;
  117. {
  118. static    Uint    bufsize;
  119. static    char    *buf;
  120.     char    *bufend;
  121.     char    *ep;
  122.     char    *bp;
  123. #ifdef    HAVE_DTOA_R
  124. static    char    *result;
  125. #endif
  126.  
  127. #ifdef    HAVE_DTOA_R
  128.     if (result) {
  129.         free(result);
  130.         result = NULL;
  131.     }
  132.     bp = __dtoa(value, 3, ndigit, decpt, sign, &ep, &result);
  133. #else
  134.     bp = __dtoa(value, 3, ndigit, decpt, sign, &ep);
  135. #endif
  136.  
  137.     if (value == 0.0) {
  138.         /*
  139.          * Handle __dtoa()'s deviation from fcvt():
  140.          * 0.0 is converted to "0" instead of 'ndigit' zeroes.
  141.          * The string "0" is not allocated, so
  142.          * we need to allocate buffer to hold 'ndigit' zeroes.
  143.          */
  144.         if (bufsize < ndigit + 1) {
  145.             if (buf != (char *)0)
  146.                 free(buf);
  147.             bufsize = ndigit + 1;
  148.             buf = malloc(bufsize);
  149.         }
  150.         ep = bp = buf;
  151.         *decpt = 0;
  152.     }
  153.  
  154.     /*
  155.      * Fill up trailing zeroes suppressed by __dtoa()
  156.      * From an internal __dtoa() comment:
  157.      *    Sufficient space is allocated to the return value
  158.      *    to hold the suppressed trailing zeros.
  159.      */
  160.     for (bufend = &bp[*decpt + ndigit]; ep < bufend; )
  161.         *ep++ = '0';
  162.     *ep = '\0';
  163.  
  164.     return (bp);
  165. }
  166. #endif
  167.  
  168. #ifndef    HAVE_GCVT
  169. #define    HAVE_GCVT
  170. char *
  171. gcvt(number, ndigit, buf)
  172.     double    number;
  173.     int    ndigit;
  174.     char    *buf;
  175. {
  176.          int    sign;
  177.          int    decpt;
  178.     register char    *b;
  179.     register char    *rs;
  180.     register int    i;
  181.  
  182.     b = ecvt(number, ndigit, &decpt, &sign);
  183.     rs = buf;
  184.     if (sign)
  185.         *rs++ = '-';
  186.     for (i = ndigit-1; i > 0 && b[i] == '0'; i--)
  187.         ndigit--;
  188. #ifdef    V7_FLOATSTYLE
  189.     if ((decpt >= 0 && decpt-ndigit > 4) ||
  190. #else
  191.     if ((decpt >= 0 && decpt-ndigit > 0) ||
  192. #endif
  193.         (decpt < 0 && decpt < -3)) {    /* e-format */
  194.         decpt--;
  195.         *rs++ = *b++;
  196.         *rs++ = '.';
  197.         for (i = 1; i < ndigit; i++)
  198.             *rs++ = *b++;
  199.         *rs++ = 'e';
  200.         if (decpt < 0) {
  201.             decpt = -decpt;
  202.             *rs++ = '-';
  203.         } else {
  204.             *rs++ = '+';
  205.         }
  206.         if (decpt >= 100) {
  207.             *rs++ = decpt / 100 + '0';
  208.             decpt %= 100;
  209.         }
  210.         *rs++ = decpt / 10 + '0';
  211.         *rs++ = decpt % 10 + '0';
  212.     } else {                /* f-format */
  213.         if (decpt <= 0) {
  214.             if (*b != '0') {
  215. #ifndef    V7_FLOATSTYLE
  216.                 *rs++ = '0';
  217. #endif
  218.                 *rs++ = '.';
  219.             }
  220.             while (decpt < 0) {
  221.                 decpt++;
  222.                 *rs++ = '0';
  223.             }
  224.         }
  225.         for (i = 1; i <= ndigit; i++) {
  226.             *rs++ = *b++;
  227.             if (i == decpt)
  228.                 *rs++ = '.';
  229.         }
  230.         if (ndigit < decpt) {
  231.             while (ndigit++ < decpt)
  232.                 *rs++ = '0';
  233.             *rs++ = '.';
  234.         }
  235.     }
  236.     if (rs[-1] == '.')
  237.         rs--;
  238.     *rs = '\0';
  239.     return (buf);
  240. }
  241. #endif
  242.