132 lines
3.3 KiB
C
132 lines
3.3 KiB
C
//
|
|
// Created by rick on 06-02-21.
|
|
//
|
|
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <myke/libk/kprint.h>
|
|
#include <myke/libk/libk.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;
|
|
}
|
|
}
|
|
|
|
void vasprintf_unsupported(char c) {
|
|
char *msg = "FMT '%x' is not supported\n";
|
|
msg[6] = c;
|
|
k_panics(msg);
|
|
}
|
|
|
|
uint32_t vasprintf(char *buf, const char *fmt, va_list args) {
|
|
uint32_t ptr = 0;
|
|
for (size_t i = 0; i < strlen(fmt); ++i) {
|
|
if (fmt[i] != '%') {
|
|
buf[ptr++] = fmt[i];
|
|
continue;
|
|
}
|
|
++i;
|
|
uint32_t field_width = 0;
|
|
uint32_t precision = 0; // todo
|
|
bool negative_field_width = false; // todo
|
|
if (fmt[i] == '-') {
|
|
// invert
|
|
negative_field_width = true;
|
|
++i;
|
|
}
|
|
while (fmt[i] >= '0' && fmt[i] <= '9') {
|
|
field_width *= 10;
|
|
field_width += fmt[i] - '0';
|
|
++i;
|
|
}
|
|
if (fmt[i] == '.') {
|
|
++i;
|
|
while (fmt[i] >= '0' && fmt[i] <= '9') {
|
|
precision *= 10;
|
|
precision += fmt[i] - '0';
|
|
++i;
|
|
}
|
|
}
|
|
switch (fmt[i]) {
|
|
case 's': { // string
|
|
uint32_t j = 0;
|
|
const char *s_fmt = (char *) va_arg(args, char*);
|
|
if (s_fmt == NULL) {
|
|
s_fmt = printf_null_str;
|
|
}
|
|
while (*s_fmt && (precision == 0 || j != precision)) {
|
|
buf[ptr++] = *s_fmt++;
|
|
j++;
|
|
}
|
|
break;
|
|
}
|
|
case 'c':
|
|
buf[ptr++] = (char) va_arg(args, int);
|
|
break;
|
|
case 'x':
|
|
case 'X': // todo capitalize
|
|
print_int((uint32_t) va_arg(args, uint32_t), field_width, buf, &ptr, 16);
|
|
break;
|
|
case 'i':
|
|
case 'd':
|
|
case 'u':
|
|
print_int((uint32_t) va_arg(args, uint32_t), field_width, buf, &ptr, 10);
|
|
break;
|
|
case '%':
|
|
buf[ptr++] = '%';
|
|
break;
|
|
default:
|
|
vasprintf_unsupported(fmt[i]);
|
|
break;
|
|
}
|
|
}
|
|
buf[ptr] = 0;
|
|
return ptr;
|
|
}
|
|
|
|
int vprintf(const char *fmt, va_list args) {
|
|
int result;
|
|
char buf[1024] = {-1};
|
|
result = vasprintf(buf, fmt, args);
|
|
kprint(buf);
|
|
return result;
|
|
}
|
|
|
|
int printf(const char *fmt, ...) {
|
|
int result;
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
result = vprintf(fmt, args);
|
|
va_end(args);
|
|
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;
|
|
} |