Subversion Repositories HelenOS

Rev

Rev 3022 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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