]> git.saurik.com Git - apple/libc.git/blobdiff - stdtime/FreeBSD/strptime.c.patch
Libc-763.11.tar.gz
[apple/libc.git] / stdtime / FreeBSD / strptime.c.patch
index 2c6acc50f67fa95856009d54e133e4d929e9a197..5bce7e0b46fa36863638ba79ee955212a74fea3c 100644 (file)
@@ -1,8 +1,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 @@
+--- strptime.c.orig    2009-11-14 13:55:44.000000000 -0800
++++ strptime.c 2009-11-18 16:56:27.000000000 -0800
+@@ -61,41 +61,55 @@ static char sccsid[] __unused = "@(#)str
  #endif /* not lint */
- __FBSDID("$FreeBSD: src/lib/libc/stdtime/strptime.c,v 1.35 2003/11/17 04:19:15 nectar Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdtime/strptime.c,v 1.37 2009/09/02 04:56:30 ache Exp $");
  
 +#include "xlocale_private.h"
 +
  #include <stdlib.h>
  #include <string.h>
  #include <pthread.h>
-@@ -72,30 +75,41 @@
++#include <stdint.h>
++#include <limits.h>
+ #include "un-namespace.h"
  #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) __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};
++
++#define _strptime(b,f,t,c,l)  _strptime0(b,f,t,c,l,-1,0,-1)
 +
  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 *convp, locale_t loc)
++_strptime0(const char *buf, const char *fmt, struct tm *tm, int *convp, locale_t loc, int year, int yday, int wday)
  {
        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();
@@ -50,7 +50,7 @@
 +                      while (isspace_l((unsigned char)*ptr, loc)) {
 +                              ptr++;
 +                      }
-+                      return ((*ptr)==0) ? fmt : 0; /* trailing whitespace is ok */
++                      return ((*ptr)==0) ? (char *)fmt : 0; /* trailing whitespace is ok */
 +              }
  
                c = *ptr++;
@@ -63,7 +63,7 @@
                                        buf++;
                        else if (c != *buf++)
                                return 0;
-@@ -114,18 +128,18 @@
+@@ -114,18 +128,18 @@ label:
                        break;
  
                case '+':
@@ -85,7 +85,7 @@
                                i *= 10;
                                i += *buf - '0';
                                len--;
-@@ -133,17 +147,21 @@
+@@ -133,17 +147,21 @@ label:
                        if (i < 19)
                                return 0;
  
                        if (buf == 0)
                                return 0;
                        break;
-@@ -161,47 +179,55 @@
+@@ -161,47 +179,55 @@ label:
                        goto label;
  
                case 'F':
                                i *= 10;
                                i += *buf - '0';
                                len--;
-@@ -209,19 +235,19 @@
+@@ -209,19 +235,19 @@ label:
                        if (i < 1 || i > 366)
                                return 0;
  
                                i *= 10;
                                i += *buf - '0';
                                len--;
-@@ -237,8 +263,8 @@
+@@ -237,8 +263,8 @@ label:
                                tm->tm_sec = i;
                        }
  
                                        ptr++;
                        break;
  
-@@ -254,11 +280,11 @@
+@@ -254,11 +280,11 @@ label:
                         * XXX The %l specifier may gobble one too many
                         * digits if used incorrectly.
                         */
                                i *= 10;
                                i += *buf - '0';
                                len--;
-@@ -271,8 +297,8 @@
+@@ -271,8 +297,8 @@ label:
  
                        tm->tm_hour = i;
  
                                        ptr++;
                        break;
  
-@@ -282,7 +308,7 @@
+@@ -282,7 +308,7 @@ label:
                         * specifiers.
                         */
                        len = strlen(tptr->am);
                                if (tm->tm_hour > 12)
                                        return 0;
                                if (tm->tm_hour == 12)
-@@ -292,7 +318,7 @@
+@@ -292,7 +318,7 @@ label:
                        }
  
                        len = strlen(tptr->pm);
                                if (tm->tm_hour > 12)
                                        return 0;
                                if (tm->tm_hour != 12)
-@@ -307,34 +333,28 @@
+@@ -307,34 +333,28 @@ label:
                case 'a':
                        for (i = 0; i < asizeof(tptr->weekday); i++) {
                                len = strlen(tptr->weekday[i]);
                                i *= 10;
                                i += *buf - '0';
                                len--;
-@@ -342,23 +362,46 @@
+@@ -342,23 +362,46 @@ label:
                        if (i > 53)
                                return 0;
  
                                        ptr++;
                        break;
  
-@@ -372,11 +415,18 @@
+@@ -372,11 +415,18 @@ label:
                         * XXX The %e specifier may gobble one too many
                         * digits if used incorrectly.
                         */
                                i *= 10;
                                i += *buf - '0';
                                len--;
-@@ -386,8 +436,8 @@
+@@ -386,8 +436,8 @@ label:
  
                        tm->tm_mday = i;
  
                                        ptr++;
                        break;
  
-@@ -398,19 +448,19 @@
+@@ -398,19 +448,19 @@ label:
                                if (Oalternative) {
                                        if (c == 'B') {
                                                len = strlen(tptr->alt_month[i]);
                                                break;
                                }
                        }
-@@ -422,11 +472,11 @@
+@@ -422,11 +472,11 @@ label:
                        break;
  
                case 'm':
                                i *= 10;
                                i += *buf - '0';
                                len--;
-@@ -436,8 +486,8 @@
+@@ -436,8 +486,8 @@ label:
  
                        tm->tm_mon = i - 1;
  
                                        ptr++;
                        break;
  
-@@ -450,7 +500,7 @@
+@@ -450,7 +500,7 @@ label:
  
                        sverrno = errno;
                        errno = 0;
                        if (errno == ERANGE || (long)(t = n) != n) {
                                errno = sverrno;
                                return 0;
-@@ -458,24 +508,37 @@
+@@ -458,24 +508,82 @@ label:
                        errno = sverrno;
                        buf = cp;
                        gmtime_r(&t, tm);
  
 +#if __DARWIN_UNIX03
 +                      if (c == 'Y') {
-+                              for (i = 0; *buf != 0 && isdigit_l((unsigned char)*buf, loc); buf++) {
-+                                      i *= 10;
-+                                      i += *buf - '0';
++                              int savei = 0;
++                              const char *savebuf = buf;
++                              int64_t i64 = 0;
++                              int overflow = 0;
++
++                              for (len = 0; *buf != 0 && isdigit_l((unsigned char)*buf, loc); buf++) {
++                                      i64 *= 10;
++                                      i64 += *buf - '0';
++                                      if (++len <= 4) {
++                                              savei = i64;
++                                              savebuf = buf + 1;
++                                      }
++                                      if (i64 > INT_MAX) {
++                                              overflow++;
++                                              break;
++                                      }
++                              }
++                              /*
++                               * Conformance requires %Y to be more then 4
++                               * digits.  However, there are several cases
++                               * where %Y is immediately followed by other
++                               * digits values.  So we do the conformance
++                               * case first (as many digits as possible),
++                               * and if we fail, we backup and try just 4
++                               * digits for %Y.
++                               */
++                              if (len > 4 && !overflow) {
++                                      struct tm savetm = *tm;
++                                      int saveconv = *convp;
++                                      const char *saveptr = ptr;
++                                      char *ret;
++
++                                      if (i64 < 1900)
++                                              return 0;
++
++                                      tm->tm_year = i64 - 1900;
++
++                                      if (*buf != 0 && isspace_l((unsigned char)*buf, loc))
++                                              while (*ptr != 0 && !isspace_l((unsigned char)*ptr, loc) && *ptr != '%')
++                                                      ptr++;
++                                      ret = _strptime0(buf, ptr, tm, convp, loc, tm->tm_year, yday, wday);
++                                      if (ret) return ret;
++                                      /* Failed, so try 4-digit year */
++                                      *tm = savetm;
++                                      *convp = saveconv;
++                                      ptr = saveptr;
 +                              }
++                              buf = savebuf;
++                              i = savei;
 +                      } else {
 +                              len = 2;
 +#else /* !__DARWIN_UNIX03 */
                        if (c == 'Y')
                                i -= 1900;
                        if (c == 'y' && i < 69)
-@@ -483,10 +546,10 @@
+@@ -483,37 +591,40 @@ label:
                        if (i < 0)
                                return 0;
  
                                        ptr++;
                        break;
  
-@@ -502,7 +565,7 @@
-                               zonestr[cp - buf] = '\0';
-                               tzset();
-                               if (0 == strcmp(zonestr, "GMT")) {
+               case 'Z':
+                       {
+                       const char *cp;
+-                      char *zonestr;
++                      size_t tzlen, len;
+                       for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) {/*empty*/}
+-                      if (cp - buf) {
+-                              zonestr = alloca(cp - buf + 1);
+-                              strncpy(zonestr, buf, cp - buf);
+-                              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 @@
+-                              } else if (0 == strcmp(zonestr, tzname[0])) {
+-                                  tm->tm_isdst = 0;
+-                              } else if (0 == strcmp(zonestr, tzname[1])) {
+-                                  tm->tm_isdst = 1;
+-                              } else {
+-                                  return 0;
+-                              }
+-                              buf += cp - buf;
++                      len = cp - buf;
++                      if (len == 3 && strncmp(buf, "GMT", 3) == 0) {
++                              *convp = CONVERT_GMT;
++                              buf += len;
++                              break;
                        }
++                      tzset();
++                      tzlen = strlen(tzname[0]);
++                      if (len == tzlen && strncmp(buf, tzname[0], tzlen) == 0) {
++                              tm->tm_isdst = 0;
++                              buf += len;
++                              break;
++                      }
++                      tzlen = strlen(tzname[1]);
++                      if (len == tzlen && strncmp(buf, tzname[1], tzlen) == 0) {
++                              tm->tm_isdst = 1;
++                              buf += len;
++                              break;
++                      }
++                      return 0;
+                       }
+-                      break;
+               case 'z':
+                       {
+@@ -529,7 +640,7 @@ label:
+                       buf++;
+                       i = 0;
+                       for (len = 4; len > 0; len--) {
+-                              if (isdigit((unsigned char)*buf)) {
++                              if (isdigit_l((unsigned char)*buf, loc)) {
+                                       i *= 10;
+                                       i += *buf - '0';
+                                       buf++;
+@@ -539,7 +650,7 @@ label:
+                       tm->tm_hour -= sign * (i / 100);
+                       tm->tm_min  -= sign * (i % 100);
+-                      *GMTp = 1;
++                      *convp = CONVERT_GMT;
                        }
                        break;
-+
-+              case 'z':
-+                      {
-+                      char sign;
-+                      int hr, min;
-+
-+                      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 @@
+@@ -552,14 +663,39 @@ char *
  strptime(const char * __restrict buf, const char * __restrict fmt,
      struct tm * __restrict tm)
  {