diff options
Diffstat (limited to 'src/tools/lcc/src/output.c')
-rw-r--r-- | src/tools/lcc/src/output.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/tools/lcc/src/output.c b/src/tools/lcc/src/output.c new file mode 100644 index 00000000..a9c93e79 --- /dev/null +++ b/src/tools/lcc/src/output.c @@ -0,0 +1,135 @@ +#include "c.h" + + +static char *outs(const char *str, FILE *f, char *bp) { + if (f) + fputs(str, f); + else + while ((*bp = *str++)) + bp++; + return bp; +} + +static char *outd(long n, FILE *f, char *bp) { + unsigned long m; + char buf[25], *s = buf + sizeof buf; + + *--s = '\0'; + if (n < 0) + m = -n; + else + m = n; + do + *--s = m%10 + '0'; + while ((m /= 10) != 0); + if (n < 0) + *--s = '-'; + return outs(s, f, bp); +} + +static char *outu(unsigned long n, int base, FILE *f, char *bp) { + char buf[25], *s = buf + sizeof buf; + + *--s = '\0'; + do + *--s = "0123456789abcdef"[n%base]; + while ((n /= base) != 0); + return outs(s, f, bp); +} +void print(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + vfprint(stdout, NULL, fmt, ap); + va_end(ap); +} +/* fprint - formatted output to f */ +void fprint(FILE *f, const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + vfprint(f, NULL, fmt, ap); + va_end(ap); +} + +/* stringf - formatted output to a saved string */ +char *stringf(const char *fmt, ...) { + char buf[1024]; + va_list ap; + + va_start(ap, fmt); + vfprint(NULL, buf, fmt, ap); + va_end(ap); + return string(buf); +} + +/* vfprint - formatted output to f or string bp */ +void vfprint(FILE *f, char *bp, const char *fmt, va_list ap) { + for (; *fmt; fmt++) + if (*fmt == '%') + switch (*++fmt) { + case 'd': bp = outd(va_arg(ap, int), f, bp); break; + case 'D': bp = outd(va_arg(ap, long), f, bp); break; + case 'U': bp = outu(va_arg(ap, unsigned long), 10, f, bp); break; + case 'u': bp = outu(va_arg(ap, unsigned), 10, f, bp); break; + case 'o': bp = outu(va_arg(ap, unsigned), 8, f, bp); break; + case 'X': bp = outu(va_arg(ap, unsigned long), 16, f, bp); break; + case 'x': bp = outu(va_arg(ap, unsigned), 16, f, bp); break; + case 'f': case 'e': + case 'g': { + static char format[] = "%f"; + char buf[128]; + format[1] = *fmt; + sprintf(buf, format, va_arg(ap, double)); + bp = outs(buf, f, bp); + } +; break; + case 's': bp = outs(va_arg(ap, char *), f, bp); break; + case 'p': { + void *p = va_arg(ap, void *); + if (p) + bp = outs("0x", f, bp); + bp = outu((unsigned long)p, 16, f, bp); + break; + } + case 'c': if (f) fputc(va_arg(ap, int), f); else *bp++ = va_arg(ap, int); break; + case 'S': { char *s = va_arg(ap, char *); + int n = va_arg(ap, int); + if (s) { + for ( ; n-- > 0; s++) + if (f) (void)putc(*s, f); else *bp++ = *s; + } + } break; + case 'k': { int t = va_arg(ap, int); + static char *tokens[] = { +#define xx(a,b,c,d,e,f,g) g, +#define yy(a,b,c,d,e,f,g) g, +#include "token.h" + }; + assert(tokens[t&0177]); + bp = outs(tokens[t&0177], f, bp); + } break; + case 't': { Type ty = va_arg(ap, Type); + assert(f); + outtype(ty ? ty : voidtype, f); + } break; + case 'w': { Coordinate *p = va_arg(ap, Coordinate *); + if (p->file && *p->file) { + bp = outs(p->file, f, bp); + bp = outs(":", f, bp); + } + bp = outd(p->y, f, bp); + } break; + case 'I': { int n = va_arg(ap, int); + while (--n >= 0) + if (f) (void)putc(' ', f); else *bp++ = ' '; + } break; + default: if (f) (void)putc(*fmt, f); else *bp++ = *fmt; break; + } + else if (f) + (void)putc(*fmt, f); + else + *bp++ = *fmt; + if (!f) + *bp = '\0'; +} |