---- 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 @@
+--- strptime.c.orig 2007-04-03 12:19:24.000000000 -0700
++++ strptime.c 2007-04-03 12:39:20.000000000 -0700
+@@ -61,10 +61,13 @@
#endif /* not lint */
__FBSDID("$FreeBSD: src/lib/libc/stdtime/strptime.c,v 1.35 2003/11/17 04:19:15 nectar Exp $");
#include "namespace.h"
#include <time.h>
#include <ctype.h>
-@@ -72,19 +74,19 @@
+ #include <errno.h>
++#include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <pthread.h>
+@@ -72,30 +75,41 @@
#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);
++static char * _strptime(const char *, const char *, struct tm *, int *, locale_t) __DARWIN_ALIAS(_strptime);
++time_t _mktime(struct tm *, const char *);
#define asizeof(a) (sizeof (a) / sizeof ((a)[0]))
++enum {CONVERT_NONE, CONVERT_GMT, CONVERT_ZONE};
++
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)
++_strptime(const char *buf, const char *fmt, struct tm *tm, int *convp, locale_t loc)
{
char c;
const char *ptr;
int i,
++ year = -1,
++ yday = 0,
++ wday = -1,
len;
int Ealternative, Oalternative;
- struct lc_time_T *tptr = __get_current_time_locale();
ptr = fmt;
while (*ptr != 0) {
-@@ -94,8 +96,8 @@
+- if (*buf == 0)
+- break;
++ if (*buf == 0) {
++ fmt = ptr;
++ while (isspace_l((unsigned char)*ptr, loc)) {
++ ptr++;
++ }
++ return ((*ptr)==0) ? fmt : 0; /* trailing whitespace is ok */
++ }
+
c = *ptr++;
if (c != '%') {
buf++;
else if (c != *buf++)
return 0;
-@@ -114,18 +116,18 @@
+@@ -114,18 +128,18 @@
break;
case '+':
- buf = _strptime(buf, tptr->date_fmt, tm, GMTp);
-+ buf = _strptime(buf, tptr->date_fmt, tm, GMTp, loc);
++ buf = _strptime(buf, tptr->date_fmt, tm, convp, loc);
if (buf == 0)
return 0;
break;
i *= 10;
i += *buf - '0';
len--;
-@@ -137,13 +139,13 @@
+@@ -133,17 +147,21 @@
+ if (i < 19)
+ return 0;
+
++ if (year != -1)
++ tm->tm_year = (year % 100) + i * 100 - 1900;
++ else
+ tm->tm_year = i * 100 - 1900;
++ year = tm->tm_year;
break;
case 'c':
- buf = _strptime(buf, tptr->c_fmt, tm, GMTp);
-+ buf = _strptime(buf, tptr->c_fmt, tm, GMTp, loc);
++ buf = _strptime(buf, tptr->c_fmt, tm, convp, 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);
++ buf = _strptime(buf, "%m/%d/%y", tm, convp, loc);
if (buf == 0)
return 0;
break;
-@@ -161,47 +163,47 @@
+@@ -161,47 +179,55 @@
goto label;
case 'F':
- buf = _strptime(buf, "%Y-%m-%d", tm, GMTp);
-+ buf = _strptime(buf, "%Y-%m-%d", tm, GMTp, loc);
++ buf = _strptime(buf, "%Y-%m-%d", tm, convp, loc);
if (buf == 0)
return 0;
break;
case 'R':
- buf = _strptime(buf, "%H:%M", tm, GMTp);
-+ buf = _strptime(buf, "%H:%M", tm, GMTp, loc);
++ buf = _strptime(buf, "%H:%M", tm, convp, 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);
++ buf = _strptime(buf, tptr->ampm_fmt, tm, convp, loc);
if (buf == 0)
return 0;
break;
++ case 'n':
++ case 't':
++ if (!isspace((unsigned char)*buf))
++ return 0;
++ while (isspace((unsigned char)*buf))
++ buf++;
++ break;
++
case 'T':
- buf = _strptime(buf, "%H:%M:%S", tm, GMTp);
-+ buf = _strptime(buf, "%H:%M:%S", tm, GMTp, loc);
++ buf = _strptime(buf, "%H:%M:%S", tm, convp, 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);
++ buf = _strptime(buf, tptr->X_fmt, tm, convp, 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);
++ buf = _strptime(buf, tptr->x_fmt, tm, convp, loc);
if (buf == 0)
return 0;
break;
i *= 10;
i += *buf - '0';
len--;
-@@ -214,14 +216,14 @@
+@@ -209,19 +235,19 @@
+ if (i < 1 || i > 366)
+ return 0;
+
+- tm->tm_yday = i - 1;
++ tm->tm_yday = yday = i - 1;
+ break;
case 'M':
case 'S':
i *= 10;
i += *buf - '0';
len--;
-@@ -237,8 +239,8 @@
+@@ -237,8 +263,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))
++ while (*ptr != 0 && !isspace_l((unsigned char)*ptr, loc) && *ptr != '%')
ptr++;
break;
-@@ -254,11 +256,11 @@
+@@ -254,11 +280,11 @@
* XXX The %l specifier may gobble one too many
* digits if used incorrectly.
*/
i *= 10;
i += *buf - '0';
len--;
-@@ -271,8 +273,8 @@
+@@ -271,8 +297,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))
++ while (*ptr != 0 && !isspace_l((unsigned char)*ptr, loc) && *ptr != '%')
ptr++;
break;
-@@ -282,7 +284,7 @@
+@@ -282,7 +308,7 @@
* specifiers.
*/
len = strlen(tptr->am);
if (tm->tm_hour > 12)
return 0;
if (tm->tm_hour == 12)
-@@ -292,7 +294,7 @@
+@@ -292,7 +318,7 @@
}
len = strlen(tptr->pm);
if (tm->tm_hour > 12)
return 0;
if (tm->tm_hour != 12)
-@@ -307,12 +309,12 @@
+@@ -307,34 +333,28 @@
case 'a':
for (i = 0; i < asizeof(tptr->weekday); i++) {
len = strlen(tptr->weekday[i]);
break;
}
if (i == asizeof(tptr->weekday))
-@@ -330,11 +332,11 @@
- * point to calculate a real value, so just check the
- * range for now.
- */
+ return 0;
+
+- tm->tm_wday = i;
++ tm->tm_wday = wday = i;
+ buf += len;
+ break;
+
+- case 'U':
+- case 'W':
+- /*
+- * XXX This is bogus, as we can not assume any valid
+- * information present in the tm structure at this
+- * point to calculate a real value, so just check the
+- * range for now.
+- */
- if (!isdigit((unsigned char)*buf))
++ case 'U': /* Sunday week */
++ case 'W': /* Monday week */
+ if (!isdigit_l((unsigned char)*buf, loc))
return 0;
i *= 10;
i += *buf - '0';
len--;
-@@ -342,13 +344,13 @@
+@@ -342,23 +362,46 @@
if (i > 53)
return 0;
- if (*buf != 0 && isspace((unsigned char)*buf))
- while (*ptr != 0 && !isspace((unsigned char)*ptr))
++ /* Calculate yday if we have enough data */
++ if ((year != -1) && (wday != -1)) {
++ struct tm mktm;
++ mktm.tm_year = year;
++ mktm.tm_mon = 0;
++ mktm.tm_mday = 1;
++ mktm.tm_sec = 1;
++ mktm.tm_min = mktm.tm_hour = 0;
++ mktm.tm_isdst = 0;
++ mktm.tm_gmtoff = 0;
++ if (mktime(&mktm) != -1) {
++ /* yday0 == Jan 1 == mktm.tm_wday */
++ int delta = wday - mktm.tm_wday;
++ if (!wday && c =='W')
++ i++; /* Sunday is part of the following week */
++ yday = 7 * i + delta;
++ if (yday < 0)
++ yday += 7;
++ tm->tm_yday = yday;
++ }
++ }
+ if (*buf != 0 && isspace_l((unsigned char)*buf, loc))
-+ while (*ptr != 0 && !isspace_l((unsigned char)*ptr, loc))
++ while (*ptr != 0 && !isspace_l((unsigned char)*ptr, loc) && *ptr != '%')
ptr++;
break;
- case 'w':
+- case 'w':
- if (!isdigit((unsigned char)*buf))
++ case 'u': /* [1,7] */
++ case 'w': /* [0,6] */
+ if (!isdigit_l((unsigned char)*buf, loc))
return 0;
i = *buf - '0';
-@@ -357,8 +359,8 @@
-
- tm->tm_wday = i;
-
+- if (i > 6)
++ if (i > 6 + (c == 'u'))
+ return 0;
+-
+- tm->tm_wday = i;
+-
- if (*buf != 0 && isspace((unsigned char)*buf))
- while (*ptr != 0 && !isspace((unsigned char)*ptr))
++ if (i == 7)
++ i = 0;
++ tm->tm_wday = wday = i;
++ buf++;
+ if (*buf != 0 && isspace_l((unsigned char)*buf, loc))
-+ while (*ptr != 0 && !isspace_l((unsigned char)*ptr, loc))
++ while (*ptr != 0 && !isspace_l((unsigned char)*ptr, loc) && *ptr != '%')
ptr++;
break;
-@@ -372,11 +374,11 @@
+@@ -372,11 +415,18 @@
* XXX The %e specifier may gobble one too many
* digits if used incorrectly.
*/
- if (!isdigit((unsigned char)*buf))
++ /* Leading space is ok if date is single digit */
++ len = 2;
++ if (isspace_l((unsigned char)buf[0], loc) &&
++ isdigit_l((unsigned char)buf[1], loc) &&
++ !isdigit_l((unsigned char)buf[2], loc)) {
++ len = 1;
++ buf++;
++ }
+ if (!isdigit_l((unsigned char)*buf, loc))
return 0;
- len = 2;
+- 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 @@
+@@ -386,8 +436,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))
++ while (*ptr != 0 && !isspace_l((unsigned char)*ptr, loc) && *ptr != '%')
ptr++;
break;
-@@ -398,19 +400,19 @@
+@@ -398,19 +448,19 @@
if (Oalternative) {
if (c == 'B') {
len = strlen(tptr->alt_month[i]);
break;
}
}
-@@ -422,11 +424,11 @@
+@@ -422,11 +472,11 @@
break;
case 'm':
i *= 10;
i += *buf - '0';
len--;
-@@ -436,8 +438,8 @@
+@@ -436,8 +486,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))
++ while (*ptr != 0 && !isspace_l((unsigned char)*ptr, loc) && *ptr != '%')
ptr++;
break;
-@@ -450,7 +452,7 @@
+@@ -450,7 +500,7 @@
sverrno = errno;
errno = 0;
if (errno == ERANGE || (long)(t = n) != n) {
errno = sverrno;
return 0;
-@@ -464,14 +466,14 @@
+@@ -458,24 +508,37 @@
+ errno = sverrno;
+ buf = cp;
+ gmtime_r(&t, tm);
+- *GMTp = 1;
++ *convp = CONVERT_GMT;
+ }
+ break;
case 'Y':
case 'y':
+ if (!isdigit_l((unsigned char)*buf, loc))
return 0;
++#if __DARWIN_UNIX03
++ if (c == 'Y') {
++ for (i = 0; *buf != 0 && isdigit_l((unsigned char)*buf, loc); buf++) {
++ i *= 10;
++ i += *buf - '0';
++ }
++ } else {
++ len = 2;
++#else /* !__DARWIN_UNIX03 */
len = (c == 'Y') ? 4 : 2;
- for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) {
++#endif /* __DARWIN_UNIX03 */
+ for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, loc); buf++) {
i *= 10;
i += *buf - '0';
len--;
-@@ -485,8 +487,8 @@
+ }
++#if __DARWIN_UNIX03
++ }
++#endif /* __DARWIN_UNIX03 */
+ if (c == 'Y')
+ i -= 1900;
+ if (c == 'y' && i < 69)
+@@ -483,10 +546,10 @@
+ if (i < 0)
+ return 0;
- tm->tm_year = i;
+- tm->tm_year = i;
++ tm->tm_year = 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))
++ while (*ptr != 0 && !isspace_l((unsigned char)*ptr, loc) && *ptr != '%')
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);
-+ }
+@@ -502,7 +565,7 @@
+ zonestr[cp - buf] = '\0';
+ tzset();
+ if (0 == strcmp(zonestr, "GMT")) {
+- *GMTp = 1;
++ *convp = CONVERT_GMT;
+ } else if (0 == strcmp(zonestr, tzname[0])) {
+ tm->tm_isdst = 0;
+ } else if (0 == strcmp(zonestr, tzname[1])) {
+@@ -514,6 +577,26 @@
+ }
+ }
+ break;
++
++ case 'z':
++ {
++ char sign;
++ int hr, min;
+
-+ return (ret);
++ if ((buf[0] != '+' && buf[0] != '-')
++ || !isdigit_l((unsigned char)buf[1], loc)
++ || !isdigit_l((unsigned char)buf[2], loc)
++ || !isdigit_l((unsigned char)buf[3], loc)
++ || !isdigit_l((unsigned char)buf[4], loc))
++ return 0;
++ sscanf(buf, "%c%2d%2d", &sign, &hr, &min);
++ *convp = CONVERT_ZONE;
++ tm->tm_gmtoff = 60 * (60 * hr + min);
++ if (sign == '-')
++ tm->tm_gmtoff = -tm->tm_gmtoff;
++ buf += 5;
++ }
++ break;
+ }
+ }
+ return (char *)buf;
+@@ -524,14 +607,39 @@
+ strptime(const char * __restrict buf, const char * __restrict fmt,
+ struct tm * __restrict tm)
+ {
++ return strptime_l(buf, fmt, tm, __current_locale());
+}
+
++extern time_t timeoff(struct tm *, long);
++
+char *
+strptime_l(const char * __restrict buf, const char * __restrict fmt,
+ struct tm * __restrict tm, locale_t loc)
+{
-+ char *ret;
-+ int gmt;
-+
+ char *ret;
+- int gmt;
++ int conv;
+
+- gmt = 0;
+- ret = _strptime(buf, fmt, tm, &gmt);
+- if (ret && gmt) {
+- time_t t = timegm(tm);
+- localtime_r(&t, tm);
+ NORMALIZE_LOCALE(loc);
-+ gmt = 0;
-+ ret = _strptime(buf, fmt, tm, &gmt, loc);
- if (ret && gmt) {
- time_t t = timegm(tm);
- localtime_r(&t, tm);
++ conv = CONVERT_NONE;
++ tm->tm_zone = NULL;
++ ret = _strptime(buf, fmt, tm, &conv, loc);
++ if (ret) {
++ time_t t;
++
++ switch(conv) {
++ case CONVERT_GMT:
++ t = timegm(tm);
++ localtime_r(&t, tm);
++ break;
++ case CONVERT_ZONE:
++ {
++ long offset = tm->tm_gmtoff;
++ tm->tm_gmtoff = 0;
++ t = timeoff(tm, offset);
++ localtime_r(&t, tm);
++ break;
++ }
++ }
+ }
+
+ return (ret);