diff -r 000000000000 -r bde4ae8d615e os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/unix/tclUnixTime.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/unix/tclUnixTime.c Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,493 @@ +/* + * tclUnixTime.c -- + * + * Contains Unix specific versions of Tcl functions that + * obtain time values from the operating system. + * + * Copyright (c) 1995 Sun Microsystems, Inc. + * Portions Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiaries. All rights reserved. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tclUnixTime.c,v 1.15.2.6 2007/04/21 19:52:15 kennykb Exp $ + */ + +#include "tclInt.h" +#include "tclPort.h" +#include +#define TM_YEAR_BASE 1900 +#define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0)) + +/* + * TclpGetDate is coded to return a pointer to a 'struct tm'. For + * thread safety, this structure must be in thread-specific data. + * The 'tmKey' variable is the key to this buffer. + */ + +static Tcl_ThreadDataKey tmKey; +typedef struct ThreadSpecificData { + struct tm gmtime_buf; + struct tm localtime_buf; +} ThreadSpecificData; + +/* + * If we fall back on the thread-unsafe versions of gmtime and localtime, + * use this mutex to try to protect them. + */ + +TCL_DECLARE_MUTEX(tmMutex) + +static char* lastTZ = NULL; /* Holds the last setting of the + * TZ environment variable, or an + * empty string if the variable was + * not set. */ + +/* Static functions declared in this file */ + +static void SetTZIfNecessary _ANSI_ARGS_((void)); +static void CleanupMemory _ANSI_ARGS_((ClientData)); + +/* + *----------------------------------------------------------------------------- + * + * TclpGetSeconds -- + * + * This procedure returns the number of seconds from the epoch. On + * most Unix systems the epoch is Midnight Jan 1, 1970 GMT. + * + * Results: + * Number of seconds from the epoch. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +unsigned long +TclpGetSeconds() +{ + return time((time_t *) NULL); +} + +/* + *----------------------------------------------------------------------------- + * + * TclpGetClicks -- + * + * This procedure returns a value that represents the highest resolution + * clock available on the system. There are no garantees on what the + * resolution will be. In Tcl we will call this value a "click". The + * start time is also system dependant. + * + * Results: + * Number of clicks from some start time. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +unsigned long +TclpGetClicks() +{ + unsigned long now; +#ifdef NO_GETTOD + struct tms dummy; +#else + struct timeval date; + struct timezone tz; +#endif + +#ifdef NO_GETTOD + now = (unsigned long) times(&dummy); +#else + gettimeofday(&date, &tz); + now = date.tv_sec*1000000 + date.tv_usec; +#endif + + return now; +} + +/* + *---------------------------------------------------------------------- + * + * TclpGetTimeZone -- + * + * Determines the current timezone. The method varies wildly + * between different platform implementations, so its hidden in + * this function. + * + * Results: + * The return value is the local time zone, measured in + * minutes away from GMT (-ve for east, +ve for west). + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TclpGetTimeZone (currentTime) + Tcl_WideInt currentTime; +{ + /* + * We prefer first to use the time zone in "struct tm" if the + * structure contains such a member. Following that, we try + * to locate the external 'timezone' variable and use its value. + * If both of those methods fail, we attempt to convert a known + * time to local time and use the difference from UTC as the local + * time zone. In all cases, we need to undo any Daylight Saving Time + * adjustment. + */ + +#if defined(HAVE_TM_TZADJ) +# define TCL_GOT_TIMEZONE + + /* Struct tm contains tm_tzadj - that value may be used. */ + + time_t curTime = (time_t) currentTime; + struct tm *timeDataPtr = TclpLocaltime((TclpTime_t) &curTime); + int timeZone; + + timeZone = timeDataPtr->tm_tzadj / 60; + if (timeDataPtr->tm_isdst) { + timeZone += 60; + } + + return timeZone; + +#endif + +#if defined(HAVE_TM_GMTOFF) && !defined (TCL_GOT_TIMEZONE) +# define TCL_GOT_TIMEZONE + + /* Struct tm contains tm_gmtoff - that value may be used. */ + + time_t curTime = (time_t) currentTime; + struct tm *timeDataPtr = TclpLocaltime((TclpTime_t) &curTime); + int timeZone; + + timeZone = -(timeDataPtr->tm_gmtoff / 60); + if (timeDataPtr->tm_isdst) { + timeZone += 60; + } + + return timeZone; + +#endif + +#if defined(HAVE_TIMEZONE_VAR) && !defined(TCL_GOT_TIMEZONE) && !defined(USE_DELTA_FOR_TZ) +# define TCL_GOT_TIMEZONE + + int timeZone; + + /* The 'timezone' external var is present and may be used. */ + + SetTZIfNecessary(); + + /* + * Note: this is not a typo in "timezone" below! See tzset + * documentation for details. + */ + + timeZone = timezone / 60; + return timeZone; + +#endif + +#if !defined(TCL_GOT_TIMEZONE) +#define TCL_GOT_TIMEZONE 1 + /* + * Fallback - determine time zone with a known reference time. + */ + + int timeZone; + time_t tt; + struct tm *stm; + tt = 849268800L; /* 1996-11-29 12:00:00 GMT */ + stm = TclpLocaltime((TclpTime_t) &tt); /* eg 1996-11-29 6:00:00 CST6CDT */ + /* The calculation below assumes a max of +12 or -12 hours from GMT */ + timeZone = (12 - stm->tm_hour)*60 + (0 - stm->tm_min); + if ( stm -> tm_isdst ) { + timeZone += 60; + } + return timeZone; /* eg +360 for CST6CDT */ +#endif + +#ifndef TCL_GOT_TIMEZONE + /* + * Cause compile error, we don't know how to get timezone. + */ + +#error autoconf did not figure out how to determine the timezone. + +#endif + +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_GetTime -- + * + * Gets the current system time in seconds and microseconds + * since the beginning of the epoch: 00:00 UCT, January 1, 1970. + * + * Results: + * Returns the current time in timePtr. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +EXPORT_C void +Tcl_GetTime(timePtr) + Tcl_Time *timePtr; /* Location to store time information. */ +{ + struct timeval tv; + struct timezone tz; + + (void) gettimeofday(&tv, &tz); + timePtr->sec = tv.tv_sec; + timePtr->usec = tv.tv_usec; +} + +/* + *---------------------------------------------------------------------- + * + * TclpGetDate -- + * + * This function converts between seconds and struct tm. If + * useGMT is true, then the returned date will be in Greenwich + * Mean Time (GMT). Otherwise, it will be in the local time zone. + * + * Results: + * Returns a static tm structure. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +struct tm * +TclpGetDate(time, useGMT) + TclpTime_t time; + int useGMT; +{ + if (useGMT) { + return TclpGmtime(time); + } else { + return TclpLocaltime(time); + } +} + +/* + *---------------------------------------------------------------------- + * + * TclpStrftime -- + * + * On Unix, we can safely call the native strftime implementation, + * and also ignore the useGMT parameter. + * + * Results: + * The normal strftime result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +size_t +TclpStrftime(s, maxsize, format, t, useGMT) + char *s; + size_t maxsize; + CONST char *format; + CONST struct tm *t; + int useGMT; +{ + if (format[0] == '%' && format[1] == 'Q') { + /* Format as a stardate */ + sprintf(s, "Stardate %2d%03d.%01d", + (((t->tm_year + TM_YEAR_BASE) + 377) - 2323), + (((t->tm_yday + 1) * 1000) / + (365 + IsLeapYear((t->tm_year + TM_YEAR_BASE)))), + (((t->tm_hour * 60) + t->tm_min)/144)); + return(strlen(s)); + } + setlocale(LC_TIME, ""); + return strftime(s, maxsize, format, t); +} + +/* + *---------------------------------------------------------------------- + * + * TclpGmtime -- + * + * Wrapper around the 'gmtime' library function to make it thread + * safe. + * + * Results: + * Returns a pointer to a 'struct tm' in thread-specific data. + * + * Side effects: + * Invokes gmtime or gmtime_r as appropriate. + * + *---------------------------------------------------------------------- + */ + +struct tm * +TclpGmtime( tt ) + TclpTime_t_CONST tt; +{ + CONST time_t *timePtr = (CONST time_t *) tt; + /* Pointer to the number of seconds + * since the local system's epoch */ + + /* + * Get a thread-local buffer to hold the returned time. + */ + + ThreadSpecificData *tsdPtr = TCL_TSD_INIT( &tmKey ); +#ifdef HAVE_GMTIME_R + gmtime_r(timePtr, &( tsdPtr->gmtime_buf )); +#else + Tcl_MutexLock( &tmMutex ); + memcpy( (VOID *) &( tsdPtr->gmtime_buf ), + (VOID *) gmtime( timePtr ), + sizeof( struct tm ) ); + Tcl_MutexUnlock( &tmMutex ); +#endif + return &( tsdPtr->gmtime_buf ); +} +/* + * Forwarder for obsolete item in Stubs + */ +struct tm* +TclpGmtime_unix( timePtr ) + TclpTime_t_CONST timePtr; +{ + return TclpGmtime( timePtr ); +} + +/* + *---------------------------------------------------------------------- + * + * TclpLocaltime -- + * + * Wrapper around the 'localtime' library function to make it thread + * safe. + * + * Results: + * Returns a pointer to a 'struct tm' in thread-specific data. + * + * Side effects: + * Invokes localtime or localtime_r as appropriate. + * + *---------------------------------------------------------------------- + */ + +struct tm * +TclpLocaltime( tt ) + TclpTime_t_CONST tt; +{ + CONST time_t *timePtr = (CONST time_t *) tt; + /* Pointer to the number of seconds + * since the local system's epoch */ + /* + * Get a thread-local buffer to hold the returned time. + */ + + ThreadSpecificData *tsdPtr = TCL_TSD_INIT( &tmKey ); + SetTZIfNecessary(); +#ifdef HAVE_LOCALTIME_R + localtime_r( timePtr, &( tsdPtr->localtime_buf ) ); +#else + Tcl_MutexLock( &tmMutex ); + memcpy( (VOID *) &( tsdPtr -> localtime_buf ), + (VOID *) localtime( timePtr ), + sizeof( struct tm ) ); + Tcl_MutexUnlock( &tmMutex ); +#endif + return &( tsdPtr->localtime_buf ); +} +/* + * Forwarder for obsolete item in Stubs + */ +struct tm* +TclpLocaltime_unix( timePtr ) + TclpTime_t_CONST timePtr; +{ + return TclpLocaltime( timePtr ); +} + +/* + *---------------------------------------------------------------------- + * + * SetTZIfNecessary -- + * + * Determines whether a call to 'tzset' is needed prior to the + * next call to 'localtime' or examination of the 'timezone' variable. + * + * Results: + * None. + * + * Side effects: + * If 'tzset' has never been called in the current process, or if + * the value of the environment variable TZ has changed since the + * last call to 'tzset', then 'tzset' is called again. + * + *---------------------------------------------------------------------- + */ + +static void +SetTZIfNecessary() { + + CONST char* newTZ = getenv( "TZ" ); + Tcl_MutexLock(&tmMutex); + if ( newTZ == NULL ) { + newTZ = ""; + } + if ( lastTZ == NULL || strcmp( lastTZ, newTZ ) ) { + tzset(); + if ( lastTZ == NULL ) { + Tcl_CreateExitHandler( CleanupMemory, (ClientData) NULL ); + } else { + Tcl_Free( lastTZ ); + } + lastTZ = ckalloc( strlen( newTZ ) + 1 ); + strcpy( lastTZ, newTZ ); + } + Tcl_MutexUnlock(&tmMutex); + +} + +/* + *---------------------------------------------------------------------- + * + * CleanupMemory -- + * + * Releases the private copy of the TZ environment variable + * upon exit from Tcl. + * + * Results: + * None. + * + * Side effects: + * Frees allocated memory. + * + *---------------------------------------------------------------------- + */ + +static void +CleanupMemory( ClientData ignored ) +{ + ckfree( lastTZ ); +}