1 /* localtime.cc: Wrapper of NetBSD tzcode support for Cygwin. See README file.
3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
10 #include "perprocess.h"
11 #include "tz_posixrules.h"
12 #include <cygwin/version.h>
14 #include <sys/_tz_structs.h>
16 static NO_COPY SRWLOCK tzset_guard
= SRWLOCK_INIT
;
18 // Convert these NetBSD rwlock ops into SRWLocks
19 #define rwlock_wrlock(X) AcquireSRWLockExclusive(&tzset_guard)
20 #define rwlock_unlock(X) ReleaseSRWLockExclusive(&tzset_guard)
22 // Set these NetBSD-related option #defines appropriately for Cygwin
23 //#define STD_INSPIRED // early-include private.h below does this
25 #define HAVE_POSIX_DECLS 0
27 #define NO_ERROR_IN_DST_GAP
30 // Turn a specific known kind of const parameter into non-const
31 #define __UNCONST(X) ((char *) (X))
33 // Turn off these NetBSD audit-related definitions
35 #define _DIAGASSERT(X)
37 // Supply this Cygwin-specific function in advance of its use in localtime.c
39 tzgetwintzi (char *wildabbr
, char *outbuf
)
41 TIME_ZONE_INFORMATION tzi
;
46 GetTimeZoneInformation (&tzi
);
48 for (wsrc
= tzi
.StandardName
; *wsrc
; wsrc
++)
49 if (*wsrc
>= L
'A' && *wsrc
<= L
'Z')
53 /* In non-english Windows, converted tz.StandardName
54 may not contain a valid standard timezone name. */
55 strcpy (cp
, wildabbr
);
56 cp
+= strlen (wildabbr
);
60 d
= div (tzi
.Bias
+ tzi
.StandardBias
, 60);
61 __small_sprintf (cp
, "%d", d
.quot
);
63 __small_sprintf (cp
= strchr (cp
, 0), ":%d", abs (d
.rem
));
64 if (tzi
.StandardDate
.wMonth
)
68 for (wsrc
= tzi
.DaylightName
; *wsrc
; wsrc
++)
69 if (*wsrc
>= L
'A' && *wsrc
<= L
'Z')
73 /* In non-english Windows, converted tz.DaylightName
74 may not contain a valid daylight timezone name. */
75 strcpy (cp
, wildabbr
);
76 cp
+= strlen (wildabbr
);
80 d
= div (tzi
.Bias
+ tzi
.DaylightBias
, 60);
81 __small_sprintf (cp
, "%d", d
.quot
);
83 __small_sprintf (cp
= strchr (cp
, 0), ":%d", abs (d
.rem
));
85 __small_sprintf (cp
= strchr (cp
, 0), ",M%d.%d.%d/%d",
86 tzi
.DaylightDate
.wMonth
,
87 tzi
.DaylightDate
.wDay
,
88 tzi
.DaylightDate
.wDayOfWeek
,
89 tzi
.DaylightDate
.wHour
);
90 if (tzi
.DaylightDate
.wMinute
|| tzi
.DaylightDate
.wSecond
)
91 __small_sprintf (cp
= strchr (cp
, 0), ":%d",
92 tzi
.DaylightDate
.wMinute
);
93 if (tzi
.DaylightDate
.wSecond
)
94 __small_sprintf (cp
= strchr (cp
, 0), ":%d",
95 tzi
.DaylightDate
.wSecond
);
97 __small_sprintf (cp
= strchr (cp
, 0), ",M%d.%d.%d/%d",
98 tzi
.StandardDate
.wMonth
,
99 tzi
.StandardDate
.wDay
,
100 tzi
.StandardDate
.wDayOfWeek
,
101 tzi
.StandardDate
.wHour
);
102 if (tzi
.StandardDate
.wMinute
|| tzi
.StandardDate
.wSecond
)
103 __small_sprintf (cp
= strchr (cp
, 0), ":%d",
104 tzi
.StandardDate
.wMinute
);
105 if (tzi
.StandardDate
.wSecond
)
106 __small_sprintf (cp
= strchr (cp
, 0), ":%d",
107 tzi
.StandardDate
.wSecond
);
109 /* __small_printf ("TZ deduced as `%s'\n", outbuf); */
113 // Pull these in early to catch any small issues before the real test
117 /* Some NetBSD differences were too difficult to work around..
118 so #include a patched copy of localtime.c rather than the NetBSD original.
119 Here is a list of the patches...
120 (1) fix an erroneous decl of tzdirslash size (flagged by g++)
121 (2) add conditional call to Cygwin's tzgetwintzi() from tzsetlcl()
122 (3) add Cygwin's historical "posixrules" support to tzloadbody()
124 #include "localtime.patched.c"
126 // Don't forget these Cygwin-specific additions from this point to EOF
127 EXPORT_ALIAS (tzset_unlocked
, _tzset_unlocked
)
130 __cygwin_gettzoffset (const struct tm
*tmp
)
133 if (CYGWIN_VERSION_CHECK_FOR_EXTRA_TM_MEMBERS
)
134 return tmp
->TM_GMTOFF
;
135 #endif /* defined TM_GMTOFF */
136 __tzinfo_type
*tz
= __gettzinfo ();
137 /* The sign of this is exactly opposite the envvar TZ. We
138 could directly use the global _timezone for tm_isdst==0,
139 but have to use __tzrule for daylight savings. */
140 long offset
= -tz
->__tzrule
[tmp
->tm_isdst
> 0].offset
;
145 __cygwin_gettzname (const struct tm
*tmp
)
148 if (CYGWIN_VERSION_CHECK_FOR_EXTRA_TM_MEMBERS
)
151 return _tzname
[tmp
->tm_isdst
> 0];