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

View File

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

View File

@ -156,95 +156,133 @@ int putc(const char c)
return (unsigned 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; 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 i = 0;
int ret = 0; int c = 0;
if (integer < 0) { while (format[i] != '\0' && size) {
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') {
switch (format[i]) { switch (format[i]) {
case '%': case '%':
switch (format[i + 1]) { switch (format[i + 1]) {
case 'i': case 'i':
case 'd': { case 'd': {
int s;
int d = va_arg(ap, int); 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; break;
} }
case 'p': case 'p':
case 'x': { case 'x': {
char val[sizeof(int) * 2]; char val[sizeof(int) * 2];
unsigned int valIdx = 0;
int d = va_arg(ap, int); int d = va_arg(ap, int);
itoa(d, val, 16); 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; break;
} }
case 'c': { case 'c': {
int c = va_arg(ap, int); if (str) {
putc((char)c); int ch = va_arg(ap, int);
str[c++] = ch;
size--;
}
ret++; ret++;
break; break;
} }
case 's': { case 's': {
char *str = va_arg(ap, char *); char *stri = va_arg(ap, char *);
if (!str) if (!stri)
str = "[NULL STR]"; stri = "[NULL STR]";
ret += puts(str); if (str) {
while (*stri) {
if (size) {
str[c++] = *(stri++);
size--;
ret++;
} else {
return ret;
}
}
} else {
ret += strlen(stri);
}
break; break;
} }
case '%': case '%':
putc('%'); if (str) {
str[c++] = '%';
size--;
}
ret++; ret++;
break; break;
case 'l': case 'l':
@ -252,16 +290,37 @@ int vprintf(const char *format, va_list ap)
case 'l': case 'l':
switch (format[i + 3]) { switch (format[i + 3]) {
case 'd': { case 'd': {
int s;
long long int d = va_arg(ap, long long int); 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; break;
} }
case 'p': case 'p':
case 'x': { case 'x': {
char val[sizeof(long long int) * 2]; char val[sizeof(long long int) * 2];
unsigned int valIdx = 0;
long long int d = va_arg(ap, long long int); long long int d = va_arg(ap, long long int);
itoa(d, val, 16); 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; break;
} }
} }
@ -269,8 +328,16 @@ int vprintf(const char *format, va_list ap)
break; break;
case 'i': case 'i':
case 'd': { case 'd': {
int s;
long int d = va_arg(ap, long int); 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; break;
} }
} }
@ -281,10 +348,36 @@ int vprintf(const char *format, va_list ap)
break; break;
default: default:
putc(format[i]); if (str) {
str[c++] = format[i];
size--;
}
ret++; ret++;
} }
i++; 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; 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); char *strzcpy(char *dst, const char *src, int len);
int puts(const char *str); int puts(const char *str);
int putc(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 vprintf(const char *format, va_list ap);
int printf(const char *format, ...); int printf(const char *format, ...);

View File

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

View File

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

View File

@ -19,11 +19,9 @@
int VGASetup(uint bgColor, uint color); int VGASetup(uint bgColor, uint color);
void VGAputc(const char str); 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 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 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 vgaScrollUp(void);
void cursorEnable(uint8_t cursor_start, uint8_t cursor_end); void cursorEnable(uint8_t cursor_start, uint8_t cursor_end);
void cursorDisable(void); void cursorDisable(void);

View File

@ -312,6 +312,14 @@ void testKthread()
void run_test(void) 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(); testPaging();
printf("Testing Serial\n"); printf("Testing Serial\n");
serialPutc('h'); serialPutc('h');