home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Libraries / Log Library 1.01 / LogLibComponent ƒ / Libsprintf.c next >
Encoding:
C/C++ Source or Header  |  1994-05-07  |  10.5 KB  |  578 lines  |  [TEXT/KAHL]

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