*
* @APPLE_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.
+ * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
*
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * 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. 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@
*/
#include <stdarg.h>
#include <sys/malloc.h>
#include <sys/lock.h>
-#include <kern/parallel.h>
#include <sys/subr_prf.h>
#include <kern/cpu_number.h> /* for cpu_number() */
extern struct tty cons; /* standard console tty */
extern struct tty *constty; /* pointer to console "window" tty */
+extern int __doprnt(const char *fmt,
+ va_list *argp,
+ void (*putc)(int, void *arg),
+ void *arg,
+ int radix);
/*
* Record cpu that panic'd and lock around panic data
extern void logwakeup();
extern void halt_cpu();
extern boot();
-int putchar();
+
static void
snprintf_func(int ch, void *arg);
+struct putchar_args {
+ int flags;
+ struct tty *tty;
+};
+static void putchar(int c, void *arg);
/*
uprintf(const char *fmt, ...)
{
register struct proc *p = current_proc();
+ struct putchar_args pca;
va_list ap;
+
+ pca.flags = TOTTY;
+ pca.tty = (struct tty *)p->p_session->s_ttyp;
- unix_master(); /* sessions, sigh */
if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
va_start(ap, fmt);
- prf(fmt, ap, TOTTY, (struct tty *)p->p_session->s_ttyvp);
+ __doprnt(fmt, &ap, putchar, &pca, 10);
va_end(ap);
}
- unix_release();
}
tpr_t
tprintf_open(p)
register struct proc *p;
{
- unix_master(); /* sessions, sigh */
if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
SESSHOLD(p->p_session);
- unix_release();
return ((tpr_t) p->p_session);
}
- unix_release();
return ((tpr_t) NULL);
}
tprintf_close(sess)
tpr_t sess;
{
- unix_master(); /* sessions, sigh */
if (sess)
SESSRELE((struct session *) sess);
- unix_release();
}
/*
struct tty *tp = NULL;
int flags = TOLOG;
va_list ap;
+ struct putchar_args pca;
logpri(LOG_INFO);
- unix_master(); /* sessions, sigh */
if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
flags |= TOTTY;
tp = sess->s_ttyp;
}
- if (tp != NULL) {
- va_start(ap, fmt);
- prf(fmt, ap, TOTTY, tp);
- va_end(ap);
- }
- unix_release();
+
+ pca.flags = flags;
+ pca.tty = tp;
+ va_start(ap, fmt);
+ __doprnt(fmt, &ap, putchar, &pca, 10);
+ va_end(ap);
+
logwakeup();
}
va_list ap;
if (tp != NULL) {
+ struct putchar_args pca;
+ pca.flags = TOTTY;
+ pca.tty = tp;
+
va_start(ap, fmt);
- prf(fmt, ap, TOTTY, tp);
+ __doprnt(fmt, &ap, putchar, &pca, 10);
va_end(ap);
}
}
logpri(level)
int level;
{
-
- putchar('<', TOLOG, (struct tty *)0);
+ struct putchar_args pca;
+ pca.flags = TOLOG;
+ pca.tty = NULL;
+
+ putchar('<', &pca);
printn((u_long)level, 10, TOLOG, (struct tty *)0, 0, 0);
- putchar('>', TOLOG, (struct tty *)0);
+ putchar('>', &pca);
}
void
{
register s = splhigh();
va_list ap;
+ struct putchar_args pca;
+
+ pca.flags = TOLOG;
+ pca.tty = NULL;
va_start(ap, fmt);
- prf(fmt, ap, TOLOG, (struct tty *)0);
+ __doprnt(fmt, &ap, putchar, &pca, 10);
+
splx(s);
- if (!log_open)
- prf(fmt, ap, TOCONS, (struct tty *)0);
+ if (!log_open) {
+ pca.flags = TOCONS;
+ __doprnt(fmt, &ap, putchar, &pca, 10);
+ }
va_end(ap);
logwakeup();
}
void _printf(int flags, struct tty *ttyp, const char *format, ...)
{
va_list ap;
+ struct putchar_args pca;
+
+ pca.flags = flags;
+ pca.tty = ttyp;
va_start(ap, format);
- prf(format, ap, flags, ttyp);
+ __doprnt(format, &ap, putchar, &pca, 10);
va_end(ap);
}
int prf(const char *fmt, va_list ap, int flags, struct tty *ttyp)
{
- register int b, c, i;
- char *s;
- int any;
- int zf = 0, fld_size;
-
-#if NCPUS > 1
- int cpun = cpu_number();
+ struct putchar_args pca;
- if(ttyp == 0) {
- simple_lock(&printf_lock);
+ pca.flags = flags;
+ pca.tty = ttyp;
+
+#if NCPUS > 1
+ int cpun = cpu_number();
+
+ if(ttyp == 0) {
+ simple_lock(&printf_lock);
} else
TTY_LOCK(ttyp);
-
+
if (cpun != master_cpu)
- new_printf_cpu_number = TRUE;
+ new_printf_cpu_number = TRUE;
if (new_printf_cpu_number) {
putchar('{', flags, ttyp);
printn((u_long)cpun, 10, flags, ttyp, 0, 0);
putchar('}', flags, ttyp);
}
-#endif /* NCPUS > 1 */
-loop:
- while ((c = *fmt++) != '%') {
- if (c == '\0') {
-#if NCPUS > 1
- if(ttyp == 0) {
- simple_unlock(&printf_lock);
- } else
- TTY_UNLOCK(ttyp);
-#endif
- return 0;
- }
- putchar(c, flags, ttyp);
- }
-again:
- zf = 0;
- fld_size = 0;
- c = *fmt++;
- if (c == '0')
- zf = '0';
- fld_size = 0;
- for (;c <= '9' && c >= '0'; c = *fmt++)
- fld_size = fld_size * 10 + c - '0';
-
- /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */
- switch (c) {
-
- case 'l':
- goto again;
- case 'x': case 'X':
- b = 16;
- goto number;
- case 'd': case 'D':
- case 'u': /* what a joke */
- b = 10;
- goto number;
- case 'o': case 'O':
- b = 8;
-number:
- printn(va_arg(ap, unsigned), b, flags, ttyp, zf, fld_size);
- break;
- case 'c':
- b = va_arg(ap, unsigned);
-#if BYTE_ORDER == LITTLE_ENDIAN
- for (i = 24; i >= 0; i -= 8)
- if (c = (b >> i) & 0x7f)
- putchar(c, flags, ttyp);
-#endif
-#if BYTE_ORDER == BIG_ENDIAN
- if ((c = (b & 0x7f)))
- putchar(c, flags, ttyp);
-#endif
- break;
- case 'b':
- b = va_arg(ap, unsigned);
- s = va_arg(ap, char *);
- printn((u_long)b, *s++, flags, ttyp, 0, 0);
- any = 0;
- if (b) {
- while ((i = *s++)) {
- if (*s <= 32) {
- register int j;
-
- if (any++)
- putchar(',', flags, ttyp);
- j = *s++ ;
- for (; (c = *s) > 32 ; s++)
- putchar(c, flags, ttyp);
- printn( (u_long)( (b >> (j-1)) &
- ( (2 << (i-j)) -1)),
- 8, flags, ttyp, 0, 0);
- } else if (b & (1 << (i-1))) {
- putchar(any? ',' : '<', flags, ttyp);
- any = 1;
- for (; (c = *s) > 32; s++)
- putchar(c, flags, ttyp);
- } else
- for (; *s > 32; s++)
- ;
- }
- putchar('>', flags, ttyp);
- }
- break;
-
- case 's':
- s = va_arg(ap, char *);
-#ifdef DEBUG
- if (fld_size) {
- while (fld_size-- > 0)
- putchar((c = *s++)? c : '_', flags, ttyp);
- } else {
- while ((c = *s++))
- putchar(c, flags, ttyp);
- }
-#else
- while (c = *s++)
- putchar(c, flags, ttyp);
-#endif
- break;
-
- case '%':
- putchar('%', flags, ttyp);
- goto loop;
- case 'C':
- b = va_arg(ap, unsigned);
-#if BYTE_ORDER == LITTLE_ENDIAN
- for (i = 24; i >= 0; i -= 8)
- if (c = (b >> i) & 0x7f)
- putchar(c, flags, ttyp);
-#endif
-#if BYTE_ORDER == BIG_ENDIAN
- if ((c = (b & 0x7f)))
- putchar(c, flags, ttyp);
-#endif
+#endif /* NCPUS > 1 */
+
+ __doprnt(fmt, &ap, putchar, &pca, 10);
- case 'r':
- case 'R':
- b = va_arg(ap, unsigned);
- s = va_arg(ap, char *);
- if (c == 'R') {
- puts("0x", flags, ttyp);
- printn((u_long)b, 16, flags, ttyp, 0, 0);
- }
- any = 0;
- if (c == 'r' || b) {
- register struct reg_desc *rd;
- register struct reg_values *rv;
- unsigned field;
-
- putchar('<', flags, ttyp);
- for (rd = (struct reg_desc *)s; rd->rd_mask; rd++) {
- field = b & rd->rd_mask;
- field = (rd->rd_shift > 0)
- ? field << rd->rd_shift
- : field >> -rd->rd_shift;
- if (any &&
- (rd->rd_format || rd->rd_values
- || (rd->rd_name && field)
- )
- )
- putchar(',', flags, ttyp);
- if (rd->rd_name) {
- if (rd->rd_format || rd->rd_values
- || field) {
- puts(rd->rd_name, flags, ttyp);
- any = 1;
- }
- if (rd->rd_format || rd->rd_values) {
- putchar('=', flags, ttyp);
- any = 1;
- }
- }
- if (rd->rd_format) {
- _printf(flags, ttyp, rd->rd_format,
- field);
- any = 1;
- if (rd->rd_values)
- putchar(':', flags, ttyp);
- }
- if (rd->rd_values) {
- any = 1;
- for (rv = rd->rd_values;
- rv->rv_name;
- rv++) {
- if (field == rv->rv_value) {
- puts(rv->rv_name, flags,
- ttyp);
- break;
- }
- }
- if (rv->rv_name == NULL)
- puts("???", flags, ttyp);
- }
- }
- putchar('>', flags, ttyp);
- }
- break;
-
- case 'n':
- case 'N':
- {
- register struct reg_values *rv;
-
- b = va_arg(ap, unsigned);
- s = va_arg(ap,char *);
- for (rv = (struct reg_values *)s; rv->rv_name; rv++) {
- if (b == rv->rv_value) {
- puts(rv->rv_name, flags, ttyp);
- break;
- }
- }
- if (rv->rv_name == NULL)
- puts("???", flags, ttyp);
- if (c == 'N' || rv->rv_name == NULL) {
- putchar(':', flags, ttyp);
- printn((u_long)b, 10, flags, ttyp, 0, 0);
- }
- }
- break;
- }
- goto loop;
+#if NCPUS > 1
+ if(ttyp == 0) {
+ simple_unlock(&printf_lock);
+ } else
+ TTY_UNLOCK(ttyp);
+#endif
+
+ return 0;
}
static void puts(const char *s, int flags, struct tty *ttyp)
{
register char c;
+ struct putchar_args pca;
+
+ pca.flags = flags;
+ pca.tty = ttyp;
while ((c = *s++))
- putchar(c, flags, ttyp);
+ putchar(c, &pca);
}
/*
{
char prbuf[11];
register char *cp;
+ struct putchar_args pca;
+
+ pca.flags = flags;
+ pca.tty = ttyp;
if (b == 10 && (int)n < 0) {
- putchar('-', flags, ttyp);
+ putchar('-', &pca);
n = (unsigned)(-(int)n);
}
cp = prbuf;
if (fld_size) {
for (fld_size -= cp - prbuf; fld_size > 0; fld_size--)
if (zf)
- putchar('0', flags, ttyp);
+ putchar('0', &pca);
else
- putchar(' ', flags, ttyp);
+ putchar(' ', &pca);
}
do
- putchar(*--cp, flags, ttyp);
+ putchar(*--cp, &pca);
while (cp > prbuf);
}
* are saved in msgbuf for inspection later.
*/
/*ARGSUSED*/
-int
-putchar(c, flags, tp)
- register int c;
- struct tty *tp;
+void
+putchar(int c, void *arg)
{
+ struct putchar_args *pca = arg;
register struct msgbuf *mbp;
- char **sp = (char**) tp;
+ char **sp = (char**) pca->tty;
if (panicstr)
constty = 0;
- if ((flags & TOCONS) && tp == NULL && constty) {
- tp = constty;
- flags |= TOTTY;
+ if ((pca->flags & TOCONS) && pca->tty == NULL && constty) {
+ pca->tty = constty;
+ pca->flags |= TOTTY;
}
- if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
- (flags & TOCONS) && tp == constty)
+ if ((pca->flags & TOTTY) && pca->tty && tputchar(c, pca->tty) < 0 &&
+ (pca->flags & TOCONS) && pca->tty == constty)
constty = 0;
- if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177)
+ if ((pca->flags & TOLOG) && c != '\0' && c != '\r' && c != 0177)
log_putc(c);
- if ((flags & TOCONS) && constty == 0 && c != '\0')
+ if ((pca->flags & TOCONS) && constty == 0 && c != '\0')
(*v_putc)(c);
- if (flags & TOSTR) {
+ if (pca->flags & TOSTR) {
**sp = c;
(*sp)++;
}
- return 0;
}
vsprintf(char *buf, const char *cfmt, va_list ap)
{
int retval;
+ struct snprintf_arg info;
- retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
- buf[retval] = '\0';
- return retval;
+ info.str = buf;
+ info.remain = 999999;
+
+ retval = __doprnt(cfmt, &ap, snprintf_func, &info, 10);
+ if (info.remain >= 1) {
+ *info.str++ = '\0';
+ }
+ return 0;
}
/*
info.str = str;
info.remain = size;
- retval = kvprintf(format, snprintf_func, &info, 10, ap);
+ retval = __doprnt(format, &ap, snprintf_func, &info, 10);
if (info.remain >= 1)
*info.str++ = '\0';
return retval;
}
}
-/*
- * Put a number (base <= 16) in a buffer in reverse order; return an
- * optional length and a pointer to the NULL terminated (preceded?)
- * buffer.
- */
-static char *
-ksprintn(ul, base, lenp)
- register u_long ul;
- register int base, *lenp;
-{ /* A long in base 8, plus NULL. */
- static char buf[sizeof(long) * NBBY / 3 + 2];
- register char *p;
-
- p = buf;
- do {
- *++p = hex2ascii(ul % base);
- } while (ul /= base);
- if (lenp)
- *lenp = p - buf;
- return (p);
-}
-
-/*
- * Scaled down version of printf(3).
- *
- * Two additional formats:
- *
- * The format %b is supported to decode error registers.
- * Its usage is:
- *
- * printf("reg=%b\n", regval, "<base><arg>*");
- *
- * where <base> is the output base expressed as a control character, e.g.
- * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
- * the first of which gives the bit number to be inspected (origin 1), and
- * the next characters (up to a control character, i.e. a character <= 32),
- * give the name of the register. Thus:
- *
- * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
- *
- * would produce output:
- *
- * reg=3<BITTWO,BITONE>
- *
- * XXX: %D -- Hexdump, takes pointer and separator string:
- * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
- * ("%*D", len, ptr, " " -> XX XX XX XX ...
- */
int
kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
{
-#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
- char *p, *q, *d;
- u_char *up;
- int ch, n;
- u_long ul;
- int base, lflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
- int dwidth;
- char padc;
- int retval = 0;
-
- if (!func)
- d = (char *) arg;
- else
- d = NULL;
-
- if (fmt == NULL)
- fmt = "(fmt null)\n";
-
- if (radix < 2 || radix > 36)
- radix = 10;
-
- for (;;) {
- padc = ' ';
- width = 0;
- while ((ch = (u_char)*fmt++) != '%') {
- if (ch == '\0')
- return retval;
- PCHAR(ch);
- }
- lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
- sign = 0; dot = 0; dwidth = 0;
-reswitch: switch (ch = (u_char)*fmt++) {
- case '.':
- dot = 1;
- goto reswitch;
- case '#':
- sharpflag = 1;
- goto reswitch;
- case '+':
- sign = 1;
- goto reswitch;
- case '-':
- ladjust = 1;
- goto reswitch;
- case '%':
- PCHAR(ch);
- break;
- case '*':
- if (!dot) {
- width = va_arg(ap, int);
- if (width < 0) {
- ladjust = !ladjust;
- width = -width;
- }
- } else {
- dwidth = va_arg(ap, int);
- }
- goto reswitch;
- case '0':
- if (!dot) {
- padc = '0';
- goto reswitch;
- }
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- for (n = 0;; ++fmt) {
- n = n * 10 + ch - '0';
- ch = *fmt;
- if (ch < '0' || ch > '9')
- break;
- }
- if (dot)
- dwidth = n;
- else
- width = n;
- goto reswitch;
- case 'b':
- ul = va_arg(ap, int);
- p = va_arg(ap, char *);
- for (q = ksprintn(ul, *p++, NULL); *q;)
- PCHAR(*q--);
-
- if (!ul)
- break;
-
- for (tmp = 0; *p;) {
- n = *p++;
- if (ul & (1 << (n - 1))) {
- PCHAR(tmp ? ',' : '<');
- for (; (n = *p) > ' '; ++p)
- PCHAR(n);
- tmp = 1;
- } else
- for (; *p > ' '; ++p)
- continue;
- }
- if (tmp)
- PCHAR('>');
- break;
- case 'c':
- PCHAR(va_arg(ap, int));
- break;
- case 'D':
- up = va_arg(ap, u_char *);
- p = va_arg(ap, char *);
- if (!width)
- width = 16;
- while(width--) {
- PCHAR(hex2ascii(*up >> 4));
- PCHAR(hex2ascii(*up & 0x0f));
- up++;
- if (width)
- for (q=p;*q;q++)
- PCHAR(*q);
- }
- break;
- case 'd':
- ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
- sign = 1;
- base = 10;
- goto number;
- case 'l':
- lflag = 1;
- goto reswitch;
- case 'o':
- ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
- base = 8;
- goto nosign;
- case 'p':
- ul = (uintptr_t)va_arg(ap, void *);
- base = 16;
- sharpflag = (width == 0);
- goto nosign;
- case 'n':
- case 'r':
- ul = lflag ? va_arg(ap, u_long) :
- sign ? (u_long)va_arg(ap, int) : va_arg(ap, u_int);
- base = radix;
- goto number;
- case 's':
- p = va_arg(ap, char *);
- if (p == NULL)
- p = "(null)";
- if (!dot)
- n = strlen (p);
- else
- for (n = 0; n < dwidth && p[n]; n++)
- continue;
-
- width -= n;
-
- if (!ladjust && width > 0)
- while (width--)
- PCHAR(padc);
- while (n--)
- PCHAR(*p++);
- if (ladjust && width > 0)
- while (width--)
- PCHAR(padc);
- break;
- case 'u':
- ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
- base = 10;
- goto nosign;
- case 'x':
- ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
- base = 16;
- goto nosign;
- case 'z':
- ul = lflag ? va_arg(ap, u_long) :
- sign ? (u_long)va_arg(ap, int) : va_arg(ap, u_int);
- base = 16;
- goto number;
-nosign: sign = 0;
-number: if (sign && (long)ul < 0L) {
- neg = 1;
- ul = -(long)ul;
- }
- p = ksprintn(ul, base, &tmp);
- if (sharpflag && ul != 0) {
- if (base == 8)
- tmp++;
- else if (base == 16)
- tmp += 2;
- }
- if (neg)
- tmp++;
-
- if (!ladjust && width && (width -= tmp) > 0)
- while (width--)
- PCHAR(padc);
- if (neg)
- PCHAR('-');
- if (sharpflag && ul != 0) {
- if (base == 8) {
- PCHAR('0');
- } else if (base == 16) {
- PCHAR('0');
- PCHAR('x');
- }
- }
-
- while (*p)
- PCHAR(*p--);
-
- if (ladjust && width && (width -= tmp) > 0)
- while (width--)
- PCHAR(padc);
-
- break;
- default:
- PCHAR('%');
- if (lflag)
- PCHAR('l');
- PCHAR(ch);
- break;
- }
- }
-#undef PCHAR
+ __doprnt(fmt, &ap, func, arg, radix);
+ return 0;
}
+