Files
KirkOS/src/stdio.c
T
2026-04-14 22:52:24 -04:00

140 lines
3.3 KiB
C

#include <stdarg.h>
#include <stdbool.h>
#include "stdio.h"
#include "debug.h"
#include "video/render.h"
#include "arch/x86_64/e9.h"
#include "mp/spinlock.h"
static const uint32_t g_LogSeverityColors[] =
{
[LVL_DEBUG] = 0xAAAAAA, // light gray
[LVL_INFO] = 0xFFFFFF, // white
[LVL_WARN] = 0xFFFF00, // yellow
[LVL_ERROR] = 0xFF0000, // red
[LVL_CRITICAL] = 0xFFFFFF, // white (can do red background separately if you want)
};
static spinlock_t s_printf_lock = SPINLOCK_INIT;
void fputc(char c)
{
putchar(c);
e9_putc(c);
}
void fputs(const char* str)
{
const char* s = str;
while (*s) fputc(*s++);
}
void fputs_colored(const char* str, uint32_t color) {
while (*str) putchar_colored(*str++, color);
while (*str) fputc(*str++);
}
const char g_HexChars[] = "0123456789abcdef";
void fprintf_unsigned(uint64_t number, int radix)
{
char buffer[32];
int pos = 0;
do {
buffer[pos++] = g_HexChars[number % radix];
number /= radix;
} while (number > 0);
while (--pos >= 0) fputc(buffer[pos]);
}
void fprintf_signed(int64_t number, int radix)
{
if (number < 0) {
fputc('-');
fprintf_unsigned(-number, radix);
} else {
fprintf_unsigned(number, radix);
}
}
void vfprintf(const char* fmt, va_list args)
{
int state = 0; // normal
int length = 0; // default
int radix = 10;
bool sign = false;
bool number = false;
while (*fmt) {
switch (state) {
case 0: // normal
if (*fmt == '%') state = 1;
else fputc(*fmt);
break;
case 1: // length
if (*fmt == 'l') { length = 3; state = 4; }
else if (*fmt == 'h') { length = 2; state = 4; }
else goto spec;
break;
case 4: // spec
spec:
switch (*fmt) {
case 'c': fputc((char)va_arg(args,int)); break;
case 's': fputs(va_arg(args,const char*)); break;
case 'd':
case 'i': sign = true; number = true; radix = 10; break;
case 'u': sign = false; number = true; radix = 10; break;
case 'x':
case 'X': sign = false; number = true; radix = 16; break;
case 'p': number = true; sign = false; radix = 16; break;
case 'o': sign = false; number = true; radix = 8; break;
case '%': fputc('%'); break;
}
if (number) {
if (sign) fprintf_signed(va_arg(args,long), radix);
else fprintf_unsigned(va_arg(args,unsigned long), radix);
}
state = 0;
length = 0;
number = false;
sign = false;
break;
}
fmt++;
}
}
void printf(const char* fmt, ...)
{
uint64_t flags;
spinlock_acquire_irqsave(&s_printf_lock, &flags);
va_list args;
va_start(args, fmt);
vfprintf(fmt, args);
va_end(args);
spinlock_release_irqrestore(&s_printf_lock, flags);
}
void fprintf(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(fmt, args);
va_end(args);
}