Re: [PATCH 10/10] timegm: add portable implementation (Solaris support)
authorJani Nikula <jani@nikula.org>
Sun, 4 Nov 2012 10:21:01 +0000 (12:21 +0200)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:50:17 +0000 (09:50 -0800)
38/29cad55131f2a44bb4edb8a6b86bbddfce766f [new file with mode: 0644]

diff --git a/38/29cad55131f2a44bb4edb8a6b86bbddfce766f b/38/29cad55131f2a44bb4edb8a6b86bbddfce766f
new file mode 100644 (file)
index 0000000..a1a7d30
--- /dev/null
@@ -0,0 +1,302 @@
+Return-Path: <jani@nikula.org>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+       by olra.theworths.org (Postfix) with ESMTP id 0253A431FAF\r
+       for <notmuch@notmuchmail.org>; Sun,  4 Nov 2012 02:21:04 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -0.699\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-0.699 tagged_above=-999 required=5\r
+       tests=[HTML_MESSAGE=0.001, RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+       by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+       with ESMTP id pmrY5ULl70g2 for <notmuch@notmuchmail.org>;\r
+       Sun,  4 Nov 2012 02:21:03 -0800 (PST)\r
+Received: from mail-oa0-f53.google.com (mail-oa0-f53.google.com\r
+       [209.85.219.53]) (using TLSv1 with cipher RC4-SHA (128/128 bits))\r
+       (No client certificate requested)\r
+       by olra.theworths.org (Postfix) with ESMTPS id 046CD431FAE\r
+       for <notmuch@notmuchmail.org>; Sun,  4 Nov 2012 02:21:02 -0800 (PST)\r
+Received: by mail-oa0-f53.google.com with SMTP id j6so5171694oag.26\r
+       for <notmuch@notmuchmail.org>; Sun, 04 Nov 2012 02:21:02 -0800 (PST)\r
+X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;\r
+       d=google.com; s=20120113;\r
+       h=mime-version:in-reply-to:references:date:message-id:subject:from:to\r
+       :cc:content-type:x-gm-message-state;\r
+       bh=zXSpgS3DMSzKlCOsj6qCbUDqK64q4wfMITJmEamc3zU=;\r
+       b=epCEiDFpj5uOPRlHcg3XUPubgEI8yDb0b9jNpF3mBg6LNowsC5sPB2Wwaouwrw7Y8w\r
+       lEjlm4N+Aic3G2zYkBCYtlVXreNQXT59jr7JJeBEGQoSib4DfcTLN+TPLi72e8ybx3/O\r
+       XcEEjI8pntMCCFmS3E5ZYH9NIQJ/vOugAEas8Tof6cCwoQEN5aD4iz5UDpUcArL7pNJD\r
+       EuXb8TOmKkB3acEM/N+U9WJkwiSaDPryMRZe7Mt6aq94YdTZMRNOCiJR96P7W2N+RMgD\r
+       gbkZfNsXiQ0WKfBi/XNFmyPmKGjRxuKlcmgBiSzJyQZzhiwoRciGgSRp7g9Yo1pkwIMT\r
+       Dc7A==\r
+MIME-Version: 1.0\r
+Received: by 10.60.19.168 with SMTP id g8mr5235227oee.101.1352024461364; Sun,\r
+       04 Nov 2012 02:21:01 -0800 (PST)\r
+Received: by 10.76.69.138 with HTTP; Sun, 4 Nov 2012 02:21:01 -0800 (PST)\r
+Received: by 10.76.69.138 with HTTP; Sun, 4 Nov 2012 02:21:01 -0800 (PST)\r
+In-Reply-To: <1351998962-25135-11-git-send-email-blakej@foo.net>\r
+References: <1351998962-25135-1-git-send-email-blakej@foo.net>\r
+       <1351998962-25135-11-git-send-email-blakej@foo.net>\r
+Date: Sun, 4 Nov 2012 12:21:01 +0200\r
+Message-ID:\r
+ <CAB+hUn-HBMnbrxQtn4E1RkKJa-wUEvm2HbdvtDxJGrv3jmtQdw@mail.gmail.com>\r
+Subject: Re: [PATCH 10/10] timegm: add portable implementation (Solaris\r
+       support)\r
+From: Jani Nikula <jani@nikula.org>\r
+To: Blake Jones <blakej@foo.net>\r
+Content-Type: multipart/alternative; boundary=e89a8fb2062cbf4fcf04cda8b931\r
+X-Gm-Message-State:\r
+ ALoCoQn8vvIW7D7MKT4K4oUEILFZhdWQoLdHoC0rzjt/+cpov8pWrU3mjywLJxzGQbVepmLRh9xd\r
+Cc: notmuch@notmuchmail.org\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+       <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Sun, 04 Nov 2012 10:21:04 -0000\r
+\r
+--e89a8fb2062cbf4fcf04cda8b931\r
+Content-Type: text/plain; charset=UTF-8\r
+\r
+On Nov 4, 2012 11:30 AM, "Blake Jones" <blakej@foo.net> wrote:\r
+>\r
+> The timegm(3) function is a non-standard extension to libc which is\r
+> available in GNU libc and on some BSDs.  Although SunOS had this\r
+> function in its libc, Solaris (unfortunately) removed it.  This patch\r
+> implements a very simple version of timegm() which is good enough for\r
+> parse-time-string.c.\r
+>\r
+> Although notmuch's idiom for portability is to test for native\r
+> availability and put alternate versions in compat/, that approach led to\r
+> a compilation problem in this case.  libnotmuch.a includes a call to\r
+> parse_time_string() from parse-time-vrp.o, and parse_time_string() in\r
+> libparse-time-string.a needs to call timegm().  An attempt to create\r
+> compat/timegm.c caused the link to fail, because libparse-time-string.a\r
+> acquired a dependency on the new timegm.o in libnotmuch.a, and the\r
+> linker only does a single pass on each ".a" looking for dependencies.\r
+> This seems to be the case both for the GNU linker and the Solaris\r
+> linker.  A different possible workaround would have been to include\r
+> libnotmuch.a multiple times on the link line, but that seemed like a\r
+> brittle way to track this dependency.\r
+\r
+I'd prefer to use timegm() where available, and the suggested alternative\r
+[1] elsewhere. I'll look into the compat build issues when I have a moment.\r
+\r
+Jani.\r
+\r
+[1] http://www.kernel.org/doc/man-pages/online/pages/man3/timegm.3.html\r
+\r
+> ---\r
+>  parse-time-string/parse-time-string.c |   37\r
+++++++++++++++++++++++++++++++++-\r
+>  1 file changed, 36 insertions(+), 1 deletion(-)\r
+>\r
+> diff --git a/parse-time-string/parse-time-string.c\r
+b/parse-time-string/parse-time-string.c\r
+> index 584067d..28901af 100644\r
+> --- a/parse-time-string/parse-time-string.c\r
+> +++ b/parse-time-string/parse-time-string.c\r
+> @@ -1315,6 +1315,41 @@ fixup_ampm (struct state *state)\r
+>      return 0;\r
+>  }\r
+>\r
+> +static int\r
+> +leapyear (int year)\r
+> +{\r
+> +    return ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0));\r
+> +}\r
+> +\r
+> +/*\r
+> + * This is a simple implementation of timegm() which does what is needed\r
+> + * by create_output() -- just turns the "struct tm" into a GMT time_t.\r
+> + * It does not normalize any of the fields of the "struct tm", nor does\r
+> + * it set tm_wday or tm_yday.\r
+> + */\r
+> +static time_t\r
+> +local_timegm (struct tm *tm)\r
+> +{\r
+> +    int        monthlen[2][12] = {\r
+> +       { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },\r
+> +       { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },\r
+> +    };\r
+> +    int        year, month, days;\r
+> +\r
+> +    days = 365 * (tm->tm_year - 70);\r
+> +    for (year = 70; year < tm->tm_year; year++) {\r
+> +       if (leapyear(1900 + year)) {\r
+> +           days++;\r
+> +       }\r
+> +    }\r
+> +    for (month = 0; month < tm->tm_mon; month++) {\r
+> +       days += monthlen[leapyear(1900 + year)][month];\r
+> +    }\r
+> +    days += tm->tm_mday - 1;\r
+> +\r
+> +    return ((((days * 24) + tm->tm_hour) * 60 + tm->tm_min) * 60 +\r
+tm->tm_sec);\r
+> +}\r
+> +\r
+>  /* Combine absolute and relative fields, and round. */\r
+>  static int\r
+>  create_output (struct state *state, time_t *t_out, const time_t *ref,\r
+> @@ -1465,7 +1500,7 @@ create_output (struct state *state, time_t *t_out,\r
+const time_t *ref,\r
+>      if (is_field_set (state, TM_TZ)) {\r
+>         /* tm is in specified TZ, convert to UTC for timegm(3). */\r
+>         tm.tm_min -= get_field (state, TM_TZ);\r
+> -       t = timegm (&tm);\r
+> +       t = local_timegm (&tm);\r
+>      } else {\r
+>         /* tm is in local time. */\r
+>         t = mktime (&tm);\r
+> --\r
+> 1.7.9.2\r
+>\r
+> _______________________________________________\r
+> notmuch mailing list\r
+> notmuch@notmuchmail.org\r
+> http://notmuchmail.org/mailman/listinfo/notmuch\r
+\r
+--e89a8fb2062cbf4fcf04cda8b931\r
+Content-Type: text/html; charset=UTF-8\r
+Content-Transfer-Encoding: quoted-printable\r
+\r
+<p><br>\r
+On Nov 4, 2012 11:30 AM, &quot;Blake Jones&quot; &lt;<a href=3D"mailto:blak=\r
+ej@foo.net">blakej@foo.net</a>&gt; wrote:<br>\r
+&gt;<br>\r
+&gt; The timegm(3) function is a non-standard extension to libc which is<br=\r
+>\r
+&gt; available in GNU libc and on some BSDs. =C2=A0Although SunOS had this<=\r
+br>\r
+&gt; function in its libc, Solaris (unfortunately) removed it. =C2=A0This p=\r
+atch<br>\r
+&gt; implements a very simple version of timegm() which is good enough for<=\r
+br>\r
+&gt; parse-time-string.c.<br>\r
+&gt;<br>\r
+&gt; Although notmuch&#39;s idiom for portability is to test for native<br>\r
+&gt; availability and put alternate versions in compat/, that approach led =\r
+to<br>\r
+&gt; a compilation problem in this case. =C2=A0libnotmuch.a includes a call=\r
+ to<br>\r
+&gt; parse_time_string() from parse-time-vrp.o, and parse_time_string() in<=\r
+br>\r
+&gt; libparse-time-string.a needs to call timegm(). =C2=A0An attempt to cre=\r
+ate<br>\r
+&gt; compat/timegm.c caused the link to fail, because libparse-time-string.=\r
+a<br>\r
+&gt; acquired a dependency on the new timegm.o in libnotmuch.a, and the<br>\r
+&gt; linker only does a single pass on each &quot;.a&quot; looking for depe=\r
+ndencies.<br>\r
+&gt; This seems to be the case both for the GNU linker and the Solaris<br>\r
+&gt; linker. =C2=A0A different possible workaround would have been to inclu=\r
+de<br>\r
+&gt; libnotmuch.a multiple times on the link line, but that seemed like a<b=\r
+r>\r
+&gt; brittle way to track this dependency.</p>\r
+<p>I&#39;d prefer to use timegm() where available, and the suggested altern=\r
+ative [1] elsewhere. I&#39;ll look into the compat build issues when I have=\r
+ a moment.</p>\r
+<p>Jani.</p>\r
+<p>[1] <a href=3D"http://www.kernel.org/doc/man-pages/online/pages/man3/tim=\r
+egm.3.html">http://www.kernel.org/doc/man-pages/online/pages/man3/timegm.3.=\r
+html</a><br></p>\r
+<p>&gt; ---<br>\r
+&gt; =C2=A0parse-time-string/parse-time-string.c | =C2=A0 37 ++++++++++++++=\r
+++++++++++++++++++-<br>\r
+&gt; =C2=A01 file changed, 36 insertions(+), 1 deletion(-)<br>\r
+&gt;<br>\r
+&gt; diff --git a/parse-time-string/parse-time-string.c b/parse-time-string=\r
+/parse-time-string.c<br>\r
+&gt; index 584067d..28901af 100644<br>\r
+&gt; --- a/parse-time-string/parse-time-string.c<br>\r
+&gt; +++ b/parse-time-string/parse-time-string.c<br>\r
+&gt; @@ -1315,6 +1315,41 @@ fixup_ampm (struct state *state)<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0return 0;<br>\r
+&gt; =C2=A0}<br>\r
+&gt;<br>\r
+&gt; +static int<br>\r
+&gt; +leapyear (int year)<br>\r
+&gt; +{<br>\r
+&gt; + =C2=A0 =C2=A0return ((year % 4) =3D=3D 0 &amp;&amp; ((year % 100) !=\r
+=3D 0 || (year % 400) =3D=3D 0));<br>\r
+&gt; +}<br>\r
+&gt; +<br>\r
+&gt; +/*<br>\r
+&gt; + * This is a simple implementation of timegm() which does what is nee=\r
+ded<br>\r
+&gt; + * by create_output() -- just turns the &quot;struct tm&quot; into a =\r
+GMT time_t.<br>\r
+&gt; + * It does not normalize any of the fields of the &quot;struct tm&quo=\r
+t;, nor does<br>\r
+&gt; + * it set tm_wday or tm_yday.<br>\r
+&gt; + */<br>\r
+&gt; +static time_t<br>\r
+&gt; +local_timegm (struct tm *tm)<br>\r
+&gt; +{<br>\r
+&gt; + =C2=A0 =C2=A0int =C2=A0 =C2=A0 =C2=A0 =C2=A0monthlen[2][12] =3D {<br=\r
+>\r
+&gt; + =C2=A0 =C2=A0 =C2=A0 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 3=\r
+1 },<br>\r
+&gt; + =C2=A0 =C2=A0 =C2=A0 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 3=\r
+1 },<br>\r
+&gt; + =C2=A0 =C2=A0};<br>\r
+&gt; + =C2=A0 =C2=A0int =C2=A0 =C2=A0 =C2=A0 =C2=A0year, month, days;<br>\r
+&gt; +<br>\r
+&gt; + =C2=A0 =C2=A0days =3D 365 * (tm-&gt;tm_year - 70);<br>\r
+&gt; + =C2=A0 =C2=A0for (year =3D 70; year &lt; tm-&gt;tm_year; year++) {<b=\r
+r>\r
+&gt; + =C2=A0 =C2=A0 =C2=A0 if (leapyear(1900 + year)) {<br>\r
+&gt; + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 days++;<br>\r
+&gt; + =C2=A0 =C2=A0 =C2=A0 }<br>\r
+&gt; + =C2=A0 =C2=A0}<br>\r
+&gt; + =C2=A0 =C2=A0for (month =3D 0; month &lt; tm-&gt;tm_mon; month++) {<=\r
+br>\r
+&gt; + =C2=A0 =C2=A0 =C2=A0 days +=3D monthlen[leapyear(1900 + year)][month=\r
+];<br>\r
+&gt; + =C2=A0 =C2=A0}<br>\r
+&gt; + =C2=A0 =C2=A0days +=3D tm-&gt;tm_mday - 1;<br>\r
+&gt; +<br>\r
+&gt; + =C2=A0 =C2=A0return ((((days * 24) + tm-&gt;tm_hour) * 60 + tm-&gt;t=\r
+m_min) * 60 + tm-&gt;tm_sec);<br>\r
+&gt; +}<br>\r
+&gt; +<br>\r
+&gt; =C2=A0/* Combine absolute and relative fields, and round. */<br>\r
+&gt; =C2=A0static int<br>\r
+&gt; =C2=A0create_output (struct state *state, time_t *t_out, const time_t =\r
+*ref,<br>\r
+&gt; @@ -1465,7 +1500,7 @@ create_output (struct state *state, time_t *t_ou=\r
+t, const time_t *ref,<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0if (is_field_set (state, TM_TZ)) {<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* tm is in specified TZ, convert to UTC f=\r
+or timegm(3). */<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 tm.tm_min -=3D get_field (state, TM_TZ);<b=\r
+r>\r
+&gt; - =C2=A0 =C2=A0 =C2=A0 t =3D timegm (&amp;tm);<br>\r
+&gt; + =C2=A0 =C2=A0 =C2=A0 t =3D local_timegm (&amp;tm);<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0} else {<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* tm is in local time. */<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 t =3D mktime (&amp;tm);<br>\r
+&gt; --<br>\r
+&gt; 1.7.9.2<br>\r
+&gt;<br>\r
+&gt; _______________________________________________<br>\r
+&gt; notmuch mailing list<br>\r
+&gt; <a href=3D"mailto:notmuch@notmuchmail.org">notmuch@notmuchmail.org</a>=\r
+<br>\r
+&gt; <a href=3D"http://notmuchmail.org/mailman/listinfo/notmuch">http://not=\r
+muchmail.org/mailman/listinfo/notmuch</a><br>\r
+</p>\r
+\r
+--e89a8fb2062cbf4fcf04cda8b931--\r