msvcrt: Return a per-thread buffer in localtime and gmtime.
This commit is contained in:
parent
2bb87a90b2
commit
06c1a36bce
|
@ -74,6 +74,18 @@ typedef void (*MSVCRT__beginthread_start_routine_t)(void *);
|
|||
typedef unsigned int (__stdcall *MSVCRT__beginthreadex_start_routine_t)(void *);
|
||||
typedef int (*MSVCRT__onexit_t)(void);
|
||||
|
||||
struct MSVCRT_tm {
|
||||
int tm_sec;
|
||||
int tm_min;
|
||||
int tm_hour;
|
||||
int tm_mday;
|
||||
int tm_mon;
|
||||
int tm_year;
|
||||
int tm_wday;
|
||||
int tm_yday;
|
||||
int tm_isdst;
|
||||
};
|
||||
|
||||
|
||||
/* TLS data */
|
||||
extern DWORD msvcrt_tls_index;
|
||||
|
@ -84,6 +96,7 @@ struct __thread_data {
|
|||
unsigned char *mbstok_next; /* next ptr for mbstok() */
|
||||
char *efcvt_buffer; /* buffer for ecvt/fcvt */
|
||||
MSVCRT_wchar_t *wasctime_buffer; /* buffer for asctime */
|
||||
struct MSVCRT_tm time_buffer; /* buffer for localtime/gmtime */
|
||||
int fpecode;
|
||||
MSVCRT_terminate_function terminate_handler;
|
||||
MSVCRT_unexpected_function unexpected_handler;
|
||||
|
@ -173,18 +186,6 @@ extern unsigned msvcrt_create_io_inherit_block(STARTUPINFOA*);
|
|||
#define _RT_CRNL 252
|
||||
#define _RT_BANNER 255
|
||||
|
||||
struct MSVCRT_tm {
|
||||
int tm_sec;
|
||||
int tm_min;
|
||||
int tm_hour;
|
||||
int tm_mday;
|
||||
int tm_mon;
|
||||
int tm_year;
|
||||
int tm_wday;
|
||||
int tm_yday;
|
||||
int tm_isdst;
|
||||
};
|
||||
|
||||
struct MSVCRT__timeb {
|
||||
MSVCRT_time_t time;
|
||||
unsigned short millitm;
|
||||
|
|
|
@ -54,9 +54,6 @@ static inline int IsLeapYear(int Year)
|
|||
#define TICKSPERMSEC 10000
|
||||
#define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
|
||||
|
||||
/* native uses a single static buffer for localtime/gmtime/mktime */
|
||||
static struct MSVCRT_tm tm;
|
||||
|
||||
/**********************************************************************
|
||||
* mktime (MSVCRT.@)
|
||||
*/
|
||||
|
@ -65,7 +62,7 @@ MSVCRT_time_t MSVCRT_mktime(struct MSVCRT_tm *t)
|
|||
MSVCRT_time_t secs;
|
||||
FILETIME lft, uft;
|
||||
ULONGLONG time;
|
||||
struct MSVCRT_tm ts;
|
||||
struct MSVCRT_tm ts, *ptm;
|
||||
int cleaps, day;
|
||||
|
||||
ts=*t;
|
||||
|
@ -125,7 +122,7 @@ MSVCRT_time_t MSVCRT_mktime(struct MSVCRT_tm *t)
|
|||
secs = time - SECS_1601_TO_1970;
|
||||
/* compute tm_wday, tm_yday and renormalize the other fields of the
|
||||
* tm structure */
|
||||
if( MSVCRT_localtime( &secs)) *t = tm;
|
||||
if ((ptm = MSVCRT_localtime( &secs ))) *t = *ptm;
|
||||
|
||||
return secs;
|
||||
}
|
||||
|
@ -135,8 +132,8 @@ MSVCRT_time_t MSVCRT_mktime(struct MSVCRT_tm *t)
|
|||
*/
|
||||
struct MSVCRT_tm* MSVCRT_localtime(const MSVCRT_time_t* secs)
|
||||
{
|
||||
thread_data_t * const data = msvcrt_get_thread_data();
|
||||
int i;
|
||||
|
||||
FILETIME ft, lft;
|
||||
SYSTEMTIME st;
|
||||
DWORD tzid;
|
||||
|
@ -152,34 +149,37 @@ struct MSVCRT_tm* MSVCRT_localtime(const MSVCRT_time_t* secs)
|
|||
|
||||
if (st.wYear < 1970) return NULL;
|
||||
|
||||
tm.tm_sec = st.wSecond;
|
||||
tm.tm_min = st.wMinute;
|
||||
tm.tm_hour = st.wHour;
|
||||
tm.tm_mday = st.wDay;
|
||||
tm.tm_year = st.wYear - 1900;
|
||||
tm.tm_mon = st.wMonth - 1;
|
||||
tm.tm_wday = st.wDayOfWeek;
|
||||
data->time_buffer.tm_sec = st.wSecond;
|
||||
data->time_buffer.tm_min = st.wMinute;
|
||||
data->time_buffer.tm_hour = st.wHour;
|
||||
data->time_buffer.tm_mday = st.wDay;
|
||||
data->time_buffer.tm_year = st.wYear - 1900;
|
||||
data->time_buffer.tm_mon = st.wMonth - 1;
|
||||
data->time_buffer.tm_wday = st.wDayOfWeek;
|
||||
|
||||
for (i = tm.tm_yday = 0; i < st.wMonth - 1; i++) {
|
||||
tm.tm_yday += MonthLengths[IsLeapYear(st.wYear)][i];
|
||||
for (i = data->time_buffer.tm_yday = 0; i < st.wMonth - 1; i++) {
|
||||
data->time_buffer.tm_yday += MonthLengths[IsLeapYear(st.wYear)][i];
|
||||
}
|
||||
|
||||
tm.tm_yday += st.wDay - 1;
|
||||
data->time_buffer.tm_yday += st.wDay - 1;
|
||||
|
||||
tzid = GetTimeZoneInformation(&tzinfo);
|
||||
|
||||
if (tzid == TIME_ZONE_ID_INVALID)
|
||||
tm.tm_isdst = -1;
|
||||
data->time_buffer.tm_isdst = -1;
|
||||
else
|
||||
tm.tm_isdst = (tzid == TIME_ZONE_ID_DAYLIGHT?1:0);
|
||||
data->time_buffer.tm_isdst = (tzid == TIME_ZONE_ID_DAYLIGHT?1:0);
|
||||
|
||||
return &tm;
|
||||
return &data->time_buffer;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* gmtime (MSVCRT.@)
|
||||
*/
|
||||
struct MSVCRT_tm* MSVCRT_gmtime(const MSVCRT_time_t* secs)
|
||||
{
|
||||
thread_data_t * const data = msvcrt_get_thread_data();
|
||||
int i;
|
||||
|
||||
FILETIME ft;
|
||||
SYSTEMTIME st;
|
||||
|
||||
|
@ -192,21 +192,21 @@ struct MSVCRT_tm* MSVCRT_gmtime(const MSVCRT_time_t* secs)
|
|||
|
||||
if (st.wYear < 1970) return NULL;
|
||||
|
||||
tm.tm_sec = st.wSecond;
|
||||
tm.tm_min = st.wMinute;
|
||||
tm.tm_hour = st.wHour;
|
||||
tm.tm_mday = st.wDay;
|
||||
tm.tm_year = st.wYear - 1900;
|
||||
tm.tm_mon = st.wMonth - 1;
|
||||
tm.tm_wday = st.wDayOfWeek;
|
||||
for (i = tm.tm_yday = 0; i < st.wMonth - 1; i++) {
|
||||
tm.tm_yday += MonthLengths[IsLeapYear(st.wYear)][i];
|
||||
data->time_buffer.tm_sec = st.wSecond;
|
||||
data->time_buffer.tm_min = st.wMinute;
|
||||
data->time_buffer.tm_hour = st.wHour;
|
||||
data->time_buffer.tm_mday = st.wDay;
|
||||
data->time_buffer.tm_year = st.wYear - 1900;
|
||||
data->time_buffer.tm_mon = st.wMonth - 1;
|
||||
data->time_buffer.tm_wday = st.wDayOfWeek;
|
||||
for (i = data->time_buffer.tm_yday = 0; i < st.wMonth - 1; i++) {
|
||||
data->time_buffer.tm_yday += MonthLengths[IsLeapYear(st.wYear)][i];
|
||||
}
|
||||
|
||||
tm.tm_yday += st.wDay - 1;
|
||||
tm.tm_isdst = 0;
|
||||
data->time_buffer.tm_yday += st.wDay - 1;
|
||||
data->time_buffer.tm_isdst = 0;
|
||||
|
||||
return &tm;
|
||||
return &data->time_buffer;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
|
|
Loading…
Reference in New Issue