X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/1c79356b52d46aa6b508fb032f5ae709b1f2897b..bd504ef0e0b883cdd7917b73b3574eb9ce669905:/osfmk/kern/printf.c diff --git a/osfmk/kern/printf.c b/osfmk/kern/printf.c index bf870083e..88813d844 100644 --- a/osfmk/kern/printf.c +++ b/osfmk/kern/printf.c @@ -1,23 +1,29 @@ /* - * 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@ @@ -78,6 +84,8 @@ * %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 @@ -86,11 +94,7 @@ * %0m.n zero-padding * %*.* width and precision taken from arguments * - * 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. + * This version does not implement %f, %e, or %g. * * As mentioned, this version does not return any reasonable value. * @@ -98,6 +102,9 @@ * 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. */ /* @@ -141,10 +148,16 @@ * 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 +#include #include #include -#include #include #include #include @@ -156,77 +169,88 @@ #ifdef MACH_BSD #include #endif - -#ifdef __ppc__ -#include -#endif - -/* - * Forward declarations - */ -void printnum( - register unsigned int u, - register int base, - void (*putc)(char)); - +#include #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 +/* Prevent CPP from breaking the definition below */ +#undef printf +#endif + +int _consume_printf_args(int a __unused, ...) +{ + return 0; +} +void _consume_kprintf_args(int a __unused, ...) +{ +} + +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, - va_list *argp, +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; @@ -267,7 +291,7 @@ _doprnt( } } else if (c == '*') { - length = va_arg(*argp, int); + length = va_arg(argp, int); c = *++fmt; if (length < 0) { ladjust = !ladjust; @@ -285,13 +309,23 @@ _doprnt( } } else if (c == '*') { - prec = va_arg(*argp, int); + prec = va_arg(argp, int); c = *++fmt; } } - if (c == 'l') + if (c == 'l') { c = *++fmt; /* need it if sizeof(int) < sizeof(long) */ + if (sizeof(int) 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); + c = va_arg(argp, int); + (*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 *); + p = va_arg(argp, char *); - if (p == (char *)0) + if (p == NULL) p = ""; if (length > 0 && !ladjust) { @@ -383,24 +430,28 @@ _doprnt( p = p2; while (n < length) { - (*putc)(' '); + (*putc)(' ', arg); n++; + nprinted++; } } n = 0; - while (*p != '\0') { - if (++n > prec || (length > 0 && n > length)) - break; - - (*putc)(*p++); + while ((n < prec) && (!(length > 0 && n >= length))) { + if (*p == '\0') { + break; + } + (*putc)(*p++, arg); + nprinted++; + n++; } if (n < length && ladjust) { while (n < length) { - (*putc)(' '); + (*putc)(' ', arg); n++; + nprinted++; } } @@ -413,9 +464,31 @@ _doprnt( 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; @@ -427,6 +500,9 @@ _doprnt( case 'p': altfmt = TRUE; + if (sizeof(int)= 0) { u = n; sign_char = plus_sign; @@ -472,7 +552,11 @@ _doprnt( 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 int); + } goto print_num; print_num: @@ -480,9 +564,9 @@ _doprnt( 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) @@ -497,33 +581,46 @@ _doprnt( u /= base; } while (u != 0); - length -= (&buf[MAXBUF-1] - p); + length -= (int)(&buf[MAXBUF-1] - p); if (sign_char) length--; if (prefix) - length -= strlen((const char *) prefix); + length -= (int)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; } @@ -533,10 +630,32 @@ _doprnt( 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 @@ -545,7 +664,10 @@ boolean_t new_printf_cpu_number = FALSE; 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) @@ -553,8 +675,21 @@ 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 */ @@ -606,52 +741,140 @@ safe_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 - log_putc(c); + if (debug_mode == 0) + log_putc(c); #endif } void +cons_putc_locked( + char c) +{ + if ((debug_mode && !disable_debug_output) || !disableConsoleOutput) + cnputc(c); +} + +int printf(const char *fmt, ...) { va_list listp; - disable_preemption(); + 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); +} + +void +consdebug_putc_unbuffered(char c) +{ + if ((debug_mode && !disable_debug_output) || !disableConsoleOutput) + cnputc_unbuffered(c); + + debug_putc(c); + + if (!console_is_serial()) + if (!disable_serial_output) + PE_kputc(c); +} + +void +consdebug_log(char c) +{ + debug_putc(c); +} + +int +kdb_printf(const char *fmt, ...) +{ + va_list listp; + va_start(listp, fmt); - _doprnt(fmt, &listp, conslog_putc, 16); + _doprnt(fmt, &listp, consdebug_putc, 16); va_end(listp); - enable_preemption(); + return 0; } -static char *copybyte_str; +int +kdb_log(const char *fmt, ...) +{ + va_list listp; + + va_start(listp, fmt); + _doprnt(fmt, &listp, consdebug_log, 16); + va_end(listp); + return 0; +} + +int +kdb_printf_unbuffered(const char *fmt, ...) +{ + va_list listp; + + va_start(listp, fmt); + _doprnt(fmt, &listp, consdebug_putc_unbuffered, 16); + va_end(listp); + return 0; +} + +#if !CONFIG_EMBEDDED 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); - return strlen(buf); + *copybyte_str = '\0'; + return (int)strlen(buf); } +#endif /* !CONFIG_EMBEDDED */