///////////////////////////////////////////////////////////////////////////////
//
// Legalese:
// This file is part of the OpenNETCF time.h port for Windows CE.
// You are free to use, modify or distribute this code or any
// derivative work that you create.  This code is provided WITHOUT
// WARRANTY and OpenNETCF does NOT claim in any way that this code
// is fit for any specific or general use and holds NO RESPONSIBILITY
// for consequences of using any of it.  It is simply provided as-is.
//
// About:
// This is part of a free and open project to provide a simply way to
// port that uses time.h functions to Windows CE.  For the latest
// code, or to submit fixes, feature additions, etc. visit:
//
// http://www.opennetcf.com
//
// Version 0.01 - March 22, 2007
//                Initial Release
//
// Version 0.02 - July 5, 2007
//                Bug fixes.  UTC offset not properly accounted for unless SetTz had been previously called.
//                            UTC offset used for functions like localtime using old, rather than current data
//
///////////////////////////////////////////////////////////////////////////////
// Many but not all of the functions were created from the following source:
//
// Copyright (C) 2002 Michael Ringgaard. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
// 3. Neither the name of the project nor the names of its contributors
//    may be used to endorse or promote products derived from this software
//    without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
///////////////////////////////////////////////////////////////////////////////



#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "celibc.h"

#ifndef __GNUC__
///////////////////////////////////////////////////////////////////////////////
// Macros
///////////////////////////////////////////////////////////////////////////////
#define TIME_FAILURE	0xFFFFFFFF
#define ASC_BUFF_SIZE	26  // Ascii buffer size is 26 bytes, (24 chars and CR+LF)
#define SEC_IN_HOUR     3600L
#define SECS_IN_MIN		60L
#define DAYSPERWEEK		7
#define YEAR0           1900
#define EPOCH_YR        1970
#define SECS_DAY        (24L * 60L * 60L)
#define LEAPYEAR(year)  (!((year) % 4) && (((year) % 100) || !((year) % 400)))
#define TIME_MAX        2147483647L

///////////////////////////////////////////////////////////////////////////////
// Local Variables
///////////////////////////////////////////////////////////////////////////////

// Number of seconds between local time and UTC time, includes DST bias
//
LONG _localtime;

// Is the local time in daylight savings time
//
DWORD _isdst;

// Bias for daylight savings time
//
int _dstBias;

// Contains the time zone string
//
char tz_name[2][32];

// Contains the 1/1/1970 reference date/time
//
const SYSTEMTIME st1970 = {1970, 1,	4, 1, 0, 0, 0, 0};

// Contains the number of days per month for
// non leap and leap years
//
const int _ytab[2][12] =
{
  {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
  {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

// Contains the days of the week abreviation
//
static char *aday[] = {
    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};

// Contains the days of the week full name
//
static char *day[] = {
    "Sunday", "Monday", "Tuesday", "Wednesday",
    "Thursday", "Friday", "Saturday"
};

// Contains the months of the year abreviation
//
static char *amonth[] = {
    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};

// Contains the months of the year full name
//
static char *month[] = {
    "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December"
};

///////////////////////////////////////////////////////////////////////////////
// Forward declaration of internal functions
///////////////////////////////////////////////////////////////////////////////

// Convert system time into seconds since 1970
//
LONGLONG SystemTimeToSecondsSince1970(SYSTEMTIME * st);

// Convert seconds since 1970 into a system time
//
void SecondsSince1970ToSystemTime(const time_t * timer, SYSTEMTIME * st,
								  BOOLEAN local);

// Initialize the time zone information needed for the time methods
//
void SetTz(SYSTEMTIME *_st);

// Copy system time structure to tm structure
//
void SystemTimeToTm(SYSTEMTIME *st, struct tm * tmbuffer);
void TmToSystemTime(struct tm * tmbuffer, SYSTEMTIME *st);

// Get Julian Days from the begining of the year
//
DWORD JulianDays(SYSTEMTIME * st);

// Method parses and formats strings
//
static void strfmt(char *str, const char *fmt, ...);

// Reentrant version of gmttime
//
struct tm *gmtime_r_ce(const time_t *timer, struct tm *tmbuf, BOOLEAN local);

// Reentrant version of localtime
//
struct tm *localtime_r_ce(const time_t *timer, struct tm *tmbuf);

///////////////////////////////////////////////////////////////////////////////
// Methods - The meat
///////////////////////////////////////////////////////////////////////////////

// Convert tm to a string in the format "Www Mmm dd hh:mm:ss yyyy",
// where Www is the weekday, Mmm the month in letters, dd the day
// of the month, hh:mm:ss the time, and yyyy the year. The string
// is followed by a newline and a terminating null character,
// conforming a total of 26 characters.
//
char *asctime(const struct tm* tmptr)
{
	static char ascbuf[ASC_BUFF_SIZE];
    strftime(ascbuf, ASC_BUFF_SIZE, "%c\n", tmptr);
    return ascbuf;
}
#endif //__GNUC__

// Return number of clock ticks since process start.
// NOTE: This differs from standard clock since GetTickCount is the
//       number of milliseconds since system startup not process start.
//       This will also rollover after 49.7 days of continuous system
//       runtime.
//
clock_t clock(void)
{
	return GetTickCount();
}

#ifndef __GNUC__
// Convert time_t value to string in the same format as asctime.
//
char* ctime(const time_t* timer)
{
	return asctime(localtime(timer));
}

// Reentrant version of gmttime_ce
//
struct tm *gmtime_r_ce(const time_t *timer, struct tm *tmbuf, BOOLEAN local)
{
  SYSTEMTIME	st;

  SecondsSince1970ToSystemTime(timer, &st, local);
  SetTz(&st);
  if(_isdst) {
    SecondsSince1970ToSystemTime(timer, &st, local);
  }

  // copy SYSTEMTIME data to tm structure
  //
  SystemTimeToTm(&st, tmbuf);

  return tmbuf;

}

// Reentrant version of localtime
//
struct tm *localtime_r_ce(const time_t *timer, struct tm *tmbuf)
{
	return gmtime_r_ce(timer, tmbuf, TRUE);
}

// Convert a time_t value to a tm structure as UTC time.
//
struct tm *gmtime(const time_t *timer)
{
	return gmtime_r_ce(timer, &tmbuf, FALSE);
}

// Convert a time_t value to a tm structure as local time.
//
struct tm *localtime(const time_t *timer)
{
	return localtime_r_ce(timer, &tmbuf);
}

// time_t represents seconds since midnight January 1, 1970 UTC
// (coordinated universal time) in 32-bits Win32 FILETIME structure is 64-bit,
// which represents the number of 100-nanosecond (hns) intervals since
// January 1, 1601 UTC (coordinate universal time) the time difference
// between midnight January 1, 1970 and midnight January 1, 1601 is 11644473600 seconds
//
time_t mktime(struct tm *tptr)
{
	SYSTEMTIME st;

	int day = 0;
	int year = 0;
	int seconds = 0;
	int overflow;
	int tm_year;
	int yday, month;

	TmToSystemTime(tptr, &st);
	SetTz(&st);

	// see if seconds are < 0
	while(tptr->tm_sec < 0)
	{
		// steal 60 seconds from the minutes
		tptr->tm_sec += 60;
		tptr->tm_min--;
	}
	// roll any seconds > 60 into the minutes
	tptr->tm_min += tptr->tm_sec / 60;
	// then crop them off
	tptr->tm_sec %= 60;

	// see if minutes are < 0
	while(tptr->tm_min < 0)
	{
		// steal 60 minutes from the hours
		tptr->tm_min += 60;
		tptr->tm_hour--;
	}
	// roll any minutes > 60 into the hours
	tptr->tm_hour += tptr->tm_min / 60;
	// then crop them off
	tptr->tm_min %= 60;

	// see if hours are < 0
	while(tptr->tm_hour < 0)
	{
		// steal 24 hours from the days
		tptr->tm_hour += 24;
		day--;
	}
	// keep any "excess" days (tm doesn't have a convenient place for this)
	day += tptr->tm_hour / 24;
	// crop
	tptr->tm_hour %= 24;

	// roll any months > 12 into the years
	tptr->tm_year += tptr->tm_mon / 12;
	// then crop the off
	tptr->tm_mon %= 12;

	// see if months are < 0
	if (tptr->tm_mon < 0)
	{
		// steal 12 months from the years
		tptr->tm_mon += 12;
		tptr->tm_year--;
	}

	// add number of days into the month to total day
	day += (tptr->tm_mday - 1);

	// if days are < 0 then calculate the number of days
	// checking to see if the month is a leap year month
	while (day < 0)
	{
		// If months are < 0 then steal 12 months from number of years
		// for the day calculation
		if(--tptr->tm_mon < 0)
		{
			tptr->tm_year--;
			tptr->tm_mon = 11;
		}
		day += _ytab[LEAPYEAR(YEAR0 + tptr->tm_year)][tptr->tm_mon];
	}
	// if day is greater then the number of days in the month
	// subtract the number of days in the month and adjust the
	// month
	while (day >= _ytab[LEAPYEAR(YEAR0 + tptr->tm_year)][tptr->tm_mon])
	{
		day -= _ytab[LEAPYEAR(YEAR0 + tptr->tm_year)][tptr->tm_mon];
		if (++(tptr->tm_mon) == 12)
		{
			tptr->tm_mon = 0;
			tptr->tm_year++;
		}
	}
	tptr->tm_mday = day + 1;
	year = EPOCH_YR;

	// if year is less then 1970 then return error
	if (tptr->tm_year < year - YEAR0) return (time_t) -1;

	seconds = 0;
	day = 0;                      // Means days since day 0 now
	overflow = 0;

	// Assume that when day becomes negative, there will certainly
	// be overflow on seconds.
	// The check for overflow needs not to be done for leapyears
	// divisible by 400.
	// The code only works when year (1970) is not a leapyear.
	tm_year = tptr->tm_year + YEAR0;

	// make sure we are not past the max year for 32-bit number
	if (TIME_MAX / 365 < tm_year - year) overflow++;

	// calculate number of days since EPOCH
	day = (tm_year - year) * 365;

	if (TIME_MAX - day < (tm_year - year) / 4 + 1) overflow++;

	day += (tm_year - year) / 4 + ((tm_year % 4) && tm_year % 4 < year % 4);
	day -= (tm_year - year) / 100 + ((tm_year % 100) && tm_year % 100 < year % 100);
	day += (tm_year - year) / 400 + ((tm_year % 400) && tm_year % 400 < year % 400);

	// setup for calculation of the yday or Julian day since Jan 1
	yday = month = 0;

	// add up the number of days for the preceding months
	while (month < tptr->tm_mon)
	{
		yday += _ytab[LEAPYEAR(tm_year)][month];
		month++;
	}
	// add the number of days in the current month
	yday += (tptr->tm_mday - 1);

	// make sure the didn't overflow
	if (day + yday < 0) overflow++;

	day += yday;

	// set the year day in the structure
	tptr->tm_yday = yday;

	// calculate the weekday
	tptr->tm_wday = (day + 4) % 7;               // Day 0 was thursday (4)

	// start the seconds calculation by totaling the hours, min, seconds
	seconds = ((tptr->tm_hour * 60L) + tptr->tm_min) * 60L + tptr->tm_sec;

	// make sure we are not going to overflow
	if ((TIME_MAX - seconds) / SECS_DAY < day) overflow++;

	// calculate the number of seconds for the number of days
	seconds += day * SECS_DAY;

	// Now adjust according to timezone and daylight saving time
	if (((_localtime > 0) && (TIME_MAX - _localtime < seconds))
	  || ((_localtime < 0) && (seconds < -_localtime)))
		  overflow++;

	// Adjust for local time zone
  seconds += _localtime;

	// return error if we are going to blow the max values
	if (overflow) return (time_t) -1;

	if ((time_t) seconds != seconds) return (time_t) -1;

	// return the number of seconds since EPOCH
	return (time_t) seconds;
}


// Get the current system time and convert to seconds since
// 1/1/1970.  Store the seconds value in tloc if not a NULL pointer then
// return the seconds value.
//
time_t time(time_t *tloc)
{
	SYSTEMTIME	st;
	LONGLONG	secs = 0;

	// Get current system time
	GetSystemTime(&st);

  // Set time zone information
	//
	SetTz(&st);

	// convert system time to number of seconds since 1970
	//
	secs = SystemTimeToSecondsSince1970(&st);

	// check for failure
	//
	if(secs == TIME_FAILURE)
	{
		return TIME_FAILURE;
	}

	// If tloc is not NULL, the return value is also stored in the location to which tloc points
	//
	if(tloc != NULL)
	{
		if(IsBadWritePtr(tloc, sizeof(time_t)))
		{
			return TIME_FAILURE;
		}
		memcpy(tloc, &secs, sizeof(time_t));
	}

	return secs;
}

// The strftime function is a modified version created by the following:
// written 6 september 1989 by jim nutt
// released into the public domain by jim nutt
//
// modified 21-Oct-89 by Rob Duff
//
//
// size_t strftime(char *str,
//                 size_t maxs,
//                 const char *fmt,
//                 const struct tm *t)
//
//      this functions acts much like a sprintf for time/date output.
//      given a pointer to an output buffer, a format string and a
//      time, it copies the time to the output buffer formatted in
//      accordance with the format string.  the parameters are used
//      as follows:
//
//          str is a pointer to the output buffer, there should
//          be at least maxs characters available at the address
//          pointed to by str.
//
//          maxs is the maximum number of characters to be copied
//          into the output buffer, included the '\0' terminator
//
//          fmt is the format string.  a percent sign (%) is used
//          to indicate that the following character is a special
//          format character.  the following are valid format
//          characters:
//
//              %A      full weekday name (Monday)
//              %a      abbreviated weekday name (Mon)
//              %B      full month name (January)
//              %b      abbreviated month name (Jan)
//              %c      standard date and time representation
//              %d      day-of-month (01-31)
//              %H      hour (24 hour clock) (00-23)
//              %I      hour (12 hour clock) (01-12)
//              %j      day-of-year (001-366)
//              %M      minute (00-59)
//              %m      month (01-12)
//              %p      local equivalent of AM or PM
//              %S      second (00-59)
//              %U      week-of-year, first day sunday (00-53)
//              %W      week-of-year, first day monday (00-53)
//              %w      weekday (0-6, sunday is 0)
//              %X      standard time representation
//              %x      standard date representation
//              %Y      year with century
//              %y      year without century (00-99)
//              %Z      timezone name
//              %%      percent sign
//
//      the standard date string is equivalent to:
//
//          %a %b %d %Y
//
//      the standard time string is equivalent to:
//
//          %H:%M:%S
//
//      the standard date and time string is equivalent to:
//
//          %a %b %d %H:%M:%S %Y
//
//      strftime returns the number of characters placed in the
//      buffer, not including the terminating \0, or zero if more
//      than maxs characters were produced.
//
size_t strftime(char *s, size_t maxs, const char *f, const struct tm *t)
{
	int			w;
	char		*p, *q, *r;
	static char	buf[26];

	p = s;
	q = s + maxs - 1;
	while ((*f != '\0'))
	{
		if (*f++ == '%')
		{
			r = buf;
			switch (*f++)
			{
				case '%' :
					r = "%";
					break;

				case 'a' :
					r = aday[t->tm_wday];
					break;

				case 'A' :
					r = day[t->tm_wday];
					break;

				case 'b' :
					r = amonth[t->tm_mon];
					break;

				case 'B' :
					r = month[t->tm_mon];
					break;

				case 'c' :
					strfmt(r, "%0 %0 %2 %2:%2:%2 %4",
						  aday[t->tm_wday], amonth[t->tm_mon],
						  t->tm_mday,t->tm_hour, t->tm_min,
						  t->tm_sec, t->tm_year+1900);
					break;

				case 'd' :
					strfmt(r,"%2",t->tm_mday);
					break;

				case 'H' :
					strfmt(r,"%2",t->tm_hour);
					break;

				case 'I' :
					strfmt(r,"%2",(t->tm_hour%12)?t->tm_hour%12:12);
					break;

				case 'j' :
					strfmt(r,"%3",t->tm_yday+1);
					break;

				case 'm' :
					strfmt(r,"%2",t->tm_mon+1);
					break;

				case 'M' :
					strfmt(r,"%2",t->tm_min);
					break;

				case 'p' :
					r = (t->tm_hour>11)?"PM":"AM";
					break;

				case 'S' :
					strfmt(r,"%2",t->tm_sec);
					break;

				case 'U' :
					w = t->tm_yday/7;
					if (t->tm_yday%7 > t->tm_wday)
						w++;
					strfmt(r, "%2", w);
					break;

				case 'W' :
					w = (t->tm_yday + DAYSPERWEEK -
						(t->tm_wday ?
						(t->tm_wday - 1) :
						(DAYSPERWEEK - 1))) / DAYSPERWEEK;
					strfmt(r, "%2", w);
					break;

				case 'w' :
					strfmt(r,"%1",t->tm_wday);
					break;

				case 'x' :
					strfmt(r, "%2/%2/%2", t->tm_mon + 1,
						   t->tm_mday, t->tm_year+1900);
					break;

				case 'X' :
					strfmt(r, "%2:%2:%2", t->tm_hour,
						   t->tm_min, t->tm_sec);
					break;

				case 'y' :
					strfmt(r,"%2",t->tm_year%100);
					break;

				case 'Y' :
					strfmt(r,"%4",t->tm_year+1900);
					break;

				case 'Z' :
					r = (t->tm_isdst && tz_name[1][0])?tz_name[1]:tz_name[0];
					break;

				default:
					buf[0] = '%';		// reconstruct the format
					buf[1] = f[-1];
					buf[2] = '\0';
					if (buf[1] == 0)
						f--;			// back up if at end of string
			}
			while (*r)
			{
				if (p == q)
				{
					*q = '\0';
					return 0;
				}
				*p++ = *r++;
			}
		}
		else
		{
			if (p == q)
			{
				*q = '\0';
				return 0;
			}
			*p++ = f[-1];
		}
	}
	*p = '\0';
	return p - s;
}

//
// static void strfmt(char *str, char *fmt);
//
// simple sprintf for strftime
//
// each format descriptor is of the form %n
// where n goes from zero to four
//
// 0    -- string %s
// 1..4 -- int %?.?d
//
static void strfmt(char *str, const char *fmt, ...)
{
	int ival, ilen;
	char *sval;
	static int pow[5] = { 1, 10, 100, 1000, 10000 };
	va_list vp;

	va_start(vp, fmt);
	while (*fmt)
	{
		if (*fmt++ == '%')
		{
			ilen = *fmt++ - '0';
			if (ilen == 0)                // zero means string arg
			{
				sval = va_arg(vp, char*);
				while (*sval)
					*str++ = *sval++;
			}
			else                          // always leading zeros
			{
				ival = va_arg(vp, int);
				while (ilen)
				{
					ival %= pow[ilen--];
					*str++ = (char)('0' + ival / pow[ilen]);
				}
			}
		}
		else  *str++ = fmt[-1];
	}
	*str = '\0';
	va_end(vp);
}

// internal functions
//-----------------------------------------------------------------------------
// Convert 100ns units since 1601 to seconds since 1970
//
LONGLONG SystemTimeToSecondsSince1970(SYSTEMTIME *st)
{
	ULARGE_INTEGER	uli;
	FILETIME		ft;
	ULARGE_INTEGER	uli1970;
	FILETIME		ft1970;

	// convert to a FILETIME
	// Gives number of 100-nanosecond intervals since January 1, 1601 (UTC)
	//
	if(!SystemTimeToFileTime(st, &ft))
	{
		return TIME_FAILURE;
	}

	// convert to a FILETIME
	// Gives number of 100-nanosecond intervals since January 1, 1970 (UTC)
	//
	if(!SystemTimeToFileTime(&st1970, &ft1970))
	{
		return TIME_FAILURE;
	}

	// Copy file time structures into ularge integer so we can do
	// the math more easily
	//
	memcpy(&uli, &ft, sizeof(uli));
	memcpy(&uli1970, &ft1970, sizeof(uli1970));

	// Subtract the 1970 number of 100 ns value from the 1601 100 ns value
	// so we can get the number of 100 ns value between 1970 and now
	// then devide be 10,000,000 to get the number of seconds since 1970
	//
	uli.QuadPart = ((uli.QuadPart - uli1970.QuadPart) / 10000000);

	return (LONGLONG)uli.QuadPart;
}

// Convert seconds since 1970 to a file time in 100ns units since 1601
// then to a system time.
//
void SecondsSince1970ToSystemTime(const time_t * timer, SYSTEMTIME * st,
								  BOOLEAN local)
{
	ULARGE_INTEGER	uli;
	FILETIME		ft;
	ULARGE_INTEGER	uli1970;
	FILETIME		ft1970;

	// Convert system time to file time
	//
	if(!SystemTimeToFileTime(&st1970, &ft1970))
	{
		st = NULL;
		return;
	}

	// convert hundreds of nanosecs to secs: 1 sec = 1e7 100ns
	// Gives number of seconds since 1/1/1601 (UTC)
	//
  memcpy(&uli, timer, sizeof(uli));
  memcpy(&uli1970, &ft1970, sizeof(uli1970));

	// If we want local time then subtract the number of seconds between
	// UTC and current local time
	//
	if (local)
	{
		// Calculate 100ns since 1/1/1601 local time
		//
    uli.QuadPart = (((uli.QuadPart - _localtime)*10000000) + uli1970.QuadPart);
	}
	else
	{
		// Calculate 100ns since 1/1/1601 UTC
		//
		uli.QuadPart = ((uli.QuadPart)*10000000 + uli1970.QuadPart);
	}

	// copy data back into the ft
	//
	memcpy(&ft, &uli, sizeof(uli));

	// convert to a SYSTEMTIME
	//
	if(!FileTimeToSystemTime(&ft, st))
	{
		st = NULL;
		return;
	}

	return;
}

// Set the time zone information needed for the rest of the methods
//
void SetTz(SYSTEMTIME *_st)
{
	TIME_ZONE_INFORMATION	tz;
	SYSTEMTIME				st = *_st;
	FILETIME				ftDT; // Daylight savings file time
	FILETIME				ftST; // Standard time file time
	FILETIME				ft;   // file time to compare
	int						i;

	GetTimeZoneInformation(&tz);

	// Convert current system time, daylight savings changover time
	// and standard time to file time to see if current time is between
	// the two dates.  If so then we are in daylight savings otherwise we
	// are not.
	//
	SystemTimeToFileTime(&st, &ft);
	tz.DaylightDate.wYear = st.wYear;
	tz.StandardDate.wYear = st.wYear;
  SystemTimeToFileTime(&tz.DaylightDate, &ftDT);
	SystemTimeToFileTime(&tz.StandardDate, &ftST);

  // -1 First file time is earlier than second file time.
  //  0 First file time is equal to second file time.
  //  1 First file time is later than second file time.
	//
	if ((CompareFileTime(&ft,&ftDT) >= 0) && (CompareFileTime(&ft,&ftST) <= 0) )
	{
		_isdst = TRUE;
	}
	else
	{
		_isdst = FALSE;
	}

	// Set localtime difference in seconds from UTC
	//
	if (_isdst)
	{
		// Adjust for Daylight Savings Time and convert to seconds
		//
		_localtime = (tz.Bias + tz.DaylightBias) * SECS_IN_MIN;
	}
	else
	{
		// Convert to seconds
		//
		_localtime = tz.Bias * SECS_IN_MIN;
	}

	_dstBias = tz.DaylightBias;

	// Set the standard and daylight strings
	//
	for (i=0;i<32;i++)
	{
		tz_name[0][i] = (char)tz.StandardName[i];
		tz_name[1][i] = (char)tz.DaylightName[i];
	}
}

// Copy system time structure to tm structure
//
void SystemTimeToTm(SYSTEMTIME *st, struct tm * tmbuffer)
{
	tmbuffer->tm_hour = st->wHour;
    tmbuffer->tm_mday = st->wDay;
    tmbuffer->tm_min = st->wMinute;
    tmbuffer->tm_mon = st->wMonth - 1;
    tmbuffer->tm_sec = st->wSecond;
    tmbuffer->tm_wday = st->wDayOfWeek;
    tmbuffer->tm_yday = JulianDays(st);		// Julian days, numer of days since Jan 1
	tmbuffer->tm_year = st->wYear - 1900;
	tmbuffer->tm_isdst = _isdst;			// Is Daylight Savings Time
}

void TmToSystemTime(struct tm * tmbuffer, SYSTEMTIME *st)
{
  st->wHour = tmbuffer->tm_hour;
  st->wDay = tmbuffer->tm_mday;
  st->wMinute = tmbuffer->tm_min;
  st->wMonth = tmbuffer->tm_mon + 1;
  st->wSecond = tmbuffer->tm_sec;
  st->wDayOfWeek = tmbuffer->tm_wday;
  st->wYear = tmbuffer->tm_year + 1900;
  st->wMilliseconds = 0;
}

// Get the JulianDay from a Gregorian Date for number of days into the current
// year
// Algorithm from: http://www.vsg.cape.com/~pbaum/date/jdalg2.htm
//
DWORD JulianDays(SYSTEMTIME * st)
{
	int m = 0;
	int y = 0;
	double jdd = 0;
	double jddYearStart = 0;

	// Calculate the Julian day for the beginning of the year
	//
    m = 13;
	y = st->wYear - 1;
    jddYearStart = 1 + (153 * m - 457) / 5 + 365 * y + (y / 4) - (y / 100) + (y / 400) + 1721118.5;

	// Calculate Julian Day for Current Date
	//
	if (st->wMonth >= 3)
	{
		m = st->wMonth;
		y = st->wYear;
	}
    jdd = st->wDay + (153 * m - 457) / 5 + 365 * y + (y / 4) - (y / 100) + (y / 400) + 1721118.5;

	// Subract the year start Julian date from the Current Julian date to get
	// the number of Julian days from the year start
	//
	return (DWORD)(jdd - jddYearStart);
}
#endif //__GNUC__


/**
 * LuaCE
 *
 *      Pedro Miller Rabinovitch, <miller@inf.puc-rio.br>
 *      http://www.inf.puc-rio.br/~miller/luace
 *
 * A quick port of Lua for Windows CE.
 **/



//int errno = 0;

const char *getenv( const char *name ) {
	return NULL;
}


char *strdup( const char *str ) {
	char *ptr = (char *)malloc( sizeof(char) * strlen( str ) + 1 );
	strcpy( ptr, str );
	return ptr;
}

FILE *tmpfile() {
	return NULL;
}

char *tmpnam( char *str ) {
	return NULL;
}

#define _tcslen wcslen
#define _tcsncpy wcsncpy
#define _T(a) L##a

int system( const char *cmd ) {
	TCHAR tpath[MAX_PATH], args[1024], cmds[1024];
	BOOL ret, cont = TRUE;
	int i, len, exit_code = -100;
    PROCESS_INFORMATION pi;

    ZeroMemory( &pi, sizeof(pi) );

	memset(tpath,0,MAX_PATH*sizeof(TCHAR));
	memset(cmds,0,1024*sizeof(TCHAR));
	memset(args,0,1024*sizeof(TCHAR));

	mbstowcs(cmds, cmd, 1024);
	len = _tcslen(cmds);

	if (cmds[0] == _T('"')) {
		for (i = 1; i < len; i++) {
			if (cmds[i] == _T('"'))
				break;
		}
		if (i >= len)
			return -1;
		i++;
		_tcsncpy(tpath, cmds + 1, i - 2);
		_tcsncpy(args, cmds + i, len - i);
	}
	else {
		for (i = 0; i < len; i++) {
			if (cmds[i] == _T(' '))
				break;
		}
		_tcsncpy(tpath, cmds, i);
		_tcsncpy(args, cmds + i, len - i);
	}

#ifdef DEBUGGING_PROCESS
	ret = CreateProcess(tpath, args, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, NULL, &pi);
#else
	ret = CreateProcess(tpath, args, NULL, NULL, FALSE, 0, NULL, NULL, NULL, &pi);
#endif

	if (!ret) {
		return GetLastError();
	}

#ifdef DEBUGGING_PROCESS
	// Enter debug loop
	while (cont) {

		DEBUG_EVENT dbgEvt;

		if ( WaitForDebugEvent( &dbgEvt, INFINITE ) ) {

			switch (dbgEvt.dwDebugEventCode) {

				case EXCEPTION_DEBUG_EVENT:
					exit_code = (int) (dbgEvt.u.Exception.ExceptionRecord.ExceptionCode - 0xC0000000);
					TerminateProcess( pi.hProcess, exit_code + (1 << 16) );
					break;

				case EXIT_PROCESS_DEBUG_EVENT:
					cont = FALSE;
					break;
			}

			ContinueDebugEvent( dbgEvt.dwProcessId, dbgEvt.dwThreadId, DBG_CONTINUE );
		}
	}
#else
    // Wait until child process exits.
    WaitForSingleObject( pi.hProcess, INFINITE );
#endif

    GetExitCodeProcess( pi.hProcess, &exit_code );

    // Close process and thread handles.
    CloseHandle( pi.hProcess );

 	return exit_code;
}

/* alloc's and returns a converted wide-char string from a normal one */
wchar_t *atowcs( const char *str ) {
	int len;
	wchar_t *wstr;
	if( str == NULL )
		return NULL;
	len = strlen( str );
	wstr = (wchar_t *)malloc( sizeof( wchar_t )*2*(len + 1) );
	wsprintf( wstr, L"%hs", str );
	return wstr;
}

int rename( const char *src, const char *dst ) {
	wchar_t *wsrc = atowcs( src ),
		    *wdst = atowcs( dst );
	int res = 0;

	if( !MoveFile( wsrc, wdst ))
		res = GetLastError();

	free( wsrc );
	free( wdst );

	return res;
}

int remove( const char *fname ) {
	wchar_t *wfname = atowcs( fname );
	int res = 0;

	if( !DeleteFile( wfname ))
		res = GetLastError();

	free( wfname );

	return res;
}

char *setlocale( int category, const char *locale ) {
	return NULL;
}

struct lconv *localeconv( void )
{
	return NULL;
}


static int file_exists(const char* filename) {
  FILE* f = fopen(filename, "r");
  if(f != NULL)
  {
    fclose(f);
    return 1;
  }
  return 0;
}

static char* conv_filename(char *filename) {
  size_t i;
  for (i = 0; i < strlen(filename); i++) {
    if (filename[i] == '/')
      filename[i] = '\\';
  }
  return filename;
}

static char* find_file(const char* filename) {
  char* fullpath = malloc(sizeof(char) * (MAX_PATH + 1));
  if(!fullpath)
    return NULL;

  if (filename != NULL && strlen(filename) > 0)
  {
    if (filename[0] == '\\' || filename[0] == '/')//absolute path
    {
      strcpy(fullpath, filename);
      return conv_filename(fullpath);
    }
    else
    {
      TCHAR tpath[MAX_PATH + 1];
      char* lastDash;
      memset(tpath, 0, (MAX_PATH+1) * sizeof(TCHAR));
      GetModuleFileName(NULL, tpath, MAX_PATH);
      wcstombs(fullpath, tpath, MAX_PATH);
      lastDash = strrchr(fullpath,'\\');
      fullpath[lastDash - fullpath+1] = 0;
      strncat(fullpath, filename, MAX_PATH - strlen(filename));
      return conv_filename(fullpath);
    }
  }
  free(fullpath);
  return NULL;
}

FILE* _fopen(const char *filename, const char *flags) {
  FILE *fp = NULL;
  char *full_path = find_file(filename);
  if (full_path) {
    fp = fopen(full_path, flags);
    free(full_path);
  }
  return fp;
}

#if 0
int chdir(const char *path) {
	wchar_t *wpath = atowcs( path );
	int res = 0;

	if( !_wchdir( wpath ))
		res = GetLastError();

	free( wpath );

	return res;
}
#endif

int mkdir(const char *path) {
	wchar_t *wpath = atowcs( path );
	int res = 0;

	if( !CreateDirectory(wpath, NULL))
		res = GetLastError();

	free( wpath );

	return res;
}

HINSTANCE LoadLibraryA(LPCSTR path)
{
	wchar_t *wpath = atowcs( path );
	HINSTANCE res = LoadLibrary( wpath );
	free( wpath );
	return res;
}

HMODULE GetModuleHandleA(LPCSTR module)
{
	wchar_t *wmodule = atowcs( module );
	HMODULE res = GetModuleHandle( module );
	free( module );
	return res;
}
