strptime.c.patch   [plain text]


--- strptime.c.orig	2004-11-25 11:38:45.000000000 -0800
+++ strptime.c	2005-02-24 01:09:32.000000000 -0800
@@ -61,6 +61,8 @@
 #endif /* not lint */
 __FBSDID("$FreeBSD: src/lib/libc/stdtime/strptime.c,v 1.35 2003/11/17 04:19:15 nectar Exp $");
 
+#include "xlocale_private.h"
+
 #include "namespace.h"
 #include <time.h>
 #include <ctype.h>
@@ -72,19 +74,19 @@
 #include "libc_private.h"
 #include "timelocal.h"
 
-static char * _strptime(const char *, const char *, struct tm *, int *);
+static char * _strptime(const char *, const char *, struct tm *, int *, locale_t);
 
 #define asizeof(a)	(sizeof (a) / sizeof ((a)[0]))
 
 static char *
-_strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp)
+_strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp, locale_t loc)
 {
 	char	c;
 	const char *ptr;
 	int	i,
 		len;
 	int Ealternative, Oalternative;
-	struct lc_time_T *tptr = __get_current_time_locale();
+	struct lc_time_T *tptr = __get_current_time_locale(loc);
 
 	ptr = fmt;
 	while (*ptr != 0) {
@@ -94,8 +96,8 @@
 		c = *ptr++;
 
 		if (c != '%') {
-			if (isspace((unsigned char)c))
-				while (*buf != 0 && isspace((unsigned char)*buf))
+			if (isspace_l((unsigned char)c, loc))
+				while (*buf != 0 && isspace_l((unsigned char)*buf, loc))
 					buf++;
 			else if (c != *buf++)
 				return 0;
@@ -114,18 +116,18 @@
 			break;
 
 		case '+':
-			buf = _strptime(buf, tptr->date_fmt, tm, GMTp);
+			buf = _strptime(buf, tptr->date_fmt, tm, GMTp, loc);
 			if (buf == 0)
 				return 0;
 			break;
 
 		case 'C':
-			if (!isdigit((unsigned char)*buf))
+			if (!isdigit_l((unsigned char)*buf, loc))
 				return 0;
 
 			/* XXX This will break for 3-digit centuries. */
 			len = 2;
-			for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+			for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, loc); buf++) {
 				i *= 10;
 				i += *buf - '0';
 				len--;
@@ -137,13 +139,13 @@
 			break;
 
 		case 'c':
-			buf = _strptime(buf, tptr->c_fmt, tm, GMTp);
+			buf = _strptime(buf, tptr->c_fmt, tm, GMTp, loc);
 			if (buf == 0)
 				return 0;
 			break;
 
 		case 'D':
-			buf = _strptime(buf, "%m/%d/%y", tm, GMTp);
+			buf = _strptime(buf, "%m/%d/%y", tm, GMTp, loc);
 			if (buf == 0)
 				return 0;
 			break;
@@ -161,47 +163,47 @@
 			goto label;
 
 		case 'F':
-			buf = _strptime(buf, "%Y-%m-%d", tm, GMTp);
+			buf = _strptime(buf, "%Y-%m-%d", tm, GMTp, loc);
 			if (buf == 0)
 				return 0;
 			break;
 
 		case 'R':
-			buf = _strptime(buf, "%H:%M", tm, GMTp);
+			buf = _strptime(buf, "%H:%M", tm, GMTp, loc);
 			if (buf == 0)
 				return 0;
 			break;
 
 		case 'r':
-			buf = _strptime(buf, tptr->ampm_fmt, tm, GMTp);
+			buf = _strptime(buf, tptr->ampm_fmt, tm, GMTp, loc);
 			if (buf == 0)
 				return 0;
 			break;
 
 		case 'T':
-			buf = _strptime(buf, "%H:%M:%S", tm, GMTp);
+			buf = _strptime(buf, "%H:%M:%S", tm, GMTp, loc);
 			if (buf == 0)
 				return 0;
 			break;
 
 		case 'X':
-			buf = _strptime(buf, tptr->X_fmt, tm, GMTp);
+			buf = _strptime(buf, tptr->X_fmt, tm, GMTp, loc);
 			if (buf == 0)
 				return 0;
 			break;
 
 		case 'x':
-			buf = _strptime(buf, tptr->x_fmt, tm, GMTp);
+			buf = _strptime(buf, tptr->x_fmt, tm, GMTp, loc);
 			if (buf == 0)
 				return 0;
 			break;
 
 		case 'j':
-			if (!isdigit((unsigned char)*buf))
+			if (!isdigit_l((unsigned char)*buf, loc))
 				return 0;
 
 			len = 3;
-			for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+			for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, loc); buf++) {
 				i *= 10;
 				i += *buf - '0';
 				len--;
@@ -214,14 +216,14 @@
 
 		case 'M':
 		case 'S':
-			if (*buf == 0 || isspace((unsigned char)*buf))
+			if (*buf == 0 || isspace_l((unsigned char)*buf, loc))
 				break;
 
-			if (!isdigit((unsigned char)*buf))
+			if (!isdigit_l((unsigned char)*buf, loc))
 				return 0;
 
 			len = 2;
-			for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+			for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, loc); buf++) {
 				i *= 10;
 				i += *buf - '0';
 				len--;
@@ -237,8 +239,8 @@
 				tm->tm_sec = i;
 			}
 
-			if (*buf != 0 && isspace((unsigned char)*buf))
-				while (*ptr != 0 && !isspace((unsigned char)*ptr))
+			if (*buf != 0 && isspace_l((unsigned char)*buf, loc))
+				while (*ptr != 0 && !isspace_l((unsigned char)*ptr, loc))
 					ptr++;
 			break;
 
@@ -254,11 +256,11 @@
 			 * XXX The %l specifier may gobble one too many
 			 * digits if used incorrectly.
 			 */
-			if (!isdigit((unsigned char)*buf))
+			if (!isdigit_l((unsigned char)*buf, loc))
 				return 0;
 
 			len = 2;
-			for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+			for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, loc); buf++) {
 				i *= 10;
 				i += *buf - '0';
 				len--;
@@ -271,8 +273,8 @@
 
 			tm->tm_hour = i;
 
-			if (*buf != 0 && isspace((unsigned char)*buf))
-				while (*ptr != 0 && !isspace((unsigned char)*ptr))
+			if (*buf != 0 && isspace_l((unsigned char)*buf, loc))
+				while (*ptr != 0 && !isspace_l((unsigned char)*ptr, loc))
 					ptr++;
 			break;
 
@@ -282,7 +284,7 @@
 			 * specifiers.
 			 */
 			len = strlen(tptr->am);
-			if (strncasecmp(buf, tptr->am, len) == 0) {
+			if (strncasecmp_l(buf, tptr->am, len, loc) == 0) {
 				if (tm->tm_hour > 12)
 					return 0;
 				if (tm->tm_hour == 12)
@@ -292,7 +294,7 @@
 			}
 
 			len = strlen(tptr->pm);
-			if (strncasecmp(buf, tptr->pm, len) == 0) {
+			if (strncasecmp_l(buf, tptr->pm, len, loc) == 0) {
 				if (tm->tm_hour > 12)
 					return 0;
 				if (tm->tm_hour != 12)
@@ -307,12 +309,12 @@
 		case 'a':
 			for (i = 0; i < asizeof(tptr->weekday); i++) {
 				len = strlen(tptr->weekday[i]);
-				if (strncasecmp(buf, tptr->weekday[i],
-						len) == 0)
+				if (strncasecmp_l(buf, tptr->weekday[i],
+						len, loc) == 0)
 					break;
 				len = strlen(tptr->wday[i]);
-				if (strncasecmp(buf, tptr->wday[i],
-						len) == 0)
+				if (strncasecmp_l(buf, tptr->wday[i],
+						len, loc) == 0)
 					break;
 			}
 			if (i == asizeof(tptr->weekday))
@@ -330,11 +332,11 @@
 			 * point to calculate a real value, so just check the
 			 * range for now.
 			 */
-			if (!isdigit((unsigned char)*buf))
+			if (!isdigit_l((unsigned char)*buf, loc))
 				return 0;
 
 			len = 2;
-			for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+			for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, loc); buf++) {
 				i *= 10;
 				i += *buf - '0';
 				len--;
@@ -342,13 +344,13 @@
 			if (i > 53)
 				return 0;
 
-			if (*buf != 0 && isspace((unsigned char)*buf))
-				while (*ptr != 0 && !isspace((unsigned char)*ptr))
+			if (*buf != 0 && isspace_l((unsigned char)*buf, loc))
+				while (*ptr != 0 && !isspace_l((unsigned char)*ptr, loc))
 					ptr++;
 			break;
 
 		case 'w':
-			if (!isdigit((unsigned char)*buf))
+			if (!isdigit_l((unsigned char)*buf, loc))
 				return 0;
 
 			i = *buf - '0';
@@ -357,8 +359,8 @@
 
 			tm->tm_wday = i;
 
-			if (*buf != 0 && isspace((unsigned char)*buf))
-				while (*ptr != 0 && !isspace((unsigned char)*ptr))
+			if (*buf != 0 && isspace_l((unsigned char)*buf, loc))
+				while (*ptr != 0 && !isspace_l((unsigned char)*ptr, loc))
 					ptr++;
 			break;
 
@@ -372,11 +374,11 @@
 			 * XXX The %e specifier may gobble one too many
 			 * digits if used incorrectly.
 			 */
-			if (!isdigit((unsigned char)*buf))
+			if (!isdigit_l((unsigned char)*buf, loc))
 				return 0;
 
 			len = 2;
-			for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+			for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, loc); buf++) {
 				i *= 10;
 				i += *buf - '0';
 				len--;
@@ -386,8 +388,8 @@
 
 			tm->tm_mday = i;
 
-			if (*buf != 0 && isspace((unsigned char)*buf))
-				while (*ptr != 0 && !isspace((unsigned char)*ptr))
+			if (*buf != 0 && isspace_l((unsigned char)*buf, loc))
+				while (*ptr != 0 && !isspace_l((unsigned char)*ptr, loc))
 					ptr++;
 			break;
 
@@ -398,19 +400,19 @@
 				if (Oalternative) {
 					if (c == 'B') {
 						len = strlen(tptr->alt_month[i]);
-						if (strncasecmp(buf,
+						if (strncasecmp_l(buf,
 								tptr->alt_month[i],
-								len) == 0)
+								len, loc) == 0)
 							break;
 					}
 				} else {
 					len = strlen(tptr->month[i]);
-					if (strncasecmp(buf, tptr->month[i],
-							len) == 0)
+					if (strncasecmp_l(buf, tptr->month[i],
+							len, loc) == 0)
 						break;
 					len = strlen(tptr->mon[i]);
-					if (strncasecmp(buf, tptr->mon[i],
-							len) == 0)
+					if (strncasecmp_l(buf, tptr->mon[i],
+							len, loc) == 0)
 						break;
 				}
 			}
@@ -422,11 +424,11 @@
 			break;
 
 		case 'm':
-			if (!isdigit((unsigned char)*buf))
+			if (!isdigit_l((unsigned char)*buf, loc))
 				return 0;
 
 			len = 2;
-			for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+			for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, loc); buf++) {
 				i *= 10;
 				i += *buf - '0';
 				len--;
@@ -436,8 +438,8 @@
 
 			tm->tm_mon = i - 1;
 
-			if (*buf != 0 && isspace((unsigned char)*buf))
-				while (*ptr != 0 && !isspace((unsigned char)*ptr))
+			if (*buf != 0 && isspace_l((unsigned char)*buf, loc))
+				while (*ptr != 0 && !isspace_l((unsigned char)*ptr, loc))
 					ptr++;
 			break;
 
@@ -450,7 +452,7 @@
 
 			sverrno = errno;
 			errno = 0;
-			n = strtol(buf, &cp, 10);
+			n = strtol_l(buf, &cp, 10, loc);
 			if (errno == ERANGE || (long)(t = n) != n) {
 				errno = sverrno;
 				return 0;
@@ -464,14 +466,14 @@
 
 		case 'Y':
 		case 'y':
-			if (*buf == 0 || isspace((unsigned char)*buf))
+			if (*buf == 0 || isspace_l((unsigned char)*buf, loc))
 				break;
 
-			if (!isdigit((unsigned char)*buf))
+			if (!isdigit_l((unsigned char)*buf, loc))
 				return 0;
 
 			len = (c == 'Y') ? 4 : 2;
-			for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
+			for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, loc); buf++) {
 				i *= 10;
 				i += *buf - '0';
 				len--;
@@ -485,8 +487,8 @@
 
 			tm->tm_year = i;
 
-			if (*buf != 0 && isspace((unsigned char)*buf))
-				while (*ptr != 0 && !isspace((unsigned char)*ptr))
+			if (*buf != 0 && isspace_l((unsigned char)*buf, loc))
+				while (*ptr != 0 && !isspace_l((unsigned char)*ptr, loc))
 					ptr++;
 			break;
 
@@ -495,7 +497,7 @@
 			const char *cp;
 			char *zonestr;
 
-			for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) {/*empty*/}
+			for (cp = buf; *cp && isupper_l((unsigned char)*cp, loc); ++cp) {/*empty*/}
 			if (cp - buf) {
 				zonestr = alloca(cp - buf + 1);
 				strncpy(zonestr, buf, cp - buf);
@@ -528,7 +530,25 @@
 	int gmt;
 
 	gmt = 0;
-	ret = _strptime(buf, fmt, tm, &gmt);
+	ret = _strptime(buf, fmt, tm, &gmt, __current_locale());
+	if (ret && gmt) {
+		time_t t = timegm(tm);
+		localtime_r(&t, tm);
+	}
+
+	return (ret);
+}
+
+char *
+strptime_l(const char * __restrict buf, const char * __restrict fmt,
+    struct tm * __restrict tm, locale_t loc)
+{
+	char *ret;
+	int gmt;
+
+	NORMALIZE_LOCALE(loc);
+	gmt = 0;
+	ret = _strptime(buf, fmt, tm, &gmt, loc);
 	if (ret && gmt) {
 		time_t t = timegm(tm);
 		localtime_r(&t, tm);