Re-implement string formatting (%s, %d, %x)

This commit is contained in:
Lauri Kenttä
2023-11-20 16:05:33 +02:00
parent 4e50b33636
commit 0dfc49c800
4 changed files with 93 additions and 22 deletions

View File

@@ -14,31 +14,99 @@ const CHAR16* TmpStr(CHAR8 *src, int length) {
return dest;
}
const CHAR16* TmpIntToStr(UINT32 x) {
static CHAR16 buf[20];
int i = 20 - 1;
buf[i] = 0;
if (!x) {
buf[--i] = '0';
}
while (x && i) {
buf[--i] = '0' + (x % 10);
x /= 10;
}
return &buf[i];
}
#define log_buffer_size (65536)
CHAR16 log_buffer[log_buffer_size] = {0};
CHAR16 LogVarName[] = L"HackBGRTLog";
EFI_GUID LogVarGuid = {0x03c64761, 0x075f, 0x4dba, {0xab, 0xfb, 0x2e, 0xd8, 0x9e, 0x18, 0xb2, 0x36}}; // self-made: 03c64761-075f-4dba-abfb-2ed89e18b236
void Log(int print, IN CONST CHAR16 *fmt, ...) {
void Log(int mode, IN CONST CHAR16 *fmt, ...) {
va_list args;
CHAR16 buf[256];
CHAR16 buf[256] = {0};
int buf_i = 0;
#define putchar(c) { if (buf_i < 255) { buf[buf_i++] = c; } }
va_start(args, fmt);
VSPrint(buf, sizeof(buf), fmt, args); // size is in bytes, not CHAR16s
va_end(args);
if (print) {
Print(L"%s", buf);
for (int i = 0; fmt[i]; ++i) {
if (fmt[i] == '\n') {
putchar('\r');
putchar('\n');
continue;
}
if (fmt[i] != '%') {
putchar(fmt[i]);
continue;
}
++i;
switch (fmt[i]) {
case '%': putchar('%'); continue;
case 'd': goto fmt_decimal;
case 'x': goto fmt_hex;
case 's': goto fmt_string;
case 0: goto fmt_end;
}
putchar('%');
putchar(fmt[i]);
continue;
if (0) fmt_decimal: {
INT32 x = va_arg(args, INT32);
if (x < 0) {
putchar('-');
x = -x;
}
const CHAR16* s = TmpIntToStr(x);
while (*s) {
putchar(*s++);
}
}
if (0) fmt_hex: {
UINT32 x = va_arg(args, UINT32);
for (int pos = 8, started = 0; pos--;) {
int d = (x >> (4 * pos)) & 0xf;
if (d || started || pos == 0) {
putchar("0123456789abcdef"[d]);
started = 1;
}
}
}
if (0) fmt_string: {
CHAR16* s = va_arg(args, CHAR16*);
while (*s) {
putchar(*s++);
}
}
}
fmt_end:
va_end(args);
if (mode) {
ST->ConOut->OutputString(ST->ConOut, buf);
}
if (mode != -1) {
StrnCat(log_buffer, buf, log_buffer_size - StrLen(log_buffer) - 1);
RT->SetVariable(LogVarName, &LogVarGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, StrLen(log_buffer) * 2, log_buffer);
}
StrnCat(log_buffer, buf, log_buffer_size - StrLen(log_buffer) - 1);
LibSetVariable(LogVarName, &LogVarGuid, StrLen(log_buffer) * 2, log_buffer);
}
void DumpLog(void) {
Print(L"%s", log_buffer);
ST->ConOut->OutputString(ST->ConOut, log_buffer);
}
void ClearLogVariable(void) {
LibDeleteVariable(LogVarName, &LogVarGuid);
RT->SetVariable(LogVarName, &LogVarGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, 0, 0);
}
const CHAR16* TrimLeft(const CHAR16* s) {