Files
my-kern/kernel/libc/kprintf.c

99 lines
2.5 KiB
C

//
// Created by rick on 06-02-21.
//
#include <libc/kprintf.h>
#include <libc/libc.h>
#include <libc/string.h>
#include <stdarg.h>
#include <libk/kprint.h>
#include <libk/libk.h>
#include <types.h>
const char* printf_null_str = "NULL";
/*
* Integer to string
*/
void print_int(uint32_t value, uint32_t width, char *buf, uint32_t *ptr, uint8_t base) {
// uint32_t in binary is 32 digits, so never longer than 33 digits
char msg[33];
itoa(value, msg, base);
uint32_t digits = strlen(msg);
if (digits < width) {
for (uint32_t i = 0; i < (width - digits); ++i) {
buf[*ptr] = '0';
*ptr += 1;
}
}
for (uint32_t i = 0; i < digits; ++i) {
buf[*ptr] = msg[i];
*ptr += 1;
}
}
uint32_t vasprintf(char *buf, const char *fmt, va_list args) {
uint32_t ptr = 0;
for (int i = 0; i < strlen(fmt); ++i) {
if (fmt[i] != '%') {
buf[ptr++] = fmt[i];
continue;
}
++i;
uint32_t arg_width = 0;
while (fmt[i] >= '0' && fmt[i] <= '9') {
arg_width *= 10;
arg_width += fmt[i] - '0';
++i;
}
switch (fmt[i]) {
case 's': { // string
const char *s_fmt = (char *) va_arg(args, char*);
if (s_fmt == NULL) {
s_fmt = printf_null_str;
}
while (*s_fmt) {
buf[ptr++] = *s_fmt++;
}
break;
}
case 'c':
buf[ptr++] = (char) va_arg(args, int);
break;
case 'x':
print_int((uint32_t) va_arg(args, uint32_t), arg_width, buf, &ptr, 16);
break;
case 'i':
case 'd':
print_int((uint32_t) va_arg(args, uint32_t), arg_width, buf, &ptr, 10);
break;
case '%':
buf[ptr++] = '%';
break;
default:
printf("FMT '%c' is not supported\n", fmt[i]);
k_panic();
break;
}
}
buf[ptr] = 0;
return ptr;
}
int printf(const char *fmt, ...) {
int result;
char buf[1024] = {-1};
va_list args;
va_start(args, fmt);
result = vasprintf(buf, fmt, args);
va_end(args);
kprint(buf);
return result;
}
int sprintf(char *target, const char *fmt, ...) {
int result;
va_list args;
va_start(args, fmt);
result = vasprintf(target, fmt, args);
va_end(args);
return result;
}