hos/kernel/lang/kio.cc
josh 5b9651299e fixed a few formatting and string bugs, kprintf() working when called during bootstrapping!
git-svn-id: svn://anubis/hos/trunk@47 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-13 21:54:27 +00:00

248 lines
5.5 KiB
C++

#include "hos_types.h"
#include "hos_defines.h"
#include "kio.h"
#include "string.h"
#include <limits.h>
#include <stdarg.h> /* va_*() */
static void fmt_d2a(char * buf, int val);
static void fmt_u2a(char * buf, unsigned int val);
static void fmt_ll2a(char * buf, long long val);
static void fmt_ull2a(char * buf, unsigned long long val);
static void fmt_x2a(char * buf, unsigned int val);
static void fmt_o2a(char * buf, unsigned int val);
static int cursor_x, cursor_y;
extern "C" {
void kio_bootstrap()
{
cursor_x = 0;
cursor_y = 9;
}
void kprintf(char * fmt, ...)
{
va_list args;
va_start(args, fmt);
kvprintf(fmt, args);
va_end(args);
}
void kvprintf(char * fmt, va_list args)
{
char tmpbuf[25];
for ( ; *fmt; fmt++)
{
if (*fmt == '%')
{
fmt++;
if (*fmt)
{
switch (*fmt)
{
case 'c':
kputc(va_arg(args, int));
break;
case 'd':
fmt_d2a(tmpbuf, va_arg(args, int));
kputs(tmpbuf);
break;
case 'l':
fmt_ll2a(tmpbuf, va_arg(args, long long));
kputs(tmpbuf);
break;
case 'L':
fmt_ull2a(tmpbuf, va_arg(args, unsigned long long));
kputs(tmpbuf);
break;
case 'o':
fmt_o2a(tmpbuf, va_arg(args, unsigned int));
kputs(tmpbuf);
break;
case 's':
kputs(va_arg(args, char *));
break;
case 'u':
fmt_u2a(tmpbuf, va_arg(args, unsigned int));
kputs(tmpbuf);
break;
case 'x':
fmt_x2a(tmpbuf, va_arg(args, unsigned int));
kputs(tmpbuf);
break;
case '%':
kputc('%');
break;
}
}
}
else
{
kputc(*fmt);
}
}
}
void kputc(char c)
{
u16_t * console_memory = (u16_t *) (CONSOLE_MEMORY + KERNEL_OFFSET);
console_memory += 80 * cursor_y + cursor_x;
switch (c)
{
case '\t':
{
int to_advance = 8 - (cursor_x & 0x3);
while (to_advance--)
{
*console_memory++ = 0x0720;
}
}
break;
case '\n':
cursor_x = 0;
cursor_y++;
break;
default:
*console_memory = 0x0700 | (c & 0xFF);
cursor_x++;
break;
}
if (cursor_x >= 80)
{
cursor_x = 0;
cursor_y++;
}
if (cursor_y >= 25)
{
memcpy((u8_t *) CONSOLE_MEMORY,
(u8_t *) (CONSOLE_MEMORY + 80 * 2),
2 * 80 * 24);
memsetw((u16_t *) (CONSOLE_MEMORY + 2 * 80 * 24), 0x0720, 80);
}
}
void kputs(char * s)
{
while (*s)
{
kputc(*s);
s++;
}
}
} /* extern "C" */
static void fmt_d2a(char * buf, int val)
{
if (val == INT_MIN)
{
strcpy(buf, "-2147483648");
}
else
{
if (val < 0)
{
*buf++ = '-';
val = -val;
}
fmt_u2a(buf, (unsigned int) val);
}
}
static void fmt_u2a(char * buf, unsigned int val)
{
bool printing = false;
for (unsigned int div = 1000000000; div >= 1; div /= 10)
{
unsigned int n = val / div;
if (n)
{
printing = true;
}
if (printing)
{
*buf++ = '0' + n;
}
val -= n * div;
}
*buf = '\0';
}
static void fmt_ll2a(char * buf, long long val)
{
if (val == LONG_LONG_MIN)
{
strcpy(buf, "-9223372036854775808");
}
else
{
if (val < 0)
{
*buf++ = '-';
val = -val;
}
fmt_ull2a(buf, (unsigned long long) val);
}
}
static void fmt_ull2a(char * buf, unsigned long long val)
{
bool printing = false;
for (unsigned long long div = 10000000000000000000ull; div >= 1; div /= 10)
{
unsigned long long n = val / div;
if (n)
{
printing = true;
}
if (printing)
{
*buf++ = '0' + n;
}
val -= n * div;
}
*buf = '\0';
}
static void fmt_x2a(char * buf, unsigned int val)
{
bool printing = false;
for (int s = 28; s >= 0; s -= 4)
{
unsigned int n = (val >> s) & 0xF;
if (n)
{
printing = true;
}
if (printing)
{
*buf++ = "0123456789abcdef"[n];
}
}
*buf = '\0';
}
static void fmt_o2a(char * buf, unsigned int val)
{
bool printing = false;
for (int s = 30; s >= 0; s -= 3)
{
unsigned int n = (val >> s) & 0x7;
if (n)
{
printing = true;
}
if (printing)
{
*buf++ = "01234567"[n];
}
}
*buf = '\0';
}