]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/printf.c
xnu-792.13.8.tar.gz
[apple/xnu.git] / osfmk / kern / printf.c
CommitLineData
1c79356b 1/*
5d5c5d0d 2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
8ad349bb 4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
1c79356b 5 *
8ad349bb
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
1c79356b
A
29 */
30/*
31 * @OSF_COPYRIGHT@
32 */
33
34/*
35 * Mach Operating System
36 * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
37 * All Rights Reserved.
38 *
39 * Permission to use, copy, modify and distribute this software and its
40 * documentation is hereby granted, provided that both the copyright
41 * notice and this permission notice appear in all copies of the
42 * software, derivative works or modified versions, and any portions
43 * thereof, and that both notices appear in supporting documentation.
44 *
45 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
46 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
47 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
48 *
49 * Carnegie Mellon requests users of this software to return to
50 *
51 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
52 * School of Computer Science
53 * Carnegie Mellon University
54 * Pittsburgh PA 15213-3890
55 *
56 * any improvements or extensions that they make and grant Carnegie Mellon
57 * the rights to redistribute these changes.
58 */
59
60/*
61 * Common code for printf et al.
62 *
63 * The calling routine typically takes a variable number of arguments,
64 * and passes the address of the first one. This implementation
65 * assumes a straightforward, stack implementation, aligned to the
66 * machine's wordsize. Increasing addresses are assumed to point to
67 * successive arguments (left-to-right), as is the case for a machine
68 * with a downward-growing stack with arguments pushed right-to-left.
69 *
70 * To write, for example, fprintf() using this routine, the code
71 *
72 * fprintf(fd, format, args)
73 * FILE *fd;
74 * char *format;
75 * {
76 * _doprnt(format, &args, fd);
77 * }
78 *
79 * would suffice. (This example does not handle the fprintf's "return
80 * value" correctly, but who looks at the return value of fprintf
81 * anyway?)
82 *
83 * This version implements the following printf features:
84 *
85 * %d decimal conversion
86 * %u unsigned conversion
87 * %x hexadecimal conversion
88 * %X hexadecimal conversion with capital letters
9bccf70c
A
89 * %D hexdump, ptr & separator string ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
90 * if you use, "%*D" then there's a length, the data ptr and then the separator
1c79356b
A
91 * %o octal conversion
92 * %c character
93 * %s string
94 * %m.n field width, precision
95 * %-m.n left adjustment
96 * %0m.n zero-padding
97 * %*.* width and precision taken from arguments
98 *
99 * This version does not implement %f, %e, or %g. It accepts, but
100 * ignores, an `l' as in %ld, %lo, %lx, and %lu, and therefore will not
101 * work correctly on machines for which sizeof(long) != sizeof(int).
1c79356b
A
102 *
103 * As mentioned, this version does not return any reasonable value.
104 *
105 * Permission is granted to use, modify, or propagate this code as
106 * long as this notice is incorporated.
107 *
108 * Steve Summit 3/25/87
9bccf70c
A
109 *
110 * Tweaked for long long support and extended to support the hexdump %D
111 * specifier by dbg 05/02/02.
1c79356b
A
112 */
113
114/*
115 * Added formats for decoding device registers:
116 *
117 * printf("reg = %b", regval, "<base><arg>*")
118 *
119 * where <base> is the output base expressed as a control character:
120 * i.e. '\10' gives octal, '\20' gives hex. Each <arg> is a sequence of
121 * characters, the first of which gives the bit number to be inspected
122 * (origin 1), and the rest (up to a control character (<= 32)) give the
123 * name of the register. Thus
124 * printf("reg = %b\n", 3, "\10\2BITTWO\1BITONE")
125 * would produce
126 * reg = 3<BITTWO,BITONE>
127 *
128 * If the second character in <arg> is also a control character, it
129 * indicates the last bit of a bit field. In this case, printf will extract
130 * bits <1> to <2> and print it. Characters following the second control
131 * character are printed before the bit field.
132 * printf("reg = %b\n", 0xb, "\10\4\3FIELD1=\2BITTWO\1BITONE")
133 * would produce
134 * reg = b<FIELD1=2,BITONE>
135 *
136 * The %B format is like %b but the bits are numbered from the most
137 * significant (the bit weighted 31), which is called 1, to the least
138 * significant, called 32.
139 */
140/*
141 * Added for general use:
142 * # prefix for alternate format:
143 * 0x (0X) for hex
144 * leading 0 for octal
145 * + print '+' if positive
146 * blank print ' ' if positive
147 *
148 * z signed hexadecimal
149 * r signed, 'radix'
150 * n unsigned, 'radix'
151 *
152 * D,U,O,Z same as corresponding lower-case versions
153 * (compatibility)
154 */
9bccf70c
A
155/*
156 * Added support for print long long (64-bit) integers.
157 * Use %lld, %Ld or %qd to print a 64-bit int. Other
158 * output bases such as x, X, u, U, o, and O also work.
159 */
1c79356b 160
55e303ae
A
161#include <debug.h>
162#include <mach_kdb.h>
163#include <mach_kdp.h>
1c79356b
A
164#include <platforms.h>
165#include <mach/boolean.h>
1c79356b
A
166#include <kern/cpu_number.h>
167#include <kern/lock.h>
168#include <kern/thread.h>
169#include <kern/sched_prim.h>
170#include <kern/misc_protos.h>
171#include <stdarg.h>
172#include <string.h>
173#include <mach_assert.h>
174#ifdef MACH_BSD
175#include <sys/msgbuf.h>
176#endif
177
178#ifdef __ppc__
179#include <ppc/Firmware.h>
180#endif
181
1c79356b
A
182#define isdigit(d) ((d) >= '0' && (d) <= '9')
183#define Ctod(c) ((c) - '0')
184
9bccf70c
A
185#define MAXBUF (sizeof(long long int) * 8) /* enough for binary */
186static char digs[] = "0123456789abcdef";
1c79356b 187
9bccf70c 188static int
1c79356b 189printnum(
9bccf70c 190 register unsigned long long int u, /* number to print */
1c79356b 191 register int base,
9bccf70c
A
192 void (*putc)(int, void *),
193 void *arg)
1c79356b
A
194{
195 char buf[MAXBUF]; /* build number here */
196 register char * p = &buf[MAXBUF-1];
9bccf70c 197 int nprinted = 0;
1c79356b
A
198
199 do {
200 *p-- = digs[u % base];
201 u /= base;
202 } while (u != 0);
203
9bccf70c
A
204 while (++p != &buf[MAXBUF]) {
205 (*putc)(*p, arg);
206 nprinted++;
207 }
1c79356b 208
9bccf70c 209 return nprinted;
1c79356b
A
210}
211
212boolean_t _doprnt_truncates = FALSE;
213
9bccf70c
A
214int
215__doprnt(
1c79356b
A
216 register const char *fmt,
217 va_list *argp,
218 /* character output routine */
9bccf70c
A
219 void (*putc)(int, void *arg),
220 void *arg,
1c79356b
A
221 int radix) /* default radix - for '%r' */
222{
223 int length;
224 int prec;
225 boolean_t ladjust;
226 char padc;
9bccf70c
A
227 long long n;
228 unsigned long long u;
1c79356b
A
229 int plus_sign;
230 int sign_char;
231 boolean_t altfmt, truncate;
232 int base;
233 register char c;
234 int capitals;
9bccf70c
A
235 int long_long;
236 int nprinted = 0;
1c79356b
A
237
238 while ((c = *fmt) != '\0') {
239 if (c != '%') {
9bccf70c
A
240 (*putc)(c, arg);
241 nprinted++;
1c79356b
A
242 fmt++;
243 continue;
244 }
245
246 fmt++;
247
9bccf70c 248 long_long = 0;
1c79356b
A
249 length = 0;
250 prec = -1;
251 ladjust = FALSE;
252 padc = ' ';
253 plus_sign = 0;
254 sign_char = 0;
255 altfmt = FALSE;
256
257 while (TRUE) {
258 c = *fmt;
259 if (c == '#') {
260 altfmt = TRUE;
261 }
262 else if (c == '-') {
263 ladjust = TRUE;
264 }
265 else if (c == '+') {
266 plus_sign = '+';
267 }
268 else if (c == ' ') {
269 if (plus_sign == 0)
270 plus_sign = ' ';
271 }
272 else
273 break;
274 fmt++;
275 }
276
277 if (c == '0') {
278 padc = '0';
279 c = *++fmt;
280 }
281
282 if (isdigit(c)) {
283 while(isdigit(c)) {
284 length = 10 * length + Ctod(c);
285 c = *++fmt;
286 }
287 }
288 else if (c == '*') {
289 length = va_arg(*argp, int);
290 c = *++fmt;
291 if (length < 0) {
292 ladjust = !ladjust;
293 length = -length;
294 }
295 }
296
297 if (c == '.') {
298 c = *++fmt;
299 if (isdigit(c)) {
300 prec = 0;
301 while(isdigit(c)) {
302 prec = 10 * prec + Ctod(c);
303 c = *++fmt;
304 }
305 }
306 else if (c == '*') {
307 prec = va_arg(*argp, int);
308 c = *++fmt;
309 }
310 }
311
9bccf70c 312 if (c == 'l') {
1c79356b 313 c = *++fmt; /* need it if sizeof(int) < sizeof(long) */
9bccf70c
A
314 if (c == 'l') {
315 long_long = 1;
316 c = *++fmt;
317 }
318 } else if (c == 'q' || c == 'L') {
319 long_long = 1;
320 c = *++fmt;
321 }
1c79356b
A
322
323 truncate = FALSE;
324 capitals=0; /* Assume lower case printing */
325
326 switch(c) {
327 case 'b':
328 case 'B':
329 {
330 register char *p;
331 boolean_t any;
332 register int i;
333
9bccf70c
A
334 if (long_long) {
335 u = va_arg(*argp, unsigned long long);
336 } else {
337 u = va_arg(*argp, unsigned long);
338 }
1c79356b
A
339 p = va_arg(*argp, char *);
340 base = *p++;
9bccf70c 341 nprinted += printnum(u, base, putc, arg);
1c79356b
A
342
343 if (u == 0)
344 break;
345
346 any = FALSE;
347 while ((i = *p++) != '\0') {
348 if (*fmt == 'B')
349 i = 33 - i;
350 if (*p <= 32) {
351 /*
352 * Bit field
353 */
354 register int j;
355 if (any)
9bccf70c 356 (*putc)(',', arg);
1c79356b 357 else {
9bccf70c 358 (*putc)('<', arg);
1c79356b
A
359 any = TRUE;
360 }
9bccf70c 361 nprinted++;
1c79356b
A
362 j = *p++;
363 if (*fmt == 'B')
364 j = 32 - j;
9bccf70c
A
365 for (; (c = *p) > 32; p++) {
366 (*putc)(c, arg);
367 nprinted++;
368 }
369 nprinted += printnum((unsigned)( (u>>(j-1)) & ((2<<(i-j))-1)),
370 base, putc, arg);
1c79356b
A
371 }
372 else if (u & (1<<(i-1))) {
373 if (any)
9bccf70c 374 (*putc)(',', arg);
1c79356b 375 else {
9bccf70c 376 (*putc)('<', arg);
1c79356b
A
377 any = TRUE;
378 }
9bccf70c
A
379 nprinted++;
380 for (; (c = *p) > 32; p++) {
381 (*putc)(c, arg);
382 nprinted++;
383 }
1c79356b
A
384 }
385 else {
386 for (; *p > 32; p++)
387 continue;
388 }
389 }
9bccf70c
A
390 if (any) {
391 (*putc)('>', arg);
392 nprinted++;
393 }
1c79356b
A
394 break;
395 }
396
397 case 'c':
398 c = va_arg(*argp, int);
9bccf70c
A
399 (*putc)(c, arg);
400 nprinted++;
1c79356b
A
401 break;
402
403 case 's':
404 {
405 register char *p;
406 register char *p2;
407
408 if (prec == -1)
409 prec = 0x7fffffff; /* MAXINT */
410
411 p = va_arg(*argp, char *);
412
413 if (p == (char *)0)
414 p = "";
415
416 if (length > 0 && !ladjust) {
417 n = 0;
418 p2 = p;
419
420 for (; *p != '\0' && n < prec; p++)
421 n++;
422
423 p = p2;
424
425 while (n < length) {
9bccf70c 426 (*putc)(' ', arg);
1c79356b 427 n++;
9bccf70c 428 nprinted++;
1c79356b
A
429 }
430 }
431
432 n = 0;
433
434 while (*p != '\0') {
435 if (++n > prec || (length > 0 && n > length))
436 break;
437
9bccf70c
A
438 (*putc)(*p++, arg);
439 nprinted++;
1c79356b
A
440 }
441
442 if (n < length && ladjust) {
443 while (n < length) {
9bccf70c 444 (*putc)(' ', arg);
1c79356b 445 n++;
9bccf70c 446 nprinted++;
1c79356b
A
447 }
448 }
449
450 break;
451 }
452
453 case 'o':
454 truncate = _doprnt_truncates;
455 case 'O':
456 base = 8;
457 goto print_unsigned;
458
9bccf70c
A
459 case 'D': {
460 unsigned char *up;
461 char *q, *p;
462
463 up = (unsigned char *)va_arg(*argp, unsigned char *);
464 p = (char *)va_arg(*argp, char *);
465 if (length == -1)
466 length = 16;
467 while(length--) {
468 (*putc)(digs[(*up >> 4)], arg);
469 (*putc)(digs[(*up & 0x0f)], arg);
470 nprinted += 2;
471 up++;
472 if (length) {
473 for (q=p;*q;q++) {
474 (*putc)(*q, arg);
475 nprinted++;
476 }
477 }
478 }
479 break;
480 }
481
1c79356b
A
482 case 'd':
483 truncate = _doprnt_truncates;
1c79356b
A
484 base = 10;
485 goto print_signed;
486
487 case 'u':
488 truncate = _doprnt_truncates;
489 case 'U':
490 base = 10;
491 goto print_unsigned;
492
493 case 'p':
494 altfmt = TRUE;
495 case 'x':
496 truncate = _doprnt_truncates;
497 base = 16;
498 goto print_unsigned;
499
500 case 'X':
501 base = 16;
502 capitals=16; /* Print in upper case */
503 goto print_unsigned;
504
505 case 'z':
506 truncate = _doprnt_truncates;
507 base = 16;
508 goto print_signed;
509
510 case 'Z':
511 base = 16;
512 capitals=16; /* Print in upper case */
513 goto print_signed;
514
515 case 'r':
516 truncate = _doprnt_truncates;
517 case 'R':
518 base = radix;
519 goto print_signed;
520
521 case 'n':
522 truncate = _doprnt_truncates;
523 case 'N':
524 base = radix;
525 goto print_unsigned;
526
527 print_signed:
9bccf70c
A
528 if (long_long) {
529 n = va_arg(*argp, long long);
530 } else {
531 n = va_arg(*argp, long);
532 }
1c79356b
A
533 if (n >= 0) {
534 u = n;
535 sign_char = plus_sign;
536 }
537 else {
538 u = -n;
539 sign_char = '-';
540 }
541 goto print_num;
542
543 print_unsigned:
9bccf70c
A
544 if (long_long) {
545 u = va_arg(*argp, unsigned long long);
546 } else {
547 u = va_arg(*argp, unsigned long);
548 }
1c79356b
A
549 goto print_num;
550
551 print_num:
552 {
553 char buf[MAXBUF]; /* build number here */
554 register char * p = &buf[MAXBUF-1];
555 static char digits[] = "0123456789abcdef0123456789ABCDEF";
556 char *prefix = 0;
557
9bccf70c 558 if (truncate) u = (long long)((int)(u));
1c79356b
A
559
560 if (u != 0 && altfmt) {
561 if (base == 8)
562 prefix = "0";
563 else if (base == 16)
564 prefix = "0x";
565 }
566
567 do {
568 /* Print in the correct case */
569 *p-- = digits[(u % base)+capitals];
570 u /= base;
571 } while (u != 0);
572
573 length -= (&buf[MAXBUF-1] - p);
574 if (sign_char)
575 length--;
576 if (prefix)
577 length -= strlen((const char *) prefix);
578
579 if (padc == ' ' && !ladjust) {
580 /* blank padding goes before prefix */
9bccf70c
A
581 while (--length >= 0) {
582 (*putc)(' ', arg);
583 nprinted++;
584 }
585 }
586 if (sign_char) {
587 (*putc)(sign_char, arg);
588 nprinted++;
589 }
590 if (prefix) {
591 while (*prefix) {
592 (*putc)(*prefix++, arg);
593 nprinted++;
594 }
1c79356b 595 }
1c79356b
A
596 if (padc == '0') {
597 /* zero padding goes after sign and prefix */
9bccf70c
A
598 while (--length >= 0) {
599 (*putc)('0', arg);
600 nprinted++;
601 }
1c79356b 602 }
9bccf70c
A
603 while (++p != &buf[MAXBUF]) {
604 (*putc)(*p, arg);
605 nprinted++;
606 }
607
1c79356b 608 if (ladjust) {
9bccf70c
A
609 while (--length >= 0) {
610 (*putc)(' ', arg);
611 nprinted++;
612 }
1c79356b
A
613 }
614 break;
615 }
616
617 case '\0':
618 fmt--;
619 break;
620
621 default:
9bccf70c
A
622 (*putc)(c, arg);
623 nprinted++;
1c79356b
A
624 }
625 fmt++;
626 }
9bccf70c
A
627
628 return nprinted;
629}
630
631static void
632dummy_putc(int ch, void *arg)
633{
634 void (*real_putc)(char) = arg;
635
636 real_putc(ch);
637}
638
639void
640_doprnt(
641 register const char *fmt,
642 va_list *argp,
643 /* character output routine */
644 void (*putc)(char),
645 int radix) /* default radix - for '%r' */
646{
647 __doprnt(fmt, argp, dummy_putc, putc, radix);
1c79356b
A
648}
649
650#if MP_PRINTF
651boolean_t new_printf_cpu_number = FALSE;
652#endif /* MP_PRINTF */
653
654
655decl_simple_lock_data(,printf_lock)
91447636 656decl_simple_lock_data(,bsd_log_spinlock)
1c79356b 657decl_mutex_data(,sprintf_lock)
91447636
A
658extern void bsd_log_init(void);
659void bsd_log_lock(void);
660void bsd_log_unlock(void);
1c79356b
A
661
662void
663printf_init(void)
664{
665 /*
666 * Lock is only really needed after the first thread is created.
667 */
91447636
A
668 simple_lock_init(&printf_lock, 0);
669 simple_lock_init(&bsd_log_spinlock, 0);
670 bsd_log_init();
671 mutex_init(&sprintf_lock, 0);
672}
673
674void
675bsd_log_lock()
676{
677 simple_lock(&bsd_log_spinlock);
678}
679
680void
681bsd_log_unlock()
682{
683 simple_unlock(&bsd_log_spinlock);
1c79356b
A
684}
685
686/* derived from boot_gets */
687void
688safe_gets(
689 char *str,
690 int maxlen)
691{
692 register char *lp;
693 register int c;
694 char *strmax = str + maxlen - 1; /* allow space for trailing 0 */
695
696 lp = str;
697 for (;;) {
698 c = cngetc();
699 switch (c) {
700 case '\n':
701 case '\r':
702 printf("\n");
703 *lp++ = 0;
704 return;
705
706 case '\b':
707 case '#':
708 case '\177':
709 if (lp > str) {
710 printf("\b \b");
711 lp--;
712 }
713 continue;
714
715 case '@':
716 case 'u'&037:
717 lp = str;
718 printf("\n\r");
719 continue;
720
721 default:
722 if (c >= ' ' && c < '\177') {
723 if (lp < strmax) {
724 *lp++ = c;
725 printf("%c", c);
726 }
727 else {
728 printf("%c", '\007'); /* beep */
729 }
730 }
731 }
732 }
733}
734
735void
736conslog_putc(
737 char c)
738{
739 extern unsigned int debug_mode, disableDebugOuput, disableConsoleOutput;
740
741 if ((debug_mode && !disableDebugOuput) || !disableConsoleOutput)
742 cnputc(c);
743
744#ifdef MACH_BSD
745 log_putc(c);
746#endif
747}
748
55e303ae
A
749void
750dbugprintf(const char *fmt, ...)
751{
752
753#if MACH_KDB
754
755 extern void db_putchar(char c);
756 va_list listp;
757
758 va_start(listp, fmt);
759 _doprnt(fmt, &listp, db_putchar, 16);
760 va_end(listp);
761#endif
762 return;
763}
764
1c79356b
A
765void
766printf(const char *fmt, ...)
767{
768 va_list listp;
769
770 disable_preemption();
771 va_start(listp, fmt);
772 _doprnt(fmt, &listp, conslog_putc, 16);
773 va_end(listp);
774 enable_preemption();
775}
776
5d5c5d0d
A
777extern unsigned int disableSerialOuput;
778
9bccf70c
A
779void
780consdebug_putc(
781 char c)
782{
783 extern unsigned int debug_mode, disableDebugOuput, disableConsoleOutput;
784
785 if ((debug_mode && !disableDebugOuput) || !disableConsoleOutput)
786 cnputc(c);
787
788 debug_putc(c);
91447636 789
91447636 790 if (!console_is_serial())
5d5c5d0d
A
791 if (!disableSerialOuput)
792 PE_kputc(c);
9bccf70c
A
793}
794
795void
796kdb_printf(const char *fmt, ...)
797{
798 va_list listp;
799
800 va_start(listp, fmt);
801 _doprnt(fmt, &listp, consdebug_putc, 16);
802 va_end(listp);
803}
804
1c79356b
A
805static char *copybyte_str;
806
807static void
808copybyte(
809 char byte)
810{
811 *copybyte_str++ = byte;
812 *copybyte_str = '\0';
813}
814
815int
816sprintf(char *buf, const char *fmt, ...)
817{
818 va_list listp;
819
820 va_start(listp, fmt);
821 mutex_lock(&sprintf_lock);
822 copybyte_str = buf;
823 _doprnt(fmt, &listp, copybyte, 16);
824 mutex_unlock(&sprintf_lock);
825 va_end(listp);
826 return strlen(buf);
827}