]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/kern/printf.c
xnu-1486.2.11.tar.gz
[apple/xnu.git] / osfmk / kern / printf.c
index 472ab86c27721e3ea72362233e075206267df70a..fd04f883a2c1a27cd4f2ab8afaf0c4729a872a04 100644 (file)
@@ -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@
@@ -88,9 +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).
+ *  This version does not implement %f, %e, or %g.
  *
  *  As mentioned, this version does not return any reasonable value.
  *
  * 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>
 #define MAXBUF (sizeof(long long int) * 8)     /* enough for binary */
 static char digs[] = "0123456789abcdef";
 
+
+#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 long long int u,      /* number to print */
-       register int            base,
+       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];
+       char *  p = &buf[MAXBUF-1];
        int nprinted = 0;
 
        do {
@@ -203,8 +224,8 @@ boolean_t   _doprnt_truncates = FALSE;
 
 int
 __doprnt(
-       register const char     *fmt,
-       va_list                 *argp,
+       const char      *fmt,
+       va_list                 argp,
                                                /* character output routine */
        void                    (*putc)(int, void *arg),
        void                    *arg,
@@ -220,7 +241,7 @@ __doprnt(
        int             sign_char;
        boolean_t       altfmt, truncate;
        int             base;
-       register char   c;
+       char    c;
        int             capitals;
        int             long_long;
        int             nprinted = 0;
@@ -276,7 +297,7 @@ __doprnt(
                }
            }
            else if (c == '*') {
-               length = va_arg(*argp, int);
+               length = va_arg(argp, int);
                c = *++fmt;
                if (length < 0) {
                    ladjust = !ladjust;
@@ -294,13 +315,15 @@ __doprnt(
                    }
                }
                else if (c == '*') {
-                   prec = va_arg(*argp, int);
+                   prec = va_arg(argp, int);
                    c = *++fmt;
                }
            }
 
            if (c == 'l') {
                c = *++fmt;     /* need it if sizeof(int) < sizeof(long) */
+               if (sizeof(int)<sizeof(long))
+                   long_long = 1;
                if (c == 'l') {
                    long_long = 1;
                    c = *++fmt;
@@ -322,11 +345,11 @@ __doprnt(
                    register int  i;
 
                    if (long_long) {
-                       u = va_arg(*argp, unsigned long long);
+                       u = va_arg(argp, unsigned long long);
                    } else {
-                       u = va_arg(*argp, unsigned long);
+                       u = va_arg(argp, unsigned int);
                    }
-                   p = va_arg(*argp, char *);
+                   p = va_arg(argp, char *);
                    base = *p++;
                    nprinted += printnum(u, base, putc, arg);
 
@@ -385,22 +408,22 @@ __doprnt(
                }
 
                case 'c':
-                   c = va_arg(*argp, int);
+                   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) {
@@ -421,12 +444,13 @@ __doprnt(
 
                    n = 0;
 
-                   while (*p != '\0') {
-                       if (++n > prec || (length > 0 && n > length))
-                           break;
-
-                       (*putc)(*p++, arg);
-                       nprinted++;
+                   while ((n < prec) && (!(length > 0 && n >= length))) {
+                           if (*p == '\0') {
+                                   break;
+                           }
+                           (*putc)(*p++, arg);
+                           nprinted++;
+                           n++;
                    }
 
                    if (n < length && ladjust) {
@@ -450,8 +474,8 @@ __doprnt(
                    unsigned char *up;
                    char *q, *p;
                    
-                       up = (unsigned char *)va_arg(*argp, unsigned char *);
-                       p = (char *)va_arg(*argp, char *);
+                       up = (unsigned char *)va_arg(argp, unsigned char *);
+                       p = (char *)va_arg(argp, char *);
                        if (length == -1)
                                length = 16;
                        while(length--) {
@@ -482,6 +506,9 @@ __doprnt(
 
                case 'p':
                    altfmt = TRUE;
+                   if (sizeof(int)<sizeof(void *)) {
+                       long_long = 1;
+                   }
                case 'x':
                    truncate = _doprnt_truncates;
                    base = 16;
@@ -516,9 +543,9 @@ __doprnt(
 
                print_signed:
                    if (long_long) {
-                       n = va_arg(*argp, long long);
+                       n = va_arg(argp, long long);
                    } else {
-                       n = va_arg(*argp, long);
+                       n = va_arg(argp, int);
                    }
                    if (n >= 0) {
                        u = n;
@@ -532,9 +559,9 @@ __doprnt(
 
                print_unsigned:
                    if (long_long) {
-                       u = va_arg(*argp, unsigned long long);
+                       u = va_arg(argp, unsigned long long);
                    } else { 
-                       u = va_arg(*argp, unsigned long);
+                       u = va_arg(argp, unsigned int);
                    }
                    goto print_num;
 
@@ -543,7 +570,7 @@ __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 long)((int)(u));
 
@@ -560,11 +587,11 @@ __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 */
@@ -634,7 +661,7 @@ _doprnt(
        void                    (*putc)(char),
        int                     radix)          /* default radix - for '%r' */
 {
-    __doprnt(fmt, argp, dummy_putc, putc, radix);
+    __doprnt(fmt, *argp, dummy_putc, putc, radix);
 }
 
 #if    MP_PRINTF 
@@ -643,7 +670,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)
@@ -651,8 +681,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 */
@@ -704,45 +747,87 @@ 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
 }
 
+#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;
 }
 
-void
-consdebug_putc(
-       char c)
+int
+printf(const char *fmt, ...)
 {
-       extern unsigned int debug_mode, disableDebugOuput, disableConsoleOutput;
+       va_list listp;
 
-       if ((debug_mode && !disableDebugOuput) || !disableConsoleOutput)
+       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;
@@ -750,28 +835,59 @@ kdb_printf(const char *fmt, ...)
        va_start(listp, fmt);
        _doprnt(fmt, &listp, consdebug_putc, 16);
        va_end(listp);
+       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;
+}
 
 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, &copybyte_str, 16);
         va_end(listp);
-        return strlen(buf);
+       *copybyte_str = '\0';
+        return (int)strlen(buf);
 }