ia64/xen-unstable

view extras/mini-os/lib/printf.c @ 4146:f2d61710e4d9

bitkeeper revision 1.1236.25.24 (42366e9aQ71LQ8uCB-Y1IwVNqx5eqA)

Merge djm@kirby.fc.hp.com://home/djm/src/xen/xeno-unstable-ia64.bk
into sportsman.spdomain:/home/djm/xeno-unstable-ia64.bk
author djm@sportsman.spdomain
date Tue Mar 15 05:11:54 2005 +0000 (2005-03-15)
parents 7561a06348cf
children df1348e72390 cdfa7dd00c44 b2f4823b6ff0
line source
1 /* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
2 ****************************************************************************
3 * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
4 ****************************************************************************
5 *
6 * File: printf.c
7 * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
8 * Changes:
9 *
10 * Date: Aug 2003
11 *
12 * Environment: Xen Minimal OS
13 * Description: Library functions for printing
14 * (freebsd port, mainly sys/subr_prf.c)
15 *
16 ****************************************************************************
17 * $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $
18 ****************************************************************************
19 *
20 *-
21 * Copyright (c) 1992, 1993
22 * The Regents of the University of California. All rights reserved.
23 *
24 * This software was developed by the Computer Systems Engineering group
25 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
26 * contributed to Berkeley.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
30 * are met:
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 *
56 * $FreeBSD: src/sys/libkern/divdi3.c,v 1.6 1999/08/28 00:46:31 peter Exp $
57 */
59 #include <os.h>
60 #include <types.h>
61 #include <hypervisor.h>
62 #include <lib.h>
64 /****************************************************************************
65 * RN: printf family of routines
66 * taken mainly from sys/subr_prf.c
67 ****************************************************************************/
68 char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
69 #define hex2ascii(hex) (hex2ascii_data[hex])
70 #define NBBY 8 /* number of bits in a byte */
71 #define MAXNBUF (sizeof(quad_t) * NBBY + 1)
73 static int kvprintf(char const *fmt, void *arg, int radix, va_list ap);
76 int
77 printf(const char *fmt, ...)
78 {
79 va_list ap;
80 int retval;
81 static char printk_buf[1024];
83 va_start(ap, fmt);
84 retval = kvprintf(fmt, printk_buf, 10, ap);
85 printk_buf[retval] = '\0';
86 va_end(ap);
87 (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(printk_buf),
88 printk_buf);
89 return retval;
90 }
92 int
93 vprintf(const char *fmt, va_list ap)
94 {
95 int retval;
96 static char printk_buf[1024];
97 retval = kvprintf(fmt, printk_buf, 10, ap);
98 printk_buf[retval] = '\0';
99 (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(printk_buf),
100 printk_buf);
101 return retval;
102 }
104 int
105 sprintf(char *buf, const char *cfmt, ...)
106 {
107 int retval;
108 va_list ap;
110 va_start(ap, cfmt);
111 retval = kvprintf(cfmt, (void *)buf, 10, ap);
112 buf[retval] = '\0';
113 va_end(ap);
114 return retval;
115 }
117 int
118 vsprintf(char *buf, const char *cfmt, va_list ap)
119 {
120 int retval;
122 retval = kvprintf(cfmt, (void *)buf, 10, ap);
123 buf[retval] = '\0';
124 return retval;
125 }
128 /*
129 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
130 * order; return an optional length and a pointer to the last character
131 * written in the buffer (i.e., the first character of the string).
132 * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
133 */
134 static char *
135 ksprintn(char *nbuf, u_long ul, int base, int *lenp)
136 {
137 char *p;
139 p = nbuf;
140 *p = '\0';
141 do {
142 *++p = hex2ascii(ul % base);
143 } while (ul /= base);
144 if (lenp)
145 *lenp = p - nbuf;
146 return (p);
147 }
148 /* ksprintn, but for a quad_t. */
149 static char *
150 ksprintqn(char *nbuf, u_quad_t uq, int base, int *lenp)
151 {
152 char *p;
154 p = nbuf;
155 *p = '\0';
156 do {
157 *++p = hex2ascii(uq % base);
158 } while (uq /= base);
159 if (lenp)
160 *lenp = p - nbuf;
161 return (p);
162 }
164 /*
165 * Scaled down version of printf(3).
166 *
167 * Two additional formats:
168 *
169 * The format %b is supported to decode error registers.
170 * Its usage is:
171 *
172 * printf("reg=%b\n", regval, "<base><arg>*");
173 *
174 * where <base> is the output base expressed as a control character, e.g.
175 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
176 * the first of which gives the bit number to be inspected (origin 1), and
177 * the next characters (up to a control character, i.e. a character <= 32),
178 * give the name of the register. Thus:
179 *
180 * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
181 *
182 * would produce output:
183 *
184 * reg=3<BITTWO,BITONE>
185 *
186 * XXX: %D -- Hexdump, takes pointer and separator string:
187 * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
188 * ("%*D", len, ptr, " " -> XX XX XX XX ...
189 */
191 /* RN: This normally takes a function for output.
192 * we always print to a string and the use HYPERCALL for write to console */
193 static int
194 kvprintf(char const *fmt, void *arg, int radix, va_list ap)
195 {
197 #define PCHAR(c) {int cc=(c); *d++ = cc; retval++; }
199 char nbuf[MAXNBUF];
200 char *p, *q, *d;
201 u_char *up;
202 int ch, n;
203 u_long ul;
204 u_quad_t uq;
205 int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
206 int dwidth;
207 char padc;
208 int retval = 0;
210 ul = 0;
211 uq = 0;
212 d = (char *) arg;
214 if (fmt == NULL)
215 fmt = "(fmt null)\n";
217 if (radix < 2 || radix > 36)
218 radix = 10;
220 for (;;) {
221 padc = ' ';
222 width = 0;
223 while ((ch = (u_char)*fmt++) != '%') {
224 if (ch == '\0')
225 return retval;
226 PCHAR(ch);
227 }
228 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
229 sign = 0; dot = 0; dwidth = 0;
230 reswitch: switch (ch = (u_char)*fmt++) {
231 case '.':
232 dot = 1;
233 goto reswitch;
234 case '#':
235 sharpflag = 1;
236 goto reswitch;
237 case '+':
238 sign = 1;
239 goto reswitch;
240 case '-':
241 ladjust = 1;
242 goto reswitch;
243 case '%':
244 PCHAR(ch);
245 break;
246 case '*':
247 if (!dot) {
248 width = va_arg(ap, int);
249 if (width < 0) {
250 ladjust = !ladjust;
251 width = -width;
252 }
253 } else {
254 dwidth = va_arg(ap, int);
255 }
256 goto reswitch;
257 case '0':
258 if (!dot) {
259 padc = '0';
260 goto reswitch;
261 }
262 case '1': case '2': case '3': case '4':
263 case '5': case '6': case '7': case '8': case '9':
264 for (n = 0;; ++fmt) {
265 n = n * 10 + ch - '0';
266 ch = *fmt;
267 if (ch < '0' || ch > '9')
268 break;
269 }
270 if (dot)
271 dwidth = n;
272 else
273 width = n;
274 goto reswitch;
275 case 'b':
276 ul = va_arg(ap, int);
277 p = va_arg(ap, char *);
278 for (q = ksprintn(nbuf, ul, *p++, NULL); *q;)
279 PCHAR(*q--);
281 if (!ul)
282 break;
284 for (tmp = 0; *p;) {
285 n = *p++;
286 if (ul & (1 << (n - 1))) {
287 PCHAR(tmp ? ',' : '<');
288 for (; (n = *p) > ' '; ++p)
289 PCHAR(n);
290 tmp = 1;
291 } else
292 for (; *p > ' '; ++p)
293 continue;
294 }
295 if (tmp)
296 PCHAR('>');
297 break;
298 case 'c':
299 PCHAR(va_arg(ap, int));
300 break;
301 case 'D':
302 up = va_arg(ap, u_char *);
303 p = va_arg(ap, char *);
304 if (!width)
305 width = 16;
306 while(width--) {
307 PCHAR(hex2ascii(*up >> 4));
308 PCHAR(hex2ascii(*up & 0x0f));
309 up++;
310 if (width)
311 for (q=p;*q;q++)
312 PCHAR(*q);
313 }
314 break;
315 case 'd':
316 if (qflag)
317 uq = va_arg(ap, quad_t);
318 else if (lflag)
319 ul = va_arg(ap, long);
320 else
321 ul = va_arg(ap, int);
322 sign = 1;
323 base = 10;
324 goto number;
325 case 'l':
326 if (lflag) {
327 lflag = 0;
328 qflag = 1;
329 } else
330 lflag = 1;
331 goto reswitch;
332 case 'o':
333 if (qflag)
334 uq = va_arg(ap, u_quad_t);
335 else if (lflag)
336 ul = va_arg(ap, u_long);
337 else
338 ul = va_arg(ap, u_int);
339 base = 8;
340 goto nosign;
341 case 'p':
342 ul = (uintptr_t)va_arg(ap, void *);
343 base = 16;
344 sharpflag = 0;
345 padc = '0';
346 width = sizeof(uintptr_t)*2;
347 goto nosign;
348 case 'q':
349 qflag = 1;
350 goto reswitch;
351 case 'n':
352 case 'r':
353 if (qflag)
354 uq = va_arg(ap, u_quad_t);
355 else if (lflag)
356 ul = va_arg(ap, u_long);
357 else
358 ul = sign ?
359 (u_long)va_arg(ap, int) : va_arg(ap, u_int);
360 base = radix;
361 goto number;
362 case 's':
363 p = va_arg(ap, char *);
364 if (p == NULL)
365 p = "(null)";
366 if (!dot)
367 n = strlen (p);
368 else
369 for (n = 0; n < dwidth && p[n]; n++)
370 continue;
372 width -= n;
374 if (!ladjust && width > 0)
375 while (width--)
376 PCHAR(padc);
377 while (n--)
378 PCHAR(*p++);
379 if (ladjust && width > 0)
380 while (width--)
381 PCHAR(padc);
382 break;
383 case 'u':
384 if (qflag)
385 uq = va_arg(ap, u_quad_t);
386 else if (lflag)
387 ul = va_arg(ap, u_long);
388 else
389 ul = va_arg(ap, u_int);
390 base = 10;
391 goto nosign;
392 case 'x':
393 case 'X':
394 if (qflag)
395 uq = va_arg(ap, u_quad_t);
396 else if (lflag)
397 ul = va_arg(ap, u_long);
398 else
399 ul = va_arg(ap, u_int);
400 base = 16;
401 goto nosign;
402 case 'z':
403 if (qflag)
404 uq = va_arg(ap, u_quad_t);
405 else if (lflag)
406 ul = va_arg(ap, u_long);
407 else
408 ul = sign ?
409 (u_long)va_arg(ap, int) : va_arg(ap, u_int);
410 base = 16;
411 goto number;
412 nosign: sign = 0;
413 number:
414 if (qflag) {
415 if (sign && (quad_t)uq < 0) {
416 neg = 1;
417 uq = -(quad_t)uq;
418 }
419 p = ksprintqn(nbuf, uq, base, &tmp);
420 } else {
421 if (sign && (long)ul < 0) {
422 neg = 1;
423 ul = -(long)ul;
424 }
425 p = ksprintn(nbuf, ul, base, &tmp);
426 }
427 if (sharpflag && (qflag ? uq != 0 : ul != 0)) {
428 if (base == 8)
429 tmp++;
430 else if (base == 16)
431 tmp += 2;
432 }
433 if (neg)
434 tmp++;
436 if (!ladjust && width && (width -= tmp) > 0)
437 while (width--)
438 PCHAR(padc);
439 if (neg)
440 PCHAR('-');
441 if (sharpflag && (qflag ? uq != 0 : ul != 0)) {
442 if (base == 8) {
443 PCHAR('0');
444 } else if (base == 16) {
445 PCHAR('0');
446 PCHAR('x');
447 }
448 }
450 while (*p)
451 PCHAR(*p--);
453 if (ladjust && width && (width -= tmp) > 0)
454 while (width--)
455 PCHAR(padc);
457 break;
458 default:
459 PCHAR('%');
460 if (lflag)
461 PCHAR('l');
462 PCHAR(ch);
463 break;
464 }
465 }
466 #undef PCHAR
467 }