Subversion Repositories HelenOS-historic

Rev

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