diff options
author | Vegard Storheil Eriksen <zyp@jvnv.net> | 2010-01-09 21:23:16 +0100 |
---|---|---|
committer | Vegard Storheil Eriksen <zyp@jvnv.net> | 2010-01-09 21:23:16 +0100 |
commit | e44ad9e6463db78c3f1df8f4dbff0cbf343ca49f (patch) | |
tree | 0159df1baf35897995995d68bba43020fc567125 | |
parent | 51a6ac67b761182d67eeb2f625d8476a2e79e632 (diff) |
Added printf().
-rw-r--r-- | kernel/SConscript | 2 | ||||
-rw-r--r-- | kernel/main.c | 23 | ||||
-rw-r--r-- | kernel/printf.c | 96 | ||||
-rw-r--r-- | kernel/printf.h | 6 | ||||
-rw-r--r-- | kernel/types.h | 2 |
5 files changed, 110 insertions, 19 deletions
diff --git a/kernel/SConscript b/kernel/SConscript index 856d2b5..8c17467 100644 --- a/kernel/SConscript +++ b/kernel/SConscript @@ -27,4 +27,4 @@ kernel_bld = Builder( env.Append(BUILDERS = {'Kernel' : kernel_bld}) -kernel = env.Kernel('kernel', ['kernel.ld', 'entry.c', 'main.c', 'gdt.c', 'idt.c']) +kernel = env.Kernel('kernel', ['kernel.ld', 'entry.c', 'main.c', 'printf.c', 'gdt.c', 'idt.c']) diff --git a/kernel/main.c b/kernel/main.c index cc0dc35..55476ce 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -1,19 +1,17 @@ +#include "printf.h" #include "gdt.h" #include "idt.h" -void kernel_serial_out(char* str); - void main() { - - kernel_serial_out("main()\n"); + printf("main()\n"); gdt_init(); - kernel_serial_out("GDT set.\n"); + printf("GDT set.\n"); idt_init(); - kernel_serial_out("IDT set.\n"); + printf("IDT set.\n"); - kernel_serial_out("Halting.\n"); + printf("Halting.\n"); asm volatile( "cli\n" @@ -21,14 +19,3 @@ void main() { ); while(1); } - -#define outb(port, value) asm volatile("out %b0,%w1" : : "a" (value), "d" (port)); - -void kernel_serial_out(char* str) { - while(*str) { - if(*str == '\n') { - outb(0x3f8, '\r'); - } - outb(0x3f8, *str++); - } -} diff --git a/kernel/printf.c b/kernel/printf.c new file mode 100644 index 0000000..4b3a632 --- /dev/null +++ b/kernel/printf.c @@ -0,0 +1,96 @@ +#include "printf.h" +#include "types.h" + +#define outb(port, value) asm volatile("out %b0,%w1" : : "a" (value), "d" (port)); + +void putchar(char c) { + if(c == '\n') { + outb(0x3f8, '\r'); + } + outb(0x3f8, c); +} + +int printf(const char* format, ...) { + int32_t* argp = (int32_t*)&format; + int num; + + while(*format) { + if(*format != '%') { + putchar(*format++); + num++; + continue; + } + format++; + + bool is_signed = false; + bool zero_pad = false; + int radix = 16; + int min_len = 0; + + if(*format == '0') { + zero_pad = true; + } + + while(*format >= '0' && *format <= '9') { + min_len = min_len * 10 + *format++ - '0'; + } + + switch(*format++) { + case '%': + putchar('%'); + num++; + break; + + case 'c': + putchar((char)*++argp); + num++; + break; + + case 's': + ; + char* str = (char*)*++argp; + while(*str) { + putchar(*str++); + num++; + } + break; + + case 'd': + is_signed = true; + case 'u': + radix = 10; + case 'x': + ; + uint32_t x = (uint32_t)*(++argp); + if(is_signed && (int32_t)x < 0) { + x = -x; + putchar('-'); + min_len--; + } + + char buf[11]; + char* bufp = &buf[sizeof(buf)]; + *--bufp = 0; + + do { + int d = x % radix; + *--bufp = d < 10 ? '0' + d : 'a' - 10 + d; + x /= radix; + min_len--; + } while(x); + + while(min_len > 0) { + putchar(zero_pad ? '0' : ' '); + num++; + min_len--; + } + + while(*bufp) { + putchar(*bufp++); + num++; + } + break; + } + } + return num; +} diff --git a/kernel/printf.h b/kernel/printf.h new file mode 100644 index 0000000..16d612c --- /dev/null +++ b/kernel/printf.h @@ -0,0 +1,6 @@ +#ifndef PRINTF_H +#define PRINTF_H + +int printf(const char* format, ...); + +#endif diff --git a/kernel/types.h b/kernel/types.h index 4fdca6b..a200526 100644 --- a/kernel/types.h +++ b/kernel/types.h @@ -8,4 +8,6 @@ typedef unsigned short uint16_t; typedef signed int int32_t; typedef unsigned int uint32_t; +typedef enum {false, true} bool; + #endif |