Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtksh / ksh93 / src / lib / libast / tm / tminit.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: tminit.c /main/3 1995/11/01 18:54:45 rswiston $ */
24 /***************************************************************
25 *                                                              *
26 *                      AT&T - PROPRIETARY                      *
27 *                                                              *
28 *         THIS IS PROPRIETARY SOURCE CODE LICENSED BY          *
29 *                          AT&T CORP.                          *
30 *                                                              *
31 *                Copyright (c) 1995 AT&T Corp.                 *
32 *                     All Rights Reserved                      *
33 *                                                              *
34 *           This software is licensed by AT&T Corp.            *
35 *       under the terms and conditions of the license in       *
36 *       http://www.research.att.com/orgs/ssr/book/reuse        *
37 *                                                              *
38 *               This software was created by the               *
39 *           Software Engineering Research Department           *
40 *                    AT&T Bell Laboratories                    *
41 *                                                              *
42 *               For further information contact                *
43 *                     gsf@research.att.com                     *
44 *                                                              *
45 ***************************************************************/
46
47 /* : : generated by proto : : */
48
49 #if !defined(__PROTO__)
50 #if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)
51 #if defined(__cplusplus)
52 #define __MANGLE__      "C"
53 #else
54 #define __MANGLE__
55 #endif
56 #define __STDARG__
57 #define __PROTO__(x)    x
58 #define __OTORP__(x)
59 #define __PARAM__(n,o)  n
60 #if !defined(__STDC__) && !defined(__cplusplus)
61 #if !defined(c_plusplus)
62 #define const
63 #endif
64 #define signed
65 #define void            int
66 #define volatile
67 #define __V_            char
68 #else
69 #define __V_            void
70 #endif
71 #else
72 #define __PROTO__(x)    ()
73 #define __OTORP__(x)    x
74 #define __PARAM__(n,o)  o
75 #define __MANGLE__
76 #define __V_            char
77 #define const
78 #define signed
79 #define void            int
80 #define volatile
81 #endif
82 #if defined(__cplusplus) || defined(c_plusplus)
83 #define __VARARG__      ...
84 #else
85 #define __VARARG__
86 #endif
87 #if defined(__STDARG__)
88 #define __VA_START__(p,a)       va_start(p,a)
89 #else
90 #define __VA_START__(p,a)       va_start(p)
91 #endif
92 #endif
93 #include <ast.h>
94 #include <tm.h>
95 #include <ctype.h>
96 #include <namval.h>
97
98 #ifndef tzname
99 #if _DLL_INDIRECT_DATA && _DLL
100 #define tzname          (_ast_getdll()->_ast_tzname)
101 #else
102 #ifdef  tzname
103 #define _dat_tzname     1
104 #else
105 #if !_dat_tzname
106 #if _dat__tzname
107 #undef  _dat_tzname
108 #define _dat_tzname     1
109 #define tzname          _tzname
110 #endif
111 #endif
112 #endif
113 #if _dat_tzname
114 extern __MANGLE__ char*         tzname[];
115 #endif
116 #endif
117 #endif
118
119 #define TM_type         (-1)
120
121 static const Namval_t           options[] =
122 {
123         "adjust",       TM_ADJUST,
124         "format",       TM_DEFAULT,
125         "leap",         TM_LEAP,
126         "type",         TM_type,
127         "utc",          TM_UTC,
128         0,              0
129 };
130
131 Tm_info_t               tm_info;
132
133 /*
134  * return minutes west of GMT for local time clock
135  *
136  * isdst will point to non-zero if DST is in effect
137  * this routine also kicks in the local initialization
138  */
139
140 static int
141 tzwest __PARAM__((time_t* clock, int* isdst), (clock, isdst)) __OTORP__(time_t* clock; int* isdst;){
142         register Tm_t*  tp;
143         register int    n;
144         register int    m;
145         int             h;
146
147         /*
148          * convert to GMT assuming local time
149          */
150
151         tp = (Tm_t*)gmtime(clock);
152         n = tp->tm_yday;
153         h = tp->tm_hour;
154         m = tp->tm_min;
155
156         /*
157          * localtime() handles DST and GMT offset
158          */
159
160         tp = (Tm_t*)localtime(clock);
161         if (n = tp->tm_yday - n)
162         {
163                 if (n > 1) n = -1;
164                 else if (n < -1) n = 1;
165         }
166         *isdst = tp->tm_isdst;
167         return((h - tp->tm_hour - n * 24) * 60 + m - tp->tm_min);
168 }
169
170 /*
171  * stropt() option handler
172  */
173
174 static int
175 tmopt __PARAM__((__V_* a, const __V_* p, int n, const char* v), (a, p, n, v)) __OTORP__(__V_* a; const __V_* p; int n; const char* v;){
176         Tm_zone_t*      zp;
177
178         NoP(a);
179         if (p) switch (((Namval_t*)p)->value)
180         {
181         case TM_DEFAULT:
182                 tm_info.deformat = (n && (n = strlen(v)) > 0 && (n < 2 || v[n-2] != '%' || v[n-1] != '?')) ? strdup(v) : tm_info.format[TM_DEFAULT];
183                 break;
184         case TM_type:
185                 tm_info.local->type = (n && *v) ? ((zp = tmtype(v, NiL)) ? zp->type : strdup(v)) : 0;
186                 break;
187         default:
188                 if (n) tm_info.flags |= ((Namval_t*)p)->value;
189                 else tm_info.flags &= ~((Namval_t*)p)->value;
190                 break;
191         }
192         return(0);
193 }
194
195 /*
196  * initialize the local timezone
197  */
198
199 static void
200 tmlocal __PARAM__((void), ()){
201         register Tm_zone_t*     zp;
202         register int            n;
203         register char*          s;
204         int                     i;
205         int                     m;
206         int                     isdst;
207         char*                   t;
208         Tm_t*                   tp;
209         time_t                  now;
210         char                    buf[20];
211
212         static Tm_zone_t        local;
213
214         /*
215          * tm_info.format language support goes here
216          */
217
218 #if _lib_tzset
219         tzset();
220 #endif
221 #if _dat_tzname
222         local.standard = tzname[0];
223         local.daylight = tzname[1];
224 #endif
225         tm_info.format = tm_data.format;
226         tm_info.deformat = tm_data.format[TM_DEFAULT];
227
228         /*
229          * tm_info.local
230          */
231
232         tm_info.zone = tm_info.local = &local;
233         time(&now);
234         n = tzwest(&now, &isdst);
235
236         /*
237          * compute local DST offset by roaming
238          * through the last 12 months until tzwest() changes
239          */
240
241         for (i = 0; i < 12; i++)
242         {
243                 now -= 31 * 24 * 60 * 60;
244                 if ((m = tzwest(&now, &isdst)) != n)
245                 {
246                         if (!isdst)
247                         {
248                                 isdst = n;
249                                 n = m;
250                                 m = isdst;
251                         }
252                         m -= n;
253                         break;
254                 }
255         }
256         local.west = n;
257         local.dst = m;
258
259         /*
260          * now get the time zone names
261          */
262
263 #if _dat_tzname
264         if (tzname[0])
265         {
266                 /*
267                  * POSIX
268                  */
269
270                 if (!local.standard) local.standard = tzname[0];
271                 if (!local.daylight) local.daylight = tzname[1];
272         }
273         else
274 #endif
275         if ((s = getenv("TZNAME")) && *s && (s = strdup(s)))
276         {
277                 /*
278                  * BSD
279                  */
280
281                 local.standard = s;
282                 if (s = strchr(s, ',')) *s++ = 0;
283                 else s = "";
284                 local.daylight = s;
285         }
286         else if ((s = getenv("TZ")) && *s && *s != ':' && (s = strdup(s)))
287         {
288                 /*
289                  * POSIX style but skipped by localtime()
290                  */
291
292                 local.standard = s;
293                 if (*++s && *++s && *++s)
294                 {
295                         *s++ = 0;
296                         tmgoff(s, &t, 0);
297                         s = t;
298                 }
299                 else s = "";
300                 local.daylight = s;
301         }
302         else
303         {
304                 /*
305                  * tm_data.zone table lookup
306                  */
307
308                 t = 0;
309                 for (zp = tm_data.zone; zp->standard; zp++)
310                 {
311                         if (zp->type) t = zp->type;
312                         if (zp->west == n && zp->dst == m)
313                         {
314                                 local.type = t;
315                                 local.standard = zp->standard;
316                                 if (!(s = zp->daylight))
317                                 {
318                                         s = tmpoff(buf, zp->standard, 0, 0);
319                                         *s++ = ' ';
320                                         tmpoff(s, tm_info.format[TM_DT], m, TM_DST);
321                                         s = strdup(buf);
322                                 }
323                                 local.daylight = s;
324                                 break;
325                         }
326                 }
327                 if (!zp->standard)
328                 {
329                         /*
330                          * not in the table
331                          */
332
333                         s = tmpoff(buf, tm_info.format[TM_UT], n, 0);
334                         local.standard = strdup(buf);
335                         *s++ = ' ';
336                         tmpoff(s, tm_info.format[TM_UT], m, TM_DST);
337                         local.daylight = strdup(buf);
338                 }
339         }
340
341         /*
342          * set the options
343          */
344
345         stropt(getenv("TM_OPTIONS"), options, sizeof(*options), tmopt, NiL);
346
347         /*
348          * the time zone type is probably related to the locale
349          */
350
351         if (!local.type)
352         {
353                 s = local.standard;
354                 t = 0;
355                 for (zp = tm_data.zone; zp->standard; zp++)
356                 {
357                         if (zp->type) t = zp->type;
358                         if (tmword(s, NiL, zp->standard, NiL, 0))
359                         {
360                                 local.type = t;
361                                 break;
362                         }
363                 }
364         }
365
366         /*
367          * tm_info.flags
368          */
369
370         if (!(tm_info.flags & TM_ADJUST))
371         {
372                 now = (time_t)78811200;         /* Jun 30 1972 23:59:60 */
373                 tp = (Tm_t*)localtime(&now);
374                 if (tp->tm_sec != 60) tm_info.flags |= TM_ADJUST;
375         }
376         if (!(tm_info.flags & TM_UTC))
377         {
378                 s = local.standard;
379                 for (zp = tm_data.zone; !zp->type && zp->standard; zp++)
380                         if (tmword(s, NiL, zp->standard, NiL, 0))
381                         {
382                                 tm_info.flags |= TM_UTC;
383                                 break;
384                         }
385         }
386 }
387
388 /*
389  * initialize tm data
390  */
391
392 void
393 tminit __PARAM__((register Tm_zone_t* zp), (zp)) __OTORP__(register Tm_zone_t* zp;){
394         if (!tm_info.local) tmlocal();
395         if (!zp) zp = tm_info.local;
396 #if HUH950804 /* it only worked on systems that ignored TZ=...! */
397         if (zp != tm_info.zone)
398         {
399                 register char*  s;
400                 time_t          clock;
401                 char            buf[128];
402
403                 tm_info.zone = zp;
404                 s = buf;
405                 s += sfsprintf(s, sizeof(buf), "TZ=%s%d", zp->standard, zp->west / 60);
406                 if (zp->daylight)
407                 {
408                         s += sfsprintf(s, sizeof(buf) - (s - buf), "%s", zp->daylight);
409                         if (zp->dst != TM_DST) sfsprintf(s, sizeof(buf) - (s - buf), "%d", zp->dst);
410                 }
411                 s = *environ;
412                 *environ = buf;
413                 time(&clock);
414 #if _lib_tzset
415                 tzset();
416 #endif
417                 localtime(&clock);
418                 *environ = s;
419         }
420 #else
421         tm_info.zone = zp;
422 #endif
423 }