On Nov 4, 2012 11:30 AM, "Blake Jones" <blakej@foo.net> wrote:
>
> The timegm(3) function is a non-standard extension to libc which is
> available in GNU libc and on some BSDs. Although SunOS had this
> function in its libc, Solaris (unfortunately) removed it. This patch
> implements a very simple version of timegm() which is good enough for
> parse-time-string.c.
>
> Although notmuch's idiom for portability is to test for native
> availability and put alternate versions in compat/, that approach led to
> a compilation problem in this case. libnotmuch.a includes a call to
> parse_time_string() from parse-time-vrp.o, and parse_time_string() in
> libparse-time-string.a needs to call timegm(). An attempt to create
> compat/timegm.c caused the link to fail, because libparse-time-string.a
> acquired a dependency on the new timegm.o in libnotmuch.a, and the
> linker only does a single pass on each ".a" looking for dependencies.
> This seems to be the case both for the GNU linker and the Solaris
> linker. A different possible workaround would have been to include
> libnotmuch.a multiple times on the link line, but that seemed like a
> brittle way to track this dependency.
I'd prefer to use timegm() where available, and the suggested alternative [1] elsewhere. I'll look into the compat build issues when I have a moment.
Jani.
[1] http://www.kernel.org/doc/man-pages/online/pages/man3/timegm.3.html
> ---
> parse-time-string/parse-time-string.c | 37 ++++++++++++++++++++++++++++++++-
> 1 file changed, 36 insertions(+), 1 deletion(-)
>
> diff --git a/parse-time-string/parse-time-string.c b/parse-time-string/parse-time-string.c
> index 584067d..28901af 100644
> --- a/parse-time-string/parse-time-string.c
> +++ b/parse-time-string/parse-time-string.c
> @@ -1315,6 +1315,41 @@ fixup_ampm (struct state *state)
> return 0;
> }
>
> +static int
> +leapyear (int year)
> +{
> + return ((year % 4) = 0 && ((year % 100) != 0 || (year % 400) = 0));
> +}
> +
> +/*
> + * This is a simple implementation of timegm() which does what is needed
> + * by create_output() -- just turns the "struct tm" into a GMT time_t.
> + * It does not normalize any of the fields of the "struct tm", nor does
> + * it set tm_wday or tm_yday.
> + */
> +static time_t
> +local_timegm (struct tm *tm)
> +{
> + int monthlen[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 },
> + };
> + int year, month, days;
> +
> + days = 365 * (tm->tm_year - 70);
> + for (year = 70; year < tm->tm_year; year++) {
> + if (leapyear(1900 + year)) {
> + days++;
> + }
> + }
> + for (month = 0; month < tm->tm_mon; month++) {
> + days += monthlen[leapyear(1900 + year)][month];
> + }
> + days += tm->tm_mday - 1;
> +
> + return ((((days * 24) + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec);
> +}
> +
> /* Combine absolute and relative fields, and round. */
> static int
> create_output (struct state *state, time_t *t_out, const time_t *ref,
> @@ -1465,7 +1500,7 @@ create_output (struct state *state, time_t *t_out, const time_t *ref,
> if (is_field_set (state, TM_TZ)) {
> /* tm is in specified TZ, convert to UTC for timegm(3). */
> tm.tm_min -= get_field (state, TM_TZ);
> - t = timegm (&tm);
> + t = local_timegm (&tm);
> } else {
> /* tm is in local time. */
> t = mktime (&tm);
> --
> 1.7.9.2
>
> _______________________________________________
> notmuch mailing list
> notmuch@notmuchmail.org
> http://notmuchmail.org/mailman/listinfo/notmuch