Subversion Repositories HelenOS-historic

Rev

Rev 675 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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