]> git.saurik.com Git - apple/libc.git/blame - stdio/FreeBSD/vfwscanf.c.patch
Libc-498.tar.gz
[apple/libc.git] / stdio / FreeBSD / vfwscanf.c.patch
CommitLineData
3d9156a7 1--- vfwscanf.c.orig 2004-11-25 11:38:36.000000000 -0800
224c7076 2+++ vfwscanf.c 2005-05-20 00:24:42.000000000 -0700
3d9156a7
A
3@@ -42,6 +42,8 @@
4 #include <sys/cdefs.h>
5 __FBSDID("$FreeBSD: src/lib/libc/stdio/vfwscanf.c,v 1.12 2004/05/02 20:13:29 obrien Exp $");
6
7+#include "xlocale_private.h"
8+
9 #include "namespace.h"
10 #include <ctype.h>
11 #include <inttypes.h>
12@@ -98,7 +100,9 @@
59e0d9fe
A
13 #define CT_INT 3 /* %[dioupxX] conversion */
14 #define CT_FLOAT 4 /* %[efgEFG] conversion */
15
16-static int parsefloat(FILE *, wchar_t *, wchar_t *);
3d9156a7
A
17+#ifndef NO_FLOATING_POINT
18+static int parsefloat(FILE *, wchar_t **, size_t, locale_t loc);
19+#endif /* !NO_FLOATING_POINT */
59e0d9fe
A
20
21 extern int __scanfdebug;
22
3d9156a7
A
23@@ -116,7 +120,21 @@
24
25 FLOCKFILE(fp);
26 ORIENT(fp, 1);
27- ret = __vfwscanf(fp, fmt, ap);
28+ ret = __vfwscanf(fp, __current_locale(), fmt, ap);
29+ FUNLOCKFILE(fp);
30+ return (ret);
31+}
32+
33+int
34+vfwscanf_l(FILE * __restrict fp, locale_t loc, const wchar_t * __restrict fmt,
35+ va_list ap)
36+{
37+ int ret;
38+
39+ NORMALIZE_LOCALE(loc);
40+ FLOCKFILE(fp);
41+ ORIENT(fp, 1);
42+ ret = __vfwscanf(fp, loc, fmt, ap);
43 FUNLOCKFILE(fp);
44 return (ret);
45 }
46@@ -124,8 +142,9 @@
47 /*
48 * Non-MT-safe version.
49 */
50-int
51-__vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap)
52+__private_extern__ int
53+__vfwscanf(FILE * __restrict fp, locale_t loc, const wchar_t * __restrict fmt,
54+ va_list ap)
55 {
56 wint_t c; /* character from format, or conversion */
57 size_t width; /* field width, or 0 */
58@@ -134,7 +153,6 @@
59e0d9fe
A
59 int flags; /* flags as defined above */
60 wchar_t *p0; /* saves original value of p when necessary */
61 int nassigned; /* number of fields assigned */
62- int nconversions; /* number of conversions */
63 int nread; /* number of characters consumed from fp */
64 int base; /* base argument to conversion function */
65 wchar_t buf[BUF]; /* buffer for numeric conversions */
3d9156a7
A
66@@ -145,27 +163,30 @@
67 char *mbp; /* multibyte string pointer for %c %s %[ */
68 size_t nconv; /* number of bytes in mb. conversion */
69 char mbbuf[MB_LEN_MAX]; /* temporary mb. character buffer */
70+ int index; /* for %index$ */
71+ va_list ap_orig; /* to reset ap to first argument */
72 static const mbstate_t initial;
73 mbstate_t mbs;
74+ int mb_cur_max = MB_CUR_MAX_L(loc);
75
76 /* `basefix' is used to avoid `if' tests in the integer scanner */
77 static short basefix[17] =
59e0d9fe
A
78 { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
79
80 nassigned = 0;
81- nconversions = 0;
82 nread = 0;
83 ccls = ccle = NULL;
3d9156a7 84+ va_copy(ap_orig, ap);
59e0d9fe 85 for (;;) {
3d9156a7
A
86 c = *fmt++;
87 if (c == 0)
88 return (nassigned);
89- if (iswspace(c)) {
90- while ((c = __fgetwc(fp)) != WEOF &&
91- iswspace(c))
92+ if (iswspace_l(c, loc)) {
93+ while ((c = __fgetwc(fp, loc)) != WEOF &&
94+ iswspace_l(c, loc))
95 ;
96 if (c != WEOF)
97- __ungetwc(c, fp);
98+ __ungetwc(c, fp, loc);
99 continue;
100 }
101 if (c != '%')
102@@ -180,15 +201,27 @@
103 switch (c) {
104 case '%':
105 literal:
106- if ((wi = __fgetwc(fp)) == WEOF)
107+ if ((wi = __fgetwc(fp, loc)) == WEOF)
108 goto input_failure;
109 if (wi != c) {
110- __ungetwc(wi, fp);
224c7076 111- goto input_failure;
3d9156a7 112+ __ungetwc(wi, fp, loc);
224c7076 113+ goto match_failure;
3d9156a7
A
114 }
115 nread++;
116 continue;
117
118+ case '$':
119+ index = width;
120+ if (index < 1 || index > NL_ARGMAX || fmt[-3] != '%') {
121+ goto input_failure;
122+ }
123+ width = 0;
124+ va_end(ap);
125+ va_copy(ap, ap_orig); /* reset to %1$ */
126+ for (; index > 1; index--) {
127+ va_arg(ap, void*);
128+ }
129+ goto again;
130 case '*':
131 flags |= SUPPRESS;
132 goto again;
133@@ -307,7 +340,6 @@
59e0d9fe
A
134 break;
135
136 case 'n':
137- nconversions++;
138 if (flags & SUPPRESS) /* ??? */
139 continue;
140 if (flags & SHORTSHORT)
3d9156a7
A
141@@ -343,11 +375,11 @@
142 * that suppress this.
143 */
144 if ((flags & NOSKIP) == 0) {
145- while ((wi = __fgetwc(fp)) != WEOF && iswspace(wi))
146+ while ((wi = __fgetwc(fp, loc)) != WEOF && iswspace_l(wi, loc))
147 nread++;
148 if (wi == WEOF)
149 goto input_failure;
150- __ungetwc(wi, fp);
151+ __ungetwc(wi, fp, loc);
152 }
153
154 /*
155@@ -364,7 +396,7 @@
156 p = va_arg(ap, wchar_t *);
157 n = 0;
158 while (width-- != 0 &&
159- (wi = __fgetwc(fp)) != WEOF) {
160+ (wi = __fgetwc(fp, loc)) != WEOF) {
161 if (!(flags & SUPPRESS))
162 *p++ = (wchar_t)wi;
163 n++;
164@@ -380,19 +412,19 @@
165 n = 0;
166 mbs = initial;
167 while (width != 0 &&
168- (wi = __fgetwc(fp)) != WEOF) {
169- if (width >= MB_CUR_MAX &&
170+ (wi = __fgetwc(fp, loc)) != WEOF) {
171+ if (width >= mb_cur_max &&
172 !(flags & SUPPRESS)) {
173- nconv = wcrtomb(mbp, wi, &mbs);
174+ nconv = wcrtomb_l(mbp, wi, &mbs, loc);
175 if (nconv == (size_t)-1)
176 goto input_failure;
177 } else {
178- nconv = wcrtomb(mbbuf, wi,
179- &mbs);
180+ nconv = wcrtomb_l(mbbuf, wi,
181+ &mbs, loc);
182 if (nconv == (size_t)-1)
183 goto input_failure;
184 if (nconv > width) {
185- __ungetwc(wi, fp);
186+ __ungetwc(wi, fp, loc);
187 break;
188 }
189 if (!(flags & SUPPRESS))
190@@ -410,7 +442,6 @@
59e0d9fe
A
191 if (!(flags & SUPPRESS))
192 nassigned++;
193 }
194- nconversions++;
195 break;
196
197 case CT_CCL:
3d9156a7
A
198@@ -420,20 +451,20 @@
199 /* take only those things in the class */
200 if ((flags & SUPPRESS) && (flags & LONG)) {
201 n = 0;
202- while ((wi = __fgetwc(fp)) != WEOF &&
203+ while ((wi = __fgetwc(fp, loc)) != WEOF &&
204 width-- != 0 && INCCL(wi))
205 n++;
206 if (wi != WEOF)
207- __ungetwc(wi, fp);
208+ __ungetwc(wi, fp, loc);
209 if (n == 0)
210 goto match_failure;
211 } else if (flags & LONG) {
212 p0 = p = va_arg(ap, wchar_t *);
213- while ((wi = __fgetwc(fp)) != WEOF &&
214+ while ((wi = __fgetwc(fp, loc)) != WEOF &&
215 width-- != 0 && INCCL(wi))
216 *p++ = (wchar_t)wi;
217 if (wi != WEOF)
218- __ungetwc(wi, fp);
219+ __ungetwc(wi, fp, loc);
220 n = p - p0;
221 if (n == 0)
222 goto match_failure;
223@@ -444,16 +475,16 @@
224 mbp = va_arg(ap, char *);
225 n = 0;
226 mbs = initial;
227- while ((wi = __fgetwc(fp)) != WEOF &&
228+ while ((wi = __fgetwc(fp, loc)) != WEOF &&
229 width != 0 && INCCL(wi)) {
230- if (width >= MB_CUR_MAX &&
231+ if (width >= mb_cur_max &&
232 !(flags & SUPPRESS)) {
233- nconv = wcrtomb(mbp, wi, &mbs);
234+ nconv = wcrtomb_l(mbp, wi, &mbs, loc);
235 if (nconv == (size_t)-1)
236 goto input_failure;
237 } else {
238- nconv = wcrtomb(mbbuf, wi,
239- &mbs);
240+ nconv = wcrtomb_l(mbbuf, wi,
241+ &mbs, loc);
242 if (nconv == (size_t)-1)
243 goto input_failure;
244 if (nconv > width)
245@@ -468,14 +499,15 @@
246 n++;
247 }
248 if (wi != WEOF)
249- __ungetwc(wi, fp);
250+ __ungetwc(wi, fp, loc);
251+ if (n == 0)
252+ goto match_failure;
253 if (!(flags & SUPPRESS)) {
254 *mbp = 0;
255 nassigned++;
59e0d9fe
A
256 }
257 }
258 nread += n;
259- nconversions++;
260 break;
261
262 case CT_STRING:
3d9156a7
A
263@@ -483,39 +515,39 @@
264 if (width == 0)
265 width = (size_t)~0;
266 if ((flags & SUPPRESS) && (flags & LONG)) {
267- while ((wi = __fgetwc(fp)) != WEOF &&
268+ while ((wi = __fgetwc(fp, loc)) != WEOF &&
269 width-- != 0 &&
270- !iswspace(wi))
271+ !iswspace_l(wi, loc))
272 nread++;
273 if (wi != WEOF)
274- __ungetwc(wi, fp);
275+ __ungetwc(wi, fp, loc);
276 } else if (flags & LONG) {
277 p0 = p = va_arg(ap, wchar_t *);
278- while ((wi = __fgetwc(fp)) != WEOF &&
279+ while ((wi = __fgetwc(fp, loc)) != WEOF &&
280 width-- != 0 &&
281- !iswspace(wi)) {
282+ !iswspace_l(wi, loc)) {
283 *p++ = (wchar_t)wi;
284 nread++;
285 }
286 if (wi != WEOF)
287- __ungetwc(wi, fp);
288+ __ungetwc(wi, fp, loc);
289 *p = '\0';
290 nassigned++;
291 } else {
292 if (!(flags & SUPPRESS))
293 mbp = va_arg(ap, char *);
294 mbs = initial;
295- while ((wi = __fgetwc(fp)) != WEOF &&
296+ while ((wi = __fgetwc(fp, loc)) != WEOF &&
297 width != 0 &&
298- !iswspace(wi)) {
299- if (width >= MB_CUR_MAX &&
300+ !iswspace_l(wi, loc)) {
301+ if (width >= mb_cur_max &&
302 !(flags & SUPPRESS)) {
303- nconv = wcrtomb(mbp, wi, &mbs);
304+ nconv = wcrtomb_l(mbp, wi, &mbs, loc);
305 if (nconv == (size_t)-1)
306 goto input_failure;
307 } else {
308- nconv = wcrtomb(mbbuf, wi,
309- &mbs);
310+ nconv = wcrtomb_l(mbbuf, wi,
311+ &mbs, loc);
312 if (nconv == (size_t)-1)
313 goto input_failure;
314 if (nconv > width)
315@@ -530,13 +562,12 @@
316 nread++;
317 }
318 if (wi != WEOF)
319- __ungetwc(wi, fp);
320+ __ungetwc(wi, fp, loc);
321 if (!(flags & SUPPRESS)) {
322 *mbp = 0;
59e0d9fe
A
323 nassigned++;
324 }
325 }
326- nconversions++;
327 continue;
328
329 case CT_INT:
3d9156a7
A
330@@ -546,7 +577,7 @@
331 width = sizeof(buf) / sizeof(*buf) - 1;
332 flags |= SIGNOK | NDIGITS | NZDIGITS;
333 for (p = buf; width; width--) {
334- c = __fgetwc(fp);
335+ c = __fgetwc(fp, loc);
336 /*
337 * Switch on the character; `goto ok'
338 * if we accept it as a part of number.
339@@ -630,7 +661,7 @@
340 * for a number. Stop accumulating digits.
341 */
342 if (c != WEOF)
343- __ungetwc(c, fp);
344+ __ungetwc(c, fp, loc);
345 break;
346 ok:
347 /*
348@@ -646,22 +677,22 @@
349 */
350 if (flags & NDIGITS) {
351 if (p > buf)
352- __ungetwc(*--p, fp);
353+ __ungetwc(*--p, fp, loc);
354 goto match_failure;
355 }
356 c = p[-1];
357 if (c == 'x' || c == 'X') {
358 --p;
359- __ungetwc(c, fp);
360+ __ungetwc(c, fp, loc);
361 }
362 if ((flags & SUPPRESS) == 0) {
363 uintmax_t res;
364
365 *p = 0;
366 if ((flags & UNSIGNED) == 0)
367- res = wcstoimax(buf, NULL, base);
368+ res = wcstoimax_l(buf, NULL, base, loc);
369 else
370- res = wcstoumax(buf, NULL, base);
371+ res = wcstoumax_l(buf, NULL, base, loc);
372 if (flags & POINTER)
373 *va_arg(ap, void **) =
374 (void *)(uintptr_t)res;
224c7076 375@@ -684,47 +715,45 @@
59e0d9fe
A
376 nassigned++;
377 }
378 nread += p - buf;
379- nconversions++;
380 break;
381
3d9156a7 382 #ifndef NO_FLOATING_POINT
59e0d9fe
A
383 case CT_FLOAT:
384+ {
385+ wchar_t *pbuf;
386 /* scan a floating point number as if by strtod */
387- if (width == 0 || width > sizeof(buf) /
388- sizeof(*buf) - 1)
389- width = sizeof(buf) / sizeof(*buf) - 1;
390- if ((width = parsefloat(fp, buf, buf + width)) == 0)
224c7076 391+ if ((width = parsefloat(fp, &pbuf, width, loc)) == 0)
59e0d9fe 392 goto match_failure;
59e0d9fe
A
393 if ((flags & SUPPRESS) == 0) {
394 if (flags & LONGDBL) {
395- long double res = wcstold(buf, &p);
3d9156a7 396+ long double res = wcstold_l(pbuf, &p, loc);
59e0d9fe
A
397 *va_arg(ap, long double *) = res;
398 } else if (flags & LONG) {
399- double res = wcstod(buf, &p);
3d9156a7 400+ double res = wcstod_l(pbuf, &p, loc);
59e0d9fe
A
401 *va_arg(ap, double *) = res;
402 } else {
403- float res = wcstof(buf, &p);
3d9156a7 404+ float res = wcstof_l(pbuf, &p, loc);
59e0d9fe
A
405 *va_arg(ap, float *) = res;
406 }
407- if (__scanfdebug && p - buf != width)
408+ if (__scanfdebug && p - pbuf != width)
409 abort();
410 nassigned++;
411 }
412 nread += width;
413- nconversions++;
59e0d9fe
A
414 break;
415+ }
3d9156a7 416 #endif /* !NO_FLOATING_POINT */
59e0d9fe
A
417 }
418 }
419 input_failure:
420- return (nconversions != 0 ? nassigned : EOF);
421+ return (nassigned ? nassigned : EOF);
422 match_failure:
423 return (nassigned);
424 }
425
3d9156a7 426 #ifndef NO_FLOATING_POINT
59e0d9fe
A
427 static int
428-parsefloat(FILE *fp, wchar_t *buf, wchar_t *end)
3d9156a7 429+parsefloat(FILE *fp, wchar_t **buf, size_t width, locale_t loc)
59e0d9fe
A
430 {
431 wchar_t *commit, *p;
432 int infnanpos = 0;
224c7076 433@@ -733,9 +762,33 @@
3d9156a7
A
434 S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS
435 } state = S_START;
59e0d9fe 436 wchar_t c;
3d9156a7 437- wchar_t decpt = (wchar_t)(unsigned char)*localeconv()->decimal_point;
224c7076
A
438+ char *decimal_point;
439+ wchar_t decpt;
59e0d9fe 440 _Bool gotmantdig = 0, ishex = 0;
224c7076
A
441-
442+ static wchar_t *b = NULL;
443+ static size_t bsiz = 0;
444+ wchar_t *e;
59e0d9fe 445+ size_t s;
224c7076
A
446+
447+ if (bsiz == 0) {
448+ b = (wchar_t *)malloc(BUF * sizeof(wchar_t));
449+ if (b == NULL) {
450+ *buf = NULL;
451+ return 0;
452+ }
453+ bsiz = BUF;
454+ }
455+ s = (width == 0 ? bsiz : (width + 1));
456+ if (s > bsiz) {
457+ b = (wchar_t *)reallocf(b, s * sizeof(wchar_t));
458+ if (b == NULL) {
459+ bsiz = 0;
460+ *buf = NULL;
461+ return 0;
462+ }
463+ bsiz = s;
59e0d9fe
A
464+ }
465+ e = b + (s - 1);
466 /*
467 * We set commit = p whenever the string we have read so far
468 * constitutes a valid representation of a floating point
224c7076 469@@ -745,10 +798,12 @@
59e0d9fe
A
470 * always necessary to read at least one character that doesn't
471 * match; thus, we can't short-circuit "infinity" or "nan(...)".
472 */
473- commit = buf - 1;
474+ commit = b - 1;
475 c = WEOF;
476- for (p = buf; p < end; ) {
3d9156a7 477- if ((c = __fgetwc(fp)) == WEOF)
224c7076
A
478+ decimal_point = localeconv_l(loc)->decimal_point;
479+ mbtowc_l(&decpt, decimal_point, strlen(decimal_point), loc);
59e0d9fe 480+ for (p = b; width == 0 || p < e; ) {
3d9156a7 481+ if ((c = __fgetwc(fp, loc)) == WEOF)
59e0d9fe
A
482 break;
483 reswitch:
3d9156a7 484 switch (state) {
224c7076 485@@ -808,7 +863,7 @@
3d9156a7
A
486 if (c == ')') {
487 commit = p;
488 infnanpos = -2;
489- } else if (!iswalnum(c) && c != '_')
490+ } else if (!iswalnum_l(c, loc) && c != '_')
491 goto parsedone;
492 break;
493 }
224c7076 494@@ -824,7 +879,7 @@
3d9156a7
A
495 goto reswitch;
496 }
497 case S_DIGITS:
498- if ((ishex && iswxdigit(c)) || iswdigit(c))
499+ if ((ishex && iswxdigit_l(c, loc)) || iswdigit_l(c, loc))
500 gotmantdig = 1;
501 else {
502 state = S_FRAC;
224c7076 503@@ -841,7 +896,7 @@
3d9156a7
A
504 goto parsedone;
505 else
506 state = S_EXP;
507- } else if ((ishex && iswxdigit(c)) || iswdigit(c)) {
508+ } else if ((ishex && iswxdigit_l(c, loc)) || iswdigit_l(c, loc)) {
509 commit = p;
510 gotmantdig = 1;
511 } else
224c7076 512@@ -854,7 +909,7 @@
3d9156a7
A
513 else
514 goto reswitch;
515 case S_EXPDIGITS:
516- if (iswdigit(c))
517+ if (iswdigit_l(c, loc))
518 commit = p;
519 else
520 goto parsedone;
224c7076 521@@ -862,16 +917,32 @@
59e0d9fe
A
522 default:
523 abort();
524 }
525+ if (p >= e) {
224c7076
A
526+ ssize_t diff = (p - b);
527+ ssize_t com = (commit - b);
59e0d9fe
A
528+ s += BUF;
529+ b = (wchar_t *)reallocf(b, s * sizeof(wchar_t));
530+ if (b == NULL) {
224c7076 531+ bsiz = 0;
59e0d9fe
A
532+ *buf = NULL;
533+ return 0;
534+ }
224c7076 535+ bsiz = s;
59e0d9fe
A
536+ e = b + (s - 1);
537+ p = b + diff;
224c7076 538+ commit = b + com;
59e0d9fe
A
539+ }
540 *p++ = c;
541 c = WEOF;
542 }
3d9156a7
A
543
544 parsedone:
545 if (c != WEOF)
546- __ungetwc(c, fp);
547+ __ungetwc(c, fp, loc);
59e0d9fe 548 while (commit < --p)
3d9156a7
A
549- __ungetwc(*p, fp);
550+ __ungetwc(*p, fp, loc);
59e0d9fe
A
551 *++commit = '\0';
552- return (commit - buf);
553+ *buf = b;
554+ return (commit - b);
555 }
556 #endif