[Cygwin PATCH 3/9] tzcode resync: localtime.cc
Mark Geisert
mark@maxrnd.com
Wed May 13 08:23:43 GMT 2020
Cygwin's wrapper around NetBSD's localtime.c.
---
winsup/cygwin/tzcode/localtime.cc | 162 ++++++++++++++++++++++++++++++
1 file changed, 162 insertions(+)
create mode 100644 winsup/cygwin/tzcode/localtime.cc
diff --git a/winsup/cygwin/tzcode/localtime.cc b/winsup/cygwin/tzcode/localtime.cc
new file mode 100644
index 000000000..9ea885ece
--- /dev/null
+++ b/winsup/cygwin/tzcode/localtime.cc
@@ -0,0 +1,162 @@
+/* localtime.cc: Wrapper of NetBSD tzcode support for Cygwin. See README file.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+#include "sync.h"
+#include "../include/cygwin/version.h"
+#include "tz_posixrules.h"
+
+// Set these NetBSD-related option #defines appropriately for Cygwin
+//#define STD_INSPIRED // early-include private.h below does this
+#define lint
+#define USG_COMPAT 1
+#define NO_ERROR_IN_DST_GAP
+#define state __state
+
+static NO_COPY muto tzset_guard;
+
+// Turn these NetBSD ops into the corresponding Cygwin ops
+#define rwlock_wrlock(X) tzset_guard.init ("tzset_guard")->acquire ()
+#define rwlock_unlock(X) tzset_guard.release ()
+
+// Turn a specific known kind of const parameter into non-const
+#define __UNCONST(X) ((char *) (X))
+
+// Turn off these NetBSD audit-related definitions
+#define __aconst
+#define _DIAGASSERT(X)
+
+// Get ready to enclose NetBSD's localtime.c
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Supply this Cygwin-specific function in advance of its use in localtime.c
+static char *
+tzgetwintz (char *wildabbr, char *outbuf)
+{
+ TIME_ZONE_INFORMATION tzi;
+ char *cp, *dst;
+ wchar_t *src;
+ div_t d;
+
+ GetTimeZoneInformation (&tzi);
+ dst = cp = outbuf;
+ for (src = tzi.StandardName; *src; src++)
+ if (*src >= L'A' && *src <= L'Z')
+ *dst++ = *src;
+ if ((dst - cp) < 3)
+ {
+ /* In non-english Windows, converted tz.StandardName
+ may not contain a valid standard timezone name. */
+ strcpy (cp, wildabbr);
+ cp += strlen (wildabbr);
+ }
+ else
+ cp = dst;
+ d = div (tzi.Bias + tzi.StandardBias, 60);
+ __small_sprintf (cp, "%d", d.quot);
+ if (d.rem)
+ __small_sprintf (cp = strchr (cp, 0), ":%d", abs (d.rem));
+ if (tzi.StandardDate.wMonth)
+ {
+ cp = strchr (cp, 0);
+ dst = cp;
+ for (src = tzi.DaylightName; *src; src++)
+ if (*src >= L'A' && *src <= L'Z')
+ *dst++ = *src;
+ if ((dst - cp) < 3)
+ {
+ /* In non-english Windows, converted tz.DaylightName
+ may not contain a valid daylight timezone name. */
+ strcpy (cp, wildabbr);
+ cp += strlen (wildabbr);
+ }
+ else
+ cp = dst;
+ d = div (tzi.Bias + tzi.DaylightBias, 60);
+ __small_sprintf (cp, "%d", d.quot);
+ if (d.rem)
+ __small_sprintf (cp = strchr (cp, 0), ":%d", abs (d.rem));
+ cp = strchr (cp, 0);
+ __small_sprintf (cp = strchr (cp, 0), ",M%d.%d.%d/%d",
+ tzi.DaylightDate.wMonth,
+ tzi.DaylightDate.wDay,
+ tzi.DaylightDate.wDayOfWeek,
+ tzi.DaylightDate.wHour);
+ if (tzi.DaylightDate.wMinute || tzi.DaylightDate.wSecond)
+ __small_sprintf (cp = strchr (cp, 0), ":%d",
+ tzi.DaylightDate.wMinute);
+ if (tzi.DaylightDate.wSecond)
+ __small_sprintf (cp = strchr (cp, 0), ":%d",
+ tzi.DaylightDate.wSecond);
+ cp = strchr (cp, 0);
+ __small_sprintf (cp = strchr (cp, 0), ",M%d.%d.%d/%d",
+ tzi.StandardDate.wMonth,
+ tzi.StandardDate.wDay,
+ tzi.StandardDate.wDayOfWeek,
+ tzi.StandardDate.wHour);
+ if (tzi.StandardDate.wMinute || tzi.StandardDate.wSecond)
+ __small_sprintf (cp = strchr (cp, 0), ":%d",
+ tzi.StandardDate.wMinute);
+ if (tzi.StandardDate.wSecond)
+ __small_sprintf (cp = strchr (cp, 0), ":%d",
+ tzi.StandardDate.wSecond);
+ }
+ /* __small_printf ("TZ deduced as `%s'\n", outbuf); */
+ return outbuf;
+}
+
+// Pull these in early to catch any small issues before the real test
+#include "private.h"
+#include "tzfile.h"
+
+/* Some NetBSD differences were too difficult to work around..
+ so #include a patched copy of localtime.c rather than the NetBSD original.
+ Here is a list of the patches...
+ (1) fix an erroneous decl of tzdirslash size (flagged by g++)
+ (2) add missing casts on all results of malloc() calls (flagged by g++)
+ (3) change all malloc() calls to analogous calloc() calls
+ (4) add conditional call to Cygwin's tzgetwintz() from tzsetlcl()
+ (5) add Cygwin's historical "posixrules" support to tzloadbody()
+ (6) enable defs of daylight, timezone, and tzname
+ (7) make def of __lclptr static to avoid exporting it
+*/
+#include "localtime.c.patched"
+
+#ifdef __cplusplus
+}
+#endif
+
+// Don't forget these Cygwin-specific additions from this point to EOF
+EXPORT_ALIAS (tzset_unlocked, _tzset_unlocked)
+
+extern "C" long
+__cygwin_gettzoffset (const struct tm *tmp)
+{
+#ifdef TM_GMTOFF
+ if (CYGWIN_VERSION_CHECK_FOR_EXTRA_TM_MEMBERS)
+ return tmp->TM_GMTOFF;
+#endif /* defined TM_GMTOFF */
+ __tzinfo_type *tz = __gettzinfo ();
+ /* The sign of this is exactly opposite the envvar TZ. We
+ could directly use the global _timezone for tm_isdst==0,
+ but have to use __tzrule for daylight savings. */
+ long offset = -tz->__tzrule[tmp->tm_isdst > 0].offset;
+ return offset;
+}
+
+extern "C" const char *
+__cygwin_gettzname (const struct tm *tmp)
+{
+#ifdef TM_ZONE
+ if (CYGWIN_VERSION_CHECK_FOR_EXTRA_TM_MEMBERS)
+ return tmp->TM_ZONE;
+#endif
+ return _tzname[tmp->tm_isdst > 0];
+}
--
2.21.0
More information about the Cygwin-patches
mailing list