/*
|
/*
|
* tclMacTime.c --
|
* tclMacTime.c --
|
*
|
*
|
* Contains Macintosh specific versions of Tcl functions that
|
* Contains Macintosh specific versions of Tcl functions that
|
* obtain time values from the operating system.
|
* obtain time values from the operating system.
|
*
|
*
|
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
|
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
|
*
|
*
|
* See the file "license.terms" for information on usage and redistribution
|
* See the file "license.terms" for information on usage and redistribution
|
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
*
|
*
|
* RCS: @(#) $Id: tclMacTime.c,v 1.1.1.1 2002-01-16 10:25:35 markom Exp $
|
* RCS: @(#) $Id: tclMacTime.c,v 1.1.1.1 2002-01-16 10:25:35 markom Exp $
|
*/
|
*/
|
|
|
#include "tclInt.h"
|
#include "tclInt.h"
|
#include "tclPort.h"
|
#include "tclPort.h"
|
#include <OSUtils.h>
|
#include <OSUtils.h>
|
#include <Timer.h>
|
#include <Timer.h>
|
#include <time.h>
|
#include <time.h>
|
|
|
/*
|
/*
|
* Static variables used by the TclpGetTime function.
|
* Static variables used by the TclpGetTime function.
|
*/
|
*/
|
|
|
static int initalized = false;
|
static int initalized = false;
|
static unsigned long baseSeconds;
|
static unsigned long baseSeconds;
|
static UnsignedWide microOffset;
|
static UnsignedWide microOffset;
|
|
|
/*
|
/*
|
* Prototypes for procedures that are private to this file:
|
* Prototypes for procedures that are private to this file:
|
*/
|
*/
|
|
|
static void SubtractUnsignedWide _ANSI_ARGS_((UnsignedWide *x,
|
static void SubtractUnsignedWide _ANSI_ARGS_((UnsignedWide *x,
|
UnsignedWide *y, UnsignedWide *result));
|
UnsignedWide *y, UnsignedWide *result));
|
|
|
/*
|
/*
|
*-----------------------------------------------------------------------------
|
*-----------------------------------------------------------------------------
|
*
|
*
|
* TclpGetSeconds --
|
* TclpGetSeconds --
|
*
|
*
|
* This procedure returns the number of seconds from the epoch. On
|
* This procedure returns the number of seconds from the epoch. On
|
* the Macintosh the epoch is Midnight Jan 1, 1904. Unfortunatly,
|
* the Macintosh the epoch is Midnight Jan 1, 1904. Unfortunatly,
|
* the Macintosh doesn't tie the epoch to a particular time zone. For
|
* the Macintosh doesn't tie the epoch to a particular time zone. For
|
* Tcl we tie the epoch to GMT. This makes the time zone date parsing
|
* Tcl we tie the epoch to GMT. This makes the time zone date parsing
|
* code work. The epoch for Mac-Tcl is: Midnight Jan 1, 1904 GMT.
|
* code work. The epoch for Mac-Tcl is: Midnight Jan 1, 1904 GMT.
|
*
|
*
|
* Results:
|
* Results:
|
* Number of seconds from the epoch in GMT.
|
* Number of seconds from the epoch in GMT.
|
*
|
*
|
* Side effects:
|
* Side effects:
|
* None.
|
* None.
|
*
|
*
|
*-----------------------------------------------------------------------------
|
*-----------------------------------------------------------------------------
|
*/
|
*/
|
|
|
unsigned long
|
unsigned long
|
TclpGetSeconds()
|
TclpGetSeconds()
|
{
|
{
|
unsigned long seconds;
|
unsigned long seconds;
|
MachineLocation loc;
|
MachineLocation loc;
|
long int offset;
|
long int offset;
|
|
|
ReadLocation(&loc);
|
ReadLocation(&loc);
|
offset = loc.u.gmtDelta & 0x00ffffff;
|
offset = loc.u.gmtDelta & 0x00ffffff;
|
if (offset & 0x00800000) {
|
if (offset & 0x00800000) {
|
offset = offset | 0xff000000;
|
offset = offset | 0xff000000;
|
}
|
}
|
|
|
if (ReadDateTime(&seconds) == noErr) {
|
if (ReadDateTime(&seconds) == noErr) {
|
return (seconds - offset);
|
return (seconds - offset);
|
} else {
|
} else {
|
panic("Can't get time.");
|
panic("Can't get time.");
|
return 0;
|
return 0;
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
*-----------------------------------------------------------------------------
|
*-----------------------------------------------------------------------------
|
*
|
*
|
* TclpGetClicks --
|
* TclpGetClicks --
|
*
|
*
|
* This procedure returns a value that represents the highest resolution
|
* This procedure returns a value that represents the highest resolution
|
* clock available on the system. There are no garantees on what the
|
* 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
|
* resolution will be. In Tcl we will call this value a "click". The
|
* start time is also system dependant.
|
* start time is also system dependant.
|
*
|
*
|
* Results:
|
* Results:
|
* Number of clicks from some start time.
|
* Number of clicks from some start time.
|
*
|
*
|
* Side effects:
|
* Side effects:
|
* None.
|
* None.
|
*
|
*
|
*-----------------------------------------------------------------------------
|
*-----------------------------------------------------------------------------
|
*/
|
*/
|
|
|
unsigned long
|
unsigned long
|
TclpGetClicks()
|
TclpGetClicks()
|
{
|
{
|
UnsignedWide micros;
|
UnsignedWide micros;
|
|
|
Microseconds(µs);
|
Microseconds(µs);
|
return micros.lo;
|
return micros.lo;
|
}
|
}
|
|
|
/*
|
/*
|
*----------------------------------------------------------------------
|
*----------------------------------------------------------------------
|
*
|
*
|
* TclpGetTimeZone --
|
* TclpGetTimeZone --
|
*
|
*
|
* Get the current time zone.
|
* Get the current time zone.
|
*
|
*
|
* Results:
|
* Results:
|
* The return value is the local time zone, measured in
|
* The return value is the local time zone, measured in
|
* minutes away from GMT (-ve for east, +ve for west).
|
* minutes away from GMT (-ve for east, +ve for west).
|
*
|
*
|
* Side effects:
|
* Side effects:
|
* None.
|
* None.
|
*
|
*
|
*----------------------------------------------------------------------
|
*----------------------------------------------------------------------
|
*/
|
*/
|
|
|
int
|
int
|
TclpGetTimeZone (
|
TclpGetTimeZone (
|
unsigned long currentTime) /* Ignored on Mac. */
|
unsigned long currentTime) /* Ignored on Mac. */
|
{
|
{
|
MachineLocation loc;
|
MachineLocation loc;
|
long int offset;
|
long int offset;
|
|
|
ReadLocation(&loc);
|
ReadLocation(&loc);
|
offset = loc.u.gmtDelta & 0x00ffffff;
|
offset = loc.u.gmtDelta & 0x00ffffff;
|
if (offset & 0x00700000) {
|
if (offset & 0x00700000) {
|
offset |= 0xff000000;
|
offset |= 0xff000000;
|
}
|
}
|
|
|
/*
|
/*
|
* Convert the Mac offset from seconds to minutes and
|
* Convert the Mac offset from seconds to minutes and
|
* add an hour if we have daylight savings time.
|
* add an hour if we have daylight savings time.
|
*/
|
*/
|
offset = -offset;
|
offset = -offset;
|
offset /= 60;
|
offset /= 60;
|
if (loc.u.dlsDelta < 0) {
|
if (loc.u.dlsDelta < 0) {
|
offset += 60;
|
offset += 60;
|
}
|
}
|
|
|
return offset;
|
return offset;
|
}
|
}
|
|
|
/*
|
/*
|
*----------------------------------------------------------------------
|
*----------------------------------------------------------------------
|
*
|
*
|
* TclpGetTime --
|
* TclpGetTime --
|
*
|
*
|
* Gets the current system time in seconds and microseconds
|
* Gets the current system time in seconds and microseconds
|
* since the beginning of the epoch: 00:00 UCT, January 1, 1970.
|
* since the beginning of the epoch: 00:00 UCT, January 1, 1970.
|
*
|
*
|
* Results:
|
* Results:
|
* Returns the current time (in the local timezone) in timePtr.
|
* Returns the current time (in the local timezone) in timePtr.
|
*
|
*
|
* Side effects:
|
* Side effects:
|
* None.
|
* None.
|
*
|
*
|
*----------------------------------------------------------------------
|
*----------------------------------------------------------------------
|
*/
|
*/
|
|
|
void
|
void
|
TclpGetTime(
|
TclpGetTime(
|
Tcl_Time *timePtr) /* Location to store time information. */
|
Tcl_Time *timePtr) /* Location to store time information. */
|
{
|
{
|
UnsignedWide micro;
|
UnsignedWide micro;
|
#ifndef NO_LONG_LONG
|
#ifndef NO_LONG_LONG
|
long long *microPtr;
|
long long *microPtr;
|
#endif
|
#endif
|
|
|
if (initalized == false) {
|
if (initalized == false) {
|
MachineLocation loc;
|
MachineLocation loc;
|
long int offset;
|
long int offset;
|
|
|
ReadLocation(&loc);
|
ReadLocation(&loc);
|
offset = loc.u.gmtDelta & 0x00ffffff;
|
offset = loc.u.gmtDelta & 0x00ffffff;
|
if (offset & 0x00800000) {
|
if (offset & 0x00800000) {
|
offset = offset | 0xff000000;
|
offset = offset | 0xff000000;
|
}
|
}
|
if (ReadDateTime(&baseSeconds) != noErr) {
|
if (ReadDateTime(&baseSeconds) != noErr) {
|
/*
|
/*
|
* This should never happen!
|
* This should never happen!
|
*/
|
*/
|
return;
|
return;
|
}
|
}
|
/*
|
/*
|
* Remove the local offset that ReadDateTime() adds.
|
* Remove the local offset that ReadDateTime() adds.
|
*/
|
*/
|
baseSeconds -= offset;
|
baseSeconds -= offset;
|
Microseconds(µOffset);
|
Microseconds(µOffset);
|
initalized = true;
|
initalized = true;
|
}
|
}
|
|
|
Microseconds(µ);
|
Microseconds(µ);
|
|
|
#ifndef NO_LONG_LONG
|
#ifndef NO_LONG_LONG
|
microPtr = (long long *) µ
|
microPtr = (long long *) µ
|
*microPtr -= *((long long *) µOffset);
|
*microPtr -= *((long long *) µOffset);
|
timePtr->sec = baseSeconds + (*microPtr / 1000000);
|
timePtr->sec = baseSeconds + (*microPtr / 1000000);
|
timePtr->usec = *microPtr % 1000000;
|
timePtr->usec = *microPtr % 1000000;
|
#else
|
#else
|
SubtractUnsignedWide(µ, µOffset, µ);
|
SubtractUnsignedWide(µ, µOffset, µ);
|
|
|
/*
|
/*
|
* This lovely computation is equal to: base + (micro / 1000000)
|
* This lovely computation is equal to: base + (micro / 1000000)
|
* For the .hi part the ratio of 0x100000000 / 1000000 has been
|
* For the .hi part the ratio of 0x100000000 / 1000000 has been
|
* reduced to avoid overflow. This computation certainly has
|
* reduced to avoid overflow. This computation certainly has
|
* problems as the .hi part gets large. However, your application
|
* problems as the .hi part gets large. However, your application
|
* would have to run for a long time to make that happen.
|
* would have to run for a long time to make that happen.
|
*/
|
*/
|
|
|
timePtr->sec = baseSeconds + (micro.lo / 1000000) +
|
timePtr->sec = baseSeconds + (micro.lo / 1000000) +
|
(long) (micro.hi * ((double) 33554432.0 / 15625.0));
|
(long) (micro.hi * ((double) 33554432.0 / 15625.0));
|
timePtr->usec = micro.lo % 1000000;
|
timePtr->usec = micro.lo % 1000000;
|
#endif
|
#endif
|
}
|
}
|
|
|
/*
|
/*
|
*----------------------------------------------------------------------
|
*----------------------------------------------------------------------
|
*
|
*
|
* TclpGetDate --
|
* TclpGetDate --
|
*
|
*
|
* Converts raw seconds to a struct tm data structure. The
|
* Converts raw seconds to a struct tm data structure. The
|
* returned time will be for Greenwich Mean Time if the useGMT flag
|
* returned time will be for Greenwich Mean Time if the useGMT flag
|
* is set. Otherwise, the returned time will be for the local
|
* is set. Otherwise, the returned time will be for the local
|
* time zone. This function is meant to be used as a replacement
|
* time zone. This function is meant to be used as a replacement
|
* for localtime and gmtime which is broken on most ANSI libs
|
* for localtime and gmtime which is broken on most ANSI libs
|
* on the Macintosh.
|
* on the Macintosh.
|
*
|
*
|
* Results:
|
* Results:
|
* None.
|
* None.
|
*
|
*
|
* Side effects:
|
* Side effects:
|
* The passed in struct tm data structure is modified.
|
* The passed in struct tm data structure is modified.
|
*
|
*
|
*----------------------------------------------------------------------
|
*----------------------------------------------------------------------
|
*/
|
*/
|
|
|
struct tm *
|
struct tm *
|
TclpGetDate(
|
TclpGetDate(
|
const time_t *tp, /* Time struct to fill. */
|
const time_t *tp, /* Time struct to fill. */
|
int useGMT) /* True if date should reflect GNT time. */
|
int useGMT) /* True if date should reflect GNT time. */
|
{
|
{
|
DateTimeRec dtr;
|
DateTimeRec dtr;
|
MachineLocation loc;
|
MachineLocation loc;
|
long int offset;
|
long int offset;
|
static struct tm statictime;
|
static struct tm statictime;
|
static const short monthday[12] =
|
static const short monthday[12] =
|
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
|
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
|
|
|
ReadLocation(&loc);
|
ReadLocation(&loc);
|
|
|
if (useGMT) {
|
if (useGMT) {
|
SecondsToDate(*tp, &dtr);
|
SecondsToDate(*tp, &dtr);
|
} else {
|
} else {
|
offset = loc.u.gmtDelta & 0x00ffffff;
|
offset = loc.u.gmtDelta & 0x00ffffff;
|
if (offset & 0x00700000) {
|
if (offset & 0x00700000) {
|
offset |= 0xff000000;
|
offset |= 0xff000000;
|
}
|
}
|
|
|
SecondsToDate(*tp + offset, &dtr);
|
SecondsToDate(*tp + offset, &dtr);
|
}
|
}
|
|
|
statictime.tm_sec = dtr.second;
|
statictime.tm_sec = dtr.second;
|
statictime.tm_min = dtr.minute;
|
statictime.tm_min = dtr.minute;
|
statictime.tm_hour = dtr.hour;
|
statictime.tm_hour = dtr.hour;
|
statictime.tm_mday = dtr.day;
|
statictime.tm_mday = dtr.day;
|
statictime.tm_mon = dtr.month - 1;
|
statictime.tm_mon = dtr.month - 1;
|
statictime.tm_year = dtr.year - 1900;
|
statictime.tm_year = dtr.year - 1900;
|
statictime.tm_wday = dtr.dayOfWeek - 1;
|
statictime.tm_wday = dtr.dayOfWeek - 1;
|
statictime.tm_yday = monthday[statictime.tm_mon]
|
statictime.tm_yday = monthday[statictime.tm_mon]
|
+ statictime.tm_mday - 1;
|
+ statictime.tm_mday - 1;
|
if (1 < statictime.tm_mon && !(statictime.tm_year & 3)) {
|
if (1 < statictime.tm_mon && !(statictime.tm_year & 3)) {
|
++statictime.tm_yday;
|
++statictime.tm_yday;
|
}
|
}
|
statictime.tm_isdst = loc.u.dlsDelta;
|
statictime.tm_isdst = loc.u.dlsDelta;
|
return(&statictime);
|
return(&statictime);
|
}
|
}
|
|
|
#ifdef NO_LONG_LONG
|
#ifdef NO_LONG_LONG
|
/*
|
/*
|
*----------------------------------------------------------------------
|
*----------------------------------------------------------------------
|
*
|
*
|
* SubtractUnsignedWide --
|
* SubtractUnsignedWide --
|
*
|
*
|
* Subtracts one UnsignedWide value from another.
|
* Subtracts one UnsignedWide value from another.
|
*
|
*
|
* Results:
|
* Results:
|
* The subtracted value.
|
* The subtracted value.
|
*
|
*
|
* Side effects:
|
* Side effects:
|
* None.
|
* None.
|
*
|
*
|
*----------------------------------------------------------------------
|
*----------------------------------------------------------------------
|
*/
|
*/
|
|
|
static void
|
static void
|
SubtractUnsignedWide(
|
SubtractUnsignedWide(
|
UnsignedWide *x, /* Ptr to wide int. */
|
UnsignedWide *x, /* Ptr to wide int. */
|
UnsignedWide *y, /* Ptr to wide int. */
|
UnsignedWide *y, /* Ptr to wide int. */
|
UnsignedWide *result) /* Ptr to result. */
|
UnsignedWide *result) /* Ptr to result. */
|
{
|
{
|
result->hi = x->hi - y->hi;
|
result->hi = x->hi - y->hi;
|
if (x->lo < y->lo) {
|
if (x->lo < y->lo) {
|
result->hi--;
|
result->hi--;
|
}
|
}
|
result->lo = x->lo - y->lo;
|
result->lo = x->lo - y->lo;
|
}
|
}
|
#endif
|
#endif
|
|
|