diff options
Diffstat (limited to 'kc')
| -rw-r--r-- | kc/core/Makefile | 2 | ||||
| -rw-r--r-- | kc/core/kprint.c | 131 | ||||
| -rw-r--r-- | kc/core/kprint.h | 4 |
3 files changed, 135 insertions, 2 deletions
diff --git a/kc/core/Makefile b/kc/core/Makefile index b0f4035..6874179 100644 --- a/kc/core/Makefile +++ b/kc/core/Makefile @@ -13,7 +13,7 @@ SOBJS := GOBJS := entry_x86_64.o reloc_x86_64.o kprint.o serial.o port.o \ kc_main.o main.o memory.o memset.o memcpy.o memmove.o memcmp.o cpu.o \ vm_tree.o exceptions.o panic.o msr.o task.o cpu_task.o \ - kcc_memory.o + kcc_memory.o string.o IOBJS := # __attribute__((interrupt)) requires -mgeneral-regs-only diff --git a/kc/core/kprint.c b/kc/core/kprint.c index 2f4da01..596d110 100644 --- a/kc/core/kprint.c +++ b/kc/core/kprint.c @@ -1,7 +1,9 @@ #include "kprint.h" #include "serial.h" -#include <stdarg.h> +#include <kc/lib.h> + +#include <stdint.h> __attribute__((optimize("O3"))) int kputchar(int c) @@ -20,3 +22,130 @@ int kputs(const char *s) return 0; } +static char *convert_scalar( + uint64_t value, + unsigned base, + char *buffer, + size_t bufsz) +{ + static const char *stringdigits = "0123456789abcdef"; + + // the string will be built from the lower-to-higher value, and the + // result pointer will point to the first character of the string in + // the supplied buffer + + // gotta zero the buffer + memset(buffer, 0, bufsz); + + // the string is being built backwards, so the pointer needs to be + // at the last byte of the string + char *result = buffer + bufsz - 1; + + // result >= buffer condition ensures we don't overflow + + while (value > 0 && result >= buffer) + { + *--result = stringdigits[value % base]; + value /= base; + } + + return result; +} + +int kvprintf(const char *restrict format, va_list arguments) +{ + int count = 0; + + while (*format) + { + if (*format != '%') + { + kputchar(*format++); + count++; + continue; + } + + switch (*++format) + { + case 0: + return count; + case '%': + count++; + kputchar('%'); + break; + case 's': + { + const char *s = va_arg(arguments, const char *); + count += strlen(s); + kputs(s); + break; + } + + case 'x': + { + char buffer[65]; + char *s = convert_scalar( + va_arg(arguments, uint64_t), + 16, + buffer, + sizeof(buffer)); + count += strlen(s); + kputs(s); + break; + } + case 'd': + { + char buffer[65]; + char *s = convert_scalar( + va_arg(arguments, uint64_t), + 10, + buffer, + sizeof(buffer)); + count += strlen(s); + kputs(s); + break; + } + case 'o': + { + char buffer[65]; + char *s = convert_scalar( + va_arg(arguments, uint64_t), + 8, + buffer, + sizeof(buffer)); + count += strlen(s); + kputs(s); + break; + } + case 'b': + { + char buffer[65]; + char *s = convert_scalar( + va_arg(arguments, uint64_t), + 2, + buffer, + sizeof(buffer)); + count += strlen(s); + kputs(s); + break; + } + + default: + break; + } + + format++; + } + + va_end(arguments); + return count; +} + +int kprintf(const char *restrict format, ...) +{ + va_list arguments; + va_start (arguments, format); + + return kvprintf(format, arguments); +} + diff --git a/kc/core/kprint.h b/kc/core/kprint.h index 5b307a2..0c547ea 100644 --- a/kc/core/kprint.h +++ b/kc/core/kprint.h @@ -1,5 +1,9 @@ #pragma once +#include <stdarg.h> + int kputchar(int c); int kputs(const char *s); +int kprintf(const char *restrict format, ...); +int kvprintf(const char *restrict format, va_list arguments); |
