4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-02-10 02:59:16 +08:00
newlib-cygwin/winsup/cygwin/tzcode/localtime_wrapper.c
Corinna Vinschen 077f6310ca Cygwin: revamp localtime.o build rule
Rename localtime.c.patched to localtime.patched.c to keep the correct
language suffix.

Create localtime.patched.c in the build dir rather than in the source
dir.  Decouple the build rule for creating localtime.patched.c from
the rule to build localtime.o, so we don't have to rebuild the patched
source file all the time.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2020-10-14 10:54:20 -04:00

154 lines
4.6 KiB
C

/* 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 "perprocess.h"
#include "tz_posixrules.h"
#include <cygwin/version.h>
#include <stdlib.h>
static NO_COPY SRWLOCK tzset_guard = SRWLOCK_INIT;
// Convert these NetBSD rwlock ops into SRWLocks
#define rwlock_wrlock(X) AcquireSRWLockExclusive(&tzset_guard)
#define rwlock_unlock(X) ReleaseSRWLockExclusive(&tzset_guard)
// Set these NetBSD-related option #defines appropriately for Cygwin
//#define STD_INSPIRED // early-include private.h below does this
#define lint
#define HAVE_POSIX_DECLS 0
#define USG_COMPAT 1
#define NO_ERROR_IN_DST_GAP
#define state __state
// 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)
// Supply this Cygwin-specific function in advance of its use in localtime.c
static char *
tzgetwintzi (char *wildabbr, char *outbuf)
{
TIME_ZONE_INFORMATION tzi;
char *cp, *dst;
wchar_t *wsrc;
div_t d;
GetTimeZoneInformation (&tzi);
dst = cp = outbuf;
for (wsrc = tzi.StandardName; *wsrc; wsrc++)
if (*wsrc >= L'A' && *wsrc <= L'Z')
*dst++ = *wsrc;
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 (wsrc = tzi.DaylightName; *wsrc; wsrc++)
if (*wsrc >= L'A' && *wsrc <= L'Z')
*dst++ = *wsrc;
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;
}
// Get ready to wrap NetBSD's localtime.c
// 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 conditional call to Cygwin's tzgetwintzi() from tzsetlcl()
(3) add Cygwin's historical "posixrules" support to tzloadbody()
*/
#include "localtime.patched.c"
// Don't forget these Cygwin-specific additions from this point to EOF
EXPORT_ALIAS (tzset_unlocked, _tzset_unlocked)
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;
}
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];
}