os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/unix/tclUnixTime.c
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 +}