summaryrefslogtreecommitdiff
path: root/printf.c
diff options
context:
space:
mode:
Diffstat (limited to 'printf.c')
-rw-r--r--printf.c76
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;
+ }
+ }
+}