Samuel Serapión (samdwise51 AT gmail DOT com):

- Sync parts of msvcrt with Wine (more will follow)
  This makes us passing a lot more msvcrt Wine tests (like all heap tests)

svn path=/trunk/; revision=33747
This commit is contained in:
Colin Finck 2008-05-28 21:08:23 +00:00
parent c6aa541df2
commit 1e95911991
21 changed files with 1445 additions and 851 deletions

File diff suppressed because it is too large Load diff

View file

@ -39,6 +39,7 @@
</directory>
<directory name="except">
<file>abnorter.c</file>
<file>checkesp.c</file>
<file>cpp.c</file>
<file>cppexcept.c</file>
<file>matherr.c</file>
@ -416,6 +417,7 @@
<file>wcsnlen.c</file>
<file>wcsrchr.c</file>
</ifnot>
<file>atol.c</file>
<file>atof.c</file>
<file>ctype.c</file>
<file>lasttok.c</file>

View file

@ -34,6 +34,7 @@
#include "wine/debug.h"
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#include <internal/wine/msvcrt.h>
#include <internal/wine/cppexcept.h>

View file

@ -1,15 +1,106 @@
#include <precomp.h>
#include "include/internal/wine/msvcrt.h"
#include "include/internal/wine/cppexcept.h"
typedef void (*sighandler_t)(int);
static sighandler_t sighandlers[NSIG] = { SIG_DFL };
/* The exception codes are actually NTSTATUS values */
static const struct
{
NTSTATUS status;
int signal;
} float_exception_map[] = {
{ EXCEPTION_FLT_DENORMAL_OPERAND, _FPE_DENORMAL },
{ EXCEPTION_FLT_DIVIDE_BY_ZERO, _FPE_ZERODIVIDE },
{ EXCEPTION_FLT_INEXACT_RESULT, _FPE_INEXACT },
{ EXCEPTION_FLT_INVALID_OPERATION, _FPE_INVALID },
{ EXCEPTION_FLT_OVERFLOW, _FPE_OVERFLOW },
{ EXCEPTION_FLT_STACK_CHECK, _FPE_STACKOVERFLOW },
{ EXCEPTION_FLT_UNDERFLOW, _FPE_UNDERFLOW },
};
/*
* @unimplemented
* @implemented
*/
int
_XcptFilter(DWORD ExceptionCode,
struct _EXCEPTION_POINTERS * ExceptionInfo)
struct _EXCEPTION_POINTERS * except)
{
//fixme XcptFilter
// return UnhandledExceptionFilter(ExceptionInfo);
return 0;
LONG ret = EXCEPTION_CONTINUE_SEARCH;
sighandler_t handler;
if (!except || !except->ExceptionRecord)
return EXCEPTION_CONTINUE_SEARCH;
switch (except->ExceptionRecord->ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
if ((handler = sighandlers[SIGSEGV]) != SIG_DFL)
{
if (handler != SIG_IGN)
{
sighandlers[SIGSEGV] = SIG_DFL;
handler(SIGSEGV);
}
ret = EXCEPTION_CONTINUE_EXECUTION;
}
break;
/* According to msdn,
* the FPE signal handler takes as a second argument the type of
* floating point exception.
*/
case EXCEPTION_FLT_DENORMAL_OPERAND:
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
case EXCEPTION_FLT_INEXACT_RESULT:
case EXCEPTION_FLT_INVALID_OPERATION:
case EXCEPTION_FLT_OVERFLOW:
case EXCEPTION_FLT_STACK_CHECK:
case EXCEPTION_FLT_UNDERFLOW:
if ((handler = sighandlers[SIGFPE]) != SIG_DFL)
{
if (handler != SIG_IGN)
{
int i, float_signal = _FPE_INVALID;
sighandlers[SIGFPE] = SIG_DFL;
for (i = 0; i < sizeof(float_exception_map) /
sizeof(float_exception_map[0]); i++)
{
if (float_exception_map[i].status ==
except->ExceptionRecord->ExceptionCode)
{
float_signal = float_exception_map[i].signal;
break;
}
}
((float_handler)handler)(SIGFPE, float_signal);
}
ret = EXCEPTION_CONTINUE_EXECUTION;
}
break;
case EXCEPTION_ILLEGAL_INSTRUCTION:
if ((handler = sighandlers[SIGILL]) != SIG_DFL)
{
if (handler != SIG_IGN)
{
sighandlers[SIGILL] = SIG_DFL;
handler(SIGILL);
}
ret = EXCEPTION_CONTINUE_EXECUTION;
}
break;
}
return ret;
}
int CDECL __CppXcptFilter(NTSTATUS ex, PEXCEPTION_POINTERS ptr)
{
/* only filter c++ exceptions */
if (ex != CXX_EXCEPTION) return EXCEPTION_CONTINUE_SEARCH;
return _XcptFilter( ex, ptr );
}

View file

@ -138,8 +138,8 @@ void _CxxThrowException(exception*,const cxx_exception_type*);
static inline const char *dbgstr_type_info( const type_info *info )
{
if (!info) return "{}";
return wine_dbg_sprintf( "{vtable=%p name=%s (%s)}",
info->vtable, info->mangled, info->name ? info->name : "" );
return "{}";/*sprintf( "{vtable=%p name=%s (%s)}",
info->vtable, info->mangled, info->name ? info->name : "" );*/
}
/* compute the this pointer for a base class of a given type */

View file

@ -22,13 +22,15 @@
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include "float.h"
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winnls.h"
//#include "msvcrt/string.h"
#include "eh.h"
typedef unsigned short MSVCRT_wchar_t;
@ -132,6 +134,9 @@ extern void msvcrt_free_console(void);
extern void msvcrt_init_args(void);
extern void msvcrt_free_args(void);
#define MSVCRT__OUT_TO_DEFAULT 0
#define MSVCRT__REPORT_ERRMODE 3
/* run-time error codes */
#define _RT_STACK 0
#define _RT_NULLPTR 1
@ -183,6 +188,17 @@ struct MSVCRT___JUMP_BUFFER {
};
#endif /* __i386__ */
typedef void (*float_handler)(int, int);
void _default_handler(int signal);
typedef struct _sig_element
{
int signal;
char *signame;
__p_sig_fn_t handler;
}sig_element;
typedef void* (*malloc_func_t)(size_t);
typedef void (*free_func_t)(void*);
#define MSVCRT_malloc malloc

View file

@ -724,3 +724,8 @@ int __crtLCMapStringA(
*/
return LCMapStringA(lcid,mapflags,src,srclen,dst,dstlen);
}
int CDECL _getmbcp(void)
{
return MSVCRT___lc_codepage;
}

View file

@ -1,5 +1,5 @@
#include <math.h>
#include <internal/debug.h>
double _CIsin(double x);
double _CIcos(double x);
@ -131,3 +131,89 @@ double _CIfmod(double x, double y)
{
return fmod(x, y);
}
/* The following functions are likely workarounds for the pentium fdiv bug */
void __stdcall _adj_fdiv_m32( unsigned int arg )
{
DPRINT("_adj_fdiv_m32 stub\n");
}
void __stdcall _adj_fdiv_m32i( int arg )
{
DPRINT1("_adj_fdiv_m32i stub\n");
}
void __stdcall _adj_fdiv_m64( unsigned __int64 arg )
{
DPRINT1("_adj_fdiv_m64 stub\n");
}
void _adj_fdiv_r(void)
{
DPRINT1("_adj_fdiv_r stub\n");
}
void __stdcall _adj_fdivr_m32( unsigned int arg )
{
DPRINT1("_adj_fdivr_m32i stub\n");
}
void __stdcall _adj_fdivr_m32i( int arg )
{
DPRINT1("_adj_fdivr_m32i stub\n");
}
void __stdcall _adj_fdivr_m64( unsigned __int64 arg )
{
DPRINT1("_adj_fdivr_m64 stub\n");
}
void _adj_fpatan(void)
{
DPRINT1("_adj_fpatan stub\n");
}
void __stdcall _adj_fdiv_m16i( short arg )
{
DPRINT("_adj_fdiv_m16i stub\n");
}
void __stdcall _adj_fdivr_m16i( short arg )
{
DPRINT("_adj_fdivr_m16i stub\n");
}
void _adj_fprem(void)
{
DPRINT("_adj_fprem stub\n");
}
void _adj_fprem1(void)
{
DPRINT("_adj_fprem1 stub\n");
}
void _adj_fptan(void)
{
DPRINT("_adj_fptan stub\n");
}
void _safe_fdiv(void)
{
DPRINT("_safe_fdiv stub\n");
}
void _safe_fdivr(void)
{
DPRINT("_safe_fdivr stub\n");
}
void _safe_fprem(void)
{
DPRINT("_safe_fprem stub\n");
}
void _safe_fprem1(void)
{
DPRINT("_safe_fprem1 stub\n");
}

View file

@ -133,3 +133,23 @@ int _ismbcl2(unsigned int c)
{
return 0;
}
/*
* @unimplemented
*/
int _ismbcgraph(unsigned int ch)
{
//wchar_t wch = msvcrt_mbc_to_wc( ch );
//return (get_char_typeW( wch ) & (C1_UPPER | C1_LOWER | C1_DIGIT | C1_PUNCT | C1_ALPHA));
return 0;
}
/*
* @unimplemented
*/
int _ismbcpunct(unsigned int ch)
{
//wchar_t wch = msvcrt_mbc_to_wc( ch );
//return (get_char_typeW( wch ) & C1_PUNCT);
return 0;
}

View file

@ -64,3 +64,11 @@ int _ismbslead( const unsigned char *str, const unsigned char *t)
return _ismbblead( *s);
}
/*
* @implemented
*/
unsigned char *__p__mbctype(void)
{
return _mbctype;
}

View file

@ -3,6 +3,12 @@
#define NDEBUG
#include <internal/debug.h>
int __STRINGTOLD( long double *value, char **endptr, const char *str, int flags )
{
DPRINT1("%p %p %s %x stub\n", value, endptr, str, flags );
return 0;
}
/*********************************************************************
* $I10_OUTPUT (MSVCRT.@)
* Function not really understood but needed to make the DLL work
@ -12,127 +18,11 @@ void MSVCRT_I10_OUTPUT(void)
/* FIXME: This is probably data, not a function */
}
/***********************************************************************
* _adj_fdiv_m32 (MSVCRT.@)
*
* NOTE
* I _think_ this function is intended to work around the Pentium
* fdiv bug.
*/
void __stdcall _adj_fdiv_m32( unsigned int arg )
{
DPRINT1("_adj_fdiv_m32 stub\n");
}
/***********************************************************************
* _adj_fdiv_m32i (MSVCRT.@)
*
* NOTE
* I _think_ this function is intended to work around the Pentium
* fdiv bug.
*/
void __stdcall _adj_fdiv_m32i( int arg )
{
DPRINT1("_adj_fdiv_m32i stub\n");
}
/***********************************************************************
* _adj_fdiv_m64 (MSVCRT.@)
*
* NOTE
* I _think_ this function is intended to work around the Pentium
* fdiv bug.
*/
void __stdcall _adj_fdiv_m64( unsigned __int64 arg )
{
DPRINT1("_adj_fdiv_m64 stub\n");
}
/***********************************************************************
* _adj_fdiv_r (MSVCRT.@)
* FIXME
* This function is likely to have the wrong number of arguments.
*
* NOTE
* I _think_ this function is intended to work around the Pentium
* fdiv bug.
*/
void _adj_fdiv_r(void)
{
DPRINT1("_adj_fdiv_r stub\n");
}
/***********************************************************************
* _adj_fdivr_m32 (MSVCRT.@)
*
* NOTE
* I _think_ this function is intended to work around the Pentium
* fdiv bug.
*/
void __stdcall _adj_fdivr_m32( unsigned int arg )
{
DPRINT1("_adj_fdivr_m32i stub\n");
}
/***********************************************************************
* _adj_fdivr_m32i (MSVCRT.@)
*
* NOTE
* I _think_ this function is intended to work around the Pentium
* fdiv bug.
*/
void __stdcall _adj_fdivr_m32i( int arg )
{
DPRINT1("_adj_fdivr_m32i stub\n");
}
/***********************************************************************
* _adj_fdivr_m64 (MSVCRT.@)
*
* NOTE
* I _think_ this function is intended to work around the Pentium
* fdiv bug.
*/
void __stdcall _adj_fdivr_m64( unsigned __int64 arg )
{
DPRINT1("_adj_fdivr_m64 stub\n");
}
/***********************************************************************
* _adj_fpatan (MSVCRT.@)
* FIXME
* This function is likely to have the wrong number of arguments.
*
* NOTE
* I _think_ this function is intended to work around the Pentium
* fdiv bug.
*/
void _adj_fpatan(void)
{
DPRINT1("_adj_fpatan stub\n");
}
void __crtCompareStringA(void)
{
DPRINT1("__crtCompareStringA stub\n");
}
void __crtGetLocaleInfoW(void)
{
DPRINT1("__crtGetLocaleInfoW stub\n");
}
void __p__amblksiz(void)
{
DPRINT1("__p__amblksiz stub\n");
}
void __p__dstbias(void)
{
DPRINT1("__p__dstbias stub\n");
}
void __fileinfo(void)
{
DPRINT1("__fileinfo stub\n");
@ -142,3 +32,26 @@ void stub(void)
{
DPRINT1("stub\n");
}
/*********************************************************************
* _getmaxstdio (MSVCRT.@)
*/
int CDECL _getmaxstdio(void)
{
DPRINT1("stub, always returns 512\n");
return 512;
}
/*********************************************************************
* _setmaxstdio_ (MSVCRT.@)
*/
int CDECL _setmaxstdio(int newmax)
{
int res;
if( newmax > 2048)
res = -1;
else
res = newmax;
DPRINT1("stub: setting new maximum for number of simultaneously open files not implemented,returning %d\n",res);
return res;
}

View file

@ -14,6 +14,8 @@
#include <string.h>
#include <process.h>
#define NDEBUG
#include<internal/debug.h>
/*
* @implemented
*/
@ -112,3 +114,9 @@ int system(const char *command)
return nStatus;
}
int CDECL _wsystem(const wchar_t* cmd)
{
DPRINT1("_wsystem stub\n");
return -1;
}

View file

@ -1,19 +1,5 @@
#include <precomp.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
void _default_handler(int signal);
typedef struct _sig_element
{
int signal;
char *signame;
__p_sig_fn_t handler;
}
sig_element;
#include "include/internal/wine/msvcrt.h"
static sig_element signal_list[] =
{
@ -34,8 +20,6 @@ static sig_element signal_list[] =
//void ( *signal( int sig, void (__cdecl *func) ( int sig [, int subcode ] )) ) ( int sig );
__p_sig_fn_t signal(int sig, __p_sig_fn_t func)
{
__p_sig_fn_t temp;
@ -139,3 +123,6 @@ void _default_handler(int sig)
}

View file

@ -3,6 +3,7 @@
*/
#include <precomp.h>
#include "doserrmap.h"
#include <internal/wine/msvcrt.h>
/*
* @implemented
@ -71,4 +72,40 @@ void _dosmaperr(unsigned long oserror)
__set_errno(EINVAL);
}
/******************************************************************************
* _set_error_mode (MSVCRT.@)
*
* Set the error mode, which describes where the C run-time writes error
* messages.
*
* PARAMS
* mode - the new error mode
*
* RETURNS
* The old error mode.
*
* TODO
* This function does not have a proper implementation; the error mode is
* never used.
*/
int CDECL _set_error_mode(int mode)
{
static int current_mode = MSVCRT__OUT_TO_DEFAULT;
const int old = current_mode;
if ( MSVCRT__REPORT_ERRMODE != mode ) {
current_mode = mode;
}
return old;
}
/******************************************************************************
* _seterrormode (MSVCRT.@)
*/
void CDECL _seterrormode(int mode)
{
SetErrorMode( mode );
}
/* EOF */

View file

@ -5,15 +5,6 @@
unsigned char _cpumode = 0;
unsigned char *_cpumode_dll = &_cpumode;
/*
* @implemented
*/
void _seterrormode(int nMode)
{
SetErrorMode(nMode);
return;
}
/*
* @implemented
*/

View file

@ -10,3 +10,10 @@ _ttol(const _TCHAR *str)
{
return _tcstol(str, 0, 10);
}
int _atoldbl(long double *value, const char *str)
{
/* FIXME needs error checking for huge/small values */
//*value = strtold(str,0);
return 0;
}

View file

@ -11,6 +11,8 @@
#include <precomp.h>
#include <sys/stat.h>
#define NDEBUG
#include <debug.h>
/*
* @implemented
@ -78,3 +80,9 @@ int _fstati64(int fd, struct _stati64* statbuf)
}
return 0;
}
int _fstat64(int fd, struct __stat64* buf)
{
DPRINT1("stub\n");
return -1;
}

View file

@ -10,6 +10,15 @@
#include <precomp.h>
#include <sys/stat.h>
#include <direct.h>
#define NDEBUG
#include <internal/debug.h>
/* for stat mode, permissions apply to all,owner and group */
#define ALL_S_IREAD (S_IREAD | (S_IREAD >> 3) | (S_IREAD >> 6))
#define ALL_S_IWRITE (S_IWRITE | (S_IWRITE >> 3) | (S_IWRITE >> 6))
#define ALL_S_IEXEC (S_IEXEC | (S_IEXEC >> 3) | (S_IEXEC >> 6))
/*
* @implemented
@ -118,3 +127,69 @@ int _stati64 (const char *path, struct _stati64 *buffer)
return 0;
}
/*********************************************************************
* _stat64 (MSVCRT.@)
*/
int CDECL _stat64(const char* path, struct __stat64 * buf)
{
DWORD dw;
WIN32_FILE_ATTRIBUTE_DATA hfi;
unsigned short mode = ALL_S_IREAD;
int plen;
if (!GetFileAttributesExA(path, GetFileExInfoStandard, &hfi))
{
DPRINT1("failed (%d)\n",GetLastError());
*_errno() = ERROR_FILE_NOT_FOUND;
return -1;
}
memset(buf,0,sizeof(struct __stat64));
/* FIXME: rdev isn't drive num, despite what the docs say-what is it?
Bon 011120: This FIXME seems incorrect
Also a letter as first char isn't enough to be classified
as a drive letter
*/
if (isalpha(*path)&& (*(path+1)==':'))
buf->st_dev = buf->st_rdev = toupper(*path) - 'A'; /* drive num */
else
buf->st_dev = buf->st_rdev = _getdrive() - 1;
plen = strlen(path);
/* Dir, or regular file? */
if ((hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
(path[plen-1] == '\\'))
mode |= (S_IFDIR | ALL_S_IEXEC);
else
{
mode |= S_IFREG;
/* executable? */
if (plen > 6 && path[plen-4] == '.') /* shortest exe: "\x.exe" */
{
char* ext = strrchr(path, '.');
if (ext && (!_stricmp(ext, ".exe") || !_stricmp(ext, ".com") || !_stricmp(ext, ".bat") ||
!_stricmp(ext, ".cmd")))
mode |= S_IEXEC;
}
}
if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
mode |= ALL_S_IWRITE;
buf->st_mode = mode;
buf->st_nlink = 1;
buf->st_size = ((__int64)hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow;
RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw);
buf->st_atime = dw;
RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw);
buf->st_mtime = buf->st_ctime = dw;
DPRINT("%d %d 0x%08lx%08lx %ld %ld %ld\n", buf->st_mode,buf->st_nlink,
(long)(buf->st_size >> 32),(long)buf->st_size,
(long)buf->st_atime,(long)buf->st_mtime,(long)buf->st_ctime);
return 0;
}

View file

@ -10,6 +10,13 @@
#include <precomp.h>
#include <sys/stat.h>
#include <wchar.h>
#include <direct.h>
/* for stat mode, permissions apply to all,owner and group */
#define ALL_S_IREAD (S_IREAD | (S_IREAD >> 3) | (S_IREAD >> 6))
#define ALL_S_IWRITE (S_IWRITE | (S_IWRITE >> 3) | (S_IWRITE >> 6))
#define ALL_S_IEXEC (S_IEXEC | (S_IEXEC >> 3) | (S_IEXEC >> 6))
/*
* @implemented
@ -117,3 +124,61 @@ int _wstati64 (const wchar_t *path, struct _stati64 *buffer)
return 0;
}
/*********************************************************************
* _wstat64 (MSVCRT.@)
*/
int CDECL _wstat64(const wchar_t* path, struct __stat64 * buf)
{
DWORD dw;
WIN32_FILE_ATTRIBUTE_DATA hfi;
unsigned short mode = ALL_S_IREAD;
int plen;
if (!GetFileAttributesExW(path, GetFileExInfoStandard, &hfi))
{
__set_errno(ERROR_FILE_NOT_FOUND);
return -1;
}
memset(buf,0,sizeof(struct __stat64));
/* FIXME: rdev isn't drive num, despite what the docs says-what is it? */
if (iswalpha(*path))
buf->st_dev = buf->st_rdev = towupper(*path - 'A'); /* drive num */
else
buf->st_dev = buf->st_rdev = _getdrive() - 1;
plen = wcslen(path);
/* Dir, or regular file? */
if ((hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
(path[plen-1] == '\\'))
mode |= (S_IFDIR | ALL_S_IEXEC);
else
{
mode |= S_IFREG;
/* executable? */
if (plen > 6 && path[plen-4] == '.') /* shortest exe: "\x.exe" */
{
wchar_t* ext = wcsrchr(path, L'.');
if (ext && (!_wcsicmp(ext, L".exe") || !_wcsicmp(ext, L".com") ||
!_wcsicmp(ext, L".bat") || !_wcsicmp(ext, L".cmd")))
mode |= S_IEXEC;
}
}
if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
mode |= ALL_S_IWRITE;
buf->st_mode = mode;
buf->st_nlink = 1;
buf->st_size = ((__int64)hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow;
RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw);
buf->st_atime = dw;
RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw);
buf->st_mtime = buf->st_ctime = dw;
return 0;
}

View file

@ -1436,3 +1436,25 @@ mktime(struct tm * tmp)
{
return time1(tmp, localsub, 0L);
}
/*
* @implemented
*/
char **
__p__tzname(void)
{
return _tzname;
}
/*********************************************************************
* _dstbias (MSVCRT.@)
*/
int _dstbias = 0;
/*********************************************************************
* __p_dstbias (MSVCRT.@)
*/
int * __p__dstbias(void)
{
return &_dstbias;
}

View file

@ -34,12 +34,20 @@
#define LOCK_HEAP _mlock( _HEAP_LOCK )
#define UNLOCK_HEAP _munlock( _HEAP_LOCK )
/* _aligned */
#define SAVED_PTR(x) ((void *)((DWORD_PTR)((char *)x - sizeof(void *)) & \
~(sizeof(void *) - 1)))
#define ALIGN_PTR(ptr, alignment, offset) ((void *) \
((((DWORD_PTR)((char *)ptr + alignment + sizeof(void *) + offset)) & \
~(alignment - 1)) - offset))
typedef void (*MSVCRT_new_handler_func)(unsigned long size);
static MSVCRT_new_handler_func MSVCRT_new_handler;
static int MSVCRT_new_mode;
/* FIXME - According to documentation it should be 480 bytes, at runtime default is 0 */
static size_t MSVCRT_sbh_threshold = 0;
/*********************************************************************
* ??2@YAPAXI@Z (MSVCRT.@)
@ -118,6 +126,33 @@ int MSVCRT__set_new_mode(int mode)
return old_mode;
}
int CDECL _callnewh(unsigned long size)
{
if(MSVCRT_new_handler)
(*MSVCRT_new_handler)(size);
return 0;
}
/*********************************************************************
* _get_sbh_threshold (MSVCRT.@)
*/
size_t CDECL _get_sbh_threshold(void)
{
return MSVCRT_sbh_threshold;
}
/*********************************************************************
* _set_sbh_threshold (MSVCRT.@)
*/
int CDECL _set_sbh_threshold(size_t threshold)
{
if(threshold > 1016)
return 0;
else
MSVCRT_sbh_threshold = threshold;
return 1;
}
/*********************************************************************
* _heapadd (MSVCRT.@)
*/
@ -127,3 +162,175 @@ int _heapadd(void* mem, size_t size)
*_errno() = ENOSYS;
return -1;
}
void CDECL _aligned_free(void *memblock)
{
if (memblock)
{
void **saved = SAVED_PTR(memblock);
free(*saved);
}
}
void * CDECL _aligned_offset_malloc(size_t size, size_t alignment, size_t offset)
{
void *memblock, *temp, **saved;
/* alignment must be a power of 2 */
if ((alignment & (alignment - 1)) != 0)
{
*_errno() = EINVAL;
return NULL;
}
/* offset must be less than size */
if (offset >= size)
{
*_errno() = EINVAL;
return NULL;
}
/* don't align to less than void pointer size */
if (alignment < sizeof(void *))
alignment = sizeof(void *);
/* allocate enough space for void pointer and alignment */
temp = malloc(size + alignment + sizeof(void *));
if (!temp)
return NULL;
/* adjust pointer for proper alignment and offset */
memblock = ALIGN_PTR(temp, alignment, offset);
/* Save the real allocation address below returned address */
/* so it can be found later to free. */
saved = SAVED_PTR(memblock);
*saved = temp;
return memblock;
}
void * CDECL _aligned_malloc(size_t size, size_t alignment)
{
return _aligned_offset_malloc(size, alignment, 0);
}
void * CDECL _aligned_offset_realloc(void *memblock, size_t size,
size_t alignment, size_t offset)
{
void * temp, **saved;
size_t old_padding, new_padding, old_size;
if (!memblock)
return _aligned_offset_malloc(size, alignment, offset);
/* alignment must be a power of 2 */
if ((alignment & (alignment - 1)) != 0)
{
*_errno() = EINVAL;
return NULL;
}
/* offset must be less than size */
if (offset >= size)
{
*_errno() = EINVAL;
return NULL;
}
if (size == 0)
{
_aligned_free(memblock);
return NULL;
}
/* don't align to less than void pointer size */
if (alignment < sizeof(void *))
alignment = sizeof(void *);
/* make sure alignment and offset didn't change */
saved = SAVED_PTR(memblock);
if (memblock != ALIGN_PTR(*saved, alignment, offset))
{
*_errno() = EINVAL;
return NULL;
}
old_padding = (char *)memblock - (char *)*saved;
/* Get previous size of block */
old_size = _msize(*saved);
if (old_size == -1)
{
/* It seems this function was called with an invalid pointer. Bail out. */
return NULL;
}
/* Adjust old_size to get amount of actual data in old block. */
if (old_size < old_padding)
{
/* Shouldn't happen. Something's weird, so bail out. */
return NULL;
}
old_size -= old_padding;
temp = realloc(*saved, size + alignment + sizeof(void *));
if (!temp)
return NULL;
/* adjust pointer for proper alignment and offset */
memblock = ALIGN_PTR(temp, alignment, offset);
/* Save the real allocation address below returned address */
/* so it can be found later to free. */
saved = SAVED_PTR(memblock);
new_padding = (char *)memblock - (char *)temp;
/*
Memory layout of old block is as follows:
+-------+---------------------+-+--------------------------+-----------+
| ... | "old_padding" bytes | | ... "old_size" bytes ... | ... |
+-------+---------------------+-+--------------------------+-----------+
^ ^ ^
| | |
*saved saved memblock
Memory layout of new block is as follows:
+-------+-----------------------------+-+----------------------+-------+
| ... | "new_padding" bytes | | ... "size" bytes ... | ... |
+-------+-----------------------------+-+----------------------+-------+
^ ^ ^
| | |
temp saved memblock
However, in the new block, actual data is still written as follows
(because it was copied by MSVCRT_realloc):
+-------+---------------------+--------------------------------+-------+
| ... | "old_padding" bytes | ... "old_size" bytes ... | ... |
+-------+---------------------+--------------------------------+-------+
^ ^ ^
| | |
temp saved memblock
Therefore, min(old_size,size) bytes of actual data have to be moved
from the offset they were at in the old block (temp + old_padding),
to the offset they have to be in the new block (temp + new_padding == memblock).
*/
if (new_padding != old_padding)
memmove((char *)memblock, (char *)temp + old_padding, (old_size < size) ? old_size : size);
*saved = temp;
return memblock;
}
void * CDECL _aligned_realloc(void *memblock, size_t size, size_t alignment)
{
return _aligned_offset_realloc(memblock, size, alignment, 0);
}