home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 4 / DATAFILE_PDCD4.iso / unix / unixlib36d / src / stdio / c / print < prev    next >
Encoding:
Text File  |  1994-03-08  |  18.0 KB  |  1,046 lines

  1. static char sccs_id[] = "@(#) print.c 3.3 " __DATE__ " HJR";
  2.  
  3. /* print.c (c) Copyright 1990 H.Rogers */
  4.  
  5. /* Implements __printf(buf,format,argp) which is called by
  6.  * all printf() functions to perform formatted output. */
  7.  
  8. /* A conversion is of the form "%[flags][width][.prec][size]function".
  9.  * For full details RTFM for printf(3). */
  10.  
  11. #include <stddef.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <ctype.h>
  15. #include <stdarg.h>
  16. #include <stdio.h>
  17.  
  18. __STDIOLIB__
  19.  
  20. /* To avoid truncation PRBUFSIZ should be 256+.
  21.  * This library will *not* buffer overflow unless PRBUFSIZ < 4.
  22.  * ANSI requires at least 509 - 512 sounds sensible (SJC). */
  23.  
  24. #define PRBUFSIZ    4096
  25.  
  26.  
  27. /* The floating point functions are the most efficient they can be without
  28.  * resorting to assuming IEEE 'D' or some other internal representation. */
  29.  
  30. /* Unfortunately most software FP units are *inaccurate* - it
  31.  * is probably worth changing these constants for architectures
  32.  * with built in hardware FP units - make MAXPREC larger &
  33.  * FPERR smaller for higher quality. Note that MAXPREC = 16
  34.  * corresponds to the limits of IEEE Packed Decimal format. */
  35.  
  36. #define MAXPREC     16    /* max. decimal precision for %feEgG */
  37. #define FPERR        1e-14    /* cutoff value for zero test */
  38.  
  39. /* It's probably best to leave POINT alone... It works. */
  40.  
  41. #define POINT        0.01    /* offset to compensate for rounding errors */
  42.  
  43.  
  44. /* the prototypes for the output functions */
  45.  
  46. static char *__p_nout (char *, va_list *);
  47.  
  48. static char *__p_char (char *, va_list *);
  49. static char *__p_str (char *, va_list *);
  50. static char *__p_sdec (char *, va_list *);
  51. static char *__p_uoct (char *, va_list *);
  52. static char *__p_udec (char *, va_list *);
  53. static char *__p_uhex (char *, va_list *);
  54. static char *__p_ffix (char *, va_list *);
  55. static char *__p_fexp (char *, va_list *);
  56. static char *__p_fmin (char *, va_list *);
  57. static char *__p_ptr (char *, va_list *);
  58.  
  59.  
  60. /* the buffer __prpad has to be prior to __prbuf in memory -
  61.  * __prjust() avoids having to do any buffer copying by being
  62.  * able to back into the __prpad area from __prbuf */
  63.  
  64. static char __prpad[(PRBUFSIZ << 1) + 2];
  65. static char *__prbuf = __prpad + PRBUFSIZ + 1;
  66.  
  67.  
  68. /* __prebuf is set to the start of the output buffer passed to __printf() and
  69.  * is used by __p_nout() to calculate the number of characters output */
  70.  
  71. static char *__prebuf;
  72.  
  73.  
  74. #define P_FLAG0     0x0001    /* '-' */
  75. #define P_FLAG1     0x0002    /* '0' */
  76. #define P_FLAG2     0x0004    /* '+' */
  77. #define P_FLAG3     0x0008    /* ' ' */
  78. #define P_FLAG4     0x0010    /* '#' */
  79. #define P_FLAG5     0x0020    /* 'h' */
  80. #define P_FLAG6     0x0040    /* 'l' */
  81. #define P_FLAG7     0x0080    /* 'L' */
  82.  
  83. static int __prflag;
  84. static unsigned int __prwidth;    /* width */
  85. static int __prprec;        /* -1 = unspecified; precision */
  86. static char __prfc;        /* function character */
  87.  
  88. static signed char __prfnc[32] =    /* conversions */
  89. {
  90.   -1, -1,
  91.   1,                /* %c */
  92.   3,                /* %d */
  93.   9,                /* %eE */
  94.   8,                /* %f */
  95.   10,                /* %gG */
  96.   -1,
  97.   4,                /* %i */
  98.   -1, -1, -1, -1,
  99.   0,                /* %n */
  100.   5,                /* %o */
  101.   11,                /* %p */
  102.   -1, -1,
  103.   2,                /* %s */
  104.   -1,
  105.   6,                /* %u */
  106.   -1, -1,
  107.   7,                /* %xX */
  108.   -1, -1, -1, -1, -1, -1, -1, -1
  109. };
  110.  
  111. /* __prfn[] is the array of output functions called by __printf() -
  112.  * they return a pointer to the end of the string (which is *not*
  113.  * necessarily 0 terminated) */
  114.  
  115. static char *(*__prfn[]) (char *, va_list *) =
  116. {
  117.   __p_nout,            /* %n no. of characters output so far */
  118.     __p_char,            /* %c character */
  119.     __p_str,            /* %s string */
  120.     __p_sdec,            /* %d signed decimal */
  121.     __p_sdec,            /* %i signed decimal */
  122.     __p_uoct,            /* %o unsigned octal */
  123.     __p_udec,            /* %u unsigned decimal */
  124.     __p_uhex,            /* %xX unsigned hex */
  125.     __p_ffix,            /* %f fixed notation double */
  126.     __p_fexp,            /* %eE exponential notation double */
  127.     __p_fmin,            /* %gG minimised space notation double */
  128.     __p_ptr            /* %p unsigned hex value of pointer */
  129. };
  130.  
  131.  
  132. /* __printf() */
  133.  
  134. int
  135. __printf (char *buf, const char *format, va_list ap)
  136. {
  137.   register const char *s1 = format;
  138.   register char *s2 = buf;
  139.  
  140.   __prebuf = buf;        /* for __p_nout() */
  141.  
  142.   while (*s1)
  143.     {
  144.       if (*s1 != '%' || *++s1 == '%')    /* left to right evaluation */
  145.     {
  146.       *s2++ = *s1++;
  147.       continue;
  148.     }
  149.  
  150.       {                /* we now have a % conversion */
  151.     register int i;
  152.     char *s;
  153.  
  154. /* looking for "%[flags][width][.prec][size]function" */
  155.  
  156. /* set flags */
  157.  
  158.     __prflag = 0;
  159.       flag:
  160.     if (*s1 == '-')
  161.       {
  162.         __prflag |= P_FLAG0, s1++;
  163.         goto flag;
  164.       }
  165.     if (*s1 == '0')
  166.       {
  167.         __prflag |= P_FLAG1, s1++;
  168.         goto flag;
  169.       }
  170.     if (*s1 == '+')
  171.       {
  172.         __prflag |= P_FLAG2, s1++;
  173.         goto flag;
  174.       }
  175.     if (*s1 == ' ')
  176.       {
  177.         __prflag |= P_FLAG3, s1++;
  178.         goto flag;
  179.       }
  180.     if (*s1 == '#')
  181.       {
  182.         __prflag |= P_FLAG4, s1++;
  183.         goto flag;
  184.       }
  185.  
  186. /* set __prwidth */
  187.  
  188.     __prwidth = 0;
  189.     if (isdigit (*s1))
  190.       {
  191.         __prwidth = (unsigned int) strtoul (s1, &s, 0);
  192.         s1 = s;
  193.       }
  194.     else
  195.       {
  196.         if (*s1 == '*')
  197.           {
  198.         __prwidth = va_arg (ap, int);
  199.         s1++;
  200.           }
  201.       }
  202.     if (__prwidth > PRBUFSIZ)
  203.       __prwidth = PRBUFSIZ;
  204.  
  205. /* set __prprec */
  206.  
  207.     __prprec = -1;
  208.     if (*s1 == '.')
  209.       {
  210.         s1++;
  211.         if (isdigit (*s1))
  212.           {
  213.         __prprec = (int) strtol (s1, &s, 0);
  214.         s1 = s;
  215.           }
  216.         else
  217.           {
  218.         if (*s1 == '*')
  219.           {
  220.             __prprec = va_arg (ap, int);
  221.             s1++;
  222.           }
  223.           }
  224.       }
  225.  
  226. /* set size */
  227.  
  228.     if (*s1 == 'h')
  229.       __prflag |= P_FLAG5, s1++;
  230.     else if (*s1 == 'l')
  231.       __prflag |= P_FLAG6, s1++;
  232.     else if (*s1 == 'L')
  233.       __prflag |= P_FLAG7, s1++;
  234.  
  235. /* call appropriate output function */
  236.  
  237.     i = __prfnc[(_tolower (*s1) - 'a') & 31];
  238.  
  239.     if (i >= 0)
  240.       {
  241.         __prfc = *s1;
  242.         s2 = (*__prfn[i]) (s2, (va_list *) (&ap));
  243.       }
  244.  
  245.     s1++;
  246.       }
  247.     }
  248.  
  249.   *s2 = 0;
  250.  
  251.   return ((size_t) (s2 - buf));    /* number of characters output */
  252. }
  253.  
  254.  
  255. /* __prjust() */
  256.  
  257. /* __prjust() justifies the string at __prbuf according to __prwidth etc.
  258.  * it's argument is the *end* of the string at __prbuf - it returns the
  259.  * start of the justified string. */
  260.  
  261. static char *
  262. __prjust (register char *e)
  263. {
  264.   register char *s1, *s2;
  265.   register char p;
  266.  
  267.   s1 = __prbuf;
  268.  
  269.   p = (__prflag & P_FLAG1) ? '0' : ' ';
  270.  
  271.   if (__prflag & P_FLAG0)
  272.     {
  273.       s2 = s1 + __prwidth;
  274.       while (e < s2)
  275.     *e++ = ' ';
  276.       *e = 0;
  277.       return (s1);
  278.     }
  279.   else
  280.     {
  281.       if ((e -= __prwidth) < s1)
  282.     {
  283.       s2 = e;
  284.       while (e < s1)
  285.         *e++ = p;
  286.       return (s2);
  287.     }
  288.       return (s1);
  289.     }
  290. }
  291.  
  292. /* __prdec() */
  293.  
  294. /* __prdec() is a subroutine (called by __p_...() functions) that writes
  295.  * a decimal number <x> backwards from <e> towards <b>, digit by digit */
  296.  
  297. static char *
  298. __prdec (register char *b, register char *e, register unsigned int x)
  299. {
  300.   *e = 0;
  301.   do
  302.     {
  303.       *--e = (x % 10) + '0';
  304.       x /= 10;
  305.     }
  306.   while (x && e > b);
  307.  
  308.   return (e);
  309. }
  310.  
  311. /* __prexp() */
  312.  
  313. /* __prexp() normalises <x> to a number of the form n.nnnn...
  314.  * and stores the exponent in *<e> */
  315.  
  316. static double
  317. __prexp (register double x, register int *e)
  318. {
  319.   register int h;
  320.  
  321.   h = 0;
  322.  
  323.   if (x != 0)
  324.     {
  325.       if (x >= 10)
  326.     {
  327.       register double l = 0, m = 10;
  328.  
  329.       while (x >= m)
  330.         {
  331.           l = m, m *= 10;
  332.           h++;
  333.         }
  334.       if (l)
  335.         x /= l;
  336.     }
  337.       else
  338.     {
  339.       while (x < 1)
  340.         {
  341.           x *= 10;
  342.           h--;
  343.         }
  344.     }
  345.     }
  346.  
  347. /* x is now n.nnnn... */
  348.  
  349.   *e = h;
  350.   return (x);
  351. }
  352.  
  353.  
  354. /* __p_nout() */
  355.  
  356. static char *
  357. __p_nout (register char *s, register va_list * ap)    /* %n */
  358. {
  359.   if (__prflag & P_FLAG5)
  360.     *va_arg (*ap, short *) = (short) (s - __prebuf);
  361.   else if (__prflag & P_FLAG6)
  362.     *va_arg (*ap, long *) = (long) (s - __prebuf);
  363.   else
  364.     *va_arg (*ap, int *) = (int) (s - __prebuf);
  365.  
  366.   return (s);
  367. }
  368.  
  369. /* __p_char() */
  370.  
  371. static char *
  372. __p_char (register char *s, register va_list * ap)    /* %c */
  373. {
  374.   register char *b;
  375.  
  376.   if (!__prwidth)
  377.     *s++ = va_arg (*ap, char);
  378.   else
  379.     {
  380.       b = __prbuf;
  381.       *b++ = va_arg (*ap, char);
  382.       *b = 0;
  383.       b = __prjust (b);
  384.       while (*s = *b)
  385.     s++, b++;
  386.     }
  387.  
  388.   return (s);
  389. }
  390.  
  391. /* __p_str() */
  392.  
  393. static char *
  394. __p_str (register char *s, register va_list * ap)    /* %s */
  395. {
  396.   register char *_s;
  397.   register char *b, *e;
  398.   register int p;
  399.  
  400.   p = (__prprec < 0) ? 0 : __prprec;
  401.   if (p > PRBUFSIZ)
  402.     p = PRBUFSIZ;
  403.  
  404.   _s = va_arg (*ap, char *);
  405.  
  406. /* tolerance */
  407.  
  408.   if (!_s)
  409.     _s = __null;
  410.  
  411. /* fast output if no width specified */
  412.  
  413.   if (!__prwidth)
  414.     {
  415.       e = s + (p ? p : PRBUFSIZ);
  416.       while ((s < e) && (*s = *_s))
  417.     s++, _s++;
  418.       return (s);
  419.     }
  420.  
  421.   e = (b = __prbuf) + (p ? p : PRBUFSIZ);
  422.  
  423.   while (b < e && (*b = *_s))
  424.     b++, _s++;
  425.  
  426.   *b = 0;
  427.   b = __prjust (b);
  428.  
  429.   while (*s = *b)
  430.     s++, b++;
  431.  
  432.   return (s);
  433. }
  434.  
  435. /* __p_sdec() */
  436.  
  437. static char *
  438. __p_sdec (register char *s, register va_list * ap)    /* %d */
  439. {
  440.   register int x, n;
  441.   register char *b, *e;
  442.   register int p;
  443.  
  444.   p = (__prprec < 0) ? 0 : __prprec;
  445.   if (p > PRBUFSIZ - 2)
  446.     p = PRBUFSIZ - 2;
  447.  
  448.   if (__prflag & P_FLAG5)
  449.     n = (int) va_arg (*ap, short);
  450.   else if (__prflag & P_FLAG6)
  451.     n = (int) va_arg (*ap, long);
  452.   else
  453.     n = va_arg (*ap, int);
  454.  
  455.   x = (n < 0) ? (-n) : n;
  456.  
  457.   b = __prbuf;
  458.   e = b + PRBUFSIZ;
  459.  
  460.   if ((__prflag & P_FLAG2) || (n < 0))
  461.     *b++ = (n < 0) ? '-' : '+';
  462.   else if (__prflag & P_FLAG3)
  463.     *b++ = ' ';
  464.  
  465.   e = __prdec (b, e, (unsigned int) x);
  466.  
  467.   if (p)
  468.     {
  469.       x = p - strlen (e);
  470.       while (x > 0)
  471.     {
  472.       *b++ = '0';
  473.       x--;
  474.     }
  475.     }
  476.  
  477.   while (*b = *e)
  478.     b++, e++;
  479.  
  480.   if (!__prwidth)
  481.     b = __prbuf;
  482.   else
  483.     b = __prjust (b);
  484.  
  485.   while (*s = *b)
  486.     s++, b++;
  487.  
  488.   return (s);
  489. }
  490.  
  491. /* __p_uoct() */
  492.  
  493. static char *
  494. __p_uoct (register char *s, register va_list * ap)    /* %o */
  495. {
  496.   register unsigned int x, n;
  497.   register char *b, *e;
  498.   register int p;
  499.  
  500.   p = (__prprec < 0) ? 0 : __prprec;
  501.   if (p > PRBUFSIZ - 3)
  502.     p = PRBUFSIZ - 3;
  503.  
  504.   if (__prflag & P_FLAG5)
  505.     n = (unsigned int) va_arg (*ap, unsigned short);
  506.   else if (__prflag & P_FLAG6)
  507.     n = (unsigned int) va_arg (*ap, unsigned long);
  508.   else
  509.     n = va_arg (*ap, unsigned int);
  510.  
  511.   x = n;
  512.  
  513.   b = __prbuf;
  514.   *(e = (b + PRBUFSIZ)) = 0;
  515.  
  516.   do
  517.     {
  518.       *--e = (x & 7) + '0';
  519.       x >>= 3;
  520.     }
  521.   while (b < e && x);
  522.  
  523.   if (__prflag & P_FLAG2)
  524.     *b++ = '+';
  525.   else if (__prflag & P_FLAG3)
  526.     *b++ = ' ';
  527.  
  528.   if (__prflag & P_FLAG4)
  529.     *b++ = '0';
  530.  
  531.   if (p)
  532.     {
  533.       x = p - strlen (e);
  534.       while (x > 0)
  535.     {
  536.       *b++ = '0';
  537.       x--;
  538.     }
  539.     }
  540.  
  541.   while (*b = *e)
  542.     b++, e++;
  543.  
  544.   if (!__prwidth)
  545.     b = __prbuf;
  546.   else
  547.     b = __prjust (b);
  548.  
  549.   while (*s = *b)
  550.     s++, b++;
  551.  
  552.   return (s);
  553. }
  554.  
  555. /* __p_udec() */
  556.  
  557. static char *
  558. __p_udec (register char *s, register va_list * ap)    /* %u */
  559. {
  560.   register unsigned int x, n;
  561.   register char *b, *e;
  562.   register int p;
  563.  
  564.   p = (__prprec < 0) ? 0 : __prprec;
  565.   if (p > PRBUFSIZ - 2)
  566.     p = PRBUFSIZ - 2;
  567.  
  568.   if (__prflag & P_FLAG5)
  569.     n = (unsigned int) va_arg (*ap, unsigned short);
  570.   else if (__prflag & P_FLAG6)
  571.     n = (unsigned int) va_arg (*ap, unsigned long);
  572.   else
  573.     n = va_arg (*ap, unsigned int);
  574.  
  575.   x = n;
  576.  
  577.   b = __prbuf;
  578.   e = b + PRBUFSIZ;
  579.  
  580.   if (__prflag & P_FLAG2)
  581.     *b++ = '+';
  582.   else if (__prflag & P_FLAG3)
  583.     *b++ = ' ';
  584.  
  585.   e = __prdec (b, e, x);
  586.  
  587.   if (p)
  588.     {
  589.       x = p - strlen (e);
  590.       while (x > 0)
  591.     {
  592.       *b++ = '0';
  593.       x--;
  594.     }
  595.     }
  596.  
  597.   while (*b = *e)
  598.     b++, e++;
  599.  
  600.   if (!__prwidth)
  601.     b = __prbuf;
  602.   else
  603.     b = __prjust (b);
  604.  
  605.   while (*s = *b)
  606.     s++, b++;
  607.  
  608.   return (s);
  609. }
  610.  
  611. /* __p_uhex() */
  612.  
  613. static char *
  614. __p_uhex (register char *s, register va_list * ap)    /* %xX */
  615. {
  616.   register unsigned int x, n;
  617.   register char *b, *e;
  618.   register char *hex;
  619.   register int p;
  620.  
  621.   p = (__prprec < 0) ? 0 : __prprec;
  622.   if (p > PRBUFSIZ - 4)
  623.     p = PRBUFSIZ - 4;
  624.  
  625.   hex = (__prfc == 'X') ? "0123456789ABCDEF" : "0123456789abcdef";
  626.  
  627.   if (__prflag & P_FLAG5)
  628.     n = (unsigned int) va_arg (*ap, unsigned short);
  629.   else if (__prflag & P_FLAG6)
  630.     n = (unsigned int) va_arg (*ap, unsigned long);
  631.   else
  632.     n = va_arg (*ap, unsigned int);
  633.  
  634.   x = n;
  635.  
  636.   b = __prbuf;
  637.   *(e = (b + PRBUFSIZ)) = 0;
  638.  
  639.   do
  640.     {
  641.       *--e = hex[x & 15];
  642.       x >>= 4;
  643.     }
  644.   while (b < e && x);
  645.  
  646.   if (__prflag & P_FLAG2)
  647.     *b++ = '+';
  648.   else if (__prflag & P_FLAG3)
  649.     *b++ = ' ';
  650.  
  651.   if ((__prflag & P_FLAG4) && n)
  652.     {
  653.       *b++ = '0';
  654.       *b++ = 'x';
  655.     }
  656.  
  657.   if (p)
  658.     {
  659.       x = p - strlen (e);
  660.       while (x > 0)
  661.     {
  662.       *b++ = '0';
  663.       x--;
  664.     }
  665.     }
  666.  
  667.   while (*b = *e)
  668.     b++, e++;
  669.  
  670.   if (!__prwidth)
  671.     b = __prbuf;
  672.   else
  673.     b = __prjust (b);
  674.  
  675.   while (*s = *b)
  676.     s++, b++;
  677.  
  678.   return (s);
  679. }
  680.  
  681. /* __p_ffix() */
  682.  
  683. static char *
  684. __p_ffix (register char *s, register va_list * ap)    /* %f */
  685. {
  686.   const double point = POINT;
  687.   const double err = FPERR;
  688.   register double x, n, w;
  689.   register unsigned int i;
  690.   int h;
  691.   register int p, m;
  692.   register char *b, *e;
  693.  
  694.   if (__prflag & P_FLAG7)
  695.     n = (double) va_arg (*ap, long double);
  696.   else
  697.     n = va_arg (*ap, double);
  698.  
  699.   b = __prbuf;
  700.   e = b + PRBUFSIZ;
  701.   if ((__prflag & P_FLAG2) || (n < 0))
  702.     *b++ = (n < 0) ? '-' : '+';
  703.   else if (__prflag & P_FLAG3)
  704.     *b++ = ' ';
  705.  
  706.   x = (n < 0) ? (-n) : n;
  707.   x = __prexp (x, &h);
  708.   w = 1;
  709.   while (h < 0)
  710.     {
  711.       w *= 10;
  712.       h++;
  713.     }
  714.   x /= w;
  715.  
  716. /* integer part - ensure at least 1 digit */
  717.  
  718.   do
  719.     {
  720.       x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  721.       *b++ = i + '0';
  722.       h--;
  723.     }
  724.   while (b < e && h >= 0 && x > err);
  725.   while (b < e && h >= 0)
  726.     {
  727.       *b++ = '0';
  728.       h--;
  729.     }
  730.  
  731.   m = (__prprec < 0) ? 6 : __prprec;
  732.   p = (m > MAXPREC) ? MAXPREC : m;
  733.   m -= p;
  734.  
  735. /* fractional part */
  736.  
  737.   if (p || (__prflag & P_FLAG4))
  738.     {
  739.       if (b < e)
  740.     *b++ = '.';
  741.  
  742.       while (b < e && p && x > err)
  743.     {
  744.       x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  745.       *b++ = i + '0';
  746.       p--;
  747.     }
  748.  
  749.       while (p && b < e)
  750.     {
  751.       *b++ = '0';
  752.       p--;
  753.     }
  754.       while (m && b < e)
  755.     {
  756.       *b++ = '0';
  757.       m--;
  758.     }
  759.     }
  760.  
  761.   *b = 0;
  762.  
  763.   if (!__prwidth)
  764.     b = __prbuf;
  765.   else
  766.     b = __prjust (b);
  767.  
  768.   while (*s = *b)
  769.     s++, b++;
  770.  
  771.   return (s);
  772. }
  773.  
  774. /* __p_fexp() */
  775.  
  776. static char *
  777. __p_fexp (register char *s, register va_list * ap)    /* %eE */
  778. {
  779.   const double point = POINT;
  780.   const double err = FPERR;
  781.   register double x, n;
  782.   register unsigned int i;
  783.   int h;
  784.   register int p, m;
  785.   register char *b, *e;
  786.  
  787.   if (__prflag & P_FLAG7)
  788.     n = (double) va_arg (*ap, long double);
  789.   else
  790.     n = va_arg (*ap, double);
  791.  
  792.   b = __prbuf;
  793.   e = b + PRBUFSIZ;
  794.   if ((__prflag & P_FLAG2) || (n < 0))
  795.     *b++ = (n < 0) ? '-' : '+';
  796.   else if (__prflag & P_FLAG3)
  797.     *b++ = ' ';
  798.  
  799.   x = (n < 0) ? (-n) : n;
  800.   x = __prexp (x, &h);
  801.  
  802.   m = (__prprec < 0) ? 6 : __prprec;
  803.   p = (m > MAXPREC) ? MAXPREC : m;
  804.   m -= p;
  805.  
  806. /* 1 digit before decimal point */
  807.  
  808.   x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  809.   *b++ = i + '0';
  810.  
  811. /* fractional part */
  812.  
  813.   if (p || (__prflag & P_FLAG4))
  814.     {
  815.       if (b < e)
  816.     *b++ = '.';
  817.  
  818.       while (b < e && p && x > err)
  819.     {
  820.       x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  821.       *b++ = i + '0';
  822.       p--;
  823.     }
  824.  
  825.       while (p && b < e)
  826.     {
  827.       *b++ = '0';
  828.       p--;
  829.     }
  830.       while (m && b < e)
  831.     {
  832.       *b++ = '0';
  833.       m--;
  834.     }
  835.     }
  836.  
  837. /* exponent */
  838.  
  839.   if (b < e)
  840.     *b++ = __prfc;
  841.   if (b < e)
  842.     *b++ = (h < 0) ? '-' : '+';
  843.  
  844.   if (b < e)
  845.     e = __prdec (b, e, (h < 0) ? (unsigned int) (-h) : (unsigned int) h);
  846.  
  847.   while (*b = *e)
  848.     b++, e++;
  849.  
  850.   if (!__prwidth)
  851.     b = __prbuf;
  852.   else
  853.     b = __prjust (b);
  854.  
  855.   while (*s = *b)
  856.     s++, b++;
  857.  
  858.   return (s);
  859. }
  860.  
  861. /* __p_fmin() */
  862.  
  863. static char *
  864. __p_fmin (register char *s, register va_list * ap)    /* %gG */
  865. {
  866.   const double point = POINT;
  867.   const double err = FPERR;
  868.   register double x, n, w;
  869.   register unsigned int i;
  870.   int h;
  871.   register int p, m;
  872.   register char *b, *e;
  873.  
  874.   if (__prflag & P_FLAG7)
  875.     n = (double) va_arg (*ap, long double);
  876.   else
  877.     n = va_arg (*ap, double);
  878.  
  879.   b = __prbuf;
  880.   e = b + PRBUFSIZ;
  881.   if ((__prflag & P_FLAG2) || (n < 0))
  882.     *b++ = (n < 0) ? '-' : '+';
  883.   else if (__prflag & P_FLAG3)
  884.     *b++ = ' ';
  885.  
  886. /* %gG count significant figures of precision, not decimal places.
  887.  * For %e we decrement the precision (for the digit before the decimal point).
  888.  * For %f we subtract the exponent from the precision. */
  889.  
  890.   m = (__prprec < 0) ? 6 : __prprec;
  891.   p = (m > MAXPREC) ? MAXPREC : m;
  892.   m -= p;
  893.  
  894.   x = (n < 0) ? (-n) : n;
  895.   x = __prexp (x, &h);
  896.  
  897. /* "The style used depends on the value converted; style %e will be used
  898.  * only if the exponent resulting from the conversion is less than -4 or
  899.  * greater than the precision." - ANSI X3J11 */
  900.  
  901.   if (h < -4 || h > p)        /* %e */
  902.     {
  903.       if (p)
  904.     p--;            /* just in case */
  905.  
  906. /* 1 digit before decimal point */
  907.  
  908.       x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  909.       *b++ = i + '0';
  910.  
  911. /* fractional part */
  912.  
  913.       if (p || (__prflag & P_FLAG4))
  914.     {
  915.       if (b < e)
  916.         *b++ = '.';
  917.  
  918.       while (b < e && p && x > err)
  919.         {
  920.           x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  921.           *b++ = i + '0';
  922.           p--;
  923.         }
  924.  
  925.       if (__prflag & P_FLAG4)
  926.         {
  927.           while (p && b < e)
  928.         {
  929.           *b++ = '0';
  930.           p--;
  931.         }
  932.           while (m && b < e)
  933.         {
  934.           *b++ = '0';
  935.           m--;
  936.         }
  937.         }
  938.       else if (b < e)    /* waste trailing 0s */
  939.         {
  940.           while (*--b == '0');
  941.           b++;
  942.           if (*--b != '.')
  943.         b++;
  944.         }
  945.     }
  946.  
  947. /* exponent */
  948.  
  949.       if (b < e)
  950.     *b++ = __prfc - ('g' - 'e');
  951.       if (b < e)
  952.     *b++ = (h < 0) ? '-' : '+';
  953.  
  954.       if (b < e)
  955.     e = __prdec (b, e, (h < 0) ? (unsigned int) (-h) : (unsigned int) h);
  956.  
  957.       while (*b = *e)
  958.     b++, e++;
  959.     }
  960.   else
  961.     /* %f */
  962.     {
  963.       w = 1;
  964.       while (h < 0)
  965.     {
  966.       w *= 10;
  967.       h++;
  968.     }
  969.       x /= w;
  970.  
  971.       p -= h;
  972.  
  973. /* integer part - ensure at least 1 digit */
  974.  
  975.       do
  976.     {
  977.       x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  978.       *b++ = i + '0';
  979.       h--;
  980.     }
  981.       while (b < e && h >= 0 && x > err);
  982.       while (b < e && h >= 0)
  983.     {
  984.       *b++ = '0';
  985.       h--;
  986.     }
  987.  
  988. /* fractional part */
  989.  
  990.       if (p || (__prflag & P_FLAG4))
  991.     {
  992.       if (b < e)
  993.         *b++ = '.';
  994.  
  995.       while (b < e && p && x > err)
  996.         {
  997.           x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  998.           *b++ = i + '0';
  999.           p--;
  1000.         }
  1001.  
  1002.       if (__prflag & P_FLAG4)
  1003.         {
  1004.           while (p && (b < e))
  1005.         {
  1006.           *b++ = '0';
  1007.           p--;
  1008.         }
  1009.           while (m && (b < e))
  1010.         {
  1011.           *b++ = '0';
  1012.           m--;
  1013.         }
  1014.         }
  1015.       else if (b < e)    /* waste trailing 0s */
  1016.         {
  1017.           while (*--b == '0');
  1018.           b++;
  1019.           if (*--b != '.')
  1020.         b++;
  1021.         }
  1022.     }
  1023.  
  1024.       *b = 0;
  1025.     }
  1026.  
  1027.   if (!__prwidth)
  1028.     b = __prbuf;
  1029.   else
  1030.     b = __prjust (b);
  1031.  
  1032.   while (*s = *b)
  1033.     s++, b++;
  1034.  
  1035.   return (s);
  1036. }
  1037.  
  1038. /* __p_ptr() */
  1039.  
  1040. static char *
  1041. __p_ptr (register char *s, register va_list * ap)    /* %p */
  1042. {
  1043.   __prflag |= P_FLAG4;
  1044.   return (__p_uhex (s, ap));
  1045. }
  1046.