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

#include <time.h>
#include <limits.h>
#include <emx/time.h>

time_t mktime (struct tm *t)
{
  time_t t1, t2;
  struct tm tmp;
  int dst;

  if (!_tzset_flag) _tzset ();

  /* _mktime() requires that tm_mon is in range.  The other members
     are not restricted. */

  if (t->tm_mon < 0)
    {
      /* Avoid applying the `/' and `%' operators to negative numbers
         as the results are implementation-defined for negative
         numbers. */

      t->tm_year -= 1 + ((-t->tm_mon) / 12);
      t->tm_mon = 12 - ((-t->tm_mon) % 12);
    }
  if (t->tm_mon >= 12)
    {
      t->tm_year += (t->tm_mon / 12);
      t->tm_mon %= 12;
    }

  t1 = (time_t)_mktime (t);
  if (t1 == (time_t)-1)
    return (time_t)-1;
  dst = _loc2gmt (&t1, t->tm_isdst);
  if (dst == -1)
    return (time_t)-1;
  t2 = t1;
  dst = _gmt2loc (&t2);
  if (dst == -1)
    return (time_t)-1;
  
  if (_gmtime (&tmp, &t2) == NULL)
    return (time_t)-1;
  *t = tmp;
  t->tm_isdst = dst;
  return t1;
}


/* year >= 1582, 1 <= month <= 12, 1 <= day <= 31 */

int _day (int year, int month, int day)
{
  int result;

  if (year < 1582 || year >= INT_MAX / 365)
    return -1;
  result = 365 * year + day + 31 * (month - 1);
  if (month <= 2)
    --year;
  else
    result -= (4 * month + 23) / 10;
  result += year / 4 - (3 * (year / 100 + 1)) / 4;
  return result;
}


unsigned long _mktime (struct tm *t)
{
  long x;
  long long r;

  x = _day (t->tm_year+1900, t->tm_mon+1, t->tm_mday);
  /* 719528 = day (1970, 1, 1) */
  r = (long long)(x - 719528) * 24 * 60 * 60;

  /* This expression is not checked for overflow. */
  x = t->tm_sec + 60*t->tm_min + 60*60*t->tm_hour;

  r += x;
  if (r < 0 || r > ULONG_MAX || r == (time_t)-1)
    return (time_t)-1;
  return (time_t)r;
}
