svn commit: r272273 - head/lib/libc/stdtime

Antoine Brodin antoine at freebsd.org
Wed Oct 1 16:46:29 UTC 2014


On Sun, Sep 28, 2014 at 11:20 PM, Pedro F. Giffuni <pfg at freebsd.org> wrote:
> Author: pfg
> Date: Sun Sep 28 21:20:20 2014
> New Revision: 272273
> URL: http://svnweb.freebsd.org/changeset/base/272273
>
> Log:
>   Add strptime(3) support for %U and %W (take 2)
>
>   Add support for the missing POSIX-2001 %U and %W features: the
>   existing FreeBSD strptime code recognizes both directives and
>   validates that the week number lies in the permitted range,
>   but then simply discards the value.
>
>   Initial support for the feature was written by Paul Green.
>   David Carlier added the initial handling of tm_wday/tm_yday.
>   Major credit goes to Andrey Chernov for detecting much of the
>   brokenness, and rewriting/cleaning most of the code, making it
>   much more robust.
>
>   Tested independently with the strptime test from the GNU C
>   library.
>
>   PR:           137307
>   MFC after:    1 month
>   Relnotes:     yes

Hi,

It seems this change breaks some ports,  so please no MFC until this is fixed:

http://gohan2.ysv.freebsd.org/data/head-amd64-default-baseline/p369565_s272290/logs/errors/latrine-1.0.0_1.log
http://gohan2.ysv.freebsd.org/data/head-amd64-default-baseline/p369565_s272290/logs/errors/mongrel2-1.7.5_2.log
http://gohan2.ysv.freebsd.org/data/head-amd64-default-baseline/p369565_s272290/logs/errors/deforaos-mailer-0.1.6_1.log

Cheers,

Antoine (portmgr hat on)


>
> Modified:
>   head/lib/libc/stdtime/strptime.c
>
> Modified: head/lib/libc/stdtime/strptime.c
> ==============================================================================
> --- head/lib/libc/stdtime/strptime.c    Sun Sep 28 21:15:30 2014        (r272272)
> +++ head/lib/libc/stdtime/strptime.c    Sun Sep 28 21:20:20 2014        (r272273)
> @@ -55,10 +55,32 @@ __FBSDID("$FreeBSD$");
>  #include "un-namespace.h"
>  #include "libc_private.h"
>  #include "timelocal.h"
> -
> +#include "tzfile.h"
> +#include <stdio.h>
>  static char * _strptime(const char *, const char *, struct tm *, int *, locale_t);
>
> -#define        asizeof(a)      (sizeof (a) / sizeof ((a)[0]))
> +#define        asizeof(a)      (sizeof(a) / sizeof((a)[0]))
> +
> +#define        FLAG_NONE       (1 << 0)
> +#define        FLAG_YEAR       (1 << 1)
> +#define        FLAG_MONTH      (1 << 2)
> +#define        FLAG_YDAY       (1 << 3)
> +#define        FLAG_MDAY       (1 << 4)
> +#define        FLAG_WDAY       (1 << 5)
> +
> +/*
> + * Calculate the week day of the first day of a year. Valid for
> + * the Gregorian calendar, which began Sept 14, 1752 in the UK
> + * and its colonies. Ref:
> + * http://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week
> + */
> +
> +static int
> +first_wday_of(int year)
> +{
> +       return (((2 * (3 - (year / 100) % 4)) + (year % 100) +
> +               ((year % 100) / 4) + (isleap(year) ? 6 : 0) + 1) % 7);
> +}
>
>  static char *
>  _strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp,
> @@ -66,9 +88,18 @@ _strptime(const char *buf, const char *f
>  {
>         char    c;
>         const char *ptr;
> +       int     day_offset = -1, wday_offset;
> +       int week_offset;
>         int     i, len;
> +       int flags;
>         int Ealternative, Oalternative;
> -       struct lc_time_T *tptr = __get_current_time_locale(locale);
> +       const struct lc_time_T *tptr = __get_current_time_locale(locale);
> +       static int start_of_month[2][13] = {
> +               {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
> +               {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
> +       };
> +
> +       flags = FLAG_NONE;
>
>         ptr = fmt;
>         while (*ptr != 0) {
> @@ -102,6 +133,7 @@ label:
>                         buf = _strptime(buf, tptr->date_fmt, tm, GMTp, locale);
>                         if (buf == NULL)
>                                 return (NULL);
> +                       flags |= FLAG_WDAY | FLAG_MONTH | FLAG_MDAY | FLAG_YEAR;
>                         break;
>
>                 case 'C':
> @@ -119,19 +151,23 @@ label:
>                         if (i < 19)
>                                 return (NULL);
>
> -                       tm->tm_year = i * 100 - 1900;
> +                       tm->tm_year = i * 100 - TM_YEAR_BASE;
> +                       flags |= FLAG_YEAR;
> +
>                         break;
>
>                 case 'c':
>                         buf = _strptime(buf, tptr->c_fmt, tm, GMTp, locale);
>                         if (buf == NULL)
>                                 return (NULL);
> +                       flags |= FLAG_WDAY | FLAG_MONTH | FLAG_MDAY | FLAG_YEAR;
>                         break;
>
>                 case 'D':
>                         buf = _strptime(buf, "%m/%d/%y", tm, GMTp, locale);
>                         if (buf == NULL)
>                                 return (NULL);
> +                       flags |= FLAG_MONTH | FLAG_MDAY | FLAG_YEAR;
>                         break;
>
>                 case 'E':
> @@ -150,6 +186,7 @@ label:
>                         buf = _strptime(buf, "%Y-%m-%d", tm, GMTp, locale);
>                         if (buf == NULL)
>                                 return (NULL);
> +                       flags |= FLAG_MONTH | FLAG_MDAY | FLAG_YEAR;
>                         break;
>
>                 case 'R':
> @@ -180,6 +217,7 @@ label:
>                         buf = _strptime(buf, tptr->x_fmt, tm, GMTp, locale);
>                         if (buf == NULL)
>                                 return (NULL);
> +                       flags |= FLAG_MONTH | FLAG_MDAY | FLAG_YEAR;
>                         break;
>
>                 case 'j':
> @@ -197,6 +235,8 @@ label:
>                                 return (NULL);
>
>                         tm->tm_yday = i - 1;
> +                       flags |= FLAG_YDAY;
> +
>                         break;
>
>                 case 'M':
> @@ -303,7 +343,7 @@ label:
>                                 return (NULL);
>
>                         tm->tm_wday = i;
> -                       buf += len;
> +                       flags |= FLAG_WDAY;
>                         break;
>
>                 case 'U':
> @@ -327,6 +367,14 @@ label:
>                         if (i > 53)
>                                 return (NULL);
>
> +                       if (c == 'U')
> +                               day_offset = TM_SUNDAY;
> +                       else
> +                               day_offset = TM_MONDAY;
> +
> +
> +                       week_offset = i;
> +
>                         break;
>
>                 case 'w':
> @@ -338,6 +386,7 @@ label:
>                                 return (NULL);
>
>                         tm->tm_wday = i;
> +                       flags |= FLAG_WDAY;
>
>                         break;
>
> @@ -374,6 +423,7 @@ label:
>                                 return (NULL);
>
>                         tm->tm_mday = i;
> +                       flags |= FLAG_MDAY;
>
>                         break;
>
> @@ -413,6 +463,8 @@ label:
>
>                         tm->tm_mon = i;
>                         buf += len;
> +                       flags |= FLAG_MONTH;
> +
>                         break;
>
>                 case 'm':
> @@ -430,6 +482,7 @@ label:
>                                 return (NULL);
>
>                         tm->tm_mon = i - 1;
> +                       flags |= FLAG_MONTH;
>
>                         break;
>
> @@ -471,13 +524,14 @@ label:
>                                 len--;
>                         }
>                         if (c == 'Y')
> -                               i -= 1900;
> +                               i -= TM_YEAR_BASE;
>                         if (c == 'y' && i < 69)
>                                 i += 100;
>                         if (i < 0)
>                                 return (NULL);
>
>                         tm->tm_year = i;
> +                       flags |= FLAG_YEAR;
>
>                         break;
>
> @@ -543,10 +597,67 @@ label:
>                         break;
>                 }
>         }
> +
> +       if (!(flags & FLAG_YDAY) && (flags & FLAG_YEAR)) {
> +               if ((flags & (FLAG_MONTH | FLAG_MDAY)) ==
> +                   (FLAG_MONTH | FLAG_MDAY)) {
> +                       tm->tm_yday = start_of_month[isleap(tm->tm_year +
> +                           TM_YEAR_BASE)][tm->tm_mon] + (tm->tm_mday - 1);
> +                       flags |= FLAG_YDAY;
> +               } else if (day_offset != -1) {
> +                       /* Set the date to the first Sunday (or Monday)
> +                        * of the specified week of the year.
> +                        */
> +                       if (!(flags & FLAG_WDAY)) {
> +                               tm->tm_wday = day_offset;
> +                               flags |= FLAG_WDAY;
> +                       }
> +                       tm->tm_yday = (7 -
> +                           first_wday_of(tm->tm_year + TM_YEAR_BASE) +
> +                           day_offset) % 7 + (week_offset - 1) * 7 +
> +                           tm->tm_wday - day_offset;
> +                       flags |= FLAG_YDAY;
> +               }
> +       }
> +
> +       if ((flags & (FLAG_YEAR | FLAG_YDAY)) == (FLAG_YEAR | FLAG_YDAY)) {
> +               if (!(flags & FLAG_MONTH)) {
> +                       i = 0;
> +                       while (tm->tm_yday >=
> +                           start_of_month[isleap(tm->tm_year +
> +                           TM_YEAR_BASE)][i])
> +                               i++;
> +                       if (i > 12) {
> +                               i = 1;
> +                               tm->tm_yday -=
> +                                   start_of_month[isleap(tm->tm_year +
> +                                   TM_YEAR_BASE)][12];
> +                               tm->tm_year++;
> +                       }
> +                       tm->tm_mon = i - 1;
> +                       flags |= FLAG_MONTH;
> +               }
> +               if (!(flags & FLAG_MDAY)) {
> +                       tm->tm_mday = tm->tm_yday -
> +                           start_of_month[isleap(tm->tm_year + TM_YEAR_BASE)]
> +                           [tm->tm_mon] + 1;
> +                       flags |= FLAG_MDAY;
> +               }
> +               if (!(flags & FLAG_WDAY)) {
> +                       i = 0;
> +                       wday_offset = first_wday_of(tm->tm_year);
> +                       while (i++ <= tm->tm_yday) {
> +                               if (wday_offset++ >= 6)
> +                                       wday_offset = 0;
> +                       }
> +                       tm->tm_wday = wday_offset;
> +                       flags |= FLAG_WDAY;
> +               }
> +       }
> +
>         return ((char *)buf);
>  }
>
> -
>  char *
>  strptime_l(const char * __restrict buf, const char * __restrict fmt,
>      struct tm * __restrict tm, locale_t loc)
> @@ -564,6 +675,7 @@ strptime_l(const char * __restrict buf,
>
>         return (ret);
>  }
> +
>  char *
>  strptime(const char * __restrict buf, const char * __restrict fmt,
>      struct tm * __restrict tm)
>


More information about the svn-src-all mailing list