msvcrt: Added sprintf_p_l implementation.

oldstable
Piotr Caban 2011-04-27 12:09:01 +02:00 committed by Alexandre Julliard
parent a415974b2e
commit 00182ca6d9
9 changed files with 246 additions and 17 deletions

View File

@ -1119,7 +1119,7 @@
@ cdecl _splitpath_s(str ptr long ptr long ptr long ptr long) msvcrt._splitpath_s
@ stub _sprintf_l
@ stub _sprintf_p
@ stub _sprintf_p_l
@ varargs _sprintf_p_l(ptr long str ptr) msvcrt._sprintf_p_l
@ stub _sprintf_s_l
@ varargs _sscanf_l(str str ptr) msvcrt._sscanf_l
@ varargs _sscanf_s_l(str str ptr) msvcrt._sscanf_s_l
@ -1174,7 +1174,7 @@
@ stub _swprintf_c
@ stub _swprintf_c_l
@ stub _swprintf_p
@ stub _swprintf_p_l
@ varargs _swprintf_p_l(ptr long wstr ptr) msvcrt._swprintf_p_l
@ stub _swprintf_s_l
@ varargs _swscanf_l(wstr wstr ptr) msvcrt._swscanf_l
@ varargs _swscanf_s_l(wstr wstr ptr) msvcrt._swscanf_s_l
@ -1259,8 +1259,8 @@
@ cdecl _vsnwprintf_s(ptr long long wstr ptr) msvcrt._vsnwprintf_s
@ cdecl _vsnwprintf_s_l(ptr long long wstr ptr ptr) msvcrt._vsnwprintf_s_l
@ stub _vsprintf_l
@ stub _vsprintf_p
@ stub _vsprintf_p_l
@ cdecl _vsprintf_p(ptr long str ptr) msvcrt._vsprintf_p
@ cdecl _vsprintf_p_l(ptr long str ptr ptr) msvcrt._vsprintf_p_l
@ stub _vsprintf_s_l
@ cdecl _vswprintf(ptr long wstr ptr) msvcrt._vswprintf
@ cdecl _vswprintf_c(ptr long wstr ptr) msvcrt._vswprintf_c

View File

@ -973,7 +973,7 @@
@ cdecl _splitpath_s(str ptr long ptr long ptr long ptr long) msvcrt._splitpath_s
@ stub _sprintf_l
@ stub _sprintf_p
@ stub _sprintf_p_l
@ varargs _sprintf_p_l(ptr long str ptr) msvcrt._sprintf_p_l
@ stub _sprintf_s_l
@ varargs _sscanf_l(str str ptr) msvcrt._sscanf_l
@ varargs _sscanf_s_l(str str ptr) msvcrt._sscanf_s_l
@ -1027,7 +1027,7 @@
@ stub _swprintf
@ stub _swprintf_c
@ stub _swprintf_p
@ stub _swprintf_p_l
@ varargs _swprintf_p_l(ptr long wstr ptr) msvcrt._swprintf_p_l
@ stub _swprintf_s_l
@ varargs _swscanf_l(wstr wstr ptr) msvcrt._swscanf_l
@ varargs _swscanf_s_l(wstr wstr ptr) msvcrt._swscanf_s_l
@ -1112,8 +1112,8 @@
@ cdecl _vsnwprintf_s(ptr long long wstr ptr) msvcrt._vsnwprintf_s
@ cdecl _vsnwprintf_s_l(ptr long long wstr ptr ptr) msvcrt._vsnwprintf_s_l
@ stub _vsprintf_l
@ stub _vsprintf_p
@ stub _vsprintf_p_l
@ cdecl _vsprintf_p(ptr long str ptr) msvcrt._vsprintf_p
@ cdecl _vsprintf_p_l(ptr long str ptr ptr) msvcrt._vsprintf_p_l
@ stub _vsprintf_s_l
@ cdecl _vswprintf(ptr long wstr ptr) msvcrt._vswprintf
@ cdecl _vswprintf_c(ptr long wstr ptr) msvcrt._vswprintf_c

View File

@ -959,7 +959,7 @@
@ cdecl _splitpath_s(str ptr long ptr long ptr long ptr long) msvcrt._splitpath_s
@ stub _sprintf_l
@ stub _sprintf_p
@ stub _sprintf_p_l
@ varargs _sprintf_p_l(ptr long str ptr) msvcrt._sprintf_p_l
@ stub _sprintf_s_l
@ varargs _sscanf_l(str str ptr) msvcrt._sscanf_l
@ varargs _sscanf_s_l(str str ptr) msvcrt._sscanf_s_l
@ -1014,7 +1014,7 @@
@ stub _swprintf_c
@ stub _swprintf_c_l
@ stub _swprintf_p
@ stub _swprintf_p_l
@ varargs _swprintf_p_l(ptr long wstr ptr) msvcrt._swprintf_p_l
@ stub _swprintf_s_l
@ varargs _swscanf_l(wstr wstr ptr) msvcrt._swscanf_l
@ varargs _swscanf_s_l(wstr wstr ptr) msvcrt._swscanf_s_l
@ -1099,8 +1099,8 @@
@ cdecl _vsnwprintf_s(ptr long long wstr ptr) msvcrt._vsnwprintf_s
@ cdecl _vsnwprintf_s_l(ptr long long wstr ptr ptr) msvcrt._vsnwprintf_s_l
@ stub _vsprintf_l
@ stub _vsprintf_p
@ stub _vsprintf_p_l
@ cdecl _vsprintf_p(ptr long str ptr) msvcrt._vsprintf_p
@ cdecl _vsprintf_p_l(ptr long str ptr ptr) msvcrt._vsprintf_p_l
@ stub _vsprintf_s_l
@ cdecl _vswprintf(ptr long wstr ptr) msvcrt._vswprintf
@ cdecl _vswprintf_c(ptr long wstr ptr) msvcrt._vswprintf_c

View File

@ -916,6 +916,7 @@ void __cdecl MSVCRT__invalid_parameter(const MSVCRT_wchar_t *expr, const MSVCRT_
#define MSVCRT_CHECK_PMT(x) ((x) || (MSVCRT_INVALID_PMT(0),FALSE))
#endif
#define MSVCRT__ARGMAX 100
typedef int (*puts_clbk_a)(void*, int, const char*);
typedef int (*puts_clbk_w)(void*, int, const MSVCRT_wchar_t*);
typedef union _printf_arg
@ -931,6 +932,7 @@ int pf_printf_a(puts_clbk_a, void*, const char*, MSVCRT__locale_t,
int pf_printf_w(puts_clbk_w, void*, const MSVCRT_wchar_t*, MSVCRT__locale_t,
BOOL, BOOL, args_clbk, void*, __ms_va_list);
printf_arg arg_clbk_valist(void*, int, int, __ms_va_list*);
printf_arg arg_clbk_positional(void*, int, int, __ms_va_list*);
#define MSVCRT__OVERFLOW 3
#define MSVCRT__UNDERFLOW 4

View File

@ -901,7 +901,7 @@
@ cdecl _splitpath(str ptr ptr ptr ptr)
@ cdecl _splitpath_s(str ptr long ptr long ptr long ptr long)
# stub _sprintf_l
# stub _sprintf_p_l
@ varargs _sprintf_p_l(ptr long str ptr) MSVCRT_sprintf_p_l
# stub _sprintf_s_l
@ varargs _sscanf_l(str str ptr) MSVCRT__sscanf_l
@ varargs _sscanf_s_l(str str ptr) MSVCRT__sscanf_s_l
@ -954,7 +954,7 @@
# stub _swprintf
# stub _swprintf_c
# stub _swprintf_c_l
# stub _swprintf_p_l
@ varargs _swprintf_p_l(ptr long wstr ptr) MSVCRT_swprintf_p_l
# stub _swprintf_s_l
@ varargs _swscanf_l(wstr wstr ptr) MSVCRT__swscanf_l
@ varargs _swscanf_s_l(wstr wstr ptr) MSVCRT__swscanf_s_l
@ -1035,14 +1035,14 @@
@ cdecl _vsnwprintf_s(ptr long long wstr ptr) MSVCRT_vsnwprintf_s
@ cdecl _vsnwprintf_s_l(ptr long long wstr ptr ptr) MSVCRT_vsnwprintf_s_l
# stub _vsprintf_l
# stub _vsprintf_p
# stub _vsprintf_p_l
@ cdecl _vsprintf_p(ptr long str ptr) MSVCRT_vsprintf_p
@ cdecl _vsprintf_p_l(ptr long str ptr ptr) MSVCRT_vsprintf_p_l
# stub _vsprintf_s_l
@ cdecl _vswprintf(ptr long wstr ptr) MSVCRT_vsnwprintf
@ cdecl _vswprintf_c(ptr long wstr ptr) MSVCRT_vsnwprintf
@ cdecl _vswprintf_c_l(ptr long wstr ptr ptr) MSVCRT_vsnwprintf_l
@ cdecl _vswprintf_l(ptr long wstr ptr ptr) MSVCRT_vsnwprintf_l
@ cdecl _vswprintf_p_l(ptr long wstr ptr ptr) MSVCRT_vsnwprintf_l
@ cdecl _vswprintf_p_l(ptr long wstr ptr ptr) MSVCRT_vswprintf_p_l
@ cdecl _vswprintf_s_l(ptr long wstr ptr ptr) MSVCRT_vswprintf_s_l
# stub _vwprintf_l
# stub _vwprintf_p

View File

@ -553,6 +553,79 @@ int FUNC_NAME(pf_printf)(FUNC_NAME(puts_clbk) pf_puts, void *puts_ctx, const API
return written;
}
#ifndef PRINTF_WIDE
enum types_clbk_flags {
TYPE_CLBK_VA_LIST = 1,
TYPE_CLBK_POSITIONAL = 2,
TYPE_CLBK_ERROR_POS = 4,
TYPE_CLBK_ERROR_TYPE = 8
};
/* This functions stores types of arguments. It uses args[0] internally */
static printf_arg arg_clbk_type(void *ctx, int pos, int type, __ms_va_list *valist)
{
static const printf_arg ret;
printf_arg *args = ctx;
if(pos == -1) {
args[0].get_int |= TYPE_CLBK_VA_LIST;
return ret;
} else
args[0].get_int |= TYPE_CLBK_POSITIONAL;
if(pos<1 || pos>MSVCRT__ARGMAX)
args[0].get_int |= TYPE_CLBK_ERROR_POS;
else if(args[pos].get_int && args[pos].get_int!=type)
args[0].get_int |= TYPE_CLBK_ERROR_TYPE;
else
args[pos].get_int = type;
return ret;
}
#endif
static int FUNC_NAME(create_positional_ctx)(void *args_ctx, const APICHAR *format, __ms_va_list valist)
{
struct FUNC_NAME(_str_ctx) puts_ctx = {INT_MAX, NULL};
printf_arg *args = args_ctx;
int i, j;
i = FUNC_NAME(pf_printf)(FUNC_NAME(puts_clbk_str), &puts_ctx, format, NULL, TRUE, FALSE,
arg_clbk_type, args_ctx, NULL);
if(i < 0)
return i;
if(args[0].get_int==0 || args[0].get_int==TYPE_CLBK_VA_LIST)
return 0;
if(args[0].get_int != TYPE_CLBK_POSITIONAL)
return -1;
for(i=MSVCRT__ARGMAX; i>0; i--)
if(args[i].get_int)
break;
for(j=1; j<=i; j++) {
switch(args[j].get_int) {
case VT_I8:
args[j].get_longlong = va_arg(valist, LONGLONG);
break;
case VT_INT:
args[j].get_int = va_arg(valist, int);
break;
case VT_R8:
args[j].get_double = va_arg(valist, double);
break;
case VT_PTR:
args[j].get_ptr = va_arg(valist, void*);
break;
default:
return -1;
}
}
return j;
}
#undef APICHAR
#undef CONVCHAR
#undef FUNC_NAME

View File

@ -44,6 +44,7 @@ static int (__cdecl *p__ecvt_s)(char *buffer, size_t length, double number,
static int (__cdecl *p__fcvt_s)(char *buffer, size_t length, double number,
int ndigits, int *decpt, int *sign);
static unsigned int (__cdecl *p__get_output_format)(void);
static int (__cdecl *p__vsprintf_p)(char*, size_t, const char*, __ms_va_list);
static void init( void )
{
@ -55,6 +56,7 @@ static void init( void )
p__ecvt_s = (void *)GetProcAddress(hmod, "_ecvt_s");
p__fcvt_s = (void *)GetProcAddress(hmod, "_fcvt_s");
p__get_output_format = (void *)GetProcAddress(hmod, "_get_output_format");
p__vsprintf_p = (void*)GetProcAddress(hmod, "_vsprintf_p");
}
static void test_sprintf( void )
@ -1050,6 +1052,47 @@ static void test_vsnwprintf_s(void)
ok( !wcscmp(out1, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
}
static int __cdecl _vsprintf_p_wrapper(char *str, size_t sizeOfBuffer,
const char *format, ...)
{
int ret;
__ms_va_list valist;
__ms_va_start(valist, format);
ret = p__vsprintf_p(str, sizeOfBuffer, format, valist);
__ms_va_end(valist);
return ret;
}
static void test_vsprintf_p(void)
{
char buf[1024];
int ret;
if(!p__vsprintf_p) {
win_skip("vsprintf_p not available\n");
return;
}
ret = _vsprintf_p_wrapper(buf, sizeof(buf), "%s %d", "test", 1234);
ok(ret == 9, "ret = %d\n", ret);
ok(!memcmp(buf, "test 1234", 10), "buf = %s\n", buf);
ret = _vsprintf_p_wrapper(buf, sizeof(buf), "%1$d", 1234, "additional param");
ok(ret == 4, "ret = %d\n", ret);
ok(!memcmp(buf, "1234", 5), "buf = %s\n", buf);
ret = _vsprintf_p_wrapper(buf, sizeof(buf), "%2$s %1$d", 1234, "test");
ok(ret == 9, "ret = %d\n", ret);
ok(!memcmp(buf, "test 1234", 10), "buf = %s\n", buf);
ret = _vsprintf_p_wrapper(buf, sizeof(buf), "%2$*3$s %2$.*1$s", 2, "test", 3);
ok(ret == 7, "ret = %d\n", ret);
ok(!memcmp(buf, "test te", 8), "buf = %s\n", buf);
/* Following test invokes invalid parameter handler */
/* ret = _vsprintf_p_wrapper(buf, sizeof(buf), "%d %1$d", 1234); */
}
static void test__get_output_format(void)
{
unsigned int ret;
@ -1078,5 +1121,6 @@ START_TEST(printf)
test_vscprintf();
test_vscwprintf();
test_vsnwprintf_s();
test_vsprintf_p();
test__get_output_format();
}

View File

@ -436,6 +436,15 @@ printf_arg arg_clbk_valist(void *ctx, int arg_pos, int type, __ms_va_list *valis
return ret;
}
/*********************************************************************
* arg_clbk_positional (INTERNAL)
*/
printf_arg arg_clbk_positional(void *ctx, int pos, int type, __ms_va_list *valist)
{
printf_arg *args = ctx;
return args[pos];
}
/*********************************************************************
* _vsnprintf (MSVCRT.@)
*/
@ -789,6 +798,105 @@ int CDECL MSVCRT_vswprintf_s_l(MSVCRT_wchar_t* str, MSVCRT_size_t numberOfElemen
format, locale, args );
}
/*********************************************************************
* _vsprintf_p_l (MSVCRT.@)
*/
int CDECL MSVCRT_vsprintf_p_l(char *buffer, MSVCRT_size_t length, const char *format,
MSVCRT__locale_t locale, __ms_va_list args)
{
static const char nullbyte = '\0';
printf_arg args_ctx[MSVCRT__ARGMAX+1];
struct _str_ctx_a puts_ctx = {length, buffer};
int ret;
memset(args_ctx, 0, sizeof(args_ctx));
ret = create_positional_ctx_a(args_ctx, format, args);
if(ret < 0) {
MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
*MSVCRT__errno() = MSVCRT_EINVAL;
return ret;
} else if(ret == 0)
ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale, FALSE, TRUE,
arg_clbk_valist, NULL, args);
else
ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale, TRUE, TRUE,
arg_clbk_positional, args_ctx, NULL);
puts_clbk_str_a(&puts_ctx, 1, &nullbyte);
return ret;
}
/*********************************************************************
* _vsprintf_p (MSVCRT.@)
*/
int CDECL MSVCRT_vsprintf_p(char *buffer, MSVCRT_size_t length,
const char *format, __ms_va_list args)
{
return MSVCRT_vsprintf_p_l(buffer, length, format, NULL, args);
}
/*********************************************************************
* _sprintf_p_l (MSVCRT.@)
*/
int CDECL MSVCRT_sprintf_p_l(char *buffer, MSVCRT_size_t length,
const char *format, MSVCRT__locale_t locale, ...)
{
__ms_va_list valist;
int r;
__ms_va_start(valist, locale);
r = MSVCRT_vsprintf_p_l(buffer, length, format, locale, valist);
__ms_va_end(valist);
return r;
}
/*********************************************************************
* _vswprintf_p_l (MSVCRT.@)
*/
int CDECL MSVCRT_vswprintf_p_l(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, __ms_va_list args)
{
static const MSVCRT_wchar_t nullbyte = '\0';
printf_arg args_ctx[MSVCRT__ARGMAX+1];
struct _str_ctx_w puts_ctx = {length, buffer};
int ret;
memset(args_ctx, 0, sizeof(args_ctx));
ret = create_positional_ctx_w(args_ctx, format, args);
if(ret < 0) {
MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
*MSVCRT__errno() = MSVCRT_EINVAL;
return ret;
} else if(ret == 0)
ret = pf_printf_w(puts_clbk_str_w, &puts_ctx, format, locale, TRUE, TRUE,
arg_clbk_valist, NULL, args);
else
ret = pf_printf_w(puts_clbk_str_w, &puts_ctx, format, locale, TRUE, TRUE,
arg_clbk_positional, args_ctx, NULL);
puts_clbk_str_w(&puts_ctx, 1, &nullbyte);
return ret;
}
/*********************************************************************
* _swprintf_p_l (MSVCRT.@)
*/
int CDECL MSVCRT_swprintf_p_l(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, ...)
{
__ms_va_list valist;
int r;
__ms_va_start(valist, locale);
r = MSVCRT_vswprintf_p_l(buffer, length, format, locale, valist);
__ms_va_end(valist);
return r;
}
/*********************************************************************
* wcscoll (MSVCRT.@)
*/

View File

@ -97,6 +97,8 @@
# endif
#endif
#define _ARGMAX 100
#ifndef _MSVCRT_LONG_DEFINED
#define _MSVCRT_LONG_DEFINED
/* we need 32-bit longs even on 64-bit */