Re-implement MSVCRT *printf

Aneurin Price wine at shadovald.dyndns.org
Wed Nov 3 09:41:50 CST 2004


In case there's anyone trying to test this, here is a more recent 
version. Now with 100% less heap corruption.
-------------- next part --------------
Index: dlls/msvcrt/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/Makefile.in,v
retrieving revision 1.16
diff -u -u -r1.16 Makefile.in
--- dlls/msvcrt/Makefile.in	25 Jun 2004 01:19:15 -0000	1.16
+++ dlls/msvcrt/Makefile.in	3 Nov 2004 15:29:06 -0000
@@ -27,6 +27,7 @@
 	math.c \
 	mbcs.c \
 	misc.c \
+	printf.c \
 	process.c \
 	scanf.c \
 	string.c \
Index: dlls/msvcrt/file.c
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/file.c,v
retrieving revision 1.72
diff -u -u -r1.72 file.c
--- dlls/msvcrt/file.c	14 Oct 2004 00:26:39 -0000	1.72
+++ dlls/msvcrt/file.c	3 Nov 2004 15:29:06 -0000
@@ -2614,113 +2614,6 @@
   return file;
 }
 
-/*********************************************************************
- *		vfprintf (MSVCRT.@)
- */
-int MSVCRT_vfprintf(MSVCRT_FILE* file, const char *format, va_list valist)
-{
-  char buf[2048], *mem = buf;
-  int written, resize = sizeof(buf), retval;
-  /* There are two conventions for vsnprintf failing:
-   * Return -1 if we truncated, or
-   * Return the number of bytes that would have been written
-   * The code below handles both cases
-   */
-  while ((written = vsnprintf(mem, resize, format, valist)) == -1 ||
-          written > resize)
-  {
-    resize = (written == -1 ? resize * 2 : written + 1);
-    if (mem != buf)
-      MSVCRT_free (mem);
-    if (!(mem = (char *)MSVCRT_malloc(resize)))
-      return MSVCRT_EOF;
-  }
-  retval = MSVCRT_fwrite(mem, sizeof(*mem), written, file);
-  if (mem != buf)
-    MSVCRT_free (mem);
-  return retval;
-}
-
-/*********************************************************************
- *		vfwprintf (MSVCRT.@)
- * FIXME:
- * Is final char included in written (then resize is too big) or not
- * (then we must test for equality too)?
- */
-int MSVCRT_vfwprintf(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, va_list valist)
-{
-  MSVCRT_wchar_t buf[2048], *mem = buf;
-  int written, resize = sizeof(buf) / sizeof(MSVCRT_wchar_t), retval;
-  /* See vfprintf comments */
-  while ((written = _vsnwprintf(mem, resize, format, valist)) == -1 ||
-          written > resize)
-  {
-    resize = (written == -1 ? resize * 2 : written + sizeof(MSVCRT_wchar_t));
-    if (mem != buf)
-      MSVCRT_free (mem);
-    if (!(mem = (MSVCRT_wchar_t *)MSVCRT_malloc(resize*sizeof(*mem))))
-      return MSVCRT_EOF;
-  }
-  retval = MSVCRT_fwrite(mem, sizeof(*mem), written, file);
-  if (mem != buf)
-    MSVCRT_free (mem);
-  return retval;
-}
-
-/*********************************************************************
- *		vprintf (MSVCRT.@)
- */
-int MSVCRT_vprintf(const char *format, va_list valist)
-{
-  return MSVCRT_vfprintf(MSVCRT_stdout,format,valist);
-}
-
-/*********************************************************************
- *		vwprintf (MSVCRT.@)
- */
-int MSVCRT_vwprintf(const MSVCRT_wchar_t *format, va_list valist)
-{
-  return MSVCRT_vfwprintf(MSVCRT_stdout,format,valist);
-}
-
-/*********************************************************************
- *		fprintf (MSVCRT.@)
- */
-int MSVCRT_fprintf(MSVCRT_FILE* file, const char *format, ...)
-{
-    va_list valist;
-    int res;
-    va_start(valist, format);
-    res = MSVCRT_vfprintf(file, format, valist);
-    va_end(valist);
-    return res;
-}
-
-/*********************************************************************
- *		fwprintf (MSVCRT.@)
- */
-int MSVCRT_fwprintf(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, ...)
-{
-    va_list valist;
-    int res;
-    va_start(valist, format);
-    res = MSVCRT_vfwprintf(file, format, valist);
-    va_end(valist);
-    return res;
-}
-
-/*********************************************************************
- *		printf (MSVCRT.@)
- */
-int MSVCRT_printf(const char *format, ...)
-{
-    va_list valist;
-    int res;
-    va_start(valist, format);
-    res = MSVCRT_vfprintf(MSVCRT_stdout, format, valist);
-    va_end(valist);
-    return res;
-}
 
 /*********************************************************************
  *		ungetc (MSVCRT.@)
@@ -2753,17 +2646,4 @@
 			return MSVCRT_WEOF;
 	}
 	return mwc;
-}
-
-/*********************************************************************
- *		wprintf (MSVCRT.@)
- */
-int MSVCRT_wprintf(const MSVCRT_wchar_t *format, ...)
-{
-    va_list valist;
-    int res;
-    va_start(valist, format);
-    res = MSVCRT_vwprintf(format, valist);
-    va_end(valist);
-    return res;
 }
Index: dlls/msvcrt/msvcrt.spec
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/msvcrt.spec,v
retrieving revision 1.93
diff -u -u -r1.93 msvcrt.spec
--- dlls/msvcrt/msvcrt.spec	14 Oct 2004 00:26:39 -0000	1.93
+++ dlls/msvcrt/msvcrt.spec	3 Nov 2004 15:29:10 -0000
@@ -433,8 +433,8 @@
 @ cdecl _setmode(long long)
 @ stub _setsystime #(ptr long)
 @ cdecl _sleep(long)
-@ varargs _snprintf(str long str) snprintf
-@ varargs _snwprintf(wstr long wstr) ntdll._snwprintf
+@ varargs _snprintf(str long str)
+@ varargs _snwprintf(wstr long wstr)
 @ varargs _sopen(str long long) MSVCRT__sopen
 @ varargs _spawnl(long str str)
 @ varargs _spawnle(long str str)
@@ -484,7 +484,7 @@
 @ cdecl _unloaddll(long)
 @ cdecl _unlock(long)
 @ cdecl _utime(str ptr)
-@ cdecl _vsnprintf(ptr long ptr ptr) vsnprintf
+@ cdecl _vsnprintf(ptr long ptr ptr)
 @ cdecl _vsnwprintf(ptr long wstr long)
 @ cdecl _waccess(wstr long)
 @ stub _wasctime #(ptr) MSVCRT__wasctime
@@ -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
@@ -735,7 +735,7 @@
 @ cdecl vfprintf(ptr str long) MSVCRT_vfprintf
 @ cdecl vfwprintf(ptr wstr long) MSVCRT_vfwprintf
 @ cdecl vprintf(str long) MSVCRT_vprintf
-@ cdecl vsprintf(ptr str ptr)
+@ cdecl vsprintf(ptr str ptr) MSVCRT_vsprintf
 @ cdecl vswprintf(ptr wstr long) MSVCRT_vswprintf
 @ cdecl vwprintf(wstr long) MSVCRT_vwprintf
 @ cdecl wcscat(wstr wstr) ntdll.wcscat
Index: dlls/msvcrt/wcs.c
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/wcs.c,v
retrieving revision 1.18
diff -u -u -r1.18 wcs.c
--- dlls/msvcrt/wcs.c	25 Jun 2004 01:19:15 -0000	1.18
+++ dlls/msvcrt/wcs.c	3 Nov 2004 15:29:10 -0000
@@ -178,194 +178,6 @@
   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 MSVCRT_vsnprintfW(str, len, format, valist);
-}
-
-/*********************************************************************
- *		vswprintf (MSVCRT.@)
- */
-int MSVCRT_vswprintf( MSVCRT_wchar_t* str, const MSVCRT_wchar_t* format, va_list args )
-{
-    return MSVCRT_vsnprintfW( str, INT_MAX, format, args );
-}
-
 /*********************************************************************
  *		wcscoll (MSVCRT.@)
  */
--- /dev/null	2004-08-23 03:25:44.000000000 +0100
+++ dlls/msvcrt/printf.c	2004-11-01 10:01:35.000000000 +0000
@@ -0,0 +1,352 @@
+/*
+ * msvcrt.dll printf functions
+ *
+ * Copyright 2004 Aneurin Price
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <limits.h>
+#include <wctype.h>
+#include <math.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "winternl.h"
+#include "msvcrt.h"
+#include "wine/debug.h"
+#include "wine/unicode.h"
+
+extern MSVCRT_FILE MSVCRT__iob[];
+extern MSVCRT_size_t MSVCRT_fwrite(const void *ptr, MSVCRT_size_t size, MSVCRT_size_t nmemb, MSVCRT_FILE* file);
+WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
+
+#define WIDE_PRINTF 8192
+
+#include "printfhelpers.c"
+
+/*********************************************************************
+ *		_vsnprintf (MSVCRT.@)
+ */
+int _vsnprintf(char *buffer, size_t count, const char *format, va_list argptr)
+{
+    /**Since the meaning of type specifiers %S and %s (and C/c) invert
+     **depending on whether the function called is *wprintf or *printf,
+     **this doesn't simply convert to wide, call _vsnwprintf, and
+     **convert back; instead, they both call the same function with a
+     **flag to indicate the correct behaviour
+     **/
+    int done=0;
+    int prev=done;
+    int bufsize=count;
+    int skip;
+    MSVCRT_wchar_t *temp;
+    MSVCRT_wchar_t *input=(MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),8,(1+strlen(format))*sizeof(MSVCRT_wchar_t));
+    MSVCRT_wchar_t *in=input;
+    MSVCRT_wchar_t *output=(MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),8,count*sizeof(MSVCRT_wchar_t));
+    MSVCRT_wchar_t *out=output;
+    MultiByteToWideChar(CP_ACP, 0, format, -1, input, strlen(format));
+    while ((done<=count)&&(*input))
+    {
+        skip=0;
+        temp=strchrW(input,'%');
+        if (!temp || (temp-input)>bufsize)
+        {
+            skip+=processw(output, input, bufsize);
+            done+=skip;
+        }
+        else
+        {
+            processw(output, input, (temp-input));
+            skip+=(temp-input);
+            done+=skip;
+            done+=_formatw((output+skip), temp, (bufsize-skip), &argptr, &skip, done,0);
+        }
+        input+=skip;
+        output+=done-prev;
+        bufsize-=done-prev;
+        prev=done;
+    }
+    if (done>count)
+    /**No more can be written.**/
+    {
+        *(out+count)=0;
+        WideCharToMultiByte(CP_ACP, 0,out, -1, buffer, count+1, NULL, NULL);
+        HeapFree(GetProcessHeap(),0,out);
+        HeapFree(GetProcessHeap(),0,in);
+        return -1;
+    }
+    else
+    {
+        WideCharToMultiByte(CP_ACP, 0,out, -1, buffer, count+1, NULL, NULL);
+        HeapFree(GetProcessHeap(),0,out);
+        HeapFree(GetProcessHeap(),0,in);
+        return done;
+    }
+}
+
+/*********************************************************************
+ *		_vsnwprintf (MSVCRT.@)
+ */
+int _vsnwprintf(MSVCRT_wchar_t *buffer, size_t count, const MSVCRT_wchar_t *format, va_list argptr)
+{
+    int done=0;
+    int prev=done;
+    int bufsize=count;
+    int skip;
+    const MSVCRT_wchar_t *input=format;
+    MSVCRT_wchar_t *output=buffer;
+    MSVCRT_wchar_t *temp;
+    while ((done<=count)&&(*input))
+    {
+        skip=0;
+        temp=strchrW(input,'%');
+        if (!temp || (temp-input)>bufsize)
+        {
+            skip+=processw(output, input, bufsize);
+            done+=skip;
+        }
+        else
+        {
+            processw(output, input, (temp-input));
+            skip+=(temp-input);
+            done+=skip;
+            done+=_formatw((output+skip), temp, (bufsize-skip), &argptr, &skip, done,WIDE_PRINTF);
+        }
+        input+=skip;
+        output+=done-prev;
+        bufsize-=done-prev;
+        prev=done;
+    }
+    if (done>count)
+    /**No more can be written.**/
+    {
+        *(buffer+count)=0;
+        return -1;
+    }
+    else
+    {
+       *(buffer+done)=0;
+       return done;
+    }
+}
+
+
+/*********************************************************************
+ *		vfprintf (MSVCRT.@)
+ */
+int MSVCRT_vfprintf(MSVCRT_FILE* file, const char *format, va_list valist)
+{
+    char buf[2048], *mem = buf;
+    int written, resize = sizeof(buf)/sizeof(char), retval;
+    while ((written = _vsnprintf(mem, resize, format, valist)) == -1)
+    {
+        resize*=2;
+        if (mem != buf)
+            MSVCRT_free (mem);
+        if (!(mem = (char *)MSVCRT_malloc(resize*sizeof(char))))
+            return (-1);
+    }
+    retval = MSVCRT_fwrite(mem, sizeof(*mem), written, file);
+    if (mem != buf)
+        MSVCRT_free (mem);
+    return retval;
+}
+
+/*********************************************************************
+ *		vfwprintf (MSVCRT.@)
+ */
+int MSVCRT_vfwprintf(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, va_list valist)
+{
+    MSVCRT_wchar_t buf[2048], *mem = buf;
+    int written, resize = sizeof(buf)/sizeof(MSVCRT_wchar_t), retval;
+    while ((written = _vsnwprintf(mem, resize, format, valist)) == -1)
+    {
+        resize*=2;
+        if (mem != buf)
+            MSVCRT_free (mem);
+        if (!(mem = (MSVCRT_wchar_t *)MSVCRT_malloc(resize*sizeof(MSVCRT_wchar_t))))
+            return (-1);
+    }
+    retval = MSVCRT_fwrite(mem, sizeof(*mem), written, file);
+    if (mem != buf)
+        MSVCRT_free (mem);
+    return retval;
+}
+
+/*********************************************************************
+ *		printf (MSVCRT.@)
+ */
+int MSVCRT_printf(const char *format, ...)
+{
+    va_list valist;
+    int res;
+    va_start(valist, format);
+    res = MSVCRT_vfprintf(MSVCRT_stdout, format, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		wprintf (MSVCRT.@)
+ */
+int MSVCRT_wprintf(const MSVCRT_wchar_t *format, ...)
+{
+    va_list valist;
+    int res;
+    va_start(valist, format);
+    res = MSVCRT_vfwprintf(MSVCRT_stdout,format, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		vprintf (MSVCRT.@)
+ */
+int MSVCRT_vprintf(const char *format, va_list valist)
+{
+    return MSVCRT_vfprintf(MSVCRT_stdout,format,valist);
+}
+
+/*********************************************************************
+ *		vwprintf (MSVCRT.@)
+ */
+int MSVCRT_vwprintf(const MSVCRT_wchar_t *format, va_list valist)
+{
+    return MSVCRT_vfwprintf(MSVCRT_stdout,format,valist);
+}
+/*********************************************************************
+ *		fprintf (MSVCRT.@)
+ */
+int MSVCRT_fprintf(MSVCRT_FILE* file, const char *format, ...)
+{
+    va_list valist;
+    int res;
+    va_start(valist, format);
+    res = MSVCRT_vfprintf(file, format, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		fwprintf (MSVCRT.@)
+ */
+int MSVCRT_fwprintf(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, ...)
+{
+    va_list valist;
+    int res;
+    va_start(valist, format);
+    res = MSVCRT_vfwprintf(file, format, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		vsprintf (MSVCRT.@)
+ */
+int MSVCRT_vsprintf( char* str, const char* format, va_list args )
+{
+    char buf[2048], *mem = buf;
+    int written, resize = sizeof(buf)/sizeof(char), retval;
+    while ((written = _vsnprintf(mem, resize, format, args)) == -1)
+    {
+        resize*=2;
+        if (mem != buf)
+            MSVCRT_free (mem);
+        if (!(mem = (char *)MSVCRT_malloc(resize*sizeof(char))))
+            return (-1);
+    }
+    strcpy(str, mem);
+    if (mem != buf)
+        MSVCRT_free (mem);
+    return written;
+}
+
+/*********************************************************************
+ *		vswprintf (MSVCRT.@)
+ */
+int MSVCRT_vswprintf( MSVCRT_wchar_t* str, const MSVCRT_wchar_t* format, va_list args )
+{
+    MSVCRT_wchar_t buf[2048], *mem = buf;
+    int written, resize = sizeof(buf)/sizeof(MSVCRT_wchar_t), retval;
+    while ((written = _vsnwprintf(mem, resize, format, args)) == -1)
+    {
+        resize*=2;
+        if (mem != buf)
+            MSVCRT_free (mem);
+        if (!(mem = (MSVCRT_wchar_t *)MSVCRT_malloc(resize*sizeof(MSVCRT_wchar_t))))
+            return (-1);
+    }
+    wcscpy(str, mem);
+    if (mem != buf)
+        MSVCRT_free (mem);
+    return written;}
+
+/*********************************************************************
+ *		sprintf (MSVCRT.@)
+ */
+int MSVCRT_sprintf(char *str, const char *format, ... )
+{
+    va_list valist;
+    int res;
+    va_start(valist, format);
+    res = MSVCRT_vsprintf(str, format, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		swprintf (MSVCRT.@)
+ */
+int MSVCRT_swprintf( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *format, ... )
+{
+    va_list valist;
+    int res;
+    va_start(valist, format);
+    res = MSVCRT_vswprintf(str, format, valist);
+    va_end(valist);
+    return res;
+}
+
+/*********************************************************************
+ *		_snprintf (MSVCRT.@)
+ */
+int _snprintf(char *buffer, size_t count, const char *format, ... )
+{
+    va_list valist;
+    int res;
+    va_start(valist, format);
+    res = _vsnprintf(buffer, count, format, valist);
+    va_end(valist);
+    return res;    
+}
+
+/*********************************************************************
+ *		_snwprintf (MSVCRT.@)
+ */
+int _snwprintf(MSVCRT_wchar_t *buffer, size_t count, const MSVCRT_wchar_t *format, ... )
+{
+    va_list valist;
+    int res;
+    va_start(valist, format);
+    res = _vsnwprintf(buffer, count, format, valist);
+    va_end(valist);
+    return res;    
+}
--- /dev/null	2004-08-23 03:25:44.000000000 +0100
+++ dlls/msvcrt/printfhelpers.c	2004-11-01 09:50:49.000000000 +0000
@@ -0,0 +1,894 @@
+/*
+ * Functions used by msvcrt.dll printf functions
+ *
+ * Copyright 2004 Aneurin Price
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define LEFT_ALIGN 1
+#define SIGN_PREFIX 2
+#define ZERO_PAD 4
+#define BLANK_PAD 8
+#define ZERO_PREFIX 16
+#define LONG 32
+#define SHORT 64
+#define SIZE_T 128
+#define INT64 256
+#define INT32 512
+#define LONG_CHAR 1024
+#define SHORT_CHAR 2048
+#define PRECISION_COUNT 4096
+
+int integertostringw(__int64 in, MSVCRT_wchar_t *out, MSVCRT_wchar_t digits[], int base, int flags,int width,int precision, int length)
+{
+    MSVCRT_wchar_t *string=out;
+    MSVCRT_wchar_t *tempstring;
+    int charsdone=0;
+    int neg=0;
+    int inint=in;
+    short inh=in;
+    long inl=in;
+    __int64 num=inint;
+    ptrdiff_t inI=in;
+    __int32 inI32=in;
+    __int64 inI64=in;
+    tempstring=(MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),8,length*sizeof(MSVCRT_wchar_t));
+    *tempstring++=0;
+    if (flags&SHORT) /**Shorten input variable to the type specified**/
+        num=inh;
+    if (flags&LONG)
+        num=inl;
+    if (flags&SIZE_T)
+        num=inI;
+    if (flags&INT32)
+        num=inI32;
+    if (flags&INT64) /**which can't be longer than 64 bits**/
+        num=inI64;
+    if (num<0)
+    {
+        num=-num;
+        neg=1;
+        flags &=~SIGN_PREFIX;
+        flags &=~BLANK_PAD;
+    }
+    
+    if ((!num)&&(precision==-1)) /**Input zero, precision unspecified, just write 0**/
+    {
+        *tempstring++=digits[0];
+        charsdone++;
+    }
+    
+    while (num)
+    {
+        *tempstring++=digits[(num%base)]; /**Find each digit (starting at the little end)**/
+        num/=base; /**tempstring then points to the output string, backwards**/
+        charsdone++;
+    }
+    
+    while (charsdone<precision) /**If precision is higher than already written, pad the end with 0s**/
+    {
+        *tempstring++=digits[0];
+        charsdone++;
+    }
+    
+    if ((precision!=-1)&&(width>precision)) (flags&=~ZERO_PAD); /**If there is a precision specified, and it is less**/
+                                                            /**than the specified width, don't use 0s to pad**/
+    if (flags&LEFT_ALIGN)
+    {
+        if (neg) {*string++='-'; charsdone++;}
+        if (flags&SIGN_PREFIX) {*string++='+'; charsdone++;}
+        if (flags&BLANK_PAD) {*string++=' '; charsdone++;}
+        while (*--tempstring)
+        {
+             *string++=*tempstring;
+        }
+        while (charsdone<width)
+        {
+            *string++=' ';
+            charsdone++;
+        }
+    }
+    else
+    {
+        if (flags&ZERO_PAD)
+        {
+            if (neg) {*string++='-'; charsdone++;}
+            if (flags&SIGN_PREFIX) {*string++='+'; charsdone++;}
+            if (flags&BLANK_PAD) {*string++=' '; charsdone++;}
+            while (charsdone<width)
+            {
+                *string++='0';
+                charsdone++;
+            }
+        }
+        else /**Pad width with spaces**/
+        {
+            if (neg) {*tempstring++='-'; charsdone++;}
+            if (flags&SIGN_PREFIX) {*tempstring++='+'; charsdone++;}
+            if (flags&BLANK_PAD) {*tempstring++=' '; charsdone++;}
+            while (charsdone<width)
+            {
+                *string++=' ';
+                charsdone++;
+            }
+        }
+        while (*--tempstring)
+        {
+            *string++=*tempstring;
+        }
+    }
+    
+    HeapFree(GetProcessHeap(),0,tempstring);
+    return strlenW(out);
+}
+
+int uintegertostringw(unsigned __int64 in, MSVCRT_wchar_t *out, MSVCRT_wchar_t digits[], int base, int flags,int width,int precision,int length)
+{
+MSVCRT_wchar_t *string=out;
+MSVCRT_wchar_t *tempstring;
+int charsdone=0;
+unsigned int inint=in;
+unsigned short inh=in;
+unsigned long inl=in;
+size_t inI=in;
+unsigned __int32 inI32=in;
+unsigned __int64 inI64=in;
+unsigned __int64 num=inint;
+tempstring=(MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),8,length*sizeof(MSVCRT_wchar_t));
+*tempstring++=0;
+if (flags&SHORT) /**Shorten input variable to the type specified**/
+    num=inh;
+if (flags&LONG)
+    num=inl;
+if (flags&SIZE_T)
+    num=inI;
+if (flags&INT32)
+    num=inI32;
+if (flags&INT64) /**which can't be longer than 64 bits**/
+    num=inI64;
+
+if ((!num)&&(precision==-1))
+{
+    *tempstring++=digits[0];
+    charsdone++;
+}
+
+while (num)
+{
+    *tempstring++=digits[(num%base)];
+    num/=base;
+    charsdone++;
+}
+
+while (charsdone<precision)
+{
+    *tempstring++=digits[0];
+    charsdone++;
+}
+
+if ((precision!=-1)&&(width>precision)) (flags&=~ZERO_PAD); /**If there is a precision specified, and it is less**/
+                                                        /**than the specified width, don't use 0s to pad**/
+if (flags&LEFT_ALIGN)
+{
+    if ((base==16)&&(flags&ZERO_PREFIX)) {*string++=digits[0];*string++=digits[16];charsdone+=2;}
+    if ((base==8)&&(flags&ZERO_PREFIX)) {*string++=digits[0]; charsdone++;}
+    while (*--tempstring)
+    {
+         *string++=*tempstring;
+    }
+    while (charsdone<width)
+    {
+        *string++=' ';
+        charsdone++;
+    }
+}
+else
+{
+    if (flags&ZERO_PAD)
+    {
+        if ((base==16)&&(flags&ZERO_PREFIX)) {*string++=digits[0];*string++=digits[16];charsdone+=2;}
+        if ((base==8)&&(flags&ZERO_PREFIX)) {*string++=digits[0]; charsdone++;}
+        while (charsdone<width)
+        {
+            *string++='0';
+            charsdone++;
+        }
+    }
+    else
+    {
+        if ((base==16)&&(flags&ZERO_PREFIX)) {*tempstring++=digits[16];*tempstring++=digits[0];charsdone+=2;}
+        if ((base==8)&&(flags&ZERO_PREFIX)) {*tempstring++=digits[0]; charsdone++;}
+        while (charsdone<width)
+        {
+            *string++=' ';
+            charsdone++;
+        }
+    }
+    while (*--tempstring)
+    {
+         *string++=*tempstring;
+    }
+}
+
+HeapFree(GetProcessHeap(),0,tempstring);
+return strlenW(out);
+}
+
+int floattostringw(double in, MSVCRT_wchar_t *out, MSVCRT_wchar_t digits[], int flags,int width,int precision,int length)
+{
+MSVCRT_wchar_t *string=out;
+MSVCRT_wchar_t *tempstring;
+MSVCRT_wchar_t *tempstringstart;
+double temp;
+int prec;
+int charsdone=0;
+int neg=0;
+int infOrNaN=0;
+tempstring=(MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),8,length*sizeof(MSVCRT_wchar_t));
+tempstringstart=tempstring;
+*tempstring++=0;
+
+if (in<0)
+{
+    in=-in;
+    neg=1;
+    flags&=~SIGN_PREFIX;
+    flags&=~BLANK_PAD;
+}
+
+if (isinf(in))
+{
+    infOrNaN=1;
+    in=1.0;
+}
+
+if (isnan(in))
+{
+    infOrNaN=2;
+    in=1.0;
+}
+
+temp=in-floor(in);
+prec=precision;
+
+while (prec)
+{
+    temp*=10;
+    prec--;
+}
+temp+=0.5;
+while (floor(temp))
+{
+    *tempstring++=digits[(int)fmod(temp,10)];
+    temp/=10;
+    charsdone++;
+}
+
+if ((flags&PRECISION_COUNT)&&charsdone) /**Count trailing zeros, so the precision**/
+{ /**can be reduced by this amount when**/
+    tempstring-=charsdone; /**called to deal with %[gG] (which**/
+    charsdone=0; /**does not display trailing zeroes).**/
+    while (*tempstring++=='0') charsdone++;
+    HeapFree(GetProcessHeap(),0,tempstringstart);
+    return charsdone;
+}
+
+while (charsdone<precision) /**If the decimal point is not followed by a digit 1-9,**/
+{
+    *tempstring++=digits[0]; /**fill in leading zeroes**/
+    charsdone++;
+}
+
+if (flags&PRECISION_COUNT) /**If there were no non-zero characters, count trailing zeros, so the precision**/
+{ /**can be reduced by this amount when**/
+    HeapFree(GetProcessHeap(),0,tempstringstart); /**called to deal with %[gG] (which**/
+    return charsdone; /**does not display trailing zeroes).**/
+}
+
+if (infOrNaN==2)
+{
+    if (precision>=4) *(tempstring-4)='N';
+    if (precision>=3) *(tempstring-3)='A';
+    if (precision>=2) *(tempstring-2)='N';
+    if (precision>=1) *(tempstring-1)='#';
+}
+
+if (infOrNaN==1)
+{
+    if (precision>=4) *(tempstring-4)='F';
+    if (precision>=3) *(tempstring-3)='N';
+    if (precision>=2) *(tempstring-2)='I';
+    if (precision>=1) *(tempstring-1)='#';
+}
+
+if (precision||(flags&ZERO_PREFIX)) {*tempstring++='.'; charsdone++;}
+
+in=floor(in);
+
+if (!in)
+{
+    *tempstring++=digits[0];
+    charsdone++;
+}
+
+while (floor(in))
+{
+    *tempstring++=digits[(int)fmod(in,10)];
+    in/=10;
+    charsdone++;
+}
+
+if (flags&LEFT_ALIGN)
+{
+    if (neg) {*string++='-'; charsdone++;}
+    if (flags&SIGN_PREFIX) {*string++='+'; charsdone++;}
+    if (flags&BLANK_PAD) {*string++=' '; charsdone++;}
+    while (*--tempstring)
+    {
+         *string++=*tempstring;
+    }
+    while (charsdone<width)
+    {
+        *string++=' ';
+        charsdone++;
+    }
+}
+else
+{
+    if (flags&ZERO_PAD)
+    {
+        if (neg) {*string++='-'; charsdone++;}
+        if (flags&SIGN_PREFIX) {*string++='+'; charsdone++;}
+        if (flags&BLANK_PAD) {*string++=' '; charsdone++;}
+        while (charsdone<width)
+        {
+            *string++='0';
+            charsdone++;
+        }
+    }
+    else
+    {
+        if (neg) {*tempstring++='-'; charsdone++;}
+        if (flags&SIGN_PREFIX) {*tempstring++='+'; charsdone++;}
+        if (flags&BLANK_PAD) {*tempstring++=' '; charsdone++;}
+        while (charsdone<width)
+        {
+            *string++=' ';
+            charsdone++;
+        }
+    }
+    while (*--tempstring)
+    {
+        *string++=*tempstring;
+    }
+}
+
+HeapFree(GetProcessHeap(),0,tempstring);
+return strlenW(out);
+}
+
+int efloattostringw(double in, MSVCRT_wchar_t *out, MSVCRT_wchar_t digits[], int flags,int width,int precision,int length)
+{
+MSVCRT_wchar_t *string=out;
+int exp;
+int neg=0;
+int charsdone=0;
+int infOrNaN=0;
+double temp=in;
+
+if (in<0)
+{
+    in=-in;
+    neg=1;
+    flags&=~SIGN_PREFIX;
+    flags&=~BLANK_PAD;
+}
+
+if (isinf(in))
+{
+    infOrNaN=1;
+    in=0;
+}
+
+if (isnan(in))
+{
+    infOrNaN=2;
+    in=0;
+}
+
+if (in) exp=floor(log10(in));
+else exp=0;
+in/=pow(10,exp);
+if (neg) in=-in;
+if (infOrNaN) in=temp;
+if (flags&PRECISION_COUNT) return floattostringw(in,string,digits,flags,width-5,precision,length-5);
+if (!(flags&LEFT_ALIGN)) charsdone+=floattostringw(in,string,digits,flags,width-5,precision,length-5);
+else charsdone+=floattostringw(in,string,digits,flags,0,precision,length-5);
+string+=charsdone;
+*string++=digits[14];
+charsdone++;
+flags=0;
+flags|=SIGN_PREFIX;
+flags|=INT64;
+integertostringw((__int64)exp, string,digits,10,flags,0,3,5);
+charsdone+=4;
+string+=4;
+while (charsdone++<width) *string++=' ';
+return strlenW(out);
+}
+
+int gfloattostringw(double in, MSVCRT_wchar_t *out, MSVCRT_wchar_t digits[], int flags,int width,int precision,int length)
+{
+MSVCRT_wchar_t *string=out;
+int exp=floor(log10(in));
+int charsdone=0;
+if ((exp<-4)||(exp>=precision))
+{
+    precision-=1;
+    if (precision<0) precision=0;
+    if (!(flags&ZERO_PREFIX))
+    {
+        flags|=PRECISION_COUNT;
+        precision-=efloattostringw(in, out, digits, flags, width,precision,length);
+        flags&=~PRECISION_COUNT;
+    }
+    charsdone+=efloattostringw(in, out, digits, flags, width,precision,length);
+    string+=charsdone;
+}
+else
+{
+    precision-=(exp+1);
+    if (precision<0) precision=0;
+    if (!(flags&ZERO_PREFIX))
+    {
+        flags|=PRECISION_COUNT;
+        precision-=floattostringw(in, out, digits, flags, width,precision,length);
+        flags&=~PRECISION_COUNT;
+    }
+    charsdone+=floattostringw(in, out, digits, flags, width,precision,length);
+    string+=charsdone;
+}
+return strlenW(out);
+}
+
+MSVCRT_wchar_t *charprocessw(int in, int flags, int width)
+{
+char inA[]={0,0};
+MSVCRT_wchar_t *inW;
+MSVCRT_wchar_t *tempW;
+MSVCRT_wchar_t *out;
+int allocsize=2;
+int charsdone=1;
+if (width>allocsize) allocsize=width;
+tempW=(MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),0,(allocsize+1)*sizeof(MSVCRT_wchar_t));
+if (flags&SHORT_CHAR)
+{
+    inA[0]=(char)in;
+    MultiByteToWideChar(CP_ACP, 0, inA, -1, tempW, allocsize);
+}
+else *tempW=(MSVCRT_wchar_t)in;
+inW=(MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),0,(allocsize+1)*sizeof(MSVCRT_wchar_t));
+out=inW;
+if (!(flags&LEFT_ALIGN))
+{
+    if (flags&ZERO_PAD)
+        while (charsdone++<width) *inW++='0';
+    else
+        while (charsdone++<width) *inW++=' ';
+}*inW++=*tempW;
+HeapFree(GetProcessHeap(),0,tempW);
+if (flags&LEFT_ALIGN)
+{
+    while (charsdone++<width) *inW++=' ';
+}
+*inW=0;
+return out;
+}
+
+MSVCRT_wchar_t *stringprocessw(va_list *in, int flags, int width, int precision)
+{
+char *inA;
+MSVCRT_wchar_t *inW;
+MSVCRT_wchar_t *tempW;
+MSVCRT_wchar_t *out;
+MSVCRT_wchar_t nullstringW[]={'(','n','u','l','l',')',0};
+char nullstringA[]={'(','n','u','l','l',')',0};
+int allocsize=width;
+int length=0;
+int charsdone=0;
+if (flags&SHORT_CHAR)
+{
+    inA=va_arg(*in, char *);
+    if (!inA) inA=nullstringA;
+    length=strlen(inA);
+    if (length>allocsize) allocsize=length;
+    tempW=(MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),0,(allocsize+1)*sizeof(MSVCRT_wchar_t));
+    MultiByteToWideChar(CP_ACP, 0, inA, -1, tempW, allocsize);
+}
+else
+{
+    tempW=va_arg(*in, MSVCRT_wchar_t *);
+    if (!tempW) tempW=nullstringW;
+    length=strlenW(tempW);
+    if (length>allocsize) allocsize=length;
+}
+inW=(MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),0,(allocsize+1)*sizeof(MSVCRT_wchar_t));
+out=inW;
+if (precision!=-1) length=precision;
+charsdone=length;
+if (!(flags&LEFT_ALIGN))
+{
+    if (flags&ZERO_PAD)
+        while (charsdone++<width) *inW++='0';
+    else
+        while (charsdone++<width) *inW++=' ';
+}
+memcpy(inW,tempW,length*sizeof(MSVCRT_wchar_t));
+if (flags&SHORT_CHAR) HeapFree(GetProcessHeap(),0,tempW);
+inW+=length;
+if (flags&LEFT_ALIGN)
+{
+    while (charsdone++<width) *inW++=' ';
+}
+*inW=0;
+return out;
+}
+
+int processw(MSVCRT_wchar_t *output, const MSVCRT_wchar_t *input, size_t bufsize)
+{
+int ret=strlenW(input);
+if (ret >= bufsize)
+    memcpy(output, input, bufsize*sizeof(MSVCRT_wchar_t));
+else
+    memcpy(output, input, ret*sizeof(MSVCRT_wchar_t));
+return ret;
+}
+
+int _formatw(MSVCRT_wchar_t *output, const MSVCRT_wchar_t *input, size_t bufsize, va_list *args, int *skip, int done, int flags)
+{
+MSVCRT_wchar_t *stringarg=NULL;
+MSVCRT_wchar_t digitsl[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','x'};
+MSVCRT_wchar_t digitsu[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','X'};
+MSVCRT_wchar_t *digits=digitsu;
+MSVCRT_wchar_t nullstring[]={'(','n','u','l','l',')',0};
+MSVCRT_wchar_t percent[]={'%',0};
+MSVCRT_wchar_t null[]={0};
+int ret=0;
+int malloced=0;
+__int64 num=0;
+__int64 precision=-1;
+__int64 length=0;
+double dnum=0;
+unsigned int width=0;
+(*skip)++;
+input++;
+/**
+ **Flags:
+ **/
+while ((*input=='-')||(*input=='+')||(*input==' ')||(*input=='0')||(*input=='#'))
+{
+switch (*input)
+{
+    case '-':
+        flags|=LEFT_ALIGN;
+        flags&=~ZERO_PAD;
+        break;
+    case '+':
+        flags|=SIGN_PREFIX;
+        flags&=~BLANK_PAD;
+        break;
+    case '0':
+        if (!(flags&LEFT_ALIGN)) flags|=ZERO_PAD;
+        break;
+    case ' ':
+        if (!(flags&SIGN_PREFIX)) flags|=BLANK_PAD;
+        break;
+    case '#':
+        flags|=ZERO_PREFIX;
+        break;
+}
+(*skip)++;
+input++;
+}
+/**Width:
+ **
+ **/
+if (*input=='*')
+{
+    width=va_arg(*args, int);
+    input++;
+    (*skip)++;
+}
+while (iswdigit(*input))
+{
+    width*=10;
+    width+=(*input)-'0';
+    input++;
+    (*skip)++;
+}
+/**Precision:
+ **
+ **/
+if (*input=='.')
+{
+precision=0;
+input++;
+(*skip)++;
+    if (*input=='*')
+    {
+        precision=va_arg(*args, int);
+        input++;
+        (*skip)++;
+    }
+    while (iswdigit(*input))
+    {
+        precision*=10;
+        precision+=(*input)-'0';
+        input++;
+        (*skip)++;
+    }
+}
+/**Size:
+ **
+ **/
+
+switch(*input)
+{
+    case 'l':
+        (*skip)++;
+        input++;
+        flags|=LONG;
+        flags|=LONG_CHAR;
+        flags&=~SHORT_CHAR;
+        break;
+    case 'L':
+        (*skip)++;
+        input++;
+        flags|=LONG;
+        flags|=LONG_CHAR;
+        flags&=~SHORT_CHAR;
+        break;
+    case 'w':
+        (*skip)++;
+        input++;
+        flags|=LONG_CHAR;
+        flags&=~SHORT_CHAR;
+        break;
+    case 'h':
+        (*skip)++;
+        input++;
+        flags|=SHORT;
+        flags|=SHORT_CHAR;
+        flags&=~LONG_CHAR;
+        break;
+    case 'I':
+        (*skip)++;
+        input++;
+        if ((*(input)=='6')&&(*(input+1)=='4'))
+        {
+            (*skip)+=2;
+            input+=2;
+            flags|=INT64;
+            break;
+        }
+        if ((*(input)=='3')&&(*(input+1)=='2'))
+        {
+            (*skip)+=2;
+            input+=2;
+            flags|=INT32;
+            break;
+        }
+        flags|=SIZE_T;
+        break;
+    default:
+        flags|=SIZE_T;
+}
+
+while ((*input=='l')||(*input=='L')||(*input=='w')||(*input=='h')||(*input=='I')) /**Further size specifications are swallowed**/
+{
+    (*skip)++;
+    input++;
+    if ((*input=='6')&&(*(input+1)=='4'))
+    {
+        (*skip)+=2;
+        input+=2;
+    }
+    if ((*input=='3')&&(*(input+1)=='2'))
+    {
+        (*skip)+=2;
+        input+=2;
+    }
+}
+
+if ((*input=='i')||(*input=='d')||(*input=='u')||(*input=='o')||(*input=='x')||(*input=='X'))
+{
+if (flags&SHORT)
+    num=va_arg(*args, int);
+if (flags&LONG)
+    num=va_arg(*args, long);
+if (flags&SIZE_T)
+    num=va_arg(*args, ptrdiff_t);
+if (flags&INT32)
+    num=va_arg(*args, __int32);
+if (flags&INT64)
+    num=va_arg(*args, __int64);
+}
+switch(*input)
+{
+        case '%':
+            stringarg=percent;
+            (*skip)++;
+            break;
+        case 'n':
+            *va_arg(*args, int *)=done;
+            stringarg=null;
+            (*skip)++;
+            break;
+        case 'c':
+            (*skip)++;
+            malloced=1;
+            if (flags&SHORT_CHAR) {stringarg=charprocessw(va_arg(*args, int),flags,width); break;}
+            if (flags&LONG_CHAR) {stringarg=charprocessw(va_arg(*args, int),flags,width); break;}
+            if (flags&WIDE_PRINTF) flags|=LONG_CHAR;
+            else flags|=SHORT_CHAR;
+            stringarg=charprocessw(va_arg(*args, int),flags,width);
+            break;
+        case 'C':
+            (*skip)++;
+            malloced=1;
+            if (flags&SHORT_CHAR) {stringarg=charprocessw(va_arg(*args, int),flags,width); break;}
+            if (flags&LONG_CHAR) {stringarg=charprocessw(va_arg(*args, int),flags,width); break;}
+            if (flags&WIDE_PRINTF) flags|=SHORT_CHAR;
+            else flags|=LONG_CHAR;
+            stringarg=charprocessw(va_arg(*args, int),flags,width);
+            break;
+        case 's':
+            (*skip)++;
+            malloced=1;
+            if (flags&SHORT_CHAR) {stringarg=stringprocessw(args,flags,width,precision); break;}
+            if (flags&LONG_CHAR) {stringarg=stringprocessw(args,flags,width,precision); break;}
+            if (flags&WIDE_PRINTF) flags|=LONG_CHAR;
+            else flags|=SHORT_CHAR;
+            stringarg=stringprocessw(args,flags,width,precision);
+            break;
+        case 'S':
+            (*skip)++;
+            malloced=1;
+            if (flags&SHORT_CHAR) {stringarg=stringprocessw(args,flags,width,precision); break;}
+            if (flags&LONG_CHAR) {stringarg=stringprocessw(args,flags,width,precision); break;}
+            if (flags&WIDE_PRINTF) flags|=SHORT_CHAR;
+            else flags|=LONG_CHAR;
+            stringarg=stringprocessw(args,flags,width,precision);
+            break;
+        case 'i':
+        case 'd':
+            if (num>0) length=ceil(log10(num));
+            if (num==0) length=1;
+            if (num<0) length=ceil(log10(-num));
+            if (width>length) length=width;
+            if (precision>length) length=precision;
+            length+=2;
+            stringarg=(MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),8,length*sizeof(MSVCRT_wchar_t));
+            integertostringw(num,stringarg,digitsl,10,flags,width,precision,length);
+            (*skip)++;
+            malloced=1;
+            break;
+        case 'u':
+            if (num==0) length=1;
+            else length=ceil(log10((unsigned __int64)num));
+            if (width>length) length=width;
+            if (precision>length) length=precision;
+            length++;
+            stringarg=(MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),8,length*sizeof(MSVCRT_wchar_t));
+            uintegertostringw(num,stringarg,digitsl,10,flags,width,precision,length);
+            (*skip)++;
+            malloced=1;
+            break;
+        case 'o':
+            if (num==0) length=1;
+            else length=ceil(log((unsigned __int64)num)/log(8));
+            if (width>length) length=width;
+            if (precision>length) length=precision;
+            length++;
+            stringarg=(MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),8,length*sizeof(MSVCRT_wchar_t));
+            uintegertostringw(num,stringarg,digitsl,8,flags,width,precision,length);
+            (*skip)++;
+            malloced=1;
+            break;
+        case 'p':
+            num=(size_t)va_arg(*args, PVOID);
+            precision=8;
+            if (num==0) length=1;
+            else length=ceil(log((unsigned __int64)num)/log(16));
+            if (width>length) length=width;
+            if (precision>length) length=precision;
+            length++;
+            stringarg=(MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),8,length*sizeof(MSVCRT_wchar_t));
+            uintegertostringw(num,stringarg,digitsu,16,flags,width,precision,length);
+            (*skip)++;
+            malloced=1;
+            break;
+        case 'x':
+            digits=digitsl;
+        case 'X':
+            if (num==0) length=1;
+            else length=ceil(log((unsigned __int64)num)/log(16));
+            if (width>length) length=width;
+            if (precision>length) length=precision;
+            length++;
+            stringarg=(MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),8,length*sizeof(MSVCRT_wchar_t));
+            uintegertostringw(num,stringarg,digits,16,flags,width,precision,length);
+            (*skip)++;
+            malloced=1;
+            break;
+        case 'e':
+            digits=digitsl;
+        case 'E':
+            flags|=INT64;
+            dnum=va_arg(*args, double);
+            if (precision==-1) precision=6;
+            length=precision+9;
+            if (width>length) length=width;
+            length+=2;
+            stringarg=(MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),8,length*sizeof(MSVCRT_wchar_t));
+            efloattostringw(dnum,stringarg,digits,flags,width,precision,length);
+            (*skip)++;
+            malloced=1;
+            break;
+        case 'f':
+            flags|=INT64;
+            dnum=va_arg(*args, double);
+            if (precision==-1) precision=6;
+            if (dnum>0) length=precision+ceil(log10(dnum))+2;
+            if (dnum==0) length=precision+2;
+            if (dnum<0) length=precision+ceil(log10(-dnum))+2;
+            if (isinf(dnum)||isnan(dnum)) length=precision+2;
+            if (width>length) length=width;
+            length+=2;
+            stringarg=(MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),8,length*sizeof(MSVCRT_wchar_t));
+            floattostringw(dnum,stringarg,digitsl,flags,width,precision,length);
+            (*skip)++;
+            malloced=1;
+            break;
+        case 'g':
+            digits=digitsl;
+        case 'G':
+            flags|=INT64;
+            dnum=va_arg(*args, double);
+            if (precision==-1) precision=6;
+            if (dnum>0) length=precision+ceil(log10(dnum))+2;
+            if (dnum==0) length=precision+2;
+            if (dnum<0) length=precision+ceil(log10(-dnum))+2;
+            if (isinf(dnum)||isnan(dnum)) length=precision+2;
+            if ((precision+9)>length) length=precision+9;
+            if (width>length) length=width;
+            length+=2;
+            stringarg=(MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),8,length*sizeof(MSVCRT_wchar_t));
+            gfloattostringw(dnum,stringarg,digits,flags,width,precision,length);
+            (*skip)++;
+            malloced=1;
+            break;
+        default:
+            stringarg=null;
+}
+if (!stringarg)
+    stringarg=nullstring;
+ret=strlenW(stringarg);
+if (ret >= bufsize) ret=bufsize;
+memcpy(output, stringarg, ret*sizeof(MSVCRT_wchar_t));
+if (malloced) HeapFree(GetProcessHeap(),0,stringarg);
+return ret;
+}


More information about the wine-patches mailing list