From e44ad9e6463db78c3f1df8f4dbff0cbf343ca49f Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Sat, 9 Jan 2010 21:23:16 +0100 Subject: Added printf(). --- kernel/printf.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 kernel/printf.c (limited to 'kernel/printf.c') 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; +} -- cgit v1.2.3