/* gmtime.c (emx+gcc) -- Copyright (c) 1990-1999 by Eberhard Mattes */

#include <stdlib.h>
#include <time.h>
#include <emx/thread.h>
#include <emx/time.h>

struct tm *gmtime (const time_t *t)
{
#if defined (__MT__)
  struct _thread *tp = _thread ();
#define result (tp->_th_gmtime_buf)
#else
  static struct tm result;
#endif
  return _gmtime (&result, t);
}

struct tm *_gmtime (struct tm *dst, const time_t *t)
{
  time_t t0;
  _uldiv_t q;

  t0 = *t;

  q = _uldiv (t0, 60); dst->tm_sec = q.rem; t0 = q.quot;
  q = _uldiv (t0, 60); dst->tm_min = q.rem; t0 = q.quot;
  q = _uldiv (t0, 24); dst->tm_hour = q.rem; t0 = q.quot;
  dst->tm_wday = (t0+4) % 7;  /* 01-Jan-1970 was Thursday, ie, 4 */

  {
    int lo, hi, i;

    /* Find an i such that _year_day[i] <= t0 < _year_day[i+1]. */

    lo = 0; hi = _YEARS - 1;
    for (;;)
      {
        i = (lo + hi) / 2;
        if (_year_day[i] > (int)t0)
          hi = i - 1;
        else if (_year_day[i+1] <= (int)t0)
          lo = i + 1;
        else
          break;
      }
    dst->tm_year = i + 70;
    t0 -= _year_day[i];
    dst->tm_yday = t0;
  }

  {
    int i;
    const int *p;

    p = (_leap_year (dst->tm_year + 1900)
         ? _month_day_leap : _month_day_non_leap);
    for (i = 0; (int)t0 >= p[i+1]; ++i)
      ;
    dst->tm_mon = i;
    dst->tm_mday = t0 - p[i] + 1;
  }
  dst->tm_isdst = -1;
  return dst;
}
