]>
Commit | Line | Data |
---|---|---|
63ff2b84 MG |
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 | ||
49a843b4 CV |
9 | #include "winsup.h" |
10 | #include "perprocess.h" | |
63ff2b84 | 11 | #include "tz_posixrules.h" |
49a843b4 CV |
12 | #include <cygwin/version.h> |
13 | #include <stdlib.h> | |
7ed95200 | 14 | #include <sys/_tz_structs.h> |
63ff2b84 | 15 | |
49a843b4 | 16 | static NO_COPY SRWLOCK tzset_guard = SRWLOCK_INIT; |
63ff2b84 | 17 | |
49a843b4 CV |
18 | // Convert these NetBSD rwlock ops into SRWLocks |
19 | #define rwlock_wrlock(X) AcquireSRWLockExclusive(&tzset_guard) | |
20 | #define rwlock_unlock(X) ReleaseSRWLockExclusive(&tzset_guard) | |
63ff2b84 MG |
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 | ||
63ff2b84 MG |
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 | */ | |
4d5efe1e | 124 | #include "localtime.patched.c" |
63ff2b84 | 125 | |
63ff2b84 | 126 | // Don't forget these Cygwin-specific additions from this point to EOF |
63ff2b84 | 127 | |
49a843b4 | 128 | long |
63ff2b84 MG |
129 | __cygwin_gettzoffset (const struct tm *tmp) |
130 | { | |
131 | #ifdef TM_GMTOFF | |
132 | if (CYGWIN_VERSION_CHECK_FOR_EXTRA_TM_MEMBERS) | |
49a843b4 | 133 | return tmp->TM_GMTOFF; |
63ff2b84 MG |
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 | ||
49a843b4 | 143 | const char * |
63ff2b84 MG |
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 | } | |
f2010ed7 CV |
152 | |
153 | EXPORT_ALIAS (tzset_unlocked, _tzset_unlocked) |