genericopenlibs/openenvcore/libc/src/stdtime/localtime.c
changeset 0 e4d67989cc36
child 18 47c74d1534e1
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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 */