]> git.saurik.com Git - apple/libc.git/blob - stdio/FreeBSD/vfscanf.c.patch
Libc-391.4.1.tar.gz
[apple/libc.git] / stdio / FreeBSD / vfscanf.c.patch
1 --- vfscanf.c.orig 2004-11-25 11:38:35.000000000 -0800
2 +++ vfscanf.c 2005-02-23 19:24:50.000000000 -0800
3 @@ -40,6 +40,8 @@
4 #include <sys/cdefs.h>
5 __FBSDID("$FreeBSD: src/lib/libc/stdio/vfscanf.c,v 1.37 2004/05/02 10:55:05 das Exp $");
6
7 +#include "xlocale_private.h"
8 +
9 #include "namespace.h"
10 #include <ctype.h>
11 #include <inttypes.h>
12 @@ -97,10 +99,21 @@
13 #define CT_INT 3 /* %[dioupxX] conversion */
14 #define CT_FLOAT 4 /* %[efgEFG] conversion */
15
16 -static const u_char *__sccl(char *, const u_char *);
17 -static int parsefloat(FILE *, char *, char *);
18 +static const u_char *__sccl(char *, const u_char *, locale_t);
19 +#ifndef NO_FLOATING_POINT
20 +static int parsefloat(FILE *, char **, size_t, locale_t);
21 +#endif /* !NO_FLOATING_POINT */
22
23 +/*
24 + * For ppc, we need to have the 64-bit long double version defining storage for
25 + * __scanfdebug, to be compatible with 10.3. For ppc64 and i386, we want the
26 + * storage defined in the only version.
27 + */
28 +#if defined(__ppc__) && !defined(BUILDING_VARIANT)
29 +extern int __scanfdebug;
30 +#else /* !__ppc__ || BUILDING_VARIANT */
31 int __scanfdebug = 0;
32 +#endif /* __ppc__ && !BUILDING_VARIANT */
33
34 __weak_reference(__vfscanf, vfscanf);
35
36 @@ -108,12 +121,24 @@
37 * __vfscanf - MT-safe version
38 */
39 int
40 -__vfscanf(FILE *fp, char const *fmt0, va_list ap)
41 +__vfscanf(FILE * __restrict fp, char const * __restrict fmt0, va_list ap)
42 +{
43 + int ret;
44 +
45 + FLOCKFILE(fp);
46 + ret = __svfscanf_l(fp, __current_locale(), fmt0, ap);
47 + FUNLOCKFILE(fp);
48 + return (ret);
49 +}
50 +
51 +int
52 +vfscanf_l(FILE * __restrict fp, locale_t loc, char const * __restrict fmt0, va_list ap)
53 {
54 int ret;
55
56 + NORMALIZE_LOCALE(loc);
57 FLOCKFILE(fp);
58 - ret = __svfscanf(fp, fmt0, ap);
59 + ret = __svfscanf_l(fp, loc, fmt0, ap);
60 FUNLOCKFILE(fp);
61 return (ret);
62 }
63 @@ -121,8 +146,8 @@
64 /*
65 * __svfscanf - non-MT-safe version of __vfscanf
66 */
67 -int
68 -__svfscanf(FILE *fp, const char *fmt0, va_list ap)
69 +__private_extern__ int
70 +__svfscanf_l(FILE * __restrict fp, locale_t loc, const char * __restrict fmt0, va_list ap)
71 {
72 const u_char *fmt = (const u_char *)fmt0;
73 int c; /* character from format, or conversion */
74 @@ -132,7 +157,6 @@
75 int flags; /* flags as defined above */
76 char *p0; /* saves original value of p when necessary */
77 int nassigned; /* number of fields assigned */
78 - int nconversions; /* number of conversions */
79 int nread; /* number of characters consumed from fp */
80 int base; /* base argument to conversion function */
81 char ccltab[256]; /* character class table for %[...] */
82 @@ -140,24 +164,29 @@
83 wchar_t *wcp; /* handy wide character pointer */
84 wchar_t *wcp0; /* saves original value of wcp */
85 size_t nconv; /* length of multibyte sequence converted */
86 + int index; /* %index$, zero if unset */
87 + va_list ap_orig; /* to reset ap to first argument */
88 static const mbstate_t initial;
89 mbstate_t mbs;
90 + int mb_cur_max;
91
92 /* `basefix' is used to avoid `if' tests in the integer scanner */
93 static short basefix[17] =
94 { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
95
96 + NORMALIZE_LOCALE(loc);
97 + mb_cur_max = MB_CUR_MAX_L(loc);
98 ORIENT(fp, -1);
99
100 nassigned = 0;
101 - nconversions = 0;
102 nread = 0;
103 + va_copy(ap_orig, ap);
104 for (;;) {
105 c = *fmt++;
106 if (c == 0)
107 return (nassigned);
108 - if (isspace(c)) {
109 - while ((fp->_r > 0 || __srefill(fp) == 0) && isspace(*fp->_p))
110 + if (isspace_l(c, loc)) {
111 + while ((fp->_r > 0 || __srefill(fp) == 0) && isspace_l(*fp->_p, loc))
112 nread++, fp->_r--, fp->_p++;
113 continue;
114 }
115 @@ -181,6 +210,18 @@
116 nread++;
117 continue;
118
119 + case '$':
120 + index = width;
121 + if (index < 1 || index > NL_ARGMAX || fmt[-3] != '%') {
122 + goto input_failure;
123 + }
124 + width = 0;
125 + va_end(ap);
126 + va_copy(ap, ap_orig); /* reset to %1$ */
127 + for (; index > 1; index--) {
128 + va_arg(ap, void*);
129 + }
130 + goto again;
131 case '*':
132 flags |= SUPPRESS;
133 goto again;
134 @@ -267,7 +308,7 @@
135 break;
136
137 case '[':
138 - fmt = __sccl(ccltab, fmt);
139 + fmt = __sccl(ccltab, fmt, loc);
140 flags |= NOSKIP;
141 c = CT_CCL;
142 break;
143 @@ -288,7 +329,6 @@
144 break;
145
146 case 'n':
147 - nconversions++;
148 if (flags & SUPPRESS) /* ??? */
149 continue;
150 if (flags & SHORTSHORT)
151 @@ -330,7 +370,7 @@
152 * that suppress this.
153 */
154 if ((flags & NOSKIP) == 0) {
155 - while (isspace(*fp->_p)) {
156 + while (isspace_l(*fp->_p, loc)) {
157 nread++;
158 if (--fp->_r > 0)
159 fp->_p++;
160 @@ -360,7 +400,7 @@
161 wcp = NULL;
162 n = 0;
163 while (width != 0) {
164 - if (n == MB_CUR_MAX) {
165 + if (n == mb_cur_max) {
166 fp->_flags |= __SERR;
167 goto input_failure;
168 }
169 @@ -368,7 +408,7 @@
170 fp->_p++;
171 fp->_r--;
172 mbs = initial;
173 - nconv = mbrtowc(wcp, buf, n, &mbs);
174 + nconv = mbrtowc_l(wcp, buf, n, &mbs, loc);
175 if (nconv == (size_t)-1) {
176 fp->_flags |= __SERR;
177 goto input_failure;
178 @@ -421,7 +461,6 @@
179 nread += r;
180 nassigned++;
181 }
182 - nconversions++;
183 break;
184
185 case CT_CCL:
186 @@ -440,7 +479,7 @@
187 n = 0;
188 nchars = 0;
189 while (width != 0) {
190 - if (n == MB_CUR_MAX) {
191 + if (n == mb_cur_max) {
192 fp->_flags |= __SERR;
193 goto input_failure;
194 }
195 @@ -448,7 +487,7 @@
196 fp->_p++;
197 fp->_r--;
198 mbs = initial;
199 - nconv = mbrtowc(wcp, buf, n, &mbs);
200 + nconv = mbrtowc_l(wcp, buf, n, &mbs, loc);
201 if (nconv == (size_t)-1) {
202 fp->_flags |= __SERR;
203 goto input_failure;
204 @@ -456,8 +495,8 @@
205 if (nconv == 0)
206 *wcp = L'\0';
207 if (nconv != (size_t)-2) {
208 - if (wctob(*wcp) != EOF &&
209 - !ccltab[wctob(*wcp)]) {
210 + if (wctob_l(*wcp, loc) != EOF &&
211 + !ccltab[wctob_l(*wcp, loc)]) {
212 while (n != 0) {
213 n--;
214 __ungetc(buf[n],
215 @@ -525,7 +564,6 @@
216 nassigned++;
217 }
218 nread += n;
219 - nconversions++;
220 break;
221
222 case CT_STRING:
223 @@ -540,8 +578,8 @@
224 else
225 wcp = &twc;
226 n = 0;
227 - while (!isspace(*fp->_p) && width != 0) {
228 - if (n == MB_CUR_MAX) {
229 + while (!isspace_l(*fp->_p, loc) && width != 0) {
230 + if (n == mb_cur_max) {
231 fp->_flags |= __SERR;
232 goto input_failure;
233 }
234 @@ -549,7 +587,7 @@
235 fp->_p++;
236 fp->_r--;
237 mbs = initial;
238 - nconv = mbrtowc(wcp, buf, n, &mbs);
239 + nconv = mbrtowc_l(wcp, buf, n, &mbs, loc);
240 if (nconv == (size_t)-1) {
241 fp->_flags |= __SERR;
242 goto input_failure;
243 @@ -557,7 +595,7 @@
244 if (nconv == 0)
245 *wcp = L'\0';
246 if (nconv != (size_t)-2) {
247 - if (iswspace(*wcp)) {
248 + if (iswspace_l(*wcp, loc)) {
249 while (n != 0) {
250 n--;
251 __ungetc(buf[n],
252 @@ -585,7 +623,7 @@
253 }
254 } else if (flags & SUPPRESS) {
255 n = 0;
256 - while (!isspace(*fp->_p)) {
257 + while (!isspace_l(*fp->_p, loc)) {
258 n++, fp->_r--, fp->_p++;
259 if (--width == 0)
260 break;
261 @@ -595,7 +633,7 @@
262 nread += n;
263 } else {
264 p0 = p = va_arg(ap, char *);
265 - while (!isspace(*fp->_p)) {
266 + while (!isspace_l(*fp->_p, loc)) {
267 fp->_r--;
268 *p++ = *fp->_p++;
269 if (--width == 0)
270 @@ -607,7 +645,6 @@
271 nread += p - p0;
272 nassigned++;
273 }
274 - nconversions++;
275 continue;
276
277 case CT_INT:
278 @@ -738,9 +775,9 @@
279
280 *p = 0;
281 if ((flags & UNSIGNED) == 0)
282 - res = strtoimax(buf, (char **)NULL, base);
283 + res = strtoimax_l(buf, (char **)NULL, base, loc);
284 else
285 - res = strtoumax(buf, (char **)NULL, base);
286 + res = strtoumax_l(buf, (char **)NULL, base, loc);
287 if (flags & POINTER)
288 *va_arg(ap, void **) =
289 (void *)(uintptr_t)res;
290 @@ -763,43 +800,52 @@
291 nassigned++;
292 }
293 nread += p - buf;
294 - nconversions++;
295 break;
296
297 #ifndef NO_FLOATING_POINT
298 case CT_FLOAT:
299 + {
300 + char *pbuf;
301 /* scan a floating point number as if by strtod */
302 - if (width == 0 || width > sizeof(buf) - 1)
303 - width = sizeof(buf) - 1;
304 - if ((width = parsefloat(fp, buf, buf + width)) == 0)
305 + if ((width = parsefloat(fp, &pbuf, width, loc)) == 0) {
306 + if (pbuf)
307 + free(pbuf);
308 goto match_failure;
309 + }
310 if ((flags & SUPPRESS) == 0) {
311 if (flags & LONGDBL) {
312 - long double res = strtold(buf, &p);
313 + long double res = strtold_l(pbuf, &p, loc);
314 *va_arg(ap, long double *) = res;
315 } else if (flags & LONG) {
316 - double res = strtod(buf, &p);
317 + double res = strtod_l(pbuf, &p, loc);
318 *va_arg(ap, double *) = res;
319 } else {
320 - float res = strtof(buf, &p);
321 + float res = strtof_l(pbuf, &p, loc);
322 *va_arg(ap, float *) = res;
323 }
324 - if (__scanfdebug && p - buf != width)
325 + if (__scanfdebug && p - pbuf != width)
326 abort();
327 nassigned++;
328 }
329 nread += width;
330 - nconversions++;
331 + free(pbuf);
332 break;
333 + }
334 #endif /* !NO_FLOATING_POINT */
335 }
336 }
337 input_failure:
338 - return (nconversions != 0 ? nassigned : EOF);
339 + return (nassigned ? nassigned : EOF);
340 match_failure:
341 return (nassigned);
342 }
343
344 +int
345 +__svfscanf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
346 +{
347 + return __svfscanf_l(fp, __current_locale(), fmt0, ap);
348 +}
349 +
350 /*
351 * Fill in the given table from the scanset at the given format
352 * (just after `['). Return a pointer to the character past the
353 @@ -807,9 +853,10 @@
354 * considered part of the scanset.
355 */
356 static const u_char *
357 -__sccl(tab, fmt)
358 +__sccl(tab, fmt, loc)
359 char *tab;
360 const u_char *fmt;
361 + locale_t loc;
362 {
363 int c, n, v, i;
364
365 @@ -845,6 +892,7 @@
366 return (fmt - 1);
367
368 case '-':
369 + {
370 /*
371 * A scanset of the form
372 * [01+-]
373 @@ -865,8 +913,8 @@
374 */
375 n = *fmt;
376 if (n == ']'
377 - || (__collate_load_error ? n < c :
378 - __collate_range_cmp (n, c) < 0
379 + || (loc->__collate_load_error ? n < c :
380 + __collate_range_cmp (n, c, loc) < 0
381 )
382 ) {
383 c = '-';
384 @@ -874,14 +922,14 @@
385 }
386 fmt++;
387 /* fill in the range */
388 - if (__collate_load_error) {
389 + if (loc->__collate_load_error) {
390 do {
391 tab[++c] = v;
392 } while (c < n);
393 } else {
394 for (i = 0; i < 256; i ++)
395 - if ( __collate_range_cmp (c, i) < 0
396 - && __collate_range_cmp (i, n) <= 0
397 + if ( __collate_range_cmp (c, i, loc) < 0
398 + && __collate_range_cmp (i, n, loc) <= 0
399 )
400 tab[i] = v;
401 }
402 @@ -901,7 +949,7 @@
403 return (fmt);
404 #endif
405 break;
406 -
407 + }
408 case ']': /* end of scanset */
409 return (fmt);
410
411 @@ -915,7 +963,7 @@
412
413 #ifndef NO_FLOATING_POINT
414 static int
415 -parsefloat(FILE *fp, char *buf, char *end)
416 +parsefloat(FILE *fp, char **buf, size_t width, locale_t loc)
417 {
418 char *commit, *p;
419 int infnanpos = 0;
420 @@ -924,9 +972,18 @@
421 S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS
422 } state = S_START;
423 unsigned char c;
424 - char decpt = *localeconv()->decimal_point;
425 + char decpt = *localeconv_l(loc)->decimal_point;
426 _Bool gotmantdig = 0, ishex = 0;
427 + char *b, *e;
428 + size_t s;
429
430 + s = (width == 0 ? BUF : width + 1);
431 + b = (char *)malloc(s);
432 + if (b == NULL) {
433 + *buf = NULL;
434 + return 0;
435 + }
436 + e = b + (s - 1);
437 /*
438 * We set commit = p whenever the string we have read so far
439 * constitutes a valid representation of a floating point
440 @@ -936,8 +993,8 @@
441 * always necessary to read at least one character that doesn't
442 * match; thus, we can't short-circuit "infinity" or "nan(...)".
443 */
444 - commit = buf - 1;
445 - for (p = buf; p < end; ) {
446 + commit = b - 1;
447 + for (p = b; width == 0 || p < e; ) {
448 c = *fp->_p;
449 reswitch:
450 switch (state) {
451 @@ -997,7 +1054,7 @@
452 if (c == ')') {
453 commit = p;
454 infnanpos = -2;
455 - } else if (!isalnum(c) && c != '_')
456 + } else if (!isalnum_l(c, loc) && c != '_')
457 goto parsedone;
458 break;
459 }
460 @@ -1013,7 +1070,7 @@
461 goto reswitch;
462 }
463 case S_DIGITS:
464 - if ((ishex && isxdigit(c)) || isdigit(c))
465 + if ((ishex && isxdigit_l(c, loc)) || isdigit_l(c, loc))
466 gotmantdig = 1;
467 else {
468 state = S_FRAC;
469 @@ -1030,7 +1087,7 @@
470 goto parsedone;
471 else
472 state = S_EXP;
473 - } else if ((ishex && isxdigit(c)) || isdigit(c)) {
474 + } else if ((ishex && isxdigit_l(c, loc)) || isdigit_l(c, loc)) {
475 commit = p;
476 gotmantdig = 1;
477 } else
478 @@ -1043,7 +1100,7 @@
479 else
480 goto reswitch;
481 case S_EXPDIGITS:
482 - if (isdigit(c))
483 + if (isdigit_l(c, loc))
484 commit = p;
485 else
486 goto parsedone;
487 @@ -1051,6 +1108,17 @@
488 default:
489 abort();
490 }
491 + if (p >= e) {
492 + size_t diff = (p - b);
493 + s += BUF;
494 + b = (char *)reallocf(b, s);
495 + if (b == NULL) {
496 + *buf = NULL;
497 + return 0;
498 + }
499 + e = b + (s - 1);
500 + p = b + diff;
501 + }
502 *p++ = c;
503 if (--fp->_r > 0)
504 fp->_p++;
505 @@ -1062,6 +1130,7 @@
506 while (commit < --p)
507 __ungetc(*(u_char *)p, fp);
508 *++commit = '\0';
509 - return (commit - buf);
510 + *buf = b;
511 + return (commit - b);
512 }
513 #endif