vfwscanf.c.patch   [plain text]


--- vfwscanf.c.orig	Tue Nov 18 16:48:06 2003
+++ vfwscanf.c	Tue Nov 18 17:36:22 2003
@@ -100,7 +100,9 @@
 #define	CT_INT		3	/* %[dioupxX] conversion */
 #define	CT_FLOAT	4	/* %[efgEFG] conversion */
 
-static int parsefloat(FILE *, wchar_t *, wchar_t *);
+#ifdef FLOATING_POINT
+static int parsefloat(FILE *, wchar_t **, size_t);
+#endif /* FLOATING_POINT */
 
 extern int __scanfdebug;
 
@@ -136,7 +138,6 @@
 	int flags;		/* flags as defined above */
 	wchar_t *p0;		/* saves original value of p when necessary */
 	int nassigned;		/* number of fields assigned */
-	int nconversions;	/* number of conversions */
 	int nread;		/* number of characters consumed from fp */
 	int base;		/* base argument to conversion function */
 	wchar_t buf[BUF];	/* buffer for numeric conversions */
@@ -154,7 +155,6 @@
 		{ 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
 
 	nassigned = 0;
-	nconversions = 0;
 	nread = 0;
 	ccls = ccle = NULL;
 	for (;;) {
@@ -308,7 +308,6 @@
 			break;
 
 		case 'n':
-			nconversions++;
 			if (flags & SUPPRESS)	/* ??? */
 				continue;
 			if (flags & SHORTSHORT)
@@ -411,7 +410,6 @@
 				if (!(flags & SUPPRESS))
 					nassigned++;
 			}
-			nconversions++;
 			break;
 
 		case CT_CCL:
@@ -476,7 +474,6 @@
 				}
 			}
 			nread += n;
-			nconversions++;
 			break;
 
 		case CT_STRING:
@@ -537,7 +534,6 @@
 					nassigned++;
 				}
 			}
-			nconversions++;
 			continue;
 
 		case CT_INT:
@@ -680,47 +676,49 @@
 				nassigned++;
 			}
 			nread += p - buf;
-			nconversions++;
 			break;
 
 #ifdef FLOATING_POINT
 		case CT_FLOAT:
+		{
+			wchar_t *pbuf;
 			/* scan a floating point number as if by strtod */
-			if (width == 0 || width > sizeof(buf) /
-			    sizeof(*buf) - 1)
-				width = sizeof(buf) / sizeof(*buf) - 1;
-			if ((width = parsefloat(fp, buf, buf + width)) == 0)
+			if ((width = parsefloat(fp, &pbuf, width)) == 0) {
+				if (pbuf)
+					free(pbuf);
 				goto match_failure;
+			}
 			if ((flags & SUPPRESS) == 0) {
 				if (flags & LONGDBL) {
-					long double res = wcstold(buf, &p);
+					long double res = wcstold(pbuf, &p);
 					*va_arg(ap, long double *) = res;
 				} else if (flags & LONG) {
-					double res = wcstod(buf, &p);
+					double res = wcstod(pbuf, &p);
 					*va_arg(ap, double *) = res;
 				} else {
-					float res = wcstof(buf, &p);
+					float res = wcstof(pbuf, &p);
 					*va_arg(ap, float *) = res;
 				}
-				if (__scanfdebug && p - buf != width)
+				if (__scanfdebug && p - pbuf != width)
 					abort();
 				nassigned++;
 			}
 			nread += width;
-			nconversions++;
+			free(pbuf);
 			break;
+		}
 #endif /* FLOATING_POINT */
 		}
 	}
 input_failure:
-	return (nconversions != 0 ? nassigned : EOF);
+	return (nassigned ? nassigned : EOF);
 match_failure:
 	return (nassigned);
 }
 
 #ifdef FLOATING_POINT
 static int
-parsefloat(FILE *fp, wchar_t *buf, wchar_t *end)
+parsefloat(FILE *fp, wchar_t **buf, size_t width)
 {
 	wchar_t *commit, *p;
 	int infnanpos = 0;
@@ -731,7 +729,16 @@
 	wchar_t c;
 	wchar_t decpt = (wchar_t)(unsigned char)*localeconv()->decimal_point;
 	_Bool gotmantdig = 0, ishex = 0;
+	wchar_t *b, *e;
+	size_t s;
 
+	s = (width == 0 ? BUF : width + 1);
+	b = (wchar_t *)malloc(s * sizeof(wchar_t));
+	if (b == NULL) {
+		*buf = NULL;
+		return 0;
+	}
+	e = b + (s - 1);
 	/*
 	 * We set commit = p whenever the string we have read so far
 	 * constitutes a valid representation of a floating point
@@ -741,9 +748,9 @@
 	 * always necessary to read at least one character that doesn't
 	 * match; thus, we can't short-circuit "infinity" or "nan(...)".
 	 */
-	commit = buf - 1;
+	commit = b - 1;
 	c = WEOF;
-	for (p = buf; p < end; ) {
+	for (p = b; width == 0 || p < e; ) {
 		if ((c = __fgetwc(fp)) == WEOF)
 			break;
 reswitch:
@@ -858,6 +865,17 @@
 		default:
 			abort();
 		}
+		if (p >= e) {
+			size_t diff = (p - b);
+			s += BUF;
+			b = (wchar_t *)reallocf(b, s * sizeof(wchar_t));
+			if (b == NULL) {
+				*buf = NULL;
+				return 0;
+			}
+			e = b + (s - 1);
+			p = b + diff;
+		}
 		*p++ = c;
 		c = WEOF;
 	}
@@ -868,6 +886,7 @@
 	while (commit < --p)
 		__ungetwc(*p, fp);
 	*++commit = '\0';
-	return (commit - buf);
+	*buf = b;
+	return (commit - b);
 }
 #endif