MSVCRT: make swprintf(L"%S","abcd") work [resend]

Mike McCormack mike at codeweavers.com
Mon May 31 03:56:45 CDT 2004


Copy the vsnprintfW implementation from libunicode.so to msvcrt and add 
a handler for the %S flag.  That requires a conversion to unicode and 
knowledge of the current ASCII code page.

Mike


ChangeLog
* make swprintf(L"%S","abcd") work
-------------- next part --------------
? dlls/msvcrt/msvcrt.spec.c
? dlls/msvcrt/tests/msvcrt_test.exe.spec.c
Index: dlls/msvcrt/msvcrt.spec
===================================================================
RCS file: /cvstrees/crossover/office/wine/dlls/msvcrt/msvcrt.spec,v
retrieving revision 1.1.1.25
diff -u -r1.1.1.25 msvcrt.spec
--- dlls/msvcrt/msvcrt.spec	15 May 2004 00:14:32 -0000	1.1.1.25
+++ dlls/msvcrt/msvcrt.spec	31 May 2004 07:47:28 -0000
@@ -718,7 +718,7 @@
 @ cdecl strtol(str ptr long)
 @ cdecl strtoul(str ptr long)
 @ cdecl strxfrm(ptr str long)
-@ varargs swprintf(wstr wstr) ntdll.swprintf
+@ varargs swprintf(wstr wstr) MSVCRT_swprintf
 @ varargs swscanf(wstr wstr) MSVCRT_swscanf
 @ cdecl system(str) MSVCRT_system
 @ cdecl tan(double)
Index: dlls/msvcrt/string.c
===================================================================
RCS file: /cvstrees/crossover/office/wine/dlls/msvcrt/string.c,v
retrieving revision 1.1.1.4
diff -u -r1.1.1.4 string.c
--- dlls/msvcrt/string.c	19 Mar 2004 03:02:14 -0000	1.1.1.4
+++ dlls/msvcrt/string.c	31 May 2004 07:47:28 -0000
@@ -25,6 +25,9 @@
 #include "msvcrt/stdlib.h"
 #include "msvcrt/string.h"
 
+#include <stdio.h>
+#include <stdarg.h>
+
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
@@ -115,3 +118,4 @@
     }
   }
 }
+
Index: dlls/msvcrt/wcs.c
===================================================================
RCS file: /cvstrees/crossover/office/wine/dlls/msvcrt/wcs.c,v
retrieving revision 1.1.1.7
diff -u -r1.1.1.7 wcs.c
--- dlls/msvcrt/wcs.c	9 Apr 2004 00:37:57 -0000	1.1.1.7
+++ dlls/msvcrt/wcs.c	31 May 2004 07:47:28 -0000
@@ -184,13 +184,184 @@
   return ret;
 }
 
+static int MSVCRT_vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist)
+{
+    unsigned int written = 0;
+    const WCHAR *iter = format;
+    char bufa[256], fmtbufa[64], *fmta;
+
+    while (*iter)
+    {
+        while (*iter && *iter != '%')
+        {
+            if (written++ >= len)
+                return -1;
+            *str++ = *iter++;
+        }
+        if (*iter == '%')
+        {
+            if (iter[1] == '%')
+            {
+                if (written++ >= len)
+                    return -1;
+                *str++ = '%'; /* "%%"->'%' */
+                iter += 2;
+                continue;
+            }
+
+            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++;
+            }
+
+            while (isdigit(*iter))
+                *fmta++ = *iter++;
+
+            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++;
+
+            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++;
+                break;
+            }
+
+            case 's':
+            {
+                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;
+            }
+
+            case 'c':
+                if (written++ >= len)
+                    return -1;
+                *str++ = (WCHAR)va_arg(valist, int);
+                iter++;
+                break;
+
+            default:
+            {
+                /* 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));
+                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;
+            }
+            }
+        }
+    }
+    if (written >= len)
+        return -1;
+    *str++ = 0;
+    return (int)written;
+}
+
+/*********************************************************************
+ *		swprintf (MSVCRT.@)
+ */
+int MSVCRT_swprintf( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *format, ... )
+{
+    va_list ap;
+    int r;
+
+    va_start( ap, format );
+    r = MSVCRT_vsnprintfW( str, INT_MAX, format, ap );
+    va_end( ap );
+    return r;
+}
+
 /*********************************************************************
  *		_vsnwprintf (MSVCRT.@)
  */
 int _vsnwprintf(MSVCRT_wchar_t *str, unsigned int len,
                 const MSVCRT_wchar_t *format, va_list valist)
 {
-    return vsnprintfW(str, len, format, valist);
+    return MSVCRT_vsnprintfW(str, len, format, valist);
 }
 
 /*********************************************************************
@@ -198,7 +369,7 @@
  */
 int MSVCRT_vswprintf( MSVCRT_wchar_t* str, const MSVCRT_wchar_t* format, va_list args )
 {
-    return vsnprintfW( str, INT_MAX, format, args );
+    return MSVCRT_vsnprintfW( str, INT_MAX, format, args );
 }
 
 /*********************************************************************


More information about the wine-patches mailing list