Mercurial > hg > sv-dependency-builds
comparison src/fftw-3.3.5/kernel/scan.c @ 127:7867fa7e1b6b
Current fftw source
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Tue, 18 Oct 2016 13:40:26 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
126:4a7071416412 | 127:7867fa7e1b6b |
---|---|
1 /* | |
2 * Copyright (c) 2003, 2007-14 Matteo Frigo | |
3 * Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology | |
4 * | |
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. | |
9 * | |
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. | |
14 * | |
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
18 * | |
19 */ | |
20 | |
21 | |
22 #include "ifftw.h" | |
23 #include <string.h> | |
24 #include <stddef.h> | |
25 #include <stdarg.h> | |
26 #include <stdio.h> | |
27 | |
28 #ifdef USE_CTYPE | |
29 #include <ctype.h> | |
30 #else | |
31 /* Screw ctype. On linux, the is* functions call a routine that gets | |
32 the ctype map in the current locale. Because this operation is | |
33 expensive, the map is cached on a per-thread basis. I am not | |
34 willing to link this crap with FFTW. Not over my dead body. | |
35 | |
36 Sic transit gloria mundi. | |
37 */ | |
38 #undef isspace | |
39 #define isspace(x) ((x) >= 0 && (x) <= ' ') | |
40 #undef isdigit | |
41 #define isdigit(x) ((x) >= '0' && (x) <= '9') | |
42 #undef isupper | |
43 #define isupper(x) ((x) >= 'A' && (x) <= 'Z') | |
44 #undef islower | |
45 #define islower(x) ((x) >= 'a' && (x) <= 'z') | |
46 #endif | |
47 | |
48 static int mygetc(scanner *sc) | |
49 { | |
50 if (sc->ungotc != EOF) { | |
51 int c = sc->ungotc; | |
52 sc->ungotc = EOF; | |
53 return c; | |
54 } | |
55 return(sc->getchr(sc)); | |
56 } | |
57 | |
58 #define GETCHR(sc) mygetc(sc) | |
59 | |
60 static void myungetc(scanner *sc, int c) | |
61 { | |
62 sc->ungotc = c; | |
63 } | |
64 | |
65 #define UNGETCHR(sc, c) myungetc(sc, c) | |
66 | |
67 static void eat_blanks(scanner *sc) | |
68 { | |
69 int ch; | |
70 while (ch = GETCHR(sc), isspace(ch)) | |
71 ; | |
72 UNGETCHR(sc, ch); | |
73 } | |
74 | |
75 static void mygets(scanner *sc, char *s, int maxlen) | |
76 { | |
77 char *s0 = s; | |
78 int ch; | |
79 | |
80 A(maxlen > 0); | |
81 while ((ch = GETCHR(sc)) != EOF && !isspace(ch) | |
82 && ch != ')' && ch != '(' && s < s0 + maxlen) | |
83 *s++ = (char)(ch & 0xFF); | |
84 *s = 0; | |
85 UNGETCHR(sc, ch); | |
86 } | |
87 | |
88 static long getlong(scanner *sc, int base, int *ret) | |
89 { | |
90 int sign = 1, ch, count; | |
91 long x = 0; | |
92 | |
93 ch = GETCHR(sc); | |
94 if (ch == '-' || ch == '+') { | |
95 sign = ch == '-' ? -1 : 1; | |
96 ch = GETCHR(sc); | |
97 } | |
98 for (count = 0; ; ++count) { | |
99 if (isdigit(ch)) | |
100 ch -= '0'; | |
101 else if (isupper(ch)) | |
102 ch -= 'A' - 10; | |
103 else if (islower(ch)) | |
104 ch -= 'a' - 10; | |
105 else | |
106 break; | |
107 x = x * base + ch; | |
108 ch = GETCHR(sc); | |
109 } | |
110 x *= sign; | |
111 UNGETCHR(sc, ch); | |
112 *ret = count > 0; | |
113 return x; | |
114 } | |
115 | |
116 /* vscan is mostly scanf-like, with our additional format specifiers, | |
117 but with a few twists. It returns simply 0 or 1 indicating whether | |
118 the match was successful. '(' and ')' in the format string match | |
119 those characters preceded by any whitespace. Finally, if a | |
120 character match fails, it will ungetchr() the last character back | |
121 onto the stream. */ | |
122 static int vscan(scanner *sc, const char *format, va_list ap) | |
123 { | |
124 const char *s = format; | |
125 char c; | |
126 int ch = 0; | |
127 int fmt_len; | |
128 | |
129 while ((c = *s++)) { | |
130 fmt_len = 0; | |
131 switch (c) { | |
132 case '%': | |
133 getformat: | |
134 switch ((c = *s++)) { | |
135 case 's': { | |
136 char *x = va_arg(ap, char *); | |
137 mygets(sc, x, fmt_len); | |
138 break; | |
139 } | |
140 case 'd': { | |
141 int *x = va_arg(ap, int *); | |
142 *x = (int) getlong(sc, 10, &ch); | |
143 if (!ch) return 0; | |
144 break; | |
145 } | |
146 case 'x': { | |
147 int *x = va_arg(ap, int *); | |
148 *x = (int) getlong(sc, 16, &ch); | |
149 if (!ch) return 0; | |
150 break; | |
151 } | |
152 case 'M': { | |
153 md5uint *x = va_arg(ap, md5uint *); | |
154 *x = (md5uint) | |
155 (0xFFFFFFFF & getlong(sc, 16, &ch)); | |
156 if (!ch) return 0; | |
157 break; | |
158 } | |
159 case '*': { | |
160 if ((fmt_len = va_arg(ap, int)) <= 0) return 0; | |
161 goto getformat; | |
162 } | |
163 default: | |
164 A(0 /* unknown format */); | |
165 break; | |
166 } | |
167 break; | |
168 default: | |
169 if (isspace(c) || c == '(' || c == ')') | |
170 eat_blanks(sc); | |
171 if (!isspace(c) && (ch = GETCHR(sc)) != c) { | |
172 UNGETCHR(sc, ch); | |
173 return 0; | |
174 } | |
175 break; | |
176 } | |
177 } | |
178 return 1; | |
179 } | |
180 | |
181 static int scan(scanner *sc, const char *format, ...) | |
182 { | |
183 int ret; | |
184 va_list ap; | |
185 va_start(ap, format); | |
186 ret = vscan(sc, format, ap); | |
187 va_end(ap); | |
188 return ret; | |
189 } | |
190 | |
191 scanner *X(mkscanner)(size_t size, int (*getchr)(scanner *sc)) | |
192 { | |
193 scanner *s = (scanner *)MALLOC(size, OTHER); | |
194 s->scan = scan; | |
195 s->vscan = vscan; | |
196 s->getchr = getchr; | |
197 s->ungotc = EOF; | |
198 return s; | |
199 } | |
200 | |
201 void X(scanner_destroy)(scanner *sc) | |
202 { | |
203 X(ifree)(sc); | |
204 } |