mirror of
https://github.com/lewurm/savezelda.git
synced 2024-11-18 00:29:19 +01:00
154 lines
2.5 KiB
C
154 lines
2.5 KiB
C
|
// Copyright 2009 Segher Boessenkool <segher@kernel.crashing.org>
|
||
|
// This code is licensed to you under the terms of the GNU GPL, version 2;
|
||
|
// see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
||
|
|
||
|
|
||
|
#include <stdarg.h>
|
||
|
|
||
|
#include "loader.h"
|
||
|
|
||
|
|
||
|
static void put(char c)
|
||
|
{
|
||
|
fb_putc(c);
|
||
|
usbgecko_console_putc(c);
|
||
|
}
|
||
|
|
||
|
|
||
|
// __umoddi3() and friends are very big, and more general than we need:
|
||
|
// radix is always (very) small, so we can work by much bigger chunks
|
||
|
// than single bits, always.
|
||
|
static int extract_dig(u64 *x, u32 radix)
|
||
|
{
|
||
|
u32 hi = *x >> 32;
|
||
|
u32 lo = *x;
|
||
|
u32 mod = hi % radix;
|
||
|
hi /= radix;
|
||
|
u32 n = (mod << 16) | (lo >> 16);
|
||
|
mod = n % radix;
|
||
|
n /= radix;
|
||
|
lo = (mod << 16) | (lo & 0xffff);
|
||
|
mod = lo % radix;
|
||
|
lo /= radix;
|
||
|
lo |= (n << 16);
|
||
|
*x = ((u64)hi << 32) | lo;
|
||
|
return mod;
|
||
|
}
|
||
|
|
||
|
|
||
|
// This implements conversions %{0}{number}{l,ll}[%cdsux] only.
|
||
|
// Field length is obeyed for numbers only.
|
||
|
// Always returns 0.
|
||
|
|
||
|
int printf(const char *restrict format, ...)
|
||
|
{
|
||
|
va_list ap;
|
||
|
|
||
|
va_start(ap, format);
|
||
|
|
||
|
while (*format) {
|
||
|
if (*format != '%') {
|
||
|
put(*format++);
|
||
|
continue;
|
||
|
}
|
||
|
format++;
|
||
|
|
||
|
int zero = 0;
|
||
|
int prec = 0;
|
||
|
|
||
|
if (*format == '0') {
|
||
|
zero = 1;
|
||
|
format++;
|
||
|
}
|
||
|
|
||
|
while (*format >= '0' && *format <= '9')
|
||
|
prec = 10*prec + (*format++ - '0');
|
||
|
|
||
|
int ll = 0;
|
||
|
while (*format == 'l') {
|
||
|
ll++;
|
||
|
format++;
|
||
|
}
|
||
|
|
||
|
int radix = 10;
|
||
|
int is_signed = 1;
|
||
|
|
||
|
switch (*format++) {
|
||
|
case '%':
|
||
|
put('%');
|
||
|
break;
|
||
|
|
||
|
case 'c':
|
||
|
put(va_arg(ap, int));
|
||
|
break;
|
||
|
|
||
|
case 's':
|
||
|
;
|
||
|
char *s = va_arg(ap, char *);
|
||
|
while (*s)
|
||
|
put(*s++);
|
||
|
break;
|
||
|
|
||
|
case 'x':
|
||
|
radix = 16;
|
||
|
|
||
|
case 'u':
|
||
|
is_signed = 0;
|
||
|
|
||
|
case 'd':
|
||
|
;
|
||
|
u64 x;
|
||
|
if (is_signed) {
|
||
|
if (ll == 0)
|
||
|
x = va_arg(ap, int);
|
||
|
else if (ll == 1)
|
||
|
x = va_arg(ap, long);
|
||
|
else
|
||
|
x = va_arg(ap, long long);
|
||
|
} else {
|
||
|
if (ll == 0)
|
||
|
x = va_arg(ap, unsigned int);
|
||
|
else if (ll == 1)
|
||
|
x = va_arg(ap, unsigned long);
|
||
|
else
|
||
|
x = va_arg(ap, unsigned long long);
|
||
|
}
|
||
|
|
||
|
if (is_signed) {
|
||
|
if ((long long)x < 0)
|
||
|
x = -x;
|
||
|
else
|
||
|
is_signed = 0;
|
||
|
}
|
||
|
|
||
|
char hold[22];
|
||
|
char *hld = &hold[sizeof hold];
|
||
|
*--hld = 0;
|
||
|
|
||
|
int len = 0;
|
||
|
do {
|
||
|
int dig = extract_dig(&x, radix);
|
||
|
if (dig >= 10)
|
||
|
dig += 'a' - 10;
|
||
|
else
|
||
|
dig += '0';
|
||
|
*--hld = dig;
|
||
|
len++;
|
||
|
} while (x);
|
||
|
if (is_signed)
|
||
|
*--hld = '-';
|
||
|
|
||
|
while (len < prec) {
|
||
|
put(zero ? '0' : ' ');
|
||
|
len++;
|
||
|
}
|
||
|
while (*hld)
|
||
|
put(*hld++);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
va_end(ap);
|
||
|
|
||
|
return 0;
|
||
|
}
|