diff options
Diffstat (limited to 'src/fftw3/kernel/scan.c')
-rw-r--r-- | src/fftw3/kernel/scan.c | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/src/fftw3/kernel/scan.c b/src/fftw3/kernel/scan.c new file mode 100644 index 0000000..f5fa6e1 --- /dev/null +++ b/src/fftw3/kernel/scan.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2003 Matteo Frigo + * Copyright (c) 2003 Massachusetts Institute of Technology + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* $Id: scan.c,v 1.1 2008/10/17 06:11:29 scuri Exp $ */ + +#include "ifftw.h" +#include <string.h> +#include <stddef.h> +#include <stdarg.h> +#include <stdio.h> + +#ifdef USE_CTYPE +#include <ctype.h> +#else +/* Screw ctype. On linux, the is* functions call a routine that gets + the ctype map in the current locale. Because this operation is + expensive, the map is cached on a per-thread basis. I am not + willing to link this crap with FFTW. Not over my dead body. + + Sic transit gloria mundi. +*/ +#undef isspace +#define isspace(x) ((x) >= 0 && (x) <= ' ') +#undef isdigit +#define isdigit(x) ((x) >= '0' && (x) <= '9') +#undef isupper +#define isupper(x) ((x) >= 'A' && (x) <= 'Z') +#undef islower +#define islower(x) ((x) >= 'a' && (x) <= 'z') +#endif + +static int mygetc(scanner *sc) +{ + if (sc->ungotc != EOF) { + int c = sc->ungotc; + sc->ungotc = EOF; + return c; + } + return(sc->getchr(sc)); +} + +#define GETCHR(sc) mygetc(sc) + +static void myungetc(scanner *sc, int c) +{ + sc->ungotc = c; +} + +#define UNGETCHR(sc, c) myungetc(sc, c) + +static void eat_blanks(scanner *sc) +{ + int ch; + while (ch = GETCHR(sc), isspace(ch)) + ; + UNGETCHR(sc, ch); +} + +static void mygets(scanner *sc, char *s, size_t maxlen) +{ + char *s0 = s; + int ch; + + A(maxlen > 0); + while ((ch = GETCHR(sc)) != EOF && !isspace(ch) + && ch != ')' && ch != '(' && s < s0 + maxlen) + *s++ = ch; + *s = 0; + UNGETCHR(sc, ch); +} + +static long getlong(scanner *sc, int base, int *ret) +{ + int sign = 1, ch, count; + long x = 0; + + ch = GETCHR(sc); + if (ch == '-' || ch == '+') { + sign = ch == '-' ? -1 : 1; + ch = GETCHR(sc); + } + for (count = 0; ; ++count) { + if (isdigit(ch)) + ch -= '0'; + else if (isupper(ch)) + ch -= 'A' - 10; + else if (islower(ch)) + ch -= 'a' - 10; + else + break; + x = x * base + ch; + ch = GETCHR(sc); + } + x *= sign; + UNGETCHR(sc, ch); + *ret = count > 0; + return x; +} + +/* vscan is mostly scanf-like, with our additional format specifiers, + but with a few twists. It returns simply 0 or 1 indicating whether + the match was successful. '(' and ')' in the format string match + those characters preceded by any whitespace. Finally, if a + character match fails, it will ungetchr() the last character back + onto the stream. */ +static int vscan(scanner *sc, const char *format, va_list ap) +{ + const char *s = format; + char c; + int ch = 0; + size_t fmt_len; + + while ((c = *s++)) { + fmt_len = 0; + switch (c) { + case '%': + getformat: + switch ((c = *s++)) { + case 's': { + char *x = va_arg(ap, char *); + mygets(sc, x, fmt_len); + break; + } + case 'd': { + int *x = va_arg(ap, int *); + *x = (int) getlong(sc, 10, &ch); + if (!ch) return 0; + break; + } + case 'x': { + int *x = va_arg(ap, int *); + *x = (int) getlong(sc, 16, &ch); + if (!ch) return 0; + break; + } + case 'M': { + md5uint *x = va_arg(ap, md5uint *); + *x = 0xffffffffUL & getlong(sc, 16, &ch); + if (!ch) return 0; + break; + } + case '*': { + if ((fmt_len = va_arg(ap, int)) <= 0) return 0; + goto getformat; + } + default: + A(0 /* unknown format */); + break; + } + break; + default: + if (isspace(c) || c == '(' || c == ')') + eat_blanks(sc); + if (!isspace(c) && (ch = GETCHR(sc)) != c) { + UNGETCHR(sc, ch); + return 0; + } + break; + } + } + return 1; +} + +static int scan(scanner *sc, const char *format, ...) +{ + int ret; + va_list ap; + va_start(ap, format); + ret = vscan(sc, format, ap); + va_end(ap); + return ret; +} + +scanner *X(mkscanner)(size_t size, int (*getchr)(scanner *sc)) +{ + scanner *s = (scanner *)MALLOC(size, OTHER); + s->scan = scan; + s->vscan = vscan; + s->getchr = getchr; + s->ungotc = EOF; + return s; +} + +void X(scanner_destroy)(scanner *sc) +{ + X(ifree)(sc); +} |