Implement vsnprintf and use it
This commit is contained in:
parent
b305653aac
commit
bea3449b11
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
219
core/klibc.c
219
core/klibc.c
@ -156,95 +156,133 @@ int putc(const char c)
|
||||
return (unsigned char)c;
|
||||
}
|
||||
|
||||
int printInt64(long long int integer)
|
||||
{
|
||||
char num[sizeof(integer) *
|
||||
3]; // int max is 2^(sizeof(int)*8) which is (2^3)^(sizeof(int)*8/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++;
|
||||
#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; \
|
||||
}
|
||||
|
||||
do {
|
||||
int digit = integer % 10;
|
||||
num[i++] = (digit > 0) ? digit : -digit;
|
||||
integer = integer / 10;
|
||||
} while (integer != 0);
|
||||
PRINT_INT(Int, int);
|
||||
PRINT_INT(Int64, long long int);
|
||||
|
||||
for (i = i - 1; i >= 0; i--) {
|
||||
putc(num[i] + '0');
|
||||
ret++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int printInt(int integer)
|
||||
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 vprintf(const char *format, va_list ap)
|
||||
{
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
while (format[i] != '\0') {
|
||||
int c = 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];
|
||||
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];
|
||||
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;
|
||||
}
|
||||
|
@ -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, ...);
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
clearScreen(bgColor);
|
||||
line = 0;
|
||||
col = 0;
|
||||
clearScreen(bgColor);
|
||||
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;
|
||||
|
@ -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);
|
||||
|
@ -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');
|
||||
|
Loading…
Reference in New Issue
Block a user