home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Tcl-Tk 8.0 / Pre-installed version / tcl8.0 / mac / tclMacTime.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-15  |  7.4 KB  |  313 lines  |  [TEXT/CWIE]

  1. /* 
  2.  * tclMacTime.c --
  3.  *
  4.  *    Contains Macintosh specific versions of Tcl functions that
  5.  *    obtain time values from the operating system.
  6.  *
  7.  * Copyright (c) 1995-1997 Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  *
  12.  * SCCS: @(#) tclMacTime.c 1.19 97/06/27 13:07:10
  13.  */
  14.  
  15. #include "tclInt.h"
  16. #include "tclPort.h"
  17. #include <OSUtils.h>
  18. #include <Timer.h>
  19. #include <time.h>
  20.  
  21. /*
  22.  * Static variables used by the TclpGetTime function.
  23.  */
  24.  
  25. static int initalized = false;
  26. static unsigned long baseSeconds;
  27. static UnsignedWide microOffset;
  28.  
  29. /*
  30.  * Prototypes for procedures that are private to this file:
  31.  */
  32.  
  33. static void SubtractUnsignedWide _ANSI_ARGS_((UnsignedWide *x,
  34.     UnsignedWide *y, UnsignedWide *result));
  35.  
  36. /*
  37.  *-----------------------------------------------------------------------------
  38.  *
  39.  * TclpGetSeconds --
  40.  *
  41.  *    This procedure returns the number of seconds from the epoch.  On
  42.  *    the Macintosh the epoch is Midnight Jan 1, 1904.  Unfortunatly,
  43.  *    the Macintosh doesn't tie the epoch to a particular time zone.  For
  44.  *    Tcl we tie the epoch to GMT.  This makes the time zone date parsing
  45.  *    code work.  The epoch for Mac-Tcl is: Midnight Jan 1, 1904 GMT.
  46.  *
  47.  * Results:
  48.  *    Number of seconds from the epoch in GMT.
  49.  *
  50.  * Side effects:
  51.  *    None.
  52.  *
  53.  *-----------------------------------------------------------------------------
  54.  */
  55.  
  56. unsigned long
  57. TclpGetSeconds()
  58. {
  59.     unsigned long seconds;
  60.     MachineLocation loc;
  61.     long int offset;
  62.     
  63.     ReadLocation(&loc);
  64.     offset = loc.u.gmtDelta & 0x00ffffff;
  65.     if (offset & 0x00800000) {
  66.     offset = offset | 0xff000000;
  67.     }
  68.  
  69.     if (ReadDateTime(&seconds) == noErr) {
  70.     return (seconds - offset);
  71.     } else {
  72.     panic("Can't get time.");
  73.     return 0;
  74.     }
  75. }
  76.  
  77. /*
  78.  *-----------------------------------------------------------------------------
  79.  *
  80.  * TclpGetClicks --
  81.  *
  82.  *    This procedure returns a value that represents the highest resolution
  83.  *    clock available on the system.  There are no garantees on what the
  84.  *    resolution will be.  In Tcl we will call this value a "click".  The
  85.  *    start time is also system dependant.
  86.  *
  87.  * Results:
  88.  *    Number of clicks from some start time.
  89.  *
  90.  * Side effects:
  91.  *    None.
  92.  *
  93.  *-----------------------------------------------------------------------------
  94.  */
  95.  
  96. unsigned long
  97. TclpGetClicks()
  98. {
  99.     UnsignedWide micros;
  100.  
  101.     Microseconds(µs);
  102.     return micros.lo;
  103. }
  104.  
  105. /*
  106.  *----------------------------------------------------------------------
  107.  *
  108.  * TclpGetTimeZone --
  109.  *
  110.  *    Get the current time zone.
  111.  *
  112.  * Results:
  113.  *    The return value is the local time zone, measured in
  114.  *    minutes away from GMT (-ve for east, +ve for west).
  115.  *
  116.  * Side effects:
  117.  *    None.
  118.  *
  119.  *----------------------------------------------------------------------
  120.  */
  121.  
  122. int
  123. TclpGetTimeZone (
  124.     unsigned long  currentTime)        /* Ignored on Mac. */
  125. {
  126.     MachineLocation loc;
  127.     long int offset;
  128.  
  129.     ReadLocation(&loc);
  130.     offset = loc.u.gmtDelta & 0x00ffffff;
  131.     if (offset & 0x00700000) {
  132.     offset |= 0xff000000;
  133.     }
  134.  
  135.     /*
  136.      * Convert the Mac offset from seconds to minutes and
  137.      * add an hour if we have daylight savings time.
  138.      */
  139.     offset = -offset;
  140.     offset /= 60;
  141.     if (loc.u.dlsDelta < 0) {
  142.     offset += 60;
  143.     }
  144.     
  145.     return offset;
  146. }
  147.  
  148. /*
  149.  *----------------------------------------------------------------------
  150.  *
  151.  * TclpGetTime --
  152.  *
  153.  *    Gets the current system time in seconds and microseconds
  154.  *    since the beginning of the epoch: 00:00 UCT, January 1, 1970.
  155.  *
  156.  * Results:
  157.  *    Returns the current time (in the local timezone) in timePtr.
  158.  *
  159.  * Side effects:
  160.  *    None.
  161.  *
  162.  *----------------------------------------------------------------------
  163.  */
  164.  
  165. void
  166. TclpGetTime(
  167.     Tcl_Time *timePtr)        /* Location to store time information. */
  168. {
  169.     UnsignedWide micro;
  170. #ifndef NO_LONG_LONG
  171.     long long *microPtr;
  172. #endif
  173.     
  174.     if (initalized == false) {
  175.         MachineLocation loc;
  176.         long int offset;
  177.     
  178.         ReadLocation(&loc);
  179.         offset = loc.u.gmtDelta & 0x00ffffff;
  180.         if (offset & 0x00800000) {
  181.             offset = offset | 0xff000000;
  182.     }
  183.     if (ReadDateTime(&baseSeconds) != noErr) {
  184.         /*
  185.          * This should never happen!
  186.          */
  187.         return;
  188.     }
  189.     /*
  190.      * Remove the local offset that ReadDateTime() adds.
  191.      */
  192.     baseSeconds -= offset;
  193.     Microseconds(µOffset);
  194.     initalized = true;
  195.     }
  196.  
  197.     Microseconds(µ);
  198.  
  199. #ifndef NO_LONG_LONG
  200.     microPtr = (long long *) µ
  201.     *microPtr -= *((long long *) µOffset);
  202.     timePtr->sec = baseSeconds + (*microPtr / 1000000);
  203.     timePtr->usec = *microPtr % 1000000;
  204. #else
  205.     SubtractUnsignedWide(µ, µOffset, µ);
  206.  
  207.     /*
  208.      * This lovely computation is equal to: base + (micro / 1000000)
  209.      * For the .hi part the ratio of 0x100000000 / 1000000 has been
  210.      * reduced to avoid overflow.  This computation certainly has 
  211.      * problems as the .hi part gets large.  However, your application
  212.      * would have to run for a long time to make that happen.
  213.      */
  214.  
  215.     timePtr->sec = baseSeconds + (micro.lo / 1000000) + 
  216.         (long) (micro.hi * ((double) 33554432.0 / 15625.0));
  217.     timePtr->usec = micro.lo % 1000000;
  218. #endif
  219. }
  220.  
  221. /*
  222.  *----------------------------------------------------------------------
  223.  *
  224.  * TclpGetDate --
  225.  *
  226.  *    Converts raw seconds to a struct tm data structure.  The
  227.  *    returned time will be for Greenwich Mean Time if the useGMT flag 
  228.  *    is set.  Otherwise, the returned time will be for the local
  229.  *    time zone.  This function is meant to be used as a replacement
  230.  *    for localtime and gmtime which is broken on most ANSI libs
  231.  *    on the Macintosh.
  232.  *
  233.  * Results:
  234.  *    None.
  235.  *
  236.  * Side effects:
  237.  *      The passed in struct tm data structure is modified.
  238.  *
  239.  *----------------------------------------------------------------------
  240.  */
  241.  
  242. struct tm *
  243. TclpGetDate(
  244.     const time_t *tp,    /* Time struct to fill. */
  245.     int useGMT)        /* True if date should reflect GNT time. */
  246. {
  247.     DateTimeRec dtr;
  248.     MachineLocation loc;
  249.     long int offset;
  250.     static struct tm statictime;
  251.     static const short monthday[12] =
  252.         {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
  253.  
  254.     ReadLocation(&loc);
  255.     
  256.     if (useGMT) {
  257.     SecondsToDate(*tp, &dtr);
  258.     } else {
  259.     offset = loc.u.gmtDelta & 0x00ffffff;
  260.     if (offset & 0x00700000) {
  261.         offset |= 0xff000000;
  262.     }
  263.     
  264.     SecondsToDate(*tp + offset, &dtr);
  265.     }
  266.  
  267.     statictime.tm_sec = dtr.second;
  268.     statictime.tm_min = dtr.minute;
  269.     statictime.tm_hour = dtr.hour;
  270.     statictime.tm_mday = dtr.day;
  271.     statictime.tm_mon = dtr.month - 1;
  272.     statictime.tm_year = dtr.year - 1900;
  273.     statictime.tm_wday = dtr.dayOfWeek - 1;
  274.     statictime.tm_yday = monthday[statictime.tm_mon]
  275.     + statictime.tm_mday - 1;
  276.     if (1 < statictime.tm_mon && !(statictime.tm_year & 3)) {
  277.     ++statictime.tm_yday;
  278.     }
  279.     statictime.tm_isdst = loc.u.dlsDelta;
  280.     return(&statictime);
  281. }
  282.  
  283. #ifdef NO_LONG_LONG
  284. /*
  285.  *----------------------------------------------------------------------
  286.  *
  287.  * SubtractUnsignedWide --
  288.  *
  289.  *    Subtracts one UnsignedWide value from another.
  290.  *
  291.  * Results:
  292.  *      The subtracted value.
  293.  *
  294.  * Side effects:
  295.  *    None.
  296.  *
  297.  *----------------------------------------------------------------------
  298.  */
  299.  
  300. static void
  301. SubtractUnsignedWide(
  302.     UnsignedWide *x,        /* Ptr to wide int. */
  303.     UnsignedWide *y,        /* Ptr to wide int. */
  304.     UnsignedWide *result)    /* Ptr to result. */
  305. {
  306.     result->hi = x->hi - y->hi;
  307.     if (x->lo < y->lo) {
  308.     result->hi--;
  309.     }
  310.     result->lo = x->lo - y->lo;
  311. }
  312. #endif
  313.