1
0
mirror of https://github.com/zeldaret/oot.git synced 2024-09-22 21:35:27 +00:00
oot/src/libultra_boot_O2/_Printf.c

228 lines
6.1 KiB
C
Raw Normal View History

2020-03-17 04:31:30 +00:00
#include <ultra64.h>
#include <ultra64/printf.h>
#include <stdarg.h>
#include <string.h>
2020-03-22 21:19:43 +00:00
#define ATOI(i, a) \
for (i = 0; *a >= '0' && *a <= '9'; a++) \
if (i < 999) \
2020-03-17 04:31:30 +00:00
i = *a + i * 10 - '0';
2020-03-22 21:19:43 +00:00
#define _PROUT(fmt, _size) \
if (_size > 0) { \
arg = (void*)pfn(arg, fmt, _size); \
if (arg != 0) \
x.nchar += _size; \
else \
return x.nchar; \
2020-03-17 04:31:30 +00:00
}
2020-03-22 21:19:43 +00:00
#define _PAD(m, src, extracond) \
if (extracond && m > 0) { \
int i; \
int j; \
for (j = m; j > 0; j -= i) { \
if ((u32)j > 32) \
i = 32; \
else \
i = j; \
_PROUT(src, i); \
} \
2020-03-17 04:31:30 +00:00
}
char spaces[] = " ";
char zeroes[] = "00000000000000000000000000000000";
2020-03-22 21:19:43 +00:00
void _Putfld(_Pft*, va_list*, u8, u8*);
2020-03-17 04:31:30 +00:00
2020-03-22 21:19:43 +00:00
s32 _Printf(char* (*pfn)(char*, const char*, size_t), char* arg, const char* fmt, va_list ap) {
2020-03-17 04:31:30 +00:00
_Pft x;
x.nchar = 0;
while (1) {
const u8* s;
u8 c;
u8* t;
static const u8 fchar[] = " +-#0";
static const u32 fbit[] = { FLAGS_SPACE, FLAGS_PLUS, FLAGS_MINUS, FLAGS_HASH, FLAGS_ZERO, 0 };
u8 ac[0x20];
2020-03-22 21:19:43 +00:00
s = (u8*)fmt;
2020-03-17 04:31:30 +00:00
while ((c = *s) != 0 && c != '%') {
s++;
}
2020-03-22 21:19:43 +00:00
_PROUT(fmt, s - (u8*)fmt);
2020-03-17 04:31:30 +00:00
if (c == 0) {
return x.nchar;
}
2020-03-22 21:19:43 +00:00
fmt = (char*)++s;
2020-03-17 04:31:30 +00:00
x.flags = 0;
for (; (t = strchr(fchar, *s)) != NULL; s++) {
x.flags |= fbit[t - fchar];
}
if (*s == '*') {
x.width = va_arg(ap, s32);
if (x.width < 0) {
x.width = -x.width;
x.flags |= FLAGS_MINUS;
}
s++;
} else {
ATOI(x.width, s);
}
if (*s != '.') {
x.prec = -1;
} else {
s++;
if (*s == '*') {
x.prec = va_arg(ap, s32);
s++;
} else {
ATOI(x.prec, s);
}
}
if (strchr("hlL", *s) != NULL) {
x.qual = *s++;
} else {
x.qual = 0;
}
if (x.qual == 'l' && *s == 'l') {
x.qual = 'L';
s++;
}
_Putfld(&x, &ap, *s, ac);
2020-03-22 21:19:43 +00:00
x.width -= x.n0 + x.nz0 + x.n1 + x.nz1 + x.n2 + x.nz2;
2020-03-17 04:31:30 +00:00
_PAD(x.width, spaces, !(x.flags & FLAGS_MINUS));
2020-03-22 21:19:43 +00:00
_PROUT((char*)ac, x.n0);
2020-03-17 04:31:30 +00:00
_PAD(x.nz0, zeroes, 1);
_PROUT(x.s, x.n1);
_PAD(x.nz1, zeroes, 1);
2020-03-22 21:19:43 +00:00
_PROUT((char*)(&x.s[x.n1]), x.n2)
2020-03-17 04:31:30 +00:00
_PAD(x.nz2, zeroes, 1);
_PAD(x.width, spaces, x.flags & FLAGS_MINUS);
2020-03-22 21:19:43 +00:00
fmt = (char*)s + 1;
2020-03-17 04:31:30 +00:00
}
}
void _Putfld(_Pft* px, va_list* pap, u8 code, u8* ac) {
2020-03-22 21:19:43 +00:00
px->n0 = px->nz0 = px->n1 = px->nz1 = px->n2 = px->nz2 = 0;
2020-03-17 04:31:30 +00:00
switch (code) {
case 'c':
ac[px->n0++] = va_arg(*pap, u32);
break;
case 'd':
case 'i':
if (px->qual == 'l') {
px->v.ll = va_arg(*pap, s32);
} else if (px->qual == 'L') {
px->v.ll = va_arg(*pap, s64);
} else {
px->v.ll = va_arg(*pap, s32);
}
if (px->qual == 'h') {
2020-03-22 21:19:43 +00:00
px->v.ll = (s16)px->v.ll;
2020-03-17 04:31:30 +00:00
}
if (px->v.ll < 0) {
ac[px->n0++] = '-';
} else if (px->flags & FLAGS_PLUS) {
ac[px->n0++] = '+';
} else if (px->flags & FLAGS_SPACE) {
ac[px->n0++] = ' ';
}
2020-03-22 21:19:43 +00:00
px->s = (char*)&ac[px->n0];
2020-03-17 04:31:30 +00:00
_Litob(px, code);
break;
case 'x':
case 'X':
case 'u':
case 'o':
if (px->qual == 'l') {
px->v.ll = va_arg(*pap, s32);
} else if (px->qual == 'L') {
px->v.ll = va_arg(*pap, s64);
} else {
px->v.ll = va_arg(*pap, s32);
}
if (px->qual == 'h') {
2020-03-22 21:19:43 +00:00
px->v.ll = (u16)px->v.ll;
2020-03-17 04:31:30 +00:00
} else if (px->qual == 0) {
2020-03-22 21:19:43 +00:00
px->v.ll = (u32)px->v.ll;
2020-03-17 04:31:30 +00:00
}
if (px->flags & FLAGS_HASH) {
ac[px->n0++] = '0';
if (code == 'x' || code == 'X') {
ac[px->n0++] = code;
}
}
2020-03-22 21:19:43 +00:00
px->s = (char*)&ac[px->n0];
2020-03-17 04:31:30 +00:00
_Litob(px, code);
break;
case 'e':
case 'f':
case 'g':
case 'E':
case 'G':
px->v.ld = px->qual == 'L' ? va_arg(*pap, f64) : va_arg(*pap, f64);
if (*(u16*)&px->v.ll & 0x8000) {
ac[px->n0++] = '-';
} else {
if (px->flags & FLAGS_PLUS) {
ac[px->n0++] = '+';
} else if (px->flags & FLAGS_SPACE) {
ac[px->n0++] = ' ';
}
}
2020-03-22 21:19:43 +00:00
px->s = (char*)&ac[px->n0];
2020-03-17 04:31:30 +00:00
_Ldtob(px, code);
break;
case 'n':
if (px->qual == 'h') {
2020-03-22 21:19:43 +00:00
*(va_arg(*pap, u16*)) = px->nchar;
2020-03-17 04:31:30 +00:00
} else if (px->qual == 'l') {
2020-03-22 21:19:43 +00:00
*va_arg(*pap, u32*) = px->nchar;
2020-03-17 04:31:30 +00:00
} else if (px->qual == 'L') {
2020-03-22 21:19:43 +00:00
*va_arg(*pap, u64*) = px->nchar;
2020-03-17 04:31:30 +00:00
} else {
2020-03-22 21:19:43 +00:00
*va_arg(*pap, u32*) = px->nchar;
2020-03-17 04:31:30 +00:00
}
break;
case 'p':
2020-03-22 21:19:43 +00:00
px->v.ll = (long)va_arg(*pap, void*);
px->s = (char*)&ac[px->n0];
2020-03-17 04:31:30 +00:00
_Litob(px, 'x');
break;
case 's':
2020-03-22 21:19:43 +00:00
px->s = va_arg(*pap, char*);
2020-03-17 04:31:30 +00:00
px->n1 = strlen(px->s);
if (px->prec >= 0 && px->n1 > px->prec) {
px->n1 = px->prec;
}
break;
case '%':
ac[px->n0++] = '%';
break;
default:
ac[px->n0++] = code;
break;
}
2020-03-22 21:19:43 +00:00
}