From e6203d58cc7e472a7937c0c830f3658970b88a2f Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Fri, 9 Dec 2022 06:59:54 +0400 Subject: [PATCH] Create generic debug output formatter (#136) --- .gitignore | 1 + ChangeLog | 4 + Makefile.am | 1 + README.md | 2 + examples/Makefile.am | 8 ++ examples/generic_display.c | 115 +++++++++++++++++++++ include/Makefile.am | 1 + include/kernaux/generic/display.h | 37 +++++++ include/kernaux/multiboot2.h.in | 17 +-- src/generic/display.c | 115 +++++++++++++++++++++ src/multiboot2/header_print.c | 35 ++++--- src/multiboot2/info_print.c | 166 ++++++++++++++++-------------- tests/multiboot2_header_print1.c | 24 +++-- tests/multiboot2_header_print2.c | 24 +++-- tests/multiboot2_info_print1.c | 24 +++-- tests/multiboot2_info_print2.c | 24 +++-- 16 files changed, 473 insertions(+), 125 deletions(-) create mode 100644 examples/generic_display.c create mode 100644 include/kernaux/generic/display.h create mode 100644 src/generic/display.c diff --git a/.gitignore b/.gitignore index 44f99e70..270fa634 100644 --- a/.gitignore +++ b/.gitignore @@ -79,6 +79,7 @@ /examples/assert /examples/cmdline +/examples/generic_display /examples/generic_malloc /examples/generic_mutex /examples/macro_bits diff --git a/ChangeLog b/ChangeLog index eb309dbf..fdb0fa18 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2022-12-09 Alex Kotov + + * include/kernaux/generic/display.h: The header has been added + 2022-12-08 Alex Kotov * include/kernaux/*.h: Definition "KERNAUX_BITFIELDS" has been added diff --git a/Makefile.am b/Makefile.am index 1022f1d5..b3aea180 100644 --- a/Makefile.am +++ b/Makefile.am @@ -31,6 +31,7 @@ lib_LTLIBRARIES = libkernaux.la libkernaux_la_LIBADD = libkernaux_la_SOURCES = \ src/assert.c \ + src/generic/display.c \ src/generic/malloc.c \ src/generic/mutex.c diff --git a/README.md b/README.md index 3791e4a8..1bc3ba52 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,8 @@ zero). Work-in-progress APIs can change at any time. * [Example: Panic](/examples/panic.c) * Stack trace *(planned)* * Generic types + * [Display](/include/kernaux/generic/display.h) (*non-breaking since* **?.?.?**) + * [Example](/examples/generic_display.c) * [Memory allocator](/include/kernaux/generic/malloc.h) (*non-breaking since* **0.5.0**) * [Example](/examples/generic_malloc.c) * [Mutex](/include/kernaux/generic/mutex.h) (*non-breaking since* **0.5.0**) diff --git a/examples/Makefile.am b/examples/Makefile.am index 1308dfa4..b792a506 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -21,6 +21,14 @@ cmdline_LDADD = $(top_builddir)/libkernaux.la cmdline_SOURCES = main.c cmdline.c endif +################### +# generic_display # +################### + +TESTS += generic_display +generic_display_LDADD = $(top_builddir)/libkernaux.la +generic_display_SOURCES = main.c generic_display.c + ################## # generic_malloc # ################## diff --git a/examples/generic_display.c b/examples/generic_display.c new file mode 100644 index 00000000..44da528c --- /dev/null +++ b/examples/generic_display.c @@ -0,0 +1,115 @@ +//============== +// my_display.c +//============== + +// To not always use macro "KERNAUX_PROTECTED_FIELD" around the names of +// structure fields you may define "KERNAUX_ACCESS_PROTECTED" before including +// any other headers, but ONLY in the file where you implement a generic type. +// +#define KERNAUX_ACCESS_PROTECTED + +//============== +// my_display.h +//============== + +#include +#include + +typedef struct MyDisplay { + struct KernAux_Display display; + char *buffer, *cursor; + size_t capacity; +} *MyDisplay; + +struct MyDisplay MyDisplay_create(); + +//============== +// my_display.c +//============== + +#include +#include +#include +#include +#include +#include +#include + +#define CAP_FREE (1024) +#define CAP_INCR (2 * (CAP_FREE)) + +static void MyDisplay_putc(void *display, char c); +void MyDisplay_vprintf(void *display, const char *format, va_list va); + +static void MyDisplay_realloc(MyDisplay my_display); + +struct MyDisplay MyDisplay_create() +{ + char *const buffer = malloc(CAP_INCR); + if (!buffer) abort(); + + return (struct MyDisplay){ + .display = { + .putc = MyDisplay_putc, + .vprintf = MyDisplay_vprintf, + }, + .buffer = buffer, + .cursor = buffer, + .capacity = CAP_INCR, + }; +} + +void MyDisplay_putc(void *display, char c) +{ + const MyDisplay my_display = display; + MyDisplay_realloc(my_display); + *(my_display->cursor++) = c; +} + +void MyDisplay_vprintf(void *display, const char *format, va_list va) +{ + const MyDisplay my_display = display; + MyDisplay_realloc(my_display); + size_t left = + my_display->buffer + my_display->capacity - my_display->cursor; + const int delta = vsnprintf(my_display->cursor, left, format, va); + if (delta < 0) abort(); + my_display->cursor += delta; +} + +void MyDisplay_realloc(const MyDisplay my_display) +{ + size_t left = + my_display->buffer + my_display->capacity - my_display->cursor; + + if (left < CAP_FREE) { + my_display->buffer = + realloc(my_display->buffer, my_display->capacity + CAP_INCR); + if (!my_display->buffer) abort(); + my_display->capacity += CAP_INCR; + } +} + +//======== +// main.c +//======== + +void example_main() +{ + struct MyDisplay my_display = MyDisplay_create(); + + KernAux_Display_putc(&my_display.display, '@'); + KernAux_Display_print(&my_display.display, "print"); + KernAux_Display_println(&my_display.display, "println"); + KernAux_Display_write(&my_display.display, "write!!!", 5); + KernAux_Display_writeln(&my_display.display, "writeln!!!", 7); + KernAux_Display_printf(&my_display.display, "printf(%d)", 123); + KernAux_Display_printlnf(&my_display.display, "printfln(%d)", 123); + + assert( + strcmp( + my_display.buffer, + "@printprintln\nwritewriteln\nprintf(123)printfln(123)\n" + ) == 0 + ); +} diff --git a/include/Makefile.am b/include/Makefile.am index f8f40ee8..2245853c 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -9,6 +9,7 @@ nobase_include_HEADERS = \ kernaux/macro/packing_start.run \ kernaux/macro/packing_end.run \ kernaux/version.h \ + kernaux/generic/display.h \ kernaux/generic/malloc.h \ kernaux/generic/mutex.h diff --git a/include/kernaux/generic/display.h b/include/kernaux/generic/display.h new file mode 100644 index 00000000..cbe1ed80 --- /dev/null +++ b/include/kernaux/generic/display.h @@ -0,0 +1,37 @@ +#ifndef KERNAUX_INCLUDED_DISPLAY +#define KERNAUX_INCLUDED_DISPLAY + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include +#include + +typedef void (*KernAux_Display_Putc )(void *display, char c); +typedef void (*KernAux_Display_Vprintf)(void *display, const char *format, va_list va); + +typedef const struct KernAux_Display { + KernAux_Display_Putc KERNAUX_PROTECTED_FIELD(putc); + KernAux_Display_Vprintf KERNAUX_PROTECTED_FIELD(vprintf); +} *KernAux_Display; + +void KernAux_Display_putc (KernAux_Display display, char c); +void KernAux_Display_print (KernAux_Display display, const char *s); +void KernAux_Display_println (KernAux_Display display, const char *s); +void KernAux_Display_write (KernAux_Display display, const char *data, size_t size); +void KernAux_Display_writeln (KernAux_Display display, const char *data, size_t size); +KERNAUX_PRINTF(2, 3) +void KernAux_Display_printf (KernAux_Display display, const char *format, ...); +KERNAUX_PRINTF(2, 3) +void KernAux_Display_printlnf (KernAux_Display display, const char *format, ...); +void KernAux_Display_vprintf (KernAux_Display display, const char *format, va_list va); +void KernAux_Display_vprintlnf(KernAux_Display display, const char *format, va_list va); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/kernaux/multiboot2.h.in b/include/kernaux/multiboot2.h.in index fb7088e1..ad5941ec 100644 --- a/include/kernaux/multiboot2.h.in +++ b/include/kernaux/multiboot2.h.in @@ -6,6 +6,7 @@ extern "C" { #endif #include +#include @comment_line_memmap@#include #include @@ -789,12 +790,12 @@ bool KernAux_Multiboot2_ITag_ImageLoadBasePhysAddr_is_valid( void KernAux_Multiboot2_Header_print( const struct KernAux_Multiboot2_Header *multiboot2_header, - void (*printf)(const char *format, ...) KERNAUX_PRINTF(1, 2) + KernAux_Display display ); void KernAux_Multiboot2_HTagBase_print( const struct KernAux_Multiboot2_HTagBase *tag_base, - void (*printf)(const char *format, ...) KERNAUX_PRINTF(1, 2) + KernAux_Display display ); /******************************* @@ -803,32 +804,32 @@ void KernAux_Multiboot2_HTagBase_print( void KernAux_Multiboot2_Info_print( const struct KernAux_Multiboot2_Info *multiboot2_info, - void (*printf)(const char *format, ...) KERNAUX_PRINTF(1, 2) + KernAux_Display display ); void KernAux_Multiboot2_ITagBase_print( const struct KernAux_Multiboot2_ITagBase *tag_base, - void (*printf)(const char *format, ...) KERNAUX_PRINTF(1, 2) + KernAux_Display display ); void KernAux_Multiboot2_ITag_BootCmdLine_print( const struct KernAux_Multiboot2_ITag_BootCmdLine *tag, - void (*printf)(const char *format, ...) KERNAUX_PRINTF(1, 2) + KernAux_Display display ); void KernAux_Multiboot2_ITag_BootLoaderName_print( const struct KernAux_Multiboot2_ITag_BootLoaderName *tag, - void (*printf)(const char *format, ...) KERNAUX_PRINTF(1, 2) + KernAux_Display display ); void KernAux_Multiboot2_ITag_MemoryMap_print( const struct KernAux_Multiboot2_ITag_MemoryMap *tag, - void (*printf)(const char *format, ...) KERNAUX_PRINTF(1, 2) + KernAux_Display display ); void KernAux_Multiboot2_ITag_ELFSymbols_print( const struct KernAux_Multiboot2_ITag_ELFSymbols *tag, - void (*printf)(const char *format, ...) KERNAUX_PRINTF(1, 2) + KernAux_Display display ); #ifdef __cplusplus diff --git a/src/generic/display.c b/src/generic/display.c new file mode 100644 index 00000000..36a40919 --- /dev/null +++ b/src/generic/display.c @@ -0,0 +1,115 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include +#include + +void KernAux_Display_putc(const KernAux_Display display, const char c) +{ + KERNAUX_ASSERT(display); + KERNAUX_ASSERT(display->putc); + + // Inherited implementation + display->putc((void*)display, c); +} + +void KernAux_Display_print(const KernAux_Display display, const char *const s) +{ + KERNAUX_ASSERT(display); + KERNAUX_ASSERT(display->putc); + + // Default implementation + for (const char *c = s; *c; ++c) display->putc((void*)display, *c); +} + +void KernAux_Display_println(const KernAux_Display display, const char *const s) +{ + KERNAUX_ASSERT(display); + KERNAUX_ASSERT(display->putc); + + // Default implementation + KernAux_Display_print(display, s); + display->putc((void*)display, '\n'); +} + +void KernAux_Display_write( + const KernAux_Display display, + const char *const data, + const size_t size +) { + KERNAUX_ASSERT(display); + KERNAUX_ASSERT(display->putc); + + // Default implementation + for (size_t i = 0; i < size; ++i) display->putc((void*)display, data[i]); +} + +void KernAux_Display_writeln( + const KernAux_Display display, + const char *const data, + const size_t size +) { + KERNAUX_ASSERT(display); + KERNAUX_ASSERT(display->putc); + + // Default implementation + KernAux_Display_write(display, data, size); + display->putc((void*)display, '\n'); +} + +void KernAux_Display_printf( + const KernAux_Display display, + const char *const format, + ... +) { + KERNAUX_ASSERT(display); + + // Default implementation + va_list va; + va_start(va, format); + KernAux_Display_vprintf(display, format, va); + va_end(va); +} + +void KernAux_Display_printlnf( + const KernAux_Display display, + const char *const format, + ... +) { + KERNAUX_ASSERT(display); + + // Default implementation + va_list va; + va_start(va, format); + KernAux_Display_vprintlnf(display, format, va); + va_end(va); +} + +void KernAux_Display_vprintf( + const KernAux_Display display, + const char *const format, + va_list va +) { + KERNAUX_ASSERT(display); + KERNAUX_ASSERT(display->vprintf); + + // Inherited implementation + display->vprintf((void*)display, format, va); +} + +void KernAux_Display_vprintlnf( + const KernAux_Display display, + const char *const format, + va_list va +) { + KERNAUX_ASSERT(display); + KERNAUX_ASSERT(display->putc); + + // Default implementation + KernAux_Display_vprintf(display, format, va); + display->putc((void*)display, '\n'); +} diff --git a/src/multiboot2/header_print.c b/src/multiboot2/header_print.c index 63dc493c..6804ae0b 100644 --- a/src/multiboot2/header_print.c +++ b/src/multiboot2/header_print.c @@ -3,27 +3,31 @@ #endif #include +#include #include #include #include +#define PRINTLN(s) KernAux_Display_println(display, s) +#define PRINTLNF(format, ...) \ + KernAux_Display_printlnf(display, format, __VA_ARGS__) + void KernAux_Multiboot2_Header_print( const struct KernAux_Multiboot2_Header *const multiboot2_header, - void (*const printf)(const char *format, ...) + const KernAux_Display display ) { KERNAUX_ASSERT(multiboot2_header); - KERNAUX_ASSERT(printf); + KERNAUX_ASSERT(display); - printf("Multiboot 2 header\n"); - printf(" magic: %u\n", multiboot2_header->magic); - printf( - " arch: %u (%s)\n", + PRINTLN("Multiboot 2 header"); + PRINTLNF(" magic: %u", multiboot2_header->magic); + PRINTLNF(" arch: %u (%s)", multiboot2_header->arch, KernAux_Multiboot2_Header_Arch_to_str(multiboot2_header->arch) ); - printf(" size: %u\n", multiboot2_header->total_size); - printf(" checksum: %u\n", multiboot2_header->checksum); + PRINTLNF(" size: %u", multiboot2_header->total_size); + PRINTLNF(" checksum: %u", multiboot2_header->checksum); const struct KernAux_Multiboot2_HTagBase *tag_base = (struct KernAux_Multiboot2_HTagBase*) @@ -35,7 +39,7 @@ void KernAux_Multiboot2_Header_print( { if (!KernAux_Multiboot2_HTagBase_is_valid(tag_base)) return; - KernAux_Multiboot2_HTagBase_print(tag_base, printf); + KernAux_Multiboot2_HTagBase_print(tag_base, display); tag_base = KERNAUX_MULTIBOOT2_HTAG_NEXT(tag_base); } @@ -43,23 +47,22 @@ void KernAux_Multiboot2_Header_print( void KernAux_Multiboot2_HTagBase_print( const struct KernAux_Multiboot2_HTagBase *const tag_base, - void (*const printf)(const char *format, ...) + const KernAux_Display display ) { KERNAUX_ASSERT(tag_base); - KERNAUX_ASSERT(printf); + KERNAUX_ASSERT(display); if (!KernAux_Multiboot2_HTagBase_is_valid(tag_base)) return; - printf("Multiboot 2 header tag\n"); + PRINTLN("Multiboot 2 header tag"); - printf( - " type: %u (%s)\n", + PRINTLNF(" type: %u (%s)", tag_base->type, KernAux_Multiboot2_HTag_to_str(tag_base->type) ); - printf(" flags: %u\n", tag_base->flags); - printf(" size: %u\n", tag_base->size); + PRINTLNF(" flags: %u", tag_base->flags); + PRINTLNF(" size: %u", tag_base->size); switch (tag_base->type) { case KERNAUX_MULTIBOOT2_HTAG_NONE: diff --git a/src/multiboot2/info_print.c b/src/multiboot2/info_print.c index 09c66f72..1cf2a93a 100644 --- a/src/multiboot2/info_print.c +++ b/src/multiboot2/info_print.c @@ -8,16 +8,23 @@ #include #include +// TODO: create macro for this +#define INT_IF(a, b) (sizeof(int) == sizeof(long) ? (a) : (b)) + +#define PRINTLN(s) KernAux_Display_println(display, s) +#define PRINTLNF(format, ...) \ + KernAux_Display_printlnf(display, format, __VA_ARGS__) + void KernAux_Multiboot2_Info_print( const struct KernAux_Multiboot2_Info *const multiboot2_info, - void (*const printf)(const char *format, ...) + const KernAux_Display display ) { KERNAUX_ASSERT(multiboot2_info); - KERNAUX_ASSERT(printf); + KERNAUX_ASSERT(display); - printf("Multiboot 2 info\n"); - printf(" size: %u\n", multiboot2_info->total_size); - printf(" reserved1: %u\n", multiboot2_info->reserved1); + PRINTLN("Multiboot 2 info"); + PRINTLNF(" size: %u", multiboot2_info->total_size); + PRINTLNF(" reserved1: %u", multiboot2_info->reserved1); const struct KernAux_Multiboot2_ITagBase *tag_base = (struct KernAux_Multiboot2_ITagBase*) @@ -29,7 +36,7 @@ void KernAux_Multiboot2_Info_print( { if (!KernAux_Multiboot2_ITagBase_is_valid(tag_base)) return; - KernAux_Multiboot2_ITagBase_print(tag_base, printf); + KernAux_Multiboot2_ITagBase_print(tag_base, display); tag_base = KERNAUX_MULTIBOOT2_ITAG_NEXT(tag_base); } @@ -37,22 +44,21 @@ void KernAux_Multiboot2_Info_print( void KernAux_Multiboot2_ITagBase_print( const struct KernAux_Multiboot2_ITagBase *const tag_base, - void (*const printf)(const char *format, ...) + const KernAux_Display display ) { KERNAUX_ASSERT(tag_base); - KERNAUX_ASSERT(printf); + KERNAUX_ASSERT(display); if (!KernAux_Multiboot2_ITagBase_is_valid(tag_base)) return; - printf("Multiboot 2 info tag\n"); + PRINTLN("Multiboot 2 info tag"); - printf( - " type: %u (%s)\n", + PRINTLNF(" type: %u (%s)", tag_base->type, KernAux_Multiboot2_ITag_to_str(tag_base->type) ); - printf(" size: %u\n", tag_base->size); + PRINTLNF(" size: %u", tag_base->size); switch (tag_base->type) { case KERNAUX_MULTIBOOT2_ITAG_NONE: @@ -60,13 +66,13 @@ void KernAux_Multiboot2_ITagBase_print( case KERNAUX_MULTIBOOT2_ITAG_BOOT_CMD_LINE: KernAux_Multiboot2_ITag_BootCmdLine_print( (struct KernAux_Multiboot2_ITag_BootCmdLine*)tag_base, - printf + display ); break; case KERNAUX_MULTIBOOT2_ITAG_BOOT_LOADER_NAME: KernAux_Multiboot2_ITag_BootLoaderName_print( (struct KernAux_Multiboot2_ITag_BootLoaderName*)tag_base, - printf + display ); break; case KERNAUX_MULTIBOOT2_ITAG_MODULE: @@ -74,9 +80,9 @@ void KernAux_Multiboot2_ITagBase_print( const struct KernAux_Multiboot2_ITag_Module *const tag_module = (struct KernAux_Multiboot2_ITag_Module*)tag_base; - printf(" start: %u\n", tag_module->mod_start); - printf(" end: %u\n", tag_module->mod_end); - printf(" cmdline: %s\n", KERNAUX_MULTIBOOT2_DATA(tag_module)); + PRINTLNF(" start: %u", tag_module->mod_start); + PRINTLNF(" end: %u", tag_module->mod_end); + PRINTLNF(" cmdline: %s", KERNAUX_MULTIBOOT2_DATA(tag_module)); } break; case KERNAUX_MULTIBOOT2_ITAG_BASIC_MEMORY_INFO: @@ -84,8 +90,8 @@ void KernAux_Multiboot2_ITagBase_print( const struct KernAux_Multiboot2_ITag_BasicMemoryInfo *const tag_bmi = (struct KernAux_Multiboot2_ITag_BasicMemoryInfo*)tag_base; - printf(" mem lower: %u\n", tag_bmi->mem_lower); - printf(" mem upper: %u\n", tag_bmi->mem_upper); + PRINTLNF(" mem lower: %u", tag_bmi->mem_lower); + PRINTLNF(" mem upper: %u", tag_bmi->mem_upper); } break; case KERNAUX_MULTIBOOT2_ITAG_BIOS_BOOT_DEVICE: @@ -93,15 +99,15 @@ void KernAux_Multiboot2_ITagBase_print( const struct KernAux_Multiboot2_ITag_BIOSBootDevice *const tag_bbd = (struct KernAux_Multiboot2_ITag_BIOSBootDevice*)tag_base; - printf(" bios dev: %u\n", tag_bbd->bios_dev); - printf(" partition: %u\n", tag_bbd->partition); - printf(" sub_partition: %u\n", tag_bbd->sub_partition); + PRINTLNF(" bios dev: %u", tag_bbd->bios_dev); + PRINTLNF(" partition: %u", tag_bbd->partition); + PRINTLNF(" sub_partition: %u", tag_bbd->sub_partition); } break; case KERNAUX_MULTIBOOT2_ITAG_MEMORY_MAP: KernAux_Multiboot2_ITag_MemoryMap_print( (struct KernAux_Multiboot2_ITag_MemoryMap*)tag_base, - printf + display ); break; case KERNAUX_MULTIBOOT2_ITAG_VBE_INFO: @@ -109,10 +115,10 @@ void KernAux_Multiboot2_ITagBase_print( const struct KernAux_Multiboot2_ITag_VBEInfo *const tag_vbe = (struct KernAux_Multiboot2_ITag_VBEInfo*)tag_base; - printf(" VBE mode: %hu\n", tag_vbe->vbe_mode); - printf(" VBE interface seg: %hu\n", tag_vbe->vbe_interface_seg); - printf(" VBE interface off: %hu\n", tag_vbe->vbe_interface_off); - printf(" VBE interface len: %hu\n", tag_vbe->vbe_interface_len); + PRINTLNF(" VBE mode: %hu", tag_vbe->vbe_mode); + PRINTLNF(" VBE interface seg: %hu", tag_vbe->vbe_interface_seg); + PRINTLNF(" VBE interface off: %hu", tag_vbe->vbe_interface_off); + PRINTLNF(" VBE interface len: %hu", tag_vbe->vbe_interface_len); } break; case KERNAUX_MULTIBOOT2_ITAG_FRAMEBUFFER_INFO: @@ -120,19 +126,22 @@ void KernAux_Multiboot2_ITagBase_print( const struct KernAux_Multiboot2_ITag_FramebufferInfo *const tag_fb = (struct KernAux_Multiboot2_ITag_FramebufferInfo*)tag_base; - printf(" framebuffer addr: %llu\n", tag_fb->framebuffer_addr); - printf(" framebuffer pitch: %u\n", tag_fb->framebuffer_pitch); - printf(" framebuffer width: %u\n", tag_fb->framebuffer_width); - printf(" framebuffer height: %u\n", tag_fb->framebuffer_height); - printf(" framebuffer bpp: %u\n", tag_fb->framebuffer_bpp); - printf(" framebuffer type: %u\n", tag_fb->framebuffer_type); - printf(" reserved1: %u\n", tag_fb->reserved1); + PRINTLNF( + INT_IF(" framebuffer addr: %llu", " framebuffer addr: %lu"), + tag_fb->framebuffer_addr + ); + PRINTLNF(" framebuffer pitch: %u", tag_fb->framebuffer_pitch); + PRINTLNF(" framebuffer width: %u", tag_fb->framebuffer_width); + PRINTLNF(" framebuffer height: %u", tag_fb->framebuffer_height); + PRINTLNF(" framebuffer bpp: %u", tag_fb->framebuffer_bpp); + PRINTLNF(" framebuffer type: %u", tag_fb->framebuffer_type); + PRINTLNF(" reserved1: %u", tag_fb->reserved1); } break; case KERNAUX_MULTIBOOT2_ITAG_ELF_SYMBOLS: KernAux_Multiboot2_ITag_ELFSymbols_print( (struct KernAux_Multiboot2_ITag_ELFSymbols*)tag_base, - printf + display ); break; case KERNAUX_MULTIBOOT2_ITAG_APM_TABLE: @@ -140,15 +149,15 @@ void KernAux_Multiboot2_ITagBase_print( const struct KernAux_Multiboot2_ITag_APMTable *const tag_apm = (struct KernAux_Multiboot2_ITag_APMTable*)tag_base; - printf(" version: %hu\n", tag_apm->version); - printf(" cseg: %hu\n", tag_apm->cseg); - printf(" offset: %u\n", tag_apm->offset); - printf(" cseg 16: %hu\n", tag_apm->cseg_16); - printf(" dseg: %hu\n", tag_apm->dseg); - printf(" flags: %hu\n", tag_apm->flags); - printf(" cseg len: %hu\n", tag_apm->cseg_len); - printf(" cseg 16 len: %hu\n", tag_apm->cseg_16_len); - printf(" dseg len: %hu\n", tag_apm->dseg_len); + PRINTLNF(" version: %hu", tag_apm->version); + PRINTLNF(" cseg: %hu", tag_apm->cseg); + PRINTLNF(" offset: %u", tag_apm->offset); + PRINTLNF(" cseg 16: %hu", tag_apm->cseg_16); + PRINTLNF(" dseg: %hu", tag_apm->dseg); + PRINTLNF(" flags: %hu", tag_apm->flags); + PRINTLNF(" cseg len: %hu", tag_apm->cseg_len); + PRINTLNF(" cseg 16 len: %hu", tag_apm->cseg_16_len); + PRINTLNF(" dseg len: %hu", tag_apm->dseg_len); } break; case KERNAUX_MULTIBOOT2_ITAG_EFI_32BIT_SYSTEM_TABLE_PTR: @@ -166,11 +175,10 @@ void KernAux_Multiboot2_ITagBase_print( const struct KernAux_Multiboot2_ITag_SMBIOSTables *const tag_smbios = (struct KernAux_Multiboot2_ITag_SMBIOSTables*)tag_base; - printf(" major: %u\n", tag_smbios->major); - printf(" minor: %u\n", tag_smbios->minor); + PRINTLNF(" major: %u", tag_smbios->major); + PRINTLNF(" minor: %u", tag_smbios->minor); - printf( - " reserved1: {%u, %u, %u, %u, %u, %u}\n", + PRINTLNF(" reserved1: {%u, %u, %u, %u, %u, %u}", tag_smbios->reserved1[0], tag_smbios->reserved1[1], tag_smbios->reserved1[2], @@ -213,8 +221,7 @@ void KernAux_Multiboot2_ITagBase_print( } break; case KERNAUX_MULTIBOOT2_ITAG_IMAGE_LOAD_BASE_PHYS_ADDR: - printf( - " load base addr: %u\n", + PRINTLNF(" load base addr: %u", ((struct KernAux_Multiboot2_ITag_ImageLoadBasePhysAddr*)tag_base)-> load_base_addr ); @@ -224,50 +231,49 @@ void KernAux_Multiboot2_ITagBase_print( void KernAux_Multiboot2_ITag_BootCmdLine_print( const struct KernAux_Multiboot2_ITag_BootCmdLine *const tag, - void (*printf)(const char *format, ...) + const KernAux_Display display ) { KERNAUX_ASSERT(tag); - KERNAUX_ASSERT(printf); + KERNAUX_ASSERT(display); if (!KernAux_Multiboot2_ITag_BootCmdLine_is_valid(tag)) { - printf(" invalid!\n"); + PRINTLN(" invalid!"); return; } - printf(" cmdline: %s\n", KERNAUX_MULTIBOOT2_DATA(tag)); + PRINTLNF(" cmdline: %s", KERNAUX_MULTIBOOT2_DATA(tag)); } void KernAux_Multiboot2_ITag_BootLoaderName_print( const struct KernAux_Multiboot2_ITag_BootLoaderName *const tag, - void (*printf)(const char *format, ...) + const KernAux_Display display ) { KERNAUX_ASSERT(tag); - KERNAUX_ASSERT(printf); + KERNAUX_ASSERT(display); if (!KernAux_Multiboot2_ITag_BootLoaderName_is_valid(tag)) { - printf(" invalid!\n"); + PRINTLN(" invalid!"); return; } - printf(" name: %s\n", KERNAUX_MULTIBOOT2_DATA(tag)); + PRINTLNF(" name: %s", KERNAUX_MULTIBOOT2_DATA(tag)); } void KernAux_Multiboot2_ITag_MemoryMap_print( const struct KernAux_Multiboot2_ITag_MemoryMap *const tag, - void (*printf)(const char *format, ...) + const KernAux_Display display ) { KERNAUX_ASSERT(tag); - KERNAUX_ASSERT(printf); + KERNAUX_ASSERT(display); if (!KernAux_Multiboot2_ITag_MemoryMap_is_valid(tag)) { - printf(" invalid!\n"); + PRINTLN(" invalid!"); return; } - printf(" entry size: %u\n", tag->entry_size); - printf(" entry version: %u\n", tag->entry_version); - - printf(" entries:\n"); + PRINTLNF(" entry size: %u", tag->entry_size); + PRINTLNF(" entry version: %u", tag->entry_version); + PRINTLN(" entries:"); const struct KernAux_Multiboot2_ITag_MemoryMap_EntryBase *const entries = (struct KernAux_Multiboot2_ITag_MemoryMap_EntryBase*) @@ -278,30 +284,36 @@ void KernAux_Multiboot2_ITag_MemoryMap_print( index < (tag->base.size - sizeof(*tag)) / tag->entry_size; ++index ) { - printf(" entry %lu\n", index); - printf(" base addr: %llu\n", entries[index].base_addr); - printf(" length: %llu\n", entries[index].length); - printf(" type: %u\n", entries[index].type); - printf(" reserved1: %u\n", entries[index].reserved1); + PRINTLNF(INT_IF(" entry %u", " entry %lu"), index); + PRINTLNF( + INT_IF(" base addr: %llu", " base addr: %lu"), + entries[index].base_addr + ); + PRINTLNF( + INT_IF(" length: %llu", " length: %lu"), + entries[index].length + ); + PRINTLNF(" type: %u", entries[index].type); + PRINTLNF(" reserved1: %u", entries[index].reserved1); } } void KernAux_Multiboot2_ITag_ELFSymbols_print( const struct KernAux_Multiboot2_ITag_ELFSymbols *const tag, - void (*printf)(const char *format, ...) + const KernAux_Display display ) { KERNAUX_ASSERT(tag); - KERNAUX_ASSERT(printf); + KERNAUX_ASSERT(display); if (!KernAux_Multiboot2_ITag_ELFSymbols_is_valid(tag)) { - printf(" invalid!\n"); + PRINTLN(" invalid!"); return; } - printf(" num: %hu\n", tag->num); - printf(" entsize: %hu\n", tag->ent_size); - printf(" shndx: %hu\n", tag->shndx); - printf(" reserved1: %hu\n", tag->reserved1); + PRINTLNF(" num: %hu", tag->num); + PRINTLNF(" entsize: %hu", tag->ent_size); + PRINTLNF(" shndx: %hu", tag->shndx); + PRINTLNF(" reserved1: %hu", tag->reserved1); // TODO: implement this } diff --git a/tests/multiboot2_header_print1.c b/tests/multiboot2_header_print1.c index b9608e08..0eab3d22 100644 --- a/tests/multiboot2_header_print1.c +++ b/tests/multiboot2_header_print1.c @@ -2,6 +2,10 @@ #include "config.h" #endif +#define KERNAUX_ACCESS_PROTECTED + +#include +#include #include #include @@ -10,14 +14,22 @@ #include "multiboot2_header_example1.h" -static void my_printf(const char *format, ...) +static void my_putc(void *display KERNAUX_UNUSED, char c) { - va_list va; - va_start(va, format); - vprintf(format, va); - va_end(va); + putchar(c); } +static +void my_vprintf(void *display KERNAUX_UNUSED, const char *format, va_list va) +{ + vprintf(format, va); +} + +static const struct KernAux_Display display = { + .putc = my_putc, + .vprintf = my_vprintf, +}; + void test_main() { assert(KernAux_Multiboot2_Header_is_valid( @@ -26,6 +38,6 @@ void test_main() KernAux_Multiboot2_Header_print( (struct KernAux_Multiboot2_Header*)&multiboot2_header_example1, - my_printf + &display ); } diff --git a/tests/multiboot2_header_print2.c b/tests/multiboot2_header_print2.c index faf79ec7..50b41bba 100644 --- a/tests/multiboot2_header_print2.c +++ b/tests/multiboot2_header_print2.c @@ -2,6 +2,10 @@ #include "config.h" #endif +#define KERNAUX_ACCESS_PROTECTED + +#include +#include #include #include @@ -10,14 +14,22 @@ #include "multiboot2_header_example2.h" -static void my_printf(const char *format, ...) +static void my_putc(void *display KERNAUX_UNUSED, char c) { - va_list va; - va_start(va, format); - vprintf(format, va); - va_end(va); + putchar(c); } +static +void my_vprintf(void *display KERNAUX_UNUSED, const char *format, va_list va) +{ + vprintf(format, va); +} + +static const struct KernAux_Display display = { + .putc = my_putc, + .vprintf = my_vprintf, +}; + void test_main() { assert(KernAux_Multiboot2_Header_is_valid( @@ -26,6 +38,6 @@ void test_main() KernAux_Multiboot2_Header_print( &multiboot2_header_example2.multiboot2_header, - my_printf + &display ); } diff --git a/tests/multiboot2_info_print1.c b/tests/multiboot2_info_print1.c index e4bc4112..095821a0 100644 --- a/tests/multiboot2_info_print1.c +++ b/tests/multiboot2_info_print1.c @@ -2,6 +2,10 @@ #include "config.h" #endif +#define KERNAUX_ACCESS_PROTECTED + +#include +#include #include #include @@ -10,14 +14,22 @@ #include "multiboot2_info_example1.h" -static void my_printf(const char *format, ...) +static void my_putc(void *display KERNAUX_UNUSED, char c) { - va_list va; - va_start(va, format); - vprintf(format, va); - va_end(va); + putchar(c); } +static +void my_vprintf(void *display KERNAUX_UNUSED, const char *format, va_list va) +{ + vprintf(format, va); +} + +static const struct KernAux_Display display = { + .putc = my_putc, + .vprintf = my_vprintf, +}; + void test_main() { assert(KernAux_Multiboot2_Info_is_valid( @@ -26,6 +38,6 @@ void test_main() KernAux_Multiboot2_Info_print( (struct KernAux_Multiboot2_Info*)multiboot2_info_example1, - my_printf + &display ); } diff --git a/tests/multiboot2_info_print2.c b/tests/multiboot2_info_print2.c index 82007b65..30ed471d 100644 --- a/tests/multiboot2_info_print2.c +++ b/tests/multiboot2_info_print2.c @@ -2,6 +2,10 @@ #include "config.h" #endif +#define KERNAUX_ACCESS_PROTECTED + +#include +#include #include #include @@ -10,14 +14,22 @@ #include "multiboot2_info_example2.h" -static void my_printf(const char *format, ...) +static void my_putc(void *display KERNAUX_UNUSED, char c) { - va_list va; - va_start(va, format); - vprintf(format, va); - va_end(va); + putchar(c); } +static +void my_vprintf(void *display KERNAUX_UNUSED, const char *format, va_list va) +{ + vprintf(format, va); +} + +static const struct KernAux_Display display = { + .putc = my_putc, + .vprintf = my_vprintf, +}; + void test_main() { assert(KernAux_Multiboot2_Info_is_valid( @@ -26,6 +38,6 @@ void test_main() KernAux_Multiboot2_Info_print( &multiboot2_info_example2.multiboot2_info, - my_printf + &display ); }