]> git.saurik.com Git - apple/libc.git/blame - stdio/FreeBSD/vfscanf.c.patch
Libc-498.tar.gz
[apple/libc.git] / stdio / FreeBSD / vfscanf.c.patch
CommitLineData
3d9156a7 1--- vfscanf.c.orig 2004-11-25 11:38:35.000000000 -0800
224c7076 2+++ vfscanf.c 2005-05-20 00:46:37.000000000 -0700
3d9156a7
A
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 */
59e0d9fe
A
14 #define CT_FLOAT 4 /* %[efgEFG] conversion */
15
3d9156a7 16-static const u_char *__sccl(char *, const u_char *);
59e0d9fe 17-static int parsefloat(FILE *, char *, char *);
3d9156a7
A
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 */
59e0d9fe 22
3d9156a7
A
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 */
59e0d9fe 31 int __scanfdebug = 0;
3d9156a7
A
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;
59e0d9fe 55
3d9156a7
A
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 @@
59e0d9fe
A
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 %[...] */
3d9156a7
A
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);
59e0d9fe
A
98 ORIENT(fp, -1);
99
100 nassigned = 0;
101- nconversions = 0;
102 nread = 0;
3d9156a7 103+ va_copy(ap_orig, ap);
59e0d9fe
A
104 for (;;) {
105 c = *fmt++;
3d9156a7
A
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 @@
59e0d9fe
A
144 break;
145
146 case 'n':
147- nconversions++;
148 if (flags & SUPPRESS) /* ??? */
149 continue;
150 if (flags & SHORTSHORT)
3d9156a7
A
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 @@
59e0d9fe
A
179 nread += r;
180 nassigned++;
181 }
182- nconversions++;
183 break;
184
185 case CT_CCL:
3d9156a7
A
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 @@
59e0d9fe
A
216 nassigned++;
217 }
218 nread += n;
219- nconversions++;
220 break;
221
222 case CT_STRING:
3d9156a7
A
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) {
224c7076 229+ while (width != 0) {
3d9156a7
A
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 @@
59e0d9fe
A
271 nread += p - p0;
272 nassigned++;
273 }
274- nconversions++;
275 continue;
276
277 case CT_INT:
3d9156a7
A
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;
224c7076 290@@ -763,43 +800,48 @@
59e0d9fe
A
291 nassigned++;
292 }
293 nread += p - buf;
294- nconversions++;
295 break;
296
3d9156a7 297 #ifndef NO_FLOATING_POINT
59e0d9fe
A
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)
224c7076 305+ if ((width = parsefloat(fp, &pbuf, width, loc)) == 0)
59e0d9fe 306 goto match_failure;
59e0d9fe
A
307 if ((flags & SUPPRESS) == 0) {
308 if (flags & LONGDBL) {
309- long double res = strtold(buf, &p);
3d9156a7 310+ long double res = strtold_l(pbuf, &p, loc);
59e0d9fe
A
311 *va_arg(ap, long double *) = res;
312 } else if (flags & LONG) {
313- double res = strtod(buf, &p);
3d9156a7 314+ double res = strtod_l(pbuf, &p, loc);
59e0d9fe
A
315 *va_arg(ap, double *) = res;
316 } else {
317- float res = strtof(buf, &p);
3d9156a7 318+ float res = strtof_l(pbuf, &p, loc);
59e0d9fe
A
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++;
59e0d9fe
A
328 break;
329+ }
3d9156a7 330 #endif /* !NO_FLOATING_POINT */
59e0d9fe
A
331 }
332 }
333 input_failure:
334- return (nconversions != 0 ? nassigned : EOF);
335+ return (nassigned ? nassigned : EOF);
336 match_failure:
337 return (nassigned);
338 }
59e0d9fe 339
3d9156a7
A
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
224c7076 349@@ -807,9 +849,10 @@
3d9156a7
A
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
224c7076 361@@ -845,6 +888,7 @@
3d9156a7
A
362 return (fmt - 1);
363
364 case '-':
365+ {
366 /*
367 * A scanset of the form
368 * [01+-]
224c7076 369@@ -865,8 +909,8 @@
3d9156a7
A
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 = '-';
224c7076 380@@ -874,14 +918,14 @@
3d9156a7
A
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 }
224c7076 398@@ -901,7 +945,7 @@
3d9156a7
A
399 return (fmt);
400 #endif
401 break;
402-
403+ }
404 case ']': /* end of scanset */
405 return (fmt);
406
224c7076 407@@ -915,18 +959,42 @@
3d9156a7
A
408
409 #ifndef NO_FLOATING_POINT
59e0d9fe
A
410 static int
411-parsefloat(FILE *fp, char *buf, char *end)
3d9156a7 412+parsefloat(FILE *fp, char **buf, size_t width, locale_t loc)
59e0d9fe
A
413 {
414 char *commit, *p;
415 int infnanpos = 0;
224c7076
A
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
3d9156a7 420 } state = S_START;
59e0d9fe 421 unsigned char c;
3d9156a7 422- char decpt = *localeconv()->decimal_point;
224c7076
A
423+ unsigned char *decpt = (unsigned char *)localeconv_l(loc)->decimal_point;
424+ char *decpt_start;
59e0d9fe 425 _Bool gotmantdig = 0, ishex = 0;
224c7076
A
426-
427+ static char *b = NULL;
428+ static size_t bsiz = 0;
429+ char *e;
59e0d9fe 430+ size_t s;
224c7076
A
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;
59e0d9fe
A
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
224c7076 454@@ -936,8 +1004,8 @@
59e0d9fe
A
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) {
224c7076 465@@ -997,7 +1065,7 @@
3d9156a7
A
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 }
224c7076 474@@ -1013,16 +1081,33 @@
3d9156a7
A
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 {
224c7076
A
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 @@
3d9156a7
A
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
224c7076 521@@ -1043,7 +1128,7 @@
3d9156a7
A
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;
224c7076 530@@ -1051,6 +1136,21 @@
59e0d9fe
A
531 default:
532 abort();
533 }
534+ if (p >= e) {
224c7076
A
535+ ssize_t diff = (p - b);
536+ ssize_t com = (commit - b);
59e0d9fe
A
537+ s += BUF;
538+ b = (char *)reallocf(b, s);
539+ if (b == NULL) {
224c7076 540+ bsiz = 0;
59e0d9fe
A
541+ *buf = NULL;
542+ return 0;
543+ }
224c7076 544+ bsiz = s;
59e0d9fe
A
545+ e = b + (s - 1);
546+ p = b + diff;
224c7076 547+ commit = b + com;
59e0d9fe
A
548+ }
549 *p++ = c;
550 if (--fp->_r > 0)
551 fp->_p++;
224c7076 552@@ -1062,6 +1162,7 @@
59e0d9fe
A
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