Cygwin: strptime: add release note
[newlib-cygwin.git] / winsup / cygwin / tzcode / localtime_wrapper.c
blob4e784480b0f4dbdff6adb3d12b31db98f11628f8
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
7 details. */
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>
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
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
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
34 #define __aconst
35 #define _DIAGASSERT(X)
37 // Supply this Cygwin-specific function in advance of its use in localtime.c
38 static char *
39 tzgetwintzi (char *wildabbr, char *outbuf)
41 TIME_ZONE_INFORMATION tzi;
42 char *cp, *dst;
43 wchar_t *wsrc;
44 div_t d;
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)
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);
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)
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)
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);
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);
109 /* __small_printf ("TZ deduced as `%s'\n", outbuf); */
110 return outbuf;
113 // Pull these in early to catch any small issues before the real test
114 #include "private.h"
115 #include "tzfile.h"
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)
129 long
130 __cygwin_gettzoffset (const struct tm *tmp)
132 #ifdef TM_GMTOFF
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;
141 return offset;
144 const char *
145 __cygwin_gettzname (const struct tm *tmp)
147 #ifdef TM_ZONE
148 if (CYGWIN_VERSION_CHECK_FOR_EXTRA_TM_MEMBERS)
149 return tmp->TM_ZONE;
150 #endif
151 return _tzname[tmp->tm_isdst > 0];