/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
*
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
*
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
*
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* @OSF_COPYRIGHT@
* %u unsigned conversion
* %x hexadecimal conversion
* %X hexadecimal conversion with capital letters
+ * %D hexdump, ptr & separator string ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
+ * if you use, "%*D" then there's a length, the data ptr and then the separator
* %o octal conversion
* %c character
* %s string
* This version does not implement %f, %e, or %g. It accepts, but
* ignores, an `l' as in %ld, %lo, %lx, and %lu, and therefore will not
* work correctly on machines for which sizeof(long) != sizeof(int).
- * It does not even parse %D, %O, or %U; you should be using %ld, %o and
- * %lu if you mean long conversion.
*
* As mentioned, this version does not return any reasonable value.
*
* long as this notice is incorporated.
*
* Steve Summit 3/25/87
+ *
+ * Tweaked for long long support and extended to support the hexdump %D
+ * specifier by dbg 05/02/02.
*/
/*
* D,U,O,Z same as corresponding lower-case versions
* (compatibility)
*/
+/*
+ * Added support for print long long (64-bit) integers.
+ * Use %lld, %Ld or %qd to print a 64-bit int. Other
+ * output bases such as x, X, u, U, o, and O also work.
+ */
+#include <debug.h>
+#include <mach_kdb.h>
+#include <mach_kdp.h>
#include <platforms.h>
#include <mach/boolean.h>
-#include <cpus.h>
#include <kern/cpu_number.h>
#include <kern/lock.h>
#include <kern/thread.h>
#ifdef MACH_BSD
#include <sys/msgbuf.h>
#endif
+#include <console/serial_protos.h>
#ifdef __ppc__
#include <ppc/Firmware.h>
#endif
-/*
- * Forward declarations
- */
-void printnum(
- register unsigned int u,
- register int base,
- void (*putc)(char));
-
-
#define isdigit(d) ((d) >= '0' && (d) <= '9')
#define Ctod(c) ((c) - '0')
-#define MAXBUF (sizeof(long int) * 8) /* enough for binary */
+#define MAXBUF (sizeof(long long int) * 8) /* enough for binary */
+static char digs[] = "0123456789abcdef";
-void
+
+#if CONFIG_NO_PRINTF_STRINGS
+#undef printf(x, ...)
+#endif
+
+static int
printnum(
- register unsigned int u, /* number to print */
- register int base,
- void (*putc)(char))
+ unsigned long long int u, /* number to print */
+ int base,
+ void (*putc)(int, void *),
+ void *arg)
{
char buf[MAXBUF]; /* build number here */
- register char * p = &buf[MAXBUF-1];
- static char digs[] = "0123456789abcdef";
+ char * p = &buf[MAXBUF-1];
+ int nprinted = 0;
do {
*p-- = digs[u % base];
u /= base;
} while (u != 0);
- while (++p != &buf[MAXBUF])
- (*putc)(*p);
+ while (++p != &buf[MAXBUF]) {
+ (*putc)(*p, arg);
+ nprinted++;
+ }
+ return nprinted;
}
boolean_t _doprnt_truncates = FALSE;
-void
-_doprnt(
- register const char *fmt,
+int
+__doprnt(
+ const char *fmt,
va_list *argp,
/* character output routine */
- void (*putc)(char),
+ void (*putc)(int, void *arg),
+ void *arg,
int radix) /* default radix - for '%r' */
{
int length;
int prec;
boolean_t ladjust;
char padc;
- long n;
- unsigned long u;
+ long long n;
+ unsigned long long u;
int plus_sign;
int sign_char;
boolean_t altfmt, truncate;
int base;
- register char c;
+ char c;
int capitals;
+ int long_long;
+ int nprinted = 0;
while ((c = *fmt) != '\0') {
if (c != '%') {
- (*putc)(c);
+ (*putc)(c, arg);
+ nprinted++;
fmt++;
continue;
}
fmt++;
+ long_long = 0;
length = 0;
prec = -1;
ladjust = FALSE;
}
}
- if (c == 'l')
+ if (c == 'l') {
c = *++fmt; /* need it if sizeof(int) < sizeof(long) */
+ if (c == 'l') {
+ long_long = 1;
+ c = *++fmt;
+ }
+ } else if (c == 'q' || c == 'L') {
+ long_long = 1;
+ c = *++fmt;
+ }
truncate = FALSE;
capitals=0; /* Assume lower case printing */
boolean_t any;
register int i;
- u = va_arg(*argp, unsigned long);
+ if (long_long) {
+ u = va_arg(*argp, unsigned long long);
+ } else {
+ u = va_arg(*argp, unsigned long);
+ }
p = va_arg(*argp, char *);
base = *p++;
- printnum(u, base, putc);
+ nprinted += printnum(u, base, putc, arg);
if (u == 0)
break;
*/
register int j;
if (any)
- (*putc)(',');
+ (*putc)(',', arg);
else {
- (*putc)('<');
+ (*putc)('<', arg);
any = TRUE;
}
+ nprinted++;
j = *p++;
if (*fmt == 'B')
j = 32 - j;
- for (; (c = *p) > 32; p++)
- (*putc)(c);
- printnum((unsigned)( (u>>(j-1)) & ((2<<(i-j))-1)),
- base, putc);
+ for (; (c = *p) > 32; p++) {
+ (*putc)(c, arg);
+ nprinted++;
+ }
+ nprinted += printnum((unsigned)( (u>>(j-1)) & ((2<<(i-j))-1)),
+ base, putc, arg);
}
else if (u & (1<<(i-1))) {
if (any)
- (*putc)(',');
+ (*putc)(',', arg);
else {
- (*putc)('<');
+ (*putc)('<', arg);
any = TRUE;
}
- for (; (c = *p) > 32; p++)
- (*putc)(c);
+ nprinted++;
+ for (; (c = *p) > 32; p++) {
+ (*putc)(c, arg);
+ nprinted++;
+ }
}
else {
for (; *p > 32; p++)
continue;
}
}
- if (any)
- (*putc)('>');
+ if (any) {
+ (*putc)('>', arg);
+ nprinted++;
+ }
break;
}
case 'c':
c = va_arg(*argp, int);
- (*putc)(c);
+ (*putc)(c, arg);
+ nprinted++;
break;
case 's':
{
- register char *p;
- register char *p2;
+ register const char *p;
+ register const char *p2;
if (prec == -1)
prec = 0x7fffffff; /* MAXINT */
p = va_arg(*argp, char *);
- if (p == (char *)0)
+ if (p == NULL)
p = "";
if (length > 0 && !ladjust) {
p = p2;
while (n < length) {
- (*putc)(' ');
+ (*putc)(' ', arg);
n++;
+ nprinted++;
}
}
if (++n > prec || (length > 0 && n > length))
break;
- (*putc)(*p++);
+ (*putc)(*p++, arg);
+ nprinted++;
}
if (n < length && ladjust) {
while (n < length) {
- (*putc)(' ');
+ (*putc)(' ', arg);
n++;
+ nprinted++;
}
}
base = 8;
goto print_unsigned;
+ case 'D': {
+ unsigned char *up;
+ char *q, *p;
+
+ up = (unsigned char *)va_arg(*argp, unsigned char *);
+ p = (char *)va_arg(*argp, char *);
+ if (length == -1)
+ length = 16;
+ while(length--) {
+ (*putc)(digs[(*up >> 4)], arg);
+ (*putc)(digs[(*up & 0x0f)], arg);
+ nprinted += 2;
+ up++;
+ if (length) {
+ for (q=p;*q;q++) {
+ (*putc)(*q, arg);
+ nprinted++;
+ }
+ }
+ }
+ break;
+ }
+
case 'd':
truncate = _doprnt_truncates;
- case 'D':
base = 10;
goto print_signed;
goto print_unsigned;
print_signed:
- n = va_arg(*argp, long);
+ if (long_long) {
+ n = va_arg(*argp, long long);
+ } else {
+ n = va_arg(*argp, long);
+ }
if (n >= 0) {
u = n;
sign_char = plus_sign;
goto print_num;
print_unsigned:
- u = va_arg(*argp, unsigned long);
+ if (long_long) {
+ u = va_arg(*argp, unsigned long long);
+ } else {
+ u = va_arg(*argp, unsigned long);
+ }
goto print_num;
print_num:
char buf[MAXBUF]; /* build number here */
register char * p = &buf[MAXBUF-1];
static char digits[] = "0123456789abcdef0123456789ABCDEF";
- char *prefix = 0;
+ const char *prefix = NULL;
- if (truncate) u = (long)((int)(u));
+ if (truncate) u = (long long)((int)(u));
if (u != 0 && altfmt) {
if (base == 8)
if (sign_char)
length--;
if (prefix)
- length -= strlen((const char *) prefix);
+ length -= strlen(prefix);
if (padc == ' ' && !ladjust) {
/* blank padding goes before prefix */
- while (--length >= 0)
- (*putc)(' ');
+ while (--length >= 0) {
+ (*putc)(' ', arg);
+ nprinted++;
+ }
+ }
+ if (sign_char) {
+ (*putc)(sign_char, arg);
+ nprinted++;
+ }
+ if (prefix) {
+ while (*prefix) {
+ (*putc)(*prefix++, arg);
+ nprinted++;
+ }
}
- if (sign_char)
- (*putc)(sign_char);
- if (prefix)
- while (*prefix)
- (*putc)(*prefix++);
if (padc == '0') {
/* zero padding goes after sign and prefix */
- while (--length >= 0)
- (*putc)('0');
+ while (--length >= 0) {
+ (*putc)('0', arg);
+ nprinted++;
+ }
}
- while (++p != &buf[MAXBUF])
- (*putc)(*p);
-
+ while (++p != &buf[MAXBUF]) {
+ (*putc)(*p, arg);
+ nprinted++;
+ }
+
if (ladjust) {
- while (--length >= 0)
- (*putc)(' ');
+ while (--length >= 0) {
+ (*putc)(' ', arg);
+ nprinted++;
+ }
}
break;
}
break;
default:
- (*putc)(c);
+ (*putc)(c, arg);
+ nprinted++;
}
fmt++;
}
+
+ return nprinted;
+}
+
+static void
+dummy_putc(int ch, void *arg)
+{
+ void (*real_putc)(char) = arg;
+
+ real_putc(ch);
+}
+
+void
+_doprnt(
+ register const char *fmt,
+ va_list *argp,
+ /* character output routine */
+ void (*putc)(char),
+ int radix) /* default radix - for '%r' */
+{
+ __doprnt(fmt, argp, dummy_putc, putc, radix);
}
#if MP_PRINTF
decl_simple_lock_data(,printf_lock)
-decl_mutex_data(,sprintf_lock)
+decl_simple_lock_data(,bsd_log_spinlock)
+extern void bsd_log_init(void);
+void bsd_log_lock(void);
+void bsd_log_unlock(void);
void
printf_init(void)
/*
* Lock is only really needed after the first thread is created.
*/
- simple_lock_init(&printf_lock, ETAP_MISC_PRINTF);
- mutex_init(&sprintf_lock, ETAP_MISC_PRINTF);
+ simple_lock_init(&printf_lock, 0);
+ simple_lock_init(&bsd_log_spinlock, 0);
+ bsd_log_init();
+}
+
+void
+bsd_log_lock(void)
+{
+ simple_lock(&bsd_log_spinlock);
+}
+
+void
+bsd_log_unlock(void)
+{
+ simple_unlock(&bsd_log_spinlock);
}
/* derived from boot_gets */
}
}
+extern int disableConsoleOutput;
+
void
conslog_putc(
char c)
{
- extern unsigned int debug_mode, disableDebugOuput, disableConsoleOutput;
-
- if ((debug_mode && !disableDebugOuput) || !disableConsoleOutput)
+ if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
cnputc(c);
#ifdef MACH_BSD
#endif
}
+#if MACH_KDB
+extern void db_putchar(char c);
+#endif
+
void
-printf(const char *fmt, ...)
+dbugprintf(__unused const char *fmt, ...)
{
+
+#if MACH_KDB
va_list listp;
- disable_preemption();
va_start(listp, fmt);
- _doprnt(fmt, &listp, conslog_putc, 16);
+ _doprnt(fmt, &listp, db_putchar, 16);
va_end(listp);
- enable_preemption();
+#endif
+ return;
+}
+
+int
+printf(const char *fmt, ...)
+{
+ va_list listp;
+
+ if (fmt) {
+ disable_preemption();
+ va_start(listp, fmt);
+ _doprnt(fmt, &listp, conslog_putc, 16);
+ va_end(listp);
+ enable_preemption();
+ }
+ return 0;
+}
+
+void
+consdebug_putc(char c)
+{
+ if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
+ cnputc(c);
+
+ debug_putc(c);
+
+ if (!console_is_serial())
+ if (!disable_serial_output)
+ PE_kputc(c);
}
-static char *copybyte_str;
+int
+kdb_printf(const char *fmt, ...)
+{
+ va_list listp;
+
+ va_start(listp, fmt);
+ _doprnt(fmt, &listp, consdebug_putc, 16);
+ va_end(listp);
+ return 0;
+}
static void
-copybyte(
- char byte)
+copybyte(int c, void *arg)
{
- *copybyte_str++ = byte;
- *copybyte_str = '\0';
+ /*
+ * arg is a pointer (outside pointer) to the pointer
+ * (inside pointer) which points to the character.
+ * We pass a double pointer, so that we can increment
+ * the inside pointer.
+ */
+ char** p = arg; /* cast outside pointer */
+ **p = c; /* store character */
+ (*p)++; /* increment inside pointer */
}
+/*
+ * Deprecation Warning:
+ * sprintf() is being deprecated. Please use snprintf() instead.
+ */
int
sprintf(char *buf, const char *fmt, ...)
{
va_list listp;
+ char *copybyte_str;
va_start(listp, fmt);
- mutex_lock(&sprintf_lock);
copybyte_str = buf;
- _doprnt(fmt, &listp, copybyte, 16);
- mutex_unlock(&sprintf_lock);
+ __doprnt(fmt, &listp, copybyte, ©byte_str, 16);
va_end(listp);
+ *copybyte_str = '\0';
return strlen(buf);
}