// // Created by rick on 06-02-21. // #include "kprintf.h" #include "libc.h" #include #include #include #include #include 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; }