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