os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/unix/tclUnixTime.c
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/unix/tclUnixTime.c	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,493 @@
     1.4 +/* 
     1.5 + * tclUnixTime.c --
     1.6 + *
     1.7 + *	Contains Unix specific versions of Tcl functions that
     1.8 + *	obtain time values from the operating system.
     1.9 + *
    1.10 + * Copyright (c) 1995 Sun Microsystems, Inc.
    1.11 + * Portions Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiaries. All rights reserved.  
    1.12 + *
    1.13 + * See the file "license.terms" for information on usage and redistribution
    1.14 + * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    1.15 + *
    1.16 + * RCS: @(#) $Id: tclUnixTime.c,v 1.15.2.6 2007/04/21 19:52:15 kennykb Exp $
    1.17 + */
    1.18 +
    1.19 +#include "tclInt.h"
    1.20 +#include "tclPort.h"
    1.21 +#include <locale.h>
    1.22 +#define TM_YEAR_BASE 1900
    1.23 +#define IsLeapYear(x)   ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0))
    1.24 +
    1.25 +/*
    1.26 + * TclpGetDate is coded to return a pointer to a 'struct tm'.  For
    1.27 + * thread safety, this structure must be in thread-specific data.
    1.28 + * The 'tmKey' variable is the key to this buffer.
    1.29 + */
    1.30 +
    1.31 +static Tcl_ThreadDataKey tmKey;
    1.32 +typedef struct ThreadSpecificData {
    1.33 +    struct tm gmtime_buf;
    1.34 +    struct tm localtime_buf;
    1.35 +} ThreadSpecificData;
    1.36 +
    1.37 +/*
    1.38 + * If we fall back on the thread-unsafe versions of gmtime and localtime,
    1.39 + * use this mutex to try to protect them.
    1.40 + */
    1.41 +
    1.42 +TCL_DECLARE_MUTEX(tmMutex)
    1.43 +
    1.44 +static char* lastTZ = NULL;	/* Holds the last setting of the
    1.45 +				 * TZ environment variable, or an
    1.46 +				 * empty string if the variable was
    1.47 +				 * not set. */
    1.48 +
    1.49 +/* Static functions declared in this file */
    1.50 +
    1.51 +static void SetTZIfNecessary _ANSI_ARGS_((void));
    1.52 +static void CleanupMemory _ANSI_ARGS_((ClientData));
    1.53 +
    1.54 +/*
    1.55 + *-----------------------------------------------------------------------------
    1.56 + *
    1.57 + * TclpGetSeconds --
    1.58 + *
    1.59 + *	This procedure returns the number of seconds from the epoch.  On
    1.60 + *	most Unix systems the epoch is Midnight Jan 1, 1970 GMT.
    1.61 + *
    1.62 + * Results:
    1.63 + *	Number of seconds from the epoch.
    1.64 + *
    1.65 + * Side effects:
    1.66 + *	None.
    1.67 + *
    1.68 + *-----------------------------------------------------------------------------
    1.69 + */
    1.70 +
    1.71 +unsigned long
    1.72 +TclpGetSeconds()
    1.73 +{
    1.74 +    return time((time_t *) NULL);
    1.75 +}
    1.76 +
    1.77 +/*
    1.78 + *-----------------------------------------------------------------------------
    1.79 + *
    1.80 + * TclpGetClicks --
    1.81 + *
    1.82 + *	This procedure returns a value that represents the highest resolution
    1.83 + *	clock available on the system.  There are no garantees on what the
    1.84 + *	resolution will be.  In Tcl we will call this value a "click".  The
    1.85 + *	start time is also system dependant.
    1.86 + *
    1.87 + * Results:
    1.88 + *	Number of clicks from some start time.
    1.89 + *
    1.90 + * Side effects:
    1.91 + *	None.
    1.92 + *
    1.93 + *-----------------------------------------------------------------------------
    1.94 + */
    1.95 +
    1.96 +unsigned long
    1.97 +TclpGetClicks()
    1.98 +{
    1.99 +    unsigned long now;
   1.100 +#ifdef NO_GETTOD
   1.101 +    struct tms dummy;
   1.102 +#else
   1.103 +    struct timeval date;
   1.104 +    struct timezone tz;
   1.105 +#endif
   1.106 +
   1.107 +#ifdef NO_GETTOD
   1.108 +    now = (unsigned long) times(&dummy);
   1.109 +#else
   1.110 +    gettimeofday(&date, &tz);
   1.111 +    now = date.tv_sec*1000000 + date.tv_usec;
   1.112 +#endif
   1.113 +
   1.114 +    return now;
   1.115 +}
   1.116 +
   1.117 +/*
   1.118 + *----------------------------------------------------------------------
   1.119 + *
   1.120 + * TclpGetTimeZone --
   1.121 + *
   1.122 + *	Determines the current timezone.  The method varies wildly
   1.123 + *	between different platform implementations, so its hidden in
   1.124 + *	this function.
   1.125 + *
   1.126 + * Results:
   1.127 + *	The return value is the local time zone, measured in
   1.128 + *	minutes away from GMT (-ve for east, +ve for west).
   1.129 + *
   1.130 + * Side effects:
   1.131 + *	None.
   1.132 + *
   1.133 + *----------------------------------------------------------------------
   1.134 + */
   1.135 +
   1.136 +int
   1.137 +TclpGetTimeZone (currentTime)
   1.138 +    Tcl_WideInt  currentTime;
   1.139 +{
   1.140 +    /*
   1.141 +     * We prefer first to use the time zone in "struct tm" if the
   1.142 +     * structure contains such a member.  Following that, we try
   1.143 +     * to locate the external 'timezone' variable and use its value.
   1.144 +     * If both of those methods fail, we attempt to convert a known
   1.145 +     * time to local time and use the difference from UTC as the local
   1.146 +     * time zone.  In all cases, we need to undo any Daylight Saving Time
   1.147 +     * adjustment.
   1.148 +     */
   1.149 +    
   1.150 +#if defined(HAVE_TM_TZADJ)
   1.151 +#   define TCL_GOT_TIMEZONE
   1.152 +
   1.153 +    /* Struct tm contains tm_tzadj - that value may be used. */
   1.154 +
   1.155 +    time_t      curTime = (time_t) currentTime;
   1.156 +    struct tm  *timeDataPtr = TclpLocaltime((TclpTime_t) &curTime);
   1.157 +    int         timeZone;
   1.158 +
   1.159 +    timeZone = timeDataPtr->tm_tzadj  / 60;
   1.160 +    if (timeDataPtr->tm_isdst) {
   1.161 +        timeZone += 60;
   1.162 +    }
   1.163 +    
   1.164 +    return timeZone;
   1.165 +
   1.166 +#endif
   1.167 +
   1.168 +#if defined(HAVE_TM_GMTOFF) && !defined (TCL_GOT_TIMEZONE)
   1.169 +#   define TCL_GOT_TIMEZONE
   1.170 +
   1.171 +    /* Struct tm contains tm_gmtoff - that value may be used. */
   1.172 +
   1.173 +    time_t     curTime = (time_t) currentTime;
   1.174 +    struct tm *timeDataPtr = TclpLocaltime((TclpTime_t) &curTime);
   1.175 +    int        timeZone;
   1.176 +
   1.177 +    timeZone = -(timeDataPtr->tm_gmtoff / 60);
   1.178 +    if (timeDataPtr->tm_isdst) {
   1.179 +        timeZone += 60;
   1.180 +    }
   1.181 +    
   1.182 +    return timeZone;
   1.183 +
   1.184 +#endif
   1.185 +
   1.186 +#if defined(HAVE_TIMEZONE_VAR) && !defined(TCL_GOT_TIMEZONE) && !defined(USE_DELTA_FOR_TZ)
   1.187 +#   define TCL_GOT_TIMEZONE
   1.188 +
   1.189 +    int        timeZone;
   1.190 +
   1.191 +    /* The 'timezone' external var is present and may be used. */
   1.192 +
   1.193 +    SetTZIfNecessary();
   1.194 +
   1.195 +    /*
   1.196 +     * Note: this is not a typo in "timezone" below!  See tzset
   1.197 +     * documentation for details.
   1.198 +     */
   1.199 +
   1.200 +    timeZone = timezone / 60;
   1.201 +    return timeZone;
   1.202 +
   1.203 +#endif
   1.204 +
   1.205 +#if !defined(TCL_GOT_TIMEZONE) 
   1.206 +#define TCL_GOT_TIMEZONE 1
   1.207 +    /*
   1.208 +     * Fallback - determine time zone with a known reference time.
   1.209 +     */
   1.210 +
   1.211 +    int timeZone;
   1.212 +    time_t tt;
   1.213 +    struct tm *stm;
   1.214 +    tt = 849268800L;      /*    1996-11-29 12:00:00  GMT */
   1.215 +    stm = TclpLocaltime((TclpTime_t) &tt); /* eg 1996-11-29  6:00:00  CST6CDT */
   1.216 +    /* The calculation below assumes a max of +12 or -12 hours from GMT */
   1.217 +    timeZone = (12 - stm->tm_hour)*60 + (0 - stm->tm_min);
   1.218 +    if ( stm -> tm_isdst ) {
   1.219 +        timeZone += 60;
   1.220 +    }
   1.221 +    return timeZone;  /* eg +360 for CST6CDT */
   1.222 +#endif
   1.223 +
   1.224 +#ifndef TCL_GOT_TIMEZONE
   1.225 +    /*
   1.226 +     * Cause compile error, we don't know how to get timezone.
   1.227 +     */
   1.228 +
   1.229 +#error autoconf did not figure out how to determine the timezone. 
   1.230 +
   1.231 +#endif
   1.232 +
   1.233 +}
   1.234 +
   1.235 +/*
   1.236 + *----------------------------------------------------------------------
   1.237 + *
   1.238 + * Tcl_GetTime --
   1.239 + *
   1.240 + *	Gets the current system time in seconds and microseconds
   1.241 + *	since the beginning of the epoch: 00:00 UCT, January 1, 1970.
   1.242 + *
   1.243 + * Results:
   1.244 + *	Returns the current time in timePtr.
   1.245 + *
   1.246 + * Side effects:
   1.247 + *	None.
   1.248 + *
   1.249 + *----------------------------------------------------------------------
   1.250 + */
   1.251 +
   1.252 +EXPORT_C void
   1.253 +Tcl_GetTime(timePtr)
   1.254 +    Tcl_Time *timePtr;		/* Location to store time information. */
   1.255 +{
   1.256 +    struct timeval tv;
   1.257 +    struct timezone tz;
   1.258 +    
   1.259 +    (void) gettimeofday(&tv, &tz);
   1.260 +    timePtr->sec = tv.tv_sec;
   1.261 +    timePtr->usec = tv.tv_usec;
   1.262 +}
   1.263 +
   1.264 +/*
   1.265 + *----------------------------------------------------------------------
   1.266 + *
   1.267 + * TclpGetDate --
   1.268 + *
   1.269 + *	This function converts between seconds and struct tm.  If
   1.270 + *	useGMT is true, then the returned date will be in Greenwich
   1.271 + *	Mean Time (GMT).  Otherwise, it will be in the local time zone.
   1.272 + *
   1.273 + * Results:
   1.274 + *	Returns a static tm structure.
   1.275 + *
   1.276 + * Side effects:
   1.277 + *	None.
   1.278 + *
   1.279 + *----------------------------------------------------------------------
   1.280 + */
   1.281 +
   1.282 +struct tm *
   1.283 +TclpGetDate(time, useGMT)
   1.284 +    TclpTime_t time;
   1.285 +    int useGMT;
   1.286 +{
   1.287 +    if (useGMT) {
   1.288 +	return TclpGmtime(time);
   1.289 +    } else {
   1.290 +	return TclpLocaltime(time);
   1.291 +    }
   1.292 +}
   1.293 +
   1.294 +/*
   1.295 + *----------------------------------------------------------------------
   1.296 + *
   1.297 + * TclpStrftime --
   1.298 + *
   1.299 + *	On Unix, we can safely call the native strftime implementation,
   1.300 + *	and also ignore the useGMT parameter.
   1.301 + *
   1.302 + * Results:
   1.303 + *	The normal strftime result.
   1.304 + *
   1.305 + * Side effects:
   1.306 + *	None.
   1.307 + *
   1.308 + *----------------------------------------------------------------------
   1.309 + */
   1.310 +
   1.311 +size_t
   1.312 +TclpStrftime(s, maxsize, format, t, useGMT)
   1.313 +    char *s;
   1.314 +    size_t maxsize;
   1.315 +    CONST char *format;
   1.316 +    CONST struct tm *t;
   1.317 +    int useGMT;
   1.318 +{
   1.319 +    if (format[0] == '%' && format[1] == 'Q') {
   1.320 +	/* Format as a stardate */
   1.321 +	sprintf(s, "Stardate %2d%03d.%01d",
   1.322 +		(((t->tm_year + TM_YEAR_BASE) + 377) - 2323),
   1.323 +		(((t->tm_yday + 1) * 1000) /
   1.324 +			(365 + IsLeapYear((t->tm_year + TM_YEAR_BASE)))),
   1.325 +		(((t->tm_hour * 60) + t->tm_min)/144));
   1.326 +	return(strlen(s));
   1.327 +    }
   1.328 +    setlocale(LC_TIME, "");
   1.329 +    return strftime(s, maxsize, format, t);
   1.330 +}
   1.331 +
   1.332 +/*
   1.333 + *----------------------------------------------------------------------
   1.334 + *
   1.335 + * TclpGmtime --
   1.336 + *
   1.337 + *	Wrapper around the 'gmtime' library function to make it thread
   1.338 + *	safe.
   1.339 + *
   1.340 + * Results:
   1.341 + *	Returns a pointer to a 'struct tm' in thread-specific data.
   1.342 + *
   1.343 + * Side effects:
   1.344 + *	Invokes gmtime or gmtime_r as appropriate.
   1.345 + *
   1.346 + *----------------------------------------------------------------------
   1.347 + */
   1.348 +
   1.349 +struct tm *
   1.350 +TclpGmtime( tt )
   1.351 +    TclpTime_t_CONST tt;
   1.352 +{
   1.353 +    CONST time_t *timePtr = (CONST time_t *) tt;
   1.354 +				/* Pointer to the number of seconds
   1.355 +				 * since the local system's epoch */
   1.356 +
   1.357 +    /*
   1.358 +     * Get a thread-local buffer to hold the returned time.
   1.359 +     */
   1.360 +
   1.361 +    ThreadSpecificData *tsdPtr = TCL_TSD_INIT( &tmKey );
   1.362 +#ifdef HAVE_GMTIME_R
   1.363 +    gmtime_r(timePtr, &( tsdPtr->gmtime_buf ));
   1.364 +#else
   1.365 +    Tcl_MutexLock( &tmMutex );
   1.366 +    memcpy( (VOID *) &( tsdPtr->gmtime_buf ),
   1.367 +	    (VOID *) gmtime( timePtr ),
   1.368 +	    sizeof( struct tm ) );
   1.369 +    Tcl_MutexUnlock( &tmMutex );
   1.370 +#endif    
   1.371 +    return &( tsdPtr->gmtime_buf );
   1.372 +}
   1.373 +/*
   1.374 + * Forwarder for obsolete item in Stubs
   1.375 + */
   1.376 +struct tm*
   1.377 +TclpGmtime_unix( timePtr )
   1.378 +    TclpTime_t_CONST timePtr;
   1.379 +{
   1.380 +    return TclpGmtime( timePtr );
   1.381 +}
   1.382 +
   1.383 +/*
   1.384 + *----------------------------------------------------------------------
   1.385 + *
   1.386 + * TclpLocaltime --
   1.387 + *
   1.388 + *	Wrapper around the 'localtime' library function to make it thread
   1.389 + *	safe.
   1.390 + *
   1.391 + * Results:
   1.392 + *	Returns a pointer to a 'struct tm' in thread-specific data.
   1.393 + *
   1.394 + * Side effects:
   1.395 + *	Invokes localtime or localtime_r as appropriate.
   1.396 + *
   1.397 + *----------------------------------------------------------------------
   1.398 + */
   1.399 +
   1.400 +struct tm *
   1.401 +TclpLocaltime( tt )
   1.402 +    TclpTime_t_CONST tt;
   1.403 +{
   1.404 +    CONST time_t *timePtr = (CONST time_t *) tt;
   1.405 +				/* Pointer to the number of seconds
   1.406 +				 * since the local system's epoch */
   1.407 +    /*
   1.408 +     * Get a thread-local buffer to hold the returned time.
   1.409 +     */
   1.410 +
   1.411 +    ThreadSpecificData *tsdPtr = TCL_TSD_INIT( &tmKey );
   1.412 +    SetTZIfNecessary();
   1.413 +#ifdef HAVE_LOCALTIME_R
   1.414 +    localtime_r( timePtr, &( tsdPtr->localtime_buf ) );
   1.415 +#else
   1.416 +    Tcl_MutexLock( &tmMutex );
   1.417 +    memcpy( (VOID *) &( tsdPtr -> localtime_buf ),
   1.418 +	    (VOID *) localtime( timePtr ),
   1.419 +	    sizeof( struct tm ) );
   1.420 +    Tcl_MutexUnlock( &tmMutex );
   1.421 +#endif    
   1.422 +    return &( tsdPtr->localtime_buf );
   1.423 +}
   1.424 +/*
   1.425 + * Forwarder for obsolete item in Stubs
   1.426 + */
   1.427 +struct tm*
   1.428 +TclpLocaltime_unix( timePtr )
   1.429 +    TclpTime_t_CONST timePtr;
   1.430 +{
   1.431 +    return TclpLocaltime( timePtr );
   1.432 +}
   1.433 +
   1.434 +/*
   1.435 + *----------------------------------------------------------------------
   1.436 + *
   1.437 + * SetTZIfNecessary --
   1.438 + *
   1.439 + *	Determines whether a call to 'tzset' is needed prior to the
   1.440 + *	next call to 'localtime' or examination of the 'timezone' variable.
   1.441 + *
   1.442 + * Results:
   1.443 + *	None.
   1.444 + *
   1.445 + * Side effects:
   1.446 + *	If 'tzset' has never been called in the current process, or if
   1.447 + *	the value of the environment variable TZ has changed since the
   1.448 + *	last call to 'tzset', then 'tzset' is called again.
   1.449 + *
   1.450 + *----------------------------------------------------------------------
   1.451 + */
   1.452 +
   1.453 +static void
   1.454 +SetTZIfNecessary() {
   1.455 +
   1.456 +    CONST char* newTZ = getenv( "TZ" );
   1.457 +    Tcl_MutexLock(&tmMutex);
   1.458 +    if ( newTZ == NULL ) {
   1.459 +	newTZ = "";
   1.460 +    }
   1.461 +    if ( lastTZ == NULL || strcmp( lastTZ, newTZ ) ) {
   1.462 +        tzset();
   1.463 +	if ( lastTZ == NULL ) {
   1.464 +	    Tcl_CreateExitHandler( CleanupMemory, (ClientData) NULL );
   1.465 +	} else {
   1.466 +	    Tcl_Free( lastTZ );
   1.467 +	}
   1.468 +	lastTZ = ckalloc( strlen( newTZ ) + 1 );
   1.469 +	strcpy( lastTZ, newTZ );
   1.470 +    }
   1.471 +    Tcl_MutexUnlock(&tmMutex);
   1.472 +
   1.473 +}
   1.474 +
   1.475 +/*
   1.476 + *----------------------------------------------------------------------
   1.477 + *
   1.478 + * CleanupMemory --
   1.479 + *
   1.480 + *	Releases the private copy of the TZ environment variable
   1.481 + *	upon exit from Tcl.
   1.482 + *
   1.483 + * Results:
   1.484 + *	None.
   1.485 + *
   1.486 + * Side effects:
   1.487 + *	Frees allocated memory.
   1.488 + *
   1.489 + *----------------------------------------------------------------------
   1.490 + */
   1.491 +
   1.492 +static void
   1.493 +CleanupMemory( ClientData ignored )
   1.494 +{
   1.495 +    ckfree( lastTZ );
   1.496 +}