diff --git a/kernel/inc/utils/string.h b/kernel/inc/utils/string.h index edf20c5..8d3a215 100644 --- a/kernel/inc/utils/string.h +++ b/kernel/inc/utils/string.h @@ -17,11 +17,18 @@ #define NOX_STRING_H #include "stdtypes.h" +#include typedef const char* string_t; uint32_t string_length (string_t string); bool string_compare (string_t a, string_t b); + +uint64_t variadic_format_size (string_t string, va_list args); +uint64_t format_size (string_t string, ...); +void variadic_format (string_t output, string_t string, va_list args); +void format (string_t output, string_t string, ...); + void string_unsigned_dec_to_alpha (string_t string, uint64_t value); void string_dec_to_alpha (string_t string, int64_t value); void string_hex_8bit_to_alpha (string_t string, uint8_t value); diff --git a/kernel/src/kmain.c b/kernel/src/kmain.c index 120afe6..57b5b5a 100644 --- a/kernel/src/kmain.c +++ b/kernel/src/kmain.c @@ -41,12 +41,16 @@ void kmain(boot_info_T boot_info) { kernel_init(&boot_info); - // this should cause a kernel panic -// int x = 1312 / 0; + uint64_t size = format_size("Test: %d", 1312); + + char string[size]; + format(string, "Test: %d", 1312); + + char buf[16]; + format(buf, "size: %d", size); - char string[17]; - string_hex_64bit_to_alpha(string, &kmain); log(LOG_DEBUG, string); + log(LOG_DEBUG, buf); CORE_HALT_FOREVER diff --git a/kernel/src/utils/string.c b/kernel/src/utils/string.c index 9a28855..b7a46b3 100644 --- a/kernel/src/utils/string.c +++ b/kernel/src/utils/string.c @@ -40,6 +40,263 @@ bool string_compare(string_t a, string_t b) { return memory_compare(a, b, a_len); } +uint64_t variadic_format_size(string_t string, va_list args) { + const char* buffer_in = (const char*)string; + + uint64_t length = 0; + while(*buffer_in != '\0') { + if (*buffer_in == '%') { + uint8_t numeric_specifier = 0; + buffer_in++; + if (*buffer_in == '.') { + buffer_in++; + while (*buffer_in > '0' && *buffer_in < '9') { + numeric_specifier *= 10; + numeric_specifier += *buffer_in - '0'; + buffer_in++; + } + } + + switch(*buffer_in) { + case '%': { + length++; + break; + } + case 's': { + // string + length += string_length(va_arg(args, string_t)); + break; + } + case 'c': { + // char + char tmp = (char)va_arg(args, int); + length++; + break; + } + case 'u': { + // decimal unsigned int + char str[32]; + string_unsigned_dec_to_alpha(str, va_arg(args, uint64_t)); + length += string_length(str); + break; + } + case 'd': { + // decimal signed int + char str[32]; + string_dec_to_alpha(str, va_arg(args, int64_t)); + length += string_length(str); + break; + } + case 'x': { + // Hexadecimal int + char str[32]; + + buffer_in++; + switch(*buffer_in) { + case 'b': { + // byte + string_hex_8bit_to_alpha(str, va_arg(args, int)); + break; + } + case 'w': { + // word + string_hex_16bit_to_alpha(str, va_arg(args, int)); + break; + } + case 'd': { + // dword + string_hex_32bit_to_alpha(str, va_arg(args, uint32_t)); + break; + } + case 'q': { + // qword + string_hex_64bit_to_alpha(str, va_arg(args, uint64_t)); + break; + } + default: { + string_hex_64bit_to_alpha(str, va_arg(args, uint64_t)); + buffer_in--; + break; + } + } + length += string_length(str); + break; + } + case '?': { + char str[7]; + string_bool_to_alpha(str, (bool)va_arg(args, int)); + length += string_length(str); + break; + } + case 'b': { + if (numeric_specifier == 0) { + numeric_specifier = 64; + } + + char str[65]; + string_bin_to_alpha(str, numeric_specifier, va_arg(args, uint64_t)); + length += string_length(str); + break; + } + } + } else { + length++; + } + buffer_in++; + } + length++; + + return length; +} + +uint64_t format_size(string_t string, ...) { + va_list args; + va_start(args, string); + + uint64_t size = variadic_format_size(string, args); + + va_end(args); + return size; +} + +void variadic_format(string_t output, string_t string, va_list args) { + char* buffer_out = (char*)output; + const char* buffer_in = (const char*)string; + + while(*buffer_in != '\0') { + if (*buffer_in == '%') { + uint8_t numeric_specifier = 0; + buffer_in++; + if (*buffer_in == '.') { + buffer_in++; + while (*buffer_in > '0' && *buffer_in < '9') { + numeric_specifier *= 10; + numeric_specifier += *buffer_in - '0'; + buffer_in++; + } + } + + switch(*buffer_in) { + case '%': { + *buffer_out = '%'; + buffer_out++; + break; + } + case 's': { + // string + string_t str = va_arg(args, string_t); + uint64_t strlen = string_length(str); + + memory_copy((void*)str, buffer_out, strlen); + buffer_out += strlen; + break; + } + case 'c': { + // char + *buffer_out = (char)va_arg(args, int); + buffer_out++; + break; + } + case 'u': { + // decimal unsigned int + char str[32]; + string_unsigned_dec_to_alpha(str, va_arg(args, uint64_t)); + uint64_t strlen = string_length(str); + + memory_copy((void*)str, buffer_out, strlen); + buffer_out += strlen; + break; + } + case 'd': { + // decimal signed int + char str[32]; + string_dec_to_alpha(str, va_arg(args, int64_t)); + uint64_t strlen = string_length(str); + + memory_copy((void*)str, buffer_out, strlen); + buffer_out += strlen; + break; + } + case 'x': { + // Hexadecimal int + char str[32]; + + buffer_in++; + switch(*buffer_in) { + case 'b': { + // byte + string_hex_8bit_to_alpha(str, va_arg(args, int)); + break; + } + case 'w': { + // word + string_hex_16bit_to_alpha(str, va_arg(args, int)); + break; + } + case 'd': { + // dword + string_hex_32bit_to_alpha(str, va_arg(args, uint32_t)); + break; + } + case 'q': { + // qword + string_hex_64bit_to_alpha(str, va_arg(args, uint64_t)); + break; + } + default: { + string_hex_64bit_to_alpha(str, va_arg(args, uint64_t)); + buffer_in--; + break; + } + } + uint64_t strlen = string_length(str); + + memory_copy((void*)str, buffer_out, strlen); + buffer_out += strlen; + break; + } + case '?': { + char str[7]; + string_bool_to_alpha(str, (bool)va_arg(args, int)); + uint64_t strlen = string_length(str); + + memory_copy((void*)str, buffer_out, strlen); + buffer_out += strlen; + break; + } + case 'b': { + if (numeric_specifier == 0) { + numeric_specifier = 64; + } + + char str[65]; + string_bin_to_alpha(str, numeric_specifier, va_arg(args, uint64_t)); + uint64_t strlen = string_length(str); + + memory_copy((void*)str, buffer_out, strlen); + buffer_out += strlen; + break; + } + } + } else { + *buffer_out = *buffer_in; + buffer_out++; + } + buffer_in++; + } + + *buffer_out = '\0'; +} + +void format(string_t output, string_t string, ...) { + va_list args; + va_start(args, string); + + variadic_format(output, string, args); + + va_end(args); +} + void string_unsigned_dec_to_alpha(string_t string, uint64_t value) { char* buffer = (char*)string; uint8_t length = 0;