source: mainline/boot/generic/printf.c@ eda7bf81

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since eda7bf81 was fb0e6f03, checked in by jermar <jermar@…>, 17 years ago

Merge the boot branch.

  • Property mode set to 100644
File size: 5.9 KB
Line 
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
33typedef char *char_ptr;
34
35static char digits[] = "0123456789abcdef"; /**< Hexadecimal characters */
36
37void 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 */
59static 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 */
78static 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 */
148void 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
236loop:
237 ;
238 }
239
240out:
241
242 va_end(ap);
243}
Note: See TracBrowser for help on using the repository browser.