15 static int read(rctx_t *r)
17 if (--r->w < 0) return r->w = -1;
23 static void unread(rctx_t *r)
25 if (r->c < 0 || r->w < 0) return;
37 static void store_int(void *dest, int size, int neg, unsigned long long i)
55 *(long long *)dest = i;
60 static void *arg_n(va_list ap, unsigned int n)
66 for (i=n; i>1; i--) va_arg(ap2, void *);
67 p = va_arg(ap2, void *);
72 int __scanf(rctx_t *r, const wchar_t *fmt, va_list ap)
86 unsigned long long i=0;
90 int (*is_space)(int) = r->is_space;
94 do p++; while (is_space(*p));
95 do r->w=1; while (is_space(read(r)));
98 } else if (*p != '%' || p[1] == '%') {
101 if ((c = read(r)) < 0)
109 for (z=p; isdigit(*z); z++);
110 if (*z != '$' && *z != '*') {
111 if (mode == 0) mode = 1;
113 } else if (*z != '*') {
117 pos = 10*pos + *p - '0';
120 if (!pos) goto fmt_fail;
121 dest = arg_n(ap, pos);
127 } else if (mode == 1) {
128 dest = va_arg(ap, void *);
131 if (!*p) goto fmt_fail;
134 for (; isdigit(*p); p++) {
135 width = 10*width + *p - '0';
143 if (*p == 'h') p++, size = SIZE_hh;
147 if (*p == 'l') p++, size = SIZE_ll;
160 case 'd': case 'i': case 'o': case 'u': case 'x':
161 case 'a': case 'e': case 'f': case 'g':
162 case 'A': case 'E': case 'F': case 'G': case 'X':
163 case 's': case 'c': case '[':
177 if (width < 1) width = 1;
179 if (size == SIZE_l) t &= ~0x20;
180 case 'd': case 'i': case 'o': case 'u': case 'x':
181 case 'a': case 'e': case 'f': case 'g':
182 case 'A': case 'E': case 'F': case 'G': case 'X':
185 if (width < 1) width = INT_MAX;
194 if (read(r) < 0) goto input_fail;
200 store_int(dest, size, 0, r->l - r->u);
201 /* do not increment match count, etc! */
204 wcs = dest ? dest : (void *)&dummy;
205 st = (mbstate_t){ 0 };
206 while ((c=read(r)) >= 0) {
208 if (dest) *wcs++ = c;
211 switch (mbrtowc(wcs, &ch, 1, &st)) {
221 if (r->w > 0) goto match_fail;
224 s = dest ? dest : (void *)&dummy;
225 while ((c=read(r)) >= 0) {
227 if ((l=wctomb(s, c)) < 0)
234 if (r->w > 0) goto match_fail;
237 wcs = dest ? dest : (void *)&dummy;
238 s = dest ? dest : (void *)&dummy;
239 if (!wide && size == SIZE_l) st = (mbstate_t){ 0 };
241 if (*p == '^') p++, invert = 1;
245 for (m=0; (c=read(r)) >= 0; m=1) {
246 for (z=p; *z && *z != c && (*z != ']' || z==p); z++);
247 if (!*z) goto fmt_fail;
248 if (*z == c && (*z != ']' || z==p)) {
253 if (size == SIZE_l) {
254 if (dest) *wcs++ = c;
256 if ((l=wctomb(s, c)) < 0)
261 for (p++; *p && *p != ']'; p++);
264 unsigned char scanset[257];
265 memset(scanset, invert, sizeof scanset);
267 for (z=p; *z && (*z != ']' || z==p); z++)
268 scanset[1+*z] = 1-invert;
269 if (!*z) goto fmt_fail;
272 for (m=0; scanset[(c=read(r))+1]; m=1) {
273 if (size == SIZE_l) {
275 switch (mbrtowc(wcs, &ch, 1, &st)) {
288 if (!m) goto match_fail;
290 if (size == SIZE_l) *wcs++ = 0;
295 /* read unlimited number of spaces, then reset width */
296 do r->w = 1; while (is_space(c = read(r)));
297 if (c < 0) goto input_fail;
312 if ((c=read(r)) == '-') neg=1;
313 else if (c != '+') unread(r);
317 if ((c=read(r)) != '0') {
318 if (t == 'i') t = 'd';
322 if (((c=read(r))|0x20) != 'x') {
325 /* lone 0 is valid octal */
326 if ((unsigned)(c-'0') >= 8) {
341 for (m=0; isdigit(c=read(r)); m=1)
345 for (m=0; (unsigned)(c=read(r))-'0' < 8; m=1)
350 if (isdigit(c=read(r))) {
352 } else if ((unsigned)(c|0x20)-'a' < 6) {
353 i = (i<<4) + (c|0x20)-'a'+10;
357 if (!m) goto match_fail;
358 store_int(dest, size, neg, i);
366 if ((c=read(r)) == '-') neg=1;
367 else if (c != '+') unread(r);
368 /* FIXME: check for INF/NAN strings here */
369 if (read(r)=='0' && (m=1, (read(r)|0x20) == 'x'))
372 for (; isdigit(c=read(r)); m=1)
373 f = 10.0 * f + (c-'0');
376 for (; isdigit(c=read(r)); mag*=10.0)
382 if ((c=read(r))=='-') en=1;
383 else if (c!='+') unread(r);
384 for (; isdigit(c=read(r)); m=1)
385 if (ex < LDBL_MAX_10_EXP)
386 ex = 10 * ex + (c-'0');
387 if (ex > LDBL_MAX_10_EXP)
388 f = en ? 0 : INFINITY;
390 if (en) while (ex--) f/=10.0;
391 else while (ex--) f*=10.0;
397 for (; isxdigit(c=read(r)); m=1)
398 if (isdigit(c)) f = 16.0*f + (c-'0');
399 else f = 16.0*f + ((c|32)-'a'+10);
402 for (; isxdigit(c=read(r)); mag*=1/16.0)
403 if (isdigit(c)) f += (c-'0')*mag;
404 else f += ((c|32)-'a'+10)*mag;
409 if ((c=read(r))=='-') en=1;
410 else if (c!='+') unread(r);
411 for (; isdigit(c=read(r)); m=1)
412 if (ex < LDBL_MAX_EXP)
413 ex = 10 * ex + (c-'0');
414 if (ex > LDBL_MAX_EXP)
415 f = en ? 0 : INFINITY;
417 if (en) while (ex--) f*=0.5;
418 else while (ex--) f*=2.0;
422 if (!m) goto match_fail;
424 if (dest) switch (size) {
432 *(long double *)dest = f;
437 wcs = dest ? dest : (void *)&dummy;
438 st = (mbstate_t){ 0 };
439 while((c=read(r)) >= 0) {
441 if (is_space(c)) break;
442 if (dest) *wcs++ = c;
445 if (is_space(c)) break;
446 switch (mbrtowc(wcs, &ch, 1, &st)) {
456 if (dest) *wcs++ = 0;
459 s = dest ? dest : (void *)&dummy;
460 while((c=read(r)) >= 0) {
462 if (is_space(c)) break;
463 if ((l=wctomb(s, c)) < 0)
467 if (is_space(c)) break;
475 /* unread will do nothing if field width was exhausted */
484 if (!matches) matches--;