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