286 lines
6.5 KiB
C
286 lines
6.5 KiB
C
|
/*
|
|||
|
* tclMacTime.c --
|
|||
|
*
|
|||
|
* Contains Macintosh specific versions of Tcl functions that
|
|||
|
* obtain time values from the operating system.
|
|||
|
*
|
|||
|
* Copyright (c) 1995-1996 Sun Microsystems, Inc.
|
|||
|
*
|
|||
|
* See the file "license.terms" for information on usage and redistribution
|
|||
|
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|||
|
*
|
|||
|
* SCCS: @(#) tclMacTime.c 1.13 96/07/25 13:30:46
|
|||
|
*/
|
|||
|
|
|||
|
#include "tclInt.h"
|
|||
|
#include "tclPort.h"
|
|||
|
#include <OSUtils.h>
|
|||
|
#include <Timer.h>
|
|||
|
#include <time.h>
|
|||
|
|
|||
|
/*
|
|||
|
* Static variables used by the TclpGetTime function.
|
|||
|
*/
|
|||
|
|
|||
|
static int initalized = false;
|
|||
|
static unsigned long baseSeconds;
|
|||
|
static UnsignedWide microOffset;
|
|||
|
|
|||
|
/*
|
|||
|
* Prototypes for procedures that are private to this file:
|
|||
|
*/
|
|||
|
|
|||
|
static void SubtractUnsignedWide _ANSI_ARGS_((UnsignedWide *x,
|
|||
|
UnsignedWide *y, UnsignedWide *result));
|
|||
|
|
|||
|
/*
|
|||
|
*-----------------------------------------------------------------------------
|
|||
|
*
|
|||
|
* TclpGetSeconds --
|
|||
|
*
|
|||
|
* This procedure returns the number of seconds from the epoch. On
|
|||
|
* the Macintosh the epoch is Midnight Jan 1, 1904. Unfortunatly,
|
|||
|
* the Macintosh doesn't tie the epoch to a paticular time zone. For
|
|||
|
* 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.
|
|||
|
*
|
|||
|
* Results:
|
|||
|
* Number of seconds from the epoch.
|
|||
|
*
|
|||
|
* Side effects:
|
|||
|
* None.
|
|||
|
*
|
|||
|
*-----------------------------------------------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
unsigned long
|
|||
|
TclpGetSeconds()
|
|||
|
{
|
|||
|
unsigned long seconds;
|
|||
|
MachineLocation loc;
|
|||
|
long int offset;
|
|||
|
|
|||
|
ReadLocation(&loc);
|
|||
|
offset = loc.u.gmtDelta & 0x00ffffff;
|
|||
|
if (offset & 0x00800000) {
|
|||
|
offset = offset | 0xff000000;
|
|||
|
}
|
|||
|
|
|||
|
if (ReadDateTime(&seconds) == noErr) {
|
|||
|
return (seconds + offset);
|
|||
|
} else {
|
|||
|
panic("Can't get time.");
|
|||
|
return 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
*-----------------------------------------------------------------------------
|
|||
|
*
|
|||
|
* 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()
|
|||
|
{
|
|||
|
UnsignedWide micros;
|
|||
|
|
|||
|
Microseconds(µs);
|
|||
|
return micros.lo;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*
|
|||
|
* TclpGetTimeZone --
|
|||
|
*
|
|||
|
* Get the current time zone.
|
|||
|
*
|
|||
|
* Results:
|
|||
|
* Minutes east of GMT.
|
|||
|
*
|
|||
|
* Side effects:
|
|||
|
* None.
|
|||
|
*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
int
|
|||
|
TclpGetTimeZone (currentTime)
|
|||
|
unsigned long currentTime;
|
|||
|
{
|
|||
|
MachineLocation loc;
|
|||
|
long int offset;
|
|||
|
|
|||
|
ReadLocation(&loc);
|
|||
|
offset = loc.u.gmtDelta & 0x00ffffff;
|
|||
|
if (offset & 0x00700000) {
|
|||
|
offset |= 0xff000000;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* Convert the Mac offset from seconds to minutes and
|
|||
|
* add an hour if we have daylight savings time.
|
|||
|
*/
|
|||
|
offset /= 60;
|
|||
|
if (loc.u.dlsDelta < 0) {
|
|||
|
offset += 60;
|
|||
|
}
|
|||
|
|
|||
|
return offset;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*
|
|||
|
* TclpGetTime --
|
|||
|
*
|
|||
|
* 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.
|
|||
|
*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
void
|
|||
|
TclpGetTime(timePtr)
|
|||
|
Tcl_Time *timePtr; /* Location to store time information. */
|
|||
|
{
|
|||
|
UnsignedWide micro;
|
|||
|
|
|||
|
if (initalized == false) {
|
|||
|
if (ReadDateTime(&baseSeconds) != noErr) {
|
|||
|
/*
|
|||
|
* This should never happen!
|
|||
|
*/
|
|||
|
return;
|
|||
|
}
|
|||
|
Microseconds(µOffset);
|
|||
|
initalized = true;
|
|||
|
}
|
|||
|
|
|||
|
Microseconds(µ);
|
|||
|
SubtractUnsignedWide(µ, µOffset, µ);
|
|||
|
|
|||
|
/*
|
|||
|
* This lovely computation is equal to: base + (micro / 1000000)
|
|||
|
* For the .hi part the ratio of 0x100000000 / 1000000 has been
|
|||
|
* reduced to avoid overflow. This computation certainly has
|
|||
|
* problems as the .hi part gets large. However, your application
|
|||
|
* would have to run for a long time to make that happen.
|
|||
|
*/
|
|||
|
timePtr->sec = baseSeconds + (micro.lo / 1000000) +
|
|||
|
(long) (micro.hi * ((double) 33554432.0 / 15625.0));
|
|||
|
timePtr->usec = micro.lo % 1000000;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*
|
|||
|
* SubtractUnsignedWide --
|
|||
|
*
|
|||
|
* Subtracts one UnsignedWide value from another.
|
|||
|
*
|
|||
|
* Results:
|
|||
|
* The subtracted value.
|
|||
|
*
|
|||
|
* Side effects:
|
|||
|
* None.
|
|||
|
*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
static void
|
|||
|
SubtractUnsignedWide(x, y, result)
|
|||
|
UnsignedWide *x;
|
|||
|
UnsignedWide *y;
|
|||
|
UnsignedWide *result;
|
|||
|
{
|
|||
|
result->hi = x->hi - y->hi;
|
|||
|
if (x->lo < y->lo) {
|
|||
|
result->hi--;
|
|||
|
}
|
|||
|
result->lo = x->lo - y->lo;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*
|
|||
|
* TclpGetDate --
|
|||
|
*
|
|||
|
* Converts raw seconds to a struct tm data structure. The
|
|||
|
* returned time will be for Grenich Mean Time if the useGMT flag
|
|||
|
* is set. Otherwise, the returned time will be for the local
|
|||
|
* time zone. This function is meant to be used as a replacement
|
|||
|
* for localtime and gmtime which is broken on most ANSI libs
|
|||
|
* on the Macintosh.
|
|||
|
*
|
|||
|
* Results:
|
|||
|
* None.
|
|||
|
*
|
|||
|
* Side effects:
|
|||
|
* The passed in struct tm data structure is modified.
|
|||
|
*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
struct tm *
|
|||
|
TclpGetDate(tp, useGMT)
|
|||
|
const time_t *tp;
|
|||
|
int useGMT;
|
|||
|
{
|
|||
|
DateTimeRec dtr;
|
|||
|
MachineLocation loc;
|
|||
|
long int offset;
|
|||
|
static struct tm statictime;
|
|||
|
static const short monthday[12] =
|
|||
|
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
|
|||
|
|
|||
|
ReadLocation(&loc);
|
|||
|
|
|||
|
if (useGMT) {
|
|||
|
SecondsToDate(*tp, &dtr);
|
|||
|
} else {
|
|||
|
offset = loc.u.gmtDelta & 0x00ffffff;
|
|||
|
if (offset & 0x00700000) {
|
|||
|
offset |= 0xff000000;
|
|||
|
}
|
|||
|
|
|||
|
SecondsToDate(*tp - offset, &dtr);
|
|||
|
}
|
|||
|
|
|||
|
statictime.tm_sec = dtr.second;
|
|||
|
statictime.tm_min = dtr.minute;
|
|||
|
statictime.tm_hour = dtr.hour;
|
|||
|
statictime.tm_mday = dtr.day;
|
|||
|
statictime.tm_mon = dtr.month - 1;
|
|||
|
statictime.tm_year = dtr.year - 1900;
|
|||
|
statictime.tm_wday = dtr.dayOfWeek - 1;
|
|||
|
statictime.tm_yday = monthday[statictime.tm_mon]
|
|||
|
+ statictime.tm_mday - 1;
|
|||
|
if (1 < statictime.tm_mon && !(statictime.tm_year & 3)) {
|
|||
|
++statictime.tm_yday;
|
|||
|
}
|
|||
|
statictime.tm_isdst = loc.u.dlsDelta;
|
|||
|
return(&statictime);
|
|||
|
}
|
|||
|
|