#include <platforms.h>
#include <mach/boolean.h>
#include <cpus.h>
#include <kern/cpu_number.h>
#include <kern/lock.h>
#include <kern/thread.h>
#include <kern/sched_prim.h>
#include <kern/misc_protos.h>
#include <stdarg.h>
#include <string.h>
#include <mach_assert.h>
#ifdef MACH_BSD
#include <sys/msgbuf.h>
#endif
#ifdef __ppc__
#include <ppc/Firmware.h>
#endif
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)
void
printnum(
register unsigned int u,
register int base,
void (*putc)(char))
{
char buf[MAXBUF];
register char * p = &buf[MAXBUF-1];
static char digs[] = "0123456789abcdef";
do {
*p-- = digs[u % base];
u /= base;
} while (u != 0);
while (++p != &buf[MAXBUF])
(*putc)(*p);
}
boolean_t _doprnt_truncates = FALSE;
void
_doprnt(
register const char *fmt,
va_list *argp,
void (*putc)(char),
int radix)
{
int length;
int prec;
boolean_t ladjust;
char padc;
long n;
unsigned long u;
int plus_sign;
int sign_char;
boolean_t altfmt, truncate;
int base;
register char c;
int capitals;
while ((c = *fmt) != '\0') {
if (c != '%') {
(*putc)(c);
fmt++;
continue;
}
fmt++;
length = 0;
prec = -1;
ladjust = FALSE;
padc = ' ';
plus_sign = 0;
sign_char = 0;
altfmt = FALSE;
while (TRUE) {
c = *fmt;
if (c == '#') {
altfmt = TRUE;
}
else if (c == '-') {
ladjust = TRUE;
}
else if (c == '+') {
plus_sign = '+';
}
else if (c == ' ') {
if (plus_sign == 0)
plus_sign = ' ';
}
else
break;
fmt++;
}
if (c == '0') {
padc = '0';
c = *++fmt;
}
if (isdigit(c)) {
while(isdigit(c)) {
length = 10 * length + Ctod(c);
c = *++fmt;
}
}
else if (c == '*') {
length = va_arg(*argp, int);
c = *++fmt;
if (length < 0) {
ladjust = !ladjust;
length = -length;
}
}
if (c == '.') {
c = *++fmt;
if (isdigit(c)) {
prec = 0;
while(isdigit(c)) {
prec = 10 * prec + Ctod(c);
c = *++fmt;
}
}
else if (c == '*') {
prec = va_arg(*argp, int);
c = *++fmt;
}
}
if (c == 'l')
c = *++fmt;
truncate = FALSE;
capitals=0;
switch(c) {
case 'b':
case 'B':
{
register char *p;
boolean_t any;
register int i;
u = va_arg(*argp, unsigned long);
p = va_arg(*argp, char *);
base = *p++;
printnum(u, base, putc);
if (u == 0)
break;
any = FALSE;
while ((i = *p++) != '\0') {
if (*fmt == 'B')
i = 33 - i;
if (*p <= 32) {
register int j;
if (any)
(*putc)(',');
else {
(*putc)('<');
any = TRUE;
}
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);
}
else if (u & (1<<(i-1))) {
if (any)
(*putc)(',');
else {
(*putc)('<');
any = TRUE;
}
for (; (c = *p) > 32; p++)
(*putc)(c);
}
else {
for (; *p > 32; p++)
continue;
}
}
if (any)
(*putc)('>');
break;
}
case 'c':
c = va_arg(*argp, int);
(*putc)(c);
break;
case 's':
{
register char *p;
register char *p2;
if (prec == -1)
prec = 0x7fffffff;
p = va_arg(*argp, char *);
if (p == (char *)0)
p = "";
if (length > 0 && !ladjust) {
n = 0;
p2 = p;
for (; *p != '\0' && n < prec; p++)
n++;
p = p2;
while (n < length) {
(*putc)(' ');
n++;
}
}
n = 0;
while (*p != '\0') {
if (++n > prec || (length > 0 && n > length))
break;
(*putc)(*p++);
}
if (n < length && ladjust) {
while (n < length) {
(*putc)(' ');
n++;
}
}
break;
}
case 'o':
truncate = _doprnt_truncates;
case 'O':
base = 8;
goto print_unsigned;
case 'd':
truncate = _doprnt_truncates;
case 'D':
base = 10;
goto print_signed;
case 'u':
truncate = _doprnt_truncates;
case 'U':
base = 10;
goto print_unsigned;
case 'p':
altfmt = TRUE;
case 'x':
truncate = _doprnt_truncates;
base = 16;
goto print_unsigned;
case 'X':
base = 16;
capitals=16;
goto print_unsigned;
case 'z':
truncate = _doprnt_truncates;
base = 16;
goto print_signed;
case 'Z':
base = 16;
capitals=16;
goto print_signed;
case 'r':
truncate = _doprnt_truncates;
case 'R':
base = radix;
goto print_signed;
case 'n':
truncate = _doprnt_truncates;
case 'N':
base = radix;
goto print_unsigned;
print_signed:
n = va_arg(*argp, long);
if (n >= 0) {
u = n;
sign_char = plus_sign;
}
else {
u = -n;
sign_char = '-';
}
goto print_num;
print_unsigned:
u = va_arg(*argp, unsigned long);
goto print_num;
print_num:
{
char buf[MAXBUF];
register char * p = &buf[MAXBUF-1];
static char digits[] = "0123456789abcdef0123456789ABCDEF";
char *prefix = 0;
if (truncate) u = (long)((int)(u));
if (u != 0 && altfmt) {
if (base == 8)
prefix = "0";
else if (base == 16)
prefix = "0x";
}
do {
*p-- = digits[(u % base)+capitals];
u /= base;
} while (u != 0);
length -= (&buf[MAXBUF-1] - p);
if (sign_char)
length--;
if (prefix)
length -= strlen((const char *) prefix);
if (padc == ' ' && !ladjust) {
while (--length >= 0)
(*putc)(' ');
}
if (sign_char)
(*putc)(sign_char);
if (prefix)
while (*prefix)
(*putc)(*prefix++);
if (padc == '0') {
while (--length >= 0)
(*putc)('0');
}
while (++p != &buf[MAXBUF])
(*putc)(*p);
if (ladjust) {
while (--length >= 0)
(*putc)(' ');
}
break;
}
case '\0':
fmt--;
break;
default:
(*putc)(c);
}
fmt++;
}
}
#if MP_PRINTF
boolean_t new_printf_cpu_number = FALSE;
#endif
decl_simple_lock_data(,printf_lock)
decl_mutex_data(,sprintf_lock)
void
printf_init(void)
{
simple_lock_init(&printf_lock, ETAP_MISC_PRINTF);
mutex_init(&sprintf_lock, ETAP_MISC_PRINTF);
}
void
safe_gets(
char *str,
int maxlen)
{
register char *lp;
register int c;
char *strmax = str + maxlen - 1;
lp = str;
for (;;) {
c = cngetc();
switch (c) {
case '\n':
case '\r':
printf("\n");
*lp++ = 0;
return;
case '\b':
case '#':
case '\177':
if (lp > str) {
printf("\b \b");
lp--;
}
continue;
case '@':
case 'u'&037:
lp = str;
printf("\n\r");
continue;
default:
if (c >= ' ' && c < '\177') {
if (lp < strmax) {
*lp++ = c;
printf("%c", c);
}
else {
printf("%c", '\007');
}
}
}
}
}
void
conslog_putc(
char c)
{
extern unsigned int debug_mode, disableDebugOuput, disableConsoleOutput;
if ((debug_mode && !disableDebugOuput) || !disableConsoleOutput)
cnputc(c);
#ifdef MACH_BSD
log_putc(c);
#endif
}
void
printf(const char *fmt, ...)
{
va_list listp;
disable_preemption();
va_start(listp, fmt);
_doprnt(fmt, &listp, conslog_putc, 16);
va_end(listp);
enable_preemption();
}
static char *copybyte_str;
static void
copybyte(
char byte)
{
*copybyte_str++ = byte;
*copybyte_str = '\0';
}
int
sprintf(char *buf, const char *fmt, ...)
{
va_list listp;
va_start(listp, fmt);
mutex_lock(&sprintf_lock);
copybyte_str = buf;
_doprnt(fmt, &listp, copybyte, 16);
mutex_unlock(&sprintf_lock);
va_end(listp);
return strlen(buf);
}