2
* Copyright (c) 2003, 2006 Matteo Frigo
3
* Copyright (c) 2003, 2006 Massachusetts Institute of Technology
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
/* $Id: scan.c,v 1.19 2006-01-10 13:24:41 athena Exp $ */
32
/* Screw ctype. On linux, the is* functions call a routine that gets
33
the ctype map in the current locale. Because this operation is
34
expensive, the map is cached on a per-thread basis. I am not
35
willing to link this crap with FFTW. Not over my dead body.
37
Sic transit gloria mundi.
40
#define isspace(x) ((x) >= 0 && (x) <= ' ')
42
#define isdigit(x) ((x) >= '0' && (x) <= '9')
44
#define isupper(x) ((x) >= 'A' && (x) <= 'Z')
46
#define islower(x) ((x) >= 'a' && (x) <= 'z')
49
static int mygetc(scanner *sc)
51
if (sc->ungotc != EOF) {
56
return(sc->getchr(sc));
59
#define GETCHR(sc) mygetc(sc)
61
static void myungetc(scanner *sc, int c)
66
#define UNGETCHR(sc, c) myungetc(sc, c)
68
static void eat_blanks(scanner *sc)
71
while (ch = GETCHR(sc), isspace(ch))
76
static void mygets(scanner *sc, char *s, size_t maxlen)
82
while ((ch = GETCHR(sc)) != EOF && !isspace(ch)
83
&& ch != ')' && ch != '(' && s < s0 + maxlen)
89
static long getlong(scanner *sc, int base, int *ret)
91
int sign = 1, ch, count;
95
if (ch == '-' || ch == '+') {
96
sign = ch == '-' ? -1 : 1;
99
for (count = 0; ; ++count) {
102
else if (isupper(ch))
104
else if (islower(ch))
117
/* vscan is mostly scanf-like, with our additional format specifiers,
118
but with a few twists. It returns simply 0 or 1 indicating whether
119
the match was successful. '(' and ')' in the format string match
120
those characters preceded by any whitespace. Finally, if a
121
character match fails, it will ungetchr() the last character back
123
static int vscan(scanner *sc, const char *format, va_list ap)
125
const char *s = format;
135
switch ((c = *s++)) {
137
char *x = va_arg(ap, char *);
138
mygets(sc, x, fmt_len);
142
int *x = va_arg(ap, int *);
143
*x = (int) getlong(sc, 10, &ch);
148
int *x = va_arg(ap, int *);
149
*x = (int) getlong(sc, 16, &ch);
154
md5uint *x = va_arg(ap, md5uint *);
156
(0xffffffffUL & getlong(sc, 16, &ch));
161
if ((fmt_len = va_arg(ap, int)) <= 0) return 0;
165
A(0 /* unknown format */);
170
if (isspace(c) || c == '(' || c == ')')
172
if (!isspace(c) && (ch = GETCHR(sc)) != c) {
182
static int scan(scanner *sc, const char *format, ...)
186
va_start(ap, format);
187
ret = vscan(sc, format, ap);
192
scanner *X(mkscanner)(size_t size, int (*getchr)(scanner *sc))
194
scanner *s = (scanner *)MALLOC(size, OTHER);
202
void X(scanner_destroy)(scanner *sc)