|
1 /* |
|
2 ** This file is in the public domain, so clarified as of |
|
3 ** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). |
|
4 |
|
5 ** © Portions Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. |
|
6 */ |
|
7 |
|
8 #include <sys/cdefs.h> |
|
9 #ifndef lint |
|
10 #ifndef NOID |
|
11 static char elsieid[] __unused = "@(#)localtime.c 7.78"; |
|
12 #endif /* !defined NOID */ |
|
13 #endif /* !defined lint */ |
|
14 __FBSDID("$FreeBSD: src/lib/libc/stdtime/localtime.c,v 1.40 2004/08/24 00:15:37 peter Exp $"); |
|
15 |
|
16 /* |
|
17 ** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu). |
|
18 ** POSIX-style TZ environment variable handling from Guy Harris |
|
19 ** (guy@auspex.com). |
|
20 */ |
|
21 #include <time.h> |
|
22 |
|
23 /*LINTLIBRARY*/ |
|
24 #include <unistd.h> |
|
25 #include "namespace.h" |
|
26 #include <sys/types.h> |
|
27 #include <pthread.h> |
|
28 #include "private.h" |
|
29 #include "un-namespace.h" |
|
30 #include "tzfile.h" |
|
31 #include <fcntl.h> |
|
32 #include <sys/stat.h> |
|
33 #include "libc_private.h" |
|
34 #include "common_def.h" |
|
35 #include <wchar.h> |
|
36 #include "timefuncs.h" |
|
37 |
|
38 #if (defined(__SYMBIAN32__) && (defined(__WINSCW__) || defined(__WINS__))) |
|
39 #include "libc_wsd_defs.h" |
|
40 #endif |
|
41 |
|
42 #define _MUTEX_LOCK(x) if (__isthreaded) _pthread_mutex_lock(x) |
|
43 #define _MUTEX_UNLOCK(x) if (__isthreaded) _pthread_mutex_unlock(x) |
|
44 |
|
45 /* |
|
46 ** SunOS 4.1.1 headers lack O_BINARY. |
|
47 */ |
|
48 |
|
49 #ifdef O_BINARY |
|
50 #define OPEN_MODE (O_RDONLY | O_BINARY) |
|
51 #endif /* defined O_BINARY */ |
|
52 #ifndef O_BINARY |
|
53 #define OPEN_MODE O_RDONLY |
|
54 #endif /* !defined O_BINARY */ |
|
55 |
|
56 #ifndef WILDABBR |
|
57 /* |
|
58 ** Someone might make incorrect use of a time zone abbreviation: |
|
59 ** 1. They might reference tzname[0] before calling tzset (explicitly |
|
60 ** or implicitly). |
|
61 ** 2. They might reference tzname[1] before calling tzset (explicitly |
|
62 ** or implicitly). |
|
63 ** 3. They might reference tzname[1] after setting to a time zone |
|
64 ** in which Daylight Saving Time is never observed. |
|
65 ** 4. They might reference tzname[0] after setting to a time zone |
|
66 ** in which Standard Time is never observed. |
|
67 ** 5. They might reference tm.TM_ZONE after calling offtime. |
|
68 ** What's best to do in the above cases is open to debate; |
|
69 ** for now, we just set things up so that in any of the five cases |
|
70 ** WILDABBR is used. Another possibility: initialize tzname[0] to the |
|
71 ** string "tzname[0] used before set", and similarly for the other cases. |
|
72 ** And another: initialize tzname[0] to "ERA", with an explanation in the |
|
73 ** manual page of what this "time zone abbreviation" means (doing this so |
|
74 ** that tzname[0] has the "normal" length of three characters). |
|
75 */ |
|
76 #define WILDABBR " " |
|
77 #endif /* !defined WILDABBR */ |
|
78 |
|
79 #ifdef __SYMBIAN32__ |
|
80 extern int GetStdOffset(void); |
|
81 extern int GetIsDst(void); |
|
82 #endif //__SYMBIAN32__ |
|
83 |
|
84 #ifdef __SYMBIAN32__ |
|
85 #ifndef EMULATOR |
|
86 |
|
87 static char wildabbr[] = "WILDABBR"; |
|
88 #else //EMULATOR |
|
89 |
|
90 GET_STATIC_ARRAY_FROM_TLS(wildabbr, char) |
|
91 #define wildabbr (GET_WSD_VAR_NAME(wildabbr, s)()) |
|
92 #endif //EMULATOR |
|
93 #else |
|
94 static char wildabbr[] = "WILDABBR"; |
|
95 #endif //__SYMBIAN32__ |
|
96 |
|
97 /* |
|
98 * In June 2004 it was decided UTC was a more appropriate default time |
|
99 * zone than GMT. |
|
100 */ |
|
101 |
|
102 #ifdef __SYMBIAN32__ |
|
103 #if !(defined(EMULATOR)) |
|
104 static const char gmt[] = "UTC"; |
|
105 #endif //EMULATOR |
|
106 #else |
|
107 static const char gmt[] = "UTC"; |
|
108 #endif //__SYMBIAN32__ |
|
109 |
|
110 /* |
|
111 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES. |
|
112 ** We default to US rules as of 1999-08-17. |
|
113 ** POSIX 1003.1 section 8.1.1 says that the default DST rules are |
|
114 ** implementation dependent; for historical reasons, US rules are a |
|
115 ** common default. |
|
116 */ |
|
117 #ifndef TZDEFRULESTRING |
|
118 #define TZDEFRULESTRING ",M4.1.0,M10.5.0" |
|
119 #endif /* !defined TZDEFDST */ |
|
120 |
|
121 #ifdef __SYMBIAN32__ |
|
122 #ifndef EMULATOR |
|
123 struct ttinfo { /* time type information */ |
|
124 long tt_gmtoff; /* UTC offset in seconds */ |
|
125 int tt_isdst; /* used to set tm_isdst */ |
|
126 int tt_abbrind; /* abbreviation list index */ |
|
127 int tt_ttisstd; /* TRUE if transition is std time */ |
|
128 int tt_ttisgmt; /* TRUE if transition is UTC */ |
|
129 }; |
|
130 |
|
131 struct lsinfo { /* leap second information */ |
|
132 time_t ls_trans; /* transition time */ |
|
133 long ls_corr; /* correction to apply */ |
|
134 }; |
|
135 #endif //EMULATOR |
|
136 #else |
|
137 struct ttinfo { /* time type information */ |
|
138 long tt_gmtoff; /* UTC offset in seconds */ |
|
139 int tt_isdst; /* used to set tm_isdst */ |
|
140 int tt_abbrind; /* abbreviation list index */ |
|
141 int tt_ttisstd; /* TRUE if transition is std time */ |
|
142 int tt_ttisgmt; /* TRUE if transition is UTC */ |
|
143 }; |
|
144 |
|
145 struct lsinfo { /* leap second information */ |
|
146 time_t ls_trans; /* transition time */ |
|
147 long ls_corr; /* correction to apply */ |
|
148 }; |
|
149 #endif //__SYMBIAN32__ |
|
150 |
|
151 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b)) |
|
152 |
|
153 #ifdef TZNAME_MAX |
|
154 #define MY_TZNAME_MAX TZNAME_MAX |
|
155 #endif /* defined TZNAME_MAX */ |
|
156 #ifndef TZNAME_MAX |
|
157 #define MY_TZNAME_MAX 255 |
|
158 #endif /* !defined TZNAME_MAX */ |
|
159 |
|
160 #ifdef __SYMBIAN32__ |
|
161 #ifndef EMULATOR |
|
162 struct state { |
|
163 int leapcnt; |
|
164 int timecnt; |
|
165 int typecnt; |
|
166 int charcnt; |
|
167 time_t ats[TZ_MAX_TIMES]; |
|
168 unsigned char types[TZ_MAX_TIMES]; |
|
169 struct ttinfo ttis[TZ_MAX_TYPES]; |
|
170 char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt), |
|
171 (2 * (MY_TZNAME_MAX + 1)))]; |
|
172 struct lsinfo lsis[TZ_MAX_LEAPS]; |
|
173 }; |
|
174 #endif //EMULATOR |
|
175 #else |
|
176 struct state { |
|
177 int leapcnt; |
|
178 int timecnt; |
|
179 int typecnt; |
|
180 int charcnt; |
|
181 time_t ats[TZ_MAX_TIMES]; |
|
182 unsigned char types[TZ_MAX_TIMES]; |
|
183 struct ttinfo ttis[TZ_MAX_TYPES]; |
|
184 char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt), |
|
185 (2 * (MY_TZNAME_MAX + 1)))]; |
|
186 struct lsinfo lsis[TZ_MAX_LEAPS]; |
|
187 }; |
|
188 #endif //__SYMBIAN32__ |
|
189 |
|
190 struct rule { |
|
191 int r_type; /* type of rule--see below */ |
|
192 int r_day; /* day number of rule */ |
|
193 int r_week; /* week number of rule */ |
|
194 int r_mon; /* month number of rule */ |
|
195 long r_time; /* transition time of rule */ |
|
196 }; |
|
197 |
|
198 #define JULIAN_DAY 0 /* Jn - Julian day */ |
|
199 #define DAY_OF_YEAR 1 /* n - day of year */ |
|
200 #define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */ |
|
201 |
|
202 /* |
|
203 ** Prototypes for static functions. |
|
204 */ |
|
205 |
|
206 #ifndef __SYMBIAN32__ |
|
207 static long detzcode(const char * codep); |
|
208 #endif //__SYMBIAN32__ |
|
209 static const char * getzname(const char * strp); |
|
210 static const char * getnum(const char * strp, int * nump, int min, |
|
211 int max); |
|
212 static const char * getsecs(const char * strp, long * secsp); |
|
213 static const char * getoffset(const char * strp, long * offsetp); |
|
214 static const char * getrule(const char * strp, struct rule * rulep); |
|
215 static void gmtload(struct state * sp); |
|
216 static void gmtsub(const time_t * timep, long offset, |
|
217 struct tm * tmp); |
|
218 static void localsub(const time_t * timep, long offset, |
|
219 struct tm * tmp); |
|
220 static int increment_overflow(int * number, int delta); |
|
221 static int normalize_overflow(int * tensptr, int * unitsptr, |
|
222 int base); |
|
223 static void settzname(void); |
|
224 static time_t time1(struct tm * tmp, |
|
225 void(*funcp) (const time_t *, |
|
226 long, struct tm *), |
|
227 long offset); |
|
228 static time_t time2(struct tm *tmp, |
|
229 void(*funcp) (const time_t *, |
|
230 long, struct tm*), |
|
231 long offset, int * okayp); |
|
232 static time_t time2sub(struct tm *tmp, |
|
233 void(*funcp) (const time_t *, |
|
234 long, struct tm*), |
|
235 long offset, int * okayp, int do_norm_secs); |
|
236 static void timesub(const time_t * timep, long offset, |
|
237 const struct state * sp, struct tm * tmp); |
|
238 static int tmcomp(const struct tm * atmp, |
|
239 const struct tm * btmp); |
|
240 static time_t transtime(time_t janfirst, int year, |
|
241 const struct rule * rulep, long offset); |
|
242 static int tzload(const char * name, struct state * sp); |
|
243 static int tzparse(const char * name, struct state * sp, |
|
244 int lastditch); |
|
245 |
|
246 #ifdef ALL_STATE |
|
247 |
|
248 #ifdef __SYMBIAN32__ |
|
249 #ifndef EMULATOR |
|
250 |
|
251 static struct state * lclptr; |
|
252 static struct state * gmtptr; |
|
253 #else //EMULATOR |
|
254 |
|
255 GET_STATIC_VAR_FROM_TLS(lclptr, state *) |
|
256 GET_STATIC_VAR_FROM_TLS(gmtptr, state *) |
|
257 |
|
258 #define lclptr (*GET_WSD_VAR_NAME(lclptr, s)()) |
|
259 #define gmtptr (*GET_WSD_VAR_NAME(gmtptr, s)()) |
|
260 #endif //EMULATOR |
|
261 #else //__SYMBIAN32__ |
|
262 static struct state * lclptr; |
|
263 static struct state * gmtptr; |
|
264 #endif //__SYMBIAN32__ |
|
265 |
|
266 #endif /* defined ALL_STATE */ |
|
267 |
|
268 #ifndef ALL_STATE |
|
269 |
|
270 #ifdef __SYMBIAN32__ |
|
271 #ifndef EMULATOR |
|
272 |
|
273 static struct state lclmem; |
|
274 static struct state gmtmem; |
|
275 #else //EMULATOR |
|
276 |
|
277 GET_STATIC_VAR_FROM_TLS(lclmem, struct state) |
|
278 GET_STATIC_VAR_FROM_TLS(gmtmem, struct state) |
|
279 #define lclmem (*GET_WSD_VAR_NAME(lclmem, s)()) |
|
280 #define gmtmem (*GET_WSD_VAR_NAME(gmtmem, s)()) |
|
281 #endif //EMULATOR |
|
282 #else //__SYMBIAN32__ |
|
283 static struct state lclmem; |
|
284 static struct state gmtmem; |
|
285 #endif //__SYMBIAN32__ |
|
286 |
|
287 #define lclptr (&lclmem) |
|
288 #define gmtptr (&gmtmem) |
|
289 #endif /* State Farm */ |
|
290 |
|
291 #ifndef TZ_STRLEN_MAX |
|
292 #define TZ_STRLEN_MAX 255 |
|
293 #endif /* !defined TZ_STRLEN_MAX */ |
|
294 |
|
295 #ifdef __SYMBIAN32__ |
|
296 #ifndef EMULATOR |
|
297 |
|
298 static char lcl_TZname[TZ_STRLEN_MAX + 1]; |
|
299 static int lcl_is_set; |
|
300 static int gmt_is_set; |
|
301 static pthread_mutex_t lcl_mutex = PTHREAD_MUTEX_INITIALIZER; |
|
302 static pthread_mutex_t gmt_mutex = PTHREAD_MUTEX_INITIALIZER; |
|
303 |
|
304 char **_tzname = NULL; |
|
305 #else //EMULATOR |
|
306 |
|
307 GET_STATIC_ARRAY_FROM_TLS(lcl_TZname, char) |
|
308 GET_STATIC_VAR_FROM_TLS(lcl_is_set, int) |
|
309 GET_STATIC_VAR_FROM_TLS(gmt_is_set, int) |
|
310 GET_STATIC_VAR_FROM_TLS(lcl_mutex, pthread_mutex_t) |
|
311 GET_STATIC_VAR_FROM_TLS(gmt_mutex, pthread_mutex_t) |
|
312 |
|
313 |
|
314 #define lcl_TZname (GET_WSD_VAR_NAME(lcl_TZname, s)()) |
|
315 #define lcl_is_set (*GET_WSD_VAR_NAME(lcl_is_set, s)()) |
|
316 #define gmt_is_set (*GET_WSD_VAR_NAME(gmt_is_set, s)()) |
|
317 #define lcl_mutex (*GET_WSD_VAR_NAME(lcl_mutex, s)()) |
|
318 #define gmt_mutex (*GET_WSD_VAR_NAME(gmt_mutex, s)()) |
|
319 |
|
320 #endif //EMULATOR |
|
321 #else //__SYMBIAN32__ |
|
322 |
|
323 static char lcl_TZname[TZ_STRLEN_MAX + 1]; |
|
324 static int lcl_is_set; |
|
325 static int gmt_is_set; |
|
326 static pthread_mutex_t lcl_mutex = PTHREAD_MUTEX_INITIALIZER; |
|
327 static pthread_mutex_t gmt_mutex = PTHREAD_MUTEX_INITIALIZER; |
|
328 |
|
329 char * tzname[2] = { |
|
330 wildabbr, |
|
331 wildabbr |
|
332 }; |
|
333 #endif //__SYMBIAN32__ |
|
334 |
|
335 /* |
|
336 ** Section 4.12.3 of X3.159-1989 requires that |
|
337 ** Except for the strftime function, these functions [asctime, |
|
338 ** ctime, gmtime, localtime] return values in one of two static |
|
339 ** objects: a broken-down time structure and an array of char. |
|
340 ** Thanks to Paul Eggert (eggert@twinsun.com) for noting this. |
|
341 */ |
|
342 #ifdef __SYMBIAN32__ |
|
343 #ifndef EMULATOR |
|
344 |
|
345 struct tm stm; |
|
346 #else //EMULATOR |
|
347 |
|
348 GET_GLOBAL_VAR_FROM_TLS(stm, struct tm) |
|
349 #define stm (*GET_WSD_VAR_NAME(stm, g)()) |
|
350 #endif //EMULATOR |
|
351 #else //__SYMBIAN32__ |
|
352 static struct tm tm; |
|
353 #endif //__SYMBIAN32__ |
|
354 |
|
355 #ifdef USG_COMPAT |
|
356 |
|
357 #ifdef __SYMBIAN32__ |
|
358 #ifndef EMULATOR |
|
359 |
|
360 time_t timezone = 0; |
|
361 int daylight = 0; |
|
362 #else //EMULATOR |
|
363 |
|
364 GET_GLOBAL_VAR_FROM_TLS(timezone, time_t) |
|
365 GET_GLOBAL_VAR_FROM_TLS(daylight, int) |
|
366 |
|
367 #define timezone (*GET_WSD_VAR_NAME(timezone, g)()) |
|
368 #define daylight (*GET_WSD_VAR_NAME(daylight, g)()) |
|
369 #endif //EMULATOR |
|
370 #else //__SYMBIAN32__ |
|
371 time_t timezone = 0; |
|
372 int daylight = 0; |
|
373 #endif //__SYMBIAN32__ |
|
374 |
|
375 #endif /* defined USG_COMPAT */ |
|
376 |
|
377 #ifdef ALTZONE |
|
378 |
|
379 #ifdef __SYMBIAN32__ |
|
380 #ifndef EMULATOR |
|
381 |
|
382 time_t altzone = 0; |
|
383 #else //EMULATOR |
|
384 |
|
385 GET_GLOBAL_VAR_FROM_TLS(altzone, time_t) |
|
386 #define altzone (*GET_WSD_VAR_NAME(altzone, g)()) |
|
387 #endif //EMULATOR |
|
388 #else //__SYMBIAN32__ |
|
389 time_t altzone = 0; |
|
390 #endif //__SYMBIAN32__ |
|
391 |
|
392 #endif /* defined ALTZONE */ |
|
393 |
|
394 #ifdef __SYMBIAN32__ |
|
395 #ifdef EMULATOR |
|
396 |
|
397 GET_STATIC_VAR_FROM_TLS(localtime_key, pthread_key_t) |
|
398 GET_STATIC_VAR_FROM_TLS(localtime_mutex, pthread_mutex_t) |
|
399 GET_STATIC_VAR_FROM_TLS(gmtime_key, pthread_key_t) |
|
400 GET_STATIC_VAR_FROM_TLS(gmtime_mutex, pthread_mutex_t) |
|
401 |
|
402 #define localtime_mutex (*GET_WSD_VAR_NAME(localtime_mutex, s)()) |
|
403 #define localtime_key (*GET_WSD_VAR_NAME(localtime_key, s)()) |
|
404 #define gmtime_mutex (*GET_WSD_VAR_NAME(gmtime_mutex, s)()) |
|
405 #define gmtime_key (*GET_WSD_VAR_NAME(gmtime_key, s)()) |
|
406 |
|
407 #endif //EMULATOR |
|
408 #endif //__SYMBIAN32__ |
|
409 |
|
410 #if !defined(__SYMBIAN32__) || defined(__SYMBIAN_COMPILE_UNUSED__) |
|
411 static long |
|
412 detzcode(codep) |
|
413 const char * const codep; |
|
414 { |
|
415 long result; |
|
416 int i; |
|
417 |
|
418 result = (codep[0] & 0x80) ? ~0L : 0L; |
|
419 for (i = 0; i < 4; ++i) |
|
420 result = (result << 8) | (codep[i] & 0xff); |
|
421 return result; |
|
422 } |
|
423 #endif //if defined(__SYMBIAN32__) || defined (__SYMBIAN_COMPILE_UNUSED__) |
|
424 |
|
425 static void |
|
426 settzname(void) |
|
427 { |
|
428 struct state * sp = lclptr; |
|
429 int i; |
|
430 |
|
431 tzname[0] = wildabbr; |
|
432 tzname[1] = wildabbr; |
|
433 #ifdef USG_COMPAT |
|
434 daylight = 0; |
|
435 timezone = 0; |
|
436 #endif /* defined USG_COMPAT */ |
|
437 #ifdef ALTZONE |
|
438 altzone = 0; |
|
439 #endif /* defined ALTZONE */ |
|
440 #ifdef ALL_STATE |
|
441 if (sp == NULL) { |
|
442 tzname[0] = tzname[1] = gmt; |
|
443 return; |
|
444 } |
|
445 #endif /* defined ALL_STATE */ |
|
446 for (i = 0; i < sp->typecnt; ++i) { |
|
447 const struct ttinfo * const ttisp = &sp->ttis[i]; |
|
448 |
|
449 tzname[ttisp->tt_isdst] = |
|
450 &sp->chars[ttisp->tt_abbrind]; |
|
451 #ifdef USG_COMPAT |
|
452 if (ttisp->tt_isdst) |
|
453 daylight = 1; |
|
454 if (i == 0 || !ttisp->tt_isdst) |
|
455 timezone = -(ttisp->tt_gmtoff); |
|
456 #endif /* defined USG_COMPAT */ |
|
457 #ifdef ALTZONE |
|
458 if (i == 0 || ttisp->tt_isdst) |
|
459 altzone = -(ttisp->tt_gmtoff); |
|
460 #endif /* defined ALTZONE */ |
|
461 } |
|
462 /* |
|
463 ** And to get the latest zone names into tzname. . . |
|
464 */ |
|
465 for (i = 0; i < sp->timecnt; ++i) { |
|
466 const struct ttinfo * const ttisp = |
|
467 &sp->ttis[ |
|
468 sp->types[i]]; |
|
469 |
|
470 tzname[ttisp->tt_isdst] = |
|
471 &sp->chars[ttisp->tt_abbrind]; |
|
472 } |
|
473 } |
|
474 |
|
475 static int |
|
476 tzload(name, sp) |
|
477 const char * name; |
|
478 struct state * const sp; |
|
479 { |
|
480 #ifndef __SYMBIAN32__ |
|
481 const char * p; |
|
482 int i; |
|
483 int fid; |
|
484 #else//__SYMBIAN32__ |
|
485 if(sp) { }//dummy implementation |
|
486 #endif//__SYMBIAN32__ |
|
487 /* XXX The following is from OpenBSD, and I'm not sure it is correct */ |
|
488 if (name != NULL && issetugid() != 0) |
|
489 if ((name[0] == ':' && name[1] == '/') || |
|
490 name[0] == '/' || strchr(name, '.')) |
|
491 name = NULL; |
|
492 if (name == NULL && (name = TZDEFAULT) == NULL) |
|
493 return -1; |
|
494 |
|
495 #ifdef __SYMBIAN32__ |
|
496 return -1; //We are doing this for the simple reason that these files |
|
497 //do not exist in the Symbian environment and we really dont |
|
498 //need to try accessing them |
|
499 #else //__SYMBIAN32__ |
|
500 |
|
501 { |
|
502 int doaccess; |
|
503 struct stat stab; |
|
504 /* |
|
505 ** Section 4.9.1 of the C standard says that |
|
506 ** "FILENAME_MAX expands to an integral constant expression |
|
507 ** that is the size needed for an array of char large enough |
|
508 ** to hold the longest file name string that the implementation |
|
509 ** guarantees can be opened." |
|
510 */ |
|
511 char fullname[FILENAME_MAX + 1]; |
|
512 |
|
513 if (name[0] == ':') |
|
514 ++name; |
|
515 doaccess = name[0] == '/'; |
|
516 if (!doaccess) { |
|
517 if ((p = TZDIR) == NULL) |
|
518 return -1; |
|
519 if ((strlen(p) + 1 + strlen(name) + 1) >= sizeof fullname) |
|
520 return -1; |
|
521 (void) strcpy(fullname, p); |
|
522 (void) strcat(fullname, "/"); |
|
523 (void) strcat(fullname, name); |
|
524 /* |
|
525 ** Set doaccess if '.' (as in "../") shows up in name. |
|
526 */ |
|
527 if (strchr(name, '.') != NULL) |
|
528 doaccess = TRUE; |
|
529 name = fullname; |
|
530 } |
|
531 if (doaccess && access(name, R_OK) != 0) |
|
532 return -1; |
|
533 if ((fid = _open(name, OPEN_MODE)) == -1) |
|
534 return -1; |
|
535 if ((_fstat(fid, &stab) < 0) || !S_ISREG(stab.st_mode)) { |
|
536 _close(fid); |
|
537 return -1; |
|
538 } |
|
539 } |
|
540 { |
|
541 struct tzhead * tzhp; |
|
542 union { |
|
543 struct tzhead tzhead; |
|
544 char buf[sizeof *sp + sizeof *tzhp]; |
|
545 } u; |
|
546 int ttisstdcnt; |
|
547 int ttisgmtcnt; |
|
548 |
|
549 i = _read(fid, u.buf, sizeof u.buf); |
|
550 if (_close(fid) != 0) |
|
551 return -1; |
|
552 ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt); |
|
553 ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt); |
|
554 sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt); |
|
555 sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt); |
|
556 sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt); |
|
557 sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt); |
|
558 p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt; |
|
559 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS || |
|
560 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES || |
|
561 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES || |
|
562 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS || |
|
563 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) || |
|
564 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0)) |
|
565 return -1; |
|
566 if (i - (p - u.buf) < sp->timecnt * 4 + /* ats */ |
|
567 sp->timecnt + /* types */ |
|
568 sp->typecnt * (4 + 2) + /* ttinfos */ |
|
569 sp->charcnt + /* chars */ |
|
570 sp->leapcnt * (4 + 4) + /* lsinfos */ |
|
571 ttisstdcnt + /* ttisstds */ |
|
572 ttisgmtcnt) /* ttisgmts */ |
|
573 return -1; |
|
574 for (i = 0; i < sp->timecnt; ++i) { |
|
575 sp->ats[i] = detzcode(p); |
|
576 p += 4; |
|
577 } |
|
578 for (i = 0; i < sp->timecnt; ++i) { |
|
579 sp->types[i] = (unsigned char) *p++; |
|
580 if (sp->types[i] >= sp->typecnt) |
|
581 return -1; |
|
582 } |
|
583 for (i = 0; i < sp->typecnt; ++i) { |
|
584 struct ttinfo * ttisp; |
|
585 |
|
586 ttisp = &sp->ttis[i]; |
|
587 ttisp->tt_gmtoff = detzcode(p); |
|
588 p += 4; |
|
589 ttisp->tt_isdst = (unsigned char) *p++; |
|
590 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1) |
|
591 return -1; |
|
592 ttisp->tt_abbrind = (unsigned char) *p++; |
|
593 if (ttisp->tt_abbrind < 0 || |
|
594 ttisp->tt_abbrind > sp->charcnt) |
|
595 return -1; |
|
596 } |
|
597 for (i = 0; i < sp->charcnt; ++i) |
|
598 sp->chars[i] = *p++; |
|
599 sp->chars[i] = '\0'; /* ensure '\0' at end */ |
|
600 for (i = 0; i < sp->leapcnt; ++i) { |
|
601 struct lsinfo * lsisp; |
|
602 |
|
603 lsisp = &sp->lsis[i]; |
|
604 lsisp->ls_trans = detzcode(p); |
|
605 p += 4; |
|
606 lsisp->ls_corr = detzcode(p); |
|
607 p += 4; |
|
608 } |
|
609 for (i = 0; i < sp->typecnt; ++i) { |
|
610 struct ttinfo * ttisp; |
|
611 |
|
612 ttisp = &sp->ttis[i]; |
|
613 if (ttisstdcnt == 0) |
|
614 ttisp->tt_ttisstd = FALSE; |
|
615 else { |
|
616 ttisp->tt_ttisstd = *p++; |
|
617 if (ttisp->tt_ttisstd != TRUE && |
|
618 ttisp->tt_ttisstd != FALSE) |
|
619 return -1; |
|
620 } |
|
621 } |
|
622 for (i = 0; i < sp->typecnt; ++i) { |
|
623 struct ttinfo * ttisp; |
|
624 |
|
625 ttisp = &sp->ttis[i]; |
|
626 if (ttisgmtcnt == 0) |
|
627 ttisp->tt_ttisgmt = FALSE; |
|
628 else { |
|
629 ttisp->tt_ttisgmt = *p++; |
|
630 if (ttisp->tt_ttisgmt != TRUE && |
|
631 ttisp->tt_ttisgmt != FALSE) |
|
632 return -1; |
|
633 } |
|
634 } |
|
635 } |
|
636 #endif //__SYMBIAN32__ |
|
637 return 0; |
|
638 } |
|
639 |
|
640 static const int mon_lengths[2][MONSPERYEAR] = { |
|
641 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, |
|
642 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } |
|
643 }; |
|
644 |
|
645 static const int year_lengths[2] = { |
|
646 DAYSPERNYEAR, DAYSPERLYEAR |
|
647 }; |
|
648 |
|
649 /* |
|
650 ** Given a pointer into a time zone string, scan until a character that is not |
|
651 ** a valid character in a zone name is found. Return a pointer to that |
|
652 ** character. |
|
653 */ |
|
654 |
|
655 static const char * |
|
656 getzname(strp) |
|
657 const char * strp; |
|
658 { |
|
659 char c; |
|
660 |
|
661 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' && |
|
662 c != '+') |
|
663 ++strp; |
|
664 return strp; |
|
665 } |
|
666 |
|
667 /* |
|
668 ** Given a pointer into a time zone string, extract a number from that string. |
|
669 ** Check that the number is within a specified range; if it is not, return |
|
670 ** NULL. |
|
671 ** Otherwise, return a pointer to the first character not part of the number. |
|
672 */ |
|
673 |
|
674 static const char * |
|
675 getnum(strp, nump, min, max) |
|
676 const char * strp; |
|
677 int * const nump; |
|
678 const int min; |
|
679 const int max; |
|
680 { |
|
681 char c; |
|
682 int num; |
|
683 |
|
684 if (strp == NULL || !is_digit(c = *strp)) |
|
685 return NULL; |
|
686 num = 0; |
|
687 do { |
|
688 num = num * 10 + (c - '0'); |
|
689 if (num > max) |
|
690 return NULL; /* illegal value */ |
|
691 c = *++strp; |
|
692 } while (is_digit(c)); |
|
693 if (num < min) |
|
694 return NULL; /* illegal value */ |
|
695 *nump = num; |
|
696 return strp; |
|
697 } |
|
698 |
|
699 /* |
|
700 ** Given a pointer into a time zone string, extract a number of seconds, |
|
701 ** in hh[:mm[:ss]] form, from the string. |
|
702 ** If any error occurs, return NULL. |
|
703 ** Otherwise, return a pointer to the first character not part of the number |
|
704 ** of seconds. |
|
705 */ |
|
706 |
|
707 static const char * |
|
708 getsecs(strp, secsp) |
|
709 const char * strp; |
|
710 long * const secsp; |
|
711 { |
|
712 int num; |
|
713 |
|
714 /* |
|
715 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like |
|
716 ** "M10.4.6/26", which does not conform to Posix, |
|
717 ** but which specifies the equivalent of |
|
718 ** ``02:00 on the first Sunday on or after 23 Oct''. |
|
719 */ |
|
720 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1); |
|
721 if (strp == NULL) |
|
722 return NULL; |
|
723 *secsp = num * (long) SECSPERHOUR; |
|
724 if (*strp == ':') { |
|
725 ++strp; |
|
726 strp = getnum(strp, &num, 0, MINSPERHOUR - 1); |
|
727 if (strp == NULL) |
|
728 return NULL; |
|
729 *secsp += num * SECSPERMIN; |
|
730 if (*strp == ':') { |
|
731 ++strp; |
|
732 /* `SECSPERMIN' allows for leap seconds. */ |
|
733 strp = getnum(strp, &num, 0, SECSPERMIN); |
|
734 if (strp == NULL) |
|
735 return NULL; |
|
736 *secsp += num; |
|
737 } |
|
738 } |
|
739 return strp; |
|
740 } |
|
741 |
|
742 /* |
|
743 ** Given a pointer into a time zone string, extract an offset, in |
|
744 ** [+-]hh[:mm[:ss]] form, from the string. |
|
745 ** If any error occurs, return NULL. |
|
746 ** Otherwise, return a pointer to the first character not part of the time. |
|
747 */ |
|
748 |
|
749 static const char * |
|
750 getoffset(strp, offsetp) |
|
751 const char * strp; |
|
752 long * const offsetp; |
|
753 { |
|
754 int neg = 0; |
|
755 |
|
756 if (*strp == '-') { |
|
757 neg = 1; |
|
758 ++strp; |
|
759 } else if (*strp == '+') |
|
760 ++strp; |
|
761 strp = getsecs(strp, offsetp); |
|
762 if (strp == NULL) |
|
763 return NULL; /* illegal time */ |
|
764 if (neg) |
|
765 *offsetp = -*offsetp; |
|
766 return strp; |
|
767 } |
|
768 |
|
769 /* |
|
770 ** Given a pointer into a time zone string, extract a rule in the form |
|
771 ** date[/time]. See POSIX section 8 for the format of "date" and "time". |
|
772 ** If a valid rule is not found, return NULL. |
|
773 ** Otherwise, return a pointer to the first character not part of the rule. |
|
774 */ |
|
775 |
|
776 static const char * |
|
777 getrule(strp, rulep) |
|
778 const char * strp; |
|
779 struct rule * const rulep; |
|
780 { |
|
781 if (*strp == 'J') { |
|
782 /* |
|
783 ** Julian day. |
|
784 */ |
|
785 rulep->r_type = JULIAN_DAY; |
|
786 ++strp; |
|
787 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR); |
|
788 } else if (*strp == 'M') { |
|
789 /* |
|
790 ** Month, week, day. |
|
791 */ |
|
792 rulep->r_type = MONTH_NTH_DAY_OF_WEEK; |
|
793 ++strp; |
|
794 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR); |
|
795 if (strp == NULL) |
|
796 return NULL; |
|
797 if (*strp++ != '.') |
|
798 return NULL; |
|
799 strp = getnum(strp, &rulep->r_week, 1, 5); |
|
800 if (strp == NULL) |
|
801 return NULL; |
|
802 if (*strp++ != '.') |
|
803 return NULL; |
|
804 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1); |
|
805 } else if (is_digit(*strp)) { |
|
806 /* |
|
807 ** Day of year. |
|
808 */ |
|
809 rulep->r_type = DAY_OF_YEAR; |
|
810 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1); |
|
811 } else return NULL; /* invalid format */ |
|
812 if (strp == NULL) |
|
813 return NULL; |
|
814 if (*strp == '/') { |
|
815 /* |
|
816 ** Time specified. |
|
817 */ |
|
818 ++strp; |
|
819 strp = getsecs(strp, &rulep->r_time); |
|
820 } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */ |
|
821 return strp; |
|
822 } |
|
823 |
|
824 /* |
|
825 ** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the |
|
826 ** year, a rule, and the offset from UTC at the time that rule takes effect, |
|
827 ** calculate the Epoch-relative time that rule takes effect. |
|
828 */ |
|
829 |
|
830 static time_t |
|
831 transtime(janfirst, year, rulep, offset) |
|
832 const time_t janfirst; |
|
833 const int year; |
|
834 const struct rule * const rulep; |
|
835 const long offset; |
|
836 { |
|
837 int leapyear; |
|
838 time_t value; |
|
839 int i; |
|
840 int d, m1, yy0, yy1, yy2, dow; |
|
841 |
|
842 INITIALIZE(value); |
|
843 leapyear = isleap(year); |
|
844 switch (rulep->r_type) { |
|
845 |
|
846 case JULIAN_DAY: |
|
847 /* |
|
848 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap |
|
849 ** years. |
|
850 ** In non-leap years, or if the day number is 59 or less, just |
|
851 ** add SECSPERDAY times the day number-1 to the time of |
|
852 ** January 1, midnight, to get the day. |
|
853 */ |
|
854 value = janfirst + (rulep->r_day - 1) * SECSPERDAY; |
|
855 if (leapyear && rulep->r_day >= 60) |
|
856 value += SECSPERDAY; |
|
857 break; |
|
858 |
|
859 case DAY_OF_YEAR: |
|
860 /* |
|
861 ** n - day of year. |
|
862 ** Just add SECSPERDAY times the day number to the time of |
|
863 ** January 1, midnight, to get the day. |
|
864 */ |
|
865 value = janfirst + rulep->r_day * SECSPERDAY; |
|
866 break; |
|
867 |
|
868 case MONTH_NTH_DAY_OF_WEEK: |
|
869 /* |
|
870 ** Mm.n.d - nth "dth day" of month m. |
|
871 */ |
|
872 value = janfirst; |
|
873 for (i = 0; i < rulep->r_mon - 1; ++i) |
|
874 value += mon_lengths[leapyear][i] * SECSPERDAY; |
|
875 |
|
876 /* |
|
877 ** Use Zeller's Congruence to get day-of-week of first day of |
|
878 ** month. |
|
879 */ |
|
880 m1 = (rulep->r_mon + 9) % 12 + 1; |
|
881 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year; |
|
882 yy1 = yy0 / 100; |
|
883 yy2 = yy0 % 100; |
|
884 dow = ((26 * m1 - 2) / 10 + |
|
885 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7; |
|
886 if (dow < 0) |
|
887 dow += DAYSPERWEEK; |
|
888 |
|
889 /* |
|
890 ** "dow" is the day-of-week of the first day of the month. Get |
|
891 ** the day-of-month (zero-origin) of the first "dow" day of the |
|
892 ** month. |
|
893 */ |
|
894 d = rulep->r_day - dow; |
|
895 if (d < 0) |
|
896 d += DAYSPERWEEK; |
|
897 for (i = 1; i < rulep->r_week; ++i) { |
|
898 if (d + DAYSPERWEEK >= |
|
899 mon_lengths[leapyear][rulep->r_mon - 1]) |
|
900 break; |
|
901 d += DAYSPERWEEK; |
|
902 } |
|
903 |
|
904 /* |
|
905 ** "d" is the day-of-month (zero-origin) of the day we want. |
|
906 */ |
|
907 value += d * SECSPERDAY; |
|
908 break; |
|
909 } |
|
910 |
|
911 /* |
|
912 ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in |
|
913 ** question. To get the Epoch-relative time of the specified local |
|
914 ** time on that day, add the transition time and the current offset |
|
915 ** from UTC. |
|
916 */ |
|
917 return value + rulep->r_time + offset; |
|
918 } |
|
919 |
|
920 /* |
|
921 ** Given a POSIX section 8-style TZ string, fill in the rule tables as |
|
922 ** appropriate. |
|
923 */ |
|
924 |
|
925 static int |
|
926 tzparse(name, sp, lastditch) |
|
927 const char * name; |
|
928 struct state * const sp; |
|
929 const int lastditch; |
|
930 { |
|
931 const char * stdname; |
|
932 const char * dstname; |
|
933 size_t stdlen; |
|
934 size_t dstlen; |
|
935 long stdoffset; |
|
936 long dstoffset; |
|
937 time_t * atp; |
|
938 unsigned char * typep; |
|
939 char * cp; |
|
940 int load_result; |
|
941 |
|
942 INITIALIZE(dstname); |
|
943 stdname = name; |
|
944 if (lastditch) { |
|
945 stdlen = strlen(name); /* length of standard zone name */ |
|
946 name += stdlen; |
|
947 if (stdlen >= sizeof sp->chars) |
|
948 stdlen = (sizeof sp->chars) - 1; |
|
949 #ifndef __SYMBIAN32__ |
|
950 stdoffset = 0; |
|
951 #else //__SYMBIAN32__ |
|
952 stdoffset = (-1)*GetStdOffset(); |
|
953 #endif //__SYMBIAN32__ |
|
954 } else { |
|
955 name = getzname(name); |
|
956 stdlen = name - stdname; |
|
957 if (stdlen < 3) |
|
958 return -1; |
|
959 if (*name == '\0') |
|
960 return -1; /* was "stdoffset = 0;" */ |
|
961 else { |
|
962 name = getoffset(name, &stdoffset); |
|
963 if (name == NULL) |
|
964 return -1; |
|
965 } |
|
966 } |
|
967 load_result = tzload(TZDEFRULES, sp); |
|
968 if (load_result != 0) |
|
969 sp->leapcnt = 0; /* so, we're off a little */ |
|
970 if (*name != '\0') { |
|
971 dstname = name; |
|
972 name = getzname(name); |
|
973 dstlen = name - dstname; /* length of DST zone name */ |
|
974 if (dstlen < 3) |
|
975 return -1; |
|
976 if (*name != '\0' && *name != ',' && *name != ';') { |
|
977 name = getoffset(name, &dstoffset); |
|
978 if (name == NULL) |
|
979 return -1; |
|
980 } else dstoffset = stdoffset - SECSPERHOUR; |
|
981 if (*name == '\0' && load_result != 0) |
|
982 name = TZDEFRULESTRING; |
|
983 if (*name == ',' || *name == ';') { |
|
984 struct rule start; |
|
985 struct rule end; |
|
986 int year; |
|
987 time_t janfirst; |
|
988 time_t starttime; |
|
989 time_t endtime; |
|
990 |
|
991 ++name; |
|
992 if ((name = getrule(name, &start)) == NULL) |
|
993 return -1; |
|
994 if (*name++ != ',') |
|
995 return -1; |
|
996 if ((name = getrule(name, &end)) == NULL) |
|
997 return -1; |
|
998 if (*name != '\0') |
|
999 return -1; |
|
1000 sp->typecnt = 2; /* standard time and DST */ |
|
1001 /* |
|
1002 ** Two transitions per year, from EPOCH_YEAR to 2037. |
|
1003 */ |
|
1004 sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1); |
|
1005 if (sp->timecnt > TZ_MAX_TIMES) |
|
1006 return -1; |
|
1007 sp->ttis[0].tt_gmtoff = -dstoffset; |
|
1008 sp->ttis[0].tt_isdst = 1; |
|
1009 sp->ttis[0].tt_abbrind = stdlen + 1; |
|
1010 sp->ttis[1].tt_gmtoff = -stdoffset; |
|
1011 sp->ttis[1].tt_isdst = 0; |
|
1012 sp->ttis[1].tt_abbrind = 0; |
|
1013 atp = sp->ats; |
|
1014 typep = sp->types; |
|
1015 janfirst = 0; |
|
1016 for (year = EPOCH_YEAR; year <= 2037; ++year) { |
|
1017 starttime = transtime(janfirst, year, &start, |
|
1018 stdoffset); |
|
1019 endtime = transtime(janfirst, year, &end, |
|
1020 dstoffset); |
|
1021 if (starttime > endtime) { |
|
1022 *atp++ = endtime; |
|
1023 *typep++ = 1; /* DST ends */ |
|
1024 *atp++ = starttime; |
|
1025 *typep++ = 0; /* DST begins */ |
|
1026 } else { |
|
1027 *atp++ = starttime; |
|
1028 *typep++ = 0; /* DST begins */ |
|
1029 *atp++ = endtime; |
|
1030 *typep++ = 1; /* DST ends */ |
|
1031 } |
|
1032 janfirst += year_lengths[isleap(year)] * |
|
1033 SECSPERDAY; |
|
1034 } |
|
1035 } else { |
|
1036 long theirstdoffset; |
|
1037 long theirdstoffset; |
|
1038 long theiroffset; |
|
1039 int isdst; |
|
1040 int i; |
|
1041 int j; |
|
1042 |
|
1043 if (*name != '\0') |
|
1044 return -1; |
|
1045 /* |
|
1046 ** Initial values of theirstdoffset and theirdstoffset. |
|
1047 */ |
|
1048 theirstdoffset = 0; |
|
1049 for (i = 0; i < sp->timecnt; ++i) { |
|
1050 j = sp->types[i]; |
|
1051 if (!sp->ttis[j].tt_isdst) { |
|
1052 theirstdoffset = |
|
1053 -sp->ttis[j].tt_gmtoff; |
|
1054 break; |
|
1055 } |
|
1056 } |
|
1057 theirdstoffset = 0; |
|
1058 for (i = 0; i < sp->timecnt; ++i) { |
|
1059 j = sp->types[i]; |
|
1060 if (sp->ttis[j].tt_isdst) { |
|
1061 theirdstoffset = |
|
1062 -sp->ttis[j].tt_gmtoff; |
|
1063 break; |
|
1064 } |
|
1065 } |
|
1066 /* |
|
1067 ** Initially we're assumed to be in standard time. |
|
1068 */ |
|
1069 isdst = FALSE; |
|
1070 theiroffset = theirstdoffset; |
|
1071 /* |
|
1072 ** Now juggle transition times and types |
|
1073 ** tracking offsets as you do. |
|
1074 */ |
|
1075 for (i = 0; i < sp->timecnt; ++i) { |
|
1076 j = sp->types[i]; |
|
1077 sp->types[i] = sp->ttis[j].tt_isdst; |
|
1078 if (sp->ttis[j].tt_ttisgmt) { |
|
1079 /* No adjustment to transition time */ |
|
1080 } else { |
|
1081 /* |
|
1082 ** If summer time is in effect, and the |
|
1083 ** transition time was not specified as |
|
1084 ** standard time, add the summer time |
|
1085 ** offset to the transition time; |
|
1086 ** otherwise, add the standard time |
|
1087 ** offset to the transition time. |
|
1088 */ |
|
1089 /* |
|
1090 ** Transitions from DST to DDST |
|
1091 ** will effectively disappear since |
|
1092 ** POSIX provides for only one DST |
|
1093 ** offset. |
|
1094 */ |
|
1095 if (isdst && !sp->ttis[j].tt_ttisstd) { |
|
1096 sp->ats[i] += dstoffset - |
|
1097 theirdstoffset; |
|
1098 } else { |
|
1099 sp->ats[i] += stdoffset - |
|
1100 theirstdoffset; |
|
1101 } |
|
1102 } |
|
1103 theiroffset = -sp->ttis[j].tt_gmtoff; |
|
1104 if (sp->ttis[j].tt_isdst) |
|
1105 theirdstoffset = theiroffset; |
|
1106 else theirstdoffset = theiroffset; |
|
1107 } |
|
1108 /* |
|
1109 ** Finally, fill in ttis. |
|
1110 ** ttisstd and ttisgmt need not be handled. |
|
1111 */ |
|
1112 sp->ttis[0].tt_gmtoff = -stdoffset; |
|
1113 sp->ttis[0].tt_isdst = FALSE; |
|
1114 sp->ttis[0].tt_abbrind = 0; |
|
1115 sp->ttis[1].tt_gmtoff = -dstoffset; |
|
1116 sp->ttis[1].tt_isdst = TRUE; |
|
1117 sp->ttis[1].tt_abbrind = stdlen + 1; |
|
1118 sp->typecnt = 2; |
|
1119 } |
|
1120 } else { |
|
1121 dstlen = 0; |
|
1122 sp->typecnt = 1; /* only standard time */ |
|
1123 sp->timecnt = 0; |
|
1124 sp->ttis[0].tt_gmtoff = -stdoffset; |
|
1125 #ifndef __SYMBIAN32__ |
|
1126 sp->ttis[0].tt_isdst = 0; |
|
1127 #else //__SYMBIAN32__ |
|
1128 sp->ttis[0].tt_isdst = GetIsDst(); |
|
1129 #endif //__SYMBIAN32__ |
|
1130 sp->ttis[0].tt_abbrind = 0; |
|
1131 } |
|
1132 sp->charcnt = stdlen + 1; |
|
1133 if (dstlen != 0) |
|
1134 sp->charcnt += dstlen + 1; |
|
1135 if ((size_t) sp->charcnt > sizeof sp->chars) |
|
1136 return -1; |
|
1137 cp = sp->chars; |
|
1138 (void) strncpy(cp, stdname, stdlen); |
|
1139 cp += stdlen; |
|
1140 *cp++ = '\0'; |
|
1141 if (dstlen != 0) { |
|
1142 (void) strncpy(cp, dstname, dstlen); |
|
1143 *(cp + dstlen) = '\0'; |
|
1144 } |
|
1145 return 0; |
|
1146 } |
|
1147 |
|
1148 static void |
|
1149 gmtload(sp) |
|
1150 struct state * const sp; |
|
1151 { |
|
1152 if (tzload(gmt, sp) != 0) |
|
1153 (void) tzparse(gmt, sp, TRUE); |
|
1154 } |
|
1155 |
|
1156 static void |
|
1157 tzsetwall_basic(void) |
|
1158 { |
|
1159 if (lcl_is_set < 0) |
|
1160 return; |
|
1161 lcl_is_set = -1; |
|
1162 |
|
1163 #ifdef ALL_STATE |
|
1164 if (lclptr == NULL) { |
|
1165 lclptr = (struct state *) malloc(sizeof *lclptr); |
|
1166 if (lclptr == NULL) { |
|
1167 settzname(); /* all we can do */ |
|
1168 return; |
|
1169 } |
|
1170 } |
|
1171 #endif /* defined ALL_STATE */ |
|
1172 if (tzload((char *) NULL, lclptr) != 0) |
|
1173 gmtload(lclptr); |
|
1174 settzname(); |
|
1175 } |
|
1176 |
|
1177 #ifndef __SYMBIAN32__ |
|
1178 void |
|
1179 tzsetwall(void) |
|
1180 { |
|
1181 _MUTEX_LOCK(&lcl_mutex); |
|
1182 tzsetwall_basic(); |
|
1183 _MUTEX_UNLOCK(&lcl_mutex); |
|
1184 } |
|
1185 #endif //__SYMBIAN32__ |
|
1186 |
|
1187 static void |
|
1188 tzset_basic(void) |
|
1189 { |
|
1190 const char * name; |
|
1191 |
|
1192 name = getenv("TZ"); |
|
1193 if (name == NULL) { |
|
1194 tzsetwall_basic(); |
|
1195 return; |
|
1196 } |
|
1197 |
|
1198 if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0) |
|
1199 return; |
|
1200 lcl_is_set = strlen(name) < sizeof lcl_TZname; |
|
1201 if (lcl_is_set) |
|
1202 (void) strcpy(lcl_TZname, name); |
|
1203 |
|
1204 #ifdef ALL_STATE |
|
1205 if (lclptr == NULL) { |
|
1206 lclptr = (struct state *) malloc(sizeof *lclptr); |
|
1207 if (lclptr == NULL) { |
|
1208 settzname(); /* all we can do */ |
|
1209 return; |
|
1210 } |
|
1211 } |
|
1212 #endif /* defined ALL_STATE */ |
|
1213 if (*name == '\0') { |
|
1214 /* |
|
1215 ** User wants it fast rather than right. |
|
1216 */ |
|
1217 lclptr->leapcnt = 0; /* so, we're off a little */ |
|
1218 lclptr->timecnt = 0; |
|
1219 lclptr->typecnt = 0; |
|
1220 lclptr->ttis[0].tt_isdst = 0; |
|
1221 lclptr->ttis[0].tt_gmtoff = 0; |
|
1222 lclptr->ttis[0].tt_abbrind = 0; |
|
1223 (void) strcpy(lclptr->chars, gmt); |
|
1224 } else if (tzload(name, lclptr) != 0) |
|
1225 if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0) |
|
1226 (void) gmtload(lclptr); |
|
1227 settzname(); |
|
1228 } |
|
1229 |
|
1230 EXPORT_C |
|
1231 void |
|
1232 tzset(void) |
|
1233 { |
|
1234 _MUTEX_LOCK(&lcl_mutex); |
|
1235 tzset_basic(); |
|
1236 _MUTEX_UNLOCK(&lcl_mutex); |
|
1237 } |
|
1238 |
|
1239 /* |
|
1240 ** The easy way to behave "as if no library function calls" localtime |
|
1241 ** is to not call it--so we drop its guts into "localsub", which can be |
|
1242 ** freely called. (And no, the PANS doesn't require the above behavior-- |
|
1243 ** but it *is* desirable.) |
|
1244 ** |
|
1245 ** The unused offset argument is for the benefit of mktime variants. |
|
1246 */ |
|
1247 |
|
1248 /*ARGSUSED*/ |
|
1249 static void |
|
1250 localsub(timep, offset, tmp) |
|
1251 const time_t * const timep; |
|
1252 #ifdef __SYMBIAN32__ |
|
1253 long offset; |
|
1254 #else//__SYMBIAN32__ |
|
1255 const long offset; |
|
1256 #endif//__SYMBIAN32__ |
|
1257 struct tm * const tmp; |
|
1258 { |
|
1259 struct state * sp; |
|
1260 const struct ttinfo * ttisp; |
|
1261 int i; |
|
1262 const time_t t = *timep; |
|
1263 |
|
1264 sp = lclptr; |
|
1265 #ifdef __SYMBIAN32__ |
|
1266 offset = offset; /*to fix warning 'variable/argument not used in function' */ |
|
1267 #endif //__SYMBIAN32__ |
|
1268 #ifdef ALL_STATE |
|
1269 if (sp == NULL) { |
|
1270 gmtsub(timep, offset, tmp); |
|
1271 return; |
|
1272 } |
|
1273 #endif /* defined ALL_STATE */ |
|
1274 if (sp->timecnt == 0 || t < sp->ats[0]) { |
|
1275 i = 0; |
|
1276 while (sp->ttis[i].tt_isdst) |
|
1277 if (++i >= sp->typecnt) { |
|
1278 i = 0; |
|
1279 break; |
|
1280 } |
|
1281 } else { |
|
1282 for (i = 1; i < sp->timecnt; ++i) |
|
1283 if (t < sp->ats[i]) |
|
1284 break; |
|
1285 i = sp->types[i - 1]; |
|
1286 } |
|
1287 ttisp = &sp->ttis[i]; |
|
1288 /* |
|
1289 ** To get (wrong) behavior that's compatible with System V Release 2.0 |
|
1290 ** you'd replace the statement below with |
|
1291 ** t += ttisp->tt_gmtoff; |
|
1292 ** timesub(&t, 0L, sp, tmp); |
|
1293 */ |
|
1294 timesub(&t, ttisp->tt_gmtoff, sp, tmp); |
|
1295 tmp->tm_isdst = ttisp->tt_isdst; |
|
1296 tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind]; |
|
1297 #ifdef TM_ZONE |
|
1298 tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind]; |
|
1299 #endif /* defined TM_ZONE */ |
|
1300 } |
|
1301 |
|
1302 EXPORT_C |
|
1303 struct tm * |
|
1304 localtime(timep) |
|
1305 const time_t * const timep; |
|
1306 { |
|
1307 #ifdef __SYMBIAN32__ |
|
1308 int err = 0; |
|
1309 #ifndef EMULATOR |
|
1310 static pthread_mutex_t localtime_mutex = PTHREAD_MUTEX_INITIALIZER; |
|
1311 static pthread_key_t localtime_key = (unsigned)-1; |
|
1312 #endif //EMULATOR |
|
1313 #else //__SYMBIAN32__ |
|
1314 static pthread_mutex_t localtime_mutex = PTHREAD_MUTEX_INITIALIZER; |
|
1315 static pthread_key_t localtime_key = -1; |
|
1316 #endif //__SYMBIAN32__ |
|
1317 struct tm *p_tm; |
|
1318 |
|
1319 if (__isthreaded != 0) { |
|
1320 _pthread_mutex_lock(&localtime_mutex); |
|
1321 if (localtime_key == (pthread_key_t)-1) { |
|
1322 if (_pthread_key_create(&localtime_key, free) < 0) { |
|
1323 _pthread_mutex_unlock(&localtime_mutex); |
|
1324 return(NULL); |
|
1325 } |
|
1326 } |
|
1327 _pthread_mutex_unlock(&localtime_mutex); |
|
1328 p_tm = _pthread_getspecific(localtime_key); |
|
1329 if (p_tm == NULL) { |
|
1330 if ((p_tm = (struct tm *)malloc(sizeof(struct tm))) |
|
1331 == NULL) |
|
1332 return(NULL); |
|
1333 _pthread_setspecific(localtime_key, p_tm); |
|
1334 } |
|
1335 _pthread_mutex_lock(&lcl_mutex); |
|
1336 tzset_basic(); |
|
1337 localsub(timep, 0L, p_tm); |
|
1338 #ifdef __SYMBIAN32__ |
|
1339 if(getenv("TZ") == NULL) |
|
1340 { |
|
1341 err = ConvertTime(EUtcToLocal, (TInt*)timep, p_tm); |
|
1342 } |
|
1343 #endif |
|
1344 _pthread_mutex_unlock(&lcl_mutex); |
|
1345 if(err) |
|
1346 { |
|
1347 return NULL; |
|
1348 } |
|
1349 |
|
1350 return(p_tm); |
|
1351 } else { |
|
1352 tzset_basic(); |
|
1353 #ifdef __SYMBIAN32__ |
|
1354 localsub(timep, 0L, &stm); |
|
1355 if(getenv("TZ") == NULL) |
|
1356 { |
|
1357 err = ConvertTime(EUtcToLocal,(TInt*)timep,&stm); |
|
1358 if(err) |
|
1359 { |
|
1360 return NULL; |
|
1361 } |
|
1362 } |
|
1363 return(&stm); |
|
1364 #else //__SYMBIAN32__ |
|
1365 localsub(timep, 0L, &tm); |
|
1366 return(&tm); |
|
1367 #endif //__SYMBIAN32__ |
|
1368 } |
|
1369 } |
|
1370 |
|
1371 /* |
|
1372 ** Re-entrant version of localtime. |
|
1373 */ |
|
1374 |
|
1375 EXPORT_C |
|
1376 struct tm * |
|
1377 localtime_r(timep, tm) |
|
1378 const time_t * const timep; |
|
1379 struct tm * tm; |
|
1380 { |
|
1381 #ifdef __SYMBIAN32__ |
|
1382 int err = 0; |
|
1383 #endif //__SYMBIAN32__ |
|
1384 _MUTEX_LOCK(&lcl_mutex); |
|
1385 tzset_basic(); |
|
1386 localsub(timep, 0L, tm); |
|
1387 #ifdef __SYMBIAN32__ |
|
1388 if(getenv("TZ") == NULL) |
|
1389 { |
|
1390 err = ConvertTime(EUtcToLocal,(TInt*)timep,tm); |
|
1391 if(err) |
|
1392 { |
|
1393 _MUTEX_UNLOCK(&lcl_mutex); |
|
1394 return NULL; |
|
1395 } |
|
1396 } |
|
1397 #endif //__SYMBIAN32__ |
|
1398 _MUTEX_UNLOCK(&lcl_mutex); |
|
1399 return tm; |
|
1400 } |
|
1401 |
|
1402 /* |
|
1403 ** gmtsub is to gmtime as localsub is to localtime. |
|
1404 */ |
|
1405 |
|
1406 static void |
|
1407 gmtsub(timep, offset, tmp) |
|
1408 const time_t * const timep; |
|
1409 const long offset; |
|
1410 struct tm * const tmp; |
|
1411 { |
|
1412 _MUTEX_LOCK(&gmt_mutex); |
|
1413 if (!gmt_is_set) { |
|
1414 gmt_is_set = TRUE; |
|
1415 #ifdef ALL_STATE |
|
1416 gmtptr = (struct state *) malloc(sizeof *gmtptr); |
|
1417 if (gmtptr != NULL) |
|
1418 #endif /* defined ALL_STATE */ |
|
1419 #ifndef __SYMBIAN32__ |
|
1420 gmtload(gmtptr); |
|
1421 #endif //__SYMBIAN32__ |
|
1422 } |
|
1423 _MUTEX_UNLOCK(&gmt_mutex); |
|
1424 timesub(timep, offset, gmtptr, tmp); |
|
1425 #ifdef TM_ZONE |
|
1426 /* |
|
1427 ** Could get fancy here and deliver something such as |
|
1428 ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero, |
|
1429 ** but this is no time for a treasure hunt. |
|
1430 */ |
|
1431 if (offset != 0) |
|
1432 tmp->TM_ZONE = wildabbr; |
|
1433 else { |
|
1434 #ifdef ALL_STATE |
|
1435 if (gmtptr == NULL) |
|
1436 tmp->TM_ZONE = gmt; |
|
1437 else tmp->TM_ZONE = gmtptr->chars; |
|
1438 #endif /* defined ALL_STATE */ |
|
1439 #ifndef ALL_STATE |
|
1440 #ifndef __SYMBIAN32__ |
|
1441 tmp->TM_ZONE = gmtptr->chars; |
|
1442 #else //__SYMBIAN32__ |
|
1443 tmp->TM_ZONE ="UTC"; |
|
1444 #endif //__SYMBIAN32__ |
|
1445 #endif /* State Farm */ |
|
1446 } |
|
1447 #endif /* defined TM_ZONE */ |
|
1448 } |
|
1449 |
|
1450 EXPORT_C |
|
1451 struct tm * |
|
1452 gmtime(timep) |
|
1453 const time_t * const timep; |
|
1454 { |
|
1455 #ifdef __SYMBIAN32__ |
|
1456 #ifndef EMULATOR |
|
1457 static pthread_mutex_t gmtime_mutex = PTHREAD_MUTEX_INITIALIZER; |
|
1458 static pthread_key_t gmtime_key = (unsigned)-1; |
|
1459 #endif //EMULATOR |
|
1460 #else //__SYMBIAN32__ |
|
1461 static pthread_mutex_t gmtime_mutex = PTHREAD_MUTEX_INITIALIZER; |
|
1462 static pthread_key_t gmtime_key = -1; |
|
1463 #endif //__SYMBIAN32__ |
|
1464 struct tm *p_tm; |
|
1465 |
|
1466 if (__isthreaded != 0) { |
|
1467 _pthread_mutex_lock(&gmtime_mutex); |
|
1468 if (gmtime_key == (pthread_key_t)-1) { |
|
1469 if (_pthread_key_create(&gmtime_key, free) < 0) { |
|
1470 _pthread_mutex_unlock(&gmtime_mutex); |
|
1471 return(NULL); |
|
1472 } |
|
1473 } |
|
1474 _pthread_mutex_unlock(&gmtime_mutex); |
|
1475 /* |
|
1476 * Changed to follow POSIX.1 threads standard, which |
|
1477 * is what BSD currently has. |
|
1478 */ |
|
1479 if ((p_tm = _pthread_getspecific(gmtime_key)) == NULL) { |
|
1480 if ((p_tm = (struct tm *)malloc(sizeof(struct tm))) |
|
1481 == NULL) { |
|
1482 return(NULL); |
|
1483 } |
|
1484 _pthread_setspecific(gmtime_key, p_tm); |
|
1485 } |
|
1486 gmtsub(timep, 0L, p_tm); |
|
1487 return(p_tm); |
|
1488 } |
|
1489 else { |
|
1490 #ifdef __SYMBIAN32__ |
|
1491 gmtsub(timep, 0L, &stm); |
|
1492 return(&stm); |
|
1493 #else //__SYMBIAN32__ |
|
1494 gmtsub(timep, 0L, &tm); |
|
1495 return(&tm); |
|
1496 #endif //__SYMBIAN32__ |
|
1497 } |
|
1498 } |
|
1499 |
|
1500 /* |
|
1501 * Re-entrant version of gmtime. |
|
1502 */ |
|
1503 |
|
1504 EXPORT_C |
|
1505 struct tm * |
|
1506 gmtime_r(timep, tm) |
|
1507 const time_t * const timep; |
|
1508 struct tm * tm; |
|
1509 { |
|
1510 gmtsub(timep, 0L, tm); |
|
1511 return tm; |
|
1512 } |
|
1513 |
|
1514 #ifdef STD_INSPIRED |
|
1515 #ifdef __SYMBIAN_COMPILE_UNUSED__ |
|
1516 struct tm * |
|
1517 offtime(timep, offset) |
|
1518 const time_t * const timep; |
|
1519 const long offset; |
|
1520 { |
|
1521 #ifdef __SYMBIAN32__ |
|
1522 gmtsub(timep, offset, &stm); |
|
1523 return &stm; |
|
1524 #else //__SYMBIAN32__ |
|
1525 gmtsub(timep, offset, &tm); |
|
1526 return &tm; |
|
1527 #endif //__SYMBIAN32__ |
|
1528 } |
|
1529 #endif //__SYMBIAN_COMPILE_UNUSED__ |
|
1530 #endif /* defined STD_INSPIRED */ |
|
1531 |
|
1532 static void |
|
1533 timesub(timep, offset, sp, tmp) |
|
1534 const time_t * const timep; |
|
1535 const long offset; |
|
1536 const struct state * const sp; |
|
1537 struct tm * const tmp; |
|
1538 { |
|
1539 const struct lsinfo * lp; |
|
1540 long days; |
|
1541 long rem; |
|
1542 long y; |
|
1543 int yleap; |
|
1544 const int * ip; |
|
1545 long corr; |
|
1546 int hit; |
|
1547 int i; |
|
1548 |
|
1549 corr = 0; |
|
1550 hit = 0; |
|
1551 #ifdef ALL_STATE |
|
1552 i = (sp == NULL) ? 0 : sp->leapcnt; |
|
1553 #endif /* defined ALL_STATE */ |
|
1554 #ifndef ALL_STATE |
|
1555 i = sp->leapcnt; |
|
1556 #endif /* State Farm */ |
|
1557 while (--i >= 0) { |
|
1558 lp = &sp->lsis[i]; |
|
1559 if (*timep >= lp->ls_trans) { |
|
1560 if (*timep == lp->ls_trans) { |
|
1561 hit = ((i == 0 && lp->ls_corr > 0) || |
|
1562 lp->ls_corr > sp->lsis[i - 1].ls_corr); |
|
1563 if (hit) |
|
1564 while (i > 0 && |
|
1565 sp->lsis[i].ls_trans == |
|
1566 sp->lsis[i - 1].ls_trans + 1 && |
|
1567 sp->lsis[i].ls_corr == |
|
1568 sp->lsis[i - 1].ls_corr + 1) { |
|
1569 ++hit; |
|
1570 --i; |
|
1571 } |
|
1572 } |
|
1573 corr = lp->ls_corr; |
|
1574 break; |
|
1575 } |
|
1576 } |
|
1577 days = *timep / SECSPERDAY; |
|
1578 rem = *timep % SECSPERDAY; |
|
1579 #ifdef mc68k |
|
1580 if (*timep == 0x80000000) { |
|
1581 /* |
|
1582 ** A 3B1 muffs the division on the most negative number. |
|
1583 */ |
|
1584 days = -24855; |
|
1585 rem = -11648; |
|
1586 } |
|
1587 #endif /* defined mc68k */ |
|
1588 rem += (offset - corr); |
|
1589 while (rem < 0) { |
|
1590 rem += SECSPERDAY; |
|
1591 --days; |
|
1592 } |
|
1593 while (rem >= SECSPERDAY) { |
|
1594 rem -= SECSPERDAY; |
|
1595 ++days; |
|
1596 } |
|
1597 tmp->tm_hour = (int) (rem / SECSPERHOUR); |
|
1598 rem = rem % SECSPERHOUR; |
|
1599 tmp->tm_min = (int) (rem / SECSPERMIN); |
|
1600 /* |
|
1601 ** A positive leap second requires a special |
|
1602 ** representation. This uses "... ??:59:60" et seq. |
|
1603 */ |
|
1604 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit; |
|
1605 tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK); |
|
1606 if (tmp->tm_wday < 0) |
|
1607 tmp->tm_wday += DAYSPERWEEK; |
|
1608 y = EPOCH_YEAR; |
|
1609 #define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400) |
|
1610 while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) { |
|
1611 long newy; |
|
1612 |
|
1613 newy = y + days / DAYSPERNYEAR; |
|
1614 if (days < 0) |
|
1615 --newy; |
|
1616 days -= (newy - y) * DAYSPERNYEAR + |
|
1617 LEAPS_THRU_END_OF(newy - 1) - |
|
1618 LEAPS_THRU_END_OF(y - 1); |
|
1619 y = newy; |
|
1620 } |
|
1621 tmp->tm_year = y - TM_YEAR_BASE; |
|
1622 tmp->tm_yday = (int) days; |
|
1623 ip = mon_lengths[yleap]; |
|
1624 for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon)) |
|
1625 days = days - (long) ip[tmp->tm_mon]; |
|
1626 tmp->tm_mday = (int) (days + 1); |
|
1627 tmp->tm_isdst = 0; |
|
1628 #ifdef TM_GMTOFF |
|
1629 tmp->TM_GMTOFF = offset; |
|
1630 #endif /* defined TM_GMTOFF */ |
|
1631 } |
|
1632 |
|
1633 EXPORT_C |
|
1634 char * |
|
1635 ctime(timep) |
|
1636 const time_t * const timep; |
|
1637 { |
|
1638 /* |
|
1639 ** Section 4.12.3.2 of X3.159-1989 requires that |
|
1640 ** The ctime function converts the calendar time pointed to by timer |
|
1641 ** to local time in the form of a string. It is equivalent to |
|
1642 ** asctime(localtime(timer)) |
|
1643 */ |
|
1644 return asctime(localtime(timep)); |
|
1645 } |
|
1646 |
|
1647 EXPORT_C |
|
1648 wchar_t * |
|
1649 wctime(timep) |
|
1650 const time_t * const timep; |
|
1651 { |
|
1652 /* |
|
1653 ** Section 4.12.3.2 of X3.159-1989 requires that |
|
1654 ** The wctime function converts the calendar time pointed to by timer |
|
1655 ** to local time in the form of a wide char string. It is equivalent to |
|
1656 ** wasctime(localtime(timer)) |
|
1657 */ |
|
1658 if (timep == NULL) |
|
1659 return NULL; |
|
1660 else |
|
1661 return (wchar_t *)wasctime(localtime(timep)); |
|
1662 } |
|
1663 |
|
1664 EXPORT_C |
|
1665 char * |
|
1666 ctime_r(timep, buf) |
|
1667 const time_t * const timep; |
|
1668 char * buf; |
|
1669 { |
|
1670 struct tm tm; |
|
1671 |
|
1672 return asctime_r(localtime_r(timep, &tm), buf); |
|
1673 } |
|
1674 |
|
1675 /* |
|
1676 ** Adapted from code provided by Robert Elz, who writes: |
|
1677 ** The "best" way to do mktime I think is based on an idea of Bob |
|
1678 ** Kridle's (so its said...) from a long time ago. |
|
1679 ** [kridle@xinet.com as of 1996-01-16.] |
|
1680 ** It does a binary search of the time_t space. Since time_t's are |
|
1681 ** just 32 bits, its a max of 32 iterations (even at 64 bits it |
|
1682 ** would still be very reasonable). |
|
1683 */ |
|
1684 |
|
1685 #ifndef WRONG |
|
1686 #define WRONG (-1) |
|
1687 #endif /* !defined WRONG */ |
|
1688 |
|
1689 /* |
|
1690 ** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com). |
|
1691 */ |
|
1692 |
|
1693 static int |
|
1694 increment_overflow(number, delta) |
|
1695 int * number; |
|
1696 int delta; |
|
1697 { |
|
1698 int number0; |
|
1699 |
|
1700 number0 = *number; |
|
1701 *number += delta; |
|
1702 return (*number < number0) != (delta < 0); |
|
1703 } |
|
1704 |
|
1705 static int |
|
1706 normalize_overflow(tensptr, unitsptr, base) |
|
1707 int * const tensptr; |
|
1708 int * const unitsptr; |
|
1709 const int base; |
|
1710 { |
|
1711 int tensdelta; |
|
1712 |
|
1713 tensdelta = (*unitsptr >= 0) ? |
|
1714 (*unitsptr / base) : |
|
1715 (-1 - (-1 - *unitsptr) / base); |
|
1716 *unitsptr -= tensdelta * base; |
|
1717 return increment_overflow(tensptr, tensdelta); |
|
1718 } |
|
1719 |
|
1720 static int |
|
1721 tmcomp(atmp, btmp) |
|
1722 const struct tm * const atmp; |
|
1723 const struct tm * const btmp; |
|
1724 { |
|
1725 int result; |
|
1726 |
|
1727 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && |
|
1728 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && |
|
1729 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && |
|
1730 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && |
|
1731 (result = (atmp->tm_min - btmp->tm_min)) == 0) |
|
1732 result = atmp->tm_sec - btmp->tm_sec; |
|
1733 return result; |
|
1734 } |
|
1735 |
|
1736 static time_t |
|
1737 time2sub(tmp, funcp, offset, okayp, do_norm_secs) |
|
1738 struct tm * const tmp; |
|
1739 void (* const funcp)(const time_t*, long, struct tm*); |
|
1740 const long offset; |
|
1741 int * const okayp; |
|
1742 const int do_norm_secs; |
|
1743 { |
|
1744 const struct state * sp; |
|
1745 int dir; |
|
1746 int bits; |
|
1747 int i, j ; |
|
1748 int saved_seconds; |
|
1749 time_t newt; |
|
1750 time_t t; |
|
1751 struct tm yourtm, mytm; |
|
1752 |
|
1753 *okayp = FALSE; |
|
1754 yourtm = *tmp; |
|
1755 if (do_norm_secs) { |
|
1756 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec, |
|
1757 SECSPERMIN)) |
|
1758 return WRONG; |
|
1759 } |
|
1760 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR)) |
|
1761 return WRONG; |
|
1762 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY)) |
|
1763 return WRONG; |
|
1764 if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR)) |
|
1765 return WRONG; |
|
1766 /* |
|
1767 ** Turn yourtm.tm_year into an actual year number for now. |
|
1768 ** It is converted back to an offset from TM_YEAR_BASE later. |
|
1769 */ |
|
1770 if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE)) |
|
1771 return WRONG; |
|
1772 while (yourtm.tm_mday <= 0) { |
|
1773 if (increment_overflow(&yourtm.tm_year, -1)) |
|
1774 return WRONG; |
|
1775 i = yourtm.tm_year + (1 < yourtm.tm_mon); |
|
1776 yourtm.tm_mday += year_lengths[isleap(i)]; |
|
1777 } |
|
1778 while (yourtm.tm_mday > DAYSPERLYEAR) { |
|
1779 i = yourtm.tm_year + (1 < yourtm.tm_mon); |
|
1780 yourtm.tm_mday -= year_lengths[isleap(i)]; |
|
1781 if (increment_overflow(&yourtm.tm_year, 1)) |
|
1782 return WRONG; |
|
1783 } |
|
1784 for ( ; ; ) { |
|
1785 i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon]; |
|
1786 if (yourtm.tm_mday <= i) |
|
1787 break; |
|
1788 yourtm.tm_mday -= i; |
|
1789 if (++yourtm.tm_mon >= MONSPERYEAR) { |
|
1790 yourtm.tm_mon = 0; |
|
1791 if (increment_overflow(&yourtm.tm_year, 1)) |
|
1792 return WRONG; |
|
1793 } |
|
1794 } |
|
1795 if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE)) |
|
1796 return WRONG; |
|
1797 /* Don't go below 1900 for POLA */ |
|
1798 if (yourtm.tm_year < 0) |
|
1799 return WRONG; |
|
1800 if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN) |
|
1801 saved_seconds = 0; |
|
1802 else if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) { |
|
1803 /* |
|
1804 ** We can't set tm_sec to 0, because that might push the |
|
1805 ** time below the minimum representable time. |
|
1806 ** Set tm_sec to 59 instead. |
|
1807 ** This assumes that the minimum representable time is |
|
1808 ** not in the same minute that a leap second was deleted from, |
|
1809 ** which is a safer assumption than using 58 would be. |
|
1810 */ |
|
1811 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN)) |
|
1812 return WRONG; |
|
1813 saved_seconds = yourtm.tm_sec; |
|
1814 yourtm.tm_sec = SECSPERMIN - 1; |
|
1815 } else { |
|
1816 saved_seconds = yourtm.tm_sec; |
|
1817 yourtm.tm_sec = 0; |
|
1818 } |
|
1819 /* |
|
1820 ** Divide the search space in half |
|
1821 ** (this works whether time_t is signed or unsigned). |
|
1822 */ |
|
1823 bits = TYPE_BIT(time_t) - 1; |
|
1824 /* |
|
1825 ** If we have more than this, we will overflow tm_year for tmcomp(). |
|
1826 ** We should really return an error if we cannot represent it. |
|
1827 */ |
|
1828 if (bits > 56) |
|
1829 bits = 56; |
|
1830 /* |
|
1831 ** If time_t is signed, then 0 is just above the median, |
|
1832 ** assuming two's complement arithmetic. |
|
1833 ** If time_t is unsigned, then (1 << bits) is just above the median. |
|
1834 */ |
|
1835 t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits); |
|
1836 for ( ; ; ) { |
|
1837 (*funcp)(&t, offset, &mytm); |
|
1838 dir = tmcomp(&mytm, &yourtm); |
|
1839 if (dir != 0) { |
|
1840 if (bits-- < 0) |
|
1841 return WRONG; |
|
1842 if (bits < 0) |
|
1843 --t; /* may be needed if new t is minimal */ |
|
1844 else if (dir > 0) |
|
1845 t -= ((time_t) 1) << bits; |
|
1846 else t += ((time_t) 1) << bits; |
|
1847 continue; |
|
1848 } |
|
1849 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) |
|
1850 break; |
|
1851 /* |
|
1852 ** Right time, wrong type. |
|
1853 ** Hunt for right time, right type. |
|
1854 ** It's okay to guess wrong since the guess |
|
1855 ** gets checked. |
|
1856 */ |
|
1857 sp = (funcp == localsub) ? lclptr : gmtptr; |
|
1858 #ifdef ALL_STATE |
|
1859 if (sp == NULL) |
|
1860 return WRONG; |
|
1861 #endif /* defined ALL_STATE */ |
|
1862 for (i = sp->typecnt - 1; i >= 0; --i) { |
|
1863 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst) |
|
1864 continue; |
|
1865 for (j = sp->typecnt - 1; j >= 0; --j) { |
|
1866 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst) |
|
1867 continue; |
|
1868 newt = t + sp->ttis[j].tt_gmtoff - |
|
1869 sp->ttis[i].tt_gmtoff; |
|
1870 (*funcp)(&newt, offset, &mytm); |
|
1871 if (tmcomp(&mytm, &yourtm) != 0) |
|
1872 continue; |
|
1873 if (mytm.tm_isdst != yourtm.tm_isdst) |
|
1874 continue; |
|
1875 /* |
|
1876 ** We have a match. |
|
1877 */ |
|
1878 t = newt; |
|
1879 goto label; |
|
1880 } |
|
1881 } |
|
1882 return WRONG; |
|
1883 } |
|
1884 label: |
|
1885 newt = t + saved_seconds; |
|
1886 if ((newt < t) != (saved_seconds < 0)) |
|
1887 return WRONG; |
|
1888 t = newt; |
|
1889 (*funcp)(&t, offset, tmp); |
|
1890 *okayp = TRUE; |
|
1891 return t; |
|
1892 } |
|
1893 |
|
1894 static time_t |
|
1895 time2(tmp, funcp, offset, okayp) |
|
1896 struct tm * const tmp; |
|
1897 void (* const funcp)(const time_t*, long, struct tm*); |
|
1898 const long offset; |
|
1899 int * const okayp; |
|
1900 { |
|
1901 time_t t; |
|
1902 |
|
1903 /* |
|
1904 ** First try without normalization of seconds |
|
1905 ** (in case tm_sec contains a value associated with a leap second). |
|
1906 ** If that fails, try with normalization of seconds. |
|
1907 */ |
|
1908 t = time2sub(tmp, funcp, offset, okayp, FALSE); |
|
1909 return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE); |
|
1910 } |
|
1911 |
|
1912 static time_t |
|
1913 time1(tmp, funcp, offset) |
|
1914 struct tm * const tmp; |
|
1915 void (* const funcp)(const time_t *, long, struct tm *); |
|
1916 const long offset; |
|
1917 { |
|
1918 time_t t; |
|
1919 const struct state * sp; |
|
1920 int samei, otheri; |
|
1921 int sameind, otherind; |
|
1922 int i; |
|
1923 int nseen; |
|
1924 int seen[TZ_MAX_TYPES]; |
|
1925 int types[TZ_MAX_TYPES]; |
|
1926 int okay; |
|
1927 |
|
1928 /* #ifdef __SYMBIAN32__ |
|
1929 if (tmp->tm_isdst == 1) |
|
1930 tmp->tm_isdst = 0; |
|
1931 #endif //__SYMBIAN32__ */ |
|
1932 |
|
1933 if (tmp->tm_isdst > 1) |
|
1934 tmp->tm_isdst = 1; |
|
1935 t = time2(tmp, funcp, offset, &okay); |
|
1936 #ifdef PCTS |
|
1937 /* |
|
1938 ** PCTS code courtesy Grant Sullivan (grant@osf.org). |
|
1939 */ |
|
1940 if (okay) |
|
1941 return t; |
|
1942 if (tmp->tm_isdst < 0) |
|
1943 tmp->tm_isdst = 0; /* reset to std and try again */ |
|
1944 #endif /* defined PCTS */ |
|
1945 #ifndef PCTS |
|
1946 if (okay || tmp->tm_isdst < 0) |
|
1947 return t; |
|
1948 #endif /* !defined PCTS */ |
|
1949 /* |
|
1950 ** We're supposed to assume that somebody took a time of one type |
|
1951 ** and did some math on it that yielded a "struct tm" that's bad. |
|
1952 ** We try to divine the type they started from and adjust to the |
|
1953 ** type they need. |
|
1954 */ |
|
1955 sp = (funcp == localsub) ? lclptr : gmtptr; |
|
1956 #ifdef ALL_STATE |
|
1957 if (sp == NULL) |
|
1958 return WRONG; |
|
1959 #endif /* defined ALL_STATE */ |
|
1960 for (i = 0; i < sp->typecnt; ++i) |
|
1961 seen[i] = FALSE; |
|
1962 nseen = 0; |
|
1963 for (i = sp->timecnt - 1; i >= 0; --i) |
|
1964 if (!seen[sp->types[i]]) { |
|
1965 seen[sp->types[i]] = TRUE; |
|
1966 types[nseen++] = sp->types[i]; |
|
1967 } |
|
1968 for (sameind = 0; sameind < nseen; ++sameind) { |
|
1969 samei = types[sameind]; |
|
1970 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst) |
|
1971 continue; |
|
1972 for (otherind = 0; otherind < nseen; ++otherind) { |
|
1973 otheri = types[otherind]; |
|
1974 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst) |
|
1975 continue; |
|
1976 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff - |
|
1977 sp->ttis[samei].tt_gmtoff; |
|
1978 tmp->tm_isdst = !tmp->tm_isdst; |
|
1979 t = time2(tmp, funcp, offset, &okay); |
|
1980 if (okay) |
|
1981 return t; |
|
1982 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff - |
|
1983 sp->ttis[samei].tt_gmtoff; |
|
1984 tmp->tm_isdst = !tmp->tm_isdst; |
|
1985 } |
|
1986 } |
|
1987 return WRONG; |
|
1988 } |
|
1989 |
|
1990 EXPORT_C |
|
1991 time_t |
|
1992 mktime(tmp) |
|
1993 struct tm * const tmp; |
|
1994 { |
|
1995 time_t mktime_return_value; |
|
1996 struct tm local_tmp; |
|
1997 #ifdef __SYMBIAN32__ |
|
1998 int err = 0; |
|
1999 if(tmp==NULL) |
|
2000 return -1; |
|
2001 #endif |
|
2002 local_tmp = (*tmp); |
|
2003 _MUTEX_LOCK(&lcl_mutex); |
|
2004 tzset_basic(); |
|
2005 mktime_return_value = time1(tmp, localsub, 0L); |
|
2006 #ifdef __SYMBIAN32__ |
|
2007 if(getenv("TZ") == NULL) |
|
2008 { |
|
2009 tmp->tm_isdst = local_tmp.tm_isdst; |
|
2010 tmp->tm_gmtoff = local_tmp.tm_gmtoff; |
|
2011 tmp->tm_zone = local_tmp.tm_zone; |
|
2012 |
|
2013 // if(mktime_return_value != WRONG) //temporay fix. Will be taken up during performance fix |
|
2014 // { |
|
2015 err = ConvertTime(ELocalToUtc,&mktime_return_value,tmp); |
|
2016 if(err) |
|
2017 { |
|
2018 _MUTEX_UNLOCK(&lcl_mutex); |
|
2019 return(time_t)-1; |
|
2020 } |
|
2021 // } |
|
2022 } |
|
2023 #endif |
|
2024 _MUTEX_UNLOCK(&lcl_mutex); |
|
2025 return(mktime_return_value); |
|
2026 } |
|
2027 |
|
2028 #ifdef STD_INSPIRED |
|
2029 |
|
2030 #ifdef __SYMBIAN_COMPILE_UNUSED__ |
|
2031 time_t |
|
2032 timelocal(tmp) |
|
2033 struct tm * const tmp; |
|
2034 { |
|
2035 tmp->tm_isdst = -1; /* in case it wasn't initialized */ |
|
2036 return mktime(tmp); |
|
2037 } |
|
2038 #endif //__SYMBIAN_COMPILE_UNUSED__ |
|
2039 EXPORT_C |
|
2040 time_t |
|
2041 timegm(tmp) |
|
2042 struct tm * const tmp; |
|
2043 { |
|
2044 tmp->tm_isdst = 0; |
|
2045 return time1(tmp, gmtsub, 0L); |
|
2046 } |
|
2047 |
|
2048 #ifdef __SYMBIAN_COMPILE_UNUSED__ |
|
2049 time_t |
|
2050 timeoff(tmp, offset) |
|
2051 struct tm * const tmp; |
|
2052 const long offset; |
|
2053 { |
|
2054 tmp->tm_isdst = 0; |
|
2055 return time1(tmp, gmtsub, offset); |
|
2056 } |
|
2057 #endif //__SYMBIAN_COMPILE_UNUSED__ |
|
2058 #endif /* defined STD_INSPIRED */ |
|
2059 |
|
2060 #ifdef CMUCS |
|
2061 |
|
2062 /* |
|
2063 ** The following is supplied for compatibility with |
|
2064 ** previous versions of the CMUCS runtime library. |
|
2065 */ |
|
2066 |
|
2067 long |
|
2068 gtime(tmp) |
|
2069 struct tm * const tmp; |
|
2070 { |
|
2071 const time_t t = mktime(tmp); |
|
2072 |
|
2073 if (t == WRONG) |
|
2074 return -1; |
|
2075 return t; |
|
2076 } |
|
2077 |
|
2078 #endif /* defined CMUCS */ |
|
2079 |
|
2080 /* |
|
2081 ** XXX--is the below the right way to conditionalize?? |
|
2082 */ |
|
2083 |
|
2084 #ifdef STD_INSPIRED |
|
2085 #ifdef __SYMBIAN_COMPILE_UNUSED__ |
|
2086 /* |
|
2087 ** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599 |
|
2088 ** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which |
|
2089 ** is not the case if we are accounting for leap seconds. |
|
2090 ** So, we provide the following conversion routines for use |
|
2091 ** when exchanging timestamps with POSIX conforming systems. |
|
2092 */ |
|
2093 |
|
2094 static long |
|
2095 leapcorr(timep) |
|
2096 time_t * timep; |
|
2097 { |
|
2098 struct state * sp; |
|
2099 struct lsinfo * lp; |
|
2100 int i; |
|
2101 |
|
2102 sp = lclptr; |
|
2103 i = sp->leapcnt; |
|
2104 while (--i >= 0) { |
|
2105 lp = &sp->lsis[i]; |
|
2106 if (*timep >= lp->ls_trans) |
|
2107 return lp->ls_corr; |
|
2108 } |
|
2109 return 0; |
|
2110 } |
|
2111 |
|
2112 time_t |
|
2113 time2posix(t) |
|
2114 time_t t; |
|
2115 { |
|
2116 tzset(); |
|
2117 return t - leapcorr(&t); |
|
2118 } |
|
2119 |
|
2120 time_t |
|
2121 posix2time(t) |
|
2122 time_t t; |
|
2123 { |
|
2124 time_t x; |
|
2125 time_t y; |
|
2126 |
|
2127 tzset(); |
|
2128 /* |
|
2129 ** For a positive leap second hit, the result |
|
2130 ** is not unique. For a negative leap second |
|
2131 ** hit, the corresponding time doesn't exist, |
|
2132 ** so we return an adjacent second. |
|
2133 */ |
|
2134 x = t + leapcorr(&t); |
|
2135 y = x - leapcorr(&x); |
|
2136 if (y < t) { |
|
2137 do { |
|
2138 x++; |
|
2139 y = x - leapcorr(&x); |
|
2140 } while (y < t); |
|
2141 if (t != y) |
|
2142 return x - 1; |
|
2143 } else if (y > t) { |
|
2144 do { |
|
2145 --x; |
|
2146 y = x - leapcorr(&x); |
|
2147 } while (y > t); |
|
2148 if (t != y) |
|
2149 return x + 1; |
|
2150 } |
|
2151 return x; |
|
2152 } |
|
2153 #endif //__SYMBIAN_COMPILE_UNUSED__ |
|
2154 #endif /* defined STD_INSPIRED */ |