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