Subversion Repositories HelenOS

Rev

Rev 1787 | Rev 2465 | Go to most recent revision | 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. #include "printf.h"
  30. #include "stdarg.h"
  31. #include <types.h>
  32.  
  33. typedef char *char_ptr;
  34.  
  35. static char digits[] = "0123456789abcdef";  /**< Hexadecimal characters */
  36.  
  37. void puts(const char *str)
  38. {
  39.     int len = 0;
  40.    
  41.     while (str[len] != 0)
  42.         len++;
  43.    
  44.     write(str, len);
  45. }
  46.  
  47.  
  48. /** Print hexadecimal digits
  49.  *
  50.  * Print fixed count of hexadecimal digits from
  51.  * the number num. The digits are printed in
  52.  * natural left-to-right order starting with
  53.  * the width-th digit.
  54.  *
  55.  * @param num   Number containing digits.
  56.  * @param width Count of digits to print.
  57.  *
  58.  */
  59. static void print_fixed_hex(const uint64_t num, const int width)
  60. {
  61.     int i;
  62.    
  63.     for (i = width * 8 - 4; i >= 0; i -= 4)
  64.         write(digits + ((num >> i) & 0xf), 1);
  65. }
  66.  
  67.  
  68. /** Print number in given base
  69.  *
  70.  * Print significant digits of a number in given
  71.  * base.
  72.  *
  73.  * @param num  Number to print.
  74.  * @param base Base to print the number in (should
  75.  *             be in range 2 .. 16).
  76.  *
  77.  */
  78. static void print_number(const unative_t num, const unsigned int base)
  79. {
  80.     int val = num;
  81.     char d[sizeof(unative_t) * 8 + 1];      /* this is good enough even for base == 2 */
  82.     int i = sizeof(unative_t) * 8 - 1;
  83.    
  84.     do {
  85.         d[i--] = digits[val % base];
  86.     } while (val /= base);
  87.    
  88.     d[sizeof(unative_t) * 8] = 0;  
  89.     puts(&d[i + 1]);
  90. }
  91.  
  92.  
  93. /** General formatted text print
  94.  *
  95.  * Print text formatted according the fmt parameter
  96.  * and variant arguments. Each formatting directive
  97.  * begins with \% (percentage) character and one of the
  98.  * following character:
  99.  *
  100.  * \%    Prints the percentage character.
  101.  *
  102.  * s    The next variant argument is treated as char*
  103.  *      and printed as a NULL terminated string.
  104.  *
  105.  * c    The next variant argument is treated as a single char.
  106.  *
  107.  * p    The next variant argument is treated as a maximum
  108.  *      bit-width integer with respect to architecture
  109.  *      and printed in full hexadecimal width.
  110.  *
  111.  * P    As with 'p', but '0x' is prefixed.
  112.  *
  113.  * q    The next variant argument is treated as a 64b integer
  114.  *      and printed in full hexadecimal width.
  115.  *
  116.  * Q    As with 'q', but '0x' is prefixed.
  117.  *
  118.  * l    The next variant argument is treated as a 32b integer
  119.  *      and printed in full hexadecimal width.
  120.  *
  121.  * L    As with 'l', but '0x' is prefixed.
  122.  *
  123.  * w    The next variant argument is treated as a 16b integer
  124.  *      and printed in full hexadecimal width.
  125.  *
  126.  * W    As with 'w', but '0x' is prefixed.
  127.  *
  128.  * b    The next variant argument is treated as a 8b integer
  129.  *      and printed in full hexadecimal width.
  130.  *
  131.  * B    As with 'b', but '0x' is prefixed.
  132.  *
  133.  * d    The next variant argument is treated as integer
  134.  *      and printed in standard decimal format (only significant
  135.  *      digits).
  136.  *
  137.  * x    The next variant argument is treated as integer
  138.  *      and printed in standard hexadecimal format (only significant
  139.  *      digits).
  140.  *
  141.  * X    As with 'x', but '0x' is prefixed.
  142.  *
  143.  * All other characters from fmt except the formatting directives
  144.  * are printed in verbatim.
  145.  *
  146.  * @param fmt Formatting NULL terminated string.
  147.  */
  148. void printf(const char *fmt, ...)
  149. {
  150.     int i = 0;
  151.     va_list ap;
  152.     char c;
  153.    
  154.     va_start(ap, fmt);
  155.    
  156.     while ((c = fmt[i++])) {
  157.         switch (c) {
  158.            
  159.             /* control character */
  160.             case '%':
  161.                
  162.                 switch (c = fmt[i++]) {
  163.                    
  164.                     /* percentile itself */
  165.                     case '%':
  166.                         break;
  167.                    
  168.                     /*
  169.                      * String and character conversions.
  170.                      */
  171.                     case 's':
  172.                         puts(va_arg(ap, char_ptr));
  173.                         goto loop;
  174.                    
  175.                     case 'c':
  176.                         c = (char) va_arg(ap, int);
  177.                         break;
  178.                    
  179.                     /*
  180.                      * Hexadecimal conversions with fixed width.
  181.                      */
  182.                     case 'P':
  183.                         puts("0x");
  184.                     case 'p':
  185.                         print_fixed_hex(va_arg(ap, unative_t), sizeof(unative_t));
  186.                         goto loop;
  187.                    
  188.                     case 'Q':
  189.                         puts("0x");
  190.                     case 'q':
  191.                         print_fixed_hex(va_arg(ap, uint64_t), INT64);
  192.                         goto loop;
  193.                    
  194.                     case 'L':
  195.                         puts("0x");
  196.                     case 'l':
  197.                         print_fixed_hex(va_arg(ap, unative_t), INT32);
  198.                         goto loop;
  199.                    
  200.                     case 'W':
  201.                         puts("0x");
  202.                     case 'w':
  203.                         print_fixed_hex(va_arg(ap, unative_t), INT16);
  204.                         goto loop;
  205.                    
  206.                     case 'B':
  207.                         puts("0x");
  208.                     case 'b':
  209.                         print_fixed_hex(va_arg(ap, unative_t), INT8);
  210.                         goto loop;
  211.                    
  212.                     /*
  213.                      * Decimal and hexadecimal conversions.
  214.                      */
  215.                     case 'd':
  216.                         print_number(va_arg(ap, unative_t), 10);
  217.                         goto loop;
  218.                    
  219.                     case 'X':
  220.                         puts("0x");
  221.                     case 'x':
  222.                         print_number(va_arg(ap, unative_t), 16);
  223.                         goto loop;
  224.                    
  225.                     /*
  226.                      * Bad formatting.
  227.                      */
  228.                     default:
  229.                         goto out;
  230.             }
  231.            
  232.             default:
  233.                 write(&c, 1);
  234.         }
  235.    
  236. loop:
  237.         ;
  238.     }
  239.    
  240. out:
  241.    
  242.     va_end(ap);
  243. }
  244.