os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/mac/tclMacTime.c
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/mac/tclMacTime.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,435 @@
1.4 +/*
1.5 + * tclMacTime.c --
1.6 + *
1.7 + * Contains Macintosh specific versions of Tcl functions that
1.8 + * obtain time values from the operating system.
1.9 + *
1.10 + * Copyright (c) 1995-1997 Sun Microsystems, Inc.
1.11 + *
1.12 + * See the file "license.terms" for information on usage and redistribution
1.13 + * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
1.14 + *
1.15 + * RCS: @(#) $Id: tclMacTime.c,v 1.7 2002/01/04 11:21:05 das Exp $
1.16 + */
1.17 +
1.18 +#include "tclInt.h"
1.19 +#include "tclPort.h"
1.20 +#include "tclMacInt.h"
1.21 +#include <OSUtils.h>
1.22 +#include <Timer.h>
1.23 +#include <time.h>
1.24 +
1.25 +/*
1.26 + * Static variables used by the Tcl_GetTime function.
1.27 + */
1.28 +
1.29 +static int initalized = false;
1.30 +static unsigned long baseSeconds;
1.31 +static UnsignedWide microOffset;
1.32 +
1.33 +static int gmt_initialized = false;
1.34 +static long gmt_offset;
1.35 +static int gmt_isdst;
1.36 +TCL_DECLARE_MUTEX(gmtMutex)
1.37 +
1.38 +static int gmt_lastGetDateUseGMT = 0;
1.39 +
1.40 +typedef struct _TABLE {
1.41 + char *name;
1.42 + int type;
1.43 + time_t value;
1.44 +} TABLE;
1.45 +
1.46 +
1.47 +#define HOUR(x) ((time_t) (3600 * x))
1.48 +
1.49 +#define tZONE 0
1.50 +#define tDAYZONE 1
1.51 +
1.52 +
1.53 +/*
1.54 + * inverse timezone table, adapted from tclDate.c by removing duplicates and
1.55 + * adding some made up names for unusual daylight savings
1.56 + */
1.57 +static TABLE invTimezoneTable[] = {
1.58 + { "Z", -1, HOUR( 36) }, /* Unknown */
1.59 + { "GMT", tZONE, HOUR( 0) }, /* Greenwich Mean */
1.60 + { "BST", tDAYZONE, HOUR( 0) }, /* British Summer */
1.61 + { "WAT", tZONE, HOUR( 1) }, /* West Africa */
1.62 + { "WADST", tDAYZONE, HOUR( 1) }, /* West Africa Daylight*/
1.63 + { "AT", tZONE, HOUR( 2) }, /* Azores Daylight*/
1.64 + { "ADST", tDAYZONE, HOUR( 2) }, /* Azores */
1.65 + { "NFT", tZONE, HOUR( 7/2) }, /* Newfoundland */
1.66 + { "NDT", tDAYZONE, HOUR( 7/2) }, /* Newfoundland Daylight */
1.67 + { "AST", tZONE, HOUR( 4) }, /* Atlantic Standard */
1.68 + { "ADT", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
1.69 + { "EST", tZONE, HOUR( 5) }, /* Eastern Standard */
1.70 + { "EDT", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
1.71 + { "CST", tZONE, HOUR( 6) }, /* Central Standard */
1.72 + { "CDT", tDAYZONE, HOUR( 6) }, /* Central Daylight */
1.73 + { "MST", tZONE, HOUR( 7) }, /* Mountain Standard */
1.74 + { "MDT", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
1.75 + { "PST", tZONE, HOUR( 8) }, /* Pacific Standard */
1.76 + { "PDT", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
1.77 + { "YST", tZONE, HOUR( 9) }, /* Yukon Standard */
1.78 + { "YDT", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
1.79 + { "HST", tZONE, HOUR(10) }, /* Hawaii Standard */
1.80 + { "HDT", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
1.81 + { "NT", tZONE, HOUR(11) }, /* Nome */
1.82 + { "NST", tDAYZONE, HOUR(11) }, /* Nome Daylight*/
1.83 + { "IDLW", tZONE, HOUR(12) }, /* International Date Line West */
1.84 + { "CET", tZONE, -HOUR( 1) }, /* Central European */
1.85 + { "CEST", tDAYZONE, -HOUR( 1) }, /* Central European Summer */
1.86 + { "EET", tZONE, -HOUR( 2) }, /* Eastern Europe, USSR Zone 1 */
1.87 + { "EEST", tDAYZONE, -HOUR( 2) }, /* Eastern Europe, USSR Zone 1 Daylight*/
1.88 + { "BT", tZONE, -HOUR( 3) }, /* Baghdad, USSR Zone 2 */
1.89 + { "BDST", tDAYZONE, -HOUR( 3) }, /* Baghdad, USSR Zone 2 Daylight*/
1.90 + { "IT", tZONE, -HOUR( 7/2) }, /* Iran */
1.91 + { "IDST", tDAYZONE, -HOUR( 7/2) }, /* Iran Daylight*/
1.92 + { "ZP4", tZONE, -HOUR( 4) }, /* USSR Zone 3 */
1.93 + { "ZP4S", tDAYZONE, -HOUR( 4) }, /* USSR Zone 3 */
1.94 + { "ZP5", tZONE, -HOUR( 5) }, /* USSR Zone 4 */
1.95 + { "ZP5S", tDAYZONE, -HOUR( 5) }, /* USSR Zone 4 */
1.96 + { "IST", tZONE, -HOUR(11/2) }, /* Indian Standard */
1.97 + { "ISDST", tDAYZONE, -HOUR(11/2) }, /* Indian Standard */
1.98 + { "ZP6", tZONE, -HOUR( 6) }, /* USSR Zone 5 */
1.99 + { "ZP6S", tDAYZONE, -HOUR( 6) }, /* USSR Zone 5 */
1.100 + { "WAST", tZONE, -HOUR( 7) }, /* West Australian Standard */
1.101 + { "WADT", tDAYZONE, -HOUR( 7) }, /* West Australian Daylight */
1.102 + { "JT", tZONE, -HOUR(15/2) }, /* Java (3pm in Cronusland!) */
1.103 + { "JDST", tDAYZONE, -HOUR(15/2) }, /* Java (3pm in Cronusland!) */
1.104 + { "CCT", tZONE, -HOUR( 8) }, /* China Coast, USSR Zone 7 */
1.105 + { "CCST", tDAYZONE, -HOUR( 8) }, /* China Coast, USSR Zone 7 */
1.106 + { "JST", tZONE, -HOUR( 9) }, /* Japan Standard, USSR Zone 8 */
1.107 + { "JSDST", tDAYZONE, -HOUR( 9) }, /* Japan Standard, USSR Zone 8 */
1.108 + { "CAST", tZONE, -HOUR(19/2) }, /* Central Australian Standard */
1.109 + { "CADT", tDAYZONE, -HOUR(19/2) }, /* Central Australian Daylight */
1.110 + { "EAST", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
1.111 + { "EADT", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
1.112 + { "NZT", tZONE, -HOUR(12) }, /* New Zealand */
1.113 + { "NZDT", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
1.114 + { NULL }
1.115 +};
1.116 +
1.117 +/*
1.118 + * Prototypes for procedures that are private to this file:
1.119 + */
1.120 +
1.121 +static void SubtractUnsignedWide _ANSI_ARGS_((UnsignedWide *x,
1.122 + UnsignedWide *y, UnsignedWide *result));
1.123 +
1.124 +/*
1.125 + *-----------------------------------------------------------------------------
1.126 + *
1.127 + * TclpGetGMTOffset --
1.128 + *
1.129 + * This procedure gets the offset seconds that needs to be _added_ to tcl time
1.130 + * in seconds (i.e. GMT time) to get local time needed as input to various
1.131 + * Mac OS APIs, to convert Mac OS API output to tcl time, _subtract_ this value.
1.132 + *
1.133 + * Results:
1.134 + * Number of seconds separating GMT time and mac.
1.135 + *
1.136 + * Side effects:
1.137 + * None.
1.138 + *
1.139 + *-----------------------------------------------------------------------------
1.140 + */
1.141 +
1.142 +long
1.143 +TclpGetGMTOffset()
1.144 +{
1.145 + if (gmt_initialized == false) {
1.146 + MachineLocation loc;
1.147 +
1.148 + Tcl_MutexLock(&gmtMutex);
1.149 + ReadLocation(&loc);
1.150 + gmt_offset = loc.u.gmtDelta & 0x00ffffff;
1.151 + if (gmt_offset & 0x00800000) {
1.152 + gmt_offset = gmt_offset | 0xff000000;
1.153 + }
1.154 + gmt_isdst=(loc.u.dlsDelta < 0);
1.155 + gmt_initialized = true;
1.156 + Tcl_MutexUnlock(&gmtMutex);
1.157 + }
1.158 + return (gmt_offset);
1.159 +}
1.160 +
1.161 +/*
1.162 + *-----------------------------------------------------------------------------
1.163 + *
1.164 + * TclpGetSeconds --
1.165 + *
1.166 + * This procedure returns the number of seconds from the epoch. On
1.167 + * the Macintosh the epoch is Midnight Jan 1, 1904. Unfortunatly,
1.168 + * the Macintosh doesn't tie the epoch to a particular time zone. For
1.169 + * Tcl we tie the epoch to GMT. This makes the time zone date parsing
1.170 + * code work. The epoch for Mac-Tcl is: Midnight Jan 1, 1904 GMT.
1.171 + *
1.172 + * Results:
1.173 + * Number of seconds from the epoch in GMT.
1.174 + *
1.175 + * Side effects:
1.176 + * None.
1.177 + *
1.178 + *-----------------------------------------------------------------------------
1.179 + */
1.180 +
1.181 +unsigned long
1.182 +TclpGetSeconds()
1.183 +{
1.184 + unsigned long seconds;
1.185 +
1.186 + GetDateTime(&seconds);
1.187 + return (seconds - TclpGetGMTOffset() + tcl_mac_epoch_offset);
1.188 +}
1.189 +
1.190 +/*
1.191 + *-----------------------------------------------------------------------------
1.192 + *
1.193 + * TclpGetClicks --
1.194 + *
1.195 + * This procedure returns a value that represents the highest resolution
1.196 + * clock available on the system. There are no garantees on what the
1.197 + * resolution will be. In Tcl we will call this value a "click". The
1.198 + * start time is also system dependant.
1.199 + *
1.200 + * Results:
1.201 + * Number of clicks from some start time.
1.202 + *
1.203 + * Side effects:
1.204 + * None.
1.205 + *
1.206 + *-----------------------------------------------------------------------------
1.207 + */
1.208 +
1.209 +unsigned long
1.210 +TclpGetClicks()
1.211 +{
1.212 + UnsignedWide micros;
1.213 +
1.214 + Microseconds(µs);
1.215 + return micros.lo;
1.216 +}
1.217 +
1.218 +/*
1.219 + *----------------------------------------------------------------------
1.220 + *
1.221 + * TclpGetTimeZone --
1.222 + *
1.223 + * Get the current time zone.
1.224 + *
1.225 + * Results:
1.226 + * The return value is the local time zone, measured in
1.227 + * minutes away from GMT (-ve for east, +ve for west).
1.228 + *
1.229 + * Side effects:
1.230 + * None.
1.231 + *
1.232 + *----------------------------------------------------------------------
1.233 + */
1.234 +
1.235 +int
1.236 +TclpGetTimeZone (
1.237 + unsigned long currentTime) /* Ignored on Mac. */
1.238 +{
1.239 + long offset;
1.240 +
1.241 + /*
1.242 + * Convert the Mac offset from seconds to minutes and
1.243 + * add an hour if we have daylight savings time.
1.244 + */
1.245 + offset = -TclpGetGMTOffset();
1.246 + offset /= 60;
1.247 + if (gmt_isdst) {
1.248 + offset += 60;
1.249 + }
1.250 +
1.251 + return offset;
1.252 +}
1.253 +
1.254 +/*
1.255 + *----------------------------------------------------------------------
1.256 + *
1.257 + * Tcl_GetTime --
1.258 + *
1.259 + * Gets the current system time in seconds and microseconds
1.260 + * since the beginning of the epoch: 00:00 UCT, January 1, 1970.
1.261 + *
1.262 + * Results:
1.263 + * Returns the current time (in the local timezone) in timePtr.
1.264 + *
1.265 + * Side effects:
1.266 + * None.
1.267 + *
1.268 + *----------------------------------------------------------------------
1.269 + */
1.270 +
1.271 +void
1.272 +Tcl_GetTime(
1.273 + Tcl_Time *timePtr) /* Location to store time information. */
1.274 +{
1.275 + UnsignedWide micro;
1.276 +#ifndef NO_LONG_LONG
1.277 + long long *microPtr;
1.278 +#endif
1.279 +
1.280 + if (initalized == false) {
1.281 + GetDateTime(&baseSeconds);
1.282 + /*
1.283 + * Remove the local offset that ReadDateTime() adds.
1.284 + */
1.285 + baseSeconds -= TclpGetGMTOffset() - tcl_mac_epoch_offset;
1.286 + Microseconds(µOffset);
1.287 + initalized = true;
1.288 + }
1.289 +
1.290 + Microseconds(µ);
1.291 +
1.292 +#ifndef NO_LONG_LONG
1.293 + microPtr = (long long *) µ
1.294 + *microPtr -= *((long long *) µOffset);
1.295 + timePtr->sec = baseSeconds + (*microPtr / 1000000);
1.296 + timePtr->usec = *microPtr % 1000000;
1.297 +#else
1.298 + SubtractUnsignedWide(µ, µOffset, µ);
1.299 +
1.300 + /*
1.301 + * This lovely computation is equal to: base + (micro / 1000000)
1.302 + * For the .hi part the ratio of 0x100000000 / 1000000 has been
1.303 + * reduced to avoid overflow. This computation certainly has
1.304 + * problems as the .hi part gets large. However, your application
1.305 + * would have to run for a long time to make that happen.
1.306 + */
1.307 +
1.308 + timePtr->sec = baseSeconds + (micro.lo / 1000000) +
1.309 + (long) (micro.hi * ((double) 33554432.0 / 15625.0));
1.310 + timePtr->usec = micro.lo % 1000000;
1.311 +#endif
1.312 +}
1.313 +
1.314 +/*
1.315 + *----------------------------------------------------------------------
1.316 + *
1.317 + * TclpGetDate --
1.318 + *
1.319 + * Converts raw seconds to a struct tm data structure. The
1.320 + * returned time will be for Greenwich Mean Time if the useGMT flag
1.321 + * is set. Otherwise, the returned time will be for the local
1.322 + * time zone. This function is meant to be used as a replacement
1.323 + * for localtime and gmtime which is broken on most ANSI libs
1.324 + * on the Macintosh.
1.325 + *
1.326 + * Results:
1.327 + * None.
1.328 + *
1.329 + * Side effects:
1.330 + * The passed in struct tm data structure is modified.
1.331 + *
1.332 + *----------------------------------------------------------------------
1.333 + */
1.334 +
1.335 +struct tm *
1.336 +TclpGetDate(
1.337 + TclpTime_t time, /* Time struct to fill. */
1.338 + int useGMT) /* True if date should reflect GNT time. */
1.339 +{
1.340 + const time_t *tp = (const time_t *)time;
1.341 + DateTimeRec dtr;
1.342 + unsigned long offset=0L;
1.343 + static struct tm statictime;
1.344 + static const short monthday[12] =
1.345 + {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
1.346 +
1.347 + if(useGMT)
1.348 + SecondsToDate(*tp - tcl_mac_epoch_offset, &dtr);
1.349 + else
1.350 + SecondsToDate(*tp + TclpGetGMTOffset() - tcl_mac_epoch_offset, &dtr);
1.351 +
1.352 + statictime.tm_sec = dtr.second;
1.353 + statictime.tm_min = dtr.minute;
1.354 + statictime.tm_hour = dtr.hour;
1.355 + statictime.tm_mday = dtr.day;
1.356 + statictime.tm_mon = dtr.month - 1;
1.357 + statictime.tm_year = dtr.year - 1900;
1.358 + statictime.tm_wday = dtr.dayOfWeek - 1;
1.359 + statictime.tm_yday = monthday[statictime.tm_mon]
1.360 + + statictime.tm_mday - 1;
1.361 + if (1 < statictime.tm_mon && !(statictime.tm_year & 3)) {
1.362 + ++statictime.tm_yday;
1.363 + }
1.364 + if(useGMT)
1.365 + statictime.tm_isdst = 0;
1.366 + else
1.367 + statictime.tm_isdst = gmt_isdst;
1.368 + gmt_lastGetDateUseGMT=useGMT; /* hack to make TclpGetTZName below work */
1.369 + return(&statictime);
1.370 +}
1.371 +
1.372 +/*
1.373 + *----------------------------------------------------------------------
1.374 + *
1.375 + * TclpGetTZName --
1.376 + *
1.377 + * Gets the current timezone string.
1.378 + *
1.379 + * Results:
1.380 + * Returns a pointer to a static string, or NULL on failure.
1.381 + *
1.382 + * Side effects:
1.383 + * None.
1.384 + *
1.385 + *----------------------------------------------------------------------
1.386 + */
1.387 +
1.388 +char *
1.389 +TclpGetTZName(int dst)
1.390 +{
1.391 + register TABLE *tp;
1.392 + long zonevalue=-TclpGetGMTOffset();
1.393 +
1.394 + if (gmt_isdst)
1.395 + zonevalue += HOUR(1);
1.396 +
1.397 + if(gmt_lastGetDateUseGMT) /* hack: if last TclpGetDate was called */
1.398 + zonevalue=0; /* with useGMT==1 then we're using GMT */
1.399 +
1.400 + for (tp = invTimezoneTable; tp->name; tp++) {
1.401 + if ((tp->value == zonevalue) && (tp->type == dst)) break;
1.402 + }
1.403 + if(!tp->name)
1.404 + tp = invTimezoneTable; /* default to unknown */
1.405 +
1.406 + return tp->name;
1.407 +}
1.408 +
1.409 +#ifdef NO_LONG_LONG
1.410 +/*
1.411 + *----------------------------------------------------------------------
1.412 + *
1.413 + * SubtractUnsignedWide --
1.414 + *
1.415 + * Subtracts one UnsignedWide value from another.
1.416 + *
1.417 + * Results:
1.418 + * The subtracted value.
1.419 + *
1.420 + * Side effects:
1.421 + * None.
1.422 + *
1.423 + *----------------------------------------------------------------------
1.424 + */
1.425 +
1.426 +static void
1.427 +SubtractUnsignedWide(
1.428 + UnsignedWide *x, /* Ptr to wide int. */
1.429 + UnsignedWide *y, /* Ptr to wide int. */
1.430 + UnsignedWide *result) /* Ptr to result. */
1.431 +{
1.432 + result->hi = x->hi - y->hi;
1.433 + if (x->lo < y->lo) {
1.434 + result->hi--;
1.435 + }
1.436 + result->lo = x->lo - y->lo;
1.437 +}
1.438 +#endif