]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/printf.c
xnu-1699.32.7.tar.gz
[apple/xnu.git] / osfmk / kern / printf.c
CommitLineData
1c79356b 1/*
0c530ab8 2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
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 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.
8f6c56a5 14 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
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
9bccf70c
A
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
1c79356b
A
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 *
b0d623f7 97 * This version does not implement %f, %e, or %g.
1c79356b
A
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
9bccf70c
A
105 *
106 * Tweaked for long long support and extended to support the hexdump %D
107 * specifier by dbg 05/02/02.
1c79356b
A
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 */
9bccf70c
A
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 */
1c79356b 156
55e303ae
A
157#include <debug.h>
158#include <mach_kdb.h>
159#include <mach_kdp.h>
1c79356b
A
160#include <platforms.h>
161#include <mach/boolean.h>
1c79356b
A
162#include <kern/cpu_number.h>
163#include <kern/lock.h>
164#include <kern/thread.h>
165#include <kern/sched_prim.h>
166#include <kern/misc_protos.h>
167#include <stdarg.h>
168#include <string.h>
169#include <mach_assert.h>
170#ifdef MACH_BSD
171#include <sys/msgbuf.h>
172#endif
2d21ac55 173#include <console/serial_protos.h>
1c79356b 174
1c79356b
A
175#define isdigit(d) ((d) >= '0' && (d) <= '9')
176#define Ctod(c) ((c) - '0')
177
9bccf70c
A
178#define MAXBUF (sizeof(long long int) * 8) /* enough for binary */
179static char digs[] = "0123456789abcdef";
1c79356b 180
2d21ac55 181#if CONFIG_NO_PRINTF_STRINGS
b0d623f7
A
182/* Prevent CPP from breaking the definition below */
183#undef printf
2d21ac55
A
184#endif
185
b0d623f7
A
186int _consume_printf_args(int a __unused, ...)
187{
188 return 0;
189}
190void _consume_kprintf_args(int a __unused, ...)
191{
192}
193
9bccf70c 194static int
1c79356b 195printnum(
2d21ac55
A
196 unsigned long long int u, /* number to print */
197 int base,
9bccf70c
A
198 void (*putc)(int, void *),
199 void *arg)
1c79356b
A
200{
201 char buf[MAXBUF]; /* build number here */
2d21ac55 202 char * p = &buf[MAXBUF-1];
9bccf70c 203 int nprinted = 0;
1c79356b
A
204
205 do {
206 *p-- = digs[u % base];
207 u /= base;
208 } while (u != 0);
209
9bccf70c
A
210 while (++p != &buf[MAXBUF]) {
211 (*putc)(*p, arg);
212 nprinted++;
213 }
1c79356b 214
9bccf70c 215 return nprinted;
1c79356b
A
216}
217
218boolean_t _doprnt_truncates = FALSE;
219
9bccf70c
A
220int
221__doprnt(
2d21ac55 222 const char *fmt,
b0d623f7 223 va_list argp,
1c79356b 224 /* character output routine */
9bccf70c
A
225 void (*putc)(int, void *arg),
226 void *arg,
1c79356b
A
227 int radix) /* default radix - for '%r' */
228{
229 int length;
230 int prec;
231 boolean_t ladjust;
232 char padc;
9bccf70c
A
233 long long n;
234 unsigned long long u;
1c79356b
A
235 int plus_sign;
236 int sign_char;
237 boolean_t altfmt, truncate;
238 int base;
2d21ac55 239 char c;
1c79356b 240 int capitals;
9bccf70c
A
241 int long_long;
242 int nprinted = 0;
1c79356b
A
243
244 while ((c = *fmt) != '\0') {
245 if (c != '%') {
9bccf70c
A
246 (*putc)(c, arg);
247 nprinted++;
1c79356b
A
248 fmt++;
249 continue;
250 }
251
252 fmt++;
253
9bccf70c 254 long_long = 0;
1c79356b
A
255 length = 0;
256 prec = -1;
257 ladjust = FALSE;
258 padc = ' ';
259 plus_sign = 0;
260 sign_char = 0;
261 altfmt = FALSE;
262
263 while (TRUE) {
264 c = *fmt;
265 if (c == '#') {
266 altfmt = TRUE;
267 }
268 else if (c == '-') {
269 ladjust = TRUE;
270 }
271 else if (c == '+') {
272 plus_sign = '+';
273 }
274 else if (c == ' ') {
275 if (plus_sign == 0)
276 plus_sign = ' ';
277 }
278 else
279 break;
280 fmt++;
281 }
282
283 if (c == '0') {
284 padc = '0';
285 c = *++fmt;
286 }
287
288 if (isdigit(c)) {
289 while(isdigit(c)) {
290 length = 10 * length + Ctod(c);
291 c = *++fmt;
292 }
293 }
294 else if (c == '*') {
b0d623f7 295 length = va_arg(argp, int);
1c79356b
A
296 c = *++fmt;
297 if (length < 0) {
298 ladjust = !ladjust;
299 length = -length;
300 }
301 }
302
303 if (c == '.') {
304 c = *++fmt;
305 if (isdigit(c)) {
306 prec = 0;
307 while(isdigit(c)) {
308 prec = 10 * prec + Ctod(c);
309 c = *++fmt;
310 }
311 }
312 else if (c == '*') {
b0d623f7 313 prec = va_arg(argp, int);
1c79356b
A
314 c = *++fmt;
315 }
316 }
317
9bccf70c 318 if (c == 'l') {
1c79356b 319 c = *++fmt; /* need it if sizeof(int) < sizeof(long) */
b0d623f7
A
320 if (sizeof(int)<sizeof(long))
321 long_long = 1;
9bccf70c
A
322 if (c == 'l') {
323 long_long = 1;
324 c = *++fmt;
325 }
326 } else if (c == 'q' || c == 'L') {
327 long_long = 1;
328 c = *++fmt;
329 }
1c79356b
A
330
331 truncate = FALSE;
332 capitals=0; /* Assume lower case printing */
333
334 switch(c) {
335 case 'b':
336 case 'B':
337 {
338 register char *p;
339 boolean_t any;
340 register int i;
341
9bccf70c 342 if (long_long) {
b0d623f7 343 u = va_arg(argp, unsigned long long);
9bccf70c 344 } else {
b0d623f7 345 u = va_arg(argp, unsigned int);
9bccf70c 346 }
b0d623f7 347 p = va_arg(argp, char *);
1c79356b 348 base = *p++;
9bccf70c 349 nprinted += printnum(u, base, putc, arg);
1c79356b
A
350
351 if (u == 0)
352 break;
353
354 any = FALSE;
355 while ((i = *p++) != '\0') {
356 if (*fmt == 'B')
357 i = 33 - i;
358 if (*p <= 32) {
359 /*
360 * Bit field
361 */
362 register int j;
363 if (any)
9bccf70c 364 (*putc)(',', arg);
1c79356b 365 else {
9bccf70c 366 (*putc)('<', arg);
1c79356b
A
367 any = TRUE;
368 }
9bccf70c 369 nprinted++;
1c79356b
A
370 j = *p++;
371 if (*fmt == 'B')
372 j = 32 - j;
9bccf70c
A
373 for (; (c = *p) > 32; p++) {
374 (*putc)(c, arg);
375 nprinted++;
376 }
377 nprinted += printnum((unsigned)( (u>>(j-1)) & ((2<<(i-j))-1)),
378 base, putc, arg);
1c79356b
A
379 }
380 else if (u & (1<<(i-1))) {
381 if (any)
9bccf70c 382 (*putc)(',', arg);
1c79356b 383 else {
9bccf70c 384 (*putc)('<', arg);
1c79356b
A
385 any = TRUE;
386 }
9bccf70c
A
387 nprinted++;
388 for (; (c = *p) > 32; p++) {
389 (*putc)(c, arg);
390 nprinted++;
391 }
1c79356b
A
392 }
393 else {
394 for (; *p > 32; p++)
395 continue;
396 }
397 }
9bccf70c
A
398 if (any) {
399 (*putc)('>', arg);
400 nprinted++;
401 }
1c79356b
A
402 break;
403 }
404
405 case 'c':
b0d623f7 406 c = va_arg(argp, int);
9bccf70c
A
407 (*putc)(c, arg);
408 nprinted++;
1c79356b
A
409 break;
410
411 case 's':
412 {
2d21ac55
A
413 register const char *p;
414 register const char *p2;
1c79356b
A
415
416 if (prec == -1)
417 prec = 0x7fffffff; /* MAXINT */
418
b0d623f7 419 p = va_arg(argp, char *);
1c79356b 420
2d21ac55 421 if (p == NULL)
1c79356b
A
422 p = "";
423
424 if (length > 0 && !ladjust) {
425 n = 0;
426 p2 = p;
427
428 for (; *p != '\0' && n < prec; p++)
429 n++;
430
431 p = p2;
432
433 while (n < length) {
9bccf70c 434 (*putc)(' ', arg);
1c79356b 435 n++;
9bccf70c 436 nprinted++;
1c79356b
A
437 }
438 }
439
440 n = 0;
441
cf7d32b8
A
442 while ((n < prec) && (!(length > 0 && n >= length))) {
443 if (*p == '\0') {
444 break;
445 }
446 (*putc)(*p++, arg);
447 nprinted++;
448 n++;
1c79356b
A
449 }
450
451 if (n < length && ladjust) {
452 while (n < length) {
9bccf70c 453 (*putc)(' ', arg);
1c79356b 454 n++;
9bccf70c 455 nprinted++;
1c79356b
A
456 }
457 }
458
459 break;
460 }
461
462 case 'o':
463 truncate = _doprnt_truncates;
464 case 'O':
465 base = 8;
466 goto print_unsigned;
467
9bccf70c
A
468 case 'D': {
469 unsigned char *up;
470 char *q, *p;
471
b0d623f7
A
472 up = (unsigned char *)va_arg(argp, unsigned char *);
473 p = (char *)va_arg(argp, char *);
9bccf70c
A
474 if (length == -1)
475 length = 16;
476 while(length--) {
477 (*putc)(digs[(*up >> 4)], arg);
478 (*putc)(digs[(*up & 0x0f)], arg);
479 nprinted += 2;
480 up++;
481 if (length) {
482 for (q=p;*q;q++) {
483 (*putc)(*q, arg);
484 nprinted++;
485 }
486 }
487 }
488 break;
489 }
490
1c79356b
A
491 case 'd':
492 truncate = _doprnt_truncates;
1c79356b
A
493 base = 10;
494 goto print_signed;
495
496 case 'u':
497 truncate = _doprnt_truncates;
498 case 'U':
499 base = 10;
500 goto print_unsigned;
501
502 case 'p':
503 altfmt = TRUE;
b0d623f7
A
504 if (sizeof(int)<sizeof(void *)) {
505 long_long = 1;
506 }
1c79356b
A
507 case 'x':
508 truncate = _doprnt_truncates;
509 base = 16;
510 goto print_unsigned;
511
512 case 'X':
513 base = 16;
514 capitals=16; /* Print in upper case */
515 goto print_unsigned;
516
517 case 'z':
518 truncate = _doprnt_truncates;
519 base = 16;
520 goto print_signed;
521
522 case 'Z':
523 base = 16;
524 capitals=16; /* Print in upper case */
525 goto print_signed;
526
527 case 'r':
528 truncate = _doprnt_truncates;
529 case 'R':
530 base = radix;
531 goto print_signed;
532
533 case 'n':
534 truncate = _doprnt_truncates;
535 case 'N':
536 base = radix;
537 goto print_unsigned;
538
539 print_signed:
9bccf70c 540 if (long_long) {
b0d623f7 541 n = va_arg(argp, long long);
9bccf70c 542 } else {
b0d623f7 543 n = va_arg(argp, int);
9bccf70c 544 }
1c79356b
A
545 if (n >= 0) {
546 u = n;
547 sign_char = plus_sign;
548 }
549 else {
550 u = -n;
551 sign_char = '-';
552 }
553 goto print_num;
554
555 print_unsigned:
9bccf70c 556 if (long_long) {
b0d623f7 557 u = va_arg(argp, unsigned long long);
9bccf70c 558 } else {
b0d623f7 559 u = va_arg(argp, unsigned int);
9bccf70c 560 }
1c79356b
A
561 goto print_num;
562
563 print_num:
564 {
565 char buf[MAXBUF]; /* build number here */
566 register char * p = &buf[MAXBUF-1];
567 static char digits[] = "0123456789abcdef0123456789ABCDEF";
2d21ac55 568 const char *prefix = NULL;
1c79356b 569
9bccf70c 570 if (truncate) u = (long long)((int)(u));
1c79356b
A
571
572 if (u != 0 && altfmt) {
573 if (base == 8)
574 prefix = "0";
575 else if (base == 16)
576 prefix = "0x";
577 }
578
579 do {
580 /* Print in the correct case */
581 *p-- = digits[(u % base)+capitals];
582 u /= base;
583 } while (u != 0);
584
b0d623f7 585 length -= (int)(&buf[MAXBUF-1] - p);
1c79356b
A
586 if (sign_char)
587 length--;
588 if (prefix)
b0d623f7 589 length -= (int)strlen(prefix);
1c79356b
A
590
591 if (padc == ' ' && !ladjust) {
592 /* blank padding goes before prefix */
9bccf70c
A
593 while (--length >= 0) {
594 (*putc)(' ', arg);
595 nprinted++;
596 }
597 }
598 if (sign_char) {
599 (*putc)(sign_char, arg);
600 nprinted++;
601 }
602 if (prefix) {
603 while (*prefix) {
604 (*putc)(*prefix++, arg);
605 nprinted++;
606 }
1c79356b 607 }
1c79356b
A
608 if (padc == '0') {
609 /* zero padding goes after sign and prefix */
9bccf70c
A
610 while (--length >= 0) {
611 (*putc)('0', arg);
612 nprinted++;
613 }
1c79356b 614 }
9bccf70c
A
615 while (++p != &buf[MAXBUF]) {
616 (*putc)(*p, arg);
617 nprinted++;
618 }
619
1c79356b 620 if (ladjust) {
9bccf70c
A
621 while (--length >= 0) {
622 (*putc)(' ', arg);
623 nprinted++;
624 }
1c79356b
A
625 }
626 break;
627 }
628
629 case '\0':
630 fmt--;
631 break;
632
633 default:
9bccf70c
A
634 (*putc)(c, arg);
635 nprinted++;
1c79356b
A
636 }
637 fmt++;
638 }
9bccf70c
A
639
640 return nprinted;
641}
642
643static void
644dummy_putc(int ch, void *arg)
645{
646 void (*real_putc)(char) = arg;
647
648 real_putc(ch);
649}
650
651void
652_doprnt(
653 register const char *fmt,
654 va_list *argp,
655 /* character output routine */
656 void (*putc)(char),
657 int radix) /* default radix - for '%r' */
658{
b0d623f7 659 __doprnt(fmt, *argp, dummy_putc, putc, radix);
1c79356b
A
660}
661
662#if MP_PRINTF
663boolean_t new_printf_cpu_number = FALSE;
664#endif /* MP_PRINTF */
665
666
667decl_simple_lock_data(,printf_lock)
91447636 668decl_simple_lock_data(,bsd_log_spinlock)
91447636
A
669extern void bsd_log_init(void);
670void bsd_log_lock(void);
671void bsd_log_unlock(void);
1c79356b
A
672
673void
674printf_init(void)
675{
676 /*
677 * Lock is only really needed after the first thread is created.
678 */
91447636
A
679 simple_lock_init(&printf_lock, 0);
680 simple_lock_init(&bsd_log_spinlock, 0);
681 bsd_log_init();
91447636
A
682}
683
684void
2d21ac55 685bsd_log_lock(void)
91447636
A
686{
687 simple_lock(&bsd_log_spinlock);
688}
689
690void
2d21ac55 691bsd_log_unlock(void)
91447636
A
692{
693 simple_unlock(&bsd_log_spinlock);
1c79356b
A
694}
695
696/* derived from boot_gets */
697void
698safe_gets(
699 char *str,
700 int maxlen)
701{
702 register char *lp;
703 register int c;
704 char *strmax = str + maxlen - 1; /* allow space for trailing 0 */
705
706 lp = str;
707 for (;;) {
708 c = cngetc();
709 switch (c) {
710 case '\n':
711 case '\r':
712 printf("\n");
713 *lp++ = 0;
714 return;
715
716 case '\b':
717 case '#':
718 case '\177':
719 if (lp > str) {
720 printf("\b \b");
721 lp--;
722 }
723 continue;
724
725 case '@':
726 case 'u'&037:
727 lp = str;
728 printf("\n\r");
729 continue;
730
731 default:
732 if (c >= ' ' && c < '\177') {
733 if (lp < strmax) {
734 *lp++ = c;
735 printf("%c", c);
736 }
737 else {
738 printf("%c", '\007'); /* beep */
739 }
740 }
741 }
742 }
743}
744
2d21ac55
A
745extern int disableConsoleOutput;
746
1c79356b
A
747void
748conslog_putc(
749 char c)
750{
2d21ac55 751 if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
1c79356b
A
752 cnputc(c);
753
754#ifdef MACH_BSD
593a1d5f
A
755 if (debug_mode == 0)
756 log_putc(c);
1c79356b
A
757#endif
758}
759
6d2010ae
A
760void
761cons_putc_locked(
762 char c)
763{
764 if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
765 cnputc(c);
766}
767
2d21ac55
A
768#if MACH_KDB
769extern void db_putchar(char c);
770#endif
771
55e303ae 772void
2d21ac55 773dbugprintf(__unused const char *fmt, ...)
55e303ae
A
774{
775
776#if MACH_KDB
55e303ae
A
777 va_list listp;
778
779 va_start(listp, fmt);
780 _doprnt(fmt, &listp, db_putchar, 16);
781 va_end(listp);
782#endif
783 return;
784}
785
2d21ac55 786int
1c79356b
A
787printf(const char *fmt, ...)
788{
789 va_list listp;
790
2d21ac55
A
791 if (fmt) {
792 disable_preemption();
793 va_start(listp, fmt);
794 _doprnt(fmt, &listp, conslog_putc, 16);
795 va_end(listp);
796 enable_preemption();
797 }
798 return 0;
1c79356b
A
799}
800
9bccf70c 801void
2d21ac55 802consdebug_putc(char c)
9bccf70c 803{
2d21ac55 804 if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
9bccf70c
A
805 cnputc(c);
806
807 debug_putc(c);
91447636 808
91447636 809 if (!console_is_serial())
2d21ac55 810 if (!disable_serial_output)
0c530ab8 811 PE_kputc(c);
9bccf70c
A
812}
813
b0d623f7
A
814void
815consdebug_putc_unbuffered(char c)
816{
817 if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
818 cnputc_unbuffered(c);
819
820 debug_putc(c);
821
822 if (!console_is_serial())
823 if (!disable_serial_output)
824 PE_kputc(c);
825}
c910b4d9
A
826
827void
828consdebug_log(char c)
829{
830 debug_putc(c);
831}
832
2d21ac55 833int
9bccf70c
A
834kdb_printf(const char *fmt, ...)
835{
836 va_list listp;
837
838 va_start(listp, fmt);
839 _doprnt(fmt, &listp, consdebug_putc, 16);
840 va_end(listp);
2d21ac55 841 return 0;
9bccf70c
A
842}
843
c910b4d9
A
844int
845kdb_log(const char *fmt, ...)
846{
847 va_list listp;
848
849 va_start(listp, fmt);
850 _doprnt(fmt, &listp, consdebug_log, 16);
851 va_end(listp);
852 return 0;
853}
854
b0d623f7
A
855int
856kdb_printf_unbuffered(const char *fmt, ...)
857{
858 va_list listp;
859
860 va_start(listp, fmt);
861 _doprnt(fmt, &listp, consdebug_putc_unbuffered, 16);
862 va_end(listp);
863 return 0;
864}
865
6d2010ae
A
866#if !CONFIG_EMBEDDED
867
1c79356b 868static void
2d21ac55 869copybyte(int c, void *arg)
1c79356b 870{
2d21ac55
A
871 /*
872 * arg is a pointer (outside pointer) to the pointer
873 * (inside pointer) which points to the character.
874 * We pass a double pointer, so that we can increment
875 * the inside pointer.
876 */
877 char** p = arg; /* cast outside pointer */
878 **p = c; /* store character */
879 (*p)++; /* increment inside pointer */
1c79356b
A
880}
881
2d21ac55
A
882/*
883 * Deprecation Warning:
884 * sprintf() is being deprecated. Please use snprintf() instead.
885 */
1c79356b
A
886int
887sprintf(char *buf, const char *fmt, ...)
888{
889 va_list listp;
2d21ac55 890 char *copybyte_str;
1c79356b
A
891
892 va_start(listp, fmt);
1c79356b 893 copybyte_str = buf;
b0d623f7 894 __doprnt(fmt, listp, copybyte, &copybyte_str, 16);
1c79356b 895 va_end(listp);
2d21ac55 896 *copybyte_str = '\0';
b0d623f7 897 return (int)strlen(buf);
1c79356b 898}
6d2010ae 899#endif /* !CONFIG_EMBEDDED */