source: mainline/generic/src/debug/print.c@ 38ee55b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 38ee55b was 226a654, checked in by Josef Cejka <malyzelenyhnus@…>, 19 years ago

Printf correctly handle NULL pointer as parameter to %s option.

  • Property mode set to 100644
File size: 6.5 KB
Line 
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
37static char digits[] = "0123456789abcdef"; /**< Hexadecimal characters */
38SPINLOCK_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 */
49static 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 */
77static 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 */
96static 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 */
167void 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
257loop:
258 ;
259 }
260
261out:
262 spinlock_unlock(&printflock);
263 interrupts_restore(irqpri);
264
265 va_end(ap);
266}
Note: See TracBrowser for help on using the repository browser.