// Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // // Copyright (C) 2004-2018 by Sonic Team Jr. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // DESCRIPTION: // stub and replacement "ANSI" C functions for use under Windows CE // //----------------------------------------------------------------------------- #include "../../doomdef.h" #include "cehelp.h" #define _SEC_IN_MINUTE 60 #define _SEC_IN_HOUR 3600 #define _SEC_IN_DAY 86400 static const int DAYS_IN_MONTH[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; #define _DAYS_IN_MONTH(x) ((x == 1) ? days_in_feb : DAYS_IN_MONTH[x]) static const int _DAYS_BEFORE_MONTH[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; #define _ISLEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || (((y)+1900) % 400) == 0)) #define _DAYS_IN_YEAR(year) (_ISLEAP(year) ? 366 : 365) char *strerror(int ecode) { static char buff[1024 + 1]; DWORD dwMsgLen = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, ecode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &buff[0], 1024, NULL); return buff; } int unlink( const char *filename ) { return remove(filename); } int remove( const char *path ) { return DeleteFileA(path)-1; } int rename( const char *oldname, const char *newname ) { return MoveFileA(oldname, newname)!=0; } static inline void STToTM(const SYSTEMTIME *st, struct tm *tm) { if (!st || !tm) return; tm->tm_sec = st->wSecond; tm->tm_min = st->wMinute; tm->tm_hour = st->wHour; tm->tm_mday = st->wDay; tm->tm_mon = st->wMonth - 1; tm->tm_year = st->wYear - 1900; tm->tm_wday = st->wDayOfWeek; tm->tm_yday = 0; tm->tm_isdst = 0; } time_t time(time_t *T) { time_t returntime; SYSTEMTIME st; struct tm stft; GetSystemTime(&st); STToTM(&st,&stft); returntime = mktime(&stft); if (T) *T = returntime; return returntime; } static inline UINT64 TTtoFT(const time_t wt, FILETIME *ft) { UINT64 temptime = wt; // FILETIME: 1/(10^7) secs since January 1, 1601 temptime *= 10000000; // time_t : 1 secs since January 1, 1970 // 369 years * 365 days * 24 hours * 60 mins * 60 secs * 10 // 123 leaps days * 24 hours * 60 mins * 60 secs * 10 temptime += 116444736000000000; if (ft) CopyMemory(ft,&temptime,sizeof (ULARGE_INTEGER)); return temptime; } static struct tm cehelptm; struct tm * localtime(const time_t *CLOCK) { SYSTEMTIME st; FILETIME stft; UINT64 ftli = 0; if (CLOCK) ftli = TTtoFT(*CLOCK, &stft); if (ftli) FileTimeToSystemTime(&stft,&st); else GetSystemTime(&st); STToTM(&st,&cehelptm); if (st.wYear >= 1970) return &cehelptm; else return NULL; } static void validate_structure (struct tm *tim_p) // from newlib { div_t res; int days_in_feb = 28; /* calculate time & date to account for out of range values */ if (tim_p->tm_sec < 0 || tim_p->tm_sec > 59) { res = div (tim_p->tm_sec, 60); tim_p->tm_min += res.quot; if ((tim_p->tm_sec = res.rem) < 0) { tim_p->tm_sec += 60; --tim_p->tm_min; } } if (tim_p->tm_min < 0 || tim_p->tm_min > 59) { res = div (tim_p->tm_min, 60); tim_p->tm_hour += res.quot; if ((tim_p->tm_min = res.rem) < 0) { tim_p->tm_min += 60; --tim_p->tm_hour; } } if (tim_p->tm_hour < 0 || tim_p->tm_hour > 23) { res = div (tim_p->tm_hour, 24); tim_p->tm_mday += res.quot; if ((tim_p->tm_hour = res.rem) < 0) { tim_p->tm_hour += 24; --tim_p->tm_mday; } } if (tim_p->tm_mon > 11) { res = div (tim_p->tm_mon, 12); tim_p->tm_year += res.quot; if ((tim_p->tm_mon = res.rem) < 0) { tim_p->tm_mon += 12; --tim_p->tm_year; } } if (_DAYS_IN_YEAR (tim_p->tm_year) == 366) days_in_feb = 29; if (tim_p->tm_mday <= 0) { while (tim_p->tm_mday <= 0) { if (--tim_p->tm_mon == -1) { tim_p->tm_year--; tim_p->tm_mon = 11; days_in_feb = ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ? 29 : 28); } tim_p->tm_mday += _DAYS_IN_MONTH (tim_p->tm_mon); } } else { while (tim_p->tm_mday > _DAYS_IN_MONTH (tim_p->tm_mon)) { tim_p->tm_mday -= _DAYS_IN_MONTH (tim_p->tm_mon); if (++tim_p->tm_mon == 12) { tim_p->tm_year++; tim_p->tm_mon = 0; days_in_feb = ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ? 29 : 28); } } } } time_t mktime (struct tm *tim_p) // from newlib { time_t tim = 0; long days = 0; int year; /* validate structure */ validate_structure (tim_p); /* compute hours, minutes, seconds */ tim += tim_p->tm_sec + (tim_p->tm_min * _SEC_IN_MINUTE) + (tim_p->tm_hour * _SEC_IN_HOUR); /* compute days in year */ days += tim_p->tm_mday - 1; days += _DAYS_BEFORE_MONTH[tim_p->tm_mon]; if (tim_p->tm_mon > 1 && _DAYS_IN_YEAR (tim_p->tm_year) == 366) days++; /* compute day of the year */ tim_p->tm_yday = days; if (tim_p->tm_year > 10000 || tim_p->tm_year < -10000) { return (time_t) -1; } /* compute days in other years */ if (tim_p->tm_year > 70) { for (year = 70; year < tim_p->tm_year; year++) days += _DAYS_IN_YEAR (year); } else if (tim_p->tm_year < 70) { for (year = 69; year > tim_p->tm_year; year--) days -= _DAYS_IN_YEAR (year); days -= _DAYS_IN_YEAR (year); } /* compute day of the week */ if ((tim_p->tm_wday = (days + 4) % 7) < 0) tim_p->tm_wday += 7; /* compute total seconds */ tim += (days * _SEC_IN_DAY); return tim; } #undef WINAPI #define WINAPI __stdcall //__delcspec(dllexport) #ifdef _MSC_VER //#pragma warning(disable : 4273) #endif static __forceinline int STRtoWSTR(LPCSTR lpMultiByteStr, int cchMultiByte, LPWSTR lpWideCharStr, int cchWideChar) { return MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,lpMultiByteStr, cchMultiByte,lpWideCharStr,cchWideChar); } static __forceinline int WSTRtoSTR(LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte) { return WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK|WC_SEPCHARS, lpWideCharStr,cchWideChar,lpMultiByteStr,cbMultiByte,NULL,NULL); } DWORD WINAPI FormatMessageA( DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPSTR lpBuffer, DWORD nSize, va_list *Arguments) { const int nSizeW = STRtoWSTR(lpBuffer,nSize,NULL,0); int nSizeF = 0; LPWSTR lpBufferW = alloca(sizeof (wchar_t)*nSizeW); LPWSTR lpSourceW = NULL; if (!lpBufferW) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); ZeroMemory(lpBuffer,nSize); return nSizeF; } if (dwFlags & FORMAT_MESSAGE_FROM_STRING) { const int sLen = STRtoWSTR(lpSource, -1, NULL, 0); lpSourceW = alloca(sizeof (wchar_t)*sLen); if (lpSourceW) STRtoWSTR(lpSource, -1, lpSourceW, sLen); else { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return nSizeF; } } if (lpSourceW) nSizeF = FormatMessageW(dwFlags, lpSourceW, dwMessageId, dwLanguageId, lpBufferW, nSizeW, Arguments); else nSizeF = FormatMessageW(dwFlags, lpSource, dwMessageId, dwLanguageId, lpBufferW, nSizeW, Arguments); return WSTRtoSTR(lpBufferW, nSizeF, lpBuffer, nSize); } BOOL WINAPI DeleteFileA( LPCSTR lpFileName) { const int sLen = STRtoWSTR(lpFileName, -1, NULL, 0); LPWSTR lpFileNameW = alloca(sizeof (wchar_t)*sLen); if (lpFileNameW) STRtoWSTR(lpFileName, -1, lpFileNameW, sLen); else { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return 0; } return DeleteFileW(lpFileNameW); } BOOL WINAPI MoveFileA( LPCSTR lpExistingFileName, LPCSTR lpNewFileName ) { const int sLen1 = STRtoWSTR(lpExistingFileName, -1, NULL, 0); LPWSTR lpExistingFileNameW = alloca(sizeof (wchar_t)*sLen1); const int sLen2 = STRtoWSTR(lpNewFileName, -1, NULL, 0); LPWSTR lpNewFileNameW = alloca(sizeof (wchar_t)*sLen2); if (!lpExistingFileNameW || !lpNewFileNameW) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return 0; } STRtoWSTR(lpExistingFileName, -1, lpExistingFileNameW, sLen1); STRtoWSTR(lpNewFileName, -1, lpNewFileNameW, sLen2); return MoveFileW(lpExistingFileNameW, lpNewFileNameW); } HANDLE WINAPI CreateFileA( LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { const int sLen = STRtoWSTR(lpFileName, -1, NULL, 0); LPWSTR lpFileNameW = alloca(sizeof (wchar_t)*sLen); if (lpFileNameW) STRtoWSTR(lpFileName, -1, lpFileNameW, sLen); else { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return INVALID_HANDLE_VALUE; } return CreateFileW(lpFileNameW, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); } BOOL WINAPI CreateDirectoryA( LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes) { const int sLen = STRtoWSTR(lpPathName, -1, NULL, 0); LPWSTR lpPathNameW = alloca(sizeof (wchar_t)*sLen); if (lpPathNameW) STRtoWSTR(lpPathName, -1, lpPathNameW, sLen); else { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return 0; } return CreateDirectoryW(lpPathNameW, lpSecurityAttributes); } int WINAPI MessageBoxA( HWND hWnd , LPCSTR lpText, LPCSTR lpCaption, UINT uType) { const int sLen1 = STRtoWSTR(lpText, -1, NULL, 0); LPWSTR lpTextW = alloca(sizeof (wchar_t)*sLen1); const int sLen2 = STRtoWSTR(lpCaption, -1, NULL, 0); LPWSTR lpCaptionW = alloca(sizeof (wchar_t)*sLen2); if (!lpTextW || !lpCaptionW) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return 0; } STRtoWSTR(lpText, -1, lpTextW, sLen1); STRtoWSTR(lpCaption, -1, lpCaptionW, sLen2); return MessageBoxW(hWnd, lpTextW, lpCaptionW, uType); } VOID WINAPI OutputDebugStringA( LPCSTR lpOutputString) { const int sLen = STRtoWSTR(lpOutputString, -1, NULL, 0); LPWSTR lpOutputStringW = alloca(sizeof (wchar_t)*sLen); if (lpOutputStringW) STRtoWSTR(lpOutputString, -1, lpOutputStringW, sLen); else { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return; } OutputDebugStringW(lpOutputStringW); }