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