blob: 0d6d84cf3d7e531167eb171fd0afe5f1c8b6559d [file] [log] [blame]
/* Dumb printing routines
Copyright (C) 1996 Pete A. Zaitcev
1997 Jakub Jelinek
2001 Ben Collins
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA. */
#include "promlib.h"
#include <stringops.h>
/*
* This part is rewritten by Igor Timkin <ivt@msu.su>. Than I
* rewritten it again but kept the MISS style, originated from
* Wladimir Butenko. --P3
*/
#define OBSIZE 200
#ifndef NULL
#define NULL (void *)0
#endif
static void putchar_1 (char c)
{
/* P3: This buffer can be static while xprintf flushes it on exit. */
static char buff[OBSIZE + 1];
static int ox;
if ((buff[ox] = c) == 0) {
prom_puts (buff, ox);
ox = 0;
} else {
if (++ox >= OBSIZE) {
buff[ox] = 0;
prom_puts (buff, ox);
ox = 0;
}
}
}
int putchar (int __c)
{
char c = (char) __c;
if (c == '\n')
putchar_1 ('\r');
putchar_1 (c);
return __c;
}
/*
* Print an unsigned integer in base b, avoiding recursion.
*/
static int printn (long long n, int b)
{
static char prbuf[33];
register char *cp;
int count = 0;
if (b == 10 && n < 0) {
putchar ('-');
count++;
n = -n;
}
cp = prbuf;
do
*cp++ = "0123456789ABCDEF"[(unsigned int) (((unsigned long)n) % b)];
while ((n = ((unsigned long long)n) / b & 0x0FFFFFFFFFFFFFFFULL));
do {
putchar (*--cp);
count++;
} while (cp > prbuf);
return count;
}
int vprintf (char *fmt, va_list adx)
{
register int c;
char *s;
int count = 0;
for (;;) {
while ((c = *fmt++) != '%') {
if (c == '\0') {
putchar (0);
return count;
}
putchar (c);
}
c = *fmt++;
if (c == 'd' || c == 'o' || c == 'x' || c == 'X') {
count += printn ((long long) va_arg (adx, unsigned),
c == 'o' ? 8 : (c == 'd' ? 10 : 16));
} else if (c == 'c') {
putchar (va_arg (adx, unsigned));
count++;
} else if (c == 's') {
if ((s = va_arg (adx, char *)) == NULL)
s = (char *)"(null)";
while ((c = *s++)) {
putchar (c);
count++;
}
} else if (c == 'l' || c == 'O') {
count += printn ((long long) va_arg (adx, long), c == 'l' ? 10 : 8);
} else if (c == 'L') {
int hex = 0;
if (*fmt == 'x') {
fmt++;
hex = 1;
}
count += printn ((long long) va_arg (adx, long long), hex ? 16 : 10);
} else {
/* This is basically what libc's printf does */
putchar('%'); putchar(c);
count += 2;
}
}
return count;
}
/*
* Scaled down version of C Library printf.
* Only %c %s %d (==%u) %o %x %X %l %O are recognized.
*/
void prom_printf (char *fmt,...)
{
va_list x1;
va_start (x1, fmt);
vprintf (fmt, x1);
va_end (x1);
}
static int sprintn (char *str, long long n, int b)
{
static char prbuf[33];
register char *cp;
int count = 0;
if (b == 10 && n < 0) {
memset (str + count, '-', 1);
count++;
n = -n;
}
cp = prbuf;
do
*cp++ = "0123456789ABCDEF"[(unsigned int) (((unsigned long)n) % b)];
while ((n = ((unsigned long long)n) / b & 0x0FFFFFFFFFFFFFFFULL));
do {
memset (str + count, *--cp, 1);
count++;
} while (cp > prbuf);
return count;
}
int vsprintf (char *str, char *fmt, va_list adx)
{
register int c;
char *s;
int count = 0;
for (;;) {
while ((c = *fmt++) != '%') {
memset (str + count, c, 1);
if (c == '\0') {
return count;
}
}
c = *fmt++;
if (c == 'd' || c == 'o' || c == 'x' || c == 'X') {
count += sprintn (str + count, (long long) va_arg (adx, unsigned),
c == 'o' ? 8 : (c == 'd' ? 10 : 16));
} else if (c == 'c') {
memset (str + count, va_arg (adx, unsigned), 1);
count++;
} else if (c == 's') {
if ((s = va_arg (adx, char *)) == NULL)
s = (char *)"(null)";
while ((c = *s++)) {
memset (str + count, c, 1);
count++;
}
} else if (c == 'l' || c == 'O') {
count += sprintn (str + count, (long long) va_arg (adx, long), c == 'l' ? 10 : 8);
} else if (c == 'L') {
int hex = 0;
if (*fmt == 'x') {
fmt++;
hex = 1;
}
count += sprintn (str + count, (long long) va_arg (adx, long long), hex ? 16 : 10);
} else {
/* This is basically what libc's printf does */
memset (str + count, '%', 1);
count++;
memset (str + count, c, 1);
count++;
}
}
return count;
}
/*
* Scaled down version of C Library sprintf.
* Only %c %s %d (==%u) %o %x %X %l %O are recognized.
*/
int sprintf (char *s, char *format, ...)
{
va_list arg;
int done;
va_start (arg, format);
done = vsprintf (s, format, arg);
va_end (arg);
return done;
}