Added %d support for printf

This commit is contained in:
lucic71 2022-06-28 19:40:51 +03:00
parent 9605fbc1e4
commit 7ab1592f75
2 changed files with 95 additions and 7 deletions

6
libc/include/digits.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef DIGITS_H_
#define DIGITS_H_
#define INT32_MAX_DIGITS 12
#endif

View File

@ -3,8 +3,9 @@
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <digits.h>
static bool print(const char* data, size_t length) {
static bool _print(const char* data, size_t length) {
const unsigned char* bytes = (const unsigned char*) data;
@ -16,6 +17,67 @@ static bool print(const char* data, size_t length) {
}
/*
* _int_to_string:
* ---------------
*
* Because there is no heap at the moment, a reference to a char array
* must be passed to store the result.
*
* The routine checks if the number is signed, and sets the first character
* of the result string to '-' if so. Else it produces a normal conversion.
*
* It has two special cases: when n is 0 and when n is INT_MIN.
*
* @param n - Number to be converted
* @param result - Pointer to a result char array
*
*/
static void _int_to_string(int n, char **result) {
if (!n) {
(*result)[0] = '0';
return;
}
if (n == INT_MIN) {
char int_min_str[] = "-2147483648";
memcpy(*result, int_min_str, strlen(int_min_str));
return;
}
int digits = 0;
int stop_at = 0;
if (n >> 31) {
n = ~n + 1;
for (int temp = n; temp != 0; temp /= 10, digits++);
(*result)[0] = '-';
digits++;
stop_at = 1;
} else
for(int temp = n; temp != 0; temp /= 10, digits++);
for (int i = digits - 1, temp = n; i >= stop_at; i--) {
(*result)[i] = (temp % 10) + '0';
temp /= 10;
}
}
int printf(const char* restrict format, ...) {
va_list parameters;
@ -42,7 +104,7 @@ int printf(const char* restrict format, ...) {
return -1;
}
if (!print(format, amount))
if (!_print(format, amount))
return -1;
format += amount;
@ -63,7 +125,7 @@ int printf(const char* restrict format, ...) {
return -1;
}
if (!print(&c, sizeof(c)))
if (!_print(&c, sizeof(c)))
return -1;
written++;
@ -79,12 +141,33 @@ int printf(const char* restrict format, ...) {
return -1;
}
if (!print(str, len))
if (!_print(str, len))
return -1;
written += len;
} else {
} else if (*format == 'd') {
format++;
int n = va_arg(parameters, int);
char str[INT32_MAX_DIGITS + 1] = {0};
char *str_ptr = str;
_int_to_string(n, &str_ptr);
size_t len = strlen(str);
if (maxrem < len) {
// TODO: Set errno to EOVERFLOW.
return -1;
}
if (!_print(str, len))
return -1;
written += len;
} else {
format = format_begun_at;
size_t len = strlen(format);
@ -94,7 +177,7 @@ int printf(const char* restrict format, ...) {
return -1;
}
if (!print(format, len))
if (!_print(format, len))
return -1;
written += len;
@ -106,5 +189,4 @@ int printf(const char* restrict format, ...) {
va_end(parameters);
return written;
}