NetBSD Problem Report #50009

From www@NetBSD.org  Sun Jun 28 19:47:25 2015
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(Client CN "mail.netbsd.org", Issuer "Postmaster NetBSD.org" (verified OK))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 0DB76A65BB
	for <gnats-bugs@gnats.NetBSD.org>; Sun, 28 Jun 2015 19:47:25 +0000 (UTC)
Message-Id: <20150628194723.3EEA1A65E7@mollari.NetBSD.org>
Date: Sun, 28 Jun 2015 19:47:23 +0000 (UTC)
From: devnexen@gmail.com
Reply-To: devnexen@gmail.com
To: gnats-bugs@NetBSD.org
Subject: strptime small enhancement
X-Send-Pr-Version: www-1.0

>Number:         50009
>Category:       lib
>Synopsis:       strptime small enhancement
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    lib-bug-people
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Jun 28 19:50:00 +0000 2015
>Closed-Date:    Sat Jul 04 08:27:45 +0000 2015
>Last-Modified:  Thu Jul 09 12:50:01 +0000 2015
>Originator:     David Carlier
>Release:        -current
>Organization:
>Environment:
NetBSD 7.99.19 (GENERIC) amd64
>Description:
Hi,

It is a small strptime libc function enhancement to fill more fields in more use cases like way, may, month ... to make it more equal to other BSDs.


>How-To-Repeat:

>Fix:
Index: time/private.h
===================================================================
RCS file: /cvsroot/src/lib/libc/time/private.h,v
retrieving revision 1.42
diff -u -r1.42 private.h
--- time/private.h	22 Jun 2015 17:43:23 -0000	1.42
+++ time/private.h	28 Jun 2015 19:32:32 -0000
@@ -558,6 +558,10 @@
 char *ctime_r(time_t const *, char *);
 #endif /* HAVE_INCOMPATIBLE_CTIME_R */

+#ifndef ISLEAPYEAR
+#define ISLEAPYEAR(y) ((y % 400) == 0 && (y % 4) == 0 && (y % 100) != 0)
+#endif
+
 #ifndef YEARSPERREPEAT
 #define YEARSPERREPEAT		400	/* years before a Gregorian repeat */
 #endif /* !defined YEARSPERREPEAT */
Index: time/strptime.c
===================================================================
RCS file: /cvsroot/src/lib/libc/time/strptime.c,v
retrieving revision 1.39
diff -u -r1.39 strptime.c
--- time/strptime.c	6 Apr 2015 14:38:22 -0000	1.39
+++ time/strptime.c	28 Jun 2015 19:32:32 -0000
@@ -60,6 +60,12 @@
 #define ALT_O			0x02
 #define	LEGAL_ALT(x)		{ if (alt_format & ~(x)) return NULL; }

+#define	FLAG_YEAR	(1 << 0)
+#define	FLAG_MTH	(1 << 1)
+#define	FLAG_YDAY	(1 << 2)
+#define	FLAG_MDAY	(1 << 3)
+#define	FLAG_WDAY	(1 << 4)
+
 static char gmt[] = { "GMT" };
 static char utc[] = { "UTC" };
 /* RFC-822/RFC-2822 */
@@ -74,6 +80,15 @@
 static const u_char *find_string(const u_char *, int *, const char * const *,
 	const char * const *, int);

+static const int mths_per_yr_kind[2][12] = {
+	{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+	{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+};
+
+static const int mths_code[12] = {
+	0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5
+};
+
 char *
 strptime(const char *buf, const char *fmt, struct tm *tm)
 {
@@ -85,7 +100,7 @@
 {
 	unsigned char c;
 	const unsigned char *bp, *ep;
-	int alt_format, i, split_year = 0, neg = 0, offs;
+	int alt_format, i, split_year = 0, neg = 0, flags = 0, offs;
 	const char *new_fmt;

 	bp = (const u_char *)buf;
@@ -180,6 +195,7 @@
 			bp = find_string(bp, &tm->tm_wday,
 			    _TIME_LOCALE(loc)->day, _TIME_LOCALE(loc)->abday, 7);
 			LEGAL_ALT(0);
+			flags |= FLAG_WDAY;
 			continue;

 		case 'B':	/* The month, using the locale's form. */
@@ -207,6 +223,7 @@
 		case 'e':
 			bp = conv_num(bp, &tm->tm_mday, 1, 31);
 			LEGAL_ALT(ALT_O);
+			flags |= FLAG_MDAY;
 			continue;

 		case 'k':	/* The hour (24-hour clock representation). */
@@ -232,6 +249,7 @@
 			bp = conv_num(bp, &i, 1, 366);
 			tm->tm_yday = i - 1;
 			LEGAL_ALT(0);
+			flags |= FLAG_YDAY;
 			continue;

 		case 'M':	/* The minute. */
@@ -244,6 +262,7 @@
 			bp = conv_num(bp, &i, 1, 12);
 			tm->tm_mon = i - 1;
 			LEGAL_ALT(ALT_O);
+			flags |= FLAG_MTH;
 			continue;

 		case 'p':	/* The locale's equivalent of AM/PM. */
@@ -305,12 +324,14 @@
 		case 'w':	/* The day of week, beginning on sunday. */
 			bp = conv_num(bp, &tm->tm_wday, 0, 6);
 			LEGAL_ALT(ALT_O);
+			flags |= FLAG_WDAY;
 			continue;

 		case 'u':	/* The day of week, monday = 1. */
 			bp = conv_num(bp, &i, 1, 7);
 			tm->tm_wday = i % 7;
 			LEGAL_ALT(ALT_O);
+			flags |= FLAG_WDAY;
 			continue;

 		case 'g':	/* The year corresponding to the ISO week
@@ -336,6 +357,7 @@
 			bp = conv_num(bp, &i, 0, 9999);
 			tm->tm_year = i - TM_YEAR_BASE;
 			LEGAL_ALT(ALT_E);
+			flags |= FLAG_YEAR;
 			continue;

 		case 'y':	/* The year within 100 years of the epoch. */
@@ -529,6 +551,60 @@
 		}
 	}

+	/**
+	 * Post processing of potential additional flags
+	 */
+	if (flags & FLAG_YEAR) {
+		int yr = 1900 + tm->tm_year;
+		const int *mths_yr = mths_per_yr_kind[ISLEAPYEAR(yr)];
+		if (!(flags & FLAG_YDAY)) {
+			if (flags & FLAG_MTH && flags & FLAG_MDAY) {
+				tm->tm_yday = tm->tm_mday - 1;
+				i = 0;
+				while (i < tm->tm_mon) {
+					tm->tm_yday += mths_yr[i];
+					i ++;
+				}
+
+				flags |= FLAG_YDAY;
+			}
+		}
+		if (flags & FLAG_YDAY) {
+			int d = tm->tm_yday;
+			if (!(flags & FLAG_MTH)) {
+				tm->tm_mon = 0;
+				i = 0;
+				while (i < 12) {
+					d -= mths_yr[i++];
+					if (d <= mths_yr[i])
+						break;
+				}
+				
+				tm->tm_mon = i;
+			}
+			if (!(flags & FLAG_MDAY))
+				tm->tm_mday = d + 1;
+			if (!(flags & FLAG_WDAY)) {
+				tm->tm_wday = tm->tm_mday / 7;
+			}
+		}
+		if (!(flags & FLAG_WDAY)) {
+			static const int centuries[4] = {
+				6, 4, 2, 0
+			};
+			int byear = ((int) yr & ~1) / 100;
+			int century = centuries[byear % 4];
+			int wday = 0;
+			
+			wday = mths_code[tm->tm_mon] + tm->tm_mday;
+			if (ISLEAPYEAR(yr) || tm->tm_mon < 2)
+				wday --;
+			wday =	(wday + tm->tm_year + (tm->tm_year / 4) + century) % 7;
+			
+			tm->tm_wday = wday > 4 ? 0 : wday;
+		}
+	}
+
 	return __UNCONST(bp);
 }


>Release-Note:

>Audit-Trail:
From: David Holland <dholland-bugs@netbsd.org>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: lib/50009: strptime small enhancement
Date: Mon, 29 Jun 2015 03:58:23 +0000

 On Sun, Jun 28, 2015 at 07:50:00PM +0000, devnexen@gmail.com wrote:
  > +#ifndef ISLEAPYEAR
  > +#define ISLEAPYEAR(y) ((y % 400) == 0 && (y % 4) == 0 && (y % 100) != 0)
  > +#endif

 ...this is wrong...

 -- 
 David A. Holland
 dholland@netbsd.org

From: David CARLIER <devnexen@gmail.com>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: lib/50009: strptime small enhancement
Date: Mon, 29 Jun 2015 05:22:45 +0100

 --001a113ab4e82a084b0519a07253
 Content-Type: text/plain; charset=UTF-8

 Ah, good catch ...

 ...

 #ifndef ISLEAPYEAR
 #define ISLEAPYEAR(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
 #endif

 ...


 On 29 June 2015 at 05:00, David Holland <dholland-bugs@netbsd.org> wrote:

 > The following reply was made to PR lib/50009; it has been noted by GNATS.
 >
 > From: David Holland <dholland-bugs@netbsd.org>
 > To: gnats-bugs@NetBSD.org
 > Cc:
 > Subject: Re: lib/50009: strptime small enhancement
 > Date: Mon, 29 Jun 2015 03:58:23 +0000
 >
 >  On Sun, Jun 28, 2015 at 07:50:00PM +0000, devnexen@gmail.com wrote:
 >   > +#ifndef ISLEAPYEAR
 >   > +#define ISLEAPYEAR(y) ((y % 400) == 0 && (y % 4) == 0 && (y % 100) !=
 > 0)
 >   > +#endif
 >
 >  ...this is wrong...
 >
 >  --
 >  David A. Holland
 >  dholland@netbsd.org
 >
 >

 --001a113ab4e82a084b0519a07253
 Content-Type: text/html; charset=UTF-8
 Content-Transfer-Encoding: quoted-printable

 <div dir=3D"ltr">Ah, good catch ...<div><br></div><div>...</div><div><pre s=
 tyle=3D"color:rgb(0,0,0)">#ifndef ISLEAPYEAR
 #define ISLEAPYEAR(y) (((y) % 4) =3D=3D 0 &amp;&amp; (((y) % 100) !=3D 0 ||=
  ((y) % 400) =3D=3D 0))
 #endif</pre><pre style=3D"color:rgb(0,0,0)">...</pre></div></div><div class=
 =3D"gmail_extra"><br><div class=3D"gmail_quote">On 29 June 2015 at 05:00, D=
 avid Holland <span dir=3D"ltr">&lt;<a href=3D"mailto:dholland-bugs@netbsd.o=
 rg" target=3D"_blank">dholland-bugs@netbsd.org</a>&gt;</span> wrote:<br><bl=
 ockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #=
 ccc solid;padding-left:1ex">The following reply was made to PR lib/50009; i=
 t has been noted by GNATS.<br>
 <br>
 From: David Holland &lt;<a href=3D"mailto:dholland-bugs@netbsd.org">dhollan=
 d-bugs@netbsd.org</a>&gt;<br>
 To: gnats-bugs@NetBSD.org<br>
 Cc:<br>
 Subject: Re: lib/50009: strptime small enhancement<br>
 Date: Mon, 29 Jun 2015 03:58:23 +0000<br>
 <br>
 =C2=A0On Sun, Jun 28, 2015 at 07:50:00PM +0000, <a href=3D"mailto:devnexen@=
 gmail.com">devnexen@gmail.com</a> wrote:<br>
 =C2=A0 &gt; +#ifndef ISLEAPYEAR<br>
 =C2=A0 &gt; +#define ISLEAPYEAR(y) ((y % 400) =3D=3D 0 &amp;&amp; (y % 4) =
 =3D=3D 0 &amp;&amp; (y % 100) !=3D 0)<br>
 =C2=A0 &gt; +#endif<br>
 <br>
 =C2=A0...this is wrong...<br>
 <br>
 =C2=A0--<br>
 =C2=A0David A. Holland<br>
 =C2=A0<a href=3D"mailto:dholland@netbsd.org">dholland@netbsd.org</a><br>
 <br>
 </blockquote></div><br></div>

 --001a113ab4e82a084b0519a07253--

From: David CARLIER <devnexen@gmail.com>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: lib/50009: strptime small enhancement
Date: Mon, 29 Jun 2015 05:31:04 +0100

 --001a113ab4e8ed28430519a08fa8
 Content-Type: text/plain; charset=UTF-8

 Ah, good catch ...

 +#ifndef ISLEAPYEAR
  +#define ISLEAPYEAR(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400)
 == 0))
  +#endif

 On 29 June 2015 at 05:00, David Holland <dholland-bugs@netbsd.org> wrote:

 > The following reply was made to PR lib/50009; it has been noted by GNATS.
 >
 > From: David Holland <dholland-bugs@netbsd.org>
 > To: gnats-bugs@NetBSD.org
 > Cc:
 > Subject: Re: lib/50009: strptime small enhancement
 > Date: Mon, 29 Jun 2015 03:58:23 +0000
 >
 >  On Sun, Jun 28, 2015 at 07:50:00PM +0000, devnexen@gmail.com wrote:
 >   > +#ifndef ISLEAPYEAR
 >   > +#define ISLEAPYEAR(y) ((y % 400) == 0 && (y % 4) == 0 && (y % 100) !=
 > 0)
 >   > +#endif
 >
 >  ...this is wrong...
 >
 >  --
 >  David A. Holland
 >  dholland@netbsd.org
 >
 >

 --001a113ab4e8ed28430519a08fa8
 Content-Type: text/html; charset=UTF-8
 Content-Transfer-Encoding: quoted-printable

 <div dir=3D"ltr"><span style=3D"font-size:13px">Ah, good catch ...=C2=A0</s=
 pan><div><span style=3D"font-size:13px"><br></span></div><div><span style=
 =3D"font-size:13px">+#ifndef ISLEAPYEAR</span><br style=3D"font-size:13px">=
 <span style=3D"font-size:13px">=C2=A0+#define ISLEAPYEAR(y) (((y) % 4) =3D=
 =3D 0 &amp;&amp; (((y) % 100) !=3D 0 || ((y) % 400) =3D=3D 0))</span><br st=
 yle=3D"font-size:13px"><span style=3D"font-size:13px">=C2=A0+#endif</span><=
 br></div></div><div class=3D"gmail_extra"><br><div class=3D"gmail_quote">On=
  29 June 2015 at 05:00, David Holland <span dir=3D"ltr">&lt;<a href=3D"mail=
 to:dholland-bugs@netbsd.org" target=3D"_blank">dholland-bugs@netbsd.org</a>=
 &gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0=
  0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The following reply wa=
 s made to PR lib/50009; it has been noted by GNATS.<br>
 <br>
 From: David Holland &lt;<a href=3D"mailto:dholland-bugs@netbsd.org">dhollan=
 d-bugs@netbsd.org</a>&gt;<br>
 To: gnats-bugs@NetBSD.org<br>
 Cc:<br>
 Subject: Re: lib/50009: strptime small enhancement<br>
 Date: Mon, 29 Jun 2015 03:58:23 +0000<br>
 <br>
 =C2=A0On Sun, Jun 28, 2015 at 07:50:00PM +0000, <a href=3D"mailto:devnexen@=
 gmail.com">devnexen@gmail.com</a> wrote:<br>
 =C2=A0 &gt; +#ifndef ISLEAPYEAR<br>
 =C2=A0 &gt; +#define ISLEAPYEAR(y) ((y % 400) =3D=3D 0 &amp;&amp; (y % 4) =
 =3D=3D 0 &amp;&amp; (y % 100) !=3D 0)<br>
 =C2=A0 &gt; +#endif<br>
 <br>
 =C2=A0...this is wrong...<br>
 <br>
 =C2=A0--<br>
 =C2=A0David A. Holland<br>
 =C2=A0<a href=3D"mailto:dholland@netbsd.org">dholland@netbsd.org</a><br>
 <br>
 </blockquote></div><br></div>

 --001a113ab4e8ed28430519a08fa8--

From: matthew green <mrg@eterna.com.au>
To: gnats-bugs@NetBSD.org
Cc: lib-bug-people@netbsd.org, gnats-admin@netbsd.org,
    netbsd-bugs@netbsd.org, devnexen@gmail.com
Subject: re: lib/50009: strptime small enhancement
Date: Mon, 29 Jun 2015 14:42:18 +1000

 >  On Sun, Jun 28, 2015 at 07:50:00PM +0000, devnexen@gmail.com wrote:
 >   > +#ifndef ISLEAPYEAR
 >   > +#define ISLEAPYEAR(y) ((y % 400) == 0 && (y % 4) == 0 && (y % 100) != 0)
 >   > +#endif
 >  
 >  ...this is wrong...

 indeed, sys/clock.h has this:

 63 /*
 64  * This inline avoids some unnecessary modulo operations
 65  * as compared with the usual macro:
 66  *   ( ((year % 4) == 0 &&
 67  *      (year % 100) != 0) ||
 68  *     ((year % 400) == 0) )
 69  * It is otherwise equivalent.
 70  */
 71 static inline int
 72 is_leap_year(uint64_t year)
 73 {
 74         if ((year & 3) != 0)
 75                 return 0;
 76
 77         if (__predict_false((year % 100) != 0))
 78                 return 1;
 79
 80         return __predict_false((year % 400) == 0);
 81 }

 which should probably be used instead, for netbsd, or at
 least the same expression in the comment.

 (the macro above also doesn't work properly for various
 inputs, like a good macro should.)


 .mrg.

From: David CARLIER <devnexen@gmail.com>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: lib/50009: strptime small enhancement
Date: Mon, 29 Jun 2015 06:13:44 +0100

 --Apple-Mail=_75D17FF7-C2FC-496A-BE65-549EA05291B1
 Content-Transfer-Encoding: quoted-printable
 Content-Type: text/plain;
 	charset=us-ascii

 Ok new corrected patch, thanks for your answers.

 Index: time/strptime.c
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 RCS file: /cvsroot/src/lib/libc/time/strptime.c,v
 retrieving revision 1.39
 diff -u -r1.39 strptime.c
 --- time/strptime.c	6 Apr 2015 14:38:22 -0000	1.39
 +++ time/strptime.c	29 Jun 2015 05:06:25 -0000
 @@ -36,6 +36,8 @@

  #include "namespace.h"
  #include <sys/localedef.h>
 +#include <sys/types.h>
 +#include <sys/clock.h>
  #include <ctype.h>
  #include <locale.h>
  #include <string.h>
 @@ -60,6 +62,12 @@
  #define ALT_O			0x02
  #define	LEGAL_ALT(x)		{ if (alt_format & ~(x)) return =
 NULL; }

 +#define	FLAG_YEAR	(1 << 0)
 +#define	FLAG_MTH	(1 << 1)
 +#define	FLAG_YDAY	(1 << 2)
 +#define	FLAG_MDAY	(1 << 3)
 +#define	FLAG_WDAY	(1 << 4)
 +
  static char gmt[] =3D { "GMT" };
  static char utc[] =3D { "UTC" };
  /* RFC-822/RFC-2822 */
 @@ -74,6 +82,15 @@
  static const u_char *find_string(const u_char *, int *, const char * =
 const *,
  	const char * const *, int);

 +static const int mths_per_yr_kind[2][12] =3D {
 +	{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
 +	{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
 +};
 +
 +static const int mths_code[12] =3D {
 +	0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5
 +};
 +
  char *
  strptime(const char *buf, const char *fmt, struct tm *tm)
  {
 @@ -85,7 +102,7 @@
  {
  	unsigned char c;
  	const unsigned char *bp, *ep;
 -	int alt_format, i, split_year =3D 0, neg =3D 0, offs;
 +	int alt_format, i, split_year =3D 0, neg =3D 0, flags =3D 0, =
 offs;
  	const char *new_fmt;

  	bp =3D (const u_char *)buf;
 @@ -180,6 +197,7 @@
  			bp =3D find_string(bp, &tm->tm_wday,
  			    _TIME_LOCALE(loc)->day, =
 _TIME_LOCALE(loc)->abday, 7);
  			LEGAL_ALT(0);
 +			flags |=3D FLAG_WDAY;
  			continue;

  		case 'B':	/* The month, using the locale's form. =
 */
 @@ -207,6 +225,7 @@
  		case 'e':
  			bp =3D conv_num(bp, &tm->tm_mday, 1, 31);
  			LEGAL_ALT(ALT_O);
 +			flags |=3D FLAG_MDAY;
  			continue;

  		case 'k':	/* The hour (24-hour clock =
 representation). */
 @@ -232,6 +251,7 @@
  			bp =3D conv_num(bp, &i, 1, 366);
  			tm->tm_yday =3D i - 1;
  			LEGAL_ALT(0);
 +			flags |=3D FLAG_YDAY;
  			continue;

  		case 'M':	/* The minute. */
 @@ -244,6 +264,7 @@
  			bp =3D conv_num(bp, &i, 1, 12);
  			tm->tm_mon =3D i - 1;
  			LEGAL_ALT(ALT_O);
 +			flags |=3D FLAG_MTH;
  			continue;

  		case 'p':	/* The locale's equivalent of AM/PM. */
 @@ -305,12 +326,14 @@
  		case 'w':	/* The day of week, beginning on sunday. =
 */
  			bp =3D conv_num(bp, &tm->tm_wday, 0, 6);
  			LEGAL_ALT(ALT_O);
 +			flags |=3D FLAG_WDAY;
  			continue;

  		case 'u':	/* The day of week, monday =3D 1. */
  			bp =3D conv_num(bp, &i, 1, 7);
  			tm->tm_wday =3D i % 7;
  			LEGAL_ALT(ALT_O);
 +			flags |=3D FLAG_WDAY;
  			continue;

  		case 'g':	/* The year corresponding to the ISO =
 week
 @@ -336,6 +359,7 @@
  			bp =3D conv_num(bp, &i, 0, 9999);
  			tm->tm_year =3D i - TM_YEAR_BASE;
  			LEGAL_ALT(ALT_E);
 +			flags |=3D FLAG_YEAR;
  			continue;

  		case 'y':	/* The year within 100 years of the =
 epoch. */
 @@ -529,6 +553,57 @@
  		}
  	}

 +	/**
 +	 * Post processing of potential additional flags
 +	 */
 +	if (flags & FLAG_YEAR) {
 +		int yr =3D 1900 + tm->tm_year;
 +		const int *mths_yr =3D =
 mths_per_yr_kind[is_leap_year(yr)];
 +		if (!(flags & FLAG_YDAY)) {
 +			if (flags & FLAG_MTH && flags & FLAG_MDAY) {
 +				tm->tm_yday =3D tm->tm_mday - 1;
 +				i =3D 0;
 +				while (i < tm->tm_mon) {
 +					tm->tm_yday +=3D mths_yr[i];
 +					i ++;
 +				}
 +
 +				flags |=3D FLAG_YDAY;
 +			}
 +		}
 +		if (flags & FLAG_YDAY) {
 +			int d =3D tm->tm_yday;
 +			if (!(flags & FLAG_MTH)) {
 +				tm->tm_mon =3D 0;
 +				i =3D 0;
 +				while (i < 12) {
 +					d -=3D mths_yr[i++];
 +					if (d <=3D mths_yr[i])
 +						break;
 +				}
 +
 +				tm->tm_mon =3D i;
 +			}
 +			if (!(flags & FLAG_MDAY))
 +				tm->tm_mday =3D d + 1;
 +			if (!(flags & FLAG_WDAY)) {
 +				static const int centuries[4] =3D {
 +					6, 4, 2, 0
 +				};
 +				int byear =3D ((int) yr & ~1) / 100;
 +				int century =3D centuries[byear % 4];
 +				int wday =3D 0;
 +
 +				wday =3D mths_code[tm->tm_mon] + =
 tm->tm_mday;
 +				if (is_leap_year(yr) || tm->tm_mon < 2)
 +					wday --;
 +				wday =3D	(wday + tm->tm_year + =
 (tm->tm_year / 4) + century) % 7;
 +
 +				tm->tm_wday =3D wday > 4 ? 0 : wday;
 +			}
 +		}
 +	}
 +
  	return __UNCONST(bp);
  }




 > On 29 Jun 2015, at 05:45, matthew green <mrg@eterna.com.au> wrote:
 >=20
 > The following reply was made to PR lib/50009; it has been noted by =
 GNATS.
 >=20
 > From: matthew green <mrg@eterna.com.au>
 > To: gnats-bugs@NetBSD.org
 > Cc: lib-bug-people@netbsd.org, gnats-admin@netbsd.org,
 >    netbsd-bugs@netbsd.org, devnexen@gmail.com
 > Subject: re: lib/50009: strptime small enhancement
 > Date: Mon, 29 Jun 2015 14:42:18 +1000
 >=20
 >> On Sun, Jun 28, 2015 at 07:50:00PM +0000, devnexen@gmail.com wrote:
 >>> +#ifndef ISLEAPYEAR
 >>> +#define ISLEAPYEAR(y) ((y % 400) =3D=3D 0 && (y % 4) =3D=3D 0 && (y =
 % 100) !=3D 0)
 >>> +#endif
 >>=20
 >> ...this is wrong...
 >=20
 > indeed, sys/clock.h has this:
 >=20
 > 63 /*
 > 64  * This inline avoids some unnecessary modulo operations
 > 65  * as compared with the usual macro:
 > 66  *   ( ((year % 4) =3D=3D 0 &&
 > 67  *      (year % 100) !=3D 0) ||
 > 68  *     ((year % 400) =3D=3D 0) )
 > 69  * It is otherwise equivalent.
 > 70  */
 > 71 static inline int
 > 72 is_leap_year(uint64_t year)
 > 73 {
 > 74         if ((year & 3) !=3D 0)
 > 75                 return 0;
 > 76
 > 77         if (__predict_false((year % 100) !=3D 0))
 > 78                 return 1;
 > 79
 > 80         return __predict_false((year % 400) =3D=3D 0);
 > 81 }
 >=20
 > which should probably be used instead, for netbsd, or at
 > least the same expression in the comment.
 >=20
 > (the macro above also doesn't work properly for various
 > inputs, like a good macro should.)
 >=20
 >=20
 > .mrg.
 >=20


 --Apple-Mail=_75D17FF7-C2FC-496A-BE65-549EA05291B1
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
 	filename=signature.asc
 Content-Type: application/pgp-signature;
 	name=signature.asc
 Content-Description: Message signed with OpenPGP using GPGMail

 -----BEGIN PGP SIGNATURE-----
 Comment: GPGTools - https://gpgtools.org

 iQEcBAEBCgAGBQJVkNQPAAoJECNxxoUnxrf4rJMIANfjh8J2YJFDpXWWoADaE5Pj
 UmmiDhzDOLNYMeM3MsGVhAdCBZgUaIwOREc14nfMzgiCugS/s/xMH2v+BgBCdbQy
 Q99OGod5LnYCFD0iYOy7T8fzJ6Lvey0PS9xay3/gr64WC9QMdTSlGx4wAFlijR4F
 qIooJqpXEIgf83b5h7fXiGlAQ/FbVHNhS+y9n4z+DBRM02PDfeol2iXxmNwCFlap
 VjM7CQZ2lbeg0KXcDU4tOWWkWGx7WBCctojn+tCjfb/0s6Xnceyz6bAgvco/yW6z
 s6Rj7QZ9miivD14gx1UdWI2kgvnzfM5xS2m7xPolGC5ZIgt7ZHiVJtN9Dg9NUuo=
 =KO//
 -----END PGP SIGNATURE-----

 --Apple-Mail=_75D17FF7-C2FC-496A-BE65-549EA05291B1--

From: christos@zoulas.com (Christos Zoulas)
To: gnats-bugs@NetBSD.org, lib-bug-people@netbsd.org, 
	gnats-admin@netbsd.org, netbsd-bugs@netbsd.org, devnexen@gmail.com
Cc: 
Subject: Re: lib/50009: strptime small enhancement
Date: Mon, 29 Jun 2015 14:38:23 -0400

 On Jun 29,  5:15am, devnexen@gmail.com (David CARLIER) wrote:
 -- Subject: Re: lib/50009: strptime small enhancement

 |  Ok new corrected patch, thanks for your answers.

 Is there a reason to prefer this version as opposed to sync with the
 one from FreeBSD?

 Thanks,

 christos

From: David CARLIER <devnexen@gmail.com>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: lib/50009: strptime small enhancement
Date: Mon, 29 Jun 2015 19:45:42 +0100

 --Apple-Mail=_0E4D147F-676A-4F63-932C-DB6B91214E79
 Content-Transfer-Encoding: quoted-printable
 Content-Type: text/plain;
 	charset=utf-8

 Well, it s closer to OpenBSD version but I m not against following =
 FreeBSD=E2=80=99s path personally. If it s better I can provide a newer =
 version ?


 > On 29 Jun 2015, at 19:40, Christos Zoulas <christos@zoulas.com> wrote:
 >=20
 > The following reply was made to PR lib/50009; it has been noted by =
 GNATS.
 >=20
 > From: christos@zoulas.com (Christos Zoulas)
 > To: gnats-bugs@NetBSD.org, lib-bug-people@netbsd.org,
 > 	gnats-admin@netbsd.org, netbsd-bugs@netbsd.org, =
 devnexen@gmail.com
 > Cc:
 > Subject: Re: lib/50009: strptime small enhancement
 > Date: Mon, 29 Jun 2015 14:38:23 -0400
 >=20
 > On Jun 29,  5:15am, devnexen@gmail.com (David CARLIER) wrote:
 > -- Subject: Re: lib/50009: strptime small enhancement
 >=20
 > |  Ok new corrected patch, thanks for your answers.
 >=20
 > Is there a reason to prefer this version as opposed to sync with the
 > one from FreeBSD?
 >=20
 > Thanks,
 >=20
 > christos
 >=20


 --Apple-Mail=_0E4D147F-676A-4F63-932C-DB6B91214E79
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
 	filename=signature.asc
 Content-Type: application/pgp-signature;
 	name=signature.asc
 Content-Description: Message signed with OpenPGP using GPGMail

 -----BEGIN PGP SIGNATURE-----
 Comment: GPGTools - https://gpgtools.org

 iQEcBAEBCgAGBQJVkZJbAAoJECNxxoUnxrf4oskIAK400yduSVYkKmu5a9Y3RX3e
 mOOCJVyG952m2a03zcV2a35XLq90kNDc35SH5An+zBYGl0xSQR/+iJAraPljUb+L
 AvRCzVveRW8lCdUuZcViL921abYA5hywHlzt/ao5UrplhYiallz5XyeIyaasVlYy
 hrrzCiJzHxGV4dxLOpIFIy/NSv4iOh+rDRF7ULTJmqQTp2rgRVw+Fb/KtNE5l4Ef
 AluXK5niDclNnTTY4FGMKrkLqPV361iVST88NpmNC5hBJDwonEa8K7URelm5fOTw
 ummS12wNBEDEa1dLnzLahLOGtjMW8Cd/sncxnQQvaR0U2KvNoEQO/W/r+le9dXU=
 =Y2z4
 -----END PGP SIGNATURE-----

 --Apple-Mail=_0E4D147F-676A-4F63-932C-DB6B91214E79--

From: christos@zoulas.com (Christos Zoulas)
To: gnats-bugs@NetBSD.org, lib-bug-people@netbsd.org, 
	gnats-admin@netbsd.org, netbsd-bugs@netbsd.org, devnexen@gmail.com
Cc: 
Subject: Re: lib/50009: strptime small enhancement
Date: Mon, 29 Jun 2015 14:53:59 -0400

 On Jun 29,  6:50pm, devnexen@gmail.com (David CARLIER) wrote:
 -- Subject: Re: lib/50009: strptime small enhancement

 |  Well, it's closer to OpenBSD version but I m not against following
 |  FreeBSD's path personally. If it s better I can provide a newer version?

 Sure, why don't you look at them both and make a recommendation?

 Thanks,

 christos

From: David CARLIER <devnexen@gmail.com>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: lib/50009: strptime small enhancement
Date: Mon, 29 Jun 2015 22:41:14 +0100

 --Apple-Mail=_65474D83-214C-489E-822A-D2420A0A27D0
 Content-Transfer-Encoding: quoted-printable
 Content-Type: text/plain;
 	charset=utf-8


 Here another version based on FreeBSD=E2=80=99s implementation pretty =
 much, works on more use cases than the first version and =E2=80=98U=E2=80=99=
  and =E2=80=98W=E2=80=99 flags work better.

 Index: time/strptime.c
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 RCS file: /cvsroot/src/lib/libc/time/strptime.c,v
 retrieving revision 1.39
 diff -u -r1.39 strptime.c
 --- time/strptime.c	6 Apr 2015 14:38:22 -0000	1.39
 +++ time/strptime.c	29 Jun 2015 21:33:46 -0000
 @@ -36,6 +36,8 @@

  #include "namespace.h"
  #include <sys/localedef.h>
 +#include <sys/types.h>
 +#include <sys/clock.h>
  #include <ctype.h>
  #include <locale.h>
  #include <string.h>
 @@ -60,6 +62,12 @@
  #define ALT_O			0x02
  #define	LEGAL_ALT(x)		{ if (alt_format & ~(x)) return =
 NULL; }

 +#define	FLAG_YEAR	(1 << 0)
 +#define	FLAG_MTH	(1 << 1)
 +#define	FLAG_YDAY	(1 << 2)
 +#define	FLAG_MDAY	(1 << 3)
 +#define	FLAG_WDAY	(1 << 4)
 +
  static char gmt[] =3D { "GMT" };
  static char utc[] =3D { "UTC" };
  /* RFC-822/RFC-2822 */
 @@ -74,6 +82,18 @@
  static const u_char *find_string(const u_char *, int *, const char * =
 const *,
  	const char * const *, int);

 +static const int mths_per_yr_kind[2][13] =3D {
 +	{ 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 }
 +};
 +
 +static int
 +first_wday_of(int yr)
 +{
 +	return ((2 * (3 - (yr / 100) % 4)) + (yr % 100) + ((yr % 100) / =
 4) +
 +		(is_leap_year(yr) ? 6 : 0) + 1) % 7;
 +}
 +
  char *
  strptime(const char *buf, const char *fmt, struct tm *tm)
  {
 @@ -85,7 +105,7 @@
  {
  	unsigned char c;
  	const unsigned char *bp, *ep;
 -	int alt_format, i, split_year =3D 0, neg =3D 0, offs;
 +	int alt_format, i, split_year =3D 0, neg =3D 0, flags =3D 0, =
 doff =3D -1, woff =3D 0, offs;
  	const char *new_fmt;

  	bp =3D (const u_char *)buf;
 @@ -133,16 +153,19 @@
  		 */
  		case 'c':	/* Date and time, using the locale's =
 format. */
  			new_fmt =3D _TIME_LOCALE(loc)->d_t_fmt;
 +			flags |=3D FLAG_WDAY | FLAG_MTH | FLAG_MDAY | =
 FLAG_YEAR;
  			goto recurse;

  		case 'D':	/* The date as "%m/%d/%y". */
  			new_fmt =3D "%m/%d/%y";
  			LEGAL_ALT(0);
 +			flags |=3D FLAG_MTH | FLAG_MDAY | FLAG_YEAR;
  			goto recurse;

  		case 'F':	/* The date as "%Y-%m-%d". */
  			new_fmt =3D "%Y-%m-%d";
  			LEGAL_ALT(0);
 +			flags |=3D FLAG_MTH | FLAG_MDAY | FLAG_YEAR;
  			goto recurse;

  		case 'R':	/* The time as "%H:%M". */
 @@ -166,6 +189,7 @@

  		case 'x':	/* The date, using the locale's format. =
 */
  			new_fmt =3D _TIME_LOCALE(loc)->d_fmt;
 +			flags |=3D FLAG_MTH | FLAG_MDAY | FLAG_YEAR;
  		    recurse:
  			bp =3D (const u_char *)strptime((const char =
 *)bp,
  							    new_fmt, =
 tm);
 @@ -180,6 +204,7 @@
  			bp =3D find_string(bp, &tm->tm_wday,
  			    _TIME_LOCALE(loc)->day, =
 _TIME_LOCALE(loc)->abday, 7);
  			LEGAL_ALT(0);
 +			flags |=3D FLAG_WDAY;
  			continue;

  		case 'B':	/* The month, using the locale's form. =
 */
 @@ -189,6 +214,7 @@
  			    _TIME_LOCALE(loc)->mon, =
 _TIME_LOCALE(loc)->abmon,
  			    12);
  			LEGAL_ALT(0);
 +			flags |=3D FLAG_MTH;
  			continue;

  		case 'C':	/* The century number. */
 @@ -201,12 +227,14 @@
  			split_year =3D 1;
  			tm->tm_year =3D i;
  			LEGAL_ALT(ALT_E);
 +			flags |=3D FLAG_YEAR;
  			continue;

  		case 'd':	/* The day of month. */
  		case 'e':
  			bp =3D conv_num(bp, &tm->tm_mday, 1, 31);
  			LEGAL_ALT(ALT_O);
 +			flags |=3D FLAG_MDAY;
  			continue;

  		case 'k':	/* The hour (24-hour clock =
 representation). */
 @@ -232,6 +260,7 @@
  			bp =3D conv_num(bp, &i, 1, 366);
  			tm->tm_yday =3D i - 1;
  			LEGAL_ALT(0);
 +			flags |=3D FLAG_YDAY;
  			continue;

  		case 'M':	/* The minute. */
 @@ -244,6 +273,7 @@
  			bp =3D conv_num(bp, &i, 1, 12);
  			tm->tm_mon =3D i - 1;
  			LEGAL_ALT(ALT_O);
 +			flags |=3D FLAG_MTH;
  			continue;

  		case 'p':	/* The locale's equivalent of AM/PM. */
 @@ -287,6 +317,8 @@

  				if (localtime_r(&sse, tm) =3D=3D NULL)
  					bp =3D NULL;
 +				else
 +					flags |=3D FLAG_YDAY | FLAG_WDAY =
 | FLAG_MTH | FLAG_MDAY | FLAG_YEAR;
  			}
  			continue;

 @@ -300,11 +332,17 @@
  			 */
  			 bp =3D conv_num(bp, &i, 0, 53);
  			 LEGAL_ALT(ALT_O);
 +			 if (c =3D=3D 'U')
 +				doff =3D TM_SUNDAY;
 +			 else
 +				doff =3D TM_MONDAY;
 +			 woff =3D i;
  			 continue;

  		case 'w':	/* The day of week, beginning on sunday. =
 */
  			bp =3D conv_num(bp, &tm->tm_wday, 0, 6);
  			LEGAL_ALT(ALT_O);
 +			flags |=3D FLAG_WDAY;
  			continue;

  		case 'u':	/* The day of week, monday =3D 1. */
 @@ -336,6 +374,7 @@
  			bp =3D conv_num(bp, &i, 0, 9999);
  			tm->tm_year =3D i - TM_YEAR_BASE;
  			LEGAL_ALT(ALT_E);
 +			flags |=3D FLAG_YEAR;
  			continue;

  		case 'y':	/* The year within 100 years of the =
 epoch. */
 @@ -353,6 +392,7 @@
  					i =3D i + 1900 - TM_YEAR_BASE;
  			}
  			tm->tm_year =3D i;
 +			flags |=3D FLAG_YEAR;
  			continue;

  		case 'Z':
 @@ -425,6 +465,7 @@
  				continue;
  			case '+':
  				neg =3D 0;
 +				flags |=3D FLAG_WDAY | FLAG_MTH | =
 FLAG_MDAY | FLAG_YEAR;
  				break;
  			case '-':
  				neg =3D 1;
 @@ -529,6 +570,52 @@
  		}
  	}

 +	if (!(flags & FLAG_YDAY) && (flags & FLAG_YEAR)) {
 +		int isleap =3D is_leap_year(tm->tm_year + TM_YEAR_BASE);
 +		if ((flags & (FLAG_MTH | FLAG_MDAY)) =3D=3D (FLAG_MTH | =
 FLAG_MDAY)) {
 +			tm->tm_yday =3D =
 mths_per_yr_kind[isleap][tm->tm_mon] + (tm->tm_mday - 1);
 +			flags |=3D FLAG_YDAY;
 +		} else if (doff !=3D -1) {
 +			if (!(flags & FLAG_WDAY)) {
 +				tm->tm_wday =3D doff;
 +				flags |=3D FLAG_WDAY;
 +			}
 +			tm->tm_yday =3D (7 - first_wday_of(tm->tm_year + =
 TM_YEAR_BASE) +
 +				doff) % 7 + (woff - 1) * 7 + tm->tm_wday =
 - doff;
 +			flags |=3D FLAG_YDAY;
 +		}
 +	}
 +
 +	if ((flags & (FLAG_YEAR | FLAG_YDAY)) =3D=3D (FLAG_YEAR | =
 FLAG_YDAY)) {
 +		int isleap =3D is_leap_year(tm->tm_year + TM_YEAR_BASE);
 +		if (!(flags & FLAG_MTH)) {
 +			i =3D 0;
 +			while (tm->tm_yday >=3D =
 mths_per_yr_kind[isleap][i])
 +				i ++;
 +			if (i > 12) {
 +				i =3D 1;
 +				tm->tm_yday -=3D =
 mths_per_yr_kind[isleap][12];
 +				tm->tm_year ++;
 +			}
 +			tm->tm_mon =3D i - 1;
 +			flags |=3D FLAG_MTH;
 +		}
 +		if (!(flags & FLAG_MDAY)) {
 +			tm->tm_mday =3D tm->tm_yday - =
 mths_per_yr_kind[isleap][tm->tm_mon] + 1;
 +			flags |=3D FLAG_MDAY;
 +		}
 +		if (!(flags & FLAG_WDAY)) {
 +			i =3D 0;
 +			woff =3D first_wday_of(tm->tm_year);
 +			while (i ++ <=3D tm->tm_yday) {
 +				if (woff ++ >=3D 6)
 +					woff =3D 0;
 +			}
 +			tm->tm_wday =3D woff;
 +			flags |=3D FLAG_WDAY;
 +		}
 +	}
 +
  	return __UNCONST(bp);
  }



 > On 29 Jun 2015, at 19:55, Christos Zoulas <christos@zoulas.com> wrote:
 >=20
 > The following reply was made to PR lib/50009; it has been noted by =
 GNATS.
 >=20
 > From: christos@zoulas.com (Christos Zoulas)
 > To: gnats-bugs@NetBSD.org, lib-bug-people@netbsd.org,
 > 	gnats-admin@netbsd.org, netbsd-bugs@netbsd.org, =
 devnexen@gmail.com
 > Cc:
 > Subject: Re: lib/50009: strptime small enhancement
 > Date: Mon, 29 Jun 2015 14:53:59 -0400
 >=20
 > On Jun 29,  6:50pm, devnexen@gmail.com (David CARLIER) wrote:
 > -- Subject: Re: lib/50009: strptime small enhancement
 >=20
 > |  Well, it's closer to OpenBSD version but I m not against following
 > |  FreeBSD's path personally. If it s better I can provide a newer =
 version?
 >=20
 > Sure, why don't you look at them both and make a recommendation?
 >=20
 > Thanks,
 >=20
 > christos
 >=20


 --Apple-Mail=_65474D83-214C-489E-822A-D2420A0A27D0
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
 	filename=signature.asc
 Content-Type: application/pgp-signature;
 	name=signature.asc
 Content-Description: Message signed with OpenPGP using GPGMail

 -----BEGIN PGP SIGNATURE-----
 Comment: GPGTools - https://gpgtools.org

 iQEcBAEBCgAGBQJVkbt/AAoJECNxxoUnxrf44tUH/1jH39r64I3xXXlZhLA9HHLx
 LIN+YXIxB3lVHNYjnM63W6YnEzUrlG4o3OTbtHn6PDk1D7zyg/SI0cVo95Gk9C+r
 ryKAfnyhmnCi34jdU4FQ79u4yqDxJawGZBeiiIYANg1od+cNfC2t8j4U4qDm53nO
 BoVhjTE1c978h1TShdaB66+LDJiLwIpL8X7JUU4UmskgJ65Knysa/91ZD36iUUxM
 O7iZAdOiQMENVKMC/LPL8FF6I/BaRYpcfNhuqGh6kmYuF3AA1wZnwWjQNpv70f5U
 Zmz34/4pjFuHDgBC3Gx6slukYl9IWY+yFXEIOdfDiK53Ejrtw9SzhoIrIxdkVCs=
 =jl1Z
 -----END PGP SIGNATURE-----

 --Apple-Mail=_65474D83-214C-489E-822A-D2420A0A27D0--

From: David CARLIER <devnexen@gmail.com>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: lib/50009: strptime small enhancement
Date: Fri, 3 Jul 2015 05:42:30 +0100

 --Apple-Mail=_B162FE6C-9B49-46CF-85BE-D64EE31B7CD3
 Content-Transfer-Encoding: quoted-printable
 Content-Type: text/plain;
 	charset=us-ascii

 Sorry was malformed patch

 Index: time/strptime.c
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 RCS file: /cvsroot/src/lib/libc/time/strptime.c,v
 retrieving revision 1.39
 diff -u -r1.39 strptime.c
 --- time/strptime.c	6 Apr 2015 14:38:22 -0000	1.39
 +++ time/strptime.c	29 Jun 2015 21:33:46 -0000
 @@ -36,6 +36,8 @@

  #include "namespace.h"
  #include <sys/localedef.h>
 +#include <sys/types.h>
 +#include <sys/clock.h>
  #include <ctype.h>
  #include <locale.h>
  #include <string.h>
 @@ -60,6 +62,12 @@
  #define ALT_O			0x02
  #define	LEGAL_ALT(x)		{ if (alt_format & ~(x)) return =
 NULL; }

 +#define	FLAG_YEAR	(1 << 0)
 +#define	FLAG_MTH	(1 << 1)
 +#define	FLAG_YDAY	(1 << 2)
 +#define	FLAG_MDAY	(1 << 3)
 +#define	FLAG_WDAY	(1 << 4)
 +
  static char gmt[] =3D { "GMT" };
  static char utc[] =3D { "UTC" };
  /* RFC-822/RFC-2822 */
 @@ -74,6 +82,18 @@
  static const u_char *find_string(const u_char *, int *, const char * =
 const *,
  	const char * const *, int);

 +static const int mths_per_yr_kind[2][13] =3D {
 +	{ 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 }
 +};
 +
 +static int
 +first_wday_of(int yr)
 +{
 +	return ((2 * (3 - (yr / 100) % 4)) + (yr % 100) + ((yr % 100) / =
 4) +
 +		(is_leap_year(yr) ? 6 : 0) + 1) % 7;
 +}
 +
  char *
  strptime(const char *buf, const char *fmt, struct tm *tm)
  {
 @@ -85,7 +105,7 @@
  {
  	unsigned char c;
  	const unsigned char *bp, *ep;
 -	int alt_format, i, split_year =3D 0, neg =3D 0, offs;
 +	int alt_format, i, split_year =3D 0, neg =3D 0, flags =3D 0, =
 doff =3D -1, woff =3D 0, offs;
  	const char *new_fmt;

  	bp =3D (const u_char *)buf;
 @@ -133,16 +153,19 @@
  		 */
  		case 'c':	/* Date and time, using the locale's =
 format. */
  			new_fmt =3D _TIME_LOCALE(loc)->d_t_fmt;
 +			flags |=3D FLAG_WDAY | FLAG_MTH | FLAG_MDAY | =
 FLAG_YEAR;
  			goto recurse;

  		case 'D':	/* The date as "%m/%d/%y". */
  			new_fmt =3D "%m/%d/%y";
  			LEGAL_ALT(0);
 +			flags |=3D FLAG_MTH | FLAG_MDAY | FLAG_YEAR;
  			goto recurse;

  		case 'F':	/* The date as "%Y-%m-%d". */
  			new_fmt =3D "%Y-%m-%d";
  			LEGAL_ALT(0);
 +			flags |=3D FLAG_MTH | FLAG_MDAY | FLAG_YEAR;
  			goto recurse;

  		case 'R':	/* The time as "%H:%M". */
 @@ -166,6 +189,7 @@

  		case 'x':	/* The date, using the locale's format. =
 */
  			new_fmt =3D _TIME_LOCALE(loc)->d_fmt;
 +			flags |=3D FLAG_MTH | FLAG_MDAY | FLAG_YEAR;
  		    recurse:
  			bp =3D (const u_char *)strptime((const char =
 *)bp,
  							    new_fmt, =
 tm);
 @@ -180,6 +204,7 @@
  			bp =3D find_string(bp, &tm->tm_wday,
  			    _TIME_LOCALE(loc)->day, =
 _TIME_LOCALE(loc)->abday, 7);
  			LEGAL_ALT(0);
 +			flags |=3D FLAG_WDAY;
  			continue;

  		case 'B':	/* The month, using the locale's form. =
 */
 @@ -189,6 +214,7 @@
  			    _TIME_LOCALE(loc)->mon, =
 _TIME_LOCALE(loc)->abmon,
  			    12);
  			LEGAL_ALT(0);
 +			flags |=3D FLAG_MTH;
  			continue;

  		case 'C':	/* The century number. */
 @@ -201,12 +227,14 @@
  			split_year =3D 1;
  			tm->tm_year =3D i;
  			LEGAL_ALT(ALT_E);
 +			flags |=3D FLAG_YEAR;
  			continue;

  		case 'd':	/* The day of month. */
  		case 'e':
  			bp =3D conv_num(bp, &tm->tm_mday, 1, 31);
  			LEGAL_ALT(ALT_O);
 +			flags |=3D FLAG_MDAY;
  			continue;

  		case 'k':	/* The hour (24-hour clock =
 representation). */
 @@ -232,6 +260,7 @@
  			bp =3D conv_num(bp, &i, 1, 366);
  			tm->tm_yday =3D i - 1;
  			LEGAL_ALT(0);
 +			flags |=3D FLAG_YDAY;
  			continue;

  		case 'M':	/* The minute. */
 @@ -244,6 +273,7 @@
  			bp =3D conv_num(bp, &i, 1, 12);
  			tm->tm_mon =3D i - 1;
  			LEGAL_ALT(ALT_O);
 +			flags |=3D FLAG_MTH;
  			continue;

  		case 'p':	/* The locale's equivalent of AM/PM. */
 @@ -287,6 +317,8 @@

  				if (localtime_r(&sse, tm) =3D=3D NULL)
  					bp =3D NULL;
 +				else
 +					flags |=3D FLAG_YDAY | FLAG_WDAY =
 | FLAG_MTH | FLAG_MDAY | FLAG_YEAR;
  			}
  			continue;

 @@ -300,11 +332,17 @@
  			 */
  			 bp =3D conv_num(bp, &i, 0, 53);
  			 LEGAL_ALT(ALT_O);
 +			 if (c =3D=3D 'U')
 +				doff =3D TM_SUNDAY;
 +			 else
 +				doff =3D TM_MONDAY;
 +			 woff =3D i;
  			 continue;

  		case 'w':	/* The day of week, beginning on sunday. =
 */
  			bp =3D conv_num(bp, &tm->tm_wday, 0, 6);
  			LEGAL_ALT(ALT_O);
 +			flags |=3D FLAG_WDAY;
  			continue;

  		case 'u':	/* The day of week, monday =3D 1. */
 @@ -336,6 +374,7 @@
  			bp =3D conv_num(bp, &i, 0, 9999);
  			tm->tm_year =3D i - TM_YEAR_BASE;
  			LEGAL_ALT(ALT_E);
 +			flags |=3D FLAG_YEAR;
  			continue;

  		case 'y':	/* The year within 100 years of the =
 epoch. */
 @@ -353,6 +392,7 @@
  					i =3D i + 1900 - TM_YEAR_BASE;
  			}
  			tm->tm_year =3D i;
 +			flags |=3D FLAG_YEAR;
  			continue;

  		case 'Z':
 @@ -425,6 +465,7 @@
  				continue;
  			case '+':
  				neg =3D 0;
 +				flags |=3D FLAG_WDAY | FLAG_MTH | =
 FLAG_MDAY | FLAG_YEAR;
  				break;
  			case '-':
  				neg =3D 1;
 @@ -529,6 +570,52 @@
  		}
  	}

 +	if (!(flags & FLAG_YDAY) && (flags & FLAG_YEAR)) {
 +		int isleap =3D is_leap_year(tm->tm_year + TM_YEAR_BASE);
 +		if ((flags & (FLAG_MTH | FLAG_MDAY)) =3D=3D (FLAG_MTH | =
 FLAG_MDAY)) {
 +			tm->tm_yday =3D =
 mths_per_yr_kind[isleap][tm->tm_mon] + (tm->tm_mday - 1);
 +			flags |=3D FLAG_YDAY;
 +		} else if (doff !=3D -1) {
 +			if (!(flags & FLAG_WDAY)) {
 +				tm->tm_wday =3D doff;
 +				flags |=3D FLAG_WDAY;
 +			}
 +			tm->tm_yday =3D (7 - first_wday_of(tm->tm_year + =
 TM_YEAR_BASE) +
 +				doff) % 7 + (woff - 1) * 7 + tm->tm_wday =
 - doff;
 +			flags |=3D FLAG_YDAY;
 +		}
 +	}
 +
 +	if ((flags & (FLAG_YEAR | FLAG_YDAY)) =3D=3D (FLAG_YEAR | =
 FLAG_YDAY)) {
 +		int isleap =3D is_leap_year(tm->tm_year + TM_YEAR_BASE);
 +		if (!(flags & FLAG_MTH)) {
 +			i =3D 0;
 +			while (tm->tm_yday >=3D =
 mths_per_yr_kind[isleap][i])
 +				i ++;
 +			if (i > 12) {
 +				i =3D 1;
 +				tm->tm_yday -=3D =
 mths_per_yr_kind[isleap][12];
 +				tm->tm_year ++;
 +			}
 +			tm->tm_mon =3D i - 1;
 +			flags |=3D FLAG_MTH;
 +		}
 +		if (!(flags & FLAG_MDAY)) {
 +			tm->tm_mday =3D tm->tm_yday - =
 mths_per_yr_kind[isleap][tm->tm_mon] + 1;
 +			flags |=3D FLAG_MDAY;
 +		}
 +		if (!(flags & FLAG_WDAY)) {
 +			i =3D 0;
 +			woff =3D first_wday_of(tm->tm_year);
 +			while (i ++ <=3D tm->tm_yday) {
 +				if (woff ++ >=3D 6)
 +					woff =3D 0;
 +			}
 +			tm->tm_wday =3D woff;
 +			flags |=3D FLAG_WDAY;
 +		}
 +	}
 +
  	return __UNCONST(bp);
  }






 > On 29 Jun 2015, at 22:45, David CARLIER <devnexen@gmail.com> wrote:
 >=20
 > The following reply was made to PR lib/50009; it has been noted by =
 GNATS.
 >=20
 > From: David CARLIER <devnexen@gmail.com>
 > To: gnats-bugs@NetBSD.org
 > Cc:
 > Subject: Re: lib/50009: strptime small enhancement
 > Date: Mon, 29 Jun 2015 22:41:14 +0100
 >=20
 > --Apple-Mail=3D_65474D83-214C-489E-822A-D2420A0A27D0
 > Content-Transfer-Encoding: quoted-printable
 > Content-Type: text/plain;
 > 	charset=3Dutf-8
 >=20
 >=20
 > Here another version based on FreeBSD=3DE2=3D80=3D99s implementation =
 pretty =3D
 > much, works on more use cases than the first version and =
 =3DE2=3D80=3D98U=3DE2=3D80=3D99=3D
 >  and =3DE2=3D80=3D98W=3DE2=3D80=3D99 flags work better.
 >=20
 > Index: time/strptime.c
 > =
 =3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3=
 D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D
 > =
 =3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3=
 D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D
 > =3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D=
 3D=3D3D=3D3D
 > RCS file: /cvsroot/src/lib/libc/time/strptime.c,v
 > retrieving revision 1.39
 > diff -u -r1.39 strptime.c
 > --- time/strptime.c	6 Apr 2015 14:38:22 -0000	1.39
 > +++ time/strptime.c	29 Jun 2015 21:33:46 -0000
 > @@ -36,6 +36,8 @@
 >=20
 >  #include "namespace.h"
 >  #include <sys/localedef.h>
 > +#include <sys/types.h>
 > +#include <sys/clock.h>
 >  #include <ctype.h>
 >  #include <locale.h>
 >  #include <string.h>
 > @@ -60,6 +62,12 @@
 >  #define ALT_O			0x02
 >  #define	LEGAL_ALT(x)		{ if (alt_format & ~(x)) return =
 =3D
 > NULL; }
 >=20
 > +#define	FLAG_YEAR	(1 << 0)
 > +#define	FLAG_MTH	(1 << 1)
 > +#define	FLAG_YDAY	(1 << 2)
 > +#define	FLAG_MDAY	(1 << 3)
 > +#define	FLAG_WDAY	(1 << 4)
 > +
 >  static char gmt[] =3D3D { "GMT" };
 >  static char utc[] =3D3D { "UTC" };
 >  /* RFC-822/RFC-2822 */
 > @@ -74,6 +82,18 @@
 >  static const u_char *find_string(const u_char *, int *, const char * =
 =3D
 > const *,
 >  	const char * const *, int);
 >=20
 > +static const int mths_per_yr_kind[2][13] =3D3D {
 > +	{ 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 }
 > +};
 > +
 > +static int
 > +first_wday_of(int yr)
 > +{
 > +	return ((2 * (3 - (yr / 100) % 4)) + (yr % 100) + ((yr % 100) / =
 =3D
 > 4) +
 > +		(is_leap_year(yr) ? 6 : 0) + 1) % 7;
 > +}
 > +
 >  char *
 >  strptime(const char *buf, const char *fmt, struct tm *tm)
 >  {
 > @@ -85,7 +105,7 @@
 >  {
 >  	unsigned char c;
 >  	const unsigned char *bp, *ep;
 > -	int alt_format, i, split_year =3D3D 0, neg =3D3D 0, offs;
 > +	int alt_format, i, split_year =3D3D 0, neg =3D3D 0, flags =3D3D =
 0, =3D
 > doff =3D3D -1, woff =3D3D 0, offs;
 >  	const char *new_fmt;
 >=20
 >  	bp =3D3D (const u_char *)buf;
 > @@ -133,16 +153,19 @@
 >  		 */
 >  		case 'c':	/* Date and time, using the locale's =3D
 > format. */
 >  			new_fmt =3D3D _TIME_LOCALE(loc)->d_t_fmt;
 > +			flags |=3D3D FLAG_WDAY | FLAG_MTH | FLAG_MDAY | =
 =3D
 > FLAG_YEAR;
 >  			goto recurse;
 >=20
 >  		case 'D':	/* The date as "%m/%d/%y". */
 >  			new_fmt =3D3D "%m/%d/%y";
 >  			LEGAL_ALT(0);
 > +			flags |=3D3D FLAG_MTH | FLAG_MDAY | FLAG_YEAR;
 >  			goto recurse;
 >=20
 >  		case 'F':	/* The date as "%Y-%m-%d". */
 >  			new_fmt =3D3D "%Y-%m-%d";
 >  			LEGAL_ALT(0);
 > +			flags |=3D3D FLAG_MTH | FLAG_MDAY | FLAG_YEAR;
 >  			goto recurse;
 >=20
 >  		case 'R':	/* The time as "%H:%M". */
 > @@ -166,6 +189,7 @@
 >=20
 >  		case 'x':	/* The date, using the locale's format. =
 =3D
 > */
 >  			new_fmt =3D3D _TIME_LOCALE(loc)->d_fmt;
 > +			flags |=3D3D FLAG_MTH | FLAG_MDAY | FLAG_YEAR;
 >  		    recurse:
 >  			bp =3D3D (const u_char *)strptime((const char =3D
 > *)bp,
 >  							    new_fmt, =3D
 > tm);
 > @@ -180,6 +204,7 @@
 >  			bp =3D3D find_string(bp, &tm->tm_wday,
 >  			    _TIME_LOCALE(loc)->day, =3D
 > _TIME_LOCALE(loc)->abday, 7);
 >  			LEGAL_ALT(0);
 > +			flags |=3D3D FLAG_WDAY;
 >  			continue;
 >=20
 >  		case 'B':	/* The month, using the locale's form. =3D=

 > */
 > @@ -189,6 +214,7 @@
 >  			    _TIME_LOCALE(loc)->mon, =3D
 > _TIME_LOCALE(loc)->abmon,
 >  			    12);
 >  			LEGAL_ALT(0);
 > +			flags |=3D3D FLAG_MTH;
 >  			continue;
 >=20
 >  		case 'C':	/* The century number. */
 > @@ -201,12 +227,14 @@
 >  			split_year =3D3D 1;
 >  			tm->tm_year =3D3D i;
 >  			LEGAL_ALT(ALT_E);
 > +			flags |=3D3D FLAG_YEAR;
 >  			continue;
 >=20
 >  		case 'd':	/* The day of month. */
 >  		case 'e':
 >  			bp =3D3D conv_num(bp, &tm->tm_mday, 1, 31);
 >  			LEGAL_ALT(ALT_O);
 > +			flags |=3D3D FLAG_MDAY;
 >  			continue;
 >=20
 >  		case 'k':	/* The hour (24-hour clock =3D
 > representation). */
 > @@ -232,6 +260,7 @@
 >  			bp =3D3D conv_num(bp, &i, 1, 366);
 >  			tm->tm_yday =3D3D i - 1;
 >  			LEGAL_ALT(0);
 > +			flags |=3D3D FLAG_YDAY;
 >  			continue;
 >=20
 >  		case 'M':	/* The minute. */
 > @@ -244,6 +273,7 @@
 >  			bp =3D3D conv_num(bp, &i, 1, 12);
 >  			tm->tm_mon =3D3D i - 1;
 >  			LEGAL_ALT(ALT_O);
 > +			flags |=3D3D FLAG_MTH;
 >  			continue;
 >=20
 >  		case 'p':	/* The locale's equivalent of AM/PM. */
 > @@ -287,6 +317,8 @@
 >=20
 >  				if (localtime_r(&sse, tm) =3D3D=3D3D =
 NULL)
 >  					bp =3D3D NULL;
 > +				else
 > +					flags |=3D3D FLAG_YDAY | =
 FLAG_WDAY =3D
 > | FLAG_MTH | FLAG_MDAY | FLAG_YEAR;
 >  			}
 >  			continue;
 >=20
 > @@ -300,11 +332,17 @@
 >  			 */
 >  			 bp =3D3D conv_num(bp, &i, 0, 53);
 >  			 LEGAL_ALT(ALT_O);
 > +			 if (c =3D3D=3D3D 'U')
 > +				doff =3D3D TM_SUNDAY;
 > +			 else
 > +				doff =3D3D TM_MONDAY;
 > +			 woff =3D3D i;
 >  			 continue;
 >=20
 >  		case 'w':	/* The day of week, beginning on sunday. =
 =3D
 > */
 >  			bp =3D3D conv_num(bp, &tm->tm_wday, 0, 6);
 >  			LEGAL_ALT(ALT_O);
 > +			flags |=3D3D FLAG_WDAY;
 >  			continue;
 >=20
 >  		case 'u':	/* The day of week, monday =3D3D 1. */
 > @@ -336,6 +374,7 @@
 >  			bp =3D3D conv_num(bp, &i, 0, 9999);
 >  			tm->tm_year =3D3D i - TM_YEAR_BASE;
 >  			LEGAL_ALT(ALT_E);
 > +			flags |=3D3D FLAG_YEAR;
 >  			continue;
 >=20
 >  		case 'y':	/* The year within 100 years of the =3D
 > epoch. */
 > @@ -353,6 +392,7 @@
 >  					i =3D3D i + 1900 - TM_YEAR_BASE;
 >  			}
 >  			tm->tm_year =3D3D i;
 > +			flags |=3D3D FLAG_YEAR;
 >  			continue;
 >=20
 >  		case 'Z':
 > @@ -425,6 +465,7 @@
 >  				continue;
 >  			case '+':
 >  				neg =3D3D 0;
 > +				flags |=3D3D FLAG_WDAY | FLAG_MTH | =3D
 > FLAG_MDAY | FLAG_YEAR;
 >  				break;
 >  			case '-':
 >  				neg =3D3D 1;
 > @@ -529,6 +570,52 @@
 >  		}
 >  	}
 >=20
 > +	if (!(flags & FLAG_YDAY) && (flags & FLAG_YEAR)) {
 > +		int isleap =3D3D is_leap_year(tm->tm_year + =
 TM_YEAR_BASE);
 > +		if ((flags & (FLAG_MTH | FLAG_MDAY)) =3D3D=3D3D =
 (FLAG_MTH | =3D
 > FLAG_MDAY)) {
 > +			tm->tm_yday =3D3D =3D
 > mths_per_yr_kind[isleap][tm->tm_mon] + (tm->tm_mday - 1);
 > +			flags |=3D3D FLAG_YDAY;
 > +		} else if (doff !=3D3D -1) {
 > +			if (!(flags & FLAG_WDAY)) {
 > +				tm->tm_wday =3D3D doff;
 > +				flags |=3D3D FLAG_WDAY;
 > +			}
 > +			tm->tm_yday =3D3D (7 - first_wday_of(tm->tm_year =
 + =3D
 > TM_YEAR_BASE) +
 > +				doff) % 7 + (woff - 1) * 7 + tm->tm_wday =
 =3D
 > - doff;
 > +			flags |=3D3D FLAG_YDAY;
 > +		}
 > +	}
 > +
 > +	if ((flags & (FLAG_YEAR | FLAG_YDAY)) =3D3D=3D3D (FLAG_YEAR | =3D
 > FLAG_YDAY)) {
 > +		int isleap =3D3D is_leap_year(tm->tm_year + =
 TM_YEAR_BASE);
 > +		if (!(flags & FLAG_MTH)) {
 > +			i =3D3D 0;
 > +			while (tm->tm_yday >=3D3D =3D
 > mths_per_yr_kind[isleap][i])
 > +				i ++;
 > +			if (i > 12) {
 > +				i =3D3D 1;
 > +				tm->tm_yday -=3D3D =3D
 > mths_per_yr_kind[isleap][12];
 > +				tm->tm_year ++;
 > +			}
 > +			tm->tm_mon =3D3D i - 1;
 > +			flags |=3D3D FLAG_MTH;
 > +		}
 > +		if (!(flags & FLAG_MDAY)) {
 > +			tm->tm_mday =3D3D tm->tm_yday - =3D
 > mths_per_yr_kind[isleap][tm->tm_mon] + 1;
 > +			flags |=3D3D FLAG_MDAY;
 > +		}
 > +		if (!(flags & FLAG_WDAY)) {
 > +			i =3D3D 0;
 > +			woff =3D3D first_wday_of(tm->tm_year);
 > +			while (i ++ <=3D3D tm->tm_yday) {
 > +				if (woff ++ >=3D3D 6)
 > +					woff =3D3D 0;
 > +			}
 > +			tm->tm_wday =3D3D woff;
 > +			flags |=3D3D FLAG_WDAY;
 > +		}
 > +	}
 > +
 >  	return __UNCONST(bp);
 >  }
 >=20
 >=20
 >=20
 >> On 29 Jun 2015, at 19:55, Christos Zoulas <christos@zoulas.com> =
 wrote:
 >> =3D20
 >> The following reply was made to PR lib/50009; it has been noted by =3D
 > GNATS.
 >> =3D20
 >> From: christos@zoulas.com (Christos Zoulas)
 >> To: gnats-bugs@NetBSD.org, lib-bug-people@netbsd.org,
 >> 	gnats-admin@netbsd.org, netbsd-bugs@netbsd.org, =3D
 > devnexen@gmail.com
 >> Cc:
 >> Subject: Re: lib/50009: strptime small enhancement
 >> Date: Mon, 29 Jun 2015 14:53:59 -0400
 >> =3D20
 >> On Jun 29,  6:50pm, devnexen@gmail.com (David CARLIER) wrote:
 >> -- Subject: Re: lib/50009: strptime small enhancement
 >> =3D20
 >> |  Well, it's closer to OpenBSD version but I m not against following
 >> |  FreeBSD's path personally. If it s better I can provide a newer =3D
 > version?
 >> =3D20
 >> Sure, why don't you look at them both and make a recommendation?
 >> =3D20
 >> Thanks,
 >> =3D20
 >> christos
 >> =3D20
 >=20
 >=20
 > --Apple-Mail=3D_65474D83-214C-489E-822A-D2420A0A27D0
 > Content-Transfer-Encoding: 7bit
 > Content-Disposition: attachment;
 > 	filename=3Dsignature.asc
 > Content-Type: application/pgp-signature;
 > 	name=3Dsignature.asc
 > Content-Description: Message signed with OpenPGP using GPGMail
 >=20
 > -----BEGIN PGP SIGNATURE-----
 > Comment: GPGTools - https://gpgtools.org
 >=20
 > iQEcBAEBCgAGBQJVkbt/AAoJECNxxoUnxrf44tUH/1jH39r64I3xXXlZhLA9HHLx
 > LIN+YXIxB3lVHNYjnM63W6YnEzUrlG4o3OTbtHn6PDk1D7zyg/SI0cVo95Gk9C+r
 > ryKAfnyhmnCi34jdU4FQ79u4yqDxJawGZBeiiIYANg1od+cNfC2t8j4U4qDm53nO
 > BoVhjTE1c978h1TShdaB66+LDJiLwIpL8X7JUU4UmskgJ65Knysa/91ZD36iUUxM
 > O7iZAdOiQMENVKMC/LPL8FF6I/BaRYpcfNhuqGh6kmYuF3AA1wZnwWjQNpv70f5U
 > Zmz34/4pjFuHDgBC3Gx6slukYl9IWY+yFXEIOdfDiK53Ejrtw9SzhoIrIxdkVCs=3D
 > =3Djl1Z
 > -----END PGP SIGNATURE-----
 >=20
 > --Apple-Mail=3D_65474D83-214C-489E-822A-D2420A0A27D0--
 >=20


 --Apple-Mail=_B162FE6C-9B49-46CF-85BE-D64EE31B7CD3
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
 	filename=signature.asc
 Content-Type: application/pgp-signature;
 	name=signature.asc
 Content-Description: Message signed with OpenPGP using GPGMail

 -----BEGIN PGP SIGNATURE-----
 Comment: GPGTools - https://gpgtools.org

 iQEcBAEBCgAGBQJVlhK6AAoJECNxxoUnxrf4uzQIAJrjyYxZ5bEVO8GuglCygOsc
 Mx5/mUf9HWl9IYN+hJbL62cLMA2aLxMPEQ/cUgEfcEjJrcRidi8Q/vcM/Vskdm7X
 mVG7Sdm9NpryG52MWUHNhu5g2a+2heTipNCxazo+IMWIU8mOwB6LyhnzWbyHmDpc
 5+Z8MLWzZvjCLwCcbU+S5rUbNn1EFvNx7Yl5aQ6v8MjyvZm14o3B/ZIGGdn8mj4c
 be0isx8Pnhvfr8Cmr+7f7L2zndiX4ma44zkKU0lYNa/zYxH/6uZaxMOPten7QxwR
 6tcri8Gz8gZAnUDqL6g6eDSZ/uL8y9BIFi8HC2UbTMCzD0ZPOmfj15XCtao54oQ=
 =H8E5
 -----END PGP SIGNATURE-----

 --Apple-Mail=_B162FE6C-9B49-46CF-85BE-D64EE31B7CD3--

From: "Christos Zoulas" <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/50009 CVS commit: src/lib/libc/time
Date: Fri, 3 Jul 2015 09:06:55 -0400

 Module Name:	src
 Committed By:	christos
 Date:		Fri Jul  3 13:06:55 UTC 2015

 Modified Files:
 	src/lib/libc/time: strptime.c

 Log Message:
 PR/50009: David CARLIER: Enhance strptime to fill out more fields when it
 can. From FreeBSD.


 To generate a diff of this commit:
 cvs rdiff -u -r1.39 -r1.40 src/lib/libc/time/strptime.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

State-Changed-From-To: open->closed
State-Changed-By: dholland@NetBSD.org
State-Changed-When: Sat, 04 Jul 2015 08:27:45 +0000
State-Changed-Why:
Christos committed it; thanks!


From: Brian Ginsbach <ginsbach@netbsd.org>
To: matthew green <mrg@eterna.com.au>
Cc: gnats-bugs@NetBSD.org, lib-bug-people@netbsd.org,
	gnats-admin@netbsd.org, netbsd-bugs@netbsd.org, devnexen@gmail.com
Subject: Re: lib/50009: strptime small enhancement
Date: Thu, 9 Jul 2015 12:45:07 +0000

 On Mon, Jun 29, 2015 at 02:42:18PM +1000, matthew green wrote:
 > 
 > >  On Sun, Jun 28, 2015 at 07:50:00PM +0000, devnexen@gmail.com wrote:
 > >   > +#ifndef ISLEAPYEAR
 > >   > +#define ISLEAPYEAR(y) ((y % 400) == 0 && (y % 4) == 0 && (y % 100) != 0)
 > >   > +#endif
 > >  
 > >  ...this is wrong...
 > 
 > indeed, sys/clock.h has this:
 > 
 > 63 /*
 > 64  * This inline avoids some unnecessary modulo operations
 > 65  * as compared with the usual macro:
 > 66  *   ( ((year % 4) == 0 &&
 > 67  *      (year % 100) != 0) ||
 > 68  *     ((year % 400) == 0) )
 > 69  * It is otherwise equivalent.
 > 70  */
 > 71 static inline int
 > 72 is_leap_year(uint64_t year)
 > 73 {
 > 74         if ((year & 3) != 0)
 > 75                 return 0;
 > 76
 > 77         if (__predict_false((year % 100) != 0))
 > 78                 return 1;
 > 79
 > 80         return __predict_false((year % 400) == 0);
 > 81 }
 > 
 > which should probably be used instead, for netbsd, or at
 > least the same expression in the comment.
 > 
 > (the macro above also doesn't work properly for various
 > inputs, like a good macro should.)
 > 
 > 

 Is there some specific reason why the sys/clock.h version should be preferred over
 the macros in libc/time/tzfile.h which are used throughout the rest of the the
 libc/time code?

 154 #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
 155 
 156 /*
 157 ** Since everything in isleap is modulo 400 (or a factor of 400), we know that
 158 **      isleap(y) == isleap(y % 400)
 159 ** and so
 160 **      isleap(a + b) == isleap((a + b) % 400)
 161 ** or
 162 **      isleap(a + b) == isleap(a % 400 + b % 400)
 163 ** This is true even if % means modulo rather than Fortran remainder
 164 ** (which is allowed by C89 but not C99).
 165 ** We use this to avoid addition overflow problems.
 166 */
 167 
 168 #define isleap_sum(a, b)        isleap((a) % 400 + (b) % 400)

 Wouldn't it be more consistent to keep using the same macro(s) throughout all the
 libc/time code?

 Brian

From: christos@zoulas.com (Christos Zoulas)
To: Brian Ginsbach <ginsbach@netbsd.org>, matthew green <mrg@eterna.com.au>
Cc: gnats-bugs@NetBSD.org, lib-bug-people@netbsd.org, 
	gnats-admin@netbsd.org, netbsd-bugs@netbsd.org, devnexen@gmail.com
Subject: Re: lib/50009: strptime small enhancement
Date: Thu, 9 Jul 2015 08:48:08 -0400

 On Jul 9, 12:45pm, ginsbach@netbsd.org (Brian Ginsbach) wrote:
 -- Subject: Re: lib/50009: strptime small enhancement

 | Wouldn't it be more consistent to keep using the same macro(s) throughout all the
 | libc/time code?

 I think that makes sense.

 christos

>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2014 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.