Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libast/tm/tminit.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1985-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* David Korn <[email protected]> *
19
* Phong Vo <[email protected]> *
20
* *
21
***********************************************************************/
22
#pragma prototyped
23
/*
24
* Glenn Fowler
25
* AT&T Research
26
*
27
* time conversion support
28
*/
29
30
#include <tm.h>
31
#include <ctype.h>
32
#include <namval.h>
33
34
#include "FEATURE/tmlib"
35
36
#ifndef tzname
37
# if defined(__DYNAMIC__)
38
# undef _dat_tzname
39
# define tzname __DYNAMIC__(tzname)
40
# else
41
# if !_dat_tzname
42
# if _dat__tzname
43
# undef _dat_tzname
44
# define _dat_tzname 1
45
# define tzname _tzname
46
# endif
47
# endif
48
# endif
49
# if _dat_tzname && !defined(tzname)
50
extern char* tzname[];
51
# endif
52
#endif
53
54
#define TM_type (-1)
55
56
static const Namval_t options[] =
57
{
58
"adjust", TM_ADJUST,
59
"format", TM_DEFAULT,
60
"leap", TM_LEAP,
61
"subsecond", TM_SUBSECOND,
62
"type", TM_type,
63
"utc", TM_UTC,
64
0, 0
65
};
66
67
/*
68
* 2007-03-19 move tm_info from _tm_info_ to (*_tm_infop_)
69
* to allow future Tm_info_t growth
70
* by 2009 _tm_info_ can be static
71
*/
72
73
#if _BLD_ast && defined(__EXPORT__)
74
#define extern extern __EXPORT__
75
#endif
76
77
extern Tm_info_t _tm_info_;
78
79
#undef extern
80
81
Tm_info_t _tm_info_ = { 0 };
82
83
__EXTERN__(Tm_info_t, _tm_info_);
84
85
__EXTERN__(Tm_info_t*, _tm_infop_);
86
87
Tm_info_t* _tm_infop_ = &_tm_info_;
88
89
#if _tzset_environ
90
91
static char TZ[256];
92
static char* TE[2];
93
94
struct tm*
95
_tm_localtime(const time_t* t)
96
{
97
struct tm* r;
98
char* e;
99
char** v = environ;
100
101
if (TZ[0])
102
{
103
if (!environ || !*environ)
104
environ = TE;
105
else
106
e = environ[0];
107
environ[0] = TZ;
108
}
109
r = localtime(t);
110
if (TZ[0])
111
{
112
if (environ != v)
113
environ = v;
114
else
115
environ[0] = e;
116
}
117
return r;
118
}
119
120
#endif
121
122
/*
123
* return minutes west of GMT for local time clock
124
*
125
* isdst will point to non-zero if DST is in effect
126
* this routine also kicks in the local initialization
127
*/
128
129
static int
130
tzwest(time_t* clock, int* isdst)
131
{
132
register struct tm* tp;
133
register int n;
134
register int m;
135
int h;
136
time_t epoch;
137
138
/*
139
* convert to GMT assuming local time
140
*/
141
142
if (!(tp = gmtime(clock)))
143
{
144
/*
145
* some systems return 0 for negative time_t
146
*/
147
148
epoch = 0;
149
clock = &epoch;
150
tp = gmtime(clock);
151
}
152
n = tp->tm_yday;
153
h = tp->tm_hour;
154
m = tp->tm_min;
155
156
/*
157
* tmlocaltime() handles DST and GMT offset
158
*/
159
160
tp = tmlocaltime(clock);
161
if (n = tp->tm_yday - n)
162
{
163
if (n > 1)
164
n = -1;
165
else if (n < -1)
166
n = 1;
167
}
168
*isdst = tp->tm_isdst;
169
return (h - tp->tm_hour - n * 24) * 60 + m - tp->tm_min;
170
}
171
172
/*
173
* stropt() option handler
174
*/
175
176
static int
177
tmopt(void* a, const void* p, int n, const char* v)
178
{
179
Tm_zone_t* zp;
180
181
NoP(a);
182
if (p)
183
switch (((Namval_t*)p)->value)
184
{
185
case TM_DEFAULT:
186
tm_info.deformat = (n && (n = strlen(v)) > 0 && (n < 2 || v[n-2] != '%' || v[n-1] != '?')) ? strdup(v) : tm_info.format[TM_DEFAULT];
187
break;
188
case TM_type:
189
tm_info.local->type = (n && *v) ? ((zp = tmtype(v, NiL)) ? zp->type : strdup(v)) : 0;
190
break;
191
default:
192
if (n)
193
tm_info.flags |= ((Namval_t*)p)->value;
194
else
195
tm_info.flags &= ~((Namval_t*)p)->value;
196
break;
197
}
198
return 0;
199
}
200
201
/*
202
* initialize the local timezone
203
*/
204
205
static void
206
tmlocal(void)
207
{
208
register Tm_zone_t* zp;
209
register int n;
210
register char* s;
211
register char* e;
212
int i;
213
int m;
214
int isdst;
215
char* t;
216
struct tm* tp;
217
time_t now;
218
char buf[16];
219
220
static Tm_zone_t local;
221
222
#if _tzset_environ
223
{
224
char** v = environ;
225
226
if (s = getenv("TZ"))
227
{
228
sfsprintf(TZ, sizeof(TZ), "TZ=%s", s);
229
if (!environ || !*environ)
230
environ = TE;
231
else
232
e = environ[0];
233
environ[0] = TZ;
234
}
235
else
236
{
237
TZ[0] = 0;
238
e = 0;
239
}
240
#endif
241
#if _lib_tzset
242
tzset();
243
#endif
244
#if _tzset_environ
245
if (environ != v)
246
environ = v;
247
else if (e)
248
environ[0] = e;
249
}
250
#endif
251
#if _dat_tzname
252
local.standard = strdup(tzname[0]);
253
local.daylight = strdup(tzname[1]);
254
#endif
255
tmlocale();
256
257
/*
258
* tm_info.local
259
*/
260
261
tm_info.zone = tm_info.local = &local;
262
time(&now);
263
n = tzwest(&now, &isdst);
264
265
/*
266
* compute local DST offset by roaming
267
* through the last 12 months until tzwest() changes
268
*/
269
270
for (i = 0; i < 12; i++)
271
{
272
now -= 31 * 24 * 60 * 60;
273
if ((m = tzwest(&now, &isdst)) != n)
274
{
275
if (!isdst)
276
{
277
isdst = n;
278
n = m;
279
m = isdst;
280
}
281
m -= n;
282
break;
283
}
284
}
285
local.west = n;
286
local.dst = m;
287
288
/*
289
* now get the time zone names
290
*/
291
292
#if _dat_tzname
293
if (tzname[0])
294
{
295
/*
296
* POSIX
297
*/
298
299
if (!local.standard)
300
local.standard = strdup(tzname[0]);
301
if (!local.daylight)
302
local.daylight = strdup(tzname[1]);
303
}
304
else
305
#endif
306
if ((s = getenv("TZNAME")) && *s && (s = strdup(s)))
307
{
308
/*
309
* BSD
310
*/
311
312
local.standard = s;
313
if (s = strchr(s, ','))
314
*s++ = 0;
315
else
316
s = "";
317
local.daylight = s;
318
}
319
else if ((s = getenv("TZ")) && *s && *s != ':' && (s = strdup(s)))
320
{
321
/*
322
* POSIX style but skipped by tmlocaltime()
323
*/
324
325
local.standard = s;
326
if (*++s && *++s && *++s)
327
{
328
*s++ = 0;
329
tmgoff(s, &t, 0);
330
for (s = t; isalpha(*t); t++);
331
*t = 0;
332
}
333
else
334
s = "";
335
local.daylight = s;
336
}
337
else
338
{
339
/*
340
* tm_data.zone table lookup
341
*/
342
343
t = 0;
344
for (zp = tm_data.zone; zp->standard; zp++)
345
{
346
if (zp->type)
347
t = zp->type;
348
if (zp->west == n && zp->dst == m)
349
{
350
local.type = t;
351
local.standard = zp->standard;
352
if (!(s = zp->daylight))
353
{
354
e = (s = buf) + sizeof(buf);
355
s = tmpoff(s, e - s, zp->standard, 0, 0);
356
if (s < e - 1)
357
{
358
*s++ = ' ';
359
tmpoff(s, e - s, tm_info.format[TM_DT], m, TM_DST);
360
}
361
s = strdup(buf);
362
}
363
local.daylight = s;
364
break;
365
}
366
}
367
if (!zp->standard)
368
{
369
/*
370
* not in the table
371
*/
372
373
e = (s = buf) + sizeof(buf);
374
s = tmpoff(s, e - s, tm_info.format[TM_UT], n, 0);
375
local.standard = strdup(buf);
376
if (s < e - 1)
377
{
378
*s++ = ' ';
379
tmpoff(s, e - s, tm_info.format[TM_UT], m, TM_DST);
380
local.daylight = strdup(buf);
381
}
382
}
383
}
384
385
/*
386
* set the options
387
*/
388
389
stropt(getenv("TM_OPTIONS"), options, sizeof(*options), tmopt, NiL);
390
391
/*
392
* the time zone type is probably related to the locale
393
*/
394
395
if (!local.type)
396
{
397
s = local.standard;
398
t = 0;
399
for (zp = tm_data.zone; zp->standard; zp++)
400
{
401
if (zp->type)
402
t = zp->type;
403
if (tmword(s, NiL, zp->standard, NiL, 0))
404
{
405
local.type = t;
406
break;
407
}
408
}
409
}
410
411
/*
412
* tm_info.flags
413
*/
414
415
if (!(tm_info.flags & TM_ADJUST))
416
{
417
now = (time_t)78811200; /* Jun 30 1972 23:59:60 */
418
tp = tmlocaltime(&now);
419
if (tp->tm_sec != 60)
420
tm_info.flags |= TM_ADJUST;
421
}
422
if (!(tm_info.flags & TM_UTC))
423
{
424
s = local.standard;
425
zp = tm_data.zone;
426
if (local.daylight)
427
zp++;
428
for (; !zp->type && zp->standard; zp++)
429
if (tmword(s, NiL, zp->standard, NiL, 0))
430
{
431
tm_info.flags |= TM_UTC;
432
break;
433
}
434
}
435
}
436
437
/*
438
* initialize tm data
439
*/
440
441
void
442
tminit(register Tm_zone_t* zp)
443
{
444
static uint32_t serial = ~(uint32_t)0;
445
446
if (serial != ast.env_serial)
447
{
448
serial = ast.env_serial;
449
if (tm_info.local)
450
{
451
memset(tm_info.local, 0, sizeof(*tm_info.local));
452
tm_info.local = 0;
453
}
454
}
455
if (!tm_info.local)
456
tmlocal();
457
if (!zp)
458
zp = tm_info.local;
459
tm_info.zone = zp;
460
}
461
462