libc: fix printf to actually print correct more-than-one-digit numbers (hint: the bugfix was a very stupid one)

This commit is contained in:
apio 2022-10-03 20:30:12 +02:00
parent cb60e418b2
commit 885e39f60f

View File

@ -25,7 +25,6 @@ static void __strrev(char* arr, int size)
template <typename IntegerType> static char* __unsignedtoa(IntegerType number, char* arr, int base) template <typename IntegerType> static char* __unsignedtoa(IntegerType number, char* arr, int base)
{ {
int i = 0; int i = 0;
IntegerType r = 0;
if (number == 0) if (number == 0)
{ {
@ -36,29 +35,60 @@ template <typename IntegerType> static char* __unsignedtoa(IntegerType number, c
while (number != 0) while (number != 0)
{ {
r = number % base; IntegerType r = number % (IntegerType)base;
arr[i] = (r > 9) ? (r - 10) + 'a' : r + '0'; arr[i] = (r > 9) ? (r - 10) + 'a' : r + '0';
i++; i++;
number /= base; number /= base;
} }
__strrev(arr, i - 1); __strrev(arr, i);
arr[i] = '\0'; arr[i] = '\0';
return arr; return arr;
} }
template <typename IntegerType, typename UnsignedIntegerType> template <typename IntegerType> static char* __signedtoa(IntegerType number, char* arr, int base)
static char* __signedtoa(IntegerType number, char* arr, int base)
{ {
int i = 0, negative = 0;
if (number == 0)
{
arr[i] = '0';
arr[i + 1] = '\0';
return arr;
}
if (number < 0 && base == 10) if (number < 0 && base == 10)
{ {
return __unsignedtoa<UnsignedIntegerType>((UnsignedIntegerType)(-number), arr, base); number *= -1;
negative = 1;
} }
return __unsignedtoa<UnsignedIntegerType>((UnsignedIntegerType)number, arr, base);
while (number != 0)
{
IntegerType r = number % base;
arr[i] = (r > 9) ? (r - 10) + 'a' : r + '0';
i++;
number /= base;
}
if (negative)
{
arr[i] = '-';
i++;
}
__strrev(arr, i);
arr[i] = '\0';
return arr;
} }
#pragma GCC push_options
#pragma GCC optimize("O0")
template <typename PutString> template <typename PutString>
static int internal_printf(const char* format, PutString put_string_callback, ssize_t max, va_list ap) static int internal_printf(const char* format, PutString put_string_callback, ssize_t max, va_list ap)
{ {
@ -150,7 +180,7 @@ static int internal_printf(const char* format, PutString put_string_callback, ss
else if (is_long) else if (is_long)
{ {
char result[25]; char result[25];
__signedtoa<long, unsigned long>(va_arg(ap, int64_t), result, 10); __signedtoa<long>(va_arg(ap, int64_t), result, 10);
if (buffer_insert_index + strlen(result) > 1024) flush_buffer(); if (buffer_insert_index + strlen(result) > 1024) flush_buffer();
memcpy(buffer + buffer_insert_index, result, strlen(result)); memcpy(buffer + buffer_insert_index, result, strlen(result));
buffer_insert_index += strlen(result); buffer_insert_index += strlen(result);
@ -160,7 +190,7 @@ static int internal_printf(const char* format, PutString put_string_callback, ss
else else
{ {
char result[25]; char result[25];
__signedtoa<int, unsigned int>(va_arg(ap, int32_t), result, 10); __signedtoa<int>(va_arg(ap, int32_t), result, 10);
if (buffer_insert_index + strlen(result) > 1024) flush_buffer(); if (buffer_insert_index + strlen(result) > 1024) flush_buffer();
memcpy(buffer + buffer_insert_index, result, strlen(result)); memcpy(buffer + buffer_insert_index, result, strlen(result));
buffer_insert_index += strlen(result); buffer_insert_index += strlen(result);
@ -245,6 +275,8 @@ static int internal_printf(const char* format, PutString put_string_callback, ss
return written; return written;
} }
#pragma GCC pop_options
extern "C" extern "C"
{ {
int vprintf(const char* format, va_list ap) int vprintf(const char* format, va_list ap)