home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / alde_c / misc / lib / dlibssrc / printf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-10-12  |  4.7 KB  |  172 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3.  
  4. _printf(op, put, fmt, args)
  5. char *op;
  6. unsigned int (*put)();
  7. register unsigned char *fmt;
  8. register unsigned int *args;
  9. /*
  10.  *    <fmt> points to a format control string.  <args> pointers to a
  11.  *    list of arguments.  The format string is used to create and output
  12.  *    stream with the arguments.  The <put> function is used to output
  13.  *    each character.  The <op> parameter is given to the <put> function
  14.  *    to specify the output stream.  Calls to <put> are of the form:
  15.  *    "(*put)(c, op);" where <c> is the character to output.  The format
  16.  *    string is composed of characters and format specifications.  The
  17.  *    '%' character introduces a format specifier.  The general form of
  18.  *    a format specifier is:
  19.  *
  20.  *        %[-][ |+][0][<width>|*][.[<precision>|*]][l]{d|i|u|o|x|b|c|s}
  21.  *
  22.  *    The '-' specifies left justification.  The ' ' or '+' specifies
  23.  *    the character which preceeds positive numeric values.  The '0'
  24.  *    specifies that numeric fields will be padded with '0' rather than
  25.  *    ' '.  The <width> field is a numeric value specifying a minimum
  26.  *    field width.  The <precision> field is a numeric value specifying
  27.  *    the maximum number of data characters to display.  If '*' is
  28.  *    specified for the width or the precision, an "int" value is taken
  29.  *    from the argument list and used for that value.  If no width is
  30.  *    specified, the field width varies according to the data width.  If
  31.  *    no precision is specified, all data characters are included in the
  32.  *    data width.  If the data width exceeds the field width, the field
  33.  *    width will expand to allow all data characters to be printed.
  34.  *    Including the 'l' or capitalizing the trailing character specifies
  35.  *    that the associated value is a "long" type.  The trailing character
  36.  *    specifies the format type, as follows:
  37.  *
  38.  *        d    Signed decimal integer
  39.  *        i    same as 'd'
  40.  *        u    Unsigned decimal integer
  41.  *        o    Unsigned octal integer
  42.  *        x    Unsigned hexadecimal integer
  43.  *        b    Unsigned binary integer
  44.  *        c    Character
  45.  *        s    String
  46.  *
  47.  *    If the character following the '%' is not recognized, it is
  48.  *    simply passed along to the output stream, thus "%%" is used to
  49.  *    print a single '%' character.
  50.  */
  51. {
  52.     register int i, cnt = 0, ljustf, lval;
  53.     int preci, dpoint, width;
  54.     char pad, sign, radix;
  55.     register char *ptmp;
  56.     char tmp[64], *ltoa(), *ultoa();
  57.  
  58.     while(*fmt) {
  59.         if(*fmt == '%') {
  60.             ljustf = FALSE;    /* left justify flag */
  61.             sign = '\0';    /* sign char & status */
  62.             pad = ' ';    /* justification padding char */
  63.             width = -1;    /* min field width */
  64.             dpoint = FALSE;    /* found decimal point */
  65.             preci = -1;    /* max data width */
  66.             radix = 10;    /* number base */
  67.             ptmp = tmp;    /* pointer to area to print */
  68.             lval = FALSE;    /* long value flaged */
  69. fmtnxt:
  70.             i = 0;
  71.             while (isdigit(*++fmt))    {
  72.                 i = (i * 10) + (*fmt - '0');
  73.                 if (dpoint)
  74.                     preci = i;
  75.                 else if (!i && (pad == ' ')) {
  76.                     pad = '0';
  77.                     goto fmtnxt;
  78.                 }
  79.                 else
  80.                     width = i;
  81.             }
  82.  
  83.             switch(*fmt) {
  84.                 case '\0':    /* early EOS */
  85.                     --fmt;
  86.                     goto charout;
  87.  
  88.                 case '-':    /* left justification */
  89.                     ljustf = TRUE;
  90.                     goto fmtnxt;
  91.  
  92.                 case ' ':
  93.                 case '+':    /* leading sign flag */
  94.                     sign = *fmt;
  95.                     goto fmtnxt;
  96.  
  97.                 case '*':    /* parameter width value */
  98.                     i = *args++;
  99.                     if (dpoint)
  100.                         preci = i;
  101.                     else
  102.                         width = i;
  103.                     goto fmtnxt;
  104.  
  105.                 case '.':    /* secondary width field */
  106.                     dpoint = TRUE;
  107.                     goto fmtnxt;
  108.  
  109.                 case 'l':    /* long data */
  110.                     lval = TRUE;
  111.                     goto fmtnxt;
  112.  
  113.                 case 'd':    /* Signed decimal */
  114.                 case 'i':
  115.                     ltoa((long)((lval)
  116.                         ?(*((long *) args)++)
  117.                         :(*((int  *) args)++)),
  118.                           ptmp, 10);
  119.                     goto printit;
  120.  
  121.                 case 'b':    /* Unsigned binary */
  122.                     radix = 2;
  123.                     goto usproc;
  124.  
  125.                 case 'o':    /* Unsigned octal */
  126.                     radix = 8;
  127.                     goto usproc;
  128.  
  129.                 case 'x':    /* Unsigned hexadecimal */
  130.                 case 'X':
  131.                     radix = 16;
  132.                     /* fall thru */
  133.  
  134.                 case 'u':    /* Unsigned decimal */
  135. usproc:
  136.                     ultoa((unsigned long)((lval)
  137.                         ?(*((unsigned long *) args)++)
  138.                         :(*((unsigned int  *) args)++)),
  139.                           ptmp, radix);
  140.                     if (*fmt == 'x')
  141.                         strlwr(ptmp, ptmp);
  142.                     goto printit;
  143.  
  144.                 case 'c':    /* Character */
  145.                     ptmp[0] = *args++;
  146.                     ptmp[1] = '\0';
  147.                     goto nopad;
  148.  
  149.                 case 's':    /* String */
  150.                     ptmp = *((char **) args)++;
  151. nopad:
  152.                     sign = '\0';
  153.                     pad  = ' ';
  154. printit:
  155.                     cnt += _prtfld(op, put, ptmp, ljustf,
  156.                                sign, pad, width, preci);
  157.                     break;
  158.  
  159.                 default:    /* unknown character */
  160.                     goto charout;
  161.             }
  162.         }
  163.         else {
  164. charout:
  165.             (*put)(*fmt, op);        /* normal char out */
  166.             ++cnt;
  167.         }
  168.         ++fmt;
  169.     }
  170.     return(cnt);
  171. }
  172.