Implement vsnprintf and use it

This commit is contained in:
Mathieu Maret 2021-01-24 23:51:21 +01:00
parent b305653aac
commit bea3449b11
8 changed files with 203 additions and 121 deletions

View File

@ -11,9 +11,7 @@
ulong error_code) \
{ \
int intNbInt = int_nb; \
printStringDetails("EXCEPTION ", RED, BLACK, 0, VGA_HEIGHT - 1); \
printIntDetails(intNbInt, RED, BLACK, 11, VGA_HEIGHT - 1); \
printIntDetails(error_code, RED, BLACK, 14, VGA_HEIGHT - 1); \
VGAprintf(RED, BLACK, 0, VGA_HEIGHT - 1, "EXCEPTION %d %d", intNbInt, error_code); \
printf("Exception %d (Err %d) at 0x%x\n", int_nb, error_code, frame->eip); \
asm("hlt"); \
}
@ -64,8 +62,7 @@ __attribute__((interrupt)) void pagefault_handler(struct interrupt_frame *frame,
struct kthread *current = getCurrentThread();
printf("page fault while in thread %s\n", current->name);
printStringDetails("PAGE FAULT", RED, BLACK, 0, VGA_HEIGHT - 1);
printIntDetails(error_code, RED, BLACK, 11, VGA_HEIGHT - 1);
VGAprintf(RED, BLACK, 0, VGA_HEIGHT - 1, "PAGE FAULT %d", error_code);
(void)faulting_address;
(void)frame;
(void)error_code;

View File

@ -18,7 +18,7 @@ __attribute__((interrupt)) void timer_handler(struct interrupt_frame *frame)
{
static int timeCnt = 0;
EOIIrq(IRQ_TIMER);
printIntDetails(timeCnt++, RED, BLACK, 20, VGA_HEIGHT - 1);
VGAprintf(RED, BLACK, 20, VGA_HEIGHT - 1, "IRQ %d", timeCnt++);
(void)frame;
}

View File

@ -156,95 +156,133 @@ int putc(const char c)
return (unsigned char)c;
}
int printInt64(long long int integer)
// int max is 2^(sizeof(int)*8) which is (2^3)^(sizeof(int)*8/3)
// = 8^(sizeof(int)*8/3) ~ 10^(sizeof(int)*8/3)
#define PRINT_INT(name, type) \
int print##name(type integer, char *str, size_t size) \
{ \
char num[sizeof(integer) * 3]; \
int i = 0; \
int c = 0; \
int ret = 0; \
\
if (integer < 0) { \
if (str) { \
if (size) { \
str[c++] = '-'; \
size--; \
ret++; \
} else { \
return ret; \
} \
} else { \
ret++; \
} \
} \
\
do { \
int digit = integer % 10; \
num[i++] = (digit > 0) ? digit : -digit; \
integer = integer / 10; \
} while (integer != 0); \
\
for (i = i - 1; i >= 0; i--) { \
if (str) { \
if (size) { \
str[c++] = num[i] + '0'; \
size--; \
ret++; \
} else { \
return ret; \
} \
} else { \
ret++; \
} \
} \
return ret; \
}
PRINT_INT(Int, int);
PRINT_INT(Int64, long long int);
int vsnprintf(char *str, size_t size, const char *format, va_list ap)
{
char num[sizeof(integer) *
3]; // int max is 2^(sizeof(int)*8) which is (2^3)^(sizeof(int)*8/3)
// = 8^(sizeof(int)*8/3) ~ 10^(sizeof(int)*8/3)
int i = 0;
int ret = 0;
if (integer < 0) {
putc('-');
ret++;
}
do {
int digit = integer % 10;
num[i++] = (digit > 0) ? digit : -digit;
integer = integer / 10;
} while (integer != 0);
for (i = i - 1; i >= 0; i--) {
putc(num[i] + '0');
ret++;
}
return ret;
}
int printInt(int integer)
{
char num[sizeof(integer) *
3]; // int max is 2^(sizeof(int)*8) which is (2^3)^(sizeof(int)*8/3)
// = 8^(sizeof(int)*8/3) ~ 10^(sizeof(int)*8/3)
int i = 0;
int ret = 0;
int c = 0;
if (integer < 0) {
putc('-');
ret++;
}
do {
int digit = integer % 10;
num[i++] = (digit > 0) ? digit : -digit;
integer = integer / 10;
} while (integer != 0);
for (i = i - 1; i >= 0; i--) {
putc(num[i] + '0');
ret++;
}
return ret;
}
int vprintf(const char *format, va_list ap)
{
int i = 0;
int ret = 0;
while (format[i] != '\0') {
while (format[i] != '\0' && size) {
switch (format[i]) {
case '%':
switch (format[i + 1]) {
case 'i':
case 'd': {
int s;
int d = va_arg(ap, int);
ret += printInt(d);
if (str)
s = printInt(d, &str[c], size);
else
s = printInt(d, NULL, size);
size -= s;
c += s;
ret += s;
break;
}
case 'p':
case 'x': {
char val[sizeof(int) * 2];
int d = va_arg(ap, int);
unsigned int valIdx = 0;
int d = va_arg(ap, int);
itoa(d, val, 16);
ret += puts(val);
if (str) {
while (val[valIdx]) {
if (size) {
str[c++] = val[valIdx++];
size--;
ret++;
} else {
return ret;
}
}
} else {
ret += strlen(val);
}
break;
}
case 'c': {
int c = va_arg(ap, int);
putc((char)c);
if (str) {
int ch = va_arg(ap, int);
str[c++] = ch;
size--;
}
ret++;
break;
}
case 's': {
char *str = va_arg(ap, char *);
if (!str)
str = "[NULL STR]";
ret += puts(str);
char *stri = va_arg(ap, char *);
if (!stri)
stri = "[NULL STR]";
if (str) {
while (*stri) {
if (size) {
str[c++] = *(stri++);
size--;
ret++;
} else {
return ret;
}
}
} else {
ret += strlen(stri);
}
break;
}
case '%':
putc('%');
if (str) {
str[c++] = '%';
size--;
}
ret++;
break;
case 'l':
@ -252,16 +290,37 @@ int vprintf(const char *format, va_list ap)
case 'l':
switch (format[i + 3]) {
case 'd': {
int s;
long long int d = va_arg(ap, long long int);
ret += printInt64(d);
if (str)
s = printInt64(d, &str[c], size);
else
s = printInt64(d, NULL, size);
size -= s;
c += s;
ret += s;
break;
}
case 'p':
case 'x': {
char val[sizeof(long long int) * 2];
long long int d = va_arg(ap, long long int);
unsigned int valIdx = 0;
long long int d = va_arg(ap, long long int);
itoa(d, val, 16);
ret += puts(val);
if (str) {
while (val[valIdx]) {
if (size) {
str[c++] = val[valIdx++];
size--;
ret++;
} else {
return ret;
}
}
} else {
ret += strlen(val);
}
break;
}
}
@ -269,8 +328,16 @@ int vprintf(const char *format, va_list ap)
break;
case 'i':
case 'd': {
int s;
long int d = va_arg(ap, long int);
ret += printInt64(d);
if (str)
s = printInt64(d, &str[c], size);
else
s = printInt64(d, NULL, size);
size -= s;
c += s;
ret += s;
break;
}
}
@ -281,10 +348,36 @@ int vprintf(const char *format, va_list ap)
break;
default:
putc(format[i]);
if (str) {
str[c++] = format[i];
size--;
}
ret++;
}
i++;
}
if (str) {
if (size) {
str[c++] = '\0';
size--;
} else {
if (c > 0) {
str[c - 1] = '\0';
}
}
}
return ret;
}
int vprintf(const char *fmt, va_list ap)
{
char tmp[256];
int idx = 0;
int ret = vsnprintf(tmp, sizeof(tmp), fmt, ap);
while (ret > 0 && tmp[idx]) {
putc(tmp[idx++]);
}
return ret;
}

View File

@ -21,6 +21,7 @@ int strcmp(const char s1[], const char s2[]);
char *strzcpy(char *dst, const char *src, int len);
int puts(const char *str);
int putc(const char str);
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
int vprintf(const char *format, va_list ap);
int printf(const char *format, ...);

View File

@ -27,7 +27,7 @@ void idleThread(void *arg)
{
(void)arg;
while (1) {
printIntDetails((jiffies / HZ), GREEN, BLACK, 0, VGA_HEIGHT - 1);
VGAprintf(GREEN, BLACK, 0, VGA_HEIGHT - 1, "%d", (jiffies / HZ));
kthreadYield();
}
}

View File

@ -1,26 +1,28 @@
#include "vga.h"
#include "io.h"
#include "klibc.h"
#include "irq.h"
#include "klibc.h"
static uint vgaBgColor;
static uint vgaColor;
static int line, col;
static volatile short *vga = (short *)VGA_ADDR;
static void clearScreen(uint bgColor);
int VGASetup(uint bgColor, uint color)
{
vgaBgColor = bgColor;
vgaColor = color;
line = 0;
col = 0;
clearScreen(bgColor);
line = 0;
col = 0;
return 0;
}
void clearScreen(uint bgColor)
static void clearScreen(uint bgColor)
{
uint32_t flags;
volatile short *vga = (short *)VGA_ADDR;
long int colorAttr = bgColor << 12;
disable_IRQs(flags);
@ -33,9 +35,11 @@ void clearScreen(uint bgColor)
void clearScreenLine(uint bgColor, uint line)
{
uint32_t flags;
volatile short *vga = (short *)VGA_ADDR;
long int colorAttr = bgColor << 12;
if (line >= VGA_HEIGHT)
return;
disable_IRQs(flags);
for (uint i = VGA_WIDTH * line; i < VGA_WIDTH * (line + 1); i++) {
vga[i] = colorAttr;
@ -43,31 +47,29 @@ void clearScreenLine(uint bgColor, uint line)
restore_IRQs(flags);
}
void printIntDetails(int integer, uint color, uint bgColor, int startX, int startY)
void VGAprintf(uint color, uint bgColor, int startX, int startY, const char *format, ...)
{
char num[sizeof(int) * 3]; // int max is 2^(sizeof(int)*8) which is (2^3)^(sizeof(int)*8/3)
// = 8^(sizeof(int)*8/3) ~ 10^(sizeof(int)*8/3)
int x = startX;
int i = 0, k = 0;
if (integer < 0) {
printCharDetails('-', color, bgColor, x++, startY);
}
if (integer == 0) {
num[i++] = 0;
}
while (integer != 0) {
int digit = integer % 10;
num[i++] = (digit > 0) ? digit : -digit;
integer = integer / 10;
}
for (k = i - 1; k >= 0; k--) {
printCharDetails(num[k] + '0', color, bgColor, x++, startY);
int flags;
char tmp[VGA_WIDTH];
int idx = 0;
disable_IRQs(flags);
va_list ap;
va_start(ap, format);
int ret = vsnprintf(tmp, sizeof(tmp), format, ap);
while (ret > 0 && tmp[idx]) {
printCharDetails(tmp[idx++], color, bgColor, startX++, startY);
}
va_end(ap);
restore_IRQs(flags);
}
void printCharDetails(const char str, uint color, uint bgColor, int startX, int startY)
{
volatile short *vga = (short *)VGA_ADDR;
long int colorAttr = (bgColor << 4 | (color & 0x0f)) << 8;
vga[VGA_WIDTH * startY + startX] = colorAttr | str;
}
@ -75,7 +77,6 @@ void printCharDetails(const char str, uint color, uint bgColor, int startX, int
void vgaScrollUp(void)
{
long int colorAttr = vgaBgColor << 12;
volatile short *vga = (short *)VGA_ADDR;
int flags;
disable_IRQs(flags);
@ -121,26 +122,11 @@ void VGAputc(const char str)
line--;
}
}
cursorMove(col, line);
restore_IRQs(flags);
}
void printStringDetails(const char *str, uint color, uint bgColor, int startX, int startY)
{
uint32_t flags;
volatile short *vga = (short *)VGA_ADDR;
int i = 0;
long int colorAttr = (bgColor << 4 | (color & 0x0f)) << 8;
disable_IRQs(flags);
while (*str) {
vga[VGA_WIDTH * startY + startX + i] = colorAttr | *str;
str++;
i++;
}
restore_IRQs(flags);
}
void cursorEnable(uint8_t cursor_start, uint8_t cursor_end)
{
outb(0x3D4, 0x0A);
@ -158,7 +144,6 @@ void cursorDisable(void)
void cursorMove(int x, int y)
{
volatile short *vga = (short *)VGA_ADDR;
long int colorAttr = (vgaBgColor << 4 | (vgaColor & 0x0f)) << 8;
uint16_t pos = y * VGA_WIDTH + x;
vga[pos] = colorAttr;

View File

@ -19,11 +19,9 @@
int VGASetup(uint bgColor, uint color);
void VGAputc(const char str);
void clearScreen(uint bgColor);
void VGAprintf(uint color, uint bgColor, int startX, int startY, const char *format, ...);
void clearScreenLine(uint bgColor, uint line);
void printIntDetails(int integer, uint color, uint bgColor, int startX, int startY);
void printCharDetails(char str, uint color, uint bgColor, int startX, int startY);
void printStringDetails(const char *str, uint color, uint bgColor, int startX, int startY);
void vgaScrollUp(void);
void cursorEnable(uint8_t cursor_start, uint8_t cursor_end);
void cursorDisable(void);

View File

@ -312,6 +312,14 @@ void testKthread()
void run_test(void)
{
int test = 1000;
long long int test64 = 0x100000000;
assert(printf("hello") == 5);
assert(printf("hello\n") == 6);
assert(printf("hello %d\n", test) == 11);
assert(printf("hello %llx\n", test64) == 16);
assert(printf("hello %c\n", 'a') == 8);
assert(printf("hello %s\n", "world") == 12);
testPaging();
printf("Testing Serial\n");
serialPutc('h');