10 #include "stdio_impl.h"
13 #include "floatscan.h"
22 static void store_int(void *dest
, int size
, unsigned long long i
)
39 *(long long *)dest
= i
;
44 static void *arg_n(va_list ap
, unsigned int n
)
50 for (i
=n
; i
>1; i
--) va_arg(ap2
, void *);
51 p
= va_arg(ap2
, void *);
56 static int in_set(const wchar_t *set
, int c
)
59 const wchar_t *p
= set
;
63 } else if (*p
== ']') {
67 for (; *p
&& *p
!= ']'; p
++) {
68 if (*p
=='-' && p
[1] && p
[1] != ']')
69 for (j
=p
++[-1]; j
<*p
; j
++)
79 ((f)->rpos != (f)->rend && *(f)->rpos < 128 ? *(f)->rpos++ : (getwc)(f))
82 #define ungetwc(c,f) \
83 ((f)->rend && (c)<128U ? *--(f)->rpos : ungetwc((c),(f)))
86 int vfwscanf(FILE *restrict f
, const wchar_t *restrict fmt
, va_list ap
)
99 static const char size_pfx
[][3] = { "hh", "h", "", "l", "L", "ll" };
100 char tmp
[3*sizeof(int)+10];
108 for (p
=fmt
; *p
; p
++) {
113 while (iswspace(p
[1])) p
++;
114 while (iswspace((c
=getwc(f
)))) pos
++;
118 if (*p
!= '%' || p
[1] == '%') {
121 while (iswspace((c
=getwc(f
)))) pos
++;
127 if (c
<0) goto input_fail
;
137 } else if (iswdigit(*p
) && p
[1]=='$') {
138 dest
= arg_n(ap
, *p
-'0'); p
+=2;
140 dest
= va_arg(ap
, void *);
143 for (width
=0; iswdigit(*p
); p
++) {
144 width
= 10*width
+ *p
- '0';
159 if (*p
== 'h') p
++, size
= SIZE_hh
;
163 if (*p
== 'l') p
++, size
= SIZE_ll
;
176 case 'd': case 'i': case 'o': case 'u': case 'x':
177 case 'a': case 'e': case 'f': case 'g':
178 case 'A': case 'E': case 'F': case 'G': case 'X':
179 case 's': case 'c': case '[':
190 /* Transform S,C -> ls,lc */
197 if (t
!= '[' && (t
|32) != 'c')
198 while (iswspace((c
=getwc(f
)))) pos
++;
201 if (c
< 0) goto input_fail
;
207 store_int(dest
, size
, pos
);
208 /* do not increment match count, etc! */
215 if (width
<1) width
= 1;
218 } else if (t
== 's') {
220 static const wchar_t spaces
[] = {
221 ' ', '\t', '\n', '\r', 11, 12, 0x0085,
222 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005,
223 0x2006, 0x2008, 0x2009, 0x200a,
224 0x2028, 0x2029, 0x205f, 0x3000, 0 };
227 if (*++p
== '^') p
++, invert
= 1;
232 if (!*p
) goto fmt_fail
;
237 s
= (size
== SIZE_def
) ? dest
: 0;
238 wcs
= (size
== SIZE_l
) ? dest
: 0;
242 if (width
< 1) width
= -1;
246 k
= t
=='c' ? width
+1U : 31;
247 if (size
== SIZE_l
) {
248 wcs
= malloc(k
*sizeof(wchar_t));
249 if (!wcs
) goto alloc_fail
;
252 if (!s
) goto alloc_fail
;
256 if ((c
=getwc(f
))<0) break;
257 if (in_set(set
, c
) == invert
)
263 wchar_t *tmp
= realloc(wcs
, k
*sizeof(wchar_t));
264 if (!tmp
) goto alloc_fail
;
267 } else if (size
!= SIZE_l
) {
268 int l
= wctomb(s
?s
+i
:tmp
, c
);
269 if (l
<0) goto input_fail
;
271 if (alloc
&& i
> k
-4) {
273 char *tmp
= realloc(s
, k
);
274 if (!tmp
) goto alloc_fail
;
284 if (t
== 'c' || !gotmatch
) goto match_fail
;
288 if (size
== SIZE_l
) *(wchar_t **)dest
= wcs
;
289 else *(char **)dest
= s
;
297 case 'd': case 'i': case 'o': case 'u': case 'x':
298 case 'a': case 'e': case 'f': case 'g':
299 case 'A': case 'E': case 'F': case 'G': case 'X':
301 if (width
< 1) width
= 0;
302 snprintf(tmp
, sizeof tmp
, "%.*s%.0d%s%c%%lln",
303 1+!dest
, "%*", width
, size_pfx
[size
+2], t
);
305 if (fscanf(f
, tmp
, dest
?dest
:&cnt
, &cnt
) == -1)
321 if (!matches
) matches
--;
332 weak_alias(vfwscanf
,__isoc99_vfwscanf
);