Subversion Repositories HelenOS

Rev

Rev 974 | Rev 992 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (C) 2001-2004 Jakub Jermar
  3.  * Copyright (C) 2006 Josef Cejka
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  *
  10.  * - Redistributions of source code must retain the above copyright
  11.  *   notice, this list of conditions and the following disclaimer.
  12.  * - Redistributions in binary form must reproduce the above copyright
  13.  *   notice, this list of conditions and the following disclaimer in the
  14.  *   documentation and/or other materials provided with the distribution.
  15.  * - The name of the author may not be used to endorse or promote products
  16.  *   derived from this software without specific prior written permission.
  17.  *
  18.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  19.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  20.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  21.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  22.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  23.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  25.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28.  */
  29.  
  30. #include <stdio.h>
  31. #include <unistd.h>
  32. #include <io/io.h>
  33. #include <stdarg.h>
  34.  
  35. static char digits[] = "0123456789abcdef";  /**< Hexadecimal characters */
  36.  
  37. /** Print hexadecimal digits
  38.  *
  39.  * Print fixed count of hexadecimal digits from
  40.  * the number num. The digits are printed in
  41.  * natural left-to-right order starting with
  42.  * the width-th digit.
  43.  *
  44.  * @param num   Number containing digits.
  45.  * @param width Count of digits to print.
  46.  *
  47.  */
  48. static int print_fixed_hex(const uint64_t num, const int width)
  49. {
  50.     int i;
  51.     char buf[16];
  52.     char *bptr;
  53.    
  54.     bptr = buf;
  55.     for (i = width*8 - 4; i >= 0; i -= 4)
  56.         *bptr++ = digits[(num>>i) & 0xf];
  57.     *bptr = '\0';
  58.    
  59.     return putstr(buf);
  60. }
  61.  
  62.  
  63. /** Print number in given base
  64.  *
  65.  * Print significant digits of a number in given
  66.  * base.
  67.  *
  68.  * @param num  Number to print.
  69.  * @param base Base to print the number in (should
  70.  *             be in range 2 .. 16).
  71.  *
  72.  */
  73. static int print_number(const unsigned int num, const unsigned int base)
  74. {
  75.     int val = num;
  76.     char d[sizeof(unsigned int)*8+1];   /* this is good enough even for base == 2 */
  77.     int i = sizeof(unsigned int)*8-1;
  78.    
  79.     do {
  80.         d[i--] = digits[val % base];
  81.     } while (val /= base);
  82.    
  83.     d[sizeof(unsigned int)*8] = 0; 
  84.  
  85.     return putstr(&d[i + 1]);
  86. }
  87.  
  88.  
  89.  
  90. /** General formatted text print
  91.  *
  92.  * Print text formatted according the fmt parameter
  93.  * and variant arguments. Each formatting directive
  94.  * begins with \% (percentage) character and one of the
  95.  * following character:
  96.  *
  97.  * \%    Prints the percentage character.
  98.  *
  99.  * s    The next variant argument is treated as char*
  100.  *      and printed as a NULL terminated string.
  101.  *
  102.  * c    The next variant argument is treated as a single char.
  103.  *
  104.  * p    The next variant argument is treated as a maximum
  105.  *      bit-width integer with respect to architecture
  106.  *      and printed in full hexadecimal width.
  107.  *
  108.  * P    As with 'p', but '0x' is prefixed.
  109.  *
  110.  * q    The next variant argument is treated as a 64b integer
  111.  *      and printed in full hexadecimal width.
  112.  *
  113.  * Q    As with 'q', but '0x' is prefixed.
  114.  *
  115.  * l    The next variant argument is treated as a 32b integer
  116.  *      and printed in full hexadecimal width.
  117.  *
  118.  * L    As with 'l', but '0x' is prefixed.
  119.  *
  120.  * w    The next variant argument is treated as a 16b integer
  121.  *      and printed in full hexadecimal width.
  122.  *
  123.  * W    As with 'w', but '0x' is prefixed.
  124.  *
  125.  * b    The next variant argument is treated as a 8b integer
  126.  *      and printed in full hexadecimal width.
  127.  *
  128.  * B    As with 'b', but '0x' is prefixed.
  129.  *
  130.  * d    The next variant argument is treated as integer
  131.  *      and printed in standard decimal format (only significant
  132.  *      digits).
  133.  *
  134.  * x    The next variant argument is treated as integer
  135.  *      and printed in standard hexadecimal format (only significant
  136.  *      digits).
  137.  *
  138.  * X    As with 'x', but '0x' is prefixed.
  139.  *
  140.  * All other characters from fmt except the formatting directives
  141.  * are printed in verbatim.
  142.  *
  143.  * @param fmt Formatting NULL terminated string.
  144.  */
  145. int printf(const char *fmt, ...)
  146. {
  147.     int i = 0, j = 0;
  148.     int counter, retval;
  149.     va_list ap;
  150.     char c;
  151.    
  152.     counter = 0;
  153.     va_start(ap, fmt);
  154.  
  155.     while ((c = fmt[i])) {
  156.             /* control character */
  157.         if (c == '%' ) {
  158.                 /* print common characters if any processed */ 
  159.             if (i > j) {
  160.                 if ((retval = putnchars(&fmt[j], i - j)) == EOF) { /* error */
  161.                     return -counter;
  162.                 }
  163.                 counter += retval;
  164.             }
  165.  
  166.             j = ++i;
  167.  
  168.             switch (c = fmt[i]) {
  169.  
  170.                 /* percentile itself */
  171.                 case '%':
  172.                     --j;    /* soon will be incremented back */
  173.                     break;
  174.  
  175.                 /*
  176.                 * String and character conversions.
  177.                 */
  178.                 case 's':
  179.                     if ((retval = putstr(va_arg(ap, char*))) == EOF) {
  180.                         return -counter;
  181.                     };
  182.                    
  183.                     counter += retval;
  184.                     break;
  185.                 case 'c':
  186.                     if ((retval = putnchars((char *)&va_arg(ap, int), sizeof(char))) == EOF) {
  187.                         return -counter;
  188.                     };
  189.                    
  190.                     counter += retval;
  191.                     break;
  192.  
  193.                 /*
  194.                 * Hexadecimal conversions with fixed width.
  195.                 */
  196.                 case 'P':
  197.                     if ((retval = putnchars("0x", 2)) == EOF) {
  198.                         return -counter;
  199.                     };
  200.                    
  201.                     counter += retval;
  202.                 case 'p':
  203.                         if ((retval = print_fixed_hex(va_arg(ap, int), sizeof(int))) == EOF ) {
  204.                         return -counter;
  205.                     };
  206.  
  207.                     counter += retval;
  208.                     break;
  209.                 case 'Q':
  210.                     if ((retval = putnchars("0x", 2)) == EOF) {
  211.                         return -counter;
  212.                     };
  213.                    
  214.                     counter += retval;
  215.                 case 'q':
  216.                         if ((retval = print_fixed_hex(va_arg(ap, uint64_t), sizeof(uint64_t))) == EOF ) {
  217.                         return -counter;
  218.                     };
  219.  
  220.                     counter += retval;
  221.                     break;
  222.                 case 'L':
  223.                     if ((retval = putnchars("0x", 2)) == EOF) {
  224.                         return -counter;
  225.                     };
  226.                    
  227.                     counter += retval;
  228.                 case 'l':
  229.                         if ((retval = print_fixed_hex(va_arg(ap, int), sizeof(uint32_t))) == EOF ) {
  230.                         return -counter;
  231.                     };
  232.  
  233.                     counter += retval;
  234.                     break;
  235.                 case 'W':
  236.                     if ((retval = putnchars("0x", 2)) == EOF) {
  237.                         return -counter;
  238.                     };
  239.                    
  240.                     counter += retval;
  241.                 case 'w':
  242.                         if ((retval = print_fixed_hex(va_arg(ap, int), sizeof(uint16_t))) == EOF ) {
  243.                         return -counter;
  244.                     };
  245.  
  246.                     counter += retval;
  247.                     break;
  248.                 case 'B':
  249.                     if ((retval = putnchars("0x", 2)) == EOF) {
  250.                         return -counter;
  251.                     };
  252.                    
  253.                     counter += retval;
  254.                 case 'b':
  255.                         if ((retval = print_fixed_hex(va_arg(ap, int), sizeof(uint8_t))) == EOF ) {
  256.                         return -counter;
  257.                     };
  258.  
  259.                     counter += retval;
  260.                     break;
  261.                 /*
  262.                 * Decimal and hexadecimal conversions.
  263.                 */
  264.                 case 'd':
  265.                         if ((retval = print_number(va_arg(ap, int), 10)) == EOF ) {
  266.                         return -counter;
  267.                     };
  268.  
  269.                     counter += retval;
  270.                     break;
  271.                 case 'X':
  272.                     if ((retval = putnchars("0x", 2)) == EOF) {
  273.                         return -counter;
  274.                     };
  275.                    
  276.                     counter += retval;
  277.                 case 'x':
  278.                         if ((retval = print_number(va_arg(ap, int), 16)) == EOF ) {
  279.                         return -counter;
  280.                     };
  281.  
  282.                     counter += retval;
  283.                     break;
  284.                 /*
  285.                 * Bad formatting.
  286.                 */
  287.                 default:
  288.                     return -counter;
  289.             }
  290.             ++j;
  291.         }  
  292.         ++i;
  293.     }
  294.    
  295.     if (i > j) {
  296.         if ((retval = putnchars(&fmt[j], i - j)) == EOF) { /* error */
  297.             return -counter;
  298.         }
  299.         counter += retval;
  300.     }
  301.    
  302.     va_end(ap);
  303.     return counter;
  304. }
  305.  
  306.