mirror of
https://git.code.sf.net/p/mingw-w64/mingw-w64
synced 2024-11-23 01:44:43 +08:00
crt: Add _(v)scwprintf emulation for msvcrt.dll
__ms_vsnwprintf() function now calls _vscwprintf() funcion. _vscwprintf() is not available in older msvcrt.dll version, so provide emulation of _scwprintf() and _vscwprintf() functions. This emulation is similar to existing _scprintf and _vscprintf emulation. Signed-off-by: Martin Storsjö <martin@martin.st>
This commit is contained in:
parent
c50df03570
commit
3d539d06a0
@ -489,7 +489,9 @@ src_msvcrt32=\
|
||||
misc/wctob.c \
|
||||
stdio/_fstat64i32.c \
|
||||
stdio/_scprintf.c \
|
||||
stdio/_scwprintf.c \
|
||||
stdio/_vscprintf.c \
|
||||
stdio/_vscwprintf.c \
|
||||
string/wcstok.c
|
||||
|
||||
# Files included in libmsvcrt-os.a (for msvcrt.dll) on x86_64
|
||||
@ -732,7 +734,9 @@ src_pre_msvcr70=\
|
||||
misc/wcstoimax.c \
|
||||
misc/wcstoumax.c \
|
||||
stdio/_scprintf.c \
|
||||
stdio/_vscprintf.c
|
||||
stdio/_scwprintf.c \
|
||||
stdio/_vscprintf.c \
|
||||
stdio/_vscwprintf.c
|
||||
|
||||
src_pre_msvcr71=\
|
||||
misc/_set_purecall_handler.c
|
||||
|
@ -1214,7 +1214,7 @@ _getwche
|
||||
_putwch
|
||||
_resetstkoflw
|
||||
F_NON_I386(_scprintf) ; i386 _scprintf replaced by emu
|
||||
_scwprintf
|
||||
F_NON_I386(_scwprintf) ; i386 _scwprintf replaced by emu
|
||||
F_I386(_set_SSE2_enable)
|
||||
_snscanf
|
||||
_snwscanf
|
||||
@ -1222,7 +1222,7 @@ F_NON_I386(_strtoi64) ; i386 _strtoi64 replaced by emu
|
||||
F_NON_I386(_strtoui64) ; i386 _strtoui64 replaced by emu
|
||||
_ungetwch
|
||||
F_NON_I386(_vscprintf) ; i386 _vscprintf replaced by emu
|
||||
_vscwprintf
|
||||
F_NON_I386(_vscwprintf) ; i386 _vscwprintf replaced by emu
|
||||
_wcserror
|
||||
F_NON_I386(_wcstoi64) ; i386 _wcstoi64 replaced by emu
|
||||
F_NON_I386(_wcstoui64) ; i386 _wcstoui64 replaced by emu
|
||||
|
67
mingw-w64-crt/stdio/_scwprintf.c
Normal file
67
mingw-w64-crt/stdio/_scwprintf.c
Normal file
@ -0,0 +1,67 @@
|
||||
/**
|
||||
* This file has no copyright assigned and is placed in the Public Domain.
|
||||
* This file is part of the mingw-w64 runtime package.
|
||||
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
|
||||
*/
|
||||
#include <windows.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
|
||||
/* mingw-w64 always provides _vscwprintf() implementation, so use it */
|
||||
static int __cdecl emu_scwprintf(const wchar_t * __restrict__ format, ...)
|
||||
{
|
||||
va_list arglist;
|
||||
int ret;
|
||||
|
||||
va_start(arglist, format);
|
||||
ret = _vscwprintf(format, arglist);
|
||||
va_end(arglist);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef __LIBMSVCRT_OS__
|
||||
|
||||
int __attribute__ ((alias ("emu_scwprintf"))) __cdecl _scwprintf(const wchar_t * __restrict__, ...);
|
||||
int (__cdecl *__MINGW_IMP_SYMBOL(_scwprintf))(const wchar_t * __restrict__, ...) = _scwprintf;
|
||||
|
||||
#else
|
||||
|
||||
#include <msvcrt.h>
|
||||
|
||||
static int __cdecl init_scwprintf(const wchar_t * __restrict__ format, ...);
|
||||
|
||||
int (__cdecl *__MINGW_IMP_SYMBOL(_scwprintf))(const wchar_t * __restrict__, ...) = init_scwprintf;
|
||||
|
||||
__attribute__((used))
|
||||
static void resolve_scwprintf(void)
|
||||
{
|
||||
HMODULE msvcrt = __mingw_get_msvcrt_handle();
|
||||
int (__cdecl *func)(const wchar_t * __restrict__, ...) = NULL;
|
||||
|
||||
if (msvcrt)
|
||||
func = (int (__cdecl *)(const wchar_t * __restrict__, ...))GetProcAddress(msvcrt, "_scwprintf");
|
||||
|
||||
if (!func)
|
||||
func = emu_scwprintf;
|
||||
|
||||
__MINGW_IMP_SYMBOL(_scwprintf) = func;
|
||||
}
|
||||
|
||||
/* gcc does not provide an easy way to call another variadic function with reusing current arguments
|
||||
* this source file is used only on i386, so do this function redirect via inline i386 assembly */
|
||||
#define ASM_SYM(sym) __MINGW64_STRINGIFY(__MINGW_USYMBOL(sym))
|
||||
asm (
|
||||
".def\t" ASM_SYM(init_scwprintf) ";\t.scl\t3;\t.type\t32;\t.endef\n"
|
||||
ASM_SYM(init_scwprintf) ":\n\t"
|
||||
"pushal\n\t"
|
||||
"call\t" ASM_SYM(resolve_scwprintf) "\n\t"
|
||||
"popal\n\t"
|
||||
/* fallthrough */
|
||||
".globl\t" ASM_SYM(_scwprintf) "\n\t"
|
||||
".def\t" ASM_SYM(_scwprintf) ";\t.scl\t2;\t.type\t32;\t.endef\n"
|
||||
ASM_SYM(_scwprintf) ":\n\t"
|
||||
"jmp\t*" ASM_SYM(__MINGW_IMP_SYMBOL(_scwprintf))
|
||||
);
|
||||
|
||||
#endif
|
87
mingw-w64-crt/stdio/_vscwprintf.c
Normal file
87
mingw-w64-crt/stdio/_vscwprintf.c
Normal file
@ -0,0 +1,87 @@
|
||||
/**
|
||||
* This file has no copyright assigned and is placed in the Public Domain.
|
||||
* This file is part of the mingw-w64 runtime package.
|
||||
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
|
||||
*/
|
||||
#include <windows.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* emulation of _vscwprintf() via _vsnwprintf() */
|
||||
static int __cdecl emu_vscwprintf(const wchar_t * __restrict__ format, va_list arglist)
|
||||
{
|
||||
wchar_t *buffer, *new_buffer;
|
||||
size_t size;
|
||||
int ret = -1;
|
||||
|
||||
/* if format is a null pointer, _vscwprintf() returns -1 and sets errno to EINVAL */
|
||||
if (!format) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* size for _vsnwprintf() must be non-zero and buffer must have place for terminating null character */
|
||||
size = (wcslen(format) * 2 + 1) * sizeof(wchar_t);
|
||||
buffer = malloc(size);
|
||||
|
||||
if (!buffer) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if the number of characters to write is greater than size, _vsnwprintf() returns -1 */
|
||||
while (size < SIZE_MAX/2 && (ret = _vsnwprintf(buffer, size, format, arglist)) < 0) {
|
||||
/* in this case try with larger buffer */
|
||||
size *= 2;
|
||||
new_buffer = realloc(buffer, size);
|
||||
if (!new_buffer)
|
||||
break;
|
||||
buffer = new_buffer;
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
|
||||
if (ret < 0) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef __LIBMSVCRT_OS__
|
||||
|
||||
int __attribute__ ((alias ("emu_vscwprintf"))) __cdecl _vscwprintf(const wchar_t * __restrict__, va_list);
|
||||
int (__cdecl *__MINGW_IMP_SYMBOL(_vscwprintf))(const wchar_t * __restrict__, va_list) = _vscwprintf;
|
||||
|
||||
#else
|
||||
|
||||
#include <msvcrt.h>
|
||||
|
||||
static int __cdecl init_vscwprintf(const wchar_t * __restrict__ format, va_list arglist);
|
||||
|
||||
int (__cdecl *__MINGW_IMP_SYMBOL(_vscwprintf))(const wchar_t * __restrict__, va_list) = init_vscwprintf;
|
||||
|
||||
static int __cdecl init_vscwprintf(const wchar_t * __restrict__ format, va_list arglist)
|
||||
{
|
||||
HMODULE msvcrt = __mingw_get_msvcrt_handle();
|
||||
int (__cdecl *func)(const wchar_t * __restrict__, va_list) = NULL;
|
||||
|
||||
if (msvcrt)
|
||||
func = (int (__cdecl *)(const wchar_t * __restrict__, va_list))GetProcAddress(msvcrt, "_vscwprintf");
|
||||
|
||||
if (!func)
|
||||
func = emu_vscwprintf;
|
||||
|
||||
return (__MINGW_IMP_SYMBOL(_vscwprintf) = func)(format, arglist);
|
||||
}
|
||||
|
||||
int __cdecl _vscwprintf(const wchar_t * __restrict__ format, va_list arglist)
|
||||
{
|
||||
return __MINGW_IMP_SYMBOL(_vscwprintf)(format, arglist);
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user