unix-time 0.3.8 → 0.4.0
raw patch · 9 files changed
+1594/−11 lines, 9 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Data.UnixTime: microSecondsToUnixDiffTime :: (Integral a) => a -> UnixDiffTime
+ Data.UnixTime: microSecondsToUnixDiffTime :: Integral a => a -> UnixDiffTime
- Data.UnixTime: secondsToUnixDiffTime :: (Integral a) => a -> UnixDiffTime
+ Data.UnixTime: secondsToUnixDiffTime :: Integral a => a -> UnixDiffTime
Files
- Data/UnixTime/Types.hsc +28/−0
- cbits/config.h.in +12/−0
- cbits/conv.c +36/−10
- cbits/strftime.c +628/−0
- cbits/strptime.c +718/−0
- cbits/win_patch.c +119/−0
- configure +44/−0
- configure.ac +4/−0
- unix-time.cabal +5/−1
Data/UnixTime/Types.hsc view
@@ -4,6 +4,9 @@ import Data.ByteString import Data.ByteString.Char8 () import Data.Int+#if defined(_WIN32)+import Data.Word+#endif import Foreign.C.Types import Foreign.Storable #if __GLASGOW_HASKELL__ >= 704@@ -34,12 +37,37 @@ instance Storable UnixTime where sizeOf _ = (#size struct timeval) alignment _ = (#const offsetof(struct {char x__; struct timeval (y__); }, y__))+#if defined(_WIN32)+ -- On windows, with mingw-w64, the struct `timeval` is defined as+ --+ -- struct timeval+ -- {+ -- long tv_sec;+ -- long tv_usec;+ -- };+ --+ -- The type `long` is 32bit on windows 64bit, however the CTime is 64bit, thus+ -- we must be careful about the layout of its foreign memory.+ --+ -- Here we try use Word32, rather than Int32, to support as large value as possible.+ -- For example, we use `4294967295` as utSeconds in testsuite, which already exceeds+ -- the range of Int32, but not for Word32.+ peek ptr = do+ sec <- (#peek struct timeval, tv_sec) ptr :: IO Word32+ msec <- (#peek struct timeval, tv_usec) ptr+ return $ UnixTime (fromIntegral sec) msec+ poke ptr ut = do+ let CTime sec = utSeconds ut+ (#poke struct timeval, tv_sec) ptr (fromIntegral sec :: Word32)+ (#poke struct timeval, tv_usec) ptr (utMicroSeconds ut)+#else peek ptr = UnixTime <$> (#peek struct timeval, tv_sec) ptr <*> (#peek struct timeval, tv_usec) ptr poke ptr ut = do (#poke struct timeval, tv_sec) ptr (utSeconds ut) (#poke struct timeval, tv_usec) ptr (utMicroSeconds ut)+#endif #if __GLASGOW_HASKELL__ >= 704 instance Binary UnixTime where
cbits/config.h.in view
@@ -30,6 +30,18 @@ /* Define to 1 if you have the `timegm' function. */ #undef HAVE_TIMEGM +/* Define to 1 if you have the `_mkgmtime' function. */+#undef HAVE__MKGMTIME++/* Define to 1 if you have the `_get_current_locale' function. */+#undef HAVE__GET_CURRENT_LOCALE++/* Define to 1 if you have the `strtol_l' function. */+#undef HAVE_STRTOL_L++/* Define to 1 if you have the `strtoll_l' function. */+#undef HAVE_STRTOLL_L+ /* Define to 1 if you have the <unistd.h> header file. */ #undef HAVE_UNISTD_H
cbits/conv.c view
@@ -16,7 +16,12 @@ #include <time.h> #include <locale.h> #include <stdlib.h>+#include <stdio.h> +#if defined(_WIN32)+#include "win_patch.h"+#endif // _WIN32+ #if THREAD_SAFE #if HAVE_XLOCALE_H #include <xlocale.h>@@ -32,7 +37,7 @@ static int initialized = 0; if (initialized == 0) { setlocale(LC_TIME, "C");- initialized == 1;+ initialized = 1; } } #endif@@ -44,7 +49,11 @@ char *set_tz_utc() { char *tz; tz = getenv("TZ");+#if defined(_WIN32)+ _patch_setenv("TZ", "", 1);+#else setenv("TZ", "", 1);+#endif tzset(); return tz; }@@ -55,9 +64,17 @@ */ void set_tz(char *local_tz) { if (local_tz) {+#if defined(_WIN32)+ _patch_setenv("TZ", local_tz, 1);+#else setenv("TZ", local_tz, 1);+#endif } else {+#if defined(_WIN32)+ _patch_unsetenv("TZ");+#else unsetenv("TZ");+#endif } tzset(); }@@ -83,13 +100,6 @@ * All rights reserved. */ -static int-is_leap(unsigned y)-{- y += 1900;- return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0);-}- static time_t timegm (struct tm *tm) {@@ -100,10 +110,10 @@ unsigned i; for (i = 70; i < tm->tm_year; ++i)- res += is_leap(i) ? 366 : 365;+ res += isleap(i + 1900) ? 366 : 365; for (i = 0; i < tm->tm_mon; ++i)- res += ndays[is_leap(tm->tm_year)][i];+ res += ndays[isleap(tm->tm_year + 1900)][i]; res += tm->tm_mday - 1; res *= 24; res += tm->tm_hour;@@ -135,9 +145,17 @@ init_locale(); localtime_r(&src, &tim); #if THREAD_SAFE+#if defined(_WIN32)+ return _patch_strftime_l(dst, siz, fmt, &tim, c_locale);+#else return strftime_l(dst, siz, fmt, &tim, c_locale);+#endif // _WIN32 #else+#if defined(_WIN32)+ return _patch_strftime(dst, siz, fmt, &tim);+#else return strftime(dst, siz, fmt, &tim);+#endif // _WIN32 #endif } @@ -151,9 +169,17 @@ local_tz = set_tz_utc(); #if THREAD_SAFE+#if defined(_WIN32)+ dst_size = _patch_strftime_l(dst, siz, fmt, &tim, c_locale);+#else dst_size = strftime_l(dst, siz, fmt, &tim, c_locale);+#endif // _WIN32 #else+#if defined(_WIN32)+ dst_size = _patch_strftime(dst, siz, fmt, &tim);+#else dst_size = strftime(dst, siz, fmt, &tim);+#endif // _WIN32 #endif set_tz(local_tz); return dst_size;
+ cbits/strftime.c view
@@ -0,0 +1,628 @@+/*+ * Copyright (c) 1989 The Regents of the University of California.+ * All rights reserved.+ *+ * Copyright (c) 2011 The FreeBSD Foundation+ * All rights reserved.+ * Portions of this software were developed by David Chisnall+ * under sponsorship from the FreeBSD Foundation.+ *+ * Redistribution and use in source and binary forms are permitted+ * provided that the above copyright notice and this paragraph are+ * duplicated in all such forms and that any documentation,+ * advertising materials, and other materials related to such+ * distribution and use acknowledge that the software was developed+ * by the University of California, Berkeley. The name of the+ * University may not be used to endorse or promote products derived+ * from this software without specific prior written permission.+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.+ */++#include <fcntl.h>+#include <sys/cdefs.h>+#include <sys/stat.h>++#include <time.h>+#include <ctype.h>+#include <errno.h>+#include <locale.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <pthread.h>++#include "win_patch.h"++static char * _add(const char *, char *, const char *);+static char * _conv(int, const char *, char *, const char *, _locale_t);+static char * _fmt(const char *, const struct tm *, char *, const char *,+ int *, _locale_t);+static char * _yconv(int, int, int, int, char *, const char *, _locale_t);++#ifndef YEAR_2000_NAME+#define YEAR_2000_NAME "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"+#endif /* !defined YEAR_2000_NAME */++#define IN_NONE 0+#define IN_SOME 1+#define IN_THIS 2+#define IN_ALL 3++#define PAD_DEFAULT 0+#define PAD_LESS 1+#define PAD_SPACE 2+#define PAD_ZERO 3++static const char fmt_padding[][4][5] = {+ /* DEFAULT, LESS, SPACE, ZERO */+#define PAD_FMT_MONTHDAY 0+#define PAD_FMT_HMS 0+#define PAD_FMT_CENTURY 0+#define PAD_FMT_SHORTYEAR 0+#define PAD_FMT_MONTH 0+#define PAD_FMT_WEEKOFYEAR 0+#define PAD_FMT_DAYOFMONTH 0+ { "%02d", "%d", "%2d", "%02d" },+#define PAD_FMT_SDAYOFMONTH 1+#define PAD_FMT_SHMS 1+ { "%2d", "%d", "%2d", "%02d" },+#define PAD_FMT_DAYOFYEAR 2+ { "%03d", "%d", "%3d", "%03d" },+#define PAD_FMT_YEAR 3+ { "%04d", "%d", "%4d", "%04d" }+};++size_t+_patch_strftime_l(char * __restrict s, size_t maxsize, const char * __restrict format,+ const struct tm * __restrict t, _locale_t loc)+{+ char * p;+ int warn;++ tzset();+ warn = IN_NONE;+ p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn, loc);+#ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU+ if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {+ (void) fprintf_l(stderr, loc, "\n");+ if (format == NULL)+ (void) fputs("NULL strftime format ", stderr);+ else (void) fprintf_l(stderr, loc, "strftime format \"%s\" ",+ format);+ (void) fputs("yields only two digits of years in ", stderr);+ if (warn == IN_SOME)+ (void) fputs("some locales", stderr);+ else if (warn == IN_THIS)+ (void) fputs("the current locale", stderr);+ else (void) fputs("all locales", stderr);+ (void) fputs("\n", stderr);+ }+#endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */+ if (p == s + maxsize)+ return (0);+ *p = '\0';+ return p - s;+}++size_t+_patch_strftime(char * __restrict s, size_t maxsize, const char * __restrict format,+ const struct tm * __restrict t)+{+#if HAVE__GET_CURRENT_LOCALE+ return _patch_strftime_l(s, maxsize, format, t, _get_current_locale());+#else+ return _patch_strftime_l(s, maxsize, format, t, _create_locale(LC_TIME, "C"));+#endif+}++static char *+_fmt(const char *format, const struct tm * const t, char *pt,+ const char * const ptlim, int *warnp, _locale_t loc)+{+ int Ealternative, Oalternative, PadIndex;+ const struct lc_time_T *tptr = &_C_time_locale;++ for ( ; *format; ++format) {+ if (*format == '%') {+ Ealternative = 0;+ Oalternative = 0;+ PadIndex = PAD_DEFAULT;+label:+ switch (*++format) {+ case '\0':+ --format;+ break;+ case 'A':+ pt = _add((t->tm_wday < 0 ||+ t->tm_wday >= DAYSPERWEEK) ?+ "?" : tptr->weekday[t->tm_wday],+ pt, ptlim);+ continue;+ case 'a':+ pt = _add((t->tm_wday < 0 ||+ t->tm_wday >= DAYSPERWEEK) ?+ "?" : tptr->wday[t->tm_wday],+ pt, ptlim);+ continue;+ case 'B':+ pt = _add((t->tm_mon < 0 ||+ t->tm_mon >= MONSPERYEAR) ?+ "?" : (Oalternative ? tptr->alt_month :+ tptr->month)[t->tm_mon],+ pt, ptlim);+ continue;+ case 'b':+ case 'h':+ pt = _add((t->tm_mon < 0 ||+ t->tm_mon >= MONSPERYEAR) ?+ "?" : tptr->mon[t->tm_mon],+ pt, ptlim);+ continue;+ case 'C':+ /*+ * %C used to do a...+ * _fmt("%a %b %e %X %Y", t);+ * ...whereas now POSIX 1003.2 calls for+ * something completely different.+ * (ado, 1993-05-24)+ */+ pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0,+ pt, ptlim, loc);+ continue;+ case 'c':+ {+ int warn2 = IN_SOME;++ pt = _fmt(tptr->c_fmt, t, pt, ptlim, &warn2, loc);+ if (warn2 == IN_ALL)+ warn2 = IN_THIS;+ if (warn2 > *warnp)+ *warnp = warn2;+ }+ continue;+ case 'D':+ pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp, loc);+ continue;+ case 'd':+ pt = _conv(t->tm_mday,+ fmt_padding[PAD_FMT_DAYOFMONTH][PadIndex],+ pt, ptlim, loc);+ continue;+ case 'E':+ if (Ealternative || Oalternative)+ break;+ Ealternative++;+ goto label;+ case 'O':+ /*+ * C99 locale modifiers.+ * The sequences+ * %Ec %EC %Ex %EX %Ey %EY+ * %Od %oe %OH %OI %Om %OM+ * %OS %Ou %OU %OV %Ow %OW %Oy+ * are supposed to provide alternate+ * representations.+ *+ * FreeBSD extension+ * %OB+ */+ if (Ealternative || Oalternative)+ break;+ Oalternative++;+ goto label;+ case 'e':+ pt = _conv(t->tm_mday,+ fmt_padding[PAD_FMT_SDAYOFMONTH][PadIndex],+ pt, ptlim, loc);+ continue;+ case 'F':+ pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp, loc);+ continue;+ case 'H':+ pt = _conv(t->tm_hour, fmt_padding[PAD_FMT_HMS][PadIndex],+ pt, ptlim, loc);+ continue;+ case 'I':+ pt = _conv((t->tm_hour % 12) ?+ (t->tm_hour % 12) : 12,+ fmt_padding[PAD_FMT_HMS][PadIndex],+ pt, ptlim, loc);+ continue;+ case 'j':+ pt = _conv(t->tm_yday + 1,+ fmt_padding[PAD_FMT_DAYOFYEAR][PadIndex],+ pt, ptlim, loc);+ continue;+ case 'k':+ /*+ * This used to be...+ * _conv(t->tm_hour % 12 ?+ * t->tm_hour % 12 : 12, 2, ' ');+ * ...and has been changed to the below to+ * match SunOS 4.1.1 and Arnold Robbins'+ * strftime version 3.0. That is, "%k" and+ * "%l" have been swapped.+ * (ado, 1993-05-24)+ */+ pt = _conv(t->tm_hour, fmt_padding[PAD_FMT_SHMS][PadIndex],+ pt, ptlim, loc);+ continue;+#ifdef KITCHEN_SINK+ case 'K':+ /*+ ** After all this time, still unclaimed!+ */+ pt = _add("kitchen sink", pt, ptlim);+ continue;+#endif /* defined KITCHEN_SINK */+ case 'l':+ /*+ * This used to be...+ * _conv(t->tm_hour, 2, ' ');+ * ...and has been changed to the below to+ * match SunOS 4.1.1 and Arnold Robbin's+ * strftime version 3.0. That is, "%k" and+ * "%l" have been swapped.+ * (ado, 1993-05-24)+ */+ pt = _conv((t->tm_hour % 12) ?+ (t->tm_hour % 12) : 12,+ fmt_padding[PAD_FMT_SHMS][PadIndex],+ pt, ptlim, loc);+ continue;+ case 'M':+ pt = _conv(t->tm_min, fmt_padding[PAD_FMT_HMS][PadIndex],+ pt, ptlim, loc);+ continue;+ case 'm':+ pt = _conv(t->tm_mon + 1,+ fmt_padding[PAD_FMT_MONTH][PadIndex],+ pt, ptlim, loc);+ continue;+ case 'n':+ pt = _add("\n", pt, ptlim);+ continue;+ case 'p':+ pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?+ tptr->pm : tptr->am,+ pt, ptlim);+ continue;+ case 'R':+ pt = _fmt("%H:%M", t, pt, ptlim, warnp, loc);+ continue;+ case 'r':+ pt = _fmt(tptr->ampm_fmt, t, pt, ptlim,+ warnp, loc);+ continue;+ case 'S':+ pt = _conv(t->tm_sec, fmt_padding[PAD_FMT_HMS][PadIndex],+ pt, ptlim, loc);+ continue;+ case 's':+ {+ struct tm tm;+ char buf[INT_STRLEN_MAXIMUM(+ time_t) + 1];+ time_t mkt;++ tm = *t;+ mkt = mktime(&tm);+ if (TYPE_SIGNED(time_t))+ (void) sprintf_l(buf, loc, "%lld", (long long)mkt);+ else+ (void) sprintf_l(buf, loc, "%llu", (unsigned long long)mkt);+ pt = _add(buf, pt, ptlim);+ }+ continue;+ case 'T':+ pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp, loc);+ continue;+ case 't':+ pt = _add("\t", pt, ptlim);+ continue;+ case 'U':+ pt = _conv((t->tm_yday + DAYSPERWEEK -+ t->tm_wday) / DAYSPERWEEK,+ fmt_padding[PAD_FMT_WEEKOFYEAR][PadIndex],+ pt, ptlim, loc);+ continue;+ case 'u':+ /*+ * From Arnold Robbins' strftime version 3.0:+ * "ISO 8601: Weekday as a decimal number+ * [1 (Monday) - 7]"+ * (ado, 1993-05-24)+ */+ pt = _conv((t->tm_wday == 0) ?+ DAYSPERWEEK : t->tm_wday,+ "%d", pt, ptlim, loc);+ continue;+ case 'V': /* ISO 8601 week number */+ case 'G': /* ISO 8601 year (four digits) */+ case 'g': /* ISO 8601 year (two digits) */+/*+ * From Arnold Robbins' strftime version 3.0: "the week number of the+ * year (the first Monday as the first day of week 1) as a decimal number+ * (01-53)."+ * (ado, 1993-05-24)+ *+ * From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn:+ * "Week 01 of a year is per definition the first week which has the+ * Thursday in this year, which is equivalent to the week which contains+ * the fourth day of January. In other words, the first week of a new year+ * is the week which has the majority of its days in the new year. Week 01+ * might also contain days from the previous year and the week before week+ * 01 of a year is the last week (52 or 53) of the previous year even if+ * it contains days from the new year. A week starts with Monday (day 1)+ * and ends with Sunday (day 7). For example, the first week of the year+ * 1997 lasts from 1996-12-30 to 1997-01-05..."+ * (ado, 1996-01-02)+ */+ {+ int year;+ int base;+ int yday;+ int wday;+ int w;++ year = t->tm_year;+ base = TM_YEAR_BASE;+ yday = t->tm_yday;+ wday = t->tm_wday;+ for ( ; ; ) {+ int len;+ int bot;+ int top;++ len = isleap_sum(year, base) ?+ DAYSPERLYEAR :+ DAYSPERNYEAR;+ /*+ * What yday (-3 ... 3) does+ * the ISO year begin on?+ */+ bot = ((yday + 11 - wday) %+ DAYSPERWEEK) - 3;+ /*+ * What yday does the NEXT+ * ISO year begin on?+ */+ top = bot -+ (len % DAYSPERWEEK);+ if (top < -3)+ top += DAYSPERWEEK;+ top += len;+ if (yday >= top) {+ ++base;+ w = 1;+ break;+ }+ if (yday >= bot) {+ w = 1 + ((yday - bot) /+ DAYSPERWEEK);+ break;+ }+ --base;+ yday += isleap_sum(year, base) ?+ DAYSPERLYEAR :+ DAYSPERNYEAR;+ }+#ifdef XPG4_1994_04_09+ if ((w == 52 &&+ t->tm_mon == TM_JANUARY) ||+ (w == 1 &&+ t->tm_mon == TM_DECEMBER))+ w = 53;+#endif /* defined XPG4_1994_04_09 */+ if (*format == 'V')+ pt = _conv(w, fmt_padding[PAD_FMT_WEEKOFYEAR][PadIndex],+ pt, ptlim, loc);+ else if (*format == 'g') {+ *warnp = IN_ALL;+ pt = _yconv(year, base, 0, 1,+ pt, ptlim, loc);+ } else pt = _yconv(year, base, 1, 1,+ pt, ptlim, loc);+ }+ continue;+ case 'v':+ /*+ * From Arnold Robbins' strftime version 3.0:+ * "date as dd-bbb-YYYY"+ * (ado, 1993-05-24)+ */+ pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp, loc);+ continue;+ case 'W':+ pt = _conv((t->tm_yday + DAYSPERWEEK -+ (t->tm_wday ?+ (t->tm_wday - 1) :+ (DAYSPERWEEK - 1))) / DAYSPERWEEK,+ fmt_padding[PAD_FMT_WEEKOFYEAR][PadIndex],+ pt, ptlim, loc);+ continue;+ case 'w':+ pt = _conv(t->tm_wday, "%d", pt, ptlim, loc);+ continue;+ case 'X':+ pt = _fmt(tptr->X_fmt, t, pt, ptlim, warnp, loc);+ continue;+ case 'x':+ {+ int warn2 = IN_SOME;++ pt = _fmt(tptr->x_fmt, t, pt, ptlim, &warn2, loc);+ if (warn2 == IN_ALL)+ warn2 = IN_THIS;+ if (warn2 > *warnp)+ *warnp = warn2;+ }+ continue;+ case 'y':+ *warnp = IN_ALL;+ pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1,+ pt, ptlim, loc);+ continue;+ case 'Y':+ pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1,+ pt, ptlim, loc);+ continue;+ case 'Z':+#ifdef TM_ZONE+ if (t->TM_ZONE != NULL)+ pt = _add(t->TM_ZONE, pt, ptlim);+ else+#endif /* defined TM_ZONE */+ if (t->tm_isdst >= 0)+ pt = _add(tzname[t->tm_isdst != 0],+ pt, ptlim);+ /*+ * C99 says that %Z must be replaced by the+ * empty string if the time zone is not+ * determinable.+ */+ continue;+ case 'z':+ {+ int diff;+ char const * sign;++ if (t->tm_isdst < 0)+ continue;+#ifdef TM_GMTOFF+ diff = t->TM_GMTOFF;+#else /* !defined TM_GMTOFF */+ /*+ * C99 says that the UTC offset must+ * be computed by looking only at+ * tm_isdst. This requirement is+ * incorrect, since it means the code+ * must rely on magic (in this case+ * altzone and timezone), and the+ * magic might not have the correct+ * offset. Doing things correctly is+ * tricky and requires disobeying C99;+ * see GNU C strftime for details.+ * For now, punt and conform to the+ * standard, even though it's incorrect.+ *+ * C99 says that %z must be replaced by the+ * empty string if the time zone is not+ * determinable, so output nothing if the+ * appropriate variables are not available.+ */+ if (t->tm_isdst == 0)+ diff = -timezone;+ else+#ifdef ALTZONE+ diff = -altzone;+#else /* !defined ALTZONE */+ continue;+#endif /* !defined ALTZONE */+#endif /* !defined TM_GMTOFF */+ if (diff < 0) {+ sign = "-";+ diff = -diff;+ } else+ sign = "+";+ pt = _add(sign, pt, ptlim);+ diff /= SECSPERMIN;+ diff = (diff / MINSPERHOUR) * 100 ++ (diff % MINSPERHOUR);+ pt = _conv(diff,+ fmt_padding[PAD_FMT_YEAR][PadIndex],+ pt, ptlim, loc);+ }+ continue;+ case '+':+ pt = _fmt(tptr->date_fmt, t, pt, ptlim,+ warnp, loc);+ continue;+ case '-':+ if (PadIndex != PAD_DEFAULT)+ break;+ PadIndex = PAD_LESS;+ goto label;+ case '_':+ if (PadIndex != PAD_DEFAULT)+ break;+ PadIndex = PAD_SPACE;+ goto label;+ case '0':+ if (PadIndex != PAD_DEFAULT)+ break;+ PadIndex = PAD_ZERO;+ goto label;+ case '%':+ /*+ * X311J/88-090 (4.12.3.5): if conversion char is+ * undefined, behavior is undefined. Print out the+ * character itself as printf(3) also does.+ */+ default:+ break;+ }+ }+ if (pt == ptlim)+ break;+ *pt++ = *format;+ }+ return (pt);+}++static char *+_conv(const int n, const char * const format, char * const pt,+ const char * const ptlim, _locale_t loc)+{+ char buf[INT_STRLEN_MAXIMUM(int) + 1];++ (void) sprintf_l(buf, loc, format, n);+ return _add(buf, pt, ptlim);+}++static char *+_add(const char *str, char *pt, const char * const ptlim)+{+ while (pt < ptlim && (*pt = *str++) != '\0')+ ++pt;+ return (pt);+}++/*+ * POSIX and the C Standard are unclear or inconsistent about+ * what %C and %y do if the year is negative or exceeds 9999.+ * Use the convention that %C concatenated with %y yields the+ * same output as %Y, and that %Y contains at least 4 bytes,+ * with more only if necessary.+ */++static char *+_yconv(const int a, const int b, const int convert_top, const int convert_yy,+ char *pt, const char * const ptlim, _locale_t loc)+{+ register int lead;+ register int trail;++#define DIVISOR 100+ trail = a % DIVISOR + b % DIVISOR;+ lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR;+ trail %= DIVISOR;+ if (trail < 0 && lead > 0) {+ trail += DIVISOR;+ --lead;+ } else if (lead < 0 && trail > 0) {+ trail -= DIVISOR;+ ++lead;+ }+ if (convert_top) {+ if (lead == 0 && trail < 0)+ pt = _add("-0", pt, ptlim);+ else pt = _conv(lead, "%02d", pt, ptlim, loc);+ }+ if (convert_yy)+ pt = _conv(((trail < 0) ? -trail : trail), "%02d", pt,+ ptlim, loc);+ return (pt);+}
+ cbits/strptime.c view
@@ -0,0 +1,718 @@+/*-+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD+ *+ * Copyright (c) 2014 Gary Mills+ * Copyright 2011, Nexenta Systems, Inc. All rights reserved.+ * Copyright (c) 1994 Powerdog Industries. All rights reserved.+ *+ * Copyright (c) 2011 The FreeBSD Foundation+ * All rights reserved.+ * Portions of this software were developed by David Chisnall+ * under sponsorship from the FreeBSD Foundation.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ * notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ * notice, this list of conditions and the following disclaimer+ * in the documentation and/or other materials provided with the+ * distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ *+ * The views and conclusions contained in the software and documentation+ * are those of the authors and should not be interpreted as representing+ * official policies, either expressed or implied, of Powerdog Industries.+ */++#include <sys/cdefs.h>++#include <time.h>+#include <ctype.h>+#include <errno.h>+#include <locale.h>+#include <stdlib.h>+#include <string.h>+#include <pthread.h>++#include "win_patch.h"++static char * _strptime(const char *, const char *, struct tm *, int *, _locale_t);++#define asizeof(a) (sizeof(a) / sizeof((a)[0]))++#define FLAG_NONE (1 << 0)+#define FLAG_YEAR (1 << 1)+#define FLAG_MONTH (1 << 2)+#define FLAG_YDAY (1 << 3)+#define FLAG_MDAY (1 << 4)+#define FLAG_WDAY (1 << 5)++/*+ * Calculate the week day of the first day of a year. Valid for+ * the Gregorian calendar, which began Sept 14, 1752 in the UK+ * and its colonies. Ref:+ * http://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week+ */++static int+first_wday_of(int year)+{+ return (((2 * (3 - (year / 100) % 4)) + (year % 100) ++ ((year % 100) / 4) + (isleap(year) ? 6 : 0) + 1) % 7);+}++static char *+_strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp,+ _locale_t locale)+{+ char c;+ const char *ptr;+ int day_offset = -1, wday_offset;+ int week_offset;+ int i, len;+ int flags;+ int Ealternative, Oalternative;+ int century, year;+ const struct lc_time_T *tptr = &_C_time_locale;+ static int start_of_month[2][13] = {+ {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}+ };++ flags = FLAG_NONE;+ century = -1;+ year = -1;++ ptr = fmt;+ while (*ptr != 0) {+ c = *ptr++;++ if (c != '%') {+ if (isspace_l((unsigned char)c, locale))+ while (*buf != 0 && + isspace_l((unsigned char)*buf, locale))+ buf++;+ else if (c != *buf++)+ return (NULL);+ continue;+ }++ Ealternative = 0;+ Oalternative = 0;+label:+ c = *ptr++;+ switch (c) {+ case '%':+ if (*buf++ != '%')+ return (NULL);+ break;++ case '+':+ buf = _strptime(buf, tptr->date_fmt, tm, GMTp, locale);+ if (buf == NULL)+ return (NULL);+ flags |= FLAG_WDAY | FLAG_MONTH | FLAG_MDAY | FLAG_YEAR;+ break;++ case 'C':+ if (!isdigit_l((unsigned char)*buf, locale))+ return (NULL);++ /* XXX This will break for 3-digit centuries. */+ len = 2;+ for (i = 0; len && *buf != 0 &&+ isdigit_l((unsigned char)*buf, locale); buf++) {+ i *= 10;+ i += *buf - '0';+ len--;+ }++ century = i;+ flags |= FLAG_YEAR;++ break;++ case 'c':+ buf = _strptime(buf, tptr->c_fmt, tm, GMTp, locale);+ if (buf == NULL)+ return (NULL);+ flags |= FLAG_WDAY | FLAG_MONTH | FLAG_MDAY | FLAG_YEAR;+ break;++ case 'D':+ buf = _strptime(buf, "%m/%d/%y", tm, GMTp, locale);+ if (buf == NULL)+ return (NULL);+ flags |= FLAG_MONTH | FLAG_MDAY | FLAG_YEAR;+ break;++ case 'E':+ if (Ealternative || Oalternative)+ break;+ Ealternative++;+ goto label;++ case 'O':+ if (Ealternative || Oalternative)+ break;+ Oalternative++;+ goto label;++ case 'F':+ buf = _strptime(buf, "%Y-%m-%d", tm, GMTp, locale);+ if (buf == NULL)+ return (NULL);+ flags |= FLAG_MONTH | FLAG_MDAY | FLAG_YEAR;+ break;++ case 'R':+ buf = _strptime(buf, "%H:%M", tm, GMTp, locale);+ if (buf == NULL)+ return (NULL);+ break;++ case 'r':+ buf = _strptime(buf, tptr->ampm_fmt, tm, GMTp, locale);+ if (buf == NULL)+ return (NULL);+ break;++ case 'T':+ buf = _strptime(buf, "%H:%M:%S", tm, GMTp, locale);+ if (buf == NULL)+ return (NULL);+ break;++ case 'X':+ buf = _strptime(buf, tptr->X_fmt, tm, GMTp, locale);+ if (buf == NULL)+ return (NULL);+ break;++ case 'x':+ buf = _strptime(buf, tptr->x_fmt, tm, GMTp, locale);+ if (buf == NULL)+ return (NULL);+ flags |= FLAG_MONTH | FLAG_MDAY | FLAG_YEAR;+ break;++ case 'j':+ if (!isdigit_l((unsigned char)*buf, locale))+ return (NULL);++ len = 3;+ for (i = 0; len && *buf != 0 &&+ isdigit_l((unsigned char)*buf, locale); buf++){+ i *= 10;+ i += *buf - '0';+ len--;+ }+ if (i < 1 || i > 366)+ return (NULL);++ tm->tm_yday = i - 1;+ flags |= FLAG_YDAY;++ break;++ case 'M':+ case 'S':+ if (*buf == 0 ||+ isspace_l((unsigned char)*buf, locale))+ break;++ if (!isdigit_l((unsigned char)*buf, locale))+ return (NULL);++ len = 2;+ for (i = 0; len && *buf != 0 &&+ isdigit_l((unsigned char)*buf, locale); buf++){+ i *= 10;+ i += *buf - '0';+ len--;+ }++ if (c == 'M') {+ if (i > 59)+ return (NULL);+ tm->tm_min = i;+ } else {+ if (i > 60)+ return (NULL);+ tm->tm_sec = i;+ }++ break;++ case 'H':+ case 'I':+ case 'k':+ case 'l':+ /*+ * %k and %l specifiers are documented as being+ * blank-padded. However, there is no harm in+ * allowing zero-padding.+ *+ * XXX %k and %l specifiers may gobble one too many+ * digits if used incorrectly.+ */++ len = 2;+ if ((c == 'k' || c == 'l') &&+ isblank_l((unsigned char)*buf, locale)) {+ buf++;+ len = 1;+ }++ if (!isdigit_l((unsigned char)*buf, locale))+ return (NULL);++ for (i = 0; len && *buf != 0 &&+ isdigit_l((unsigned char)*buf, locale); buf++) {+ i *= 10;+ i += *buf - '0';+ len--;+ }+ if (c == 'H' || c == 'k') {+ if (i > 23)+ return (NULL);+ } else if (i == 0 || i > 12)+ return (NULL);++ tm->tm_hour = i;++ break;++ case 'p':+ /*+ * XXX This is bogus if parsed before hour-related+ * specifiers.+ */+ if (tm->tm_hour > 12)+ return (NULL);++ len = strlen(tptr->am);+ if (strncasecmp_l(buf, tptr->am, len, locale) == 0) {+ if (tm->tm_hour == 12)+ tm->tm_hour = 0;+ buf += len;+ break;+ }++ len = strlen(tptr->pm);+ if (strncasecmp_l(buf, tptr->pm, len, locale) == 0) {+ if (tm->tm_hour != 12)+ tm->tm_hour += 12;+ buf += len;+ break;+ }++ return (NULL);++ case 'A':+ case 'a':+ for (i = 0; i < asizeof(tptr->weekday); i++) {+ len = strlen(tptr->weekday[i]);+ if (strncasecmp_l(buf, tptr->weekday[i],+ len, locale) == 0)+ break;+ len = strlen(tptr->wday[i]);+ if (strncasecmp_l(buf, tptr->wday[i],+ len, locale) == 0)+ break;+ }+ if (i == asizeof(tptr->weekday))+ return (NULL);++ buf += len;+ tm->tm_wday = i;+ flags |= FLAG_WDAY;+ break;++ case 'U':+ case 'W':+ /*+ * XXX This is bogus, as we can not assume any valid+ * information present in the tm structure at this+ * point to calculate a real value, so just check the+ * range for now.+ */+ if (!isdigit_l((unsigned char)*buf, locale))+ return (NULL);++ len = 2;+ for (i = 0; len && *buf != 0 &&+ isdigit_l((unsigned char)*buf, locale); buf++) {+ i *= 10;+ i += *buf - '0';+ len--;+ }+ if (i > 53)+ return (NULL);++ if (c == 'U')+ day_offset = TM_SUNDAY;+ else+ day_offset = TM_MONDAY;+++ week_offset = i;++ break;++ case 'u':+ case 'w':+ if (!isdigit_l((unsigned char)*buf, locale))+ return (NULL);++ i = *buf++ - '0';+ if (i < 0 || i > 7 || (c == 'u' && i < 1) ||+ (c == 'w' && i > 6))+ return (NULL);++ tm->tm_wday = i % 7;+ flags |= FLAG_WDAY;++ break;++ case 'e':+ /*+ * With %e format, our strftime(3) adds a blank space+ * before single digits.+ */+ if (*buf != 0 &&+ isspace_l((unsigned char)*buf, locale))+ buf++;+ /* FALLTHROUGH */+ case 'd':+ /*+ * The %e specifier was once explicitly documented as+ * not being zero-padded but was later changed to+ * equivalent to %d. There is no harm in allowing+ * such padding.+ *+ * XXX The %e specifier may gobble one too many+ * digits if used incorrectly.+ */+ if (!isdigit_l((unsigned char)*buf, locale))+ return (NULL);++ len = 2;+ for (i = 0; len && *buf != 0 &&+ isdigit_l((unsigned char)*buf, locale); buf++) {+ i *= 10;+ i += *buf - '0';+ len--;+ }+ if (i == 0 || i > 31)+ return (NULL);++ tm->tm_mday = i;+ flags |= FLAG_MDAY;++ break;++ case 'B':+ case 'b':+ case 'h':+ for (i = 0; i < asizeof(tptr->month); i++) {+ if (Oalternative) {+ if (c == 'B') {+ len = strlen(tptr->alt_month[i]);+ if (strncasecmp_l(buf,+ tptr->alt_month[i],+ len, locale) == 0)+ break;+ }+ } else {+ len = strlen(tptr->month[i]);+ if (strncasecmp_l(buf, tptr->month[i],+ len, locale) == 0)+ break;+ }+ }+ /*+ * Try the abbreviated month name if the full name+ * wasn't found and Oalternative was not requested.+ */+ if (i == asizeof(tptr->month) && !Oalternative) {+ for (i = 0; i < asizeof(tptr->month); i++) {+ len = strlen(tptr->mon[i]);+ if (strncasecmp_l(buf, tptr->mon[i],+ len, locale) == 0)+ break;+ }+ }+ if (i == asizeof(tptr->month))+ return (NULL);++ tm->tm_mon = i;+ buf += len;+ flags |= FLAG_MONTH;++ break;++ case 'm':+ if (!isdigit_l((unsigned char)*buf, locale))+ return (NULL);++ len = 2;+ for (i = 0; len && *buf != 0 &&+ isdigit_l((unsigned char)*buf, locale); buf++) {+ i *= 10;+ i += *buf - '0';+ len--;+ }+ if (i < 1 || i > 12)+ return (NULL);++ tm->tm_mon = i - 1;+ flags |= FLAG_MONTH;++ break;++ case 's':+ {+ char *cp;+ int sverrno;+ long long n;+ time_t t;++ sverrno = errno;+ errno = 0;+ n = strtoll_l(buf, &cp, 10, locale);+ if (errno == ERANGE || (long long)(t = n) != n) {+ errno = sverrno;+ return (NULL);+ }+ errno = sverrno;+ buf = cp;+ if (gmtime_r(&t, tm) == NULL)+ return (NULL);+ *GMTp = 1;+ flags |= FLAG_YDAY | FLAG_WDAY | FLAG_MONTH |+ FLAG_MDAY | FLAG_YEAR;+ }+ break;++ case 'Y':+ case 'y':+ if (*buf == 0 ||+ isspace_l((unsigned char)*buf, locale))+ break;++ if (!isdigit_l((unsigned char)*buf, locale))+ return (NULL);++ len = (c == 'Y') ? 4 : 2;+ for (i = 0; len && *buf != 0 &&+ isdigit_l((unsigned char)*buf, locale); buf++) {+ i *= 10;+ i += *buf - '0';+ len--;+ }+ if (c == 'Y')+ century = i / 100;+ year = i % 100;++ flags |= FLAG_YEAR;++ break;++ case 'Z':+ {+ const char *cp;+ char *zonestr;++ for (cp = buf; *cp &&+ isupper_l((unsigned char)*cp, locale); ++cp) {+ /*empty*/}+ if (cp - buf) {+ zonestr = alloca(cp - buf + 1);+ strncpy(zonestr, buf, cp - buf);+ zonestr[cp - buf] = '\0';+ tzset();+ if (0 == strcmp(zonestr, "GMT") ||+ 0 == strcmp(zonestr, "UTC")) {+ *GMTp = 1;+ } else if (0 == strcmp(zonestr, tzname[0])) {+ tm->tm_isdst = 0;+ } else if (0 == strcmp(zonestr, tzname[1])) {+ tm->tm_isdst = 1;+ } else {+ return (NULL);+ }+ buf += cp - buf;+ }+ }+ break;++ case 'z':+ {+ int sign = 1;++ if (*buf != '+') {+ if (*buf == '-')+ sign = -1;+ else+ return (NULL);+ }++ buf++;+ i = 0;+ for (len = 4; len > 0; len--) {+ if (isdigit_l((unsigned char)*buf, locale)) {+ i *= 10;+ i += *buf - '0';+ buf++;+ } else if (len == 2) {+ i *= 100;+ break;+ } else+ return (NULL);+ }++ if (i > 1400 || (sign == -1 && i > 1200) ||+ (i % 100) >= 60)+ return (NULL);+ tm->tm_hour -= sign * (i / 100);+ tm->tm_min -= sign * (i % 100);+ *GMTp = 1;+ }+ break;++ case 'n':+ case 't':+ while (isspace_l((unsigned char)*buf, locale))+ buf++;+ break;++ default:+ return (NULL);+ }+ }++ if (century != -1 || year != -1) {+ if (year == -1)+ year = 0;+ if (century == -1) {+ if (year < 69)+ year += 100;+ } else+ year += century * 100 - TM_YEAR_BASE;+ tm->tm_year = year;+ }++ if (!(flags & FLAG_YDAY) && (flags & FLAG_YEAR)) {+ if ((flags & (FLAG_MONTH | FLAG_MDAY)) ==+ (FLAG_MONTH | FLAG_MDAY)) {+ tm->tm_yday = start_of_month[isleap(tm->tm_year ++ TM_YEAR_BASE)][tm->tm_mon] + (tm->tm_mday - 1);+ flags |= FLAG_YDAY;+ } else if (day_offset != -1) {+ int tmpwday, tmpyday, fwo;++ fwo = first_wday_of(tm->tm_year + TM_YEAR_BASE);+ /* No incomplete week (week 0). */+ if (week_offset == 0 && fwo == day_offset)+ return (NULL);++ /* Set the date to the first Sunday (or Monday)+ * of the specified week of the year.+ */+ tmpwday = (flags & FLAG_WDAY) ? tm->tm_wday :+ day_offset;+ tmpyday = (7 - fwo + day_offset) % 7 ++ (week_offset - 1) * 7 ++ (tmpwday - day_offset + 7) % 7;+ /* Impossible yday for incomplete week (week 0). */+ if (tmpyday < 0) {+ if (flags & FLAG_WDAY)+ return (NULL);+ tmpyday = 0;+ }+ tm->tm_yday = tmpyday;+ flags |= FLAG_YDAY;+ }+ }++ if ((flags & (FLAG_YEAR | FLAG_YDAY)) == (FLAG_YEAR | FLAG_YDAY)) {+ if (!(flags & FLAG_MONTH)) {+ i = 0;+ while (tm->tm_yday >=+ start_of_month[isleap(tm->tm_year ++ TM_YEAR_BASE)][i])+ i++;+ if (i > 12) {+ i = 1;+ tm->tm_yday -=+ start_of_month[isleap(tm->tm_year ++ TM_YEAR_BASE)][12];+ tm->tm_year++;+ }+ tm->tm_mon = i - 1;+ flags |= FLAG_MONTH;+ }+ if (!(flags & FLAG_MDAY)) {+ tm->tm_mday = tm->tm_yday -+ start_of_month[isleap(tm->tm_year + TM_YEAR_BASE)]+ [tm->tm_mon] + 1;+ flags |= FLAG_MDAY;+ }+ if (!(flags & FLAG_WDAY)) {+ i = 0;+ wday_offset = first_wday_of(tm->tm_year);+ while (i++ <= tm->tm_yday) {+ if (wday_offset++ >= 6)+ wday_offset = 0;+ }+ tm->tm_wday = wday_offset;+ flags |= FLAG_WDAY;+ }+ }++ return ((char *)buf);+}++char *+strptime_l(const char * __restrict buf, const char * __restrict fmt,+ struct tm * __restrict tm, _locale_t loc)+{+ char *ret;+ int gmt;+ // FIX_LOCALE(loc);++ gmt = 0;+ ret = _strptime(buf, fmt, tm, &gmt, loc);+ if (ret && gmt) {+ time_t t = timegm(tm);++ localtime_s(tm, &t);+ }++ return (ret);+}++char *+strptime(const char * __restrict buf, const char * __restrict fmt,+ struct tm * __restrict tm)+{+#if HAVE__GET_CURRENT_LOCALE+ return strptime_l(buf, fmt, tm, _get_current_locale());+#else+ return strptime_l(buf, fmt, tm, _create_locale(LC_TIME, "C"));+#endif+}
+ cbits/win_patch.c view
@@ -0,0 +1,119 @@+#include "win_patch.h"++#if !HAVE_STRTOL_L+long strtol_l(const char *nptr, char **endptr, int base, _locale_t locale) {+ return strtol(nptr, endptr, base);+}+#endif++#if !HAVE_STRTOLL_L+long long strtoll_l(const char *nptr, char **endptr, int base, _locale_t locale) {+ return strtoll(nptr, endptr, base);+}+#endif++inline int isblank_l( int c, _locale_t _loc)+{+ return ( c == ' ' || c == '\t' );+}++inline int strncasecmp_l(const char *s1, const char *s2, int len, _locale_t _loc) {+ return strncasecmp(s1, s2, len);+}++inline struct tm *gmtime_r(const time_t *_time_t, struct tm *_tm) {+ errno_t err = gmtime_s(_tm, _time_t);+ if (err) {+ return NULL;+ }+ return _tm;+}++inline struct tm *localtime_r(const time_t *_time_t, struct tm *_tm) {+ errno_t err = localtime_s(_tm, _time_t);+ if (err) {+ return NULL;+ }+ return _tm;+}++const struct lc_time_T _C_time_locale = {+ {+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"+ }, {+ "January", "February", "March", "April", "May", "June",+ "July", "August", "September", "October", "November", "December"+ }, {+ "Sun", "Mon", "Tue", "Wed",+ "Thu", "Fri", "Sat"+ }, {+ "Sunday", "Monday", "Tuesday", "Wednesday",+ "Thursday", "Friday", "Saturday"+ },++ /* X_fmt */+ "%H:%M:%S",++ /*+ * x_fmt+ * Since the C language standard calls for+ * "date, using locale's date format," anything goes.+ * Using just numbers (as here) makes Quakers happier;+ * it's also compatible with SVR4.+ */+ "%m/%d/%y",++ /*+ * c_fmt+ */+ "%a %b %e %H:%M:%S %Y",++ /* am */+ "AM",++ /* pm */+ "PM",++ /* date_fmt */+ "%a %b %e %H:%M:%S %Z %Y",+ + /* alt_month+ * Standalone months forms for %OB+ */+ {+ "January", "February", "March", "April", "May", "June",+ "July", "August", "September", "October", "November", "December"+ },++ /* md_order+ * Month / day order in dates+ */+ "md",++ /* ampm_fmt+ * To determine 12-hour clock format time (empty, if N/A)+ */+ "%I:%M:%S %p"+};+++int _patch_setenv(const char *var, const char *val, int ovr) {+ BOOL b = SetEnvironmentVariableA(var, val);+ if (b) {+ return 0;+ } else {+ return 1;+ }+}++int _patch_unsetenv(const char *name) {+ int len = strlen(name);+ char *sname = (char *)malloc(len + 2);+ strcpy(sname, name);+ sname[len] = '=';+ sname[len + 1] = '\0';+ int r = _putenv(sname);+ free(sname);+ return r;+}
configure view
@@ -3304,6 +3304,50 @@ fi done +for ac_func in _mkgmtime+do :+ ac_fn_c_check_func "$LINENO" "_mkgmtime" "ac_cv_func__mkgmtime"+if test "x$ac_cv_func__mkgmtime" = xyes; then :+ cat >>confdefs.h <<_ACEOF+#define HAVE__MKGMTIME 1+_ACEOF++fi+done++for ac_func in _get_current_locale+do :+ ac_fn_c_check_func "$LINENO" "_get_current_locale" "ac_cv_func__get_current_locale"+if test "x$ac_cv_func__get_current_locale" = xyes; then :+ cat >>confdefs.h <<_ACEOF+#define HAVE__GET_CURRENT_LOCALE 1+_ACEOF++fi+done++for ac_func in strtol_l+do :+ ac_fn_c_check_func "$LINENO" "strtol_l" "ac_cv_func_strtol_l"+if test "x$ac_cv_func_strtol_l" = xyes; then :+ cat >>confdefs.h <<_ACEOF+#define HAVE_STRTOL_L 1+_ACEOF++fi+done++for ac_func in strtoll_l+do :+ ac_fn_c_check_func "$LINENO" "strtoll_l" "ac_cv_func_strtoll_l"+if test "x$ac_cv_func_strtoll_l" = xyes; then :+ cat >>confdefs.h <<_ACEOF+#define HAVE_STRTOLL_L 1+_ACEOF++fi+done+ host=`uname -a` case $host in
configure.ac view
@@ -8,6 +8,10 @@ AC_CHECK_FUNCS(strptime_l) AC_CHECK_FUNCS(timegm)+AC_CHECK_FUNCS(_mkgmtime)+AC_CHECK_FUNCS(_get_current_locale)+AC_CHECK_FUNCS(strtol_l)+AC_CHECK_FUNCS(strtoll_l) host=`uname -a` case $host in
unix-time.cabal view
@@ -1,5 +1,5 @@ Name: unix-time-Version: 0.3.8+Version: 0.4.0 Author: Kazu Yamamoto <kazu@iij.ad.jp> Maintainer: Kazu Yamamoto <kazu@iij.ad.jp> License: BSD3@@ -27,6 +27,10 @@ , old-time , binary C-Sources: cbits/conv.c+ if os(windows)+ C-Sources: cbits/strftime.c+ , cbits/strptime.c+ , cbits/win_patch.c include-dirs: cbits Test-Suite doctest