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->u || r->w < 0) return;
38 static void store_int(void *dest, int size, int neg, unsigned long long i)
56 *(long long *)dest = i;
61 static void *arg_n(va_list ap, unsigned int n)
67 for (i=n; i>1; i--) va_arg(ap2, void *);
68 p = va_arg(ap2, void *);
73 int __scanf(rctx_t *r, const wchar_t *fmt, va_list ap)
87 unsigned long long i=0;
91 int (*is_space)(int) = r->is_space;
95 do p++; while (is_space(*p));
96 do r->w=1; while (is_space(read(r)));
99 } else if (*p != '%' || p[1] == '%') {
108 for (z=p; isdigit(*z); z++);
109 if (*z != '$' && *z != '*') {
110 if (mode == 0) mode = 1;
112 } else if (*z != '*') {
116 pos = 10*pos + *p - '0';
119 if (!pos) goto fmt_fail;
120 dest = arg_n(ap, pos);
126 } else if (mode == 1) {
127 dest = va_arg(ap, void *);
130 if (!*p) goto fmt_fail;
133 for (; isdigit(*p); p++) {
134 width = 10*width + *p - '0';
142 if (*p == 'h') p++, size = SIZE_hh;
146 if (*p == 'l') p++, size = SIZE_ll;
159 case 'd': case 'i': case 'o': case 'u': case 'x':
160 case 'a': case 'e': case 'f': case 'g':
161 case 'A': case 'E': case 'F': case 'G': case 'X':
162 case 's': case 'c': case '[':
176 if (width < 1) width = 1;
178 if (size == SIZE_l) t &= ~0x20;
179 case 'd': case 'i': case 'o': case 'u': case 'x':
180 case 'a': case 'e': case 'f': case 'g':
181 case 'A': case 'E': case 'F': case 'G': case 'X':
184 if (width < 1) width = INT_MAX;
193 if (read(r) < 0) goto input_fail;
199 store_int(dest, size, 0, r->l - r->u);
200 /* do not increment match count, etc! */
203 wcs = dest ? dest : (void *)&dummy;
204 st = (mbstate_t){ 0 };
205 while ((c=read(r)) >= 0) {
207 if (dest) *wcs++ = c;
210 switch (mbrtowc(wcs, &ch, 1, &st)) {
220 if (r->w > 0) goto match_fail;
223 s = dest ? dest : (void *)&dummy;
224 while ((c=read(r)) >= 0) {
226 if ((l=wctomb(s, c)) < 0)
233 if (r->w > 0) goto match_fail;
236 wcs = dest ? dest : (void *)&dummy;
237 s = dest ? dest : (void *)&dummy;
238 if (!wide && size == SIZE_l) st = (mbstate_t){ 0 };
240 if (*p == '^') p++, invert = 1;
244 for (m=0; (c=read(r)) >= 0; m=1) {
245 for (z=p; *z && *z != c && (*z != ']' || z==p); z++);
246 if (!*z) goto fmt_fail;
247 if (*z == c && (*z != ']' || z==p)) {
252 if (size == SIZE_l) {
253 if (dest) *wcs++ = c;
255 if ((l=wctomb(s, c)) < 0)
260 for (p++; *p && *p != ']'; p++);
263 unsigned char scanset[257];
264 memset(scanset, invert, sizeof scanset);
266 for (z=p; *z && (*z != ']' || z==p); z++)
267 scanset[1+*z] = 1-invert;
268 if (!*z) goto fmt_fail;
271 for (m=0; scanset[(c=read(r))+1]; m=1) {
272 if (size == SIZE_l) {
274 switch (mbrtowc(wcs, &ch, 1, &st)) {
287 if (!m) goto match_fail;
289 if (size == SIZE_l) *wcs++ = 0;
294 /* read unlimited number of spaces, then reset width */
295 do r->w = 1; while (is_space(c = read(r)));
296 if (c < 0) goto input_fail;
311 if ((c=read(r)) == '-') neg=1;
312 else if (c != '+') unread(r);
316 if ((c=read(r)) != '0') {
317 if (t == 'i') t = 'd';
321 if (((c=read(r))|0x20) != 'x') {
324 /* lone 0 is valid octal */
325 if ((unsigned)(c-'0') >= 8) {
340 for (m=0; isdigit(c=read(r)); m=1)
344 for (m=0; (unsigned)(c=read(r))-'0' < 8; m=1)
349 if (isdigit(c=read(r))) {
351 } else if ((unsigned)(c|0x20)-'a' < 6) {
352 i = (i<<4) + (c|0x20)-'a'+10;
356 if (!m) goto match_fail;
357 store_int(dest, size, neg, i);
365 if ((c=read(r)) == '-') neg=1;
366 else if (c != '+') unread(r);
367 /* FIXME: check for INF/NAN strings here */
368 if (read(r)=='0' && (m=1, (read(r)|0x20) == 'x'))
371 for (; isdigit(c=read(r)); m=1)
372 f = 10.0 * f + (c-'0');
375 for (; isdigit(c=read(r)); mag*=10.0)
381 if ((c=read(r))=='-') en=1;
382 else if (c!='+') unread(r);
383 for (; isdigit(c=read(r)); m=1)
384 if (ex < LDBL_MAX_10_EXP)
385 ex = 10 * ex + (c-'0');
386 if (ex > LDBL_MAX_10_EXP)
387 f = en ? 0 : INFINITY;
389 if (en) while (ex--) f/=10.0;
390 else while (ex--) f*=10.0;
396 for (; isxdigit(c=read(r)); m=1)
397 if (isdigit(c)) f = 16.0*f + (c-'0');
398 else f = 16.0*f + ((c|32)-'a'+10);
401 for (; isxdigit(c=read(r)); mag*=1/16.0)
402 if (isdigit(c)) f += (c-'0')*mag;
403 else f += ((c|32)-'a'+10)*mag;
408 if ((c=read(r))=='-') en=1;
409 else if (c!='+') unread(r);
410 for (; isdigit(c=read(r)); m=1)
411 if (ex < LDBL_MAX_EXP)
412 ex = 10 * ex + (c-'0');
413 if (ex > LDBL_MAX_EXP)
414 f = en ? 0 : INFINITY;
416 if (en) while (ex--) f*=0.5;
417 else while (ex--) f*=2.0;
421 if (!m) goto match_fail;
423 if (dest) switch (size) {
431 *(long double *)dest = f;
436 wcs = dest ? dest : (void *)&dummy;
437 st = (mbstate_t){ 0 };
438 while((c=read(r)) >= 0) {
440 if (is_space(c)) break;
441 if (dest) *wcs++ = c;
444 if (is_space(c)) break;
445 switch (mbrtowc(wcs, &ch, 1, &st)) {
455 if (dest) *wcs++ = 0;
458 s = dest ? dest : (void *)&dummy;
459 while((c=read(r)) >= 0) {
461 if (is_space(c)) break;
462 if ((l=wctomb(s, c)) < 0)
466 if (is_space(c)) break;
474 /* unread will do nothing if field width was exhausted */
483 if (!matches) matches--;