ia64/xen-unstable

view extras/mini-os/lib/printf.c @ 1534:793f5eb5d149

bitkeeper revision 1.996 (40d7f3c2ByN1WWCHbNtt1l_a8at-GQ)

Merge http://xen.bkbits.net:8080/xeno-unstable.bk
into gandalf.hpl.hp.com:/var/bk/xeno-unstable.bk
author xenbk@gandalf.hpl.hp.com
date Tue Jun 22 08:54:26 2004 +0000 (2004-06-22)
parents aadd0dc51c45
children f023d40722e4
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_write(printk_buf, strlen(printk_buf));
88 return retval;
89 }
91 int
92 vprintf(const char *fmt, va_list ap)
93 {
94 int retval;
95 static char printk_buf[1024];
96 retval = kvprintf(fmt, printk_buf, 10, ap);
97 printk_buf[retval] = '\0';
98 (void)HYPERVISOR_console_write(printk_buf, strlen(printk_buf));
99 return retval;
100 }
102 int
103 sprintf(char *buf, const char *cfmt, ...)
104 {
105 int retval;
106 va_list ap;
108 va_start(ap, cfmt);
109 retval = kvprintf(cfmt, (void *)buf, 10, ap);
110 buf[retval] = '\0';
111 va_end(ap);
112 return retval;
113 }
115 int
116 vsprintf(char *buf, const char *cfmt, va_list ap)
117 {
118 int retval;
120 retval = kvprintf(cfmt, (void *)buf, 10, ap);
121 buf[retval] = '\0';
122 return retval;
123 }
126 /*
127 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
128 * order; return an optional length and a pointer to the last character
129 * written in the buffer (i.e., the first character of the string).
130 * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
131 */
132 static char *
133 ksprintn(char *nbuf, u_long ul, int base, int *lenp)
134 {
135 char *p;
137 p = nbuf;
138 *p = '\0';
139 do {
140 *++p = hex2ascii(ul % base);
141 } while (ul /= base);
142 if (lenp)
143 *lenp = p - nbuf;
144 return (p);
145 }
146 /* ksprintn, but for a quad_t. */
147 static char *
148 ksprintqn(char *nbuf, u_quad_t uq, int base, int *lenp)
149 {
150 char *p;
152 p = nbuf;
153 *p = '\0';
154 do {
155 *++p = hex2ascii(uq % base);
156 } while (uq /= base);
157 if (lenp)
158 *lenp = p - nbuf;
159 return (p);
160 }
162 /*
163 * Scaled down version of printf(3).
164 *
165 * Two additional formats:
166 *
167 * The format %b is supported to decode error registers.
168 * Its usage is:
169 *
170 * printf("reg=%b\n", regval, "<base><arg>*");
171 *
172 * where <base> is the output base expressed as a control character, e.g.
173 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
174 * the first of which gives the bit number to be inspected (origin 1), and
175 * the next characters (up to a control character, i.e. a character <= 32),
176 * give the name of the register. Thus:
177 *
178 * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
179 *
180 * would produce output:
181 *
182 * reg=3<BITTWO,BITONE>
183 *
184 * XXX: %D -- Hexdump, takes pointer and separator string:
185 * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
186 * ("%*D", len, ptr, " " -> XX XX XX XX ...
187 */
189 /* RN: This normally takes a function for output.
190 * we always print to a string and the use HYPERCALL for write to console */
191 static int
192 kvprintf(char const *fmt, void *arg, int radix, va_list ap)
193 {
195 #define PCHAR(c) {int cc=(c); *d++ = cc; retval++; }
197 char nbuf[MAXNBUF];
198 char *p, *q, *d;
199 u_char *up;
200 int ch, n;
201 u_long ul;
202 u_quad_t uq;
203 int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
204 int dwidth;
205 char padc;
206 int retval = 0;
208 ul = 0;
209 uq = 0;
210 d = (char *) arg;
212 if (fmt == NULL)
213 fmt = "(fmt null)\n";
215 if (radix < 2 || radix > 36)
216 radix = 10;
218 for (;;) {
219 padc = ' ';
220 width = 0;
221 while ((ch = (u_char)*fmt++) != '%') {
222 if (ch == '\0')
223 return retval;
224 PCHAR(ch);
225 }
226 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
227 sign = 0; dot = 0; dwidth = 0;
228 reswitch: switch (ch = (u_char)*fmt++) {
229 case '.':
230 dot = 1;
231 goto reswitch;
232 case '#':
233 sharpflag = 1;
234 goto reswitch;
235 case '+':
236 sign = 1;
237 goto reswitch;
238 case '-':
239 ladjust = 1;
240 goto reswitch;
241 case '%':
242 PCHAR(ch);
243 break;
244 case '*':
245 if (!dot) {
246 width = va_arg(ap, int);
247 if (width < 0) {
248 ladjust = !ladjust;
249 width = -width;
250 }
251 } else {
252 dwidth = va_arg(ap, int);
253 }
254 goto reswitch;
255 case '0':
256 if (!dot) {
257 padc = '0';
258 goto reswitch;
259 }
260 case '1': case '2': case '3': case '4':
261 case '5': case '6': case '7': case '8': case '9':
262 for (n = 0;; ++fmt) {
263 n = n * 10 + ch - '0';
264 ch = *fmt;
265 if (ch < '0' || ch > '9')
266 break;
267 }
268 if (dot)
269 dwidth = n;
270 else
271 width = n;
272 goto reswitch;
273 case 'b':
274 ul = va_arg(ap, int);
275 p = va_arg(ap, char *);
276 for (q = ksprintn(nbuf, ul, *p++, NULL); *q;)
277 PCHAR(*q--);
279 if (!ul)
280 break;
282 for (tmp = 0; *p;) {
283 n = *p++;
284 if (ul & (1 << (n - 1))) {
285 PCHAR(tmp ? ',' : '<');
286 for (; (n = *p) > ' '; ++p)
287 PCHAR(n);
288 tmp = 1;
289 } else
290 for (; *p > ' '; ++p)
291 continue;
292 }
293 if (tmp)
294 PCHAR('>');
295 break;
296 case 'c':
297 PCHAR(va_arg(ap, int));
298 break;
299 case 'D':
300 up = va_arg(ap, u_char *);
301 p = va_arg(ap, char *);
302 if (!width)
303 width = 16;
304 while(width--) {
305 PCHAR(hex2ascii(*up >> 4));
306 PCHAR(hex2ascii(*up & 0x0f));
307 up++;
308 if (width)
309 for (q=p;*q;q++)
310 PCHAR(*q);
311 }
312 break;
313 case 'd':
314 if (qflag)
315 uq = va_arg(ap, quad_t);
316 else if (lflag)
317 ul = va_arg(ap, long);
318 else
319 ul = va_arg(ap, int);
320 sign = 1;
321 base = 10;
322 goto number;
323 case 'l':
324 if (lflag) {
325 lflag = 0;
326 qflag = 1;
327 } else
328 lflag = 1;
329 goto reswitch;
330 case 'o':
331 if (qflag)
332 uq = va_arg(ap, u_quad_t);
333 else if (lflag)
334 ul = va_arg(ap, u_long);
335 else
336 ul = va_arg(ap, u_int);
337 base = 8;
338 goto nosign;
339 case 'p':
340 ul = (uintptr_t)va_arg(ap, void *);
341 base = 16;
342 sharpflag = (width == 0);
343 goto nosign;
344 case 'q':
345 qflag = 1;
346 goto reswitch;
347 case 'n':
348 case 'r':
349 if (qflag)
350 uq = va_arg(ap, u_quad_t);
351 else if (lflag)
352 ul = va_arg(ap, u_long);
353 else
354 ul = sign ?
355 (u_long)va_arg(ap, int) : va_arg(ap, u_int);
356 base = radix;
357 goto number;
358 case 's':
359 p = va_arg(ap, char *);
360 if (p == NULL)
361 p = "(null)";
362 if (!dot)
363 n = strlen (p);
364 else
365 for (n = 0; n < dwidth && p[n]; n++)
366 continue;
368 width -= n;
370 if (!ladjust && width > 0)
371 while (width--)
372 PCHAR(padc);
373 while (n--)
374 PCHAR(*p++);
375 if (ladjust && width > 0)
376 while (width--)
377 PCHAR(padc);
378 break;
379 case 'u':
380 if (qflag)
381 uq = va_arg(ap, u_quad_t);
382 else if (lflag)
383 ul = va_arg(ap, u_long);
384 else
385 ul = va_arg(ap, u_int);
386 base = 10;
387 goto nosign;
388 case 'x':
389 case 'X':
390 if (qflag)
391 uq = va_arg(ap, u_quad_t);
392 else if (lflag)
393 ul = va_arg(ap, u_long);
394 else
395 ul = va_arg(ap, u_int);
396 base = 16;
397 goto nosign;
398 case 'z':
399 if (qflag)
400 uq = va_arg(ap, u_quad_t);
401 else if (lflag)
402 ul = va_arg(ap, u_long);
403 else
404 ul = sign ?
405 (u_long)va_arg(ap, int) : va_arg(ap, u_int);
406 base = 16;
407 goto number;
408 nosign: sign = 0;
409 number:
410 if (qflag) {
411 if (sign && (quad_t)uq < 0) {
412 neg = 1;
413 uq = -(quad_t)uq;
414 }
415 p = ksprintqn(nbuf, uq, base, &tmp);
416 } else {
417 if (sign && (long)ul < 0) {
418 neg = 1;
419 ul = -(long)ul;
420 }
421 p = ksprintn(nbuf, ul, base, &tmp);
422 }
423 if (sharpflag && (qflag ? uq != 0 : ul != 0)) {
424 if (base == 8)
425 tmp++;
426 else if (base == 16)
427 tmp += 2;
428 }
429 if (neg)
430 tmp++;
432 if (!ladjust && width && (width -= tmp) > 0)
433 while (width--)
434 PCHAR(padc);
435 if (neg)
436 PCHAR('-');
437 if (sharpflag && (qflag ? uq != 0 : ul != 0)) {
438 if (base == 8) {
439 PCHAR('0');
440 } else if (base == 16) {
441 PCHAR('0');
442 PCHAR('x');
443 }
444 }
446 while (*p)
447 PCHAR(*p--);
449 if (ladjust && width && (width -= tmp) > 0)
450 while (width--)
451 PCHAR(padc);
453 break;
454 default:
455 PCHAR('%');
456 if (lflag)
457 PCHAR('l');
458 PCHAR(ch);
459 break;
460 }
461 }
462 #undef PCHAR
463 }