diff options
Diffstat (limited to 'kc')
| -rw-r--r-- | kc/api/lib.h | 4 | ||||
| -rw-r--r-- | kc/core/Makefile | 2 | ||||
| -rw-r--r-- | kc/core/kprint.c | 91 |
3 files changed, 91 insertions, 6 deletions
diff --git a/kc/api/lib.h b/kc/api/lib.h index 3bf0eca..c28e17c 100644 --- a/kc/api/lib.h +++ b/kc/api/lib.h @@ -7,4 +7,8 @@ void *memmove(void *dest, const void *src, size_t size); void *memset(void *dest, int val, size_t size); int memcmp(const void *str1, const void *str2, size_t count); size_t strlen(const char *s); +unsigned long long strtoull( + const char *restrict begin, + char **restrict end, + int base); diff --git a/kc/core/Makefile b/kc/core/Makefile index 9b8983a..2c7303e 100644 --- a/kc/core/Makefile +++ b/kc/core/Makefile @@ -14,7 +14,7 @@ GOBJS := entry_x86_64.o reloc_x86_64.o kprint.o serial.o port.o mmu.o \ kc_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 irq.o \ kcc_memory.o string.o pic8259.o pic8259_isr.o pit8253.o \ - page_early.o page_stack.o + page_early.o page_stack.o strtoull.o IOBJS := # __attribute__((interrupt)) requires -mgeneral-regs-only diff --git a/kc/core/kprint.c b/kc/core/kprint.c index 762f99f..4acbddd 100644 --- a/kc/core/kprint.c +++ b/kc/core/kprint.c @@ -82,7 +82,6 @@ struct specifier static struct specifier parse_specifier(const char *format, va_list *arguments) { - (void)arguments; struct specifier result = { INVALID_PRINT, @@ -150,6 +149,76 @@ static struct specifier parse_specifier(const char *format, va_list *arguments) * b. if is numeric character, parse field precision via strtoul, add * length of numeric string to begin. */ + bool field_width_parsed = false; + bool field_precision_parsed = false; + + while (!field_width_parsed || !field_precision_parsed) + { + switch (*begin) + { + case '.': + if (!field_width_parsed) + { + result.field_width = 0; + field_width_parsed = true; + begin++; + } + else + { + // the specifier is invalid! + result.type = INVALID_PRINT; + } + break; + case '*': + { + int w = *va_arg(*arguments, int *); + if (!field_width_parsed) + { + result.field_width = w; + field_width_parsed = true; + } + else + { + result.field_precision = w; + field_precision_parsed = true; + } + begin++; + } + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '0': + { + char *next; + unsigned long long w = strtoull(begin, &next, 10); + if (!field_width_parsed) + { + result.field_width = (int)w; + field_width_parsed = true; + } + else if (!field_precision_parsed) + { + result.field_precision = (int)w; + field_precision_parsed = true; + } + if (next > begin) + { + begin = next; + } + } + break; + default: + field_width_parsed = true; + field_precision_parsed = true; + } + } // step 3: check for type width arguments switch (*begin) @@ -245,7 +314,7 @@ static struct specifier parse_specifier(const char *format, va_list *arguments) // TODO: use UINTPTR_T_WIDTH here? // pointer type overrides all flags // i can do what i want it says "implementation-defined" in the spec - result.field_precision = 8; + result.field_precision = 16; result.type = INTEGER_PRINT; result.integer_base = HEX_BASE; result.integer_width = LONG_WIDTH; @@ -277,8 +346,9 @@ static struct specifier parse_specifier(const char *format, va_list *arguments) static char *convert_integer( uint64_t value, - unsigned base, - char *buffer, + unsigned base, + int zpadding, + char *buffer, size_t bufsz) { static const char *stringdigits = "0123456789abcdef"; @@ -304,10 +374,16 @@ static char *convert_integer( do { *--result = stringdigits[value % base]; + zpadding--; value /= base; } while (value > 0 && result >= buffer); + while (zpadding-- > 0 && result >= buffer) + { + *--result = '0'; + } + return result; } @@ -361,6 +437,7 @@ static int print_integer( bool negative = false; uint64_t value = 0; int r = 0; + unsigned zpad = 0; switch (spec->integer_width) { @@ -429,7 +506,11 @@ static int print_integer( break; } - s = convert_integer(value, spec->integer_base, buffer, sizeof(buffer)); + if (spec->flags & ZERO_PAD_FLAG) + { + zpad = spec->field_precision; + } + s = convert_integer(value, spec->integer_base, zpad, buffer, sizeof(buffer)); if (s) { |
