]> git.saurik.com Git - apple/libc.git/blob - stdio/FreeBSD/vfscanf.c.patch
Libc-498.1.5.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-05-20 00:46:37.000000000 -0700
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 (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,48 @@
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 goto match_failure;
307 if ((flags & SUPPRESS) == 0) {
308 if (flags & LONGDBL) {
309 - long double res = strtold(buf, &p);
310 + long double res = strtold_l(pbuf, &p, loc);
311 *va_arg(ap, long double *) = res;
312 } else if (flags & LONG) {
313 - double res = strtod(buf, &p);
314 + double res = strtod_l(pbuf, &p, loc);
315 *va_arg(ap, double *) = res;
316 } else {
317 - float res = strtof(buf, &p);
318 + float res = strtof_l(pbuf, &p, loc);
319 *va_arg(ap, float *) = res;
320 }
321 - if (__scanfdebug && p - buf != width)
322 + if (__scanfdebug && p - pbuf != width)
323 abort();
324 nassigned++;
325 }
326 nread += width;
327 - nconversions++;
328 break;
329 + }
330 #endif /* !NO_FLOATING_POINT */
331 }
332 }
333 input_failure:
334 - return (nconversions != 0 ? nassigned : EOF);
335 + return (nassigned ? nassigned : EOF);
336 match_failure:
337 return (nassigned);
338 }
339
340 +int
341 +__svfscanf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
342 +{
343 + return __svfscanf_l(fp, __current_locale(), fmt0, ap);
344 +}
345 +
346 /*
347 * Fill in the given table from the scanset at the given format
348 * (just after `['). Return a pointer to the character past the
349 @@ -807,9 +849,10 @@
350 * considered part of the scanset.
351 */
352 static const u_char *
353 -__sccl(tab, fmt)
354 +__sccl(tab, fmt, loc)
355 char *tab;
356 const u_char *fmt;
357 + locale_t loc;
358 {
359 int c, n, v, i;
360
361 @@ -845,6 +888,7 @@
362 return (fmt - 1);
363
364 case '-':
365 + {
366 /*
367 * A scanset of the form
368 * [01+-]
369 @@ -865,8 +909,8 @@
370 */
371 n = *fmt;
372 if (n == ']'
373 - || (__collate_load_error ? n < c :
374 - __collate_range_cmp (n, c) < 0
375 + || (loc->__collate_load_error ? n < c :
376 + __collate_range_cmp (n, c, loc) < 0
377 )
378 ) {
379 c = '-';
380 @@ -874,14 +918,14 @@
381 }
382 fmt++;
383 /* fill in the range */
384 - if (__collate_load_error) {
385 + if (loc->__collate_load_error) {
386 do {
387 tab[++c] = v;
388 } while (c < n);
389 } else {
390 for (i = 0; i < 256; i ++)
391 - if ( __collate_range_cmp (c, i) < 0
392 - && __collate_range_cmp (i, n) <= 0
393 + if ( __collate_range_cmp (c, i, loc) < 0
394 + && __collate_range_cmp (i, n, loc) <= 0
395 )
396 tab[i] = v;
397 }
398 @@ -901,7 +945,7 @@
399 return (fmt);
400 #endif
401 break;
402 -
403 + }
404 case ']': /* end of scanset */
405 return (fmt);
406
407 @@ -915,18 +959,42 @@
408
409 #ifndef NO_FLOATING_POINT
410 static int
411 -parsefloat(FILE *fp, char *buf, char *end)
412 +parsefloat(FILE *fp, char **buf, size_t width, locale_t loc)
413 {
414 char *commit, *p;
415 int infnanpos = 0;
416 enum {
417 S_START, S_GOTSIGN, S_INF, S_NAN, S_MAYBEHEX,
418 - S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS
419 + S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS, S_DECIMAL_POINT
420 } state = S_START;
421 unsigned char c;
422 - char decpt = *localeconv()->decimal_point;
423 + unsigned char *decpt = (unsigned char *)localeconv_l(loc)->decimal_point;
424 + char *decpt_start;
425 _Bool gotmantdig = 0, ishex = 0;
426 -
427 + static char *b = NULL;
428 + static size_t bsiz = 0;
429 + char *e;
430 + size_t s;
431 +
432 + if (bsiz = 0) {
433 + b = (char *)malloc(BUF);
434 + if (b == NULL) {
435 + *buf = NULL;
436 + return 0;
437 + }
438 + bsiz = BUF;
439 + }
440 + s = (width == 0 ? BUF : (width + 1));
441 + if (s > bsiz) {
442 + b = (char *)reallocf(b, s);
443 + if (b == NULL) {
444 + bsiz = 0;
445 + *buf = NULL;
446 + return 0;
447 + }
448 + bsiz = s;
449 + }
450 + e = b + (s - 1);
451 /*
452 * We set commit = p whenever the string we have read so far
453 * constitutes a valid representation of a floating point
454 @@ -936,8 +1004,8 @@
455 * always necessary to read at least one character that doesn't
456 * match; thus, we can't short-circuit "infinity" or "nan(...)".
457 */
458 - commit = buf - 1;
459 - for (p = buf; p < end; ) {
460 + commit = b - 1;
461 + for (p = b; width == 0 || p < e; ) {
462 c = *fp->_p;
463 reswitch:
464 switch (state) {
465 @@ -997,7 +1065,7 @@
466 if (c == ')') {
467 commit = p;
468 infnanpos = -2;
469 - } else if (!isalnum(c) && c != '_')
470 + } else if (!isalnum_l(c, loc) && c != '_')
471 goto parsedone;
472 break;
473 }
474 @@ -1013,16 +1081,33 @@
475 goto reswitch;
476 }
477 case S_DIGITS:
478 - if ((ishex && isxdigit(c)) || isdigit(c))
479 + if ((ishex && isxdigit_l(c, loc)) || isdigit_l(c, loc))
480 gotmantdig = 1;
481 else {
482 - state = S_FRAC;
483 - if (c != decpt)
484 - goto reswitch;
485 + state = S_DECIMAL_POINT;
486 + decpt_start = p;
487 + goto reswitch;
488 }
489 if (gotmantdig)
490 commit = p;
491 break;
492 + case S_DECIMAL_POINT:
493 + if (*decpt == 0) {
494 + if (gotmantdig)
495 + commit = p - 1;
496 + state = S_FRAC;
497 + goto reswitch;
498 + }
499 + if (*decpt++ == c)
500 + break;
501 + /* not decimal point */
502 + state = S_FRAC;
503 + if (decpt_start == p)
504 + goto reswitch;
505 + while (decpt_start < --p)
506 + __ungetc(*(u_char *)p, fp);
507 + c = *(u_char *)p;
508 + goto reswitch;
509 case S_FRAC:
510 if (((c == 'E' || c == 'e') && !ishex) ||
511 ((c == 'P' || c == 'p') && ishex)) {
512 @@ -1030,7 +1115,7 @@
513 goto parsedone;
514 else
515 state = S_EXP;
516 - } else if ((ishex && isxdigit(c)) || isdigit(c)) {
517 + } else if ((ishex && isxdigit_l(c, loc)) || isdigit_l(c, loc)) {
518 commit = p;
519 gotmantdig = 1;
520 } else
521 @@ -1043,7 +1128,7 @@
522 else
523 goto reswitch;
524 case S_EXPDIGITS:
525 - if (isdigit(c))
526 + if (isdigit_l(c, loc))
527 commit = p;
528 else
529 goto parsedone;
530 @@ -1051,6 +1136,21 @@
531 default:
532 abort();
533 }
534 + if (p >= e) {
535 + ssize_t diff = (p - b);
536 + ssize_t com = (commit - b);
537 + s += BUF;
538 + b = (char *)reallocf(b, s);
539 + if (b == NULL) {
540 + bsiz = 0;
541 + *buf = NULL;
542 + return 0;
543 + }
544 + bsiz = s;
545 + e = b + (s - 1);
546 + p = b + diff;
547 + commit = b + com;
548 + }
549 *p++ = c;
550 if (--fp->_r > 0)
551 fp->_p++;
552 @@ -1062,6 +1162,7 @@
553 while (commit < --p)
554 __ungetc(*(u_char *)p, fp);
555 *++commit = '\0';
556 - return (commit - buf);
557 + *buf = b;
558 + return (commit - b);
559 }
560 #endif