diff options
author | Alex AUVOLAT <alexis211@gmail.com> | 2012-05-19 11:45:49 +0200 |
---|---|---|
committer | Alex AUVOLAT <alexis211@gmail.com> | 2012-05-19 11:45:49 +0200 |
commit | 499ca6c243b05da176a2d4bd9a2317f0b28afc7f (patch) | |
tree | f55ff788632b017ab8de83b71ad02b0998e1dda5 /src/user/lib/libc/std/stdio.c | |
parent | 7b466345af0d3a7dc5622617ce443a90c64e34a4 (diff) | |
download | TCE-499ca6c243b05da176a2d4bd9a2317f0b28afc7f.tar.gz TCE-499ca6c243b05da176a2d4bd9a2317f0b28afc7f.zip |
Introducing FWIK, the userland C++ framework. Far from complete.
Diffstat (limited to 'src/user/lib/libc/std/stdio.c')
-rw-r--r-- | src/user/lib/libc/std/stdio.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/src/user/lib/libc/std/stdio.c b/src/user/lib/libc/std/stdio.c new file mode 100644 index 0000000..3595622 --- /dev/null +++ b/src/user/lib/libc/std/stdio.c @@ -0,0 +1,119 @@ +#include <stdlib.h> +#include <stdio.h> +#include <tce/syscall.h> +#include <readline.h> + +FILE term = 0; +void print(char *s) { fprint(term, s); } +void printf(char *format, ...) { + va_list ap; + va_start(ap, format); + vfprintf(term, format, ap); + va_end(ap); +} +char* readln() { return freadln(term); } + +void fprintf(FILE f, char* format, ...) { + va_list ap; + va_start(ap, format); + vfprintf(f, format, ap); + va_end(ap); +} + +// INTERNAL, FOR FORMATTING + +static char* format_int(char* buf, int number) { + if (number == 0) { + *(buf++) = '0'; + return buf; + } + if (number < 0) { + *(buf++) = '-'; + number = 0 - number; + } + + int order = 0, temp = number, i; + char numbers[] = "0123456789"; + while (temp > 0) { + order++; + temp /= 10; + } + + for (i = order; i > 0; i--) { + buf[i - 1] = numbers[number % 10]; + number /= 10; + } + return buf + order; +} + +static char* format_hex(char *buf, unsigned v) { + *(buf++) = '0'; + *(buf++) = 'x'; + + int i; + char hexdigits[] = "0123456789ABCDEF"; + for (i = 0; i < 8; i++) { + *(buf++) = hexdigits[v >> 28]; + v = v << 4; + } + return buf; +} + + +// FUNCTIONS + +void fprint(FILE f, char *s) { + write(f, 0, strlen(s), s); +} + +void fprint_int(FILE f, int number) { + char s[32]; + char *v = format_int(s, number); + *v = 0; + fprint(f, s); +} + +void fprint_hex(FILE f, unsigned v) { + char s[11]; + char *e = format_hex(s, v); + *e = 0; + fprint(f, s); +} + +void vfprintf(FILE f, char *format, va_list ap) { + char bb[256]; + int bufl = 256; + + char *buf = bb; + char *end = buf; + + while (*format) { + if (*format == '%') { + // ASSUMPTION : (TODO) WE HAVE ENOUGH SPACE - NOT THE CASE!!! + format++; + if (*format == 'd' || *format == 'i') { + end = format_int(end, va_arg(ap, int)); + } else if (*format == 'p') { + end = format_hex(end, va_arg(ap, uint32_t)); + } else if (*format == 's') { + char *s = va_arg(ap, char*); + strcpy(end, s); + end += strlen(s); + } + format++; + } else { + *(end++) = *(format++); + } + if (end - buf > bufl - 2) { + bufl *= 2; + char *nbuf = (char*)malloc(bufl); + memcpy(nbuf, buf, end - buf); + end = nbuf + (end - buf); + if (buf != bb) free(buf); + buf = nbuf; + } + } + *end = 0; + fprint(f, buf); + if (buf != bb) free(buf); +} |