diff --git a/kern/init.c b/kern/init.c index df46700..729fae9 100644 --- a/kern/init.c +++ b/kern/init.c @@ -38,6 +38,14 @@ i386_init(void) // Test the stack backtrace function (lab 1 only) test_backtrace(5); + // Test ANSI color escape codes + cprintf("\33[31m" "C" + "\33[33m" "o" + "\33[32m" "l" + "\33[36m" "o" + "\33[34m" "r" + "\33[0m" " Works!" "\n"); + // Drop into the kernel monitor. while (1) monitor(NULL); diff --git a/lib/printfmt.c b/lib/printfmt.c index b1de635..7535e93 100644 --- a/lib/printfmt.c +++ b/lib/printfmt.c @@ -79,6 +79,54 @@ getint(va_list *ap, int lflag) // Main function to format and print a string. void printfmt(void (*putch)(int, void*), void *putdat, const char *fmt, ...); +struct AttrState { + uint8_t cattrs; + uint8_t attrs; + enum { + NORMAL, + ESC, + BRACKET, + COLOR_FG, + COLOR + } state; +}; + +void +putchw(void (*putch)(int, void*), int c, void* data, struct AttrState* s) { + switch(s->state) { + case NORMAL: + if(c != 27) putch(c | (s->cattrs << 8), data); + else s->state = ESC; + return; + case ESC: + s->state = (c == '[') ? BRACKET : NORMAL; + return; + case BRACKET: + if(c == '3') { + s->state = COLOR_FG; + } else if(c == '0') { + s->state = COLOR; + s->attrs = 0; + } else { + s->state = NORMAL; + } + return; + case COLOR_FG: + if(c >= '0' && c <= '9') { + s->attrs = (s->attrs & ~(0x07)) | (c - '0'); + c |= ((c - '0') << 8); + s->state = COLOR; + } else { + s->state = NORMAL; + } + return; + case COLOR: + s->state = (c == ';') ? BRACKET : NORMAL; + if(c == 'm') s->cattrs = s->attrs; + return; + } +} + void vprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, va_list ap) { @@ -87,12 +135,17 @@ vprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, va_list ap) unsigned long long num; int base, lflag, width, precision, altflag; char padc; + struct AttrState attst; + + attst.state = NORMAL; + attst.cattrs = 0; + attst.attrs = 0; while (1) { while ((ch = *(unsigned char *) fmt++) != '%') { if (ch == '\0') return; - putch(ch, putdat); + putchw(putch, ch, putdat, &attst); } // Process a %-escape sequence