home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / pdksh-4.9-src.tgz / tar.out / contrib / pdksh / std / stdc / vprintf.c < prev   
C/C++ Source or Header  |  1996-09-28  |  5KB  |  243 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: vprintf.c,v 1.4 93/05/05 21:19:03 sjg Exp $";
  3. #endif
  4. #ifdef __STDC__
  5. #include <stdarg.h>
  6. #else
  7. #include <varargs.h>
  8. #endif
  9. #include <stdio.h>
  10.  
  11. #define    BUF    40        /* buffer for int -> string conversion */
  12.  
  13. int
  14. #ifdef __STDC__
  15. vprintf(const char *fmt, va_list va) {
  16. #else
  17. vprintf(fmt, va) char *fmt; va_list va; {
  18. #endif
  19.     return vfprintf(stdout, fmt, va);
  20. }
  21.  
  22. int
  23. #ifdef __STDC__
  24. vfprintf(register FILE *f, register const char *fmt, register va_list va) {
  25. #else
  26. vfprintf(f, fmt, va) register FILE *f; register char *fmt; register va_list va; {
  27. #endif
  28.     register int c;
  29.     int pos = 0;            /* todo: implement */
  30.  
  31.     while ((c = *fmt++))
  32.         if (c == '%') {
  33.         long n;
  34.         register unsigned long u;
  35.         char buf [BUF+1];
  36.         register char *p = buf + BUF;
  37.         register enum {
  38.             FF_ALT = 0x01, /* #, alternate format */
  39.             FF_SHORT = 0x02, /* h, short arg */
  40.             FF_LONG = 0x04,    /* l, long arg */
  41.             FF_ZERO = 0x08,    /* 0, zero fill */
  42.             FF_LEFT = 0x10,    /* -, left adjust */
  43.             FF_PREC = 0x20,    /* .*, precision */
  44.             FF_NEG = 0x40,    /* signed arg */
  45.             FF_PUTS = 0x80,    /* fputs(p, f) */
  46.             FF_DEFAULT = 0
  47.         } flags = FF_DEFAULT;
  48.         int sign = '-';    /* sign: [ +-] */
  49.         int width = 0, prec = 0; /* width, precision */
  50.  
  51.         *p = 0;
  52.  
  53.         /* scan flag characters */
  54.         for (c = *fmt++; ; c = *fmt++) switch (c) {
  55.           case '0':
  56.             flags |= FF_ZERO;
  57.             break;
  58.  
  59.           case '#':        /* alternate format */
  60.             flags |= FF_ALT;
  61.             break;
  62.  
  63.           case ' ':        /* blank sign */
  64.             sign = ' ';
  65.             break;
  66.           case '+':        /* +/- sign */
  67.             sign = '+';
  68.             break;
  69.  
  70.           case '-':        /* left just. */
  71.             flags |= FF_LEFT;
  72.             break;
  73.  
  74.           default:
  75.             goto Frogs;
  76.         }
  77.       Frogs:
  78.  
  79.         /* scan width */
  80.           if (c == '*') {        /* width from arg list */
  81.             width = va_arg(va, int);
  82.             c = *fmt++;
  83.         } else
  84.             while ('0' <= c && c <= '9') {
  85.                 width = width*10 + (c-'0');
  86.                 c = *fmt++;
  87.             }
  88.  
  89.         if (c == '.') {        /* scan precision */
  90.             flags |= FF_PREC;
  91.             c = *fmt++;
  92.             if (c == '*') {    /* precision from arg list */
  93.                 prec = va_arg(va, int);
  94.                 c = *fmt++;
  95.             } else
  96.                 while ('0' <= c && c <= '9') {
  97.                     prec = prec*10 + (c-'0');
  98.                     c = *fmt++;
  99.                 }
  100.         }
  101.  
  102.         /* length modifiers */
  103.         if (c == 'h') {
  104.             flags |= FF_SHORT;
  105.             c = *fmt++;
  106.         } else if (c == 'l') {
  107.             flags |= FF_LONG;
  108.             c = *fmt++;
  109.         }
  110.  
  111.         /* do conversion */
  112.         switch (c) {
  113.           case '%':        /* %% -> % */
  114.             putc(c, f);
  115.             pos ++;
  116.             break;
  117.  
  118.           case 'p':        /* pointer */
  119.             *--p = '}';
  120.             u = (unsigned long) va_arg(va, void*);
  121.             do {
  122.                 *--p = "0123456789ABCDEF"[u%16];
  123.                 u /= 16;
  124.             } while (u != 0);
  125.             *--p = '{';
  126.             flags |= FF_PUTS;
  127.             break;
  128.  
  129.           case 'n':        /* save position */
  130.             *va_arg(va, int*) = pos;
  131.             break;
  132.  
  133.           case 'c':        /* character */
  134.             u = (flags&FF_SHORT) ? va_arg(va, unsigned short)
  135.               : (flags&&FF_LONG) ? va_arg(va, unsigned long)
  136.               : va_arg(va, unsigned int);
  137.             *--p = u;
  138.             flags |= FF_PUTS;
  139.             break;
  140.  
  141.           case 's':        /* string */
  142.             if ((p = va_arg(va, char *)) == NULL)
  143.               p = "";
  144.             if ((flags&FF_PREC) && strlen(p) > prec) {
  145.                 pos += prec;
  146.                 while (--prec >= 0)
  147.                 {
  148.                   c = *p++;
  149.                   putc(c, f);
  150.                 }
  151.                 break;
  152.             }
  153.             flags |= FF_PUTS;
  154.             break;
  155.  
  156.           case 'i': case 'd': case 'u': /* decimal */
  157.             if (c != 'u') {    /* signed */
  158.                 n = (flags&FF_SHORT) ? va_arg(va, short)
  159.                   : (flags&&FF_LONG) ? va_arg(va, long)
  160.                   : va_arg(va, int);
  161.                 if (n < 0)
  162.                     flags |= FF_NEG;
  163.                 u = (n < 0) ? -n : n;
  164.             } else
  165.                 u = (flags&FF_SHORT) ? va_arg(va, unsigned short)
  166.                   : (flags&&FF_LONG) ? va_arg(va, unsigned long)
  167.                   : va_arg(va, unsigned int);
  168.             do {
  169.                 *--p = '0' + u%10;
  170.                 u /= 10;
  171.             } while (u != 0);
  172.             prec -= buf+BUF - p;
  173.             while (--prec >= 0)
  174.                 *--p = '0';
  175.             if (flags&FF_NEG)
  176.                 *--p = '-';
  177.             else
  178.                 if (sign != '-')
  179.                     *--p = (sign == '+') ? '+' : ' ';
  180.             flags |= FF_PUTS;
  181.             break;
  182.  
  183.           case 'x': case 'X':    /* hex, Hex */
  184.             u = (flags&FF_SHORT) ? va_arg(va, unsigned short)
  185.               : (flags&&FF_LONG) ? va_arg(va, unsigned long)
  186.               : va_arg(va, unsigned int);
  187.             do {
  188.                 *--p = "0123456789ABCDEF"[u%16];
  189.                 u /= 16;
  190.             } while (u != 0);
  191.             prec -= buf+BUF - p;
  192.             while (--prec >= 0)
  193.                 *--p = '0';
  194.             if (flags&&FF_ALT)
  195.                 *--p = 'x', *--p = '0';
  196.             flags |= FF_PUTS;
  197.             break;
  198.  
  199.           case 'o':        /* octal */
  200.             u = (flags&FF_SHORT) ? va_arg(va, unsigned short)
  201.               : (flags&&FF_LONG) ? va_arg(va, unsigned long)
  202.               : va_arg(va, unsigned int);
  203.             do {
  204.                 *--p = '0' + u%8;
  205.                 u /= 8;
  206.             } while (u != 0);
  207.             prec -= buf+BUF - p;
  208.             while (--prec >= 0)
  209.                 *--p = '0';
  210.             if (flags&&FF_ALT && *p != '0')
  211.                 *--p = '0';
  212.             flags |= FF_PUTS;
  213.             break;
  214.  
  215.           default:        /* todo: error */
  216.             putc('%', f);
  217.             putc(c, f);
  218.             pos += 2;
  219.             break;
  220.         }
  221.  
  222.         /* copy adjusted string "p" to output */
  223.         if (flags&FF_PUTS) {
  224.             int len = strlen(p);
  225.             int pad = width - len;
  226.             if (!(flags&FF_LEFT))
  227.                 while (--pad >= 0)
  228.                     putc((flags&FF_ZERO) ? '0' : ' ', f);
  229.             while (c = *p++)
  230.                 putc(c, f);
  231.             if ((flags&FF_LEFT))
  232.                 while (--pad >= 0)
  233.                     putc(' ', f);
  234.             pos += (len < width) ? width : len;
  235.         }
  236.         } else {            /* ordinary character */
  237.         putc(c, f);
  238.         pos ++;
  239.         }
  240.     return pos;
  241. }
  242.  
  243.