public inbox for cygwin-patches@cygwin.com
 help / color / mirror / Atom feed
From: Mark Geisert <mark@maxrnd.com>
To: cygwin-patches@cygwin.com
Subject: [Cygwin PATCH 3/9] tzcode resync: localtime.cc
Date: Wed, 13 May 2020 01:23:43 -0700	[thread overview]
Message-ID: <20200513082349.831-3-mark@maxrnd.com> (raw)
In-Reply-To: <20200513082349.831-1-mark@maxrnd.com>

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


  parent reply	other threads:[~2020-05-13  8:24 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-13  8:23 [Cygwin PATCH 1/9] tzcode resync: Makefile.in Mark Geisert
2020-05-13  8:23 ` [Cygwin PATCH 2/9] tzcode resync: README Mark Geisert
2020-05-13  8:23 ` Mark Geisert [this message]
2020-05-13  8:23 ` [Cygwin PATCH 4/9] tzcode resync: localtime.c.patched Mark Geisert
2020-05-13  8:23 ` [Cygwin PATCH 5/9] tzcode resync: localtime.c Mark Geisert
2020-05-13  8:23 ` [Cygwin PATCH 6/9] tzcode resync: namespace.h Mark Geisert
2020-05-13  8:23 ` [Cygwin PATCH 7/9] tzcode resync: private.h Mark Geisert
2020-05-13  8:23 ` [Cygwin PATCH 8/9] tzcode resync: tzfile.h Mark Geisert
2020-05-13  8:23 ` [Cygwin PATCH 9/9] tzcode resync: tz_posixrules.h Mark Geisert

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200513082349.831-3-mark@maxrnd.com \
    --to=mark@maxrnd.com \
    --cc=cygwin-patches@cygwin.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).