Chris@82: /* Chris@82: * Copyright (c) 2003, 2007-14 Matteo Frigo Chris@82: * Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology Chris@82: * Chris@82: * This program is free software; you can redistribute it and/or modify Chris@82: * it under the terms of the GNU General Public License as published by Chris@82: * the Free Software Foundation; either version 2 of the License, or Chris@82: * (at your option) any later version. Chris@82: * Chris@82: * This program is distributed in the hope that it will be useful, Chris@82: * but WITHOUT ANY WARRANTY; without even the implied warranty of Chris@82: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Chris@82: * GNU General Public License for more details. Chris@82: * Chris@82: * You should have received a copy of the GNU General Public License Chris@82: * along with this program; if not, write to the Free Software Chris@82: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Chris@82: * Chris@82: */ Chris@82: Chris@82: Chris@82: #include "kernel/ifftw.h" Chris@82: #include Chris@82: #include Chris@82: #include Chris@82: Chris@82: #define BSZ 64 Chris@82: Chris@82: static void myputs(printer *p, const char *s) Chris@82: { Chris@82: char c; Chris@82: while ((c = *s++)) Chris@82: p->putchr(p, c); Chris@82: } Chris@82: Chris@82: static void newline(printer *p) Chris@82: { Chris@82: int i; Chris@82: Chris@82: p->putchr(p, '\n'); Chris@82: for (i = 0; i < p->indent; ++i) Chris@82: p->putchr(p, ' '); Chris@82: } Chris@82: Chris@82: static const char *digits = "0123456789abcdef"; Chris@82: Chris@82: static void putint(printer *p, INT i) Chris@82: { Chris@82: char buf[BSZ]; Chris@82: char *f = buf; Chris@82: Chris@82: if (i < 0) { Chris@82: p->putchr(p, '-'); Chris@82: i = -i; Chris@82: } Chris@82: Chris@82: do { Chris@82: *f++ = digits[i % 10]; Chris@82: i /= 10; Chris@82: } while (i); Chris@82: Chris@82: do { Chris@82: p->putchr(p, *--f); Chris@82: } while (f != buf); Chris@82: } Chris@82: Chris@82: static void putulong(printer *p, unsigned long i, unsigned base, int width) Chris@82: { Chris@82: char buf[BSZ]; Chris@82: char *f = buf; Chris@82: Chris@82: do { Chris@82: *f++ = digits[i % base]; Chris@82: i /= base; Chris@82: } while (i); Chris@82: Chris@82: while (width > f - buf) { Chris@82: p->putchr(p, '0'); Chris@82: --width; Chris@82: } Chris@82: Chris@82: do { Chris@82: p->putchr(p, *--f); Chris@82: } while (f != buf); Chris@82: } Chris@82: Chris@82: static void vprint(printer *p, const char *format, va_list ap) Chris@82: { Chris@82: const char *s = format; Chris@82: char c; Chris@82: INT ival; Chris@82: Chris@82: while ((c = *s++)) { Chris@82: switch (c) { Chris@82: case '%': Chris@82: switch ((c = *s++)) { Chris@82: case 'M': { Chris@82: /* md5 value */ Chris@82: md5uint x = va_arg(ap, md5uint); Chris@82: putulong(p, (unsigned long)(0xffffffffUL & x), Chris@82: 16u, 8); Chris@82: break; Chris@82: } Chris@82: case 'c': { Chris@82: int x = va_arg(ap, int); Chris@82: p->putchr(p, (char)x); Chris@82: break; Chris@82: } Chris@82: case 's': { Chris@82: char *x = va_arg(ap, char *); Chris@82: if (x) Chris@82: myputs(p, x); Chris@82: else Chris@82: goto putnull; Chris@82: break; Chris@82: } Chris@82: case 'd': { Chris@82: int x = va_arg(ap, int); Chris@82: ival = (INT)x; Chris@82: goto putival; Chris@82: } Chris@82: case 'D': { Chris@82: ival = va_arg(ap, INT); Chris@82: goto putival; Chris@82: } Chris@82: case 'v': { Chris@82: /* print optional vector length */ Chris@82: ival = va_arg(ap, INT); Chris@82: if (ival > 1) { Chris@82: myputs(p, "-x"); Chris@82: goto putival; Chris@82: } Chris@82: break; Chris@82: } Chris@82: case 'o': { Chris@82: /* integer option. Usage: %oNAME= */ Chris@82: ival = va_arg(ap, INT); Chris@82: if (ival) Chris@82: p->putchr(p, '/'); Chris@82: while ((c = *s++) != '=') Chris@82: if (ival) Chris@82: p->putchr(p, c); Chris@82: if (ival) { Chris@82: p->putchr(p, '='); Chris@82: goto putival; Chris@82: } Chris@82: break; Chris@82: } Chris@82: case 'u': { Chris@82: unsigned x = va_arg(ap, unsigned); Chris@82: putulong(p, (unsigned long)x, 10u, 0); Chris@82: break; Chris@82: } Chris@82: case 'x': { Chris@82: unsigned x = va_arg(ap, unsigned); Chris@82: putulong(p, (unsigned long)x, 16u, 0); Chris@82: break; Chris@82: } Chris@82: case '(': { Chris@82: /* newline, augment indent level */ Chris@82: p->indent += p->indent_incr; Chris@82: newline(p); Chris@82: break; Chris@82: } Chris@82: case ')': { Chris@82: /* decrement indent level */ Chris@82: p->indent -= p->indent_incr; Chris@82: break; Chris@82: } Chris@82: case 'p': { /* note difference from C's %p */ Chris@82: /* print plan */ Chris@82: plan *x = va_arg(ap, plan *); Chris@82: if (x) Chris@82: x->adt->print(x, p); Chris@82: else Chris@82: goto putnull; Chris@82: break; Chris@82: } Chris@82: case 'P': { Chris@82: /* print problem */ Chris@82: problem *x = va_arg(ap, problem *); Chris@82: if (x) Chris@82: x->adt->print(x, p); Chris@82: else Chris@82: goto putnull; Chris@82: break; Chris@82: } Chris@82: case 'T': { Chris@82: /* print tensor */ Chris@82: tensor *x = va_arg(ap, tensor *); Chris@82: if (x) Chris@82: X(tensor_print)(x, p); Chris@82: else Chris@82: goto putnull; Chris@82: break; Chris@82: } Chris@82: default: Chris@82: A(0 /* unknown format */); Chris@82: break; Chris@82: Chris@82: putnull: Chris@82: myputs(p, "(null)"); Chris@82: break; Chris@82: Chris@82: putival: Chris@82: putint(p, ival); Chris@82: break; Chris@82: } Chris@82: break; Chris@82: default: Chris@82: p->putchr(p, c); Chris@82: break; Chris@82: } Chris@82: } Chris@82: } Chris@82: Chris@82: static void print(printer *p, const char *format, ...) Chris@82: { Chris@82: va_list ap; Chris@82: va_start(ap, format); Chris@82: vprint(p, format, ap); Chris@82: va_end(ap); Chris@82: } Chris@82: Chris@82: printer *X(mkprinter)(size_t size, Chris@82: void (*putchr)(printer *p, char c), Chris@82: void (*cleanup)(printer *p)) Chris@82: { Chris@82: printer *s = (printer *)MALLOC(size, OTHER); Chris@82: s->print = print; Chris@82: s->vprint = vprint; Chris@82: s->putchr = putchr; Chris@82: s->cleanup = cleanup; Chris@82: s->indent = 0; Chris@82: s->indent_incr = 2; Chris@82: return s; Chris@82: } Chris@82: Chris@82: void X(printer_destroy)(printer *p) Chris@82: { Chris@82: if (p->cleanup) Chris@82: p->cleanup(p); Chris@82: X(ifree)(p); Chris@82: }