Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /****************************************************************************
  2. *
  3. *                            Open Watcom Project
  4. *
  5. *    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
  6. *
  7. *  ========================================================================
  8. *
  9. *    This file contains Original Code and/or Modifications of Original
  10. *    Code as defined in and that are subject to the Sybase Open Watcom
  11. *    Public License version 1.0 (the 'License'). You may not use this file
  12. *    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
  13. *    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
  14. *    provided with the Original Code and Modifications, and is also
  15. *    available at www.sybase.com/developer/opensource.
  16. *
  17. *    The Original Code and all software distributed under the License are
  18. *    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  19. *    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
  20. *    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
  21. *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
  22. *    NON-INFRINGEMENT. Please see the License for the specific language
  23. *    governing rights and limitations under the License.
  24. *
  25. *  ========================================================================
  26. *
  27. * Description:  Platform independent tzset() implementation.
  28. *
  29. ****************************************************************************/
  30.  
  31. #include "variety.h"
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include <limits.h>
  35. #include <time.h>
  36. #include "rtdata.h"
  37. #include "timedata.h"
  38. #include "exitwmsg.h"
  39. #include "_time.h"
  40.  
  41. /*
  42.  * TZSET - sets the values of the variables 'timezone', 'daylight'
  43.  *         and 'tzname' according to the setting of the environment
  44.  *         variable "TZ". The "TZ" variable has the format
  45.  *          :characters
  46.  *              or
  47.  *          <std><offset>[<dst>[<offset>]][,<start>[/<time>],<end>[/<time>]]]
  48.  */
  49.  
  50. //#define TZNAME_MAX    128     /* defined in <limits.h> */
  51.  
  52. struct tm       __start_dst = { /* start of daylight savings */
  53.     0, 0, 2,                    /* M4.1.0/02:00:00 default */
  54.     1, 3, 0,                    /* i.e., 1st Sunday of Apr */
  55.     0, 0, 0
  56. };
  57.  
  58. struct tm       __end_dst = {   /* end of daylight savings */
  59.     0, 0, 1,                    /* M10.5.0/02:00:00 default */
  60.     5, 9, 0,                    /* i.e., last Sunday of Oct */
  61.     0, 0, 0                     /* note that this is specified*/
  62. };                              /* in terms of EST */
  63. /* i.e. 02:00 EDT == 01:00 EST*/
  64.  
  65. static char     stzone[TZNAME_MAX + 1] = "EST";       /* place to store names */
  66. static char     dtzone[TZNAME_MAX + 1] = "EDT";       /* place to store names */
  67.  
  68. _WCRTLINKD char *tzname[2] = { stzone, dtzone };
  69.  
  70. _WCRTLINKD long timezone = 5L * 60L * 60L;      /* seconds from GMT */
  71. _WCRTLINKD int  daylight = 1;                   /* d.s.t. indicator */
  72. int             __dst_adjust = 60 * 60;         /* daylight adjustment */
  73.  
  74. static struct {
  75.     unsigned    cache_OS_TZ : 1;
  76.     unsigned    have_OS_TZ : 1;
  77. }               tzFlag = { 1, 0 };
  78.  
  79. int __DontCacheOSTZ( void )
  80. /*************************/
  81. {
  82.     int old_flag;
  83.  
  84.     old_flag           = tzFlag.cache_OS_TZ;
  85.     tzFlag.cache_OS_TZ = 0;
  86.     tzFlag.have_OS_TZ  = 0;
  87.     return( old_flag );
  88. }
  89.  
  90. int __CacheOSTZ( void )
  91. /*********************/
  92. {
  93.     int old_flag;
  94.  
  95.     old_flag           = tzFlag.cache_OS_TZ;
  96.     tzFlag.cache_OS_TZ = 1;
  97.     tzFlag.have_OS_TZ  = 0;
  98.     return( old_flag );
  99. }
  100.  
  101. static char *parse_time( char *tz, int *val )
  102. /*******************************************/
  103. {
  104.     int value;
  105.  
  106.     value = 0;
  107.     while( *tz >= '0' && *tz <= '9' ) {
  108.         value = value * 10 + *tz - '0';
  109.         ++tz;
  110.     }
  111.     *val = value;
  112.     return( tz );
  113. }
  114.  
  115. static char *parse_offset( char *tz, char *name, long *offset )
  116. /*************************************************************/
  117. {
  118.     int         hours;
  119.     int         minutes;
  120.     int         seconds;
  121.     int         neg;
  122.     int         len;
  123.     char        ch;
  124.     char const  *tzstart;
  125.  
  126.     if( *tz == ':' )
  127.         tz++;
  128.     /* remember where time zone name string begins */
  129.     tzstart = tz;
  130.     /* parse time zone name (should be 3 or more characters) */
  131.     /* examples:    PST8, EDT+6, Central Standard Time+7:00:00 */
  132.     for( ;; ) {
  133.         ch = *tz;
  134.         if( ch == '\0' )
  135.             break;
  136.         if( ch == ',' )
  137.             break;
  138.         if( ch == '-' )
  139.             break;
  140.         if( ch == '+' )
  141.             break;
  142.         if( ch >= '0' && ch <= '9' )
  143.             break;
  144.         ++tz;
  145.     }
  146.     len = tz - tzstart;
  147.     if( len > TZNAME_MAX )
  148.         len = TZNAME_MAX;
  149.     memcpy( name, tzstart, ( size_t ) len );
  150.     name[len] = '\0';
  151.  
  152.     neg = 0;
  153.     if( ch == '-' ) {
  154.         neg = 1;
  155.         ++tz;
  156.     } else if( ch == '+' )
  157.         ++tz;
  158.     ch = *tz;
  159.     if( ch >= '0' && ch <= '9' ) {
  160.         hours = minutes = seconds = 0;
  161.         tz = parse_time( tz, &hours );
  162.         if( *tz == ':' ) {
  163.             tz = parse_time( tz + 1, &minutes );
  164.             if( *tz == ':' )
  165.                 tz = parse_time( tz + 1, &seconds );
  166.         }
  167.         *offset = seconds + ( ( minutes + ( hours * 60 ) ) * 60L );
  168.         if( neg )
  169.             *offset = -*offset;
  170.     }
  171.     return( tz );
  172. }
  173.  
  174. static char *parse_rule( char *tz, struct tm *timeptr )
  175. /*****************************************************/
  176. {
  177.     int         date_form;
  178.     int         days;
  179.     int         hours;
  180.     int         minutes;
  181.     int         seconds;
  182.  
  183.     date_form = -1;                         /* n  0-365 */
  184.     if( *tz == 'J' ) { /* Jn 1-365 (no leap days) */
  185.         date_form = 1;
  186.         tz++;
  187.     }
  188.     if( *tz == 'M' ) { /* Mm.n.d n'th day of month */
  189.         date_form = 0;
  190.         tz++;
  191.     }
  192.     timeptr->tm_isdst = date_form;
  193.     tz = parse_time( tz, &days );
  194.     if( date_form != 0 )
  195.         timeptr->tm_yday = days;
  196.     else {
  197.         timeptr->tm_mon = days - 1;             /* 1-12 for M form */
  198.         if( *tz == '.' ) {
  199.             tz = parse_time( tz + 1, &days );   /* 1-5 for M form */
  200.             timeptr->tm_mday = days;
  201.             if( *tz == '.' ) {
  202.                 tz = parse_time( tz + 1, &days );/* 0-6 for M form */
  203.                 timeptr->tm_wday = days;
  204.             }
  205.         }
  206.         timeptr->tm_yday = 0;
  207.     }
  208.  
  209.     hours = 2;
  210.     minutes = seconds = 0;
  211.     if( *tz == '/' ) {
  212.         tz = parse_time( tz + 1, &hours );
  213.         if( *tz == ':' ) {
  214.             tz = parse_time( tz + 1, &minutes );
  215.             if( *tz == ':' )
  216.                 tz = parse_time( tz + 1, &seconds );
  217.         }
  218.     }
  219.     timeptr->tm_sec = seconds;
  220.     timeptr->tm_min = minutes;
  221.     timeptr->tm_hour = hours;
  222.     return( tz );
  223. }
  224.  
  225. void __parse_tz( char * tz )
  226. /**************************/
  227. {
  228.     long        dayzone;
  229.  
  230.     _RWD_daylight = 0;
  231.     tz = parse_offset( tz, stzone, &_RWD_timezone );
  232.     if( *tz == '\0' ) {
  233.         dtzone[0] = '\0';
  234.         return;
  235.     }
  236.     _RWD_daylight = 1;
  237.     dayzone = _RWD_timezone - ( 60*60 );              /* 16-aug-91 */
  238.     tz = parse_offset( tz, dtzone, &dayzone );
  239.     _RWD_dst_adjust = _RWD_timezone - dayzone;
  240.  
  241.     /* parse daylight changing rules */
  242.     if( *tz == ',' )
  243.         tz = parse_rule( tz + 1, &__start_dst );
  244.     if( *tz == ',' ) {
  245.         tz = parse_rule( tz + 1, &__end_dst );
  246.         /* convert rule to be in terms of Standard Time */
  247.         /* rather than Daylight Time */
  248.         __end_dst.tm_hour -= _RWD_dst_adjust / 3600;
  249.         __end_dst.tm_min -= ( _RWD_dst_adjust / 60 ) % 60;
  250.         __end_dst.tm_sec -= _RWD_dst_adjust % 60;
  251.     }
  252. }
  253.  
  254. static int tryOSTimeZone( const char *tz )
  255. /****************************************/
  256. {
  257.     if( tz == NULL ) {
  258.         /* calling OS can be expensive; many programs don't care */
  259.         if( tzFlag.cache_OS_TZ && tzFlag.have_OS_TZ )
  260.             return( 1 );
  261.         /* Assume that even if we end up not getting the TZ from OS,
  262.             we won't have any better luck if we try later. */
  263.         tzFlag.have_OS_TZ = 1;
  264.     } else {
  265.         tzFlag.have_OS_TZ = 0;
  266.         return( 0 );
  267.     }
  268.  
  269.     // assume Eastern (North America) time zone
  270.     _RWD_timezone = 5L * 60L * 60L;
  271.     _RWD_dst_adjust = 60L * 60L;
  272.     return( 1 );
  273. }
  274.  
  275. _WCRTLINK void tzset( void )
  276. /**************************/
  277. {
  278.     #ifndef __NETWARE__
  279.     char        *tz;
  280.  
  281.     tz = getenv( "TZ" );
  282.     if( !tryOSTimeZone( tz ) && tz != NULL )
  283.         __parse_tz( tz );
  284.     #endif
  285. }
  286.