home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 1 / RISC_DISC_1.iso / pd_share / code / unixlib / !UnixLib / src / stdio / c / print < prev    next >
Encoding:
Text File  |  1994-09-30  |  18.2 KB  |  1,053 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.         int tmpwidth;
  199.         tmpwidth = va_arg (ap, int);
  200.         if (tmpwidth < 0)
  201.           {
  202.             __prflag |= P_FLAG0;
  203.             tmpwidth = -tmpwidth;
  204.           }
  205.         __prwidth = tmpwidth;
  206.         s1++;
  207.           }
  208.       }
  209.     if (__prwidth > PRBUFSIZ)
  210.       __prwidth = PRBUFSIZ;
  211.  
  212. /* set __prprec */
  213.  
  214.     __prprec = -1;
  215.     if (*s1 == '.')
  216.       {
  217.         s1++;
  218.         if (isdigit (*s1))
  219.           {
  220.         __prprec = (int) strtol (s1, &s, 0);
  221.         s1 = s;
  222.           }
  223.         else
  224.           {
  225.         if (*s1 == '*')
  226.           {
  227.             __prprec = va_arg (ap, int);
  228.             s1++;
  229.           }
  230.           }
  231.       }
  232.  
  233. /* set size */
  234.  
  235.     if (*s1 == 'h')
  236.       __prflag |= P_FLAG5, s1++;
  237.     else if (*s1 == 'l')
  238.       __prflag |= P_FLAG6, s1++;
  239.     else if (*s1 == 'L')
  240.       __prflag |= P_FLAG7, s1++;
  241.  
  242. /* call appropriate output function */
  243.  
  244.     i = __prfnc[(_tolower (*s1) - 'a') & 31];
  245.  
  246.     if (i >= 0)
  247.       {
  248.         __prfc = *s1;
  249.         s2 = (*__prfn[i]) (s2, (va_list *) (&ap));
  250.       }
  251.  
  252.     s1++;
  253.       }
  254.     }
  255.  
  256.   *s2 = 0;
  257.  
  258.   return ((size_t) (s2 - buf));    /* number of characters output */
  259. }
  260.  
  261.  
  262. /* __prjust() */
  263.  
  264. /* __prjust() justifies the string at __prbuf according to __prwidth etc.
  265.  * it's argument is the *end* of the string at __prbuf - it returns the
  266.  * start of the justified string. */
  267.  
  268. static char *
  269. __prjust (register char *e)
  270. {
  271.   register char *s1, *s2;
  272.   register char p;
  273.  
  274.   s1 = __prbuf;
  275.  
  276.   p = (__prflag & P_FLAG1) ? '0' : ' ';
  277.  
  278.   if (__prflag & P_FLAG0)
  279.     {
  280.       s2 = s1 + __prwidth;
  281.       while (e < s2)
  282.     *e++ = ' ';
  283.       *e = 0;
  284.       return (s1);
  285.     }
  286.   else
  287.     {
  288.       if ((e -= __prwidth) < s1)
  289.     {
  290.       s2 = e;
  291.       while (e < s1)
  292.         *e++ = p;
  293.       return (s2);
  294.     }
  295.       return (s1);
  296.     }
  297. }
  298.  
  299. /* __prdec() */
  300.  
  301. /* __prdec() is a subroutine (called by __p_...() functions) that writes
  302.  * a decimal number <x> backwards from <e> towards <b>, digit by digit */
  303.  
  304. static char *
  305. __prdec (register char *b, register char *e, register unsigned int x)
  306. {
  307.   *e = 0;
  308.   do
  309.     {
  310.       *--e = (x % 10) + '0';
  311.       x /= 10;
  312.     }
  313.   while (x && e > b);
  314.  
  315.   return (e);
  316. }
  317.  
  318. /* __prexp() */
  319.  
  320. /* __prexp() normalises <x> to a number of the form n.nnnn...
  321.  * and stores the exponent in *<e> */
  322.  
  323. static double
  324. __prexp (register double x, register int *e)
  325. {
  326.   register int h;
  327.  
  328.   h = 0;
  329.  
  330.   if (x != 0)
  331.     {
  332.       if (x >= 10)
  333.     {
  334.       register double l = 0, m = 10;
  335.  
  336.       while (x >= m)
  337.         {
  338.           l = m, m *= 10;
  339.           h++;
  340.         }
  341.       if (l)
  342.         x /= l;
  343.     }
  344.       else
  345.     {
  346.       while (x < 1)
  347.         {
  348.           x *= 10;
  349.           h--;
  350.         }
  351.     }
  352.     }
  353.  
  354. /* x is now n.nnnn... */
  355.  
  356.   *e = h;
  357.   return (x);
  358. }
  359.  
  360.  
  361. /* __p_nout() */
  362.  
  363. static char *
  364. __p_nout (register char *s, register va_list * ap)    /* %n */
  365. {
  366.   if (__prflag & P_FLAG5)
  367.     *va_arg (*ap, short *) = (short) (s - __prebuf);
  368.   else if (__prflag & P_FLAG6)
  369.     *va_arg (*ap, long *) = (long) (s - __prebuf);
  370.   else
  371.     *va_arg (*ap, int *) = (int) (s - __prebuf);
  372.  
  373.   return (s);
  374. }
  375.  
  376. /* __p_char() */
  377.  
  378. static char *
  379. __p_char (register char *s, register va_list * ap)    /* %c */
  380. {
  381.   register char *b;
  382.  
  383.   if (!__prwidth)
  384.     *s++ = va_arg (*ap, char);
  385.   else
  386.     {
  387.       b = __prbuf;
  388.       *b++ = va_arg (*ap, char);
  389.       *b = 0;
  390.       b = __prjust (b);
  391.       while (*s = *b)
  392.     s++, b++;
  393.     }
  394.  
  395.   return (s);
  396. }
  397.  
  398. /* __p_str() */
  399.  
  400. static char *
  401. __p_str (register char *s, register va_list * ap)    /* %s */
  402. {
  403.   register char *_s;
  404.   register char *b, *e;
  405.   register int p;
  406.  
  407.   p = (__prprec < 0) ? 0 : __prprec;
  408.   if (p > PRBUFSIZ)
  409.     p = PRBUFSIZ;
  410.  
  411.   _s = va_arg (*ap, char *);
  412.  
  413. /* tolerance */
  414.  
  415.   if (!_s)
  416.     _s = __null;
  417.  
  418. /* fast output if no width specified */
  419.  
  420.   if (!__prwidth)
  421.     {
  422.       e = s + (p ? p : PRBUFSIZ);
  423.       while ((s < e) && (*s = *_s))
  424.     s++, _s++;
  425.       return (s);
  426.     }
  427.  
  428.   e = (b = __prbuf) + (p ? p : PRBUFSIZ);
  429.  
  430.   while (b < e && (*b = *_s))
  431.     b++, _s++;
  432.  
  433.   *b = 0;
  434.   b = __prjust (b);
  435.  
  436.   while (*s = *b)
  437.     s++, b++;
  438.  
  439.   return (s);
  440. }
  441.  
  442. /* __p_sdec() */
  443.  
  444. static char *
  445. __p_sdec (register char *s, register va_list * ap)    /* %d */
  446. {
  447.   register int x, n;
  448.   register char *b, *e;
  449.   register int p;
  450.  
  451.   p = (__prprec < 0) ? 0 : __prprec;
  452.   if (p > PRBUFSIZ - 2)
  453.     p = PRBUFSIZ - 2;
  454.  
  455.   if (__prflag & P_FLAG5)
  456.     n = (int) va_arg (*ap, short);
  457.   else if (__prflag & P_FLAG6)
  458.     n = (int) va_arg (*ap, long);
  459.   else
  460.     n = va_arg (*ap, int);
  461.  
  462.   x = (n < 0) ? (-n) : n;
  463.  
  464.   b = __prbuf;
  465.   e = b + PRBUFSIZ;
  466.  
  467.   if ((__prflag & P_FLAG2) || (n < 0))
  468.     *b++ = (n < 0) ? '-' : '+';
  469.   else if (__prflag & P_FLAG3)
  470.     *b++ = ' ';
  471.  
  472.   e = __prdec (b, e, (unsigned int) x);
  473.  
  474.   if (p)
  475.     {
  476.       x = p - strlen (e);
  477.       while (x > 0)
  478.     {
  479.       *b++ = '0';
  480.       x--;
  481.     }
  482.     }
  483.  
  484.   while (*b = *e)
  485.     b++, e++;
  486.  
  487.   if (!__prwidth)
  488.     b = __prbuf;
  489.   else
  490.     b = __prjust (b);
  491.  
  492.   while (*s = *b)
  493.     s++, b++;
  494.  
  495.   return (s);
  496. }
  497.  
  498. /* __p_uoct() */
  499.  
  500. static char *
  501. __p_uoct (register char *s, register va_list * ap)    /* %o */
  502. {
  503.   register unsigned int x, n;
  504.   register char *b, *e;
  505.   register int p;
  506.  
  507.   p = (__prprec < 0) ? 0 : __prprec;
  508.   if (p > PRBUFSIZ - 3)
  509.     p = PRBUFSIZ - 3;
  510.  
  511.   if (__prflag & P_FLAG5)
  512.     n = (unsigned int) va_arg (*ap, unsigned short);
  513.   else if (__prflag & P_FLAG6)
  514.     n = (unsigned int) va_arg (*ap, unsigned long);
  515.   else
  516.     n = va_arg (*ap, unsigned int);
  517.  
  518.   x = n;
  519.  
  520.   b = __prbuf;
  521.   *(e = (b + PRBUFSIZ)) = 0;
  522.  
  523.   do
  524.     {
  525.       *--e = (x & 7) + '0';
  526.       x >>= 3;
  527.     }
  528.   while (b < e && x);
  529.  
  530.   if (__prflag & P_FLAG2)
  531.     *b++ = '+';
  532.   else if (__prflag & P_FLAG3)
  533.     *b++ = ' ';
  534.  
  535.   if (__prflag & P_FLAG4)
  536.     *b++ = '0';
  537.  
  538.   if (p)
  539.     {
  540.       x = p - strlen (e);
  541.       while (x > 0)
  542.     {
  543.       *b++ = '0';
  544.       x--;
  545.     }
  546.     }
  547.  
  548.   while (*b = *e)
  549.     b++, e++;
  550.  
  551.   if (!__prwidth)
  552.     b = __prbuf;
  553.   else
  554.     b = __prjust (b);
  555.  
  556.   while (*s = *b)
  557.     s++, b++;
  558.  
  559.   return (s);
  560. }
  561.  
  562. /* __p_udec() */
  563.  
  564. static char *
  565. __p_udec (register char *s, register va_list * ap)    /* %u */
  566. {
  567.   register unsigned int x, n;
  568.   register char *b, *e;
  569.   register int p;
  570.  
  571.   p = (__prprec < 0) ? 0 : __prprec;
  572.   if (p > PRBUFSIZ - 2)
  573.     p = PRBUFSIZ - 2;
  574.  
  575.   if (__prflag & P_FLAG5)
  576.     n = (unsigned int) va_arg (*ap, unsigned short);
  577.   else if (__prflag & P_FLAG6)
  578.     n = (unsigned int) va_arg (*ap, unsigned long);
  579.   else
  580.     n = va_arg (*ap, unsigned int);
  581.  
  582.   x = n;
  583.  
  584.   b = __prbuf;
  585.   e = b + PRBUFSIZ;
  586.  
  587.   if (__prflag & P_FLAG2)
  588.     *b++ = '+';
  589.   else if (__prflag & P_FLAG3)
  590.     *b++ = ' ';
  591.  
  592.   e = __prdec (b, e, x);
  593.  
  594.   if (p)
  595.     {
  596.       x = p - strlen (e);
  597.       while (x > 0)
  598.     {
  599.       *b++ = '0';
  600.       x--;
  601.     }
  602.     }
  603.  
  604.   while (*b = *e)
  605.     b++, e++;
  606.  
  607.   if (!__prwidth)
  608.     b = __prbuf;
  609.   else
  610.     b = __prjust (b);
  611.  
  612.   while (*s = *b)
  613.     s++, b++;
  614.  
  615.   return (s);
  616. }
  617.  
  618. /* __p_uhex() */
  619.  
  620. static char *
  621. __p_uhex (register char *s, register va_list * ap)    /* %xX */
  622. {
  623.   register unsigned int x, n;
  624.   register char *b, *e;
  625.   register char *hex;
  626.   register int p;
  627.  
  628.   p = (__prprec < 0) ? 0 : __prprec;
  629.   if (p > PRBUFSIZ - 4)
  630.     p = PRBUFSIZ - 4;
  631.  
  632.   hex = (__prfc == 'X') ? "0123456789ABCDEF" : "0123456789abcdef";
  633.  
  634.   if (__prflag & P_FLAG5)
  635.     n = (unsigned int) va_arg (*ap, unsigned short);
  636.   else if (__prflag & P_FLAG6)
  637.     n = (unsigned int) va_arg (*ap, unsigned long);
  638.   else
  639.     n = va_arg (*ap, unsigned int);
  640.  
  641.   x = n;
  642.  
  643.   b = __prbuf;
  644.   *(e = (b + PRBUFSIZ)) = 0;
  645.  
  646.   do
  647.     {
  648.       *--e = hex[x & 15];
  649.       x >>= 4;
  650.     }
  651.   while (b < e && x);
  652.  
  653.   if (__prflag & P_FLAG2)
  654.     *b++ = '+';
  655.   else if (__prflag & P_FLAG3)
  656.     *b++ = ' ';
  657.  
  658.   if ((__prflag & P_FLAG4) && n)
  659.     {
  660.       *b++ = '0';
  661.       *b++ = 'x';
  662.     }
  663.  
  664.   if (p)
  665.     {
  666.       x = p - strlen (e);
  667.       while (x > 0)
  668.     {
  669.       *b++ = '0';
  670.       x--;
  671.     }
  672.     }
  673.  
  674.   while (*b = *e)
  675.     b++, e++;
  676.  
  677.   if (!__prwidth)
  678.     b = __prbuf;
  679.   else
  680.     b = __prjust (b);
  681.  
  682.   while (*s = *b)
  683.     s++, b++;
  684.  
  685.   return (s);
  686. }
  687.  
  688. /* __p_ffix() */
  689.  
  690. static char *
  691. __p_ffix (register char *s, register va_list * ap)    /* %f */
  692. {
  693.   const double point = POINT;
  694.   const double err = FPERR;
  695.   register double x, n, w;
  696.   register unsigned int i;
  697.   int h;
  698.   register int p, m;
  699.   register char *b, *e;
  700.  
  701.   if (__prflag & P_FLAG7)
  702.     n = (double) va_arg (*ap, long double);
  703.   else
  704.     n = va_arg (*ap, double);
  705.  
  706.   b = __prbuf;
  707.   e = b + PRBUFSIZ;
  708.   if ((__prflag & P_FLAG2) || (n < 0))
  709.     *b++ = (n < 0) ? '-' : '+';
  710.   else if (__prflag & P_FLAG3)
  711.     *b++ = ' ';
  712.  
  713.   x = (n < 0) ? (-n) : n;
  714.   x = __prexp (x, &h);
  715.   w = 1;
  716.   while (h < 0)
  717.     {
  718.       w *= 10;
  719.       h++;
  720.     }
  721.   x /= w;
  722.  
  723. /* integer part - ensure at least 1 digit */
  724.  
  725.   do
  726.     {
  727.       x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  728.       *b++ = i + '0';
  729.       h--;
  730.     }
  731.   while (b < e && h >= 0 && x > err);
  732.   while (b < e && h >= 0)
  733.     {
  734.       *b++ = '0';
  735.       h--;
  736.     }
  737.  
  738.   m = (__prprec < 0) ? 6 : __prprec;
  739.   p = (m > MAXPREC) ? MAXPREC : m;
  740.   m -= p;
  741.  
  742. /* fractional part */
  743.  
  744.   if (p || (__prflag & P_FLAG4))
  745.     {
  746.       if (b < e)
  747.     *b++ = '.';
  748.  
  749.       while (b < e && p && x > err)
  750.     {
  751.       x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  752.       *b++ = i + '0';
  753.       p--;
  754.     }
  755.  
  756.       while (p && b < e)
  757.     {
  758.       *b++ = '0';
  759.       p--;
  760.     }
  761.       while (m && b < e)
  762.     {
  763.       *b++ = '0';
  764.       m--;
  765.     }
  766.     }
  767.  
  768.   *b = 0;
  769.  
  770.   if (!__prwidth)
  771.     b = __prbuf;
  772.   else
  773.     b = __prjust (b);
  774.  
  775.   while (*s = *b)
  776.     s++, b++;
  777.  
  778.   return (s);
  779. }
  780.  
  781. /* __p_fexp() */
  782.  
  783. static char *
  784. __p_fexp (register char *s, register va_list * ap)    /* %eE */
  785. {
  786.   const double point = POINT;
  787.   const double err = FPERR;
  788.   register double x, n;
  789.   register unsigned int i;
  790.   int h;
  791.   register int p, m;
  792.   register char *b, *e;
  793.  
  794.   if (__prflag & P_FLAG7)
  795.     n = (double) va_arg (*ap, long double);
  796.   else
  797.     n = va_arg (*ap, double);
  798.  
  799.   b = __prbuf;
  800.   e = b + PRBUFSIZ;
  801.   if ((__prflag & P_FLAG2) || (n < 0))
  802.     *b++ = (n < 0) ? '-' : '+';
  803.   else if (__prflag & P_FLAG3)
  804.     *b++ = ' ';
  805.  
  806.   x = (n < 0) ? (-n) : n;
  807.   x = __prexp (x, &h);
  808.  
  809.   m = (__prprec < 0) ? 6 : __prprec;
  810.   p = (m > MAXPREC) ? MAXPREC : m;
  811.   m -= p;
  812.  
  813. /* 1 digit before decimal point */
  814.  
  815.   x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  816.   *b++ = i + '0';
  817.  
  818. /* fractional part */
  819.  
  820.   if (p || (__prflag & P_FLAG4))
  821.     {
  822.       if (b < e)
  823.     *b++ = '.';
  824.  
  825.       while (b < e && p && x > err)
  826.     {
  827.       x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  828.       *b++ = i + '0';
  829.       p--;
  830.     }
  831.  
  832.       while (p && b < e)
  833.     {
  834.       *b++ = '0';
  835.       p--;
  836.     }
  837.       while (m && b < e)
  838.     {
  839.       *b++ = '0';
  840.       m--;
  841.     }
  842.     }
  843.  
  844. /* exponent */
  845.  
  846.   if (b < e)
  847.     *b++ = __prfc;
  848.   if (b < e)
  849.     *b++ = (h < 0) ? '-' : '+';
  850.  
  851.   if (b < e)
  852.     e = __prdec (b, e, (h < 0) ? (unsigned int) (-h) : (unsigned int) h);
  853.  
  854.   while (*b = *e)
  855.     b++, e++;
  856.  
  857.   if (!__prwidth)
  858.     b = __prbuf;
  859.   else
  860.     b = __prjust (b);
  861.  
  862.   while (*s = *b)
  863.     s++, b++;
  864.  
  865.   return (s);
  866. }
  867.  
  868. /* __p_fmin() */
  869.  
  870. static char *
  871. __p_fmin (register char *s, register va_list * ap)    /* %gG */
  872. {
  873.   const double point = POINT;
  874.   const double err = FPERR;
  875.   register double x, n, w;
  876.   register unsigned int i;
  877.   int h;
  878.   register int p, m;
  879.   register char *b, *e;
  880.  
  881.   if (__prflag & P_FLAG7)
  882.     n = (double) va_arg (*ap, long double);
  883.   else
  884.     n = va_arg (*ap, double);
  885.  
  886.   b = __prbuf;
  887.   e = b + PRBUFSIZ;
  888.   if ((__prflag & P_FLAG2) || (n < 0))
  889.     *b++ = (n < 0) ? '-' : '+';
  890.   else if (__prflag & P_FLAG3)
  891.     *b++ = ' ';
  892.  
  893. /* %gG count significant figures of precision, not decimal places.
  894.  * For %e we decrement the precision (for the digit before the decimal point).
  895.  * For %f we subtract the exponent from the precision. */
  896.  
  897.   m = (__prprec < 0) ? 6 : __prprec;
  898.   p = (m > MAXPREC) ? MAXPREC : m;
  899.   m -= p;
  900.  
  901.   x = (n < 0) ? (-n) : n;
  902.   x = __prexp (x, &h);
  903.  
  904. /* "The style used depends on the value converted; style %e will be used
  905.  * only if the exponent resulting from the conversion is less than -4 or
  906.  * greater than the precision." - ANSI X3J11 */
  907.  
  908.   if (h < -4 || h > p)        /* %e */
  909.     {
  910.       if (p)
  911.     p--;            /* just in case */
  912.  
  913. /* 1 digit before decimal point */
  914.  
  915.       x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  916.       *b++ = i + '0';
  917.  
  918. /* fractional part */
  919.  
  920.       if (p || (__prflag & P_FLAG4))
  921.     {
  922.       if (b < e)
  923.         *b++ = '.';
  924.  
  925.       while (b < e && p && x > err)
  926.         {
  927.           x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  928.           *b++ = i + '0';
  929.           p--;
  930.         }
  931.  
  932.       if (__prflag & P_FLAG4)
  933.         {
  934.           while (p && b < e)
  935.         {
  936.           *b++ = '0';
  937.           p--;
  938.         }
  939.           while (m && b < e)
  940.         {
  941.           *b++ = '0';
  942.           m--;
  943.         }
  944.         }
  945.       else if (b < e)    /* waste trailing 0s */
  946.         {
  947.           while (*--b == '0');
  948.           b++;
  949.           if (*--b != '.')
  950.         b++;
  951.         }
  952.     }
  953.  
  954. /* exponent */
  955.  
  956.       if (b < e)
  957.     *b++ = __prfc - ('g' - 'e');
  958.       if (b < e)
  959.     *b++ = (h < 0) ? '-' : '+';
  960.  
  961.       if (b < e)
  962.     e = __prdec (b, e, (h < 0) ? (unsigned int) (-h) : (unsigned int) h);
  963.  
  964.       while (*b = *e)
  965.     b++, e++;
  966.     }
  967.   else
  968.     /* %f */
  969.     {
  970.       w = 1;
  971.       while (h < 0)
  972.     {
  973.       w *= 10;
  974.       h++;
  975.     }
  976.       x /= w;
  977.  
  978.       p -= h;
  979.  
  980. /* integer part - ensure at least 1 digit */
  981.  
  982.       do
  983.     {
  984.       x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  985.       *b++ = i + '0';
  986.       h--;
  987.     }
  988.       while (b < e && h >= 0 && x > err);
  989.       while (b < e && h >= 0)
  990.     {
  991.       *b++ = '0';
  992.       h--;
  993.     }
  994.  
  995. /* fractional part */
  996.  
  997.       if (p || (__prflag & P_FLAG4))
  998.     {
  999.       if (b < e)
  1000.         *b++ = '.';
  1001.  
  1002.       while (b < e && p && x > err)
  1003.         {
  1004.           x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  1005.           *b++ = i + '0';
  1006.           p--;
  1007.         }
  1008.  
  1009.       if (__prflag & P_FLAG4)
  1010.         {
  1011.           while (p && (b < e))
  1012.         {
  1013.           *b++ = '0';
  1014.           p--;
  1015.         }
  1016.           while (m && (b < e))
  1017.         {
  1018.           *b++ = '0';
  1019.           m--;
  1020.         }
  1021.         }
  1022.       else if (b < e)    /* waste trailing 0s */
  1023.         {
  1024.           while (*--b == '0');
  1025.           b++;
  1026.           if (*--b != '.')
  1027.         b++;
  1028.         }
  1029.     }
  1030.  
  1031.       *b = 0;
  1032.     }
  1033.  
  1034.   if (!__prwidth)
  1035.     b = __prbuf;
  1036.   else
  1037.     b = __prjust (b);
  1038.  
  1039.   while (*s = *b)
  1040.     s++, b++;
  1041.  
  1042.   return (s);
  1043. }
  1044.  
  1045. /* __p_ptr() */
  1046.  
  1047. static char *
  1048. __p_ptr (register char *s, register va_list * ap)    /* %p */
  1049. {
  1050.   __prflag |= P_FLAG4;
  1051.   return (__p_uhex (s, ap));
  1052. }
  1053.