Commit f9e5b0f5 authored by Alexandre Julliard's avatar Alexandre Julliard

msvcrt: Implemented asctime, ctime and strftime instead of using the libc ones.

Make the code thread-safe by using asctime_r if available.
parent b52146d9
......@@ -14619,6 +14619,7 @@ fi
for ac_func in \
_lwp_create \
_lwp_self \
......@@ -14629,6 +14630,7 @@ for ac_func in \
_stricmp \
_strnicmp \
_vsnprintf \
asctime_r \
chsize \
clone \
epoll_create \
......
......@@ -1157,6 +1157,7 @@ AC_CHECK_FUNCS(\
_stricmp \
_strnicmp \
_vsnprintf \
asctime_r \
chsize \
clone \
epoll_create \
......
......@@ -73,6 +73,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
if (tls)
{
HeapFree(GetProcessHeap(),0,tls->efcvt_buffer);
HeapFree(GetProcessHeap(),0,tls->asctime_buffer);
HeapFree(GetProcessHeap(),0,tls->wasctime_buffer);
}
HeapFree(GetProcessHeap(), 0, tls);
......
......@@ -95,7 +95,8 @@ struct __thread_data {
unsigned long thread_doserrno;
unsigned char *mbstok_next; /* next ptr for mbstok() */
char *efcvt_buffer; /* buffer for ecvt/fcvt */
MSVCRT_wchar_t *wasctime_buffer; /* buffer for asctime */
char *asctime_buffer; /* buffer for asctime */
MSVCRT_wchar_t *wasctime_buffer; /* buffer for wasctime */
struct MSVCRT_tm time_buffer; /* buffer for localtime/gmtime */
int fpecode;
MSVCRT_terminate_function terminate_handler;
......
......@@ -570,7 +570,7 @@
@ cdecl abort() MSVCRT_abort
@ cdecl abs(long)
@ cdecl acos(double)
@ cdecl asctime(ptr)
@ cdecl asctime(ptr) MSVCRT_asctime
@ cdecl asin(double)
@ cdecl atan(double)
@ cdecl atan2(double double)
......@@ -585,7 +585,7 @@
@ cdecl clock() MSVCRT_clock
@ cdecl cos(double)
@ cdecl cosh(double)
@ cdecl ctime(ptr)
@ cdecl ctime(ptr) MSVCRT_ctime
@ cdecl difftime(long long) MSVCRT_difftime
@ cdecl div(long long) MSVCRT_div
@ cdecl exit(long) MSVCRT_exit
......@@ -704,7 +704,7 @@
@ cdecl strcpy(ptr str)
@ cdecl strcspn(str str)
@ cdecl strerror(long) MSVCRT_strerror
@ cdecl strftime(str long str ptr)
@ cdecl strftime(str long str ptr) MSVCRT_strftime
@ cdecl strlen(str)
@ cdecl strncat(str str long)
@ cdecl strncmp(str str long)
......
......@@ -47,6 +47,20 @@ static inline int IsLeapYear(int Year)
return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0);
}
static inline void msvcrt_tm_to_unix( struct tm *dest, const struct MSVCRT_tm *src )
{
memset( dest, 0, sizeof(*dest) );
dest->tm_sec = src->tm_sec;
dest->tm_min = src->tm_min;
dest->tm_hour = src->tm_hour;
dest->tm_mday = src->tm_mday;
dest->tm_mon = src->tm_mon;
dest->tm_year = src->tm_year;
dest->tm_wday = src->tm_wday;
dest->tm_yday = src->tm_yday;
dest->tm_isdst = src->tm_isdst;
}
#define SECSPERDAY 86400
/* 1601 to 1970 is 369 years plus 89 leap days */
#define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
......@@ -412,33 +426,73 @@ void MSVCRT__tzset(void)
}
/*********************************************************************
* _wctime (MSVCRT.@)
* strftime (MSVCRT.@)
*/
MSVCRT_size_t MSVCRT_strftime( char *str, MSVCRT_size_t max, const char *format,
const struct MSVCRT_tm *mstm )
{
struct tm tm;
msvcrt_tm_to_unix( &tm, mstm );
return strftime( str, max, format, &tm );
}
/*********************************************************************
* asctime (MSVCRT.@)
*/
char *MSVCRT_asctime(const struct MSVCRT_tm *mstm)
{
thread_data_t *data = msvcrt_get_thread_data();
struct tm tm;
msvcrt_tm_to_unix( &tm, mstm );
if (!data->asctime_buffer)
data->asctime_buffer = MSVCRT_malloc( 30 ); /* ought to be enough */
/* FIXME: may want to map from Unix codepage to CP_ACP */
#ifdef HAVE_ASCTIME_R
asctime_r( &tm, data->asctime_buffer );
#else
strcpy( data->asctime_buffer, asctime(&tm) );
#endif
return data->asctime_buffer;
}
/*********************************************************************
* _wasctime (MSVCRT.@)
*/
MSVCRT_wchar_t *MSVCRT__wasctime(const struct MSVCRT_tm *mstm) {
MSVCRT_wchar_t *MSVCRT__wasctime(const struct MSVCRT_tm *mstm)
{
thread_data_t *data = msvcrt_get_thread_data();
struct tm xtm;
memset(&xtm,0,sizeof(xtm));
xtm.tm_sec = mstm->tm_sec;
xtm.tm_min = mstm->tm_min;
xtm.tm_hour = mstm->tm_hour;
xtm.tm_mday = mstm->tm_mday;
xtm.tm_mon = mstm->tm_mon;
xtm.tm_year = mstm->tm_year;
xtm.tm_wday = mstm->tm_wday;
xtm.tm_yday = mstm->tm_yday;
xtm.tm_isdst = mstm->tm_isdst;
struct tm tm;
char buffer[30];
msvcrt_tm_to_unix( &tm, mstm );
if (!data->wasctime_buffer)
data->wasctime_buffer = MSVCRT_malloc( 30*sizeof(MSVCRT_wchar_t) ); /* ought to be enough */
MultiByteToWideChar( CP_UNIXCP, 0, asctime(&xtm), -1, data->wasctime_buffer, 30 );
#ifdef HAVE_ASCTIME_R
asctime_r( &tm, buffer );
#else
strcpy( buffer, asctime(&tm) );
#endif
MultiByteToWideChar( CP_UNIXCP, 0, buffer, -1, data->wasctime_buffer, 30 );
return data->wasctime_buffer;
}
/*********************************************************************
* ctime (MSVCRT.@)
*/
char *MSVCRT_ctime(const MSVCRT_time_t *time)
{
return MSVCRT_asctime( MSVCRT_localtime(time) );
}
/*********************************************************************
* _wctime (MSVCRT.@)
*/
MSVCRT_wchar_t *MSVCRT__wctime(MSVCRT_time_t *time)
MSVCRT_wchar_t *MSVCRT__wctime(const MSVCRT_time_t *time)
{
return MSVCRT__wasctime( MSVCRT_localtime(time) );
}
......@@ -20,6 +20,9 @@
/* Define if you have ARTS sound server */
#undef HAVE_ARTS
/* Define to 1 if you have the `asctime_r' function. */
#undef HAVE_ASCTIME_R
/* Define to 1 if you have the <asm/types.h> header file. */
#undef HAVE_ASM_TYPES_H
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment