home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / os / kludge03.tz / kludge03 / mk74 / user / libmach / doprnt.c < prev    next >
C/C++ Source or Header  |  1992-02-26  |  11KB  |  493 lines

  1. /* 
  2.  * Mach Operating System
  3.  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
  4.  * All Rights Reserved.
  5.  * 
  6.  * Permission to use, copy, modify and distribute this software and its
  7.  * documentation is hereby granted, provided that both the copyright
  8.  * notice and this permission notice appear in all copies of the
  9.  * software, derivative works or modified versions, and any portions
  10.  * thereof, and that both notices appear in supporting documentation.
  11.  * 
  12.  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  13.  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  14.  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  15.  * 
  16.  * Carnegie Mellon requests users of this software to return to
  17.  * 
  18.  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
  19.  *  School of Computer Science
  20.  *  Carnegie Mellon University
  21.  *  Pittsburgh PA 15213-3890
  22.  * 
  23.  * any improvements or extensions that they make and grant Carnegie Mellon
  24.  * the rights to redistribute these changes.
  25.  */
  26. /*
  27.  * HISTORY
  28.  * $Log:    doprnt.c,v $
  29.  * Revision 2.2  92/02/20  15:58:00  elf
  30.  *     Moved from bootstrap to libmach.
  31.  *     [92/02/11            rpd]
  32.  * 
  33.  * Revision 2.2  92/01/03  19:55:21  dbg
  34.  *     Moved outside of kernel to bootstrap.
  35.  *     [91/08/02            dbg]
  36.  * 
  37.  * Revision 2.8  91/05/14  15:20:47  mrt
  38.  *     Correcting copyright
  39.  * 
  40.  * Revision 2.7  91/03/13  16:50:19  rpd
  41.  *     Should initialize the "count" before a device_read_inband().
  42.  *     Bug found by laverne@sumitomo.com.
  43.  *     [91/03/13  15:03:15  af]
  44.  * 
  45.  * Revision 2.6  91/02/05  17:00:25  mrt
  46.  *     Changed to new copyright
  47.  *     [91/01/28  14:54:14  mrt]
  48.  * 
  49.  * Revision 2.5  90/10/25  14:41:34  rwd
  50.  *     Modified boot_gets to allocate arrays from heap, not stack.
  51.  *     [90/10/23            rpd]
  52.  * 
  53.  * Revision 2.4  90/08/27  21:44:20  dbg
  54.  *     Pass extra argument to _doprnt.
  55.  *     [90/08/21            dbg]
  56.  * 
  57.  * Revision 2.3  90/06/02  14:45:13  rpd
  58.  *     Converted to new IPC and new host port mechanism.
  59.  *     [90/03/26  21:28:27  rpd]
  60.  * 
  61.  * Revision 2.2  90/01/11  11:40:53  dbg
  62.  *     Created.
  63.  *     [89/12/20            dbg]
  64.  * 
  65.  */
  66.  
  67. #define EXPORT_BOOLEAN
  68. #include <mach/boolean.h>
  69. #include <varargs.h>
  70.  
  71. /*
  72.  *  Common code for printf et al.
  73.  *
  74.  *  The calling routine typically takes a variable number of arguments,
  75.  *  and passes the address of the first one.  This implementation
  76.  *  assumes a straightforward, stack implementation, aligned to the
  77.  *  machine's wordsize.  Increasing addresses are assumed to point to
  78.  *  successive arguments (left-to-right), as is the case for a machine
  79.  *  with a downward-growing stack with arguments pushed right-to-left.
  80.  *
  81.  *  To write, for example, fprintf() using this routine, the code
  82.  *
  83.  *    fprintf(fd, format, args)
  84.  *    FILE *fd;
  85.  *    char *format;
  86.  *    {
  87.  *    _doprnt(format, &args, fd);
  88.  *    }
  89.  *
  90.  *  would suffice.  (This example does not handle the fprintf's "return
  91.  *  value" correctly, but who looks at the return value of fprintf
  92.  *  anyway?)
  93.  *
  94.  *  This version implements the following printf features:
  95.  *
  96.  *    %d    decimal conversion
  97.  *    %u    unsigned conversion
  98.  *    %x    hexadecimal conversion
  99.  *    %X    hexadecimal conversion with capital letters
  100.  *    %o    octal conversion
  101.  *    %c    character
  102.  *    %s    string
  103.  *    %m.n    field width, precision
  104.  *    %-m.n    left adjustment
  105.  *    %0m.n    zero-padding
  106.  *    %*.*    width and precision taken from arguments
  107.  *
  108.  *  This version does not implement %f, %e, or %g.  It accepts, but
  109.  *  ignores, an `l' as in %ld, %lo, %lx, and %lu, and therefore will not
  110.  *  work correctly on machines for which sizeof(long) != sizeof(int).
  111.  *  It does not even parse %D, %O, or %U; you should be using %ld, %o and
  112.  *  %lu if you mean long conversion.
  113.  *
  114.  *  As mentioned, this version does not return any reasonable value.
  115.  *
  116.  *  Permission is granted to use, modify, or propagate this code as
  117.  *  long as this notice is incorporated.
  118.  *
  119.  *  Steve Summit 3/25/87
  120.  */
  121.  
  122. /*
  123.  * Added formats for decoding device registers:
  124.  *
  125.  * printf("reg = %b", regval, "<base><arg>*")
  126.  *
  127.  * where <base> is the output base expressed as a control character:
  128.  * i.e. '\10' gives octal, '\20' gives hex.  Each <arg> is a sequence of
  129.  * characters, the first of which gives the bit number to be inspected
  130.  * (origin 1), and the rest (up to a control character (<= 32)) give the
  131.  * name of the register.  Thus
  132.  *    printf("reg = %b\n", 3, "\10\2BITTWO\1BITONE")
  133.  * would produce
  134.  *    reg = 3<BITTWO,BITONE>
  135.  *
  136.  * If the second character in <arg> is also a control character, it
  137.  * indicates the last bit of a bit field.  In this case, printf will extract
  138.  * bits <1> to <2> and print it.  Characters following the second control
  139.  * character are printed before the bit field.
  140.  *    printf("reg = %b\n", 0xb, "\10\4\3FIELD1=\2BITTWO\1BITONE")
  141.  * would produce
  142.  *    reg = b<FIELD1=2,BITONE>
  143.  */
  144. /*
  145.  * Added for general use:
  146.  *    #    prefix for alternate format:
  147.  *        0x (0X) for hex
  148.  *        leading 0 for octal
  149.  *    +    print '+' if positive
  150.  *    blank    print ' ' if positive
  151.  *
  152.  *    z    signed hexadecimal
  153.  *    r    signed, 'radix'
  154.  *    n    unsigned, 'radix'
  155.  *
  156.  *    D,U,O,Z    same as corresponding lower-case versions
  157.  *        (compatibility)
  158.  */
  159.  
  160. #define isdigit(d) ((d) >= '0' && (d) <= '9')
  161. #define Ctod(c) ((c) - '0')
  162.  
  163. #define MAXBUF (sizeof(long int) * 8)         /* enough for binary */
  164.  
  165. static
  166. printnum(u, base, putc, putc_arg)
  167.     register unsigned int    u;    /* number to print */
  168.     register int        base;
  169.     void            (*putc)();
  170.     char            *putc_arg;
  171. {
  172.     char    buf[MAXBUF];    /* build number here */
  173.     register char *    p = &buf[MAXBUF-1];
  174.     static char digs[] = "0123456789abcdef";
  175.  
  176.     do {
  177.         *p-- = digs[u % base];
  178.         u /= base;
  179.     } while (u != 0);
  180.  
  181.     while (++p != &buf[MAXBUF])
  182.         (*putc)(putc_arg, *p);
  183. }
  184.  
  185. _doprnt(fmt, args, radix, putc, putc_arg)
  186.     register char    *fmt;
  187.     va_list        args;
  188.     int        radix;        /* default radix - for '%r' */
  189.      void        (*putc)();    /* character output */
  190.     char        *putc_arg;    /* argument for putc */
  191. {
  192.     int        length;
  193.     int        prec;
  194.     boolean_t    ladjust;
  195.     char        padc;
  196.     int        n;
  197.     unsigned int    u;
  198.     int        plus_sign;
  199.     int        sign_char;
  200.     boolean_t    altfmt;
  201.     int        base;
  202.     char        c;
  203.  
  204.     while (*fmt != '\0') {
  205.         if (*fmt != '%') {
  206.         (*putc)(putc_arg, *fmt++);
  207.         continue;
  208.         }
  209.  
  210.         fmt++;
  211.  
  212.         length = 0;
  213.         prec = -1;
  214.         ladjust = FALSE;
  215.         padc = ' ';
  216.         plus_sign = 0;
  217.         sign_char = 0;
  218.         altfmt = FALSE;
  219.  
  220.         while (TRUE) {
  221.         if (*fmt == '#') {
  222.             altfmt = TRUE;
  223.             fmt++;
  224.         }
  225.         else if (*fmt == '-') {
  226.             ladjust = TRUE;
  227.             fmt++;
  228.         }
  229.         else if (*fmt == '+') {
  230.             plus_sign = '+';
  231.             fmt++;
  232.         }
  233.         else if (*fmt == ' ') {
  234.             if (plus_sign == 0)
  235.             plus_sign = ' ';
  236.             fmt++;
  237.         }
  238.         else
  239.             break;
  240.         }
  241.  
  242.         if (*fmt == '0') {
  243.         padc = '0';
  244.         fmt++;
  245.         }
  246.  
  247.         if (isdigit(*fmt)) {
  248.         while(isdigit(*fmt))
  249.             length = 10 * length + Ctod(*fmt++);
  250.         }
  251.         else if (*fmt == '*') {
  252.         length = va_arg(args, int);
  253.         fmt++;
  254.         if (length < 0) {
  255.             ladjust = !ladjust;
  256.             length = -length;
  257.         }
  258.         }
  259.  
  260.         if (*fmt == '.') {
  261.         fmt++;
  262.         if (isdigit(*fmt)) {
  263.             prec = 0;
  264.             while(isdigit(*fmt))
  265.             prec = 10 * prec + Ctod(*fmt++);
  266.         }
  267.         else if (*fmt == '*') {
  268.             prec = va_arg(args, int);
  269.             fmt++;
  270.         }
  271.         }
  272.  
  273.         if (*fmt == 'l')
  274.         fmt++;    /* need it if sizeof(int) < sizeof(long) */
  275.  
  276.         switch(*fmt) {
  277.         case 'b':
  278.         case 'B':
  279.         {
  280.             register char *p;
  281.             boolean_t      any;
  282.             register int  i;
  283.  
  284.             u = va_arg(args, unsigned int);
  285.             p = va_arg(args, char *);
  286.             base = *p++;
  287.             printnum(u, base, putc, putc_arg);
  288.  
  289.             if (u == 0)
  290.             break;
  291.  
  292.             any = FALSE;
  293.             while (i = *p++) {
  294.             if (*p <= 32) {
  295.                 /*
  296.                  * Bit field
  297.                  */
  298.                 register int j;
  299.                 if (any)
  300.                 (*putc)(putc_arg, ',');
  301.                 else {
  302.                 (*putc)(putc_arg, '<');
  303.                 any = TRUE;
  304.                 }
  305.                 j = *p++;
  306.                 for (; (c = *p) > 32; p++)
  307.                 (*putc)(putc_arg, c);
  308.                 printnum((unsigned)( (u>>(j-1)) & ((2<<(i-j))-1)),
  309.                     base, putc, putc_arg);
  310.             }
  311.             else if (u & (1<<(i-1))) {
  312.                 if (any)
  313.                 (*putc)(putc_arg, ',');
  314.                 else {
  315.                 (*putc)(putc_arg, '<');
  316.                 any = TRUE;
  317.                 }
  318.                 for (; (c = *p) > 32; p++)
  319.                 (*putc)(putc_arg, c);
  320.             }
  321.             else {
  322.                 for (; *p > 32; p++)
  323.                 continue;
  324.             }
  325.             }
  326.             if (any)
  327.             (*putc)(putc_arg, '>');
  328.             break;
  329.         }
  330.  
  331.         case 'c':
  332.             c = va_arg(args, int);
  333.             (*putc)(putc_arg, c);
  334.             break;
  335.  
  336.         case 's':
  337.         {
  338.             register char *p;
  339.             register char *p2;
  340.  
  341.             if (prec == -1)
  342.             prec = 0x7fffffff;    /* MAXINT */
  343.  
  344.             p = va_arg(args, char *);
  345.  
  346.             if (p == (char *)0)
  347.             p = "";
  348.  
  349.             if (length > 0 && !ladjust) {
  350.             n = 0;
  351.             p2 = p;
  352.  
  353.             for (; *p != '\0' && n < prec; p++)
  354.                 n++;
  355.  
  356.             p = p2;
  357.  
  358.             while (n < length) {
  359.                 (*putc)(putc_arg, ' ');
  360.                 n++;
  361.             }
  362.             }
  363.  
  364.             n = 0;
  365.  
  366.             while (*p != '\0') {
  367.             if (++n > prec)
  368.                 break;
  369.  
  370.             (*putc)(putc_arg, *p++);
  371.             }
  372.  
  373.             if (n < length && ladjust) {
  374.             while (n < length) {
  375.                 (*putc)(putc_arg, ' ');
  376.                 n++;
  377.             }
  378.             }
  379.  
  380.             break;
  381.         }
  382.  
  383.         case 'o':
  384.         case 'O':
  385.             base = 8;
  386.             goto print_unsigned;
  387.  
  388.         case 'd':
  389.         case 'D':
  390.             base = 10;
  391.             goto print_signed;
  392.  
  393.         case 'u':
  394.         case 'U':
  395.             base = 10;
  396.             goto print_unsigned;
  397.  
  398.         case 'x':
  399.         case 'X':
  400.             base = 16;
  401.             goto print_unsigned;
  402.  
  403.         case 'z':
  404.         case 'Z':
  405.             base = 16;
  406.             goto print_signed;
  407.  
  408.         case 'r':
  409.         case 'R':
  410.             base = radix;
  411.             goto print_signed;
  412.  
  413.         case 'n':
  414.             base = radix;
  415.             goto print_unsigned;
  416.  
  417.         print_signed:
  418.             n = va_arg(args, int);
  419.             if (n >= 0) {
  420.             u = n;
  421.             sign_char = plus_sign;
  422.             }
  423.             else {
  424.             u = -n;
  425.             sign_char = '-';
  426.             }
  427.             goto print_num;
  428.  
  429.         print_unsigned:
  430.             u = va_arg(args, unsigned int);
  431.             goto print_num;
  432.  
  433.         print_num:
  434.         {
  435.             char    buf[MAXBUF];    /* build number here */
  436.             register char *    p = &buf[MAXBUF-1];
  437.             static char digits[] = "0123456789abcdef";
  438.             char *prefix = 0;
  439.  
  440.             if (u != 0 && altfmt) {
  441.             if (base == 8)
  442.                 prefix = "0";
  443.             else if (base == 16)
  444.                 prefix = "0x";
  445.             }
  446.  
  447.             do {
  448.             *p-- = digits[u % base];
  449.             u /= base;
  450.             } while (u != 0);
  451.  
  452.             length -= (&buf[MAXBUF-1] - p);
  453.             if (sign_char)
  454.             length--;
  455.             if (prefix)
  456.             length -= strlen(prefix);
  457.  
  458.             if (padc == ' ' && !ladjust) {
  459.             /* blank padding goes before prefix */
  460.             while (--length >= 0)
  461.                 (*putc)(putc_arg, ' ');
  462.             }
  463.             if (sign_char)
  464.             (*putc)(putc_arg, sign_char);
  465.             if (prefix)
  466.             while (*prefix)
  467.                 (*putc)(putc_arg, *prefix++);
  468.             if (padc == '0') {
  469.             /* zero padding goes after sign and prefix */
  470.             while (--length >= 0)
  471.                 (*putc)(putc_arg, '0');
  472.             }
  473.             while (++p != &buf[MAXBUF])
  474.             (*putc)(putc_arg, *p);
  475.  
  476.             if (ladjust) {
  477.             while (--length >= 0)
  478.                 (*putc)(putc_arg, ' ');
  479.             }
  480.             break;
  481.         }
  482.  
  483.         case '\0':
  484.             fmt--;
  485.             break;
  486.  
  487.         default:
  488.             (*putc)(putc_arg, *fmt);
  489.         }
  490.     fmt++;
  491.     }
  492. }
  493.