home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Add-Ons / BBEdit / MacBob 1.0ß2 / Source / printf.c < prev    next >
Encoding:
Text File  |  1995-12-07  |  10.6 KB  |  568 lines  |  [TEXT/KAHL]

  1. /***
  2.   *
  3.   *    printf.c
  4.   *
  5.   *    Copyright (c) 1991 Symantec Corporation.  All rights reserved.
  6.   *    Modified by Christopher E. Hyde, 1995
  7.   *
  8.   ***/
  9.  
  10. //#include <stdio.h>
  11. #include <stdarg.h>
  12. #ifndef _NOFLOATING_
  13. #include <fp.h>
  14. #endif
  15.  
  16. #ifdef _NOFLOATING_
  17. #define    BUFLEN        80
  18. #else
  19. #define    BUFLEN        512
  20. #endif
  21. #define    TRUE            1
  22. #define    FALSE        0
  23.  
  24. static struct format {
  25.     unsigned         leftJustify : 1;
  26.     unsigned         forceSign : 1;
  27.     unsigned         altForm : 1;
  28.     unsigned         zeroPad : 1;
  29.     unsigned         havePrecision : 1;
  30.     unsigned         hSize : 1;
  31.     unsigned         lSize : 1;
  32.     unsigned         LSize : 1;
  33.     char            sign;
  34.     char            exponent;
  35.     int                fieldWidth;
  36.     int                precision;
  37. } default_format;
  38.  
  39.  
  40. #ifndef _NOFLOATING_
  41. struct decrec {
  42.     decimal    dec;
  43.     /* following fields aren't used by SANE */
  44.     short            min;
  45.     short            dot;
  46.     short            max;
  47. };
  48.  
  49. static void ftod(int, int, struct decrec *, long double);
  50. #endif
  51.  
  52.  
  53. #ifndef NULL
  54. #define    NULL        ((void*) 0)
  55. #endif
  56. int    vsprintf (char* dst, const char* fmt, va_list arg);
  57.  
  58.  
  59. int
  60. sprintf (char* s, const char* fmt, ...)
  61. {
  62.     return vsprintf(s, fmt, __va(fmt));
  63. }
  64.  
  65.  
  66. int
  67. vsprintf (char* dst, const char* fmt, va_list arg)
  68. {
  69.     register int c, i, j, nwritten = 0;
  70.     register unsigned long n;
  71.     register char *s;
  72.     char buf[BUFLEN], *digits, *t;
  73.     struct format F;
  74. #ifndef _NOFLOATING_
  75.     long double x;
  76.     struct decrec D;
  77. #endif
  78.     
  79.     for (c = *fmt; c; c = *++fmt) {
  80.         if (c != '%')
  81.             goto copy1;
  82.         F = default_format;
  83.         
  84.             /*  decode flags  */
  85.             
  86.         for (;;) {
  87.             c = *++fmt;
  88.             if (c == '-')
  89.                 F.leftJustify = TRUE;
  90.             else if (c == '+')
  91.                 F.forceSign = TRUE;
  92.             else if (c == ' ')
  93.                 F.sign = ' ';
  94.             else if (c == '#')
  95.                 F.altForm = TRUE;
  96.             else if (c == '0')
  97.                 F.zeroPad = TRUE;
  98.             else
  99.                 break;
  100.         }
  101.         
  102.             /*  decode field width  */
  103.             
  104.         if (c == '*') {
  105.             if ((F.fieldWidth = va_arg(arg, int)) < 0) {
  106.                 F.leftJustify = TRUE;
  107.                 F.fieldWidth = -F.fieldWidth;
  108.             }
  109.             c = *++fmt;
  110.         }
  111.         else {
  112.             for (; c >= '0' && c <= '9'; c = *++fmt)
  113.                 F.fieldWidth = (10 * F.fieldWidth) + (c - '0');
  114.         }
  115.         
  116.             /*  decode precision  */
  117.             
  118.         if (c == '.') {
  119.             if ((c = *++fmt) == '*') {
  120.                 F.precision = va_arg(arg, int);
  121.                 c = *++fmt;
  122.             }
  123.             else {
  124.                 for (; c >= '0' && c <= '9'; c = *++fmt)
  125.                     F.precision = (10 * F.precision) + (c - '0');
  126.             }
  127.             if (F.precision >= 0)
  128.                 F.havePrecision = TRUE;
  129.         }
  130.         
  131.             /*  perform appropriate conversion  */
  132.         
  133.         s = &buf[BUFLEN];
  134.         if (F.leftJustify)
  135.             F.zeroPad = FALSE;
  136. conv:    switch (c) {
  137.                 
  138.                 /*  'h' size modifier  */
  139.                 
  140.             case 'h':
  141.                 F.hSize = TRUE;
  142.                 c = *++fmt;
  143.                 goto conv;
  144.                 
  145.                 /*  'l' size modifier  */
  146.                 
  147.             case 'l':
  148.                 F.lSize = TRUE;
  149.                 c = *++fmt;
  150.                 goto conv;
  151.                         
  152.                 /*  'L' size modifier  */
  153.                 
  154.             case 'L':
  155.                 F.LSize = TRUE;
  156.                 c = *++fmt;
  157.                 goto conv;
  158.         
  159.                 /*  decimal (signed)  */
  160.                 
  161.             case 'd':
  162.             case 'i':
  163.                 if (F.lSize)
  164.                     n = va_arg(arg, long);
  165.                 else
  166.                     n = va_arg(arg, int);
  167.                 if (F.hSize)
  168.                     n = (short) n;
  169.                 if ((long) n < 0) {
  170.                     n = -n;
  171.                     F.sign = '-';
  172.                 }
  173.                 else if (F.forceSign)
  174.                     F.sign = '+';
  175.                 goto decimal;
  176.                 
  177.                 /*  decimal (unsigned)  */
  178.                 
  179.             case 'u':
  180.                 if (F.lSize)
  181.                     n = va_arg(arg, unsigned long);
  182.                 else
  183.                     n = va_arg(arg, unsigned int);
  184.                 if (F.hSize)
  185.                     n = (unsigned short) n;
  186.                 F.sign = 0;
  187.                 goto decimal;
  188.                 
  189.                 /*  decimal (common code)  */
  190.  
  191.             decimal:
  192.                 if (!F.havePrecision) {
  193.                     if (F.zeroPad) {
  194.                         F.precision = F.fieldWidth;
  195.                         if (F.sign)
  196.                             --F.precision;
  197.                     }
  198.                     if (F.precision < 1)
  199.                         F.precision = 1;
  200.                 }
  201.                 for (i = 0; n; n /= 10, i++)
  202.                     *--s = n % 10 + '0';
  203.                 for (; i < F.precision; i++)
  204.                     *--s = '0';
  205.                 if (F.sign) {
  206.                     *--s = F.sign;
  207.                     i++;
  208.                 }
  209.                 break;
  210.                 
  211.                 /*  octal (unsigned)  */
  212.                 
  213.             case 'o':
  214.                 if (F.lSize)
  215.                     n = va_arg(arg, unsigned long);
  216.                 else
  217.                     n = va_arg(arg, unsigned int);
  218.                 if (F.hSize)
  219.                     n = (unsigned short) n;
  220.                 if (!F.havePrecision) {
  221.                     if (F.zeroPad)
  222.                         F.precision = F.fieldWidth;
  223.                     if (F.precision < 1)
  224.                         F.precision = 1;
  225.                 }
  226.                 for (i = 0; n; n /= 8, i++)
  227.                     *--s = n % 8 + '0';
  228.                 if (F.altForm && i && *s != '0') {
  229.                     *--s = '0';
  230.                     i++;
  231.                 }
  232.                 for (; i < F.precision; i++)
  233.                     *--s = '0';
  234.                 break;
  235.                 
  236.                 /*  hexadecimal (unsigned)  */
  237.                 
  238.             case 'p':
  239.                 F.havePrecision = F.lSize = TRUE;
  240.                 F.precision = 8;
  241.                 /* ... */
  242.             case 'X':
  243.                 digits = "0123456789ABCDEF";
  244.                 goto hexadecimal;
  245.             case 'x':
  246.                 digits = "0123456789abcdef";
  247.                 /* ... */
  248.             hexadecimal:
  249.                 if (F.lSize)
  250.                     n = va_arg(arg, unsigned long);
  251.                 else
  252.                     n = va_arg(arg, unsigned int);
  253.                 if (F.hSize)
  254.                     n = (unsigned short) n;
  255.                 if (!F.havePrecision) {
  256.                     if (F.zeroPad) {
  257.                         F.precision = F.fieldWidth;
  258.                         if (F.altForm)
  259.                             F.precision -= 2;
  260.                     }
  261.                     if (F.precision < 1)
  262.                         F.precision = 1;
  263.                 }
  264.                 for (i = 0; n; n /= 16, i++)
  265.                     *--s = digits[n % 16];
  266.                 for (; i < F.precision; i++)
  267.                     *--s = '0';
  268.                 if (F.altForm) {
  269.                     *--s = c;
  270.                     *--s = '0';
  271.                     i += 2;
  272.                 }
  273.                 break;
  274.                 
  275. #ifndef _NOFLOATING_
  276.                 /*  fixed-point  */
  277.  
  278.             case 'f':
  279.                 if (F.LSize)
  280.                     x = va_arg(arg, long double);
  281.                 else
  282.                     x = va_arg(arg, double);
  283.                 if (!F.havePrecision)
  284.                     F.precision = 6;
  285.                 ftod(1, F.precision, &D, x);
  286.                 D.dot = D.dec.exp + D.dec.sig.length;
  287.                 if ((D.min = D.dot) > 1)
  288.                     D.min = 1;
  289.                 D.max = D.dot + F.precision;
  290.                 if (D.max - D.min > 508)
  291.                     memcpy(&D.dec.sig, "\6>>>>>>", 7);
  292.                 goto floating;
  293.  
  294.                 /*  floating-point  */
  295.                 
  296.             case 'e':
  297.             case 'E':
  298.                 if (F.LSize)
  299.                     x = va_arg(arg, long double);
  300.                 else
  301.                     x = va_arg(arg, double);
  302.                 if (!F.havePrecision)
  303.                     F.precision = 6;
  304.                 F.exponent = c;
  305.                 ftod(0, D.max = F.precision + 1, &D, x);
  306.                 D.min = D.dot = 1;
  307.                 D.dec.exp += D.dec.sig.length - 1;
  308.                 goto floating;
  309.                 
  310.                 /*  "general" notation  */
  311.                 
  312.             case 'g':
  313.             case 'G':
  314.                 if (F.LSize)
  315.                     x = va_arg(arg, long double);
  316.                 else
  317.                     x = va_arg(arg, double);
  318.                 if (!F.havePrecision)
  319.                     F.precision = 6;
  320.                 else if (F.precision == 0)
  321.                     F.precision = 1;
  322.                 F.exponent = c - 2;
  323.                 ftod(0, D.max = F.precision, &D, x);
  324.                 D.min = D.dot = 1;
  325.                 D.dec.exp += D.dec.sig.length - 1;
  326.                 if (D.dec.exp >= -4 && D.dec.exp < F.precision) {
  327.                     F.exponent = 0;
  328.                     if ((D.dot += D.dec.exp) < 1)
  329.                         D.min = D.dot;
  330.                 }
  331.                 if (!F.altForm && D.max > D.dec.sig.length) {
  332.                     if ((D.max = D.dec.sig.length) < D.dot)
  333.                         D.max = D.dot;
  334.                 }
  335.                 goto floating;
  336.                 
  337.                     /*  floating (common code)  */
  338.  
  339.             floating:
  340.                 if (D.dec.sig.text[0] > '9') {
  341.                     F.exponent = FALSE;
  342.                     D.dot = 0;
  343.                     D.min = 1;
  344.                     D.max = D.dec.sig.length;
  345.                 }
  346.                 i = 0;
  347.                 if (F.exponent) {
  348.                     n = D.dec.exp < 0 ? -D.dec.exp : D.dec.exp;
  349.                     for (; n; n /= 10, i++)
  350.                         *--s = n % 10 + '0';
  351.                     for (; i < 2; i++)
  352.                         *--s = '0';
  353.                     *--s = D.dec.exp < 0 ? '-' : '+';
  354.                     *--s = F.exponent;
  355.                     i += 2;
  356.                 }
  357.                 j = D.max;
  358.                 if (j == D.dot && !F.altForm)
  359.                     ++D.dot;
  360.                 do {
  361.                     if (j == D.dot) {
  362.                         *--s = '.';
  363.                         i++;
  364.                     }
  365.                     *--s = j > 0 && j <= D.dec.sig.length ? D.dec.sig.text[j-1] : '0';
  366.                 } while (--j >= D.min);
  367.                 i += D.max - j;
  368.                 if (D.dec.sgn)
  369.                     F.sign = '-';
  370.                 else if (F.forceSign)
  371.                     F.sign = '+';
  372.                 if (F.zeroPad) {
  373.                     j = F.fieldWidth;
  374.                     if (F.sign)
  375.                         --j;
  376.                     for (; i < j; i++)
  377.                         *--s = '0';
  378.                 }
  379.                 if (F.sign) {
  380.                     *--s = F.sign;
  381.                     i++;
  382.                 }
  383.                 break;
  384. #endif /* _NOFLOATING_ */
  385.  
  386.                 /*  character  */
  387.                 
  388.             case 'c':
  389.                 *--s = va_arg(arg, int);
  390.                 i = 1;
  391.                 break;
  392.                 
  393.                 /*  string  */
  394.                 
  395.             case 's':
  396.                 s = va_arg(arg, char *);
  397.                 if (F.altForm) {
  398.                     i = (unsigned char) *s++;
  399.                     if (F.havePrecision && i > F.precision)
  400.                         i = F.precision;
  401.                 }
  402.                 else {
  403.                     if (!F.havePrecision)
  404.                         i = strlen(s);
  405.                     else if ((t = (char *)memchr(s, '\0', F.precision)) != NULL)
  406.                         i = t - s;
  407.                     else
  408.                         i = F.precision;
  409.                 }
  410.                 break;
  411.                 
  412.                 /*  store # bytes written so far  */
  413.                 
  414.             case 'n':
  415.                 s = (char *)va_arg(arg, void *);
  416.                 if (F.hSize)
  417.                     * (short *) s = nwritten;
  418.                 else if (F.lSize)
  419.                     * (long *) s = nwritten;
  420.                 else
  421.                     * (int *) s = nwritten;
  422.                 continue;
  423.  
  424.                 /*  oops - unknown conversion, abort  */
  425.  
  426.             default:
  427.                 if (c != '%')
  428.                     goto done;
  429.             copy1:
  430.                 *dst++ = c;
  431.                 ++nwritten;
  432.                 continue;
  433.         }
  434.  
  435.             /*  pad on the left  */
  436.  
  437.         if (i < F.fieldWidth && !F.leftJustify) {
  438.             do {
  439.                 *dst++ = ' ';
  440.                 ++nwritten;
  441.             } while (i < --F.fieldWidth);
  442.         }
  443.  
  444.             /*  write the converted result  */
  445.  
  446.         memcpy(dst, s, i);
  447.         dst += i;
  448.         nwritten += i;
  449.  
  450.             /*  pad on the right  */
  451.  
  452.         for (; i < F.fieldWidth; i++) {
  453.             *dst++ = ' ';
  454.             ++nwritten;
  455.         }
  456.     }
  457.  
  458.         /*  all done!  */
  459.  
  460. done:
  461. //    if (nwritten >= 0)
  462.         *dst = 0;
  463.     return nwritten;
  464. }
  465.  
  466. #ifndef _NOFLOATING_
  467.  
  468. static void
  469. post_conversion( struct decrec *d)
  470. {
  471.     int i;
  472.     /*  strip trailing zeroes  */
  473.  
  474.     for (i = d->dec.sig.length; i > 1 && d->dec.sig.text[i-1] == '0'; --i)
  475.         ++d->dec.exp;
  476.     d->dec.sig.length = i;
  477.         
  478.         /*  format 0, INF, NAN  */
  479.         
  480.     if (d->dec.sig.text[0] == '0') {
  481. /*        d->dec.sgn = 0;             add back to disallow printing "-0"  */
  482.         d->dec.exp = 0;
  483.     }
  484.     else if (d->dec.sig.text[0] == 'I') {
  485.         d->dec.sig.length = 3;
  486.         d->dec.sig.text[1] = 'N';
  487.         d->dec.sig.text[2] = 'F';
  488.     }
  489.     else if (d->dec.sig.text[0] == 'N') {
  490.         d->dec.sig.length = 5;
  491.         d->dec.sig.text[1] = 'A';
  492.         d->dec.sig.text[2] = 'N';
  493.     }
  494. }
  495.  
  496. /* ---------- floating-point conversion ---------- */
  497.  
  498. #if powerc
  499. static void 
  500. ftod( int fixed, int precision, struct decrec *d, long double x)
  501. {
  502.     struct decform form;
  503.     
  504.     
  505.     if (precision >= sizeof d->dec.sig)
  506.         precision = sizeof d->dec.sig - 1;
  507.  
  508.     if (fixed)
  509.         form.style = FIXEDDECIMAL;
  510.     else
  511.         form.style = FLOATDECIMAL;
  512.     form.digits = precision;
  513.     /*
  514.         Until the long double data type is really implemented, this must be a call
  515.         to num2dec and not num2decl even though the argument is declared as a long
  516.         double 
  517.     */
  518.     
  519.     num2dec( &form, x, &(d->dec) );
  520.     
  521.         /*  handle fixed-point overflow  */
  522.         
  523.     if (d->dec.sig.text[0] == '?') {
  524.         form.style = FLOATDECIMAL;
  525.         form.digits = sizeof d->dec.sig - 1;
  526.         num2dec( &form, x, &(d->dec));
  527.     }
  528.     post_conversion(d);
  529. #else
  530.  
  531. static void
  532. ftod(int fixed, int precision, struct decrec *d, long double x)
  533. {
  534.     struct { char style; short digits; } form;
  535.     register short *p = (short *) &x;
  536.     
  537.         /*  point to SANE extended  */
  538.  
  539.     #if __option(mc68881) && _NATIVE_FP_
  540.         p[1] = p[0];
  541.     #endif
  542.     #if __option(mc68881) || !_NATIVE_FP_
  543.         p++;
  544.     #endif
  545.     
  546.         /*  convert to decimal record  */
  547.     
  548.     if (precision >= sizeof d->dec.sig)
  549.         precision = sizeof d->dec.sig - 1;
  550.     form.style = fixed;
  551.     form.digits = precision;
  552.     fp68k(&form, p, d, FX2DEC);
  553.     
  554.         /*  handle fixed-point overflow  */
  555.         
  556.     if (d->dec.sig.text[0] == '?') {
  557.         form.style = 0;
  558.         form.digits = sizeof d->dec.sig - 1;
  559.         fp68k(&form, p, d, FX2DEC);
  560.     }
  561.     
  562.     post_conversion(d);    
  563.  
  564. }
  565. #endif
  566. #endif
  567.