I am still a little unsure about a couple of points; ones I can remember off the top of my head: probably insufficient attribution for code derived from file.c, since I have no idea who wrote the functions I used (these are specified in the copyright notice for printf.c, BTW). It's also pretty big; I presume it's okay to have this much in one file, but maybe not. Either way it can't be broken down into smaller patches since it's one big change.
Thanks,
Aneurin Price
Index: dlls/msvcrt/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/Makefile.in,v
retrieving revision 1.17
diff -u -u -r1.17 Makefile.in
--- dlls/msvcrt/Makefile.in 8 Nov 2004 22:10:43 -0000 1.17
+++ dlls/msvcrt/Makefile.in 6 Jan 2005 15:59:55 -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.79
diff -u -u -r1.79 file.c
--- dlls/msvcrt/file.c 4 Jan 2005 20:37:54 -0000 1.79
+++ dlls/msvcrt/file.c 6 Jan 2005 15:59:59 -0000
@@ -2831,113 +2831,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.@)
@@ -2971,6 +2864,8 @@
}
return mwc;
}
+<<<<<<< file.c
+=======
/*********************************************************************
* wprintf (MSVCRT.@)
@@ -3007,3 +2902,4 @@
* __badioinfo (MSVCRT.@)
*/
ioinfo MSVCRT___badioinfo = { INVALID_HANDLE_VALUE, WX_TEXT };
+>>>>>>> 1.79
Index: dlls/msvcrt/msvcrt.spec
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/msvcrt.spec,v
retrieving revision 1.95
diff -u -u -r1.95 msvcrt.spec
--- dlls/msvcrt/msvcrt.spec 10 Dec 2004 15:28:25 -0000 1.95
+++ dlls/msvcrt/msvcrt.spec 6 Jan 2005 16:00:00 -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 6 Jan 2005 16:00:00 -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 2005-01-01 18:38:10.000000000 +0000
+++ dlls/msvcrt/printf.c 2005-01-06 15:53:36.000000000 +0000
@@ -0,0 +1,1458 @@
+/*
+ * msvcrt.dll printf functions
+ *
+ * Copyright 2004 Aneurin Price
+ * Definitions of vf[w]printf, [w]printf, v[w]printf, f[w]printf,
+ * vs[w]printf, s[w]printf, and _sn[w]printf wrapper functions
+ * derived from file.c. See that file for copyright holders.
+ *
+ * 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"
+
+#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
+#define WIDE_PRINTF 8192
+#define INPUT_GIVEN 16384
+
+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);
+
+typedef struct
+{
+ int flags;
+ unsigned int width;
+ __int64 precision;
+ const MSVCRT_wchar_t *input;
+ MSVCRT_wchar_t *output;
+ int HeapAlloced;
+ union
+ {
+ int intIn;
+ double doubleIn;
+ };
+} PRINTF_SPECIFIER;
+
+PRINTF_SPECIFIER integertostringw(va_list *args, MSVCRT_wchar_t digits[], PRINTF_SPECIFIER specifier)
+{
+ MSVCRT_wchar_t *string;
+ MSVCRT_wchar_t *tempstring;
+ __int64 length = 0;
+ __int64 num = 0;
+ int charsdone = 0;
+ int neg = 0;
+
+ if (specifier.flags & INPUT_GIVEN)
+ num = (__int64)specifier.intIn;
+ else if (specifier.flags & SIZE_T)
+ num = (__int64)va_arg(*args, ptrdiff_t);
+ else if (specifier.flags & SHORT)
+ num = (__int64)(short)va_arg(*args, int);
+ else if (specifier.flags & LONG)
+ num = (__int64)va_arg(*args, long);
+ else if (specifier.flags & INT32)
+ num = (__int64)va_arg(*args, __int32);
+ else if (specifier.flags & INT64)
+ num = va_arg(*args, __int64);
+
+/* Need to determine the string length
+ * necessary to hold the output.
+ */
+ if (num > 0)
+ length = ceil(log10(num));
+ else if (num < 0)
+ length = ceil(log10(-num));
+ else
+ length = 1;
+
+ if (specifier.width > length)
+ length = specifier.width;
+
+ if (specifier.precision > length)
+ length = specifier.precision;
+
+ length += 2;
+ /*Add 2 for sign and null terminator*/
+ string = (MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),0,length * sizeof(MSVCRT_wchar_t));
+ specifier.HeapAlloced = 1;
+ tempstring = (MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),0,length * sizeof(MSVCRT_wchar_t));
+ *tempstring++ = 0;
+
+ if (num<0)
+ {
+ num = -num;
+ neg = 1;
+ specifier.flags &= ~SIGN_PREFIX;
+ specifier.flags &= ~BLANK_PAD;
+ }
+
+ if ((!num) && (specifier.precision == -1))
+ /* Input zero, precision unspecified, just write 0 */
+ {
+ *tempstring++ = digits[0];
+ charsdone++;
+ }
+
+ while (num)
+ {
+ /* Find each digit (starting at the little end).
+ * tempstring then points to the output string, backwards.
+ * Ie. it's used as a stack from which chars are popped
+ * and pushed on to the output.
+ */
+ *tempstring++ = digits[num % 10];
+ num /= 10;
+ charsdone++;
+ }
+
+ while (charsdone < specifier.precision)
+ {
+ /* If precision is higher than already written, pad the end with 0s */
+ *tempstring++ = digits[0];
+ charsdone++;
+ }
+
+ /* If there is a precision specified, and it is less
+ * than the specified width, don't use 0s to pad
+ */
+ if ((specifier.precision != -1) && (specifier.width > specifier.precision))
+ specifier.flags &= ~ZERO_PAD;
+
+ if (specifier.flags & LEFT_ALIGN)
+ /* The output should be left-aligned */
+ {
+ if (neg)
+ {
+ *string++ = '-';
+ charsdone++;
+ }
+ if (specifier.flags & SIGN_PREFIX)
+ {
+ *string++ = '+';
+ charsdone++;
+ }
+ if (specifier.flags & BLANK_PAD)
+ {
+ *string++ = ' ';
+ charsdone++;
+ }
+ while (*--tempstring)
+ {
+ *string++ = *tempstring;
+ }
+ while (charsdone < specifier.width)
+ {
+ *string++ = ' ';
+ charsdone++;
+ }
+ }
+ else
+ /* The output should be right-aligned */
+ {
+ if (specifier.flags & ZERO_PAD)
+ /* Pad up to width with 0s */
+ {
+ if (neg)
+ {
+ *string++ = '-';
+ charsdone++;
+ }
+ /* Sign should be before 0s, so add it to string */
+ if (specifier.flags & SIGN_PREFIX)
+ {
+ *string++ = '+';
+ charsdone++;
+ }
+ if (specifier.flags & BLANK_PAD)
+ {
+ *string++ = ' ';
+ charsdone++;
+ }
+ while (charsdone < specifier.width)
+ {
+ *string++ = '0';
+ charsdone++;
+ }
+ }
+ else
+ /* Pad up to width with spaces */
+ {
+ if (neg)
+ /* Sign should be after spaces, so add it to
+ * tempstring, which will be copied backwards to string
+ */
+ {
+ *tempstring++ = '-';
+ charsdone++;
+ }
+ if (specifier.flags & SIGN_PREFIX)
+ {
+ *tempstring++ = '+';
+ charsdone++;
+ }
+ if (specifier.flags & BLANK_PAD)
+ {
+ *tempstring++ = ' ';
+ charsdone++;
+ }
+ while (charsdone < specifier.width)
+ {
+ *string++ = ' ';
+ charsdone++;
+ }
+ }
+ while (*--tempstring)
+ {
+ *string++ = *tempstring;
+ }
+ }
+
+ *string = 0;
+ HeapFree(GetProcessHeap(),0,tempstring);
+ specifier.output = string - charsdone;
+ return specifier;
+}
+
+PRINTF_SPECIFIER uintegertostringw(va_list *args, MSVCRT_wchar_t digits[], int base, PRINTF_SPECIFIER specifier)
+{
+ MSVCRT_wchar_t *string;
+ MSVCRT_wchar_t *tempstring;
+ int charsdone = 0;
+ __int64 length;
+ unsigned __int64 num = 0;
+
+ if (specifier.flags & SIZE_T)
+ num = (unsigned __int64)va_arg(*args, size_t);
+ else if (specifier.flags & SHORT)
+ num = (unsigned __int64)(unsigned short)va_arg(*args, unsigned int);
+ else if (specifier.flags & LONG)
+ num = (unsigned __int64)va_arg(*args, unsigned long);
+ else if (specifier.flags & INT32)
+ num = (unsigned __int64)va_arg(*args, unsigned __int32);
+ else if (specifier.flags & INT64)
+ num = va_arg(*args, unsigned __int64);
+
+ if (num == 0)
+ length = 1;
+ else
+ length = ceil(log((unsigned __int64)num) / log(base));
+ if (specifier.width > length)
+ length = specifier.width;
+ if (specifier.precision > length)
+ length = specifier.precision;
+ length++;
+ string = (MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),0,length * sizeof(MSVCRT_wchar_t));
+ specifier.HeapAlloced = 1;
+ tempstring = (MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),0,length * sizeof(MSVCRT_wchar_t));
+ *tempstring++ = 0;
+
+ if ((!num) && (specifier.precision == -1))
+ {
+ *tempstring++ = digits[0];
+ charsdone++;
+ }
+
+ while (num)
+ {
+ *tempstring++ = digits[num % base];
+ num /= base;
+ charsdone++;
+ }
+
+ while (charsdone < specifier.precision)
+ {
+ *tempstring++ = digits[0];
+ charsdone++;
+ }
+
+ /*If there is a precision specified, and it is less
+ *than the specified width, don't use 0s to pad
+ */
+ if ((specifier.precision != -1) && (specifier.width > specifier.precision))
+ (specifier.flags &= ~ZERO_PAD);
+
+ if (specifier.flags & LEFT_ALIGN)
+ {
+ if ((base == 16) && (specifier.flags & ZERO_PREFIX))
+ {
+ *string++ = digits[0];
+ *string++ = digits[16];
+ charsdone += 2;
+ }
+ if ((base == 8) && (specifier.flags & ZERO_PREFIX))
+ {
+ *string++ = digits[0];
+ charsdone++;
+ }
+ while (*--tempstring)
+ {
+ *string++ = *tempstring;
+ }
+ while (charsdone < specifier.width)
+ {
+ *string++ = ' ';
+ charsdone++;
+ }
+ }
+ else
+ {
+ if (specifier.flags & ZERO_PAD)
+ {
+ if ((base == 16) && (specifier.flags & ZERO_PREFIX))
+ {
+ *string++ = digits[0];
+ *string++ = digits[16];
+ charsdone += 2;
+ }
+ if ((base == 8) && (specifier.flags & ZERO_PREFIX))
+ {
+ *string++ = digits[0];
+ charsdone++;
+ }
+ while (charsdone < specifier.width)
+ {
+ *string++ = '0';
+ charsdone++;
+ }
+ }
+ else
+ {
+ if ((base == 16) && (specifier.flags & ZERO_PREFIX))
+ {
+ *tempstring++ = digits[16];
+ *tempstring++ = digits[0];
+ charsdone += 2;
+ }
+ if ((base == 8) && (specifier.flags & ZERO_PREFIX))
+ {
+ *tempstring++ = digits[0];
+ charsdone++;
+ }
+ while (charsdone < specifier.width)
+ {
+ *string++ = ' ';
+ charsdone++;
+ }
+ }
+ while (*--tempstring)
+ {
+ *string++ = *tempstring;
+ }
+ }
+ *string = 0;
+ HeapFree(GetProcessHeap(),0,tempstring);
+ specifier.output = string-charsdone;
+ return specifier;
+}
+
+PRINTF_SPECIFIER floattostringw(va_list *args, MSVCRT_wchar_t digits[], PRINTF_SPECIFIER specifier)
+{
+ MSVCRT_wchar_t *string;
+ MSVCRT_wchar_t *tempstring;
+ MSVCRT_wchar_t *tempstringstart;
+ double temp;
+ int prec;
+ int charsdone = 0;
+ int neg = 0;
+ int infOrNaN = 0;
+ double in;
+ double length = 0;
+
+ if (specifier.flags & INPUT_GIVEN)
+ in = specifier.doubleIn;
+ else
+ in = va_arg(*args, double);
+
+ if (specifier.precision == -1)
+ specifier.precision = 6;
+
+ if (in == 0)
+ length = specifier.precision + 2;
+ /*Add 2 for leading 0 and decimal point*/
+ else if (isinf(in) || isnan(in))
+ length = specifier.precision + 2;
+ else if (in > 0)
+ length = specifier.precision + ceil(log10(in) + 1);
+ /*Add 1 for decimal point*/
+ else if (in < 0)
+ length = specifier.precision + ceil(log10(-in) + 1);
+ if (specifier.width > length)
+ length = specifier.width;
+ length += 2;
+ /*Add 2 for sign and null terminator*/
+ tempstring = (MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),0,length * sizeof(MSVCRT_wchar_t));
+ tempstringstart = tempstring;
+ *tempstring++ = 0;
+
+ if (in < 0)
+ {
+ in = -in;
+ neg = 1;
+ specifier.flags &= ~SIGN_PREFIX;
+ specifier.flags &= ~BLANK_PAD;
+ }
+
+ if (isinf(in))
+ {
+ infOrNaN = 1;
+ in = 1.0;
+ }
+
+ if (isnan(in))
+ {
+ infOrNaN = 2;
+ in = 1.0;
+ }
+
+ temp = in - floor(in);
+ prec = specifier.precision;
+
+ while (prec)
+ {
+ temp *= 10;
+ prec--;
+ }
+ temp += 0.5;
+ while (floor(temp))
+ {
+ *tempstring++ = digits[(int)fmod(temp,10)];
+ temp /= 10;
+ charsdone++;
+ }
+
+ if ((specifier.flags & PRECISION_COUNT) && charsdone)
+ /*Count trailing zeros, so the precision can be reduced
+ *by this amount when called to deal with %[gG] (which
+ *does not display trailing zeroes).
+ */
+ {
+ tempstring -= charsdone;
+ charsdone = 0;
+ while (*tempstring++ == '0')
+ charsdone++;
+ HeapFree(GetProcessHeap(),0,tempstringstart);
+ specifier.precision -= charsdone;
+ return specifier;
+ }
+
+ while (charsdone < specifier.precision)
+ /*If the decimal point is not followed by a digit 1-9,
+ *fill in trailing zeroes
+ */
+ {
+ *tempstring++ = digits[0];
+ charsdone++;
+ }
+
+ if (specifier.flags & PRECISION_COUNT)
+ /*If there were no non-zero characters, charsdone is
+ *now the number of trailing zeros, so reduce the
+ *precision by this amount when called to deal with
+ *%[gG] (which does not display trailing zeroes).
+ */
+ {
+ HeapFree(GetProcessHeap(),0,tempstringstart);
+ specifier.precision -= charsdone;
+ return specifier;
+ }
+
+ if (infOrNaN == 2)
+ {
+ FIXME("Outputting possibly incorrect string for NAN.\n");
+ /*Although an output of "NAN" is specified by MSDN,
+ *native msvcrt.dll seems to output QNAN. Also, when the
+ *specified precision causes the string to be truncated,
+ *the final character outputted is incremented by one.
+ *I've ignored this for the moment
+ */
+ if (specifier.precision >= 4)
+ *(tempstring - 4) = 'N';
+ if (specifier.precision >= 3)
+ *(tempstring - 3) = 'A';
+ if (specifier.precision >= 2)
+ *(tempstring - 2) = 'N';
+ if (specifier.precision >= 1)
+ *(tempstring - 1) = '#';
+ }
+
+ if (infOrNaN == 1)
+ {
+ if (specifier.precision >= 4)
+ *(tempstring - 4) = 'F';
+ if (specifier.precision >= 3)
+ *(tempstring - 3) = 'N';
+ if (specifier.precision >= 2)
+ *(tempstring - 2) = 'I';
+ if (specifier.precision >= 1)
+ *(tempstring - 1) = '#';
+ }
+
+ if (specifier.precision || (specifier.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++;
+ }
+
+ string = (MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),0,length * sizeof(MSVCRT_wchar_t));
+ specifier.HeapAlloced = 1;
+ specifier.output = string;
+
+ if (specifier.flags & LEFT_ALIGN)
+ {
+ if (neg)
+ {
+ *string++ = '-';
+ charsdone++;
+ }
+ if (specifier.flags & SIGN_PREFIX)
+ {
+ *string++ = '+';
+ charsdone++;
+ }
+ if (specifier.flags & BLANK_PAD)
+ {
+ *string++ = ' ';
+ charsdone++;
+ }
+ while (*--tempstring)
+ {
+ *string++ = *tempstring;
+ }
+ while (charsdone < specifier.width)
+ {
+ *string++ = ' ';
+ charsdone++;
+ }
+ }
+ else
+ {
+ if (specifier.flags & ZERO_PAD)
+ {
+ if (neg)
+ {
+ *string++ = '-';
+ charsdone++;
+ }
+ if (specifier.flags & SIGN_PREFIX)
+ {
+ *string++ = '+';
+ charsdone++;
+ }
+ if (specifier.flags & BLANK_PAD)
+ {
+ *string++ = ' ';
+ charsdone++;
+ }
+ while (charsdone < specifier.width)
+ {
+ *string++ = '0';
+ charsdone++;
+ }
+ }
+ else
+ {
+ if (neg)
+ {
+ *tempstring++ = '-';
+ charsdone++;
+ }
+ if (specifier.flags & SIGN_PREFIX)
+ {
+ *tempstring++ = '+';
+ charsdone++;
+ }
+ if (specifier.flags & BLANK_PAD)
+ {
+ *tempstring++ = ' ';
+ charsdone++;
+ }
+ while (charsdone < specifier.width)
+ {
+ *string++ = ' ';
+ charsdone++;
+ }
+ }
+ while (*--tempstring)
+ {
+ *string++ = *tempstring;
+ }
+ }
+ *string = 0;
+ HeapFree(GetProcessHeap(),0,tempstring);
+ return specifier;
+}
+
+PRINTF_SPECIFIER efloattostringw(va_list *args, MSVCRT_wchar_t digits[], PRINTF_SPECIFIER specifier)
+{
+ MSVCRT_wchar_t *string;
+ int exp;
+ int neg = 0;
+ int charsdone = 0;
+ int infOrNaN = 0;
+ double in = va_arg(*args, double);
+ double temp = in;
+ unsigned int width;
+
+ if (in < 0)
+ {
+ in = -in;
+ neg = 1;
+ specifier.flags &= ~SIGN_PREFIX;
+ specifier.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;
+
+ width = specifier.width;
+ specifier.flags |= INPUT_GIVEN;
+
+ if ((specifier.flags & LEFT_ALIGN) || (width < 6))
+ specifier.width = 0;
+ else
+ specifier.width -= 5;
+
+ specifier.doubleIn = in;
+ specifier = floattostringw(args,digits,specifier);
+ charsdone = strlenW(specifier.output);
+
+ if (specifier.width > charsdone + 5)
+ string = (MSVCRT_wchar_t *)HeapReAlloc(GetProcessHeap(),0,
+ specifier.output,(specifier.width+1) * sizeof(MSVCRT_wchar_t));
+ else
+ string = (MSVCRT_wchar_t *)HeapReAlloc(GetProcessHeap(),0,
+ specifier.output,(charsdone+6) * sizeof(MSVCRT_wchar_t));
+
+ string += charsdone;
+ *string++ = digits[14];
+ charsdone++;
+ specifier.flags = 0;
+ specifier.flags |= INPUT_GIVEN;
+ specifier.flags |= SIGN_PREFIX;
+ specifier.intIn = exp;
+ specifier.width = 0;
+ specifier.precision = 3;
+ specifier = integertostringw(args,digits,specifier);
+ charsdone += 4;
+ *string++ =*(specifier.output);
+ *string++ =*(specifier.output + 1);
+ *string++ =*(specifier.output + 2);
+ *string++ =*(specifier.output + 3);
+ HeapFree(GetProcessHeap(),0,specifier.output);
+ while (charsdone < width)
+ {
+ *string++ = ' ';
+ charsdone++;
+ }
+ *string = 0;
+ specifier.output = string-charsdone;
+ return specifier;
+}
+
+PRINTF_SPECIFIER gfloattostringw(va_list *args, MSVCRT_wchar_t digits[], PRINTF_SPECIFIER specifier)
+{
+ double in = va_arg(*args, double);
+ int exp = floor(log10(in));
+
+ specifier.doubleIn = in;
+ specifier.flags |= INPUT_GIVEN;
+
+ if (specifier.precision == -1)
+ specifier.precision = 6;
+
+ if ((exp < -4) || (exp >= specifier.precision))
+ {
+ specifier.precision -= 1;
+ if (specifier.precision < 0)
+ specifier.precision = 0;
+ if (!(specifier.flags & ZERO_PREFIX))
+ /*Need to determine how many trailing 0s so precision can
+ *be reduced, as they should not be printed.
+ */
+ {
+ specifier.flags |= PRECISION_COUNT;
+ specifier = floattostringw(args, digits, specifier);
+ specifier.flags &= ~PRECISION_COUNT;
+ }
+ specifier = efloattostringw(args, digits, specifier);
+ }
+ else
+ {
+ specifier.precision -= (exp + 1);
+ if (specifier.precision < 0)
+ specifier.precision = 0;
+ if (!(specifier.flags & ZERO_PREFIX))
+ {
+ specifier.flags |= PRECISION_COUNT;
+ specifier = floattostringw(args, digits, specifier);
+ specifier.flags &= ~PRECISION_COUNT;
+ }
+ specifier = floattostringw(args, digits, specifier);
+ }
+ return specifier;
+}
+
+PRINTF_SPECIFIER charprocessw(int in, PRINTF_SPECIFIER specifier)
+{
+ char inA[] = {0,0};
+ MSVCRT_wchar_t *inW;
+ MSVCRT_wchar_t *tempW;
+ int allocsize = 2;
+ int charsdone = 1;
+
+ if (!(specifier.flags & SHORT_CHAR) && !(specifier.flags & LONG_CHAR))
+ /*If character width is unspecified, set it appropriately.
+ */
+ {
+ if (specifier.flags & WIDE_PRINTF)
+ specifier.flags |= LONG_CHAR;
+ else
+ specifier.flags |= SHORT_CHAR;
+ }
+
+ if (specifier.width > allocsize)
+ allocsize = specifier.width;
+ tempW = (MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),0,(allocsize + 1) * sizeof(MSVCRT_wchar_t));
+ if (specifier.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));
+ specifier.HeapAlloced = 1;
+ specifier.output = inW;
+ if (!(specifier.flags & LEFT_ALIGN))
+ {
+ if (specifier.flags & ZERO_PAD)
+ while (charsdone++ < specifier.width)
+ *inW++ = '0';
+ else
+ while (charsdone++ < specifier.width)
+ *inW++ = ' ';
+ }
+ *inW++ = *tempW;
+ HeapFree(GetProcessHeap(),0,tempW);
+ if (specifier.flags & LEFT_ALIGN)
+ while (charsdone++ < specifier.width)
+ *inW++ = ' ';
+ *inW = 0;
+ return specifier;
+}
+
+PRINTF_SPECIFIER stringprocessw(va_list *in, PRINTF_SPECIFIER specifier)
+{
+ char *inA;
+ MSVCRT_wchar_t *inW;
+ MSVCRT_wchar_t *tempW;
+ MSVCRT_wchar_t nullstringW[] = {'(','n','u','l','l',')',0};
+ char nullstringA[] = {'(','n','u','l','l',')',0};
+ int allocsize = specifier.width;
+ int length = 0;
+ int charsdone = 0;
+
+ if (!(specifier.flags & SHORT_CHAR) && !(specifier.flags & LONG_CHAR))
+ /*If character width is unspecified, set it appropriately.
+ */
+ {
+ if (specifier.flags & WIDE_PRINTF)
+ specifier.flags |= LONG_CHAR;
+ else
+ specifier.flags |= SHORT_CHAR;
+ }
+
+ if (specifier.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));
+ specifier.HeapAlloced = 1;
+ specifier.output = inW;
+ if (specifier.precision != -1)
+ length = specifier.precision;
+ charsdone = length;
+ if (!(specifier.flags & LEFT_ALIGN))
+ {
+ if (specifier.flags & ZERO_PAD)
+ while (charsdone++ < specifier.width)
+ *inW++ = '0';
+ else
+ while (charsdone++ < specifier.width)
+ *inW++ = ' ';
+ }
+ memcpy(inW,tempW,length*sizeof(MSVCRT_wchar_t));
+ if (specifier.flags & SHORT_CHAR)
+ HeapFree(GetProcessHeap(),0,tempW);
+
+ inW += length;
+ if (specifier.flags & LEFT_ALIGN)
+ {
+ while (charsdone++ < specifier.width)
+ *inW++ = ' ';
+ }
+ *inW = 0;
+ return specifier;
+}
+
+PRINTF_SPECIFIER specParse(PRINTF_SPECIFIER specifier, va_list *args)
+{
+/*Flags:
+ */
+ while ((*(specifier.input) == '-')||
+ (*(specifier.input) == '+')||
+ (*(specifier.input) == ' ')||
+ (*(specifier.input) == '0')||
+ (*(specifier.input) == '#'))
+ {
+ switch (*(specifier.input))
+ {
+ case '-':
+ (specifier.flags) |= LEFT_ALIGN;
+ (specifier.flags) &= ~ZERO_PAD;
+ break;
+ case '+':
+ (specifier.flags) |= SIGN_PREFIX;
+ (specifier.flags) &= ~BLANK_PAD;
+ break;
+ case '0':
+ if (!((specifier.flags) & LEFT_ALIGN))
+ (specifier.flags) |= ZERO_PAD;
+ break;
+ case ' ':
+ if (!((specifier.flags) & SIGN_PREFIX))
+ (specifier.flags) |= BLANK_PAD;
+ break;
+ case '#':
+ (specifier.flags) |= ZERO_PREFIX;
+ break;
+ }
+ specifier.input++;
+ }
+/*Width:
+ */
+ specifier.width = 0;
+ if (*(specifier.input) == '*')
+ {
+ specifier.width = va_arg(*args, int);
+ specifier.input++;
+ }
+ while (iswdigit(*(specifier.input)))
+ {
+ specifier.width *= 10;
+ specifier.width += *(specifier.input) - '0';
+ specifier.input++;
+ }
+/*Precision:
+ */
+ specifier.precision = -1;
+ if (*(specifier.input) == '.')
+ {
+ specifier.precision = 0;
+ specifier.input++;
+ if (*(specifier.input) == '*')
+ {
+ specifier.precision = va_arg(*args, int);
+ specifier.input++;
+ }
+ while (iswdigit(*(specifier.input)))
+ {
+ specifier.precision *= 10;
+ specifier.precision += *(specifier.input) - '0';
+ specifier.input++;
+ }
+ }
+/*Size:
+ */
+ switch(*(specifier.input))
+ {
+ case 'l':
+ case 'L':
+ specifier.flags |= LONG;
+ case 'w':
+ specifier.input++;
+ specifier.flags |= LONG_CHAR;
+ specifier.flags &= ~SHORT_CHAR;
+ break;
+ case 'h':
+ specifier.input++;
+ specifier.flags |= SHORT;
+ specifier.flags |= SHORT_CHAR;
+ specifier.flags &= ~LONG_CHAR;
+ break;
+ case 'I':
+ specifier.input++;
+ if ((*(specifier.input) == '6') && (*(specifier.input + 1) == '4'))
+ {
+ specifier.input += 2;
+ specifier.flags |= INT64;
+ break;
+ }
+ if ((*(specifier.input) == '3') && (*(specifier.input + 1) == '2'))
+ {
+ specifier.input += 2;
+ specifier.flags |= INT32;
+ break;
+ }
+ specifier.flags |= SIZE_T;
+ break;
+ default:
+ specifier.flags |= SIZE_T;
+ }
+
+ while ((*(specifier.input) == 'l')||
+ (*(specifier.input) == 'L')||
+ (*(specifier.input) == 'w')||
+ (*(specifier.input) == 'h')||
+ (*(specifier.input) == 'I'))
+ /* Further size specifiers are swallowed; this isn't specified, but was determined from testing.
+ * Thus "ll", for example, does not mean "long long" (I64 should be used instead), but "long"
+ */
+ {
+ specifier.input++;
+ if ((*(specifier.input - 1) == 'I')&&
+ (*(specifier.input) == '6')&&
+ (*(specifier.input + 1) == '4'))
+ {
+ specifier.input += 2;
+ }
+ if ((*(specifier.input - 1) == 'I')&&
+ (*(specifier.input) == '3')&&
+ (*(specifier.input + 1) == '2'))
+ {
+ specifier.input += 2;
+ }
+ }
+ return specifier;
+}
+
+PRINTF_SPECIFIER process(PRINTF_SPECIFIER specifier, va_list *args, int done)
+{
+ 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 percent[] = {'%',0};
+ MSVCRT_wchar_t null[] = {0};
+ specifier.HeapAlloced = 0;
+
+ switch(*(specifier.input))
+ {
+ case '%':
+ specifier.output = percent;
+ break;
+ case 'n':
+ *va_arg(*args, int *) = done;
+ specifier.output = null;
+ break;
+ case 'C':
+ if (specifier.flags & WIDE_PRINTF)
+ specifier.flags &= ~WIDE_PRINTF;
+ else
+ specifier.flags |= WIDE_PRINTF;
+ case 'c':
+ specifier = charprocessw(va_arg(*args, int),specifier);
+ break;
+ case 'S':
+ if (specifier.flags & WIDE_PRINTF)
+ specifier.flags &= ~WIDE_PRINTF;
+ else
+ specifier.flags |= WIDE_PRINTF;
+ case 's':
+ specifier = stringprocessw(args,specifier);
+ break;
+ case 'i':
+ case 'd':
+ specifier = integertostringw(args,digitsl,specifier);
+ break;
+ case 'u':
+ specifier = uintegertostringw(args,digitsl,10,specifier);
+ break;
+ case 'o':
+ specifier = uintegertostringw(args,digitsl,8,specifier);
+ break;
+ case 'p':
+ specifier.precision = 8;
+ specifier.flags |= SIZE_T;
+ specifier = uintegertostringw(args,digitsu,16,specifier);
+ break;
+ case 'X':
+ specifier = uintegertostringw(args,digitsu,16,specifier);
+ break;
+ case 'x':
+ specifier = uintegertostringw(args,digitsl,16,specifier);
+ break;
+ case 'E':
+ specifier = efloattostringw(args,digitsu,specifier);
+ break;
+ case 'e':
+ specifier = efloattostringw(args,digitsl,specifier);
+ break;
+ case 'f':
+ specifier = floattostringw(args,digitsl,specifier);
+ break;
+ case 'G':
+ specifier = gfloattostringw(args,digitsu,specifier);
+ break;
+ case 'g':
+ specifier = gfloattostringw(args,digitsl,specifier);
+ break;
+ default:
+ specifier.output = null;
+ specifier.input--;
+ }
+
+ specifier.input++;
+ return specifier;
+}
+
+int formatw(MSVCRT_wchar_t *output, const MSVCRT_wchar_t *input, size_t bufsize, va_list *args, int *charsRead, int done, int flags)
+{
+ int ret;
+ MSVCRT_wchar_t nullstring[] = {'(','n','u','l','l',')',0};
+ PRINTF_SPECIFIER specifier;
+
+ specifier.input = (input + 1);
+ specifier.flags = flags;
+ specifier = specParse(specifier, args);
+ specifier = process(specifier, args, done);
+ (*charsRead) = specifier.input - input;
+
+ if (!specifier.output)
+ specifier.output = nullstring;
+
+ ret = strlenW(specifier.output);
+
+ if (ret >= bufsize)
+ memcpy(output, specifier.output, bufsize * sizeof(MSVCRT_wchar_t));
+ else
+ memcpy(output, specifier.output, ret * sizeof(MSVCRT_wchar_t));
+
+ if (specifier.HeapAlloced)
+ HeapFree(GetProcessHeap(),0,specifier.output);
+ return ret;
+}
+
+
+/*********************************************************************
+ * _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 charsPrinted = 0;
+ int charsRead = 0;
+ int copied = 0;
+ int outputBufferRemaining = count;
+ MSVCRT_wchar_t *percentLocation;
+ MSVCRT_wchar_t *input = (MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),
+ 0, (1 + strlen(format)) * sizeof(MSVCRT_wchar_t));
+ MSVCRT_wchar_t *in = input;
+ MSVCRT_wchar_t *output = (MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),
+ 0, count * sizeof(MSVCRT_wchar_t));
+ MSVCRT_wchar_t *out = output;
+ MultiByteToWideChar(CP_ACP, 0, format, -1, input, strlen(format) + 1);
+ while ((outputBufferRemaining) && (*input))
+ {
+ percentLocation = strchrW(input,'%');
+ if (!percentLocation || ((percentLocation - input) > outputBufferRemaining) )
+ {
+ strncpyW(output, input, outputBufferRemaining);
+ copied = strlenW(input);
+ if (copied > outputBufferRemaining)
+ {
+ *(output + outputBufferRemaining) = 0;
+ WideCharToMultiByte(CP_ACP, 0,out, -1, buffer, count + 1, NULL, NULL);
+ HeapFree(GetProcessHeap(),0,out);
+ HeapFree(GetProcessHeap(),0,in);
+ return -1;
+ }
+ input += copied;
+ }
+ else
+ {
+ copied = percentLocation - input;
+ strncpyW(output, input, copied);
+ input = percentLocation;
+ output += copied;
+ charsPrinted += copied;
+ outputBufferRemaining -= copied;
+ copied = formatw(output, input, outputBufferRemaining, &argptr, &charsRead, charsPrinted, 0);
+ if (copied > outputBufferRemaining)
+ {
+ *(output + outputBufferRemaining)=0;
+ WideCharToMultiByte(CP_ACP, 0, out, -1, buffer, count + 1, NULL, NULL);
+ HeapFree(GetProcessHeap(),0,out);
+ HeapFree(GetProcessHeap(),0,in);
+ return -1;
+ }
+ input += charsRead;
+ }
+ output += copied;
+ charsPrinted += copied;
+ outputBufferRemaining -= copied;
+ }
+ *output = 0;
+ WideCharToMultiByte(CP_ACP, 0, out, -1, buffer, count + 1, NULL, NULL);
+ HeapFree(GetProcessHeap(), 0, out);
+ HeapFree(GetProcessHeap(), 0, in);
+ return charsPrinted;
+}
+
+/*********************************************************************
+ * _vsnwprintf (MSVCRT.@)
+ */
+int _vsnwprintf(MSVCRT_wchar_t *output, size_t outputBufferRemaining, const MSVCRT_wchar_t *format, va_list argptr)
+{
+ int charsPrinted = 0;
+ int charsRead = 0;
+ int copied = 0;
+ const MSVCRT_wchar_t *input = format;
+ MSVCRT_wchar_t *percentLocation;
+ while ((outputBufferRemaining) && (*input))
+ {
+ percentLocation = strchrW(input,'%');
+ if (!percentLocation || ((percentLocation - input) > outputBufferRemaining) )
+ {
+ strncpyW(output, input, outputBufferRemaining);
+ copied = strlenW(input);
+ if (copied > outputBufferRemaining)
+ {
+ *(output + outputBufferRemaining) = 0;
+ return -1;
+ }
+ input += copied;
+ }
+ else
+ {
+ copied = percentLocation - input;
+ strncpyW(output, input, copied);
+ input = percentLocation;
+ output += copied;
+ charsPrinted += copied;
+ outputBufferRemaining -= copied;
+ copied = formatw(output, input, outputBufferRemaining, &argptr, &charsRead, charsPrinted, WIDE_PRINTF);
+ if (copied > outputBufferRemaining)
+ {
+ *(output + outputBufferRemaining) = 0;
+ return -1;
+ }
+ input += charsRead;
+ }
+ output += copied;
+ charsPrinted += copied;
+ outputBufferRemaining -= copied;
+ }
+ *output = 0;
+ return charsPrinted;
+}
+
+
+/*********************************************************************
+ * vfprintf (MSVCRT.@)
+ */
+int MSVCRT_vfprintf(MSVCRT_FILE* file, const char *format, va_list valist)
+{
+ char buf[2048];
+ char *mem = buf;
+ int written;
+ int resize = sizeof(buf) / sizeof(char);
+ int retval;
+ while ((written = _vsnprintf(mem, resize, format, valist)) == -1)
+ {
+ resize *= 2;
+ if (mem != buf)
+ HeapFree(GetProcessHeap(),0,mem);
+ if (!(mem = (char *)HeapAlloc(GetProcessHeap(),0,resize * sizeof(char))))
+ return (-1);
+ }
+ retval = MSVCRT_fwrite(mem, sizeof(*mem), written, file);
+ if (mem != buf)
+ HeapFree(GetProcessHeap(),0,mem);
+ return retval;
+}
+
+/*********************************************************************
+ * vfwprintf (MSVCRT.@)
+ */
+int MSVCRT_vfwprintf(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, va_list valist)
+{
+ MSVCRT_wchar_t buf[2048];
+ MSVCRT_wchar_t *mem = buf;
+ int written;
+ int resize = sizeof(buf) / sizeof(MSVCRT_wchar_t);
+ int retval;
+ while ((written = _vsnwprintf(mem, resize, format, valist)) == -1)
+ {
+ resize *= 2;
+ if (mem != buf)
+ HeapFree(GetProcessHeap(),0,mem);
+ if (!(mem = (MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),0,resize * sizeof(MSVCRT_wchar_t))))
+ return (-1);
+ }
+ retval = MSVCRT_fwrite(mem, sizeof(*mem), written, file);
+ if (mem != buf)
+ HeapFree(GetProcessHeap(),0,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];
+ char *mem = buf;
+ int written;
+ int resize = sizeof(buf) / sizeof(char);
+ while ((written = _vsnprintf(mem, resize, format, args)) == -1)
+ {
+ resize *= 2;
+ if (mem != buf)
+ HeapFree(GetProcessHeap(),0,mem);
+ if (!(mem = (char *)HeapAlloc(GetProcessHeap(),0,resize * sizeof(char))))
+ return (-1);
+ }
+ strcpy(str, mem);
+ if (mem != buf)
+ HeapFree(GetProcessHeap(),0,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];
+ MSVCRT_wchar_t *mem = buf;
+ int written;
+ int resize = sizeof(buf) / sizeof(MSVCRT_wchar_t);
+ while ((written = _vsnwprintf(mem, resize, format, args)) == -1)
+ {
+ resize *= 2;
+ if (mem != buf)
+ HeapFree(GetProcessHeap(),0,mem);
+ if (!(mem = (MSVCRT_wchar_t *)HeapAlloc(GetProcessHeap(),0,resize * sizeof(MSVCRT_wchar_t))))
+ return (-1);
+ }
+ strcpyW(str, mem);
+ if (mem != buf)
+ HeapFree(GetProcessHeap(),0,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;
+}
