12aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/**
22aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  Definitions and Implementation for <time.h>.
32aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
453e1e5c647b73e45569ed6e8b8a0a5b276aa685edarylm  Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
52aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  This program and the accompanying materials are licensed and made available under
62aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  the terms and conditions of the BSD License that accompanies this distribution.
72aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  The full text of the license may be found at
82aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  http://opensource.org/licenses/bsd-license.php.
92aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  Portions derived from the NIH time zone package file, localtime.c,
142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  which contains the following notice:
152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    This file is in the public domain, so clarified as of
172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  NetBSD: localtime.c,v 1.39 2006/03/22 14:01:30 christos Exp
202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm**/
212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <Uefi.h>
222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <Library/UefiLib.h>
232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <Library/TimerLib.h>
242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <Library/BaseLib.h>
252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <Library/UefiRuntimeServicesTableLib.h>
262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm//#include  <Library/UefiRuntimeLib.h>
272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <LibConfig.h>
292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <errno.h>
312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <limits.h>
322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <time.h>
332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <reentrant.h>
342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  "tzfile.h"
352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  "TimeVals.h"
362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <MainData.h>
372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include  <extern.h>      // Library/include/extern.h: Private to implementation
382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#if defined(_MSC_VER)           /* Handle Microsoft VC++ compiler specifics. */
402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm// Keep compiler quiet about casting from function to data pointers
412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#pragma warning ( disable : 4054 )
422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif  /* defined(_MSC_VER) */
432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/* #######################  Private Data  ################################# */
452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#if 0
472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic EFI_TIME TimeBuffer;
482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  static  UINT16   MonthOffs[12] = {
502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm     00,
512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm     31,   59,   90,  120,
522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    151,  181,  212,  243,
532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    273,  304,  334
542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  };
552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  static  clock_t   y2kOffs = 730485;
562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif
572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmconst int  mon_lengths[2][MONSPERYEAR] = {
592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm};
622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmconst int  year_lengths[2] = {
642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  DAYSPERNYEAR, DAYSPERLYEAR
652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm};
662aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
672aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
682aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic const char *wday_name[7] = {
692aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
702aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm};
712aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
722aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic const char *mon_name[12] = {
732aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
742aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
752aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm};
762aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic int    gmt_is_set;
782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/* ###############  Implementation Functions  ############################ */
802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm// Forward reference
812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic void
822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmlocalsub(const time_t * const timep, const long   offset, struct tm * const tmp);
832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
842aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmclock_t
852aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm__getCPS(void)
862aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
872aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  return gMD->ClocksPerSecond;
882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic void
912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmtimesub(
922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  const time_t        * const timep,
932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  const long                  offset,
942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  const struct state  * const sp,
952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        struct tm     * const tmp
962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  )
972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  const struct lsinfo *  lp;
992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  time_t /*INTN*/     days;
1002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  time_t /*INTN*/     rem;
1012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  time_t /*INTN*/      y;
1022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  int      yleap;
1032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  const int *    ip;
1042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  time_t /*INTN*/     corr;
1052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  int      hit;
1062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  int      i;
1072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
1082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  corr = 0;
1092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  hit = 0;
1102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifdef ALL_STATE
1112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  i = (sp == NULL) ? 0 : sp->leapcnt;
1122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif /* defined ALL_STATE */
1132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifndef ALL_STATE
1142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  i = sp->leapcnt;
1152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif /* State Farm */
1162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  while (--i >= 0) {
1172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    lp = &sp->lsis[i];
1182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (*timep >= lp->ls_trans) {
1192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      if (*timep == lp->ls_trans) {
1202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        hit = ((i == 0 && lp->ls_corr > 0) ||
1212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm               lp->ls_corr > sp->lsis[i - 1].ls_corr);
1222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        if (hit)
1232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          while (i > 0                                                &&
1242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm                 sp->lsis[i].ls_trans == sp->lsis[i - 1].ls_trans + 1 &&
1252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm                 sp->lsis[i].ls_corr  == sp->lsis[i - 1].ls_corr  + 1 )
1262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          {
1272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm            ++hit;
1282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm            --i;
1292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          }
1302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      }
1312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      corr = lp->ls_corr;
1322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      break;
1332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    }
1342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
1352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  days = *timep / SECSPERDAY;
1362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  rem = *timep % SECSPERDAY;
1372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  rem += (offset - corr);
1382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  while (rem < 0) {
1392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    rem += SECSPERDAY;
1402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    --days;
1412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
1422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  while (rem >= SECSPERDAY) {
1432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    rem -= SECSPERDAY;
1442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    ++days;
1452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
1462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  tmp->tm_hour = (int) (rem / SECSPERHOUR);
1472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  rem = rem % SECSPERHOUR;
1482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  tmp->tm_min = (int) (rem / SECSPERMIN);
1492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  /*
1502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** A positive leap second requires a special
1512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** representation.  This uses "... ??:59:60" et seq.
1522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  */
1532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
1542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
1552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (tmp->tm_wday < 0)
1562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    tmp->tm_wday += DAYSPERWEEK;
1572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  y = EPOCH_YEAR;
1582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  while (days < 0 || days >= (LONG32) year_lengths[yleap = isleap(y)]) {
1592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    time_t /*INTN*/  newy;
1602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
1612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    newy = (y + days / DAYSPERNYEAR);
1622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (days < 0)
1632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      --newy;
1642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    days -= (newy - y) * DAYSPERNYEAR +
1652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      LEAPS_THRU_END_OF(newy - 1) -
1662aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      LEAPS_THRU_END_OF(y - 1);
1672aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    y = newy;
1682aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
1692aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  tmp->tm_year = (int)(y - TM_YEAR_BASE);
1702aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  tmp->tm_yday = (int) days;
1712aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ip = mon_lengths[yleap];
1722aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  for (tmp->tm_mon = 0; days >= (LONG32) ip[tmp->tm_mon]; ++(tmp->tm_mon))
1732aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    days = days - (LONG32) ip[tmp->tm_mon];
1742aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  tmp->tm_mday = (int) (days + 1);
1752aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  tmp->tm_isdst = 0;
1762aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifdef TM_GMTOFF
1772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  tmp->TM_GMTOFF = offset;
1782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif /* defined TM_GMTOFF */
1792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
1802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
1812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/* ###############  Time Manipulation Functions  ########################## */
1822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
1832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/**
1842aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm**/
1852aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmdouble
1862aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmdifftime(time_t time1, time_t time0)
1872aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
1882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  return (double)(time1 - time0);
1892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
1902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
1912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/*
1922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm** Adapted from code provided by Robert Elz, who writes:
1932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm**  The "best" way to do mktime I think is based on an idea of Bob
1942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm**  Kridle's (so its said...) from a long time ago.
1952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm**  [kridle@xinet.com as of 1996-01-16.]
1962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm**  It does a binary search of the time_t space.  Since time_t's are
1972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm**  just 32 bits, its a max of 32 iterations (even at 64 bits it
1982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm**  would still be very reasonable).
1992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm*/
2002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifndef WRONG
2022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define WRONG (-1)
2032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif /* !defined WRONG */
2042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/*
2062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).
2072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm*/
2082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic int
2102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmincrement_overflow(int * number, int delta)
2112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
2122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  int number0;
2132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  number0 = *number;
2152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  *number += delta;
2162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  return (*number < number0) != (delta < 0);
2172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
2182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic int
2202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmnormalize_overflow(int * const tensptr, int * const unitsptr, const int base)
2212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
2222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  register int  tensdelta;
2232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  tensdelta = (*unitsptr >= 0)  ?
2252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm              (*unitsptr / base) : (-1 - (-1 - *unitsptr) / base);
2262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  *unitsptr -= tensdelta * base;
2272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  return increment_overflow(tensptr, tensdelta);
2282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
2292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic int
2312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmtmcomp(const struct tm * const atmp, const struct tm * const btmp)
2322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
2332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  register int  result;
2342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
2362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
2372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
2382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
2392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      (result = (atmp->tm_min - btmp->tm_min)) == 0)
2402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    result = atmp->tm_sec - btmp->tm_sec;
2412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  return result;
2422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
2432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic time_t
2452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmtime2sub(
2462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  struct tm * const tmp,
2472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  void (* const funcp)(const time_t*, long, struct tm*),
2482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  const long offset,
2492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  int * const okayp,
2502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  const int do_norm_secs
2512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  )
2522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
2532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  register const struct state * sp;
2542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  register int                  dir;
2552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  register int                  bits;
2562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  register int                  i, j ;
2572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  register int                  saved_seconds;
2582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  time_t                        newt;
2592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  time_t                        t;
2602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  struct tm                     yourtm, mytm;
2612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
2622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  *okayp = FALSE;
2632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  yourtm = *tmp;    // Create a copy of tmp
2642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (do_norm_secs) {
2652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
2662aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm                           SECSPERMIN))
2672aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      return WRONG;
2682aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
2692aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
2702aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return WRONG;
2712aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
2722aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return WRONG;
2732aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR))
2742aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return WRONG;
2752aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  /*
2762aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** Turn yourtm.tm_year into an actual year number for now.
2772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** It is converted back to an offset from TM_YEAR_BASE later.
2782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  */
2792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))
2802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return WRONG;
2812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  while (yourtm.tm_mday <= 0) {
2822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (increment_overflow(&yourtm.tm_year, -1))
2832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      return WRONG;
2842aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    i = yourtm.tm_year + (1 < yourtm.tm_mon);
2852aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    yourtm.tm_mday += year_lengths[isleap(i)];
2862aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
2872aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  while (yourtm.tm_mday > DAYSPERLYEAR) {
2882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    i = yourtm.tm_year + (1 < yourtm.tm_mon);
2892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    yourtm.tm_mday -= year_lengths[isleap(i)];
2902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (increment_overflow(&yourtm.tm_year, 1))
2912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      return WRONG;
2922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
2932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  for ( ; ; ) {
2942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];
2952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (yourtm.tm_mday <= i)
2962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      break;
2972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    yourtm.tm_mday -= i;
2982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (++yourtm.tm_mon >= MONSPERYEAR) {
2992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      yourtm.tm_mon = 0;
3002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      if (increment_overflow(&yourtm.tm_year, 1))
3012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        return WRONG;
3022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    }
3032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
3042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE))
3052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return WRONG;
3062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
3072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    saved_seconds = 0;
3082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  else if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) {
3092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    /*
3102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    ** We can't set tm_sec to 0, because that might push the
3112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    ** time below the minimum representable time.
3122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    ** Set tm_sec to 59 instead.
3132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    ** This assumes that the minimum representable time is
3142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    ** not in the same minute that a leap second was deleted from,
3152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    ** which is a safer assumption than using 58 would be.
3162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    */
3172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
3182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      return WRONG;
3192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    saved_seconds = yourtm.tm_sec;
3202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    yourtm.tm_sec = SECSPERMIN - 1;
3212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  } else {
3222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    saved_seconds = yourtm.tm_sec;
3232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    yourtm.tm_sec = 0;
3242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
3252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  /*
3262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** Divide the search space in half
3272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** (this works whether time_t is signed or unsigned).
3282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  */
3292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  bits = TYPE_BIT(time_t) - 1;
3302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  /*
3312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** Set t to the midpoint of our binary search.
3322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  **
3332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** If time_t is signed, then 0 is just above the median,
3342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** assuming two's complement arithmetic.
3352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** If time_t is unsigned, then (1 << bits) is just above the median.
3362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  */
3372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits);
3382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  for ( ; ; ) {
3392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    (*funcp)(&t, offset, &mytm);    // Convert t to broken-down time in mytm
3402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    dir = tmcomp(&mytm, &yourtm);   // Is mytm larger, equal, or less than yourtm?
3412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (dir != 0) {                 // If mytm != yourtm...
3422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      if (bits-- < 0)                   // If we have exhausted all the bits..
3432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        return WRONG;                       // Return that we failed
3442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      if (bits < 0)                     // If on the last bit...
3452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        --t; /* may be needed if new t is minimal */
3462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      else if (dir > 0)                 // else if mytm > yourtm...
3472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        t -= ((time_t) 1) << bits;          // subtract half the remaining time-space
3482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      else  t += ((time_t) 1) << bits;      // otherwise add half the remaining time-space
3492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      continue;                     // Repeat for the next half
3502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    }
3512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
3522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      break;
3532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    /*
3542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    ** Right time, wrong type.
3552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    ** Hunt for right time, right type.
3562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    ** It's okay to guess wrong since the guess
3572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    ** gets checked.
3582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    */
3592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    /*
3602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
3612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    */
3622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    sp = (const struct state *)
3632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      (((void *) funcp == (void *) localsub) ?
3642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm       lclptr : gmtptr);
3652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifdef ALL_STATE
3662aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (sp == NULL)
3672aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      return WRONG;
3682aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif /* defined ALL_STATE */
3692aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    for (i = sp->typecnt - 1; i >= 0; --i) {
3702aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
3712aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        continue;
3722aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      for (j = sp->typecnt - 1; j >= 0; --j) {
3732aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
3742aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          continue;
3752aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        newt = t + sp->ttis[j].tt_gmtoff -
3762aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          sp->ttis[i].tt_gmtoff;
3772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        (*funcp)(&newt, offset, &mytm);
3782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        if (tmcomp(&mytm, &yourtm) != 0)
3792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          continue;
3802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        if (mytm.tm_isdst != yourtm.tm_isdst)
3812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          continue;
3822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        /*
3832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        ** We have a match.
3842aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        */
3852aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        t = newt;
3862aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        goto label;
3872aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      }
3882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    }
3892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return WRONG;
3902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
3912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  label:
3922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  newt = t + saved_seconds;
3932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if ((newt < t) != (saved_seconds < 0))
3942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return WRONG;
3952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  t = newt;
3962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  (*funcp)(&t, offset, tmp);
3972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  *okayp = TRUE;
3982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  return t;
3992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
4002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
401d7ce700605e1af0e455e31ec11f19ff21d26b525darylmtime_t
4022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmtime2(struct tm * const tmp, void (* const funcp)(const time_t*, long, struct tm*),
4032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      const long offset, int * const okayp)
4042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
4052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  time_t  t;
4062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
4072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  /*
4082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** First try without normalization of seconds
4092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** (in case tm_sec contains a value associated with a leap second).
4102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** If that fails, try with normalization of seconds.
4112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  */
4122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  t = time2sub(tmp, funcp, offset, okayp, FALSE);
4132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE);
4142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
4152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
4162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic time_t
4172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmtime1(
4182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  struct tm * const tmp,
4192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  void (* const funcp)(const time_t *, long, struct tm *),
4202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  const long offset
4212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  )
4222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
4232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  register time_t               t;
4242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  register const struct state * sp;
4252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  register int                  samei, otheri;
4262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  register int                  sameind, otherind;
4272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  register int                  i;
4282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  register int                  nseen;
4292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  int                           seen[TZ_MAX_TYPES];
4302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  int                           types[TZ_MAX_TYPES];
4312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  int                           okay;
4322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
4332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (tmp->tm_isdst > 1)
4342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    tmp->tm_isdst = 1;
4352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  t = time2(tmp, funcp, offset, &okay);
4362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifdef PCTS
4372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  /*
4382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** PCTS code courtesy Grant Sullivan (grant@osf.org).
4392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  */
4402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (okay)
4412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return t;
4422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (tmp->tm_isdst < 0)
4432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    tmp->tm_isdst = 0;  /* reset to std and try again */
4442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif /* defined PCTS */
4452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifndef PCTS
4462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (okay || tmp->tm_isdst < 0)
4472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return t;
4482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif /* !defined PCTS */
4492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  /*
4502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** We're supposed to assume that somebody took a time of one type
4512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** and did some math on it that yielded a "struct tm" that's bad.
4522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** We try to divine the type they started from and adjust to the
4532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** type they need.
4542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  */
4552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  /*
4562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
4572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  */
4582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  sp = (const struct state *) (((void *) funcp == (void *) localsub) ?
4592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm                               lclptr : gmtptr);
4602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifdef ALL_STATE
4612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (sp == NULL)
4622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return WRONG;
4632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif /* defined ALL_STATE */
4642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  for (i = 0; i < sp->typecnt; ++i)
4652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    seen[i] = FALSE;
4662aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  nseen = 0;
4672aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  for (i = sp->timecnt - 1; i >= 0; --i)
4682aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (!seen[sp->types[i]]) {
4692aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    seen[sp->types[i]] = TRUE;
4702aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    types[nseen++] = sp->types[i];
4712aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    }
4722aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    for (sameind = 0; sameind < nseen; ++sameind) {
4732aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      samei = types[sameind];
4742aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
4752aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        continue;
4762aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      for (otherind = 0; otherind < nseen; ++otherind) {
4772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        otheri = types[otherind];
4782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
4792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          continue;
4802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        tmp->tm_sec += (int)(sp->ttis[otheri].tt_gmtoff -
4812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm                             sp->ttis[samei].tt_gmtoff);
4822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        tmp->tm_isdst = !tmp->tm_isdst;
4832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        t = time2(tmp, funcp, offset, &okay);
4842aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        if (okay)
4852aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          return t;
4862aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        tmp->tm_sec -= (int)(sp->ttis[otheri].tt_gmtoff -
4872aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm                             sp->ttis[samei].tt_gmtoff);
4882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        tmp->tm_isdst = !tmp->tm_isdst;
4892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      }
4902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    }
4912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return WRONG;
4922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
4932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
4942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/** The mktime function converts the broken-down time, expressed as local time,
4952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    in the structure pointed to by timeptr into a calendar time value with the
4962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    same encoding as that of the values returned by the time function.  The
4972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    original values of the tm_wday and tm_yday components of the structure are
4982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    ignored, and the original values of the other components are not restricted
4992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    to the ranges indicated above.  Thus, a positive or zero value for tm_isdst
5002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    causes the mktime function to presume initially that Daylight Saving Time,
5012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    respectively, is or is not in effect for the specified time. A negative
5022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    value causes it to attempt to determine whether Daylight Saving Time is in
5032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    effect for the specified time.  On successful completion, the values of the
5042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    tm_wday and tm_yday components of the structure are set appropriately, and
5052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    the other components are set to represent the specified calendar time, but
5062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    with their values forced to the ranges indicated above; the final value of
5072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    tm_mday is not set until tm_mon and tm_year are determined.
5082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
5092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    @return   The mktime function returns the specified calendar time encoded
5102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm              as a value of type time_t.  If the calendar time cannot be
5112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm              represented, the function returns the value (time_t)(-1).
5122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm**/
5132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmtime_t
5142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmmktime(struct tm *timeptr)
5152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
5162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  /* From NetBSD */
5172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  time_t result;
5182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
5192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  rwlock_wrlock(&lcl_lock);
5202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  tzset();
5212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  result = time1(timeptr, &localsub, 0L);
5222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  rwlock_unlock(&lcl_lock);
5232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  return (result);
5242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
5252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
5262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/** The time function determines the current calendar time.  The encoding of
5272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    the value is unspecified.
5282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
529d7ce700605e1af0e455e31ec11f19ff21d26b525darylm    @return   The time function returns the implementation's best approximation
5302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm              to the current calendar time.  The value (time_t)(-1) is returned
5312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm              if the calendar time is not available.  If timer is not a null
5322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm              pointer, the return value is also assigned to the object it
5332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm              points to.
5342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm**/
5352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmtime_t
5362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmtime(time_t *timer)
5372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
5382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  time_t      CalTime;
5392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  EFI_STATUS  Status;
5402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  EFI_TIME   *ET;
5412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  struct tm  *BT;
5422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
5432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ET = &gMD->TimeBuffer;
5442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  BT = &gMD->BDTime;
5452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
5462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  // Get EFI Time
5472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  Status = gRT->GetTime( ET, NULL);
5482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm//  Status = EfiGetTime( ET, NULL);
5492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  EFIerrno = Status;
5502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if( Status != RETURN_SUCCESS) {
5512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return (time_t)-1;
5522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
5532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
5542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  // Convert EFI time to broken-down time.
5552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  Efi2Tm( ET, BT);
5562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
5572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  // Convert to time_t
5582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  CalTime  =  mktime(&gMD->BDTime);
5592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
5602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if( timer != NULL) {
5612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    *timer = CalTime;
5622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
5632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  return CalTime;   // Return calendar time in microseconds
5642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
5652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
5668aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylm/** The clock function determines the processor time used.
5678aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylm
5688aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylm    @return   The clock function returns the implementation's best
5698aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylm              approximation to the processor time used by the program since the
5708aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylm              beginning of an implementation-defined era related only to the
5718aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylm              program invocation.  To determine the time in seconds, the value
5728aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylm              returned by the clock function should be divided by the value of
5738aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylm              the macro CLOCKS_PER_SEC.  If the processor time used is not
5748aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylm              available or its value cannot be represented, the function
5758aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylm              returns the value (clock_t)(-1).
5768aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylm**/
5778aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylmclock_t
5788aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylmclock(void)
5798aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylm{
5808aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylm  clock_t   retval;
5818aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylm  time_t    temp;
5828aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylm
5838aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylm  temp = time(NULL);
5848aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylm  retval = ((clock_t)((UINT32)temp)) - gMD->AppStartTime;
5858aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylm  return retval;
5868aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylm}
5878aa163da5ac7bf40d1a3b0612a46504dc56d16a2darylm
5882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/* #################  Time Conversion Functions  ########################## */
5892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/*
5902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    Except for the strftime function, these functions each return a pointer to
5912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    one of two types of static objects: a broken-down time structure or an
5922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    array of char.  Execution of any of the functions that return a pointer to
5932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    one of these object types may overwrite the information in any object of
5942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    the same type pointed to by the value returned from any previous call to
5952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    any of them.  The implementation shall behave as if no other library
5962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    functions call these functions.
5972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm*/
5982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
5992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/** The asctime function converts the broken-down time in the structure pointed
6002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    to by timeptr into a string in the form
6012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      Sun Sep 16 01:03:52 1973\n\0
6022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    using the equivalent of the following algorithm.
6032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
6042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      char *asctime(const struct tm *timeptr)
6052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      {
6062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        static const char wday_name[7][3] = {
6072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
6082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        };
6092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        static const char mon_name[12][3] = {
6102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          "Jan", "Feb", "Mar", "Apr", "May", "Jun",
6112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
6122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        };
6132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        static char result[26];
6142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
6152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm                wday_name[timeptr->tm_wday],
6162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm                mon_name[timeptr->tm_mon],
6172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm                timeptr->tm_mday, timeptr->tm_hour,
6182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm                timeptr->tm_min, timeptr->tm_sec,
6192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm                1900 + timeptr->tm_year);
6202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        return result;
6212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      }
6222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    @return   The asctime function returns a pointer to the string.
6232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm**/
6242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmchar *
6252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmasctime(const struct tm *timeptr)
6262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
6272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  register const char * wn;
6282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  register const char * mn;
6292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
6302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK)
6312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    wn = "???";
6322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  else  wn = wday_name[timeptr->tm_wday];
6332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (timeptr->tm_mon < 0 || timeptr->tm_mon >= MONSPERYEAR)
6342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    mn = "???";
6352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  else  mn = mon_name[timeptr->tm_mon];
6362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  /*
6372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** The X3J11-suggested format is
6382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  **  "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %d\n"
6392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** Since the .2 in 02.2d is ignored, we drop it.
6402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  */
6412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  (void)snprintf(gMD->ASasctime,
6422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm                 sizeof (char[ASCTIME_BUFLEN]),
6432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm                 "%.3s %.3s%3d %02d:%02d:%02d %d\r\n",    // explicit CRLF for EFI
6442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm                 wn, mn,
6452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm                 timeptr->tm_mday, timeptr->tm_hour,
6462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm                 timeptr->tm_min, timeptr->tm_sec,
6472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm                 TM_YEAR_BASE + timeptr->tm_year);
6482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  return gMD->ASasctime;
6492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
6502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
6512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/**
6522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm**/
6532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmchar *
6542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmctime(const time_t *timer)
6552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
6562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  return asctime(localtime(timer));
6572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
6582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
6592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/*
6602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm** gmtsub is to gmtime as localsub is to localtime.
6612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm*/
662d7ce700605e1af0e455e31ec11f19ff21d26b525darylmvoid
6632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmgmtsub(
6642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  const time_t * const  timep,
6652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  const long            offset,
6662aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  struct tm    * const  tmp
6672aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  )
6682aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
6692aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifdef _REENTRANT
6702aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  static mutex_t gmt_mutex = MUTEX_INITIALIZER;
6712aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif
6722aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
6732aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  mutex_lock(&gmt_mutex);
6742aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (!gmt_is_set) {
6752aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    gmt_is_set = TRUE;
6762aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifdef ALL_STATE
6772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    gmtptr = (struct state *) malloc(sizeof *gmtptr);
6782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (gmtptr != NULL)
6792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif /* defined ALL_STATE */
6802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      gmtload(gmtptr);
6812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
6822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  mutex_unlock(&gmt_mutex);
6832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  timesub(timep, offset, gmtptr, tmp);
6842aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifdef TM_ZONE
6852aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  /*
6862aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** Could get fancy here and deliver something such as
6872aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
6882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** but this is no time for a treasure hunt.
6892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  */
6902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (offset != 0)
6912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    tmp->TM_ZONE = (__aconst char *)__UNCONST(wildabbr);
6922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  else {
6932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifdef ALL_STATE
6942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    if (gmtptr == NULL)
6952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      tmp->TM_ZONE = (__aconst char *)__UNCONST(gmt);
6962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    else  tmp->TM_ZONE = gmtptr->chars;
6972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif /* defined ALL_STATE */
6982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifndef ALL_STATE
6992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    tmp->TM_ZONE = gmtptr->chars;
7002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif /* State Farm */
7012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
7022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif /* defined TM_ZONE */
7032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
7042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
7052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/**
7062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm**/
7072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstruct tm *
7082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmgmtime(const time_t *timer)
7092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
7102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  gmtsub(timer, 0L, &gMD->BDTime);
7112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  return &gMD->BDTime;
7122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
7132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
7142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic void
7152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmlocalsub(const time_t * const timep, const long   offset, struct tm * const tmp)
7162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
7172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  register struct state *   sp;
7182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  register const struct ttinfo *  ttisp;
7192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  register int      i;
7202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  const time_t      t = *timep;
7212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
7222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  sp = lclptr;
7232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifdef ALL_STATE
7242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (sp == NULL) {
7252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    gmtsub(timep, offset, tmp);
7262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    return;
7272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
7282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif /* defined ALL_STATE */
7292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  if (sp->timecnt == 0 || t < sp->ats[0]) {
7302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    i = 0;
7312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    while (sp->ttis[i].tt_isdst)
7322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      if (++i >= sp->typecnt) {
7332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        i = 0;
7342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm        break;
7352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      }
7362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  } else {
7372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    for (i = 1; i < sp->timecnt; ++i)
7382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      if (t < sp->ats[i])
7392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm      break;
7402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm    i = sp->types[i - 1];
7412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  }
7422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ttisp = &sp->ttis[i];
7432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  /*
7442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** To get (wrong) behavior that's compatible with System V Release 2.0
7452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  ** you'd replace the statement below with
7462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  **  t += ttisp->tt_gmtoff;
7472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  **  timesub(&t, 0L, sp, tmp);
7482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  */
7492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  timesub(&t, ttisp->tt_gmtoff, sp, tmp);
7502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  tmp->tm_isdst = ttisp->tt_isdst;
7512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
7522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifdef TM_ZONE
7532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
7542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif /* defined TM_ZONE */
7552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
7562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm
7572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/**
7582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm**/
7592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstruct tm *
7602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmlocaltime(const time_t *timer)
7612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{
7622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  tzset();
7632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  localsub(timer, 0L, &gMD->BDTime);
7642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm  return &gMD->BDTime;
7652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm}
766