Additional printf formats
This commit is contained in:
parent
8ccf823c67
commit
d3991147c7
@ -7,7 +7,7 @@
|
|||||||
void kmain(void) {
|
void kmain(void) {
|
||||||
uart_init();
|
uart_init();
|
||||||
|
|
||||||
print("Hello world, %s!\n", ARCH);
|
print("Hello world, %x!\n", 0xff);
|
||||||
|
|
||||||
power_off();
|
power_off();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "../../uart.h"
|
#include "../../uart.h"
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
// QEMU emulates the NS16550A UART
|
// QEMU emulates the NS16550A UART
|
||||||
// The UART is memory mapped at 0x1000000
|
// The UART is memory mapped at 0x1000000
|
||||||
#define UART_ADDR 0x10000000
|
#define UART_ADDR 0x10000000
|
||||||
@ -36,9 +38,16 @@ void uart_puts(const char *line) {
|
|||||||
uart_putchar('\n');
|
uart_putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DIGIT_TO_STR(digit) ('0' + (digit))
|
||||||
|
#define DIGIT_TO_HEX(digit) ('0' + (digit) + ((digit < 10 ? 0 : 'a' - '0' - 10)))
|
||||||
|
|
||||||
// Basic implementation of printf supporting the following formats:
|
// Basic implementation of printf supporting the following formats:
|
||||||
// - c: Character
|
// - c: Character
|
||||||
// - s: String of characters
|
// - s: String of characters
|
||||||
|
// - d, i: Signed integer
|
||||||
|
// - u: Unsigned integer
|
||||||
|
// - x: Unsigned hexadecimal
|
||||||
|
// - p: Pointer address
|
||||||
// - %: Literal '%'
|
// - %: Literal '%'
|
||||||
void uart_vprintf(const char *restrict format, va_list args) {
|
void uart_vprintf(const char *restrict format, va_list args) {
|
||||||
while (*format) {
|
while (*format) {
|
||||||
@ -57,6 +66,79 @@ void uart_vprintf(const char *restrict format, va_list args) {
|
|||||||
case 's': // String
|
case 's': // String
|
||||||
uart_print(va_arg(args, char*));
|
uart_print(va_arg(args, char*));
|
||||||
break;
|
break;
|
||||||
|
case 'd':
|
||||||
|
case 'i': {
|
||||||
|
// TODO: This implementation breaks when the number starts with '0'. Check when debugging is possible?
|
||||||
|
int num = va_arg(args, int);
|
||||||
|
if (num == INT_MIN) {
|
||||||
|
uart_print("-2147483648");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num < 0) {
|
||||||
|
uart_putchar('-');
|
||||||
|
num = -num;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char lsh = DIGIT_TO_STR(num % 10);
|
||||||
|
num /= 10;
|
||||||
|
|
||||||
|
// Convert the number into a buffer of characters
|
||||||
|
// The buffer will be reversed (the last digit will be first)
|
||||||
|
char buf[9]; // There can't be more than 10 digits in an integer, -1 because of lsh
|
||||||
|
char *buf_ptr = buf;
|
||||||
|
while (num > 0) {
|
||||||
|
*buf_ptr++ = DIGIT_TO_STR(num % 10);
|
||||||
|
num /= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the characters in correct order
|
||||||
|
while (buf_ptr != buf) {
|
||||||
|
uart_putchar(*--buf_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
uart_putchar(lsh);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'u': {
|
||||||
|
// Similar as the signed variant, without support for negatives
|
||||||
|
unsigned int num = va_arg(args, unsigned int);
|
||||||
|
const char lsh = DIGIT_TO_STR(num % 10);
|
||||||
|
num /= 10;
|
||||||
|
|
||||||
|
char buf[9];
|
||||||
|
char *buf_ptr = buf;
|
||||||
|
while (num > 0) {
|
||||||
|
*buf_ptr++ = DIGIT_TO_STR(num % 10);
|
||||||
|
num /= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (buf_ptr != buf) {
|
||||||
|
uart_putchar(*--buf_ptr);
|
||||||
|
}
|
||||||
|
uart_putchar(lsh);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
uart_print("0x");
|
||||||
|
case 'x': {
|
||||||
|
unsigned int num = va_arg(args, unsigned int);
|
||||||
|
const char lsh = DIGIT_TO_HEX(num % 16);
|
||||||
|
num /= 16;
|
||||||
|
|
||||||
|
char buf[7];
|
||||||
|
char *buf_ptr = buf;
|
||||||
|
while (num > 0) {
|
||||||
|
*buf_ptr++ = DIGIT_TO_HEX(num % 16);
|
||||||
|
num /= 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (buf_ptr != buf) {
|
||||||
|
uart_putchar(*--buf_ptr);
|
||||||
|
}
|
||||||
|
uart_putchar(lsh);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case '%': // Literal '%'
|
case '%': // Literal '%'
|
||||||
uart_putchar('%');
|
uart_putchar('%');
|
||||||
break;
|
break;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user