home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / gnu / libsrc87 / doprnt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-30  |  25.2 KB  |  1,140 lines

  1. /*
  2.  * Copyright (c) 1988 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. /*
  19.  * minorly customized for gcc lib
  20.  *    ++jrb
  21.  * and for the sfp004 as well as the TT's 68881
  22.  *      mjr++
  23.  * and for turbo C and the MiNT library
  24.  *     ++um,mh
  25.  * and special M68881 and sfp004 version of cvt() added that uses fmovep for
  26.  * maximum precision, no bits lost anymore!
  27.  *    ++schwab
  28.  */
  29.  
  30. #ifndef __NO_FLOAT__
  31. #if 0
  32. static unsigned long
  33.     __notanumber[2] = { 0x7fffffffL, 0xffffffffL }; /* ieee NAN */
  34. #define NAN  (*((double *)&__notanumber[0]))
  35. static unsigned long
  36.     __p_infinity[2] = { 0x7ff00000L, 0x00000000L }; /* ieee NAN */
  37. #define INF  (*((double *)&__p_infinity[0]))
  38. #endif
  39.  
  40. #define NAN_HI 0x7fffffffL
  41. #define NAN_LO 0xffffffffL
  42. #define INF_HI 0x7ff00000L
  43. #define INF_LO 0x00000000L
  44.  
  45. #endif /* __NO_FLOAT__ */
  46.  
  47. #ifdef LIBC_SCCS
  48. static char sccsid[] = "@(#)doprnt.c    5.37 (Berkeley) 3/26/89";
  49. #endif /* LIBC_SCCS */
  50.  
  51. #include <compiler.h>
  52. #ifdef __TURBOC__
  53. #include <sys\types.h>
  54. #else
  55. #include <sys/types.h>
  56. #endif
  57. #include <stdarg.h>
  58. #include <stdio.h>
  59. #include <ctype.h>
  60. #include <string.h>
  61. #include <limits.h>
  62. #include    <math.h>    /* mjr++    */
  63.  
  64. #ifndef __GNUC__    /* gcc lib has these typedefs in sys/types.h */
  65. #ifndef __MINT__    /* as does the MiNT library */
  66. typedef unsigned char u_char;
  67. typedef unsigned long u_long;
  68. #endif
  69. #endif
  70.  
  71. /* 11-bit exponent (VAX G floating point) is 308 decimal digits */
  72. #define    MAXEXP        308
  73.  
  74. /* 128 bit fraction takes up 39 decimal digits; max reasonable precision */
  75. # define    MAXFRACT    39
  76. # define    MAXEXP        308
  77.  
  78. #if defined (__M68881__) && !defined (sfp004)
  79. #  include <math-68881.h>    /* mjr: use the inline functions    */
  80. #endif    __M68881__
  81.  
  82. #define    DEFPREC        6
  83.  
  84. #define    BUF        (MAXEXP+MAXFRACT+1)    /* + decimal point */
  85.  
  86. #define    PUTC(ch)     if( fputc(ch, fp) == EOF ) return EOF;
  87.  
  88.  
  89. #define ARG(signtag) \
  90.     _ulong = \
  91.         flags&LONGINT ? \
  92.             (unsigned long)va_arg(argp, signtag long) : \
  93.         (flags&SHORTINT ? \
  94.             (unsigned long)(signtag short)va_arg(argp, signtag int) : \
  95.              (unsigned long)va_arg(argp, signtag int))
  96.      /* shorts are always promoted to ints; thus, it's `va_arg(... int)'
  97.       * for `flags&SHORTINT'!
  98.       */
  99.  
  100. #define TEN_MUL(X)    ((((X) << 2) + (X)) << 1)
  101.  
  102. #define    todigit(c)    ((c) - '0')
  103. #define    tochar(n)    ((n) + '0')
  104.  
  105. #define    LONGINT        0x01        /* long integer */
  106. #define    LONGDBL        0x02        /* long double; unimplemented */
  107. #define    SHORTINT    0x04        /* short integer */
  108. #define    ALT        0x08        /* alternate form */
  109. #define    LADJUST        0x10        /* left adjustment */
  110. #define    ZEROPAD        0x20        /* zero (as opposed to blank) pad */
  111. #define    HEXPREFIX    0x40        /* add 0x or 0X prefix */
  112.  
  113. #ifndef __NO_FLOAT__
  114. #define __FLOATS__ 1
  115. #endif
  116.  
  117. #ifdef __FLOATS__
  118. # include    "flonum.h"
  119. #if defined (__M68881__) || defined (sfp004)
  120. static char *exponent __PROTO ((char *, int, int));
  121. static int _round __PROTO ((int, char *, char *, char *));
  122. static int cvt __PROTO ((double, int, int, char *, int, char *));
  123. #else
  124. #  if __STDC__
  125. static char *exponent(char *, int, int);
  126. static char *_round(double, int *, char *, char *, int, char *);
  127. static int  cvt(double, int, int, char *, int, char *, char *);
  128. #  else
  129. static char *exponent();
  130. static char *_round();
  131. static int  cvt();
  132. #  endif
  133. #endif /* __M68881__ */
  134. #endif
  135.  
  136. #if defined(__GNUC__) && (!defined(__NO_INLINE__))
  137. #ifdef __M68020__
  138.  
  139. #define _ICONV(NUMBER, BASE, BUF)                \
  140. {                                \
  141.   long i;                            \
  142.   do                                \
  143.     {                                \
  144.       __asm__ volatile                        \
  145.     ("divull %3,%0:%1"                    \
  146.      : "=d"((long)(NUMBER)), "=d"(i)            \
  147.      : "0"((long)(NUMBER)), "d"((long)(BASE)));        \
  148.       *--(BUF) = digs[i];                    \
  149.     }                                \
  150.   while (NUMBER);                        \
  151. }
  152.  
  153. #else /* !__M68020 */  
  154.  
  155. #define _ICONV(NUMBER, BASE, BUF)                 \
  156. {                                \
  157.                                 \
  158.     while((NUMBER) > 65535L)                    \
  159.     {                                \
  160.         extern unsigned long __udivsi3(); /* quot = d0, rem = d1 */ \
  161.         register long i __asm ("d1");                    \
  162.     __asm__ volatile("
  163.         movl    %3,sp@-;
  164.          movl    %2,sp@-;
  165.          jsr    ___udivsi3;
  166.          addqw    #8,sp;
  167.          movl    d0,%0"                    \
  168.              : "=r"((long)NUMBER), "=d"(i)            \
  169.          : "0"((long)NUMBER), "r"((long)BASE)        \
  170.              : "d0", "d1", "a0", "a1");            \
  171.         *--BUF = digs[i];                    \
  172.     }                                \
  173.     do                                 \
  174.     {                                \
  175.             short i;                        \
  176.         __asm__ volatile("
  177.          divu    %3,%2;
  178.          swap    %0;
  179.          movw    %0,%1;
  180.          clrw    %0;
  181.                 swap    %0"                    \
  182.              : "=d"((long)NUMBER), "=g"(i)            \
  183.          : "0"((long)NUMBER), "dm"((short)BASE));    \
  184.         *--BUF = digs[i];                    \
  185.     } while(NUMBER);                        \
  186. }
  187.  
  188. #endif /* __M68020 */
  189.  
  190. #else /* !__GNUC__ */
  191.  
  192. #define _ICONV(NUMBER, BASE, BUF)                 \
  193.   do {                                \
  194.     *--(BUF) = digs[(NUMBER) % (BASE)];                \
  195.     (NUMBER) /= (BASE);                        \
  196.   } while (NUMBER);
  197.  
  198. #endif /* __GNUC__ */
  199.  
  200.  
  201. int _doprnt(fp, fmt0, argp)
  202.     register FILE *fp;
  203.     const char *fmt0;
  204.     va_list argp;
  205. {
  206.     register const u_char *fmt;    /* format string */
  207.     register int ch;    /* character from fmt */
  208.     register int cnt;    /* return value accumulator */
  209.     register int n;        /* random handy integer */
  210.     register char *t;    /* buffer pointer */
  211. #ifdef    __FLOATS__
  212. /*    double _double;        *//* double precision arguments %[eEfgG] */
  213.     union double_di _dd;    /* _double is #defined to be _dd later on */
  214.     char softsign;        /* temporary negative sign for floats */
  215. #endif    __FLOATS__
  216.     u_long _ulong;        /* integer arguments %[diouxX] */
  217.     short base;        /* base for [diouxX] conversion */
  218.     short dprec;        /* decimal precision in [diouxX] */
  219.     short fieldsz;        /* field size expanded by sign, etc */
  220.     short flags;        /* flags as above */
  221.     short fpprec;        /* `extra' floating precision in [eEfgG] */
  222.     short prec;        /* precision from format (%.3d), or -1 */
  223.     short realsz;        /* field size expanded by decimal precision */
  224.     short size;        /* size of converted field or string */
  225.     short width;        /* width from format (%8d), or 0 */
  226.     char sign;        /* sign prefix (' ', '+', '-', or \0) */
  227.     char *digs;        /* digits for [diouxX] conversion */
  228.     char buf[BUF];        /* space for %c, %[diouxX], %[eEfgG] */
  229.  
  230.         t = buf;
  231.     fmt = (const u_char *) fmt0;
  232.     digs = "0123456789abcdef";
  233.     for (cnt = 0;; ++fmt) {
  234.         if ((ch = *fmt) == 0)
  235.             return (cnt);
  236.         if (ch != '%') {
  237.             PUTC(ch);
  238.             cnt++;
  239.             continue;
  240.         }
  241.         flags = 0; dprec = 0; fpprec = 0; width = 0;
  242.         prec = -1;
  243.         sign = '\0';
  244.  
  245. rflag:        switch (*++fmt) {
  246.         case ' ':
  247.             /*
  248.              * ``If the space and + flags both appear, the space
  249.              * flag will be ignored.''
  250.              *    -- ANSI X3J11
  251.              */
  252.             if (!sign)
  253.                 sign = ' ';
  254.             goto rflag;
  255.         case '#':
  256.             flags |= ALT;
  257.             goto rflag;
  258.         case '*':
  259.             /*
  260.              * ``A negative field width argument is taken as a
  261.              * - flag followed by a  positive field width.''
  262.              *    -- ANSI X3J11
  263.              * They don't exclude field widths read from args.
  264.              */
  265.             if ((width = (short)(va_arg(argp, int))) >= 0)
  266.                 goto rflag;
  267.             width = -width;
  268.             /* FALLTHROUGH */
  269.         case '-':
  270.             flags |= LADJUST;
  271.             goto rflag;
  272.         case '+':
  273.             sign = '+';
  274.             goto rflag;
  275.         case '.':
  276.             if (*++fmt == '*')
  277.                 n = va_arg(argp, int);
  278.             else {
  279.                 n = 0;
  280.                 while (isascii(*fmt) && isdigit(*fmt))
  281.                     n = TEN_MUL(n) + todigit(*fmt++);
  282.                 --fmt;
  283.             }
  284.             prec = n < 0 ? -1 : n;
  285.             goto rflag;
  286.         case '0':
  287.             /*
  288.              * ``Note that 0 is taken as a flag, not as the
  289.              * beginning of a field width.''
  290.              *    -- ANSI X3J11
  291.              */
  292.             flags |= ZEROPAD;
  293.             goto rflag;
  294.         case '1': case '2': case '3': case '4':
  295.         case '5': case '6': case '7': case '8': case '9':
  296.             n = 0;
  297.             do {
  298.                 n = TEN_MUL(n) + todigit(*fmt);
  299.             } while (isascii(*++fmt) && isdigit(*fmt));
  300.             width = n;
  301.             --fmt;
  302.             goto rflag;
  303.         case 'L':
  304.             flags |= LONGDBL;
  305.             goto rflag;
  306.         case 'h':
  307.             flags |= SHORTINT;
  308.             goto rflag;
  309.         case 'l':
  310.             flags |= LONGINT;
  311.             goto rflag;
  312.         case 'c':
  313.             *(t = buf) = va_arg(argp, int);
  314.             size = 1;
  315.             sign = '\0';
  316.             goto pforw;
  317.         case 'D':
  318.             flags |= LONGINT;
  319.             /*FALLTHROUGH*/
  320.         case 'd':
  321.         case 'i':
  322.             ARG(signed);
  323.             if ((long)_ulong < 0) {
  324.                 _ulong = -_ulong;
  325.                 sign = '-';
  326.             }
  327.             base = 10;
  328.             goto number;
  329. #ifdef __FLOATS__
  330.         case 'e':
  331.         case 'E':
  332.         case 'f':
  333.         case 'g':
  334.         case 'G':
  335.  
  336. /* mjr: check for NANs */
  337. #define    _double _dd.d
  338.             _double = va_arg(argp, double);
  339.             if (_dd.i[0] == NAN_HI)
  340.             {
  341.                 t = buf;
  342.                 t = strcpy(t, "NaN");
  343.                 size = strlen(t);
  344.                 goto pforw;
  345.             }
  346.             /*
  347.              * don't do unrealistic precision; just pad it with
  348.              * zeroes later, so buffer size stays rational.
  349.              */
  350.             if (prec > (MAXEXP - MAXFRACT)) {
  351.                 if ((*fmt != 'g' && *fmt != 'G') || (flags&ALT))
  352.                     fpprec = prec - MAXFRACT;
  353.                 prec = MAXFRACT;
  354.             }
  355.             else if (prec == -1)
  356.                 prec = DEFPREC;
  357.             /*
  358.              * softsign avoids negative 0 if _double is < 0 and
  359.              * no significant digits will be shown
  360.              */
  361.             if (_double < 0) {
  362.                 softsign = '-';
  363.                 _double = -_double;
  364.             }
  365.             else
  366.                 softsign = 0;
  367. /* hyc: check for overflows ... */
  368.             if (((unsigned long)_dd.i[0] > INF_HI) ||
  369.                 ((unsigned long)_dd.i[0] == INF_HI &&
  370.                  (unsigned long)_dd.i[1] > INF_LO))
  371.               {
  372.                 t = buf;
  373.                 if(softsign == 0)
  374.                 t = strcpy(t, "NaN");
  375.                 else
  376.                 t = strcpy(t, "-NaN");
  377.                 size = strlen(t);
  378.                 goto pforw;
  379.             }
  380.             else    /* Not greater, see if equal to Inf */
  381.  
  382. /* mjr: check for +-INFINITY */
  383.             if ((unsigned long)_dd.i[0] == INF_HI)
  384.               {
  385.                 t = buf;
  386.                 if(softsign == 0)
  387.                 t = strcpy(t, "+Inf");
  388.                 else
  389.                 t = strcpy(t, "-Inf");
  390.                 size = strlen(t);
  391.                 goto pforw;
  392.             }
  393.             /*
  394.              * cvt may have to round up past the "start" of the
  395.              * buffer, i.e. ``printf("%.2f", (double)9.999);'';
  396.              * if the first char isn't '\0', it did.
  397.              */
  398.             *buf = '\0';
  399.             size = cvt(_double, (int)prec, (int)flags, &softsign,
  400.                    *fmt, buf
  401. #if !defined (__M68881__) && !defined (sfp004)
  402.                    , buf + (int)sizeof(buf)
  403. #endif
  404.                    ); 
  405.             if (softsign)
  406.                 sign = '-';
  407.             t = *buf ? buf : buf + 1;
  408.             goto pforw;
  409. #endif /* __FLOATS__ */
  410.         case 'n':
  411.             if (flags & LONGINT)
  412.                 *va_arg(argp, long *) = cnt;
  413.             else if (flags & SHORTINT)
  414.                 *va_arg(argp, short *) = cnt;
  415.             else
  416.                 *va_arg(argp, int *) = cnt;
  417.             break;
  418.         case 'O':
  419.             flags |= LONGINT;
  420.             /*FALLTHROUGH*/
  421.         case 'o':
  422.             ARG(unsigned);
  423.             base = 8;
  424.             goto nosign;
  425.         case 'p':
  426.             /*
  427.              * ``The argument shall be a pointer to void.  The
  428.              * value of the pointer is converted to a sequence
  429.              * of printable characters, in an implementation-
  430.              * defined manner.''
  431.              *    -- ANSI X3J11
  432.              */
  433.             /* NOSTRICT */
  434.             _ulong = (u_long)va_arg(argp, void *);
  435.             base = 16;
  436.             goto nosign;
  437.         case 's':
  438.             if ((t = va_arg(argp, char *)) == 0)
  439.                 t = "(null)";
  440.             if (prec >= 0) {
  441.                 /*
  442.                  * can't use strlen; can only look for the
  443.                  * NUL in the first `prec' characters, and
  444.                  * strlen() will go further.
  445.                  */
  446. #ifdef __STDC__
  447.                 char *p;
  448.                 void *memchr(const void *, int, size_t);
  449. #else
  450.                 char *p, *memchr();
  451. #endif
  452.  
  453.                 if ((p = (char *)memchr(t, 0, (size_t)prec)) != NULL) {
  454.                     size = p - t;
  455.                     if (size > prec)
  456.                         size = prec;
  457.                 } else
  458.                     size = prec;
  459.             } else
  460.                 size = (int)strlen(t);
  461.             sign = '\0';
  462.             goto pforw;
  463.         case 'U':
  464.             flags |= LONGINT;
  465.             /*FALLTHROUGH*/
  466.         case 'u':
  467.             ARG(unsigned);
  468.             base = 10;
  469.             goto nosign;
  470.         case 'X':
  471.             digs = "0123456789ABCDEF";
  472.             /* FALLTHROUGH */
  473.         case 'x':
  474.             ARG(unsigned);
  475.             base = 16;
  476.             /* leading 0x/X only if non-zero */
  477.             if (flags & ALT && _ulong != 0)
  478.                 flags |= HEXPREFIX;
  479.  
  480.             /* unsigned conversions */
  481. nosign:            sign = '\0';
  482.             /*
  483.              * ``... diouXx conversions ... if a precision is
  484.              * specified, the 0 flag will be ignored.''
  485.              *    -- ANSI X3J11
  486.              */
  487. number:            if ((dprec = prec) >= 0)
  488.                 flags &= ~ZEROPAD;
  489.  
  490.             /*
  491.              * ``The result of converting a zero value with an
  492.              * explicit precision of zero is no characters.''
  493.              *    -- ANSI X3J11
  494.              */
  495.             t = buf + BUF;
  496.             if (_ulong != 0 || prec != 0) {
  497.                 _ICONV(_ulong, base, t);
  498.                 digs = "0123456789abcdef";
  499.                 if (flags & ALT && base == 8 && *t != '0')
  500.                     *--t = '0'; /* octal leading 0 */
  501.             }
  502.             size = buf + BUF - t;
  503.  
  504. pforw:
  505.             /*
  506.              * All reasonable formats wind up here.  At this point,
  507.              * `t' points to a string which (if not flags&LADJUST)
  508.              * should be padded out to `width' places.  If
  509.              * flags&ZEROPAD, it should first be prefixed by any
  510.              * sign or other prefix; otherwise, it should be blank
  511.              * padded before the prefix is emitted.  After any
  512.              * left-hand padding and prefixing, emit zeroes
  513.              * required by a decimal [diouxX] precision, then print
  514.              * the string proper, then emit zeroes required by any
  515.              * leftover floating precision; finally, if LADJUST,
  516.              * pad with blanks.
  517.              */
  518.  
  519.             /*
  520.              * compute actual size, so we know how much to pad
  521.              * fieldsz excludes decimal prec; realsz includes it
  522.              */
  523.             fieldsz = size + fpprec;
  524.             if (sign)
  525.                 fieldsz++;
  526.             if (flags & HEXPREFIX)
  527.                 fieldsz += 2;
  528.             realsz = dprec > fieldsz ? dprec : fieldsz;
  529.  
  530.             /* right-adjusting blank padding */
  531.             if ((flags & (LADJUST|ZEROPAD)) == 0 && width)
  532.                 for (n = realsz; n < width; n++)
  533.                     PUTC(' ');
  534.             /* prefix */
  535.             if (sign)
  536.                 PUTC(sign);
  537.             if (flags & HEXPREFIX) {
  538.                 PUTC('0');
  539.                 PUTC((char)*fmt);
  540.             }
  541.             /* right-adjusting zero padding */
  542.             if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
  543.                 for (n = realsz; n < width; n++)
  544.                     PUTC('0');
  545.             /* leading zeroes from decimal precision */
  546.             for (n = fieldsz; n < dprec; n++)
  547.                 PUTC('0');
  548.  
  549. #ifdef __FLOATS__
  550.             if (fpprec > 0)
  551.               {
  552.                 /* the number without exponent */
  553.                 n = size;
  554.                 while (*t != 'e' && *t != 'E' && --n >= 0)
  555.                   PUTC (*t++);
  556.               }
  557.             else
  558. #endif
  559.             /* the string or number proper */
  560.             for (n = size; --n >= 0; )
  561.                 PUTC(*t++);
  562.             /* trailing f.p. zeroes */
  563.             while (--fpprec >= 0)
  564.                 PUTC('0');
  565. #ifdef __FLOATS__
  566.             /* exponent */
  567.             while (--n >= 0)
  568.               PUTC (*t++);
  569. #endif
  570.             /* left-adjusting padding (always blank) */
  571.             if (flags & LADJUST)
  572.                 for (n = realsz; n < width; n++)
  573.                     PUTC(' ');
  574.             /* finally, adjust cnt */
  575.             cnt += width > realsz ? width : realsz;
  576.             break;
  577.         case '\0':    /* "%?" prints ?, unless ? is NULL */
  578.             return (cnt);
  579.         default:
  580.             PUTC((char)*fmt);
  581.             cnt++;
  582.         }
  583.     }
  584.     /* NOTREACHED */
  585. }
  586.  
  587. #ifdef __FLOATS__
  588. #if defined (__M68881__) || defined (sfp004)
  589.  
  590. /* Format of packed decimal (from left to right):
  591.  
  592.     1 Bit: sign of mantissa
  593.     1 Bit: sign of exponent
  594.     2 Bits zero
  595.    12 Bits: three digits exponent
  596.     4 Bits unused, fourth (higher order) digit of exponent
  597.     8 Bits zero
  598.    68 Bits: 17 digits of mantissa, decimal point after first digit
  599.   --------
  600.    96 Bits == 12 Bytes
  601.  
  602.    All numbers in BCD format.  */
  603.  
  604. #ifdef sfp004
  605. /* Note: not tested -- schwab */
  606.  
  607. /* static */ void Format __PROTO ((double number, char *buf));
  608.  
  609. asm ("
  610. comm = -6;
  611. resp = -16;
  612. .text
  613. .even
  614. _Format:
  615.     lea    0xfffffa50:w,a0            | fpu address
  616.     lea    sp@(4),a1            | argptr
  617.  
  618.     movew    #0x5400,a0@(comm)        | fmoved -> fp0
  619. 1:    cmpw    #0x8900,a0@(resp)
  620.     beq    1b
  621.     movel    a1@+,a0@
  622.     movel    a1@+,a0@
  623.  
  624.     movel    a1@,a1                | get buf
  625.     movew    #0x6c11,a0@(comm)        | fmovep fp0,a1@{#17}
  626. 1:    cmpw    #0x8900,a0@(resp)
  627.     beq    1b
  628.     movel    a0@,a1@+
  629.     movel    a0@,a1@+
  630.     movel    a0@,a1@+
  631.     rts
  632. ");
  633. #endif /* sfp004 */
  634.     
  635. static int
  636. cvt (number, prec, flags, signp, fmtch, startp)
  637.      double number;
  638.      int prec, flags, fmtch;
  639.      char *signp, *startp;
  640. {
  641.   char buf[12];
  642.   char digits[18];
  643.   int i;
  644.   char *p, *t;
  645.   int expcnt;
  646.   int gformat = 0, dotrim;
  647.  
  648.   /* Convert to packed decimal.  */
  649. #ifdef sfp004
  650.   Format (number, buf);
  651. #else
  652.   asm volatile ("fmovep %0,%1{#17}" : : "f" (number), "m" (buf[0]));
  653. #endif
  654.   /* Unpack it. */
  655.   p = buf + 3;
  656.   for (i = 0; i < 17; i++)
  657.     digits[i] = ((i & 1 ? *p >> 4 : *p++) & 15) + '0';
  658.   digits[i] = 0;
  659.   expcnt = ((buf[0] & 15) * 10 + ((buf[1] >> 4) & 15)) * 10 + (buf[1] & 15);
  660.   if (buf[0] & 0x40)
  661.     expcnt = -expcnt;
  662.   t = ++startp;
  663.   p = digits;
  664.   switch (fmtch)
  665.     {
  666.     case 'f':
  667.       if (expcnt >= 0)
  668.     {
  669.       *t++ = *p++;
  670.       while (expcnt > 0 && *p)
  671.         {
  672.           *t++ = *p++;
  673.           expcnt--;
  674.         }
  675.       while (expcnt > 0)
  676.         {
  677.           *t++ = '0';
  678.           expcnt--;
  679.         }
  680.     }
  681.       else
  682.     {
  683.       /* Note: decimal point after the first digit. */
  684.       expcnt++;
  685.       *t++ = '0';
  686.     }
  687.       if (prec || flags & ALT)
  688.     *t++ = '.';
  689.       while (prec > 0 && expcnt < 0)
  690.     {
  691.       *t++ = '0';
  692.       prec--;
  693.       expcnt++;
  694.     }
  695.       while (prec > 0 && *p)
  696.     {
  697.       *t++ = *p++;
  698.       prec--;
  699.     }
  700.       if (*p)
  701.     if (_round (*p, startp, t - 1, signp))
  702.       *--startp = '1';
  703.       while (prec > 0)
  704.     {
  705.       *t++ = '0';
  706.       prec--;
  707.     }
  708.       break;
  709.  
  710.     case 'e':
  711.     case 'E':
  712.     eformat:
  713.       *t++ = *p++;
  714.       if (prec || flags & ALT)
  715.     *t++ = '.';
  716.       while (prec > 0 && *p)
  717.     {
  718.       *t++ = *p++;
  719.       prec--;
  720.     }
  721.       if (*p)
  722.     if (_round (*p, startp, t - 1, signp))
  723.       {
  724.         expcnt++;
  725.         *startp = '1';
  726.       }
  727.       if (!gformat || flags & ALT)
  728.     {
  729.       while (prec > 0)
  730.         {
  731.           *t++ = '0';
  732.           prec--;
  733.         }
  734.     }
  735.       else
  736.     {
  737.       /* Suppress trailing zero's. */
  738.       while (t > startp && t[-1] == '0')
  739.         t--;
  740.       if (t[-1] == '.')
  741.         t--;
  742.     }
  743.       t = exponent (t, expcnt, fmtch);
  744.       break;
  745.  
  746.     case 'g':
  747.     case 'G':
  748.       if (prec == 0)
  749.     prec++;
  750.       /* If the exponent is not less than the precision or less than -4,
  751.      use 'e' format, otherwise use 'f' format.  */
  752.       if (expcnt >= prec || expcnt < -4)
  753.     {
  754.       /* Count the significant digit before the decimal point.  */
  755.       prec--;
  756.       /* 'g'/'G' -> 'e'/'E' */
  757.       fmtch -= 2;
  758.       gformat = 1;
  759.       goto eformat;
  760.     }
  761.       /* Like 'f', but prec counts significant digits.  */
  762.       if (expcnt >= 0)
  763.     {
  764.       *t++ = *p++;
  765.       prec--;
  766.       /* Note that prec >= expcnt */
  767.       while (expcnt > 0 && *p)
  768.         {
  769.           *t++ = *p++;
  770.           expcnt--;
  771.           prec--;
  772.         }
  773.       while (expcnt > 0)
  774.         {
  775.           *t++ = '0';
  776.           expcnt--;
  777.           prec--;
  778.         }
  779.     }
  780.       else
  781.     {
  782.       *t++ = '0';
  783.       expcnt++;
  784.     }
  785.       if (prec > 0 || flags & ALT)
  786.     {
  787.       dotrim = 1;
  788.       *t++ = '.';
  789.     }
  790.       else
  791.     dotrim = 0;
  792.       if (prec > 0)
  793.     /* Pad with 0's */
  794.     while (expcnt < 0)
  795.       {
  796.         *t++ = '0';
  797.         expcnt++;
  798.       }
  799.       /* While more precision required and digits left */
  800.       while (prec > 0 && *p)
  801.     {
  802.       *t++ = *p++;
  803.       prec--;
  804.     }
  805.       if (*p)
  806.     if (_round (*p, startp, t - 1, signp))
  807.       /* Overflow, e.g. 9.999 -> 10.000 */
  808.       *--startp = '1';
  809.       if (flags & ALT)
  810.     {
  811.       while (prec > 0)
  812.         {
  813.           *t++ = '0';
  814.           prec--;
  815.         }
  816.     }
  817.       else if (dotrim)
  818.     {
  819.       /* Strip trailing 0's. */
  820.       while (t > startp && *--t == '0');
  821.       if (*t != '.')
  822.         t++;
  823.     }
  824.       break;
  825.     }
  826.   return (int) (t - startp);
  827. }
  828.  
  829. static int
  830. _round (nxtdig, start, end, signp)
  831.      int nxtdig;
  832.      char *start, *end;
  833.      char *signp;
  834. {
  835.   if (nxtdig > '4')
  836.     {
  837.       for (;; --end)
  838.     {
  839.       if (*end == '.')
  840.         --end;
  841.       if (++*end <= '9')
  842.         break;
  843.       *end = '0';
  844.       if (end == start)
  845.         /* Report overflow, caller must handle appropriately.  */
  846.         return 1;
  847.     }
  848.     }
  849.   else if (*signp == '-')
  850.     {
  851.       for (;; --end)
  852.     {
  853.       if (*end == '.')
  854.         --end;
  855.       if (*end != '0')
  856.         break;
  857.       if (end == start)
  858.         *signp = 0;
  859.     }
  860.     }
  861.   return 0;
  862. }
  863.  
  864. #else /* !(__M68881__ || sfp004) */
  865.  
  866. static int
  867. cvt(number,prec,flags, signp, fmtch, startp, endp)
  868.     double number;
  869.     register int prec;
  870.     int flags;
  871.     int fmtch;
  872.     char *signp, *startp, *endp;
  873. {
  874.     register char *p, *t;
  875.     register double fract;
  876.     int dotrim, expcnt, gformat;
  877.     double integer, tmp, modf __PROTO((double, double *));
  878.     char *exponent __PROTO((char *, int, int)),
  879.          *_round __PROTO((double, int *, char *, char *, int, char *));
  880.  
  881.     dotrim = expcnt = gformat = 0;
  882.     fract = modf(number, &integer);
  883.  
  884.     /* get an extra slot for rounding. */
  885.     t = ++startp;
  886. /* jrb -- #define DBL_EPSILON 1.1107651257113995e-16 /* mjr ++ /
  887.     /*
  888.      * get integer portion of number; put into the end of the buffer; the
  889.      * .01 is added for modf(356.0 / 10, &integer) returning .59999999...
  890.      */
  891.     for (p = endp - 1; integer; ++expcnt) {
  892.         tmp = modf(integer / 10, &integer);
  893.         *p-- = tochar((int)((tmp + .01) * 10));
  894. /* await michals advise on this    -- in the mean while use above line
  895.     *p-- = tochar((int)((tmp + DBL_EPSILON) * 10));
  896.  */
  897.     }
  898.     switch(fmtch) {
  899.     case 'f':
  900.         /* reverse integer into beginning of buffer */
  901.         if (expcnt)
  902.             for (; ++p < endp; *t++ = *p);
  903.         else
  904.             *t++ = '0';
  905.         /*
  906.          * if precision required or alternate flag set, add in a
  907.          * decimal point.
  908.          */
  909.         if (prec || flags&ALT)
  910.             *t++ = '.';
  911.         /* if requires more precision and some fraction left */
  912.         if (fract) {
  913.             if (prec)
  914.                 do {
  915.                     fract = modf(fract * 10, &tmp);
  916.                     *t++ = tochar((int)tmp);
  917.                 } while (--prec && fract);
  918.             if (fract)
  919.                 startp = _round(fract, (int *)NULL, startp,
  920.                     t - 1, (char)0, signp);
  921.         }
  922.         for (; prec--; *t++ = '0');
  923.         break;
  924.     case 'e':
  925.     case 'E':
  926. eformat:    if (expcnt) {
  927.             *t++ = *++p;
  928.             if (prec || flags&ALT)
  929.                 *t++ = '.';
  930.             /* if requires more precision and some integer left */
  931.             for (; prec && ++p < endp; --prec)
  932.                 *t++ = *p;
  933.             /*
  934.              * if done precision and more of the integer component,
  935.              * round using it; adjust fract so we don't re-round
  936.              * later.
  937.              */
  938.             if (!prec && ++p < endp) {
  939.                 fract = 0;
  940.                 startp = _round((double)0, &expcnt, startp,
  941.                     t - 1, *p, signp);
  942.             }
  943.             /* adjust expcnt for digit in front of decimal */
  944.             --expcnt;
  945.         }
  946.         /* until first fractional digit, decrement exponent */
  947.         else if (fract) {
  948.             /* adjust expcnt for digit in front of decimal */
  949.             for (expcnt = -1;; --expcnt) {
  950.                 fract = modf(fract * 10, &tmp);
  951.                 if (tmp)
  952.                     break;
  953.             }
  954.             *t++ = tochar((int)tmp);
  955.             if (prec || flags&ALT)
  956.                 *t++ = '.';
  957.         }
  958.         else {
  959.             *t++ = '0';
  960.             if (prec || flags&ALT)
  961.                 *t++ = '.';
  962.         }
  963.         /* if requires more precision and some fraction left */
  964.         if (fract) {
  965.             if (prec)
  966.                 do {
  967.                     fract = modf(fract * 10, &tmp);
  968.                     *t++ = tochar((int)tmp);
  969.                 } while (--prec && fract);
  970.             if (fract)
  971.                 startp = _round(fract, &expcnt, startp,
  972.                     t - 1, (char)0, signp);
  973.         }
  974.         /* if requires more precision */
  975.         for (; prec--; *t++ = '0');
  976.  
  977.         /* unless alternate flag, trim any g/G format trailing 0's */
  978.         if (gformat && !(flags&ALT)) {
  979.             while (t > startp && *--t == '0');
  980.             if (*t == '.')
  981.                 --t;
  982.             ++t;
  983.         }
  984.         t = exponent(t, expcnt, fmtch);
  985.         break;
  986.     case 'g':
  987.     case 'G':
  988.         /* a precision of 0 is treated as a precision of 1. */
  989.         if (!prec)
  990.             ++prec;
  991.         /*
  992.          * ``The style used depends on the value converted; style e
  993.          * will be used only if the exponent resulting from the
  994.          * conversion is less than -4 or greater than the precision.''
  995.          *    -- ANSI X3J11
  996.          */
  997.         if (expcnt > prec || (!expcnt && fract && fract < .0001)) {
  998.             /*
  999.              * g/G format counts "significant digits, not digits of
  1000.              * precision; for the e/E format, this just causes an
  1001.              * off-by-one problem, i.e. g/G considers the digit
  1002.              * before the decimal point significant and e/E doesn't
  1003.              * count it as precision.
  1004.              */
  1005.             --prec;
  1006.             fmtch -= 2;        /* G->E, g->e */
  1007.             gformat = 1;
  1008.             goto eformat;
  1009.         }
  1010.         /*
  1011.          * reverse integer into beginning of buffer,
  1012.          * note, decrement precision
  1013.          */
  1014.         if (expcnt)
  1015.             for (; ++p < endp; *t++ = *p, --prec);
  1016.         else
  1017.             *t++ = '0';
  1018.         /*
  1019.          * if precision required or alternate flag set, add in a
  1020.          * decimal point.  If no digits yet, add in leading 0.
  1021.          */
  1022.         if (prec || flags&ALT) {
  1023.             dotrim = 1;
  1024.             *t++ = '.';
  1025.         }
  1026.         else
  1027.             dotrim = 0;
  1028.         /* if requires more precision and some fraction left */
  1029.         if (fract) {
  1030.             if (prec) {
  1031.                 if (0 == expcnt) {
  1032.                     /* if no significant digits yet */
  1033.                     do {
  1034.                         fract = modf(fract * 10, &tmp);
  1035.                         *t++ = tochar((int)tmp);
  1036.                     } while(!tmp);
  1037.                     prec--;
  1038.                 }
  1039.                 while (prec && fract) {
  1040.                     fract = modf(fract * 10, &tmp);
  1041.                     *t++ = tochar((int)tmp);
  1042.                     prec--;
  1043.                 }
  1044.             }
  1045.             if (fract)
  1046.                 startp = _round(fract, (int *)NULL, startp,
  1047.                     t - 1, (char)0, signp);
  1048.         }
  1049.         /* alternate format, adds 0's for precision, else trim 0's */
  1050.         if (flags&ALT)
  1051.             for (; prec--; *t++ = '0');
  1052.         else if (dotrim) {
  1053.             while (t > startp && *--t == '0');
  1054.             if (*t != '.')
  1055.                 ++t;
  1056.         }
  1057.     }
  1058.     return((int)(t - startp));
  1059. }
  1060.  
  1061. static char *
  1062. _round(fract, exp, start, end, ch, signp)
  1063.     double fract;
  1064.     int *exp;
  1065.     register char *start, *end;
  1066.     int ch;
  1067.     char *signp;
  1068. {
  1069.     double tmp;
  1070.  
  1071.     if (fract)
  1072.         (void)modf(fract * 10, &tmp);
  1073.     else
  1074.         tmp = todigit(ch);
  1075.     if (tmp > 4)
  1076.         for (;; --end) {
  1077.             if (*end == '.')
  1078.                 --end;
  1079.             if (++*end <= '9')
  1080.                 break;
  1081.             *end = '0';
  1082.             if (end == start) {
  1083.                 if (exp) {    /* e/E; increment exponent */
  1084.                     *end = '1';
  1085.                     ++*exp;
  1086.                 }
  1087.                 else {        /* f; add extra digit */
  1088.                     *--end = '1';
  1089.                     --start;
  1090.                 }
  1091.                 break;
  1092.             }
  1093.         }
  1094.     /* ``"%.3f", (double)-0.0004'' gives you a negative 0. */
  1095.     else if (*signp == '-')
  1096.         for (;; --end) {
  1097.             if (*end == '.')
  1098.                 --end;
  1099.             if (*end != '0')
  1100.                 break;
  1101.             if (end == start)
  1102.                 *signp = 0;
  1103.         }
  1104.     return(start);
  1105. }
  1106.  
  1107. #endif /* !(__M68881__ || sfp004) */
  1108.  
  1109. static char *
  1110. exponent(p, exp, fmtch)
  1111.     register char *p;
  1112.     register int exp;
  1113.     int fmtch;
  1114. {
  1115.     register char *t;
  1116.     char expbuf[MAXEXP];
  1117.  
  1118.     *p++ = fmtch;
  1119.     if (exp < 0) {
  1120.         exp = -exp;
  1121.         *p++ = '-';
  1122.     }
  1123.     else
  1124.         *p++ = '+';
  1125.     t = expbuf + MAXEXP;
  1126.     if (exp > 9) {
  1127.         do {
  1128.             *--t = tochar(exp % 10);
  1129.         } while ((exp /= 10) > 9);
  1130.         *--t = tochar(exp);
  1131.         for (; t < expbuf + MAXEXP; *p++ = *t++);
  1132.     }
  1133.     else {
  1134.         *p++ = '0';
  1135.         *p++ = tochar(exp);
  1136.     }
  1137.     return(p);
  1138. }
  1139. #endif /* __FLOATS__ */
  1140.