diff options
Diffstat (limited to 'printf.c')
-rw-r--r-- | printf.c | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/printf.c b/printf.c new file mode 100644 index 0000000..0d42236 --- /dev/null +++ b/printf.c @@ -0,0 +1,76 @@ +#include "user.h" +#include "types.h" + +static void +putc(int fd, char c) +{ + write (fd, &c, 1); +} + +static void +printint(int fd, int xx, int base, int sgn) +{ + char buf[16]; + char digits[] = "0123456789ABCDEF"; + int i = 0, neg = 0; + uint x; + + if(sgn && xx < 0){ + neg = 1; + x = 0 - xx; + } else { + x = xx; + } + + do { + buf[i++] = digits[x % base]; + } while((x /= base) != 0); + if(neg) + buf[i++] = '-'; + + while(--i >= 0) + putc(fd, buf[i]); +} + +/* + * printf to the stdout. only understands %d, %x, %p, %s. + */ +void +printf(int fd, char *fmt, ...) +{ + int i, state = 0, c; + uint *ap = (uint *)(void*)&fmt + 1; + + for(i = 0; fmt[i]; i++){ + c = fmt[i] & 0xff; + if(state == 0){ + if(c == '%'){ + state = '%'; + } else { + putc(fd, c); + } + } else if(state == '%'){ + if(c == 'd'){ + printint(fd, *ap, 10, 1); + ap++; + } else if(c == 'x' || c == 'p'){ + printint(fd, *ap, 16, 0); + ap++; + } else if(c == 's'){ + char *s = (char*)*ap; + ap++; + while(*s != 0){ + putc(fd, *s); + s++; + } + } else if(c == '%'){ + putc(fd, c); + } else { + // Unknown % sequence. Print it to draw attention. + putc(fd, '%'); + putc(fd, c); + } + state = 0; + } + } +} |