}
#endif /* not SYSTEM_FNMATCH */
+\f
+#ifndef HAVE_TIMEGM
+/* timegm is a GNU extension typically unavailable on non-glibc-based
+ platforms. */
+
+/* Inverse of gmtime: converts struct tm to time_t, assuming the data
+ in tm is UTC rather than local timezone.
+
+ mktime is similar but assumes struct tm, also known as the
+ "broken-down" form of time, is in local time zone. This
+ implementation of timegm uses mktime to make the conversion
+ understanding that an offset will be introduced by the local time
+ assumption.
+
+ timegm then measures the introduced offset by applying gmtime to
+ the initial result and applying mktime to the resulting
+ "broken-down" form. The difference between the two mktime results
+ is the measured offset which is then subtracted from the initial
+ mktime result to yield a calendar time which is the value returned.
+
+ tm_isdst in struct tm is set to 0 to force mktime to introduce a
+ consistent offset (the non DST offset) since tm and tm+o might be
+ on opposite sides of a DST change.
+
+ Some implementations of mktime return -1 for the nonexistent
+ localtime hour at the beginning of DST. In this event, use
+ mktime(tm - 1hr) + 3600.
+
+ Schematically
+ mktime(tm) --> t+o
+ gmtime(t+o) --> tm+o
+ mktime(tm+o) --> t+2o
+ t+o - (t+2o - t+o) = t
+
+ Contributed by Roger Beeman <beeman@cisco.com>, with the help of
+ Mark Baushke <mdb@cisco.com> and other experts at CISCO. Further
+ improved by Roger with assistance from Edward J. Sabol based on
+ input by Jamie Zawinski. */
+
+time_t
+timegm (struct tm *t)
+{
+ time_t tl, tb;
+ struct tm *tg;
+
+ tl = mktime (t);
+ if (tl == -1)
+ {
+ t->tm_hour--;
+ tl = mktime (t);
+ if (tl == -1)
+ return -1; /* can't deal with contents of T */
+ tl += 3600;
+ }
+ tg = gmtime (&tl);
+ tg->tm_isdst = 0;
+ tb = mktime (tg);
+ if (tb == -1)
+ {
+ tg->tm_hour--;
+ tb = mktime (tg);
+ if (tb == -1)
+ return -1; /* can't deal with output from gmtime */
+ tb += 3600;
+ }
+ return (tl - (tb - tl));
+}
+#endif /* HAVE_TIMEGM */