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 ...@@ -14619,6 +14619,7 @@ fi
for ac_func in \ for ac_func in \
_lwp_create \ _lwp_create \
_lwp_self \ _lwp_self \
...@@ -14629,6 +14630,7 @@ for ac_func in \ ...@@ -14629,6 +14630,7 @@ for ac_func in \
_stricmp \ _stricmp \
_strnicmp \ _strnicmp \
_vsnprintf \ _vsnprintf \
asctime_r \
chsize \ chsize \
clone \ clone \
epoll_create \ epoll_create \
......
...@@ -1157,6 +1157,7 @@ AC_CHECK_FUNCS(\ ...@@ -1157,6 +1157,7 @@ AC_CHECK_FUNCS(\
_stricmp \ _stricmp \
_strnicmp \ _strnicmp \
_vsnprintf \ _vsnprintf \
asctime_r \
chsize \ chsize \
clone \ clone \
epoll_create \ epoll_create \
......
...@@ -73,6 +73,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) ...@@ -73,6 +73,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
if (tls) if (tls)
{ {
HeapFree(GetProcessHeap(),0,tls->efcvt_buffer); HeapFree(GetProcessHeap(),0,tls->efcvt_buffer);
HeapFree(GetProcessHeap(),0,tls->asctime_buffer);
HeapFree(GetProcessHeap(),0,tls->wasctime_buffer); HeapFree(GetProcessHeap(),0,tls->wasctime_buffer);
} }
HeapFree(GetProcessHeap(), 0, tls); HeapFree(GetProcessHeap(), 0, tls);
......
...@@ -95,7 +95,8 @@ struct __thread_data { ...@@ -95,7 +95,8 @@ struct __thread_data {
unsigned long thread_doserrno; unsigned long thread_doserrno;
unsigned char *mbstok_next; /* next ptr for mbstok() */ unsigned char *mbstok_next; /* next ptr for mbstok() */
char *efcvt_buffer; /* buffer for ecvt/fcvt */ 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 */ struct MSVCRT_tm time_buffer; /* buffer for localtime/gmtime */
int fpecode; int fpecode;
MSVCRT_terminate_function terminate_handler; MSVCRT_terminate_function terminate_handler;
......
...@@ -570,7 +570,7 @@ ...@@ -570,7 +570,7 @@
@ cdecl abort() MSVCRT_abort @ cdecl abort() MSVCRT_abort
@ cdecl abs(long) @ cdecl abs(long)
@ cdecl acos(double) @ cdecl acos(double)
@ cdecl asctime(ptr) @ cdecl asctime(ptr) MSVCRT_asctime
@ cdecl asin(double) @ cdecl asin(double)
@ cdecl atan(double) @ cdecl atan(double)
@ cdecl atan2(double double) @ cdecl atan2(double double)
...@@ -585,7 +585,7 @@ ...@@ -585,7 +585,7 @@
@ cdecl clock() MSVCRT_clock @ cdecl clock() MSVCRT_clock
@ cdecl cos(double) @ cdecl cos(double)
@ cdecl cosh(double) @ cdecl cosh(double)
@ cdecl ctime(ptr) @ cdecl ctime(ptr) MSVCRT_ctime
@ cdecl difftime(long long) MSVCRT_difftime @ cdecl difftime(long long) MSVCRT_difftime
@ cdecl div(long long) MSVCRT_div @ cdecl div(long long) MSVCRT_div
@ cdecl exit(long) MSVCRT_exit @ cdecl exit(long) MSVCRT_exit
...@@ -704,7 +704,7 @@ ...@@ -704,7 +704,7 @@
@ cdecl strcpy(ptr str) @ cdecl strcpy(ptr str)
@ cdecl strcspn(str str) @ cdecl strcspn(str str)
@ cdecl strerror(long) MSVCRT_strerror @ cdecl strerror(long) MSVCRT_strerror
@ cdecl strftime(str long str ptr) @ cdecl strftime(str long str ptr) MSVCRT_strftime
@ cdecl strlen(str) @ cdecl strlen(str)
@ cdecl strncat(str str long) @ cdecl strncat(str str long)
@ cdecl strncmp(str str long) @ cdecl strncmp(str str long)
......
...@@ -47,6 +47,20 @@ static inline int IsLeapYear(int Year) ...@@ -47,6 +47,20 @@ static inline int IsLeapYear(int Year)
return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0); 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 #define SECSPERDAY 86400
/* 1601 to 1970 is 369 years plus 89 leap days */ /* 1601 to 1970 is 369 years plus 89 leap days */
#define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY) #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
...@@ -412,33 +426,73 @@ void MSVCRT__tzset(void) ...@@ -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(); thread_data_t *data = msvcrt_get_thread_data();
struct tm xtm; struct tm tm;
char buffer[30];
memset(&xtm,0,sizeof(xtm));
xtm.tm_sec = mstm->tm_sec; msvcrt_tm_to_unix( &tm, mstm );
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;
if (!data->wasctime_buffer) if (!data->wasctime_buffer)
data->wasctime_buffer = MSVCRT_malloc( 30*sizeof(MSVCRT_wchar_t) ); /* ought to be enough */ 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; return data->wasctime_buffer;
} }
/********************************************************************* /*********************************************************************
* ctime (MSVCRT.@)
*/
char *MSVCRT_ctime(const MSVCRT_time_t *time)
{
return MSVCRT_asctime( MSVCRT_localtime(time) );
}
/*********************************************************************
* _wctime (MSVCRT.@) * _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) ); return MSVCRT__wasctime( MSVCRT_localtime(time) );
} }
...@@ -20,6 +20,9 @@ ...@@ -20,6 +20,9 @@
/* Define if you have ARTS sound server */ /* Define if you have ARTS sound server */
#undef HAVE_ARTS #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. */ /* Define to 1 if you have the <asm/types.h> header file. */
#undef HAVE_ASM_TYPES_H #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