MSVCRT: add handling of %ws, %S and %C to _vsn(w)printf, improve
sprintf tests
Mike McCormack
mike at codeweavers.com
Sat Feb 12 08:27:26 CST 2005
This implementation uses libc's printf for floats and integers, and
handles other format strings itself. The _vsnwprintf and _vsnprintf are
handled by the new code so they remain consistent with each other.
Mike
ChangeLog:
* add handling of %ws, %S and %C to _vns(w)printf, improve sprintf tests
-------------- next part --------------
Index: dlls/msvcrt/msvcrt.spec
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/msvcrt.spec,v
retrieving revision 1.95
diff -u -p -r1.95 msvcrt.spec
--- dlls/msvcrt/msvcrt.spec 10 Dec 2004 15:28:25 -0000 1.95
+++ dlls/msvcrt/msvcrt.spec 12 Feb 2005 14:10:06 -0000
@@ -484,8 +484,8 @@
@ cdecl _unloaddll(long)
@ cdecl _unlock(long)
@ cdecl _utime(str ptr)
-@ cdecl _vsnprintf(ptr long ptr ptr) vsnprintf
-@ cdecl _vsnwprintf(ptr long wstr long)
+@ cdecl _vsnprintf(ptr long ptr ptr) MSVCRT_vsnprintf
+@ cdecl _vsnwprintf(ptr long wstr long) MSVCRT_vsnwprintf
@ cdecl _waccess(wstr long)
@ stub _wasctime #(ptr) MSVCRT__wasctime
@ cdecl _wchdir(wstr)
@@ -693,7 +693,7 @@
@ cdecl signal(long long) MSVCRT_signal
@ cdecl sin(double)
@ cdecl sinh(double)
-@ varargs sprintf(ptr str)
+@ varargs sprintf(ptr str) MSVCRT_sprintf
@ cdecl sqrt(double)
@ cdecl srand(long)
@ varargs sscanf(str str) MSVCRT_sscanf
Index: dlls/msvcrt/wcs.c
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/wcs.c,v
retrieving revision 1.18
diff -u -p -r1.18 wcs.c
--- dlls/msvcrt/wcs.c 25 Jun 2004 01:19:15 -0000 1.18
+++ dlls/msvcrt/wcs.c 12 Feb 2005 14:10:06 -0000
@@ -21,6 +21,7 @@
#include <limits.h>
#include <stdio.h>
#include <math.h>
+#include <assert.h>
#include "msvcrt.h"
#include "winnls.h"
#include "wine/unicode.h"
@@ -178,184 +179,490 @@ double MSVCRT_wcstod(const MSVCRT_wchar_
return ret;
}
-static int MSVCRT_vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist)
+
+typedef struct pf_output_t
+{
+ int used;
+ int len;
+ BOOL unicode;
+ union {
+ LPWSTR W;
+ LPSTR A;
+ } buf;
+} pf_output;
+
+typedef struct pf_flags_t
+{
+ char Sign, LeftAlign, Alternate, PadZero;
+ char FieldLength, Precision;
+ char IntegerLength, IntegerDouble;
+ char WideString;
+ char Format;
+} pf_flags;
+
+/*
+ * writes a string of characters to the output
+ * returns -1 if the string doesn't fit in the output buffer
+ * return the length of the string if all characters were written
+ */
+static inline int pf_output_stringW( pf_output *out, LPCWSTR str, int len )
{
- unsigned int written = 0;
- const WCHAR *iter = format;
- char bufa[256], fmtbufa[64], *fmta;
+ int space = out->len - out->used;
- while (*iter)
+ if( len < 0 )
+ len = strlenW( str );
+ if( out->unicode )
{
- while (*iter && *iter != '%')
+ LPWSTR p = out->buf.W + out->used;
+
+ if( space >= len )
{
- if (written++ >= len)
- return -1;
- *str++ = *iter++;
+ memcpy( p, str, len*sizeof(WCHAR) );
+ out->used += len;
+ return len;
}
- if (*iter == '%')
+ if( space > 0 )
+ memcpy( p, str, space*sizeof(WCHAR) );
+ out->used += len;
+ }
+ else
+ {
+ int n = WideCharToMultiByte( CP_ACP, 0, str, len, NULL, 0, NULL, NULL );
+ LPSTR p = out->buf.A + out->used;
+
+ if( space >= n )
{
- if (iter[1] == '%')
- {
- if (written++ >= len)
- return -1;
- *str++ = '%'; /* "%%"->'%' */
- iter += 2;
- continue;
- }
+ WideCharToMultiByte( CP_ACP, 0, str, len, p, n, NULL, NULL );
+ out->used += n;
+ return len;
+ }
+ if( space > 0 )
+ WideCharToMultiByte( CP_ACP, 0, str, len, p, space, NULL, NULL );
+ out->used += n;
+ }
+ return -1;
+}
- fmta = fmtbufa;
- *fmta++ = *iter++;
- while (*iter == '0' ||
- *iter == '+' ||
- *iter == '-' ||
- *iter == ' ' ||
- *iter == '*' ||
- *iter == '#')
- {
- if (*iter == '*')
- {
- char *buffiter = bufa;
- int fieldlen = va_arg(valist, int);
- sprintf(buffiter, "%d", fieldlen);
- while (*buffiter)
- *fmta++ = *buffiter++;
- }
- else
- *fmta++ = *iter;
- iter++;
- }
+static inline int pf_output_stringA( pf_output *out, LPCSTR str, int len )
+{
+ int space = out->len - out->used;
- while (isdigit(*iter))
- *fmta++ = *iter++;
+ if( len < 0 )
+ len = strlen( str );
+ if( !out->unicode )
+ {
+ LPSTR p = out->buf.A + out->used;
- if (*iter == '.')
- {
- *fmta++ = *iter++;
- if (*iter == '*')
- {
- char *buffiter = bufa;
- int fieldlen = va_arg(valist, int);
- sprintf(buffiter, "%d", fieldlen);
- while (*buffiter)
- *fmta++ = *buffiter++;
- }
- else
- while (isdigit(*iter))
- *fmta++ = *iter++;
- }
- if (*iter == 'h' || *iter == 'l')
- *fmta++ = *iter++;
+ if( space >= len )
+ {
+ memcpy( p, str, len );
+ out->used += len;
+ return len;
+ }
+ if( space > 0 )
+ memcpy( p, str, space );
+ out->used += len;
+ }
+ else
+ {
+ int n = MultiByteToWideChar( CP_ACP, 0, str, len, NULL, 0 );
+ LPWSTR p = out->buf.W + out->used;
- switch (*iter)
- {
- case 'S':
- {
- static const char *none = "(null)";
- const char *astr = va_arg(valist, const char *);
- const char *striter = astr ? astr : none;
- int r, n;
- while (*striter)
- {
- if (written >= len)
- return -1;
- n = 1;
- if( IsDBCSLeadByte( *striter ) )
- n++;
- r = MultiByteToWideChar( CP_ACP, 0,
- striter, n, str, len - written );
- striter += n;
- str += r;
- written += r;
- }
- iter++;
+ if( space >= n )
+ {
+ MultiByteToWideChar( CP_ACP, 0, str, len, p, n );
+ out->used += n;
+ return len;
+ }
+ if( space > 0 )
+ MultiByteToWideChar( CP_ACP, 0, str, len, p, space );
+ out->used += n;
+ }
+ return -1;
+}
+
+static inline int pf_fill( pf_output *out, int len, pf_flags *flags, char left )
+{
+ int i, r = 0;
+
+ if( ( !left && flags->LeftAlign ) ||
+ ( left && !flags->LeftAlign ) ||
+ ( left && flags->PadZero ) )
+ {
+ for( i=0; (i<(flags->FieldLength-len)) && (r>=0); i++ )
+ {
+ if( flags->PadZero )
+ r = pf_output_stringA( out, "0", 1 );
+ else
+ r = pf_output_stringA( out, " ", 1 );
+ }
+ }
+
+ return r;
+}
+
+static inline int pf_output_format_W( pf_output *out, LPCWSTR str,
+ int len, pf_flags *flags )
+{
+ int r = 0;
+
+ if( len < 0 )
+ len = strlenW( str );
+
+ r = pf_fill( out, len, flags, 1 );
+
+ if( r>=0 )
+ r = pf_output_stringW( out, str, len );
+
+ if( r>=0 )
+ r = pf_fill( out, len, flags, 0 );
+
+ return r;
+}
+
+static inline int pf_output_format_A( pf_output *out, LPCSTR str,
+ int len, pf_flags *flags )
+{
+ int r = 0;
+
+ if( len < 0 )
+ len = strlen( str );
+
+ r = pf_fill( out, len, flags, 1 );
+
+ if( r>=0 )
+ r = pf_output_stringA( out, str, len );
+
+ if( r>=0 )
+ r = pf_fill( out, len, flags, 0 );
+
+ return r;
+}
+
+static inline BOOL pf_is_double_format( char fmt )
+{
+ char float_fmts[] = "aefg";
+ if (!fmt)
+ return FALSE;
+ fmt = tolower( fmt );
+ return strchr( float_fmts, fmt ) ? TRUE : FALSE;
+}
+
+static inline BOOL pf_is_valid_format( char fmt )
+{
+ char float_fmts[] = "acdefginoux";
+ if (!fmt)
+ return FALSE;
+ fmt = tolower( fmt );
+ return strchr( float_fmts, fmt ) ? TRUE : FALSE;
+}
+
+static void pf_rebuild_format_string( char *p, pf_flags *flags )
+{
+ *p++ = '%';
+ if( flags->Sign )
+ *p++ = flags->Sign;
+ if( flags->LeftAlign )
+ *p++ = flags->LeftAlign;
+ if( flags->Alternate )
+ *p++ = flags->Alternate;
+ if( flags->PadZero )
+ *p++ = flags->PadZero;
+ if( flags->FieldLength )
+ {
+ sprintf(p, "%d", flags->FieldLength);
+ p += strlen(p);
+ }
+ if( flags->Precision )
+ {
+ sprintf(p, ".%d", flags->Precision);
+ p += strlen(p);
+ }
+ *p++ = flags->Format;
+ *p++ = 0;
+}
+
+/*********************************************************************
+ * pf_vsnprintf (INTERNAL)
+ *
+ * implements both A and W vsnprintf functions
+ */
+static int pf_vsnprintf( pf_output *out, const WCHAR *format, va_list valist )
+{
+ int r;
+ LPCWSTR q, p = format;
+ pf_flags flags;
+
+ while (*p)
+ {
+ q = strchrW( p, '%' );
+
+ /* there's no % characters left, output the rest of the string */
+ if( !q )
+ {
+ r = pf_output_stringW(out, p, -1);
+ if( r<0 )
+ return r;
+ p += r;
+ continue;
+ }
+
+ /* there's characters before the %, output them */
+ if( q != p )
+ {
+ r = pf_output_stringW(out, p, q - p);
+ if( r<0 )
+ return r;
+ p = q;
+ }
+
+ /* we must be at a % now, skip over it */
+ assert( *p == '%' );
+ p++;
+
+ /* output a single % character */
+ if( *p == '%' )
+ {
+ r = pf_output_stringW(out, p, 1);
+ if( r<0 )
+ return r;
+ continue;
+ }
+
+ /* parse the flags */
+ memset( &flags, 0, sizeof flags );
+ while (*p)
+ {
+ if( *p == '+' || *p == ' ' )
+ flags.Sign = '+';
+ else if( *p == '-' )
+ flags.LeftAlign = *p;
+ else if( *p == '0' )
+ flags.PadZero = *p;
+ else if( *p == '#' )
+ flags.Alternate = *p;
+ else
break;
- }
+ p++;
+ }
- case 's':
+ /* deal with the field width specifier */
+ flags.FieldLength = 0;
+ if( *p == '*' )
+ flags.FieldLength = va_arg( valist, int );
+ else while( isdigit(*p) )
+ {
+ flags.FieldLength *= 10;
+ flags.FieldLength += *p++ - '0';
+ }
+
+ /* deal with precision */
+ if( *p == '.' )
+ {
+ p++;
+ if( *p == '*' )
+ flags.Precision = va_arg( valist, int );
+ else while( isdigit(*p) )
{
- static const WCHAR none[] = { '(','n','u','l','l',')',0 };
- const WCHAR *wstr = va_arg(valist, const WCHAR *);
- const WCHAR *striter = wstr ? wstr : none;
- while (*striter)
- {
- if (written++ >= len)
- return -1;
- *str++ = *striter++;
- }
- iter++;
- break;
+ flags.Precision *= 10;
+ flags.Precision += *p++ - '0';
}
+ }
- case 'c':
- if (written++ >= len)
- return -1;
- *str++ = (WCHAR)va_arg(valist, int);
- iter++;
- break;
-
- default:
+ /* deal with integer width modifier */
+ while( *p )
+ {
+ if( *p == 'h' || *p == 'l' || *p == 'L' )
{
- /* For non wc types, use system sprintf and append to wide char output */
- /* FIXME: for unrecognised types, should ignore % when printing */
- char *bufaiter = bufa;
- if (*iter == 'p')
- sprintf(bufaiter, "%08lX", va_arg(valist, long));
+ if( flags.IntegerLength == *p )
+ flags.IntegerDouble++;
else
- {
- *fmta++ = *iter;
- *fmta = '\0';
- if (*iter == 'a' || *iter == 'A' ||
- *iter == 'e' || *iter == 'E' ||
- *iter == 'f' || *iter == 'F' ||
- *iter == 'g' || *iter == 'G')
- sprintf(bufaiter, fmtbufa, va_arg(valist, double));
- else
- {
- /* FIXME: On 32 bit systems this doesn't handle int 64's.
- * on 64 bit systems this doesn't work for 32 bit types
- */
- sprintf(bufaiter, fmtbufa, va_arg(valist, void *));
- }
- }
- while (*bufaiter)
- {
- if (written++ >= len)
- return -1;
- *str++ = *bufaiter++;
- }
- iter++;
- break;
- }
+ flags.IntegerLength = *p;
+ p++;
}
+ else if( *p == 'w' )
+ flags.WideString = *p++;
+ else
+ break;
+ }
+
+ flags.Format = *p;
+ r = 0;
+
+ /* output a unicode string */
+ if( ( flags.Format == 's' && flags.WideString ) ||
+ ( !out->unicode && flags.Format == 'S' ) ||
+ ( out->unicode && flags.Format == 's' ) )
+ {
+ LPCWSTR str = va_arg( valist, const WCHAR * );
+
+ if( str )
+ r = pf_output_format_W( out, str, -1, &flags );
+ else
+ r = pf_output_format_A( out, "(null)", -1, &flags );
+ }
+
+ /* output a ASCII string */
+ else if( ( flags.Format == 's' && flags.IntegerLength == 'h' ) ||
+ ( out->unicode && flags.Format == 'S' ) ||
+ ( !out->unicode && flags.Format == 's' ) )
+ {
+ LPCSTR str = va_arg( valist, const CHAR * );
+
+ if( str )
+ r = pf_output_format_A( out, str, -1, &flags );
+ else
+ r = pf_output_format_A( out, "(null)", -1, &flags );
+ }
+
+ /* output a single wide character */
+ else if( ( flags.Format == 'c' && flags.IntegerLength == 'w' ) ||
+ ( out->unicode && flags.Format == 'c' ) ||
+ ( !out->unicode && flags.Format == 'C' ) )
+ {
+ WCHAR ch = va_arg( valist, int );
+
+ r = pf_output_format_W( out, &ch, 1, &flags );
+ }
+
+ /* output a single ascii character */
+ else if( ( flags.Format == 'c' && flags.IntegerLength == 'h' ) ||
+ ( out->unicode && flags.Format == 'C' ) ||
+ ( !out->unicode && flags.Format == 'c' ) )
+ {
+ CHAR ch = va_arg( valist, int );
+
+ r = pf_output_format_A( out, &ch, 1, &flags );
+ }
+
+ /* output a pointer */
+ else if( flags.Format == 'p' )
+ {
+ char pointer[10];
+
+ flags.PadZero = 0;
+ if( flags.Alternate )
+ sprintf(pointer, "0X%08lX", va_arg(valist, long));
+ else
+ sprintf(pointer, "%08lX", va_arg(valist, long));
+ r = pf_output_format_A( out, pointer, -1, &flags );
+ }
+
+ /* deal with %n */
+ else if( flags.Format == 'n' )
+ {
+ int *x = va_arg(valist, int *);
+ *x = out->used;
}
+
+ /* deal with integers and floats using libc's printf */
+ else if( pf_is_valid_format( flags.Format ) )
+ {
+ char fmt[20], number[40], *x = number;
+
+ if( flags.FieldLength >= sizeof number )
+ x = HeapAlloc( GetProcessHeap(), 0, flags.FieldLength+1 );
+
+ pf_rebuild_format_string( fmt, &flags );
+
+ if( pf_is_double_format( flags.Format ) )
+ sprintf( number, fmt, va_arg(valist, double) );
+ else
+ sprintf( number, fmt, va_arg(valist, int) );
+
+ r = pf_output_stringA( out, number, -1 );
+ if( x != number )
+ HeapFree( GetProcessHeap(), 0, number );
+ }
+ else
+ continue;
+
+ if( r<0 )
+ return r;
+ p++;
}
- if (written >= len)
- return -1;
- *str++ = 0;
- return (int)written;
+
+ /* check we reached the end, and null terminate the string */
+ assert( *p == 0 );
+ r = pf_output_stringW( out, p, 1 );
+ if( r<0 )
+ return r;
+
+ return out->used - 1;
}
/*********************************************************************
- * swprintf (MSVCRT.@)
+ * _vsnprintf (MSVCRT.@)
*/
-int MSVCRT_swprintf( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *format, ... )
+int MSVCRT_vsnprintf( char *str, unsigned int len,
+ const char *format, va_list valist )
+{
+ DWORD sz;
+ LPWSTR formatW = NULL;
+ pf_output out;
+ int r;
+
+ out.unicode = FALSE;
+ out.buf.A = str;
+ out.used = 0;
+ out.len = len;
+
+ if( format )
+ {
+ sz = MultiByteToWideChar( CP_ACP, 0, format, -1, NULL, 0 );
+ formatW = HeapAlloc( GetProcessHeap(), 0, sz*sizeof(WCHAR) );
+ MultiByteToWideChar( CP_ACP, 0, format, -1, formatW, sz );
+ }
+
+ r = pf_vsnprintf( &out, formatW, valist );
+
+ HeapFree( GetProcessHeap(), 0, formatW );
+
+ return r;
+}
+
+/*********************************************************************
+ * _vsnwsprintf (MSVCRT.@)
+ */
+int MSVCRT_vsnwprintf( MSVCRT_wchar_t *str, unsigned int len,
+ const WCHAR *format, va_list valist )
+{
+ pf_output out;
+
+ out.unicode = TRUE;
+ out.buf.W = str;
+ out.used = 0;
+ out.len = len;
+
+ return pf_vsnprintf( &out, format, valist );
+}
+
+/*********************************************************************
+ * sprintf (MSVCRT.@)
+ */
+int MSVCRT_sprintf( char *str, const char *format, ... )
{
va_list ap;
int r;
va_start( ap, format );
- r = MSVCRT_vsnprintfW( str, INT_MAX, format, ap );
+ r = MSVCRT_vsnprintf( str, INT_MAX, format, ap );
va_end( ap );
return r;
}
/*********************************************************************
- * _vsnwprintf (MSVCRT.@)
+ * swprintf (MSVCRT.@)
*/
-int _vsnwprintf(MSVCRT_wchar_t *str, unsigned int len,
- const MSVCRT_wchar_t *format, va_list valist)
+int MSVCRT_swprintf( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *format, ... )
{
- return MSVCRT_vsnprintfW(str, len, format, valist);
+ va_list ap;
+ int r;
+
+ va_start( ap, format );
+ r = MSVCRT_vsnwprintf( str, INT_MAX, format, ap );
+ va_end( ap );
+ return r;
}
/*********************************************************************
@@ -363,7 +670,7 @@ int _vsnwprintf(MSVCRT_wchar_t *str, uns
*/
int MSVCRT_vswprintf( MSVCRT_wchar_t* str, const MSVCRT_wchar_t* format, va_list args )
{
- return MSVCRT_vsnprintfW( str, INT_MAX, format, args );
+ return MSVCRT_vsnwprintf( str, INT_MAX, format, args );
}
/*********************************************************************
Index: dlls/msvcrt/tests/printf.c
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/tests/printf.c,v
retrieving revision 1.2
diff -u -p -r1.2 printf.c
--- dlls/msvcrt/tests/printf.c 28 Nov 2004 15:01:50 -0000 1.2
+++ dlls/msvcrt/tests/printf.c 12 Feb 2005 14:10:07 -0000
@@ -3,6 +3,7 @@
*
* Copyright 2002 Uwe Bonnes
* Copyright 2004 Aneurin Price
+ * Copyright 2005 Mike McCormack
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -26,54 +27,213 @@
static void test_sprintf( void )
{
char buffer[100];
- const char *I64d = "%I64d";
- const char *O4c = "%04c";
- const char *O4s = "%04s";
- const char *hash012p = "%#012p";
+ const char *format;
double pnumber=789456123;
-/** WCHAR widestring[]={'w','i','d','e','s','t','r','i','n','g',0};**/
- sprintf(buffer,"%+#23.15e",pnumber);
- todo_wine
- {
- ok(strstr(buffer,"e+008") != 0,"Sprintf different \"%s\"\n",buffer);
- }
- sprintf(buffer,I64d,((ULONGLONG)0xffffffff)*0xffffffff);
- todo_wine
- {
- ok(strlen(buffer) == 11,"Problem with long long \"%s\"\n",buffer);
- }
- sprintf(buffer,"%lld",((ULONGLONG)0xffffffff)*0xffffffff);
- todo_wine
- {
- ok(strlen(buffer) == 1,"Problem with \"ll\" interpretation \"%s\"\n",buffer);
- }
-/** This one actually crashes WINE at the moment, when using builtin msvcrt.dll.
- sprintf(buffer,"%S",widestring);
- todo_wine
- {
- ok(strlen(buffer) == 10,"Problem with \"%%S\" interpretation \"%s\"\n",buffer);
- }
- **/
- sprintf(buffer,O4c,'1');
- todo_wine
- {
- ok(!strcmp(buffer,"0001"),"Character not zero-prefixed \"%s\"\n",buffer);
- }
- sprintf(buffer,"%p",(void *)57);
- todo_wine
- {
- ok(!strcmp(buffer,"00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
- }
- sprintf(buffer,hash012p,(void *)57);
- todo_wine
- {
- ok(!strcmp(buffer," 0X00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
- }
- sprintf(buffer,O4s,"foo");/**Warning again**/
- todo_wine
- {
- ok(!strcmp(buffer,"0foo"),"String not zero-prefixed \"%s\"\n",buffer);
- }
+ int x, r;
+ WCHAR wide[] = { 'w','i','d','e',0};
+
+ format = "%+#23.15e";
+ r = sprintf(buffer,format,pnumber);
+ todo_wine {
+ ok(!strcmp(buffer,"+7.894561230000000e+008"),"exponent format incorrect\n");
+ }
+ ok( r==23, "return count wrong\n");
+
+ todo_wine {
+ format = "%I64d";
+ r = sprintf(buffer,format,((ULONGLONG)0xffffffff)*0xffffffff);
+ ok(!strcmp(buffer,"-8589934591"),"Problem with long long\n");
+ ok( r==11, "return count wrong\n");
+ }
+
+ format = "%lld";
+ r = sprintf(buffer,format,((ULONGLONG)0xffffffff)*0xffffffff);
+ ok(!strcmp(buffer, "1"), "Problem with \"ll\" interpretation\n");
+ ok( r==1, "return count wrong\n");
+
+ format = "%S";
+ r = sprintf(buffer,format,wide);
+ ok(!strcmp(buffer,"wide"),"Problem with wide string format\n");
+ ok( r==4, "return count wrong\n");
+
+ format = "%04c";
+ r = sprintf(buffer,format,'1');
+ ok(!strcmp(buffer,"0001"),"Character not zero-prefixed \"%s\"\n",buffer);
+ ok( r==4, "return count wrong\n");
+
+ format = "%p";
+ r = sprintf(buffer,format,(void *)57);
+ ok(!strcmp(buffer,"00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
+ ok( r==8, "return count wrong\n");
+
+ format = "%#012p";
+ r = sprintf(buffer,format,(void *)57);
+ ok(!strcmp(buffer," 0X00000039"),"Pointer formatted incorrectly\n");
+ ok( r==12, "return count wrong\n");
+
+ format = "%04s";
+ r = sprintf(buffer,format,"foo");
+ ok(!strcmp(buffer,"0foo"),"String not zero-prefixed \"%s\"\n",buffer);
+ ok( r==4, "return count wrong\n");
+
+ format = "%#-012p";
+ r = sprintf(buffer,format,(void *)57);
+ ok(!strcmp(buffer,"0X00000039 "),"Pointer formatted incorrectly\n");
+ ok( r==12, "return count wrong\n");
+
+ format = "hello";
+ r = sprintf(buffer, format);
+ ok(!strcmp(buffer,"hello"), "failed\n");
+ ok( r==5, "return count wrong\n");
+
+ format = "%ws";
+ r = sprintf(buffer, format, wide);
+ ok(!strcmp(buffer,"wide"), "failed\n");
+ ok( r==4, "return count wrong\n");
+
+ format = "%-10ws";
+ r = sprintf(buffer, format, wide );
+ ok(!strcmp(buffer,"wide "), "failed\n");
+ ok( r==10, "return count wrong\n");
+
+ format = "%10ws";
+ r = sprintf(buffer, format, wide );
+ ok(!strcmp(buffer," wide"), "failed\n");
+ ok( r==10, "return count wrong\n");
+
+ format = "%#+ -03whlls";
+ r = sprintf(buffer, format, wide );
+ ok(!strcmp(buffer,"wide"), "failed\n");
+ ok( r==4, "return count wrong\n");
+
+ format = "%w0s";
+ r = sprintf(buffer, format, wide );
+ ok(!strcmp(buffer,"0s"), "failed\n");
+ ok( r==2, "return count wrong\n");
+
+ format = "%w-s";
+ r = sprintf(buffer, format, wide );
+ ok(!strcmp(buffer,"-s"), "failed\n");
+ ok( r==2, "return count wrong\n");
+
+ format = "%b";
+ r = sprintf(buffer, format);
+ ok(!strcmp(buffer,"b"), "failed\n");
+ ok( r==1, "return count wrong\n");
+
+ format = "%3c";
+ r = sprintf(buffer, format,'a');
+ ok(!strcmp(buffer," a"), "failed\n");
+ ok( r==3, "return count wrong\n");
+
+ format = "%3d";
+ r = sprintf(buffer, format,1234);
+ ok(!strcmp(buffer,"1234"), "failed\n");
+ ok( r==4, "return count wrong\n");
+
+ format = "%3h";
+ r = sprintf(buffer, format);
+ ok(!strcmp(buffer,""), "failed\n");
+ ok( r==0, "return count wrong\n");
+
+ format = "%j%k%m%q%r%t%v%y%z";
+ r = sprintf(buffer, format);
+ ok(!strcmp(buffer,"jkmqrtvyz"), "failed\n");
+ ok( r==9, "return count wrong\n");
+
+ format = "asdf%n";
+ x = 0;
+ r = sprintf(buffer, format, &x );
+ ok(x == 4, "should write to x\n");
+ ok(!strcmp(buffer,"asdf"), "failed\n");
+ ok( r==4, "return count wrong\n");
+
+ format = "%-1d";
+ r = sprintf(buffer, format,2);
+ ok(!strcmp(buffer,"2"), "failed\n");
+ ok( r==1, "return count wrong\n");
+
+ format = "%2.4f";
+ r = sprintf(buffer, format,8.6);
+ ok(!strcmp(buffer,"8.6000"), "failed\n");
+ ok( r==6, "return count wrong\n");
+
+ todo_wine {
+ format = "%2.4e";
+ r = sprintf(buffer, format,8.6);
+ ok(!strcmp(buffer,"8.6000e+000"), "failed\n");
+ ok( r==11, "return count wrong\n");
+ }
+
+ format = "%2.4g";
+ r = sprintf(buffer, format,8.6);
+ ok(!strcmp(buffer,"8.6"), "failed\n");
+ ok( r==3, "return count wrong\n");
+
+ format = "%-i";
+ r = sprintf(buffer, format,-1);
+ ok(!strcmp(buffer,"-1"), "failed\n");
+ ok( r==2, "return count wrong\n");
+
+ format = "%-i";
+ r = sprintf(buffer, format,1);
+ ok(!strcmp(buffer,"1"), "failed\n");
+ ok( r==1, "return count wrong\n");
+
+ format = "%+i";
+ r = sprintf(buffer, format,1);
+ ok(!strcmp(buffer,"+1"), "failed\n");
+ ok( r==2, "return count wrong\n");
+
+ format = "%o";
+ r = sprintf(buffer, format,10);
+ ok(!strcmp(buffer,"12"), "failed\n");
+ ok( r==2, "return count wrong\n");
+
+ format = "%p";
+ r = sprintf(buffer, format,0);
+ ok(!strcmp(buffer,"00000000"), "failed\n");
+ ok( r==8, "return count wrong\n");
+
+ format = "%s";
+ r = sprintf(buffer, format,0);
+ ok(!strcmp(buffer,"(null)"), "failed\n");
+ ok( r==6, "return count wrong\n");
+
+ format = "%s";
+ r = sprintf(buffer, format,"%%%%");
+ ok(!strcmp(buffer,"%%%%"), "failed\n");
+ ok( r==4, "return count wrong\n");
+
+ format = "%u";
+ r = sprintf(buffer, format,-1);
+ ok(!strcmp(buffer,"4294967295"), "failed\n");
+ ok( r==10, "return count wrong\n");
+
+ format = "%w";
+ r = sprintf(buffer, format,-1);
+ ok(!strcmp(buffer,""), "failed\n");
+ ok( r==0, "return count wrong\n");
+
+ format = "%h";
+ r = sprintf(buffer, format,-1);
+ ok(!strcmp(buffer,""), "failed\n");
+ ok( r==0, "return count wrong\n");
+
+ format = "%z";
+ r = sprintf(buffer, format,-1);
+ ok(!strcmp(buffer,"z"), "failed\n");
+ ok( r==1, "return count wrong\n");
+
+ format = "%j";
+ r = sprintf(buffer, format,-1);
+ ok(!strcmp(buffer,"j"), "failed\n");
+ ok( r==1, "return count wrong\n");
+
+ format = "x%cx";
+ r = sprintf(buffer, format, 0x100+'X');
+ ok(!strcmp(buffer,"xXx"), "failed\n");
+ ok( r==3, "return count wrong\n");
}
static void test_swprintf( void )
More information about the wine-patches
mailing list