]> sourceware.org Git - newlib-cygwin.git/blob - winsup/cygwin/tzcode/localtime_wrapper.c
41a5bcb63cc9861e19eea65272de6eb33b75996d
[newlib-cygwin.git] / winsup / cygwin / tzcode / localtime_wrapper.c
1 /* localtime.cc: Wrapper of NetBSD tzcode support for Cygwin. See README file.
2
3 This file is part of Cygwin.
4
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
7 details. */
8
9 #include "winsup.h"
10 #include "perprocess.h"
11 #include "tz_posixrules.h"
12 #include <cygwin/version.h>
13 #include <stdlib.h>
14 #include <sys/_tz_structs.h>
15
16 static NO_COPY SRWLOCK tzset_guard = SRWLOCK_INIT;
17
18 // Convert these NetBSD rwlock ops into SRWLocks
19 #define rwlock_wrlock(X) AcquireSRWLockExclusive(&tzset_guard)
20 #define rwlock_unlock(X) ReleaseSRWLockExclusive(&tzset_guard)
21
22 // Set these NetBSD-related option #defines appropriately for Cygwin
23 //#define STD_INSPIRED // early-include private.h below does this
24 #define lint
25 #define HAVE_POSIX_DECLS 0
26 #define USG_COMPAT 1
27 #define NO_ERROR_IN_DST_GAP
28 #define state __state
29
30 // Turn a specific known kind of const parameter into non-const
31 #define __UNCONST(X) ((char *) (X))
32
33 // Turn off these NetBSD audit-related definitions
34 #define __aconst
35 #define _DIAGASSERT(X)
36
37 // Supply this Cygwin-specific function in advance of its use in localtime.c
38 static char *
39 tzgetwintzi (char *wildabbr, char *outbuf)
40 {
41 TIME_ZONE_INFORMATION tzi;
42 char *cp, *dst;
43 wchar_t *wsrc;
44 div_t d;
45
46 GetTimeZoneInformation (&tzi);
47 dst = cp = outbuf;
48 for (wsrc = tzi.StandardName; *wsrc; wsrc++)
49 if (*wsrc >= L'A' && *wsrc <= L'Z')
50 *dst++ = *wsrc;
51 if ((dst - cp) < 3)
52 {
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);
57 }
58 else
59 cp = dst;
60 d = div (tzi.Bias + tzi.StandardBias, 60);
61 __small_sprintf (cp, "%d", d.quot);
62 if (d.rem)
63 __small_sprintf (cp = strchr (cp, 0), ":%d", abs (d.rem));
64 if (tzi.StandardDate.wMonth)
65 {
66 cp = strchr (cp, 0);
67 dst = cp;
68 for (wsrc = tzi.DaylightName; *wsrc; wsrc++)
69 if (*wsrc >= L'A' && *wsrc <= L'Z')
70 *dst++ = *wsrc;
71 if ((dst - cp) < 3)
72 {
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);
77 }
78 else
79 cp = dst;
80 d = div (tzi.Bias + tzi.DaylightBias, 60);
81 __small_sprintf (cp, "%d", d.quot);
82 if (d.rem)
83 __small_sprintf (cp = strchr (cp, 0), ":%d", abs (d.rem));
84 cp = strchr (cp, 0);
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);
96 cp = strchr (cp, 0);
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);
108 }
109 /* __small_printf ("TZ deduced as `%s'\n", outbuf); */
110 return outbuf;
111 }
112
113 // Pull these in early to catch any small issues before the real test
114 #include "private.h"
115 #include "tzfile.h"
116
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()
123 */
124 #include "localtime.patched.c"
125
126 // Don't forget these Cygwin-specific additions from this point to EOF
127
128 long
129 __cygwin_gettzoffset (const struct tm *tmp)
130 {
131 #ifdef TM_GMTOFF
132 if (CYGWIN_VERSION_CHECK_FOR_EXTRA_TM_MEMBERS)
133 return tmp->TM_GMTOFF;
134 #endif /* defined TM_GMTOFF */
135 __tzinfo_type *tz = __gettzinfo ();
136 /* The sign of this is exactly opposite the envvar TZ. We
137 could directly use the global _timezone for tm_isdst==0,
138 but have to use __tzrule for daylight savings. */
139 long offset = -tz->__tzrule[tmp->tm_isdst > 0].offset;
140 return offset;
141 }
142
143 const char *
144 __cygwin_gettzname (const struct tm *tmp)
145 {
146 #ifdef TM_ZONE
147 if (CYGWIN_VERSION_CHECK_FOR_EXTRA_TM_MEMBERS)
148 return tmp->TM_ZONE;
149 #endif
150 return _tzname[tmp->tm_isdst > 0];
151 }
152
153 EXPORT_ALIAS (tzset_unlocked, _tzset_unlocked)
This page took 0.050553 seconds and 6 git commands to generate.