From bf49c46b2381374bcd14315508ff5e296e9fb19a Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Fri, 5 Nov 2010 22:21:36 +0000 Subject: [PATCH] [CRT] New implementation of all printf functions. It's stream based (like MS one is) rather than buffer based (like our old is). Floating point is not 100% finished, but current implementation is good enough to boot. It can be enabled by a config switch. svn path=/trunk/; revision=49499 --- reactos/boot/freeldr/freeldr/debug.c | 13 + reactos/config.template.rbuild | 5 + reactos/lib/rtl/rtl.rbuild | 5 + reactos/lib/rtl/sprintf.c | 4 + reactos/lib/rtl/swprintf.c | 2 + reactos/lib/sdk/crt/conio/cprintf.c | 3 + reactos/lib/sdk/crt/crt.rbuild | 29 ++ reactos/lib/sdk/crt/libcntpr.rbuild | 27 + reactos/lib/sdk/crt/mbstring/mbstrlen.c | 5 + reactos/lib/sdk/crt/printf/_cprintf.c | 25 + reactos/lib/sdk/crt/printf/_snprintf.c | 39 ++ reactos/lib/sdk/crt/printf/_snwprintf.c | 42 ++ reactos/lib/sdk/crt/printf/_vcprintf.c | 18 + reactos/lib/sdk/crt/printf/_vsnprintf.c | 37 ++ reactos/lib/sdk/crt/printf/_vsnwprintf.c | 37 ++ reactos/lib/sdk/crt/printf/fprintf.c | 24 + reactos/lib/sdk/crt/printf/fwprintf.c | 23 + reactos/lib/sdk/crt/printf/printf.c | 27 + reactos/lib/sdk/crt/printf/sprintf.c | 38 ++ reactos/lib/sdk/crt/printf/streamout.c | 629 +++++++++++++++++++++++ reactos/lib/sdk/crt/printf/swprintf.c | 39 ++ reactos/lib/sdk/crt/printf/vfprintf.c | 29 ++ reactos/lib/sdk/crt/printf/vfwprintf.c | 20 + reactos/lib/sdk/crt/printf/vprintf.c | 19 + reactos/lib/sdk/crt/printf/vsprintf.c | 38 ++ reactos/lib/sdk/crt/printf/vswprintf.c | 18 + reactos/lib/sdk/crt/printf/vwprintf.c | 19 + reactos/lib/sdk/crt/printf/wprintf.c | 25 + reactos/lib/sdk/crt/printf/wstreamout.c | 12 + reactos/lib/sdk/crt/stdio/file.c | 4 + reactos/lib/sdk/crt/stdio/lnx_sprintf.c | 3 +- reactos/lib/sdk/crt/stdio/lock_file.c | 15 + reactos/lib/sdk/crt/string/wcs.c | 2 + reactos/modules/directory.rbuild | 7 + 34 files changed, 1281 insertions(+), 1 deletion(-) create mode 100644 reactos/lib/sdk/crt/printf/_cprintf.c create mode 100644 reactos/lib/sdk/crt/printf/_snprintf.c create mode 100644 reactos/lib/sdk/crt/printf/_snwprintf.c create mode 100644 reactos/lib/sdk/crt/printf/_vcprintf.c create mode 100644 reactos/lib/sdk/crt/printf/_vsnprintf.c create mode 100644 reactos/lib/sdk/crt/printf/_vsnwprintf.c create mode 100644 reactos/lib/sdk/crt/printf/fprintf.c create mode 100644 reactos/lib/sdk/crt/printf/fwprintf.c create mode 100644 reactos/lib/sdk/crt/printf/printf.c create mode 100644 reactos/lib/sdk/crt/printf/sprintf.c create mode 100644 reactos/lib/sdk/crt/printf/streamout.c create mode 100644 reactos/lib/sdk/crt/printf/swprintf.c create mode 100644 reactos/lib/sdk/crt/printf/vfprintf.c create mode 100644 reactos/lib/sdk/crt/printf/vfwprintf.c create mode 100644 reactos/lib/sdk/crt/printf/vprintf.c create mode 100644 reactos/lib/sdk/crt/printf/vsprintf.c create mode 100644 reactos/lib/sdk/crt/printf/vswprintf.c create mode 100644 reactos/lib/sdk/crt/printf/vwprintf.c create mode 100644 reactos/lib/sdk/crt/printf/wprintf.c create mode 100644 reactos/lib/sdk/crt/printf/wstreamout.c create mode 100644 reactos/lib/sdk/crt/stdio/lock_file.c diff --git a/reactos/boot/freeldr/freeldr/debug.c b/reactos/boot/freeldr/freeldr/debug.c index 4ab90966192..95a5a4f1b71 100644 --- a/reactos/boot/freeldr/freeldr/debug.c +++ b/reactos/boot/freeldr/freeldr/debug.c @@ -66,6 +66,19 @@ ULONG BaudRate = 115200; BOOLEAN DebugStartOfLine = TRUE; +// We need to emulate these, because the original ones don't work in freeldr +int __cdecl wctomb(char *mbchar, wchar_t wchar) +{ + *mbchar = wchar; + return 1; +} + +int __cdecl mbtowc (wchar_t *wchar, const char *mbchar, size_t count) +{ + *wchar = *mbchar; + return 1; +} + VOID DebugInit(VOID) { if (DebugPort & RS232) diff --git a/reactos/config.template.rbuild b/reactos/config.template.rbuild index 5e20dd5fd55..225850e45da 100644 --- a/reactos/config.template.rbuild +++ b/reactos/config.template.rbuild @@ -104,4 +104,9 @@ --> + + + diff --git a/reactos/lib/rtl/rtl.rbuild b/reactos/lib/rtl/rtl.rbuild index eac455e626d..0bce2979a22 100644 --- a/reactos/lib/rtl/rtl.rbuild +++ b/reactos/lib/rtl/rtl.rbuild @@ -6,6 +6,11 @@ . + + + + + debug_asm.S diff --git a/reactos/lib/rtl/sprintf.c b/reactos/lib/rtl/sprintf.c index 52f46f8a3d3..51461147d0a 100644 --- a/reactos/lib/rtl/sprintf.c +++ b/reactos/lib/rtl/sprintf.c @@ -1,3 +1,5 @@ + +#ifndef USE_NEW_SPRINTF /* * PROGRAMMERS: David Welch * Eric Kohl @@ -741,3 +743,5 @@ int __cdecl vsprintf(char *buf, const char *fmt, va_list args) } /* EOF */ +#endif + diff --git a/reactos/lib/rtl/swprintf.c b/reactos/lib/rtl/swprintf.c index 64d7d65397a..20d975ff757 100644 --- a/reactos/lib/rtl/swprintf.c +++ b/reactos/lib/rtl/swprintf.c @@ -1,3 +1,4 @@ +#ifndef USE_NEW_SPRINTF /* * PROGRAMMERS: David Welch * Eric Kohl @@ -740,3 +741,4 @@ int __cdecl vswprintf(wchar_t *buf, const wchar_t *fmt, va_list args) } /* EOF */ +#endif diff --git a/reactos/lib/sdk/crt/conio/cprintf.c b/reactos/lib/sdk/crt/conio/cprintf.c index 5c6295c15a1..100e6ae63cf 100644 --- a/reactos/lib/sdk/crt/conio/cprintf.c +++ b/reactos/lib/sdk/crt/conio/cprintf.c @@ -5,6 +5,7 @@ * PURPOSE: C Runtime * PROGRAMMER: Magnus Olsen (Imported from wine cvs 2006-05-23) */ +#ifndef USE_NEW_SPRINTF #include @@ -38,3 +39,5 @@ _cprintf(const char *fmt, ...) free (mem); return retval; } + +#endif diff --git a/reactos/lib/sdk/crt/crt.rbuild b/reactos/lib/sdk/crt/crt.rbuild index 9217450014d..c6f60a7d997 100644 --- a/reactos/lib/sdk/crt/crt.rbuild +++ b/reactos/lib/sdk/crt/crt.rbuild @@ -26,6 +26,33 @@ + + + + + _cprintf.c + _snprintf.c + _snwprintf.c + _vcprintf.c + _vsnprintf.c + _vsnwprintf.c + fprintf.c + fwprintf.c + printf.c + sprintf.c + streamout.c + swprintf.c + vfprintf.c + vfwprintf.c + vprintf.c + vsprintf.c + vswprintf.c + vwprintf.c + wprintf.c + wstreamout.c + + + cgets.c cprintf.c @@ -123,6 +150,7 @@ ldiv.c logf.c modf.c + powf.c rand.c s_modf.c sinf.c @@ -343,6 +371,7 @@ wpopen.c wstat.c wstat64.c + lock_file.c _exit.c diff --git a/reactos/lib/sdk/crt/libcntpr.rbuild b/reactos/lib/sdk/crt/libcntpr.rbuild index e27ac1d265c..5bb60df8b9c 100644 --- a/reactos/lib/sdk/crt/libcntpr.rbuild +++ b/reactos/lib/sdk/crt/libcntpr.rbuild @@ -9,6 +9,25 @@ + + + + + _snprintf.c + _snwprintf.c + _vcprintf.c + _vsnprintf.c + _vsnwprintf.c + sprintf.c + streamout.c + swprintf.c + vprintf.c + vsprintf.c + vswprintf.c + wstreamout.c + + + "extern __attribute__ ((dllexport))" @@ -33,6 +52,9 @@ + + isnan.c + @@ -54,6 +76,7 @@ floor_asm.s ftol_asm.s log_asm.s + log10_asm.s pow_asm.s sin_asm.s sqrt_asm.s @@ -207,6 +230,10 @@ wtol.c + + mbstrlen.c + + wcsicmp.c wcslwr.c diff --git a/reactos/lib/sdk/crt/mbstring/mbstrlen.c b/reactos/lib/sdk/crt/mbstring/mbstrlen.c index c600bd1029b..9b324668458 100644 --- a/reactos/lib/sdk/crt/mbstring/mbstrlen.c +++ b/reactos/lib/sdk/crt/mbstring/mbstrlen.c @@ -12,7 +12,12 @@ #include #include +#ifdef _LIBCNT_ +unsigned short *NlsLeadByteInfo; +#define isleadbyte(c) NlsLeadByteInfo[c] +#else int isleadbyte(int byte); +#endif /* * @implemented diff --git a/reactos/lib/sdk/crt/printf/_cprintf.c b/reactos/lib/sdk/crt/printf/_cprintf.c new file mode 100644 index 00000000000..4ce0494bbd6 --- /dev/null +++ b/reactos/lib/sdk/crt/printf/_cprintf.c @@ -0,0 +1,25 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/_vcprintf.c + * PURPOSE: Implementation of _vcprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include + +int _vcprintf(const char* format, va_list argptr); + +int +_cdecl +_cprintf(const char * format, ...) +{ + va_list argptr; + int result; + + va_start(argptr, format); + result = _vcprintf(format, argptr); + va_end(argptr); + return result; +} + diff --git a/reactos/lib/sdk/crt/printf/_snprintf.c b/reactos/lib/sdk/crt/printf/_snprintf.c new file mode 100644 index 00000000000..b8bd5370c56 --- /dev/null +++ b/reactos/lib/sdk/crt/printf/_snprintf.c @@ -0,0 +1,39 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/_snprintf.c + * PURPOSE: Implementation of _snprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include +#include + +int _cdecl streamout(FILE *stream, const char *format, va_list argptr); + +int +_cdecl +_snprintf(char *buffer, size_t count, const char *format, ...) +{ + va_list argptr; + int result; + FILE stream; + + stream._base = buffer; + stream._ptr = stream._base; + stream._charbuf = 0; + stream._bufsiz = (unsigned long)-1; + stream._cnt = stream._bufsiz; + stream._flag = 0; + stream._tmpfname = 0; + + va_start(argptr, format); + result = streamout(&stream, format, argptr); + va_end(argptr); + + *stream._ptr = '\0'; + return result; +} + + diff --git a/reactos/lib/sdk/crt/printf/_snwprintf.c b/reactos/lib/sdk/crt/printf/_snwprintf.c new file mode 100644 index 00000000000..5a4a951d2eb --- /dev/null +++ b/reactos/lib/sdk/crt/printf/_snwprintf.c @@ -0,0 +1,42 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/_snwprintf.c + * PURPOSE: Implementation of _snwprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +int _cdecl wstreamout(FILE *stream, const wchar_t *format, va_list argptr); + +int +__cdecl +_snwprintf( + wchar_t *buffer, + size_t count, + const wchar_t *format, + ...) +{ + va_list argptr; + int result; + FILE stream; + + stream._base = (char*)buffer; + stream._ptr = stream._base; + stream._bufsiz = count * sizeof(wchar_t); + stream._cnt = stream._bufsiz; + stream._flag = _IOSTRG | _IOWRT; + stream._tmpfname = 0; + stream._charbuf = 0; + + va_start(argptr, format); + result = wstreamout(&stream, format, argptr); + va_end(argptr); + + /* Only zero terminate if there is enough space left */ + if (stream._cnt >= sizeof(wchar_t)) *(wchar_t*)stream._ptr = L'\0'; + + return result; +} diff --git a/reactos/lib/sdk/crt/printf/_vcprintf.c b/reactos/lib/sdk/crt/printf/_vcprintf.c new file mode 100644 index 00000000000..345a4421e91 --- /dev/null +++ b/reactos/lib/sdk/crt/printf/_vcprintf.c @@ -0,0 +1,18 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/_vcprintf.c + * PURPOSE: Implementation of _vcprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include + +int +_cdecl +_vcprintf(const char* format, va_list va) +{ + return 0; +} + + diff --git a/reactos/lib/sdk/crt/printf/_vsnprintf.c b/reactos/lib/sdk/crt/printf/_vsnprintf.c new file mode 100644 index 00000000000..c94ffc60a8b --- /dev/null +++ b/reactos/lib/sdk/crt/printf/_vsnprintf.c @@ -0,0 +1,37 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/_vsnprintf.c + * PURPOSE: Implementation of _vsnprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +int _cdecl streamout(FILE *stream, const char *format, va_list argptr); + +int +__cdecl +_vsnprintf( + char *buffer, + size_t count, + const char *format, + va_list argptr) +{ + int result; + FILE stream; + + stream._base = buffer; + stream._ptr = stream._base; + stream._bufsiz = count; + stream._cnt = stream._bufsiz; + stream._flag = _IOSTRG | _IOWRT; + stream._tmpfname = 0; + stream._charbuf = 0; + + result = streamout(&stream, format, argptr); + *stream._ptr = '\0'; + + return result; +} diff --git a/reactos/lib/sdk/crt/printf/_vsnwprintf.c b/reactos/lib/sdk/crt/printf/_vsnwprintf.c new file mode 100644 index 00000000000..77e12303136 --- /dev/null +++ b/reactos/lib/sdk/crt/printf/_vsnwprintf.c @@ -0,0 +1,37 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/_vsnwprintf.c + * PURPOSE: Implementation of _vsnwprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +int _cdecl wstreamout(FILE *stream, const wchar_t *format, va_list argptr); + +int +__cdecl +_vsnwprintf( + wchar_t *buffer, + size_t count, + const wchar_t *format, + va_list argptr) +{ + int result; + FILE stream; + + stream._base = (char*)buffer; + stream._ptr = stream._base; + stream._bufsiz = count * sizeof(wchar_t); + stream._cnt = stream._bufsiz; + stream._flag = _IOSTRG | _IOWRT; + stream._tmpfname = 0; + stream._charbuf = 0; + + result = wstreamout(&stream, format, argptr); + *(wchar_t*)stream._ptr = L'\0'; + + return result; +} diff --git a/reactos/lib/sdk/crt/printf/fprintf.c b/reactos/lib/sdk/crt/printf/fprintf.c new file mode 100644 index 00000000000..9d0b9540995 --- /dev/null +++ b/reactos/lib/sdk/crt/printf/fprintf.c @@ -0,0 +1,24 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/fprintf.c + * PURPOSE: Implementation of fprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +int +_cdecl +fprintf(FILE *stream, const char *format, ...) +{ + va_list argptr; + int result; + + va_start(argptr, format); + result = vfprintf(stream, format, argptr); + va_end(argptr); + return result; +} + diff --git a/reactos/lib/sdk/crt/printf/fwprintf.c b/reactos/lib/sdk/crt/printf/fwprintf.c new file mode 100644 index 00000000000..f4b32b13488 --- /dev/null +++ b/reactos/lib/sdk/crt/printf/fwprintf.c @@ -0,0 +1,23 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/fwprintf.c + * PURPOSE: Implementation of fwprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +int +__cdecl +fwprintf(FILE* file, const wchar_t *format, ...) +{ + va_list argptr; + int result; + + va_start(argptr, format); + result = vfwprintf(file, format, argptr); + va_end(argptr); + return result; +} diff --git a/reactos/lib/sdk/crt/printf/printf.c b/reactos/lib/sdk/crt/printf/printf.c new file mode 100644 index 00000000000..a9f83f1046c --- /dev/null +++ b/reactos/lib/sdk/crt/printf/printf.c @@ -0,0 +1,27 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/printf.c + * PURPOSE: Implementation of printf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include +#include + +int _cdecl streamout(FILE *stream, const char *format, va_list argptr); + +int +_cdecl +printf(const char *format, ...) +{ + va_list argptr; + int result; + + va_start(argptr, format); + result = streamout(stdout, format, argptr); + va_end(argptr); + return result; +} + diff --git a/reactos/lib/sdk/crt/printf/sprintf.c b/reactos/lib/sdk/crt/printf/sprintf.c new file mode 100644 index 00000000000..33c60926c72 --- /dev/null +++ b/reactos/lib/sdk/crt/printf/sprintf.c @@ -0,0 +1,38 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/sprintf.c + * PURPOSE: Implementation of sprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include +#include + +int _cdecl streamout(FILE *stream, const char *format, va_list argptr); + +int +_cdecl +sprintf(char *buffer, const char *format, ...) +{ + va_list argptr; + int result; + FILE stream; + + stream._base = buffer; + stream._ptr = stream._base; + stream._charbuf = 0; + stream._bufsiz = INT_MAX; + stream._cnt = stream._bufsiz; + stream._flag = 0; + stream._tmpfname = 0; + + va_start(argptr, format); + result = streamout(&stream, format, argptr); + va_end(argptr); + + *stream._ptr = '\0'; + return result; +} + diff --git a/reactos/lib/sdk/crt/printf/streamout.c b/reactos/lib/sdk/crt/printf/streamout.c new file mode 100644 index 00000000000..7ac47d43934 --- /dev/null +++ b/reactos/lib/sdk/crt/printf/streamout.c @@ -0,0 +1,629 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/streamout.c + * PURPOSE: Implementation of streamout + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include +#include +#include +#include + +#ifdef _UNICODE +#define streamout wstreamout +#define format_float format_floatw +#endif + +#define MB_CUR_MAX 10 +#define BUFFER_SIZE (32 + 17) + +int mbtowc(wchar_t *wchar, const char *mbchar, size_t count); +int wctomb(char *mbchar, wchar_t wchar); + +typedef struct _STRING +{ + unsigned short Length; + unsigned short MaximumLength; + void *Buffer; +} STRING; + +enum +{ + /* Formatting flags */ + FLAG_ALIGN_LEFT = 0x01, + FLAG_FORCE_SIGN = 0x02, + FLAG_FORCE_SIGNSP = 0x04, + FLAG_PAD_ZERO = 0x08, + FLAG_SPECIAL = 0x10, + + /* Data format flags */ + FLAG_SHORT = 0x100, + FLAG_LONG = 0x200, + FLAG_WIDECHAR = FLAG_LONG, + FLAG_INT64 = 0x400, +#ifdef _WIN64 + FLAG_INTPTR = FLAG_INT64, +#else + FLAG_INTPTR = 0, +#endif + FLAG_LONGDOUBLE = 0x800, +}; + +#define va_arg_f(argptr, flags) \ + (flags & FLAG_INT64) ? va_arg(argptr, __int64) : \ + (flags & FLAG_SHORT) ? (short)va_arg(argptr, int) : \ + va_arg(argptr, int) + +#define va_arg_fu(argptr, flags) \ + (flags & FLAG_INT64) ? va_arg(argptr, unsigned __int64) : \ + (flags & FLAG_SHORT) ? (unsigned short)va_arg(argptr, int) : \ + va_arg(argptr, unsigned int) + +#define va_arg_ffp(argptr, flags) \ + (flags & FLAG_LONGDOUBLE) ? va_arg(argptr, long double) : \ + va_arg(argptr, double) + +#ifdef _LIBCNT_ +# define _flsbuf(chr, stream) 0 +#endif + +#define get_exp(f) floor(f > 0 ? log10(f) : log10(-f)) + +void +#ifdef _LIBCNT +/* Due to restrictions in kernel mode regarding the use of floating point, + we prevent it from being inlined */ +__declspec(noinline) +#endif +format_float( + TCHAR chr, + unsigned int flags, + int precision, + TCHAR **string, + const TCHAR **prefix, + va_list *argptr) +{ + static const TCHAR digits_l[] = _T("0123456789abcdef0x"); + static const TCHAR digits_u[] = _T("0123456789ABCDEF0X"); + static const TCHAR _nan[] = _T("#QNAN"); + static const TCHAR _infinity[] = _T("#INF"); + const TCHAR *digits = digits_l; + int exponent = 0; + long double fpval; + int num_digits, val32, base = 10; + __int64 val64; + + if (precision == -1) precision = 6; + + fpval = va_arg_ffp(*argptr, flags); + exponent = get_exp(fpval); + + switch (chr) + { + case _T('G'): + digits = digits_u; + case _T('g'): + if (exponent < -4 || exponent >= precision) goto case_e; + break; + + case _T('E'): + digits = digits_u; + case _T('e'): + case_e: + fpval /= pow(10., exponent); + val32 = exponent >= 0 ? exponent : -exponent; + + // FIXME: handle length of exponent field: + // http://msdn.microsoft.com/de-de/library/0fatw238%28VS.80%29.aspx + num_digits = 3; + while (num_digits--) + { + *--(*string) = digits[val32 % 10]; + val32 /= 10; + } + + /* Sign for the exponent */ + *--(*string) = exponent > 0 ? _T('+') : _T('-'); + + /* Add 'e' or 'E' separator */ + *--(*string) = digits[0xe]; + break; + + case _T('A'): + digits = digits_u; + case _T('a'): +// base = 16; + // FIXME: TODO + + case _T('f'): + break; + } + + /* CHECKME: Windows seems to handle a max of 17 digits(?) */ + num_digits = precision <= 17 ? precision : 17; + + /* Handle sign */ + if (fpval < 0) + { + fpval = -fpval; + *prefix = _T("-"); + } + else if (flags & FLAG_FORCE_SIGN) + *prefix = _T("+"); + else if (flags & FLAG_FORCE_SIGNSP) + *prefix = _T(" "); + + /* Handle special cases first */ + if (_isnan(fpval)) + { + (*string) -= sizeof(_nan) / sizeof(TCHAR) - 1; + _tcscpy((*string), _nan); + val64 = 1; + } + else if (!_finite(fpval)) + { + (*string) -= sizeof(_infinity) / sizeof(TCHAR) - 1; + _tcscpy((*string), _infinity); + val64 = 1; + } + else + { + val64 = (__int64)fpval; + fpval -= val64; + fpval *= pow(10., precision); + + while (num_digits--) + { + *--(*string) = digits[(__int64)fpval % 10]; + fpval /= 10; + } + } + + *--(*string) = _T('.'); + + /* Gather digits in reverse order */ + do + { + *--(*string) = digits[val64 % base]; + val64 /= base; + } + while (val64); + +} + +static +int +streamout_char(FILE *stream, int chr) +{ + /* Flush the buffer if neccessary */ + if (stream->_cnt < sizeof(TCHAR)) + { + return _flsbuf(chr, stream) != EOF; + } + + *(TCHAR*)stream->_ptr = chr; + stream->_ptr += sizeof(TCHAR); + stream->_cnt -= sizeof(TCHAR); + + return 1; +} + +static +int +streamout_astring(FILE *stream, const char *string, int count) +{ + TCHAR chr; + int written = 0; + + while (count--) + { +#ifdef _UNICODE + int len; + if ((len = mbtowc(&chr, string, MB_CUR_MAX)) < 1) break; + string += len; +#else + chr = *string++; +#endif + if (streamout_char(stream, chr) == 0) return -1; + written++; + } + + return written; +} + +static +int +streamout_wstring(FILE *stream, const wchar_t *string, int count) +{ + wchar_t chr; + int written = 0; + + while (count--) + { +#ifndef _UNICODE + char mbchar[MB_CUR_MAX], *ptr = mbchar; + int mblen; + + mblen = wctomb(mbchar, *string++); + if (mblen <= 0) return written; + + while (chr = *ptr++, mblen--) +#else + chr = *string++; +#endif + { + if (streamout_char(stream, chr) == 0) return -1; + written++; + } + } + + return written; +} + +#ifdef _UNICODE +#define streamout_string streamout_wstring +#else +#define streamout_string streamout_astring +#endif + + +int +_cdecl +streamout(FILE *stream, const TCHAR *format, va_list argptr) +{ + static const TCHAR digits_l[] = _T("0123456789abcdef0x"); + static const TCHAR digits_u[] = _T("0123456789ABCDEF0X"); + static const char *_nullstring = "(null)"; + TCHAR buffer[BUFFER_SIZE + 1]; + TCHAR chr, *string; + STRING *nt_string; + const TCHAR *digits, *prefix; + int base, len, prefixlen, fieldwidth, precision, padding; + int written = 1, written_all = 0; + unsigned int flags; + __int64 val64; + + buffer[BUFFER_SIZE] = '\0'; + + while (written >= 0) + { + chr = *format++; + + /* Check for end of format string */ + if (chr == _T('\0')) break; + + /* Check for 'normal' character */ + if (chr != _T('%')) + { + /* Write the character to the stream */ + if ((written = streamout_char(stream, chr)) == -1) return -1; + written_all += written; + /* Continue with next char */ + continue; + } + + /* Handle flags */ + flags = 0; + while (1) + { + chr = *format++; + if (chr == _T('-')) flags |= FLAG_ALIGN_LEFT; + else if (chr == _T('+')) flags |= FLAG_FORCE_SIGN; + else if (chr == _T(' ')) flags |= FLAG_FORCE_SIGNSP; + else if (chr == _T('0')) flags |= FLAG_PAD_ZERO; + else if (chr == _T('#')) flags |= FLAG_SPECIAL; + else break; + } + + /* Handle field width modifier */ + if (chr == _T('*')) + { + fieldwidth = va_arg(argptr, int); + chr = *format++; + } + else + { + fieldwidth = 0; + while (chr >= _T('0') && chr <= _T('9')) + { + fieldwidth = fieldwidth * 10 + (chr - _T('0')); + chr = *format++; + } + } + + /* Handle precision modifier */ + if (chr == '.') + { + chr = *format++; + + if (chr == _T('*')) + { + precision = va_arg(argptr, int); + chr = *format++; + } + else + { + precision = 0; + while (chr >= _T('0') && chr <= _T('9')) + { + precision = precision * 10 + (chr - _T('0')); + chr = *format++; + } + } + } + else precision = -1; + + /* Handle argument size prefix */ + while (1) + { + if (chr == _T('h')) flags |= FLAG_SHORT; + else if (chr == _T('w')) flags |= FLAG_WIDECHAR; + else if (chr == _T('L')) flags |= 0; // FIXME: long double + else if (chr == _T('l')) + { + flags |= FLAG_LONG; +#if SUPPORT_LL + if (format[0] == _T('l')) + { + format++; + flags |= FLAG_INT64; + } +#endif + } + else if (chr == _T('I')) + { + if (format[0] == _T('3') && format[1] == _T('2')) + { + format += 2; + } + else if (format[0] == _T('6') && format[1] == _T('4')) + { + format += 2; + flags |= FLAG_INT64; + } + else if (format[0] == _T('x') || format[0] == _T('X') || + format[0] == _T('d') || format[0] == _T('i') || + format[0] == _T('u') || format[0] == _T('o')) + { + flags |= FLAG_INTPTR; + } + else break; + } + else break; + chr = *format++; + } + + /* Handle the format specifier */ + digits = digits_l; + string = &buffer[BUFFER_SIZE]; + base = 10; + prefix = 0; + switch (chr) + { + case _T('n'): + if (flags & FLAG_INT64) + *va_arg(argptr, __int64*) = written_all; + else if (flags & FLAG_SHORT) + *va_arg(argptr, short*) = written_all; + else + *va_arg(argptr, int*) = written_all; + continue; + + case _T('C'): +#ifndef _UNICODE + if (!(flags & FLAG_SHORT)) flags |= FLAG_WIDECHAR; +#endif + goto case_char; + + case _T('c'): +#ifdef _UNICODE + if (!(flags & FLAG_SHORT)) flags |= FLAG_WIDECHAR; +#endif + case_char: + string = buffer; + len = 1; + if (flags & FLAG_WIDECHAR) + { + ((wchar_t*)string)[0] = va_arg(argptr, int); + ((wchar_t*)string)[1] = _T('\0'); + } + else + { + ((char*)string)[0] = va_arg(argptr, int); + ((char*)string)[1] = _T('\0'); + } + break; + + case _T('Z'): + nt_string = va_arg(argptr, void*); + if (nt_string && (string = nt_string->Buffer)) + { + len = nt_string->Length; + if (flags & FLAG_WIDECHAR) len /= sizeof(wchar_t); + break; + } + string = 0; + goto case_string; + + case _T('S'): + string = va_arg(argptr, void*); +#ifndef _UNICODE + if (!(flags & FLAG_SHORT)) flags |= FLAG_WIDECHAR; +#endif + goto case_string; + + case _T('s'): + string = va_arg(argptr, void*); +#ifdef _UNICODE + if (!(flags & FLAG_SHORT)) flags |= FLAG_WIDECHAR; +#endif + + case_string: + if (!string) + { + string = (TCHAR*)_nullstring; + flags &= ~FLAG_WIDECHAR; + } + + if (flags & FLAG_WIDECHAR) + len = wcslen((wchar_t*)string); + else + len = strlen((char*)string); + if (precision >= 0 && len > precision) len = precision; + break; + + case _T('G'): + case _T('E'): + case _T('A'): + case _T('g'): + case _T('e'): + case _T('a'): + case _T('f'): +#ifdef _UNICODE + flags |= FLAG_WIDECHAR; +#else + flags &= ~FLAG_WIDECHAR; +#endif + /* Use external function, one for kernel one for user mode */ + format_float(chr, flags, precision, &string, &prefix, &argptr); + len = _tcslen(string); + break; + + case _T('d'): + case _T('i'): + val64 = va_arg_f(argptr, flags); + + if (val64 < 0) + { + val64 = -val64; + prefix = _T("-"); + } + else if (flags & FLAG_FORCE_SIGN) + prefix = _T("+"); + else if (flags & FLAG_FORCE_SIGNSP) + prefix = _T(" "); + + goto case_number; + + case _T('o'): + base = 8; + if (flags & FLAG_SPECIAL) prefix = _T("0"); + /* Fall through */ + + case _T('u'): + val64 = (unsigned __int64)va_arg_fu(argptr, flags); + goto case_number; + + case _T('p'): + precision = 2 * sizeof(void*); + flags &= ~FLAG_PAD_ZERO; + flags |= FLAG_INTPTR; + /* Fall through */ + + case _T('X'): + digits = digits_u; + /* Fall through */ + + case _T('x'): + val64 = (unsigned __int64)va_arg_fu(argptr, flags); + base = 16; + if (flags & FLAG_SPECIAL) + { + prefix = &digits[16]; + } + + case_number: +#ifdef _UNICODE + flags |= FLAG_WIDECHAR; +#else + flags &= ~FLAG_WIDECHAR; +#endif + /* Gather digits in reverse order */ + do + { + *--string = digits[val64 % base]; + val64 /= base; + precision--; + } + while (val64); + + while (precision-- > 0) *--string = '0'; + len = _tcslen(string); + break; + + default: + /* Treat anything else as a new character */ + format--; + continue; + } + + /* Calculate padding */ + prefixlen = prefix ? _tcslen(prefix) : 0; + padding = fieldwidth - len - prefixlen; + + /* Optional left space padding */ + if ((flags & (FLAG_ALIGN_LEFT | FLAG_PAD_ZERO)) == 0) + { + while (padding-- > 0) + { + if ((written = streamout_char(stream, _T(' '))) == -1) return -2; + written_all += written; + } + } + + /* Optional prefix */ + if (prefix) + { + written = streamout_string(stream, prefix, prefixlen); + if (written == -1) return -3; + written_all += written; + } + + /* Optional left '0' padding */ + if ((flags & (FLAG_ALIGN_LEFT | FLAG_PAD_ZERO)) == FLAG_PAD_ZERO) + { + while (padding-- > 0) + { + if ((written = streamout_char(stream, _T('0'))) == -1) return -4; + written_all += written; + } + } + + /* Output the string */ + if (flags & FLAG_WIDECHAR) + written = streamout_wstring(stream, (wchar_t*)string, len); + else + written = streamout_astring(stream, (char*)string, len); + if (written == -1) return -5; + written_all += written; + +#if 0 && SUPPORT_FLOAT + /* Optional right '0' padding */ + while (precision-- > 0) + { + if ((written = streamout_char(stream, _T('0'))) == -1) return -6; + written_all += written; + len++; + } +#endif + + /* Optional right padding */ + if (flags & FLAG_ALIGN_LEFT) + { + while (padding-- > 0) + { + if ((written = streamout_char(stream, _T(' '))) == -1) return -7; + written_all += written; + } + } + + } + + if (written == -1) return -8; + + return written_all; +} + diff --git a/reactos/lib/sdk/crt/printf/swprintf.c b/reactos/lib/sdk/crt/printf/swprintf.c new file mode 100644 index 00000000000..115c1e6da56 --- /dev/null +++ b/reactos/lib/sdk/crt/printf/swprintf.c @@ -0,0 +1,39 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/swprintf.c + * PURPOSE: Implementation of swprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include +#include + +int _cdecl wstreamout(FILE *stream, const wchar_t *format, va_list argptr); + +int +_cdecl +swprintf(wchar_t *buffer, const wchar_t *format, ...) +{ + va_list argptr; + int result; + FILE stream; + + stream._base = (char*)buffer; + stream._ptr = stream._base; + stream._charbuf = 0; + stream._bufsiz = INT_MAX; + stream._cnt = stream._bufsiz; + stream._flag = 0; + stream._tmpfname = 0; + + va_start(argptr, format); + result = wstreamout(&stream, format, argptr); + va_end(argptr); + + *(wchar_t*)stream._ptr = '\0'; + return result; +} + + diff --git a/reactos/lib/sdk/crt/printf/vfprintf.c b/reactos/lib/sdk/crt/printf/vfprintf.c new file mode 100644 index 00000000000..5a28be59dac --- /dev/null +++ b/reactos/lib/sdk/crt/printf/vfprintf.c @@ -0,0 +1,29 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/vfprintf.c + * PURPOSE: Implementation of vfprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +void _cdecl _lock_file(FILE* file); +void _cdecl _unlock_file(FILE* file); +int _cdecl streamout(FILE *stream, const char *format, va_list argptr); + +int +_cdecl +vfprintf(FILE *stream, const char *format, va_list argptr) +{ + int result; + + _lock_file(stream); + + result = streamout(stream, format, argptr); + + _unlock_file(stream); + + return result; +} diff --git a/reactos/lib/sdk/crt/printf/vfwprintf.c b/reactos/lib/sdk/crt/printf/vfwprintf.c new file mode 100644 index 00000000000..fef618845c2 --- /dev/null +++ b/reactos/lib/sdk/crt/printf/vfwprintf.c @@ -0,0 +1,20 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/vfwprintf.c + * PURPOSE: Implementation of vfwprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +int _cdecl wstreamout(FILE *stream, const wchar_t *format, va_list argptr); + +int +__cdecl +vfwprintf(FILE* file, const wchar_t *format, va_list argptr) +{ + return wstreamout(file, format, argptr); +} + diff --git a/reactos/lib/sdk/crt/printf/vprintf.c b/reactos/lib/sdk/crt/printf/vprintf.c new file mode 100644 index 00000000000..e126c8ddf8f --- /dev/null +++ b/reactos/lib/sdk/crt/printf/vprintf.c @@ -0,0 +1,19 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/vprintf.c + * PURPOSE: Implementation of vprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +int _cdecl streamout(FILE *stream, const char *format, va_list argptr); + +int +__cdecl +vprintf(const char *format, va_list argptr) +{ + return streamout(stdout, format, argptr); +} diff --git a/reactos/lib/sdk/crt/printf/vsprintf.c b/reactos/lib/sdk/crt/printf/vsprintf.c new file mode 100644 index 00000000000..1af97761c5c --- /dev/null +++ b/reactos/lib/sdk/crt/printf/vsprintf.c @@ -0,0 +1,38 @@ +#include "myfunc.h" +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/vsprintf.c + * PURPOSE: Implementation of vsprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include +#include + +int _cdecl streamout(FILE *stream, const char *format, va_list argptr); + +int +__cdecl +vsprintf( + char *buffer, + const char *format, + va_list argptr) +{ + int result; + FILE stream; + + stream._base = buffer; + stream._ptr = stream._base; + stream._charbuf = 0; + stream._bufsiz = INT_MAX; + stream._cnt = stream._bufsiz; + stream._flag = _IOSTRG|_IOWRT|_IOMYBUF; + stream._tmpfname = 0; + + result = streamout(&stream, format, argptr); + *stream._ptr = '\0'; + + return result; +} diff --git a/reactos/lib/sdk/crt/printf/vswprintf.c b/reactos/lib/sdk/crt/printf/vswprintf.c new file mode 100644 index 00000000000..4bba6ba3b2c --- /dev/null +++ b/reactos/lib/sdk/crt/printf/vswprintf.c @@ -0,0 +1,18 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/vswprintf.c + * PURPOSE: Implementation of vswprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include +#include + +int +__cdecl +vswprintf(wchar_t *buffer, const wchar_t *format, va_list argptr) +{ + return _vsnwprintf(buffer, INT_MAX, format, argptr); +} diff --git a/reactos/lib/sdk/crt/printf/vwprintf.c b/reactos/lib/sdk/crt/printf/vwprintf.c new file mode 100644 index 00000000000..b9ee541613d --- /dev/null +++ b/reactos/lib/sdk/crt/printf/vwprintf.c @@ -0,0 +1,19 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/vwprintf.c + * PURPOSE: Implementation of vwprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +int _cdecl wstreamout(FILE *stream, const wchar_t *format, va_list argptr); + +int +__cdecl +vwprintf(const wchar_t *format, va_list argptr) +{ + return wstreamout(stdout, format, argptr); +} diff --git a/reactos/lib/sdk/crt/printf/wprintf.c b/reactos/lib/sdk/crt/printf/wprintf.c new file mode 100644 index 00000000000..1c5e9011132 --- /dev/null +++ b/reactos/lib/sdk/crt/printf/wprintf.c @@ -0,0 +1,25 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/wprintf.c + * PURPOSE: Implementation of wprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +int _cdecl wstreamout(FILE *stream, const wchar_t *format, va_list argptr); + +int +__cdecl +wprintf(const wchar_t *format, ...) +{ + va_list argptr; + int result; + + va_start(argptr, format); + result = wstreamout(stdout, format, argptr); + va_end(argptr); + return result; +} diff --git a/reactos/lib/sdk/crt/printf/wstreamout.c b/reactos/lib/sdk/crt/printf/wstreamout.c new file mode 100644 index 00000000000..bc078737db6 --- /dev/null +++ b/reactos/lib/sdk/crt/printf/wstreamout.c @@ -0,0 +1,12 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/wstreamout.c + * PURPOSE: Implementation of wstreamout + * PROGRAMMER: Timo Kreuzer + */ + +#define _UNICODE +#define UNICODE + +#include "streamout.c" diff --git a/reactos/lib/sdk/crt/stdio/file.c b/reactos/lib/sdk/crt/stdio/file.c index a3540ce28bd..eb20be7cf3f 100644 --- a/reactos/lib/sdk/crt/stdio/file.c +++ b/reactos/lib/sdk/crt/stdio/file.c @@ -2814,6 +2814,7 @@ FILE* CDECL tmpfile(void) return file; } +#ifndef USE_NEW_SPRINTF /********************************************************************* * vfprintf (MSVCRT.@) */ @@ -2947,6 +2948,7 @@ int CDECL printf(const char *format, ...) va_end(valist); return res; } +#endif /********************************************************************* * ungetc (MSVCRT.@) @@ -2984,6 +2986,7 @@ wint_t CDECL ungetwc(wint_t wc, FILE * file) return mwc; } +#ifndef USE_NEW_SPRINTF /********************************************************************* * wprintf (MSVCRT.@) */ @@ -2996,6 +2999,7 @@ int CDECL wprintf(const wchar_t *format, ...) va_end(valist); return res; } +#endif /********************************************************************* * _getmaxstdio (MSVCRT.@) diff --git a/reactos/lib/sdk/crt/stdio/lnx_sprintf.c b/reactos/lib/sdk/crt/stdio/lnx_sprintf.c index f42a4e37662..29d150d68e5 100644 --- a/reactos/lib/sdk/crt/stdio/lnx_sprintf.c +++ b/reactos/lib/sdk/crt/stdio/lnx_sprintf.c @@ -14,7 +14,7 @@ * Lars Wirzenius & Linus Torvalds * Wirzenius wrote this portably, Torvalds fucked it up :-) */ - +#ifndef USE_NEW_SPRINTF #include #include @@ -879,3 +879,4 @@ int __cdecl vsprintf(char *buf, const char *fmt, va_list args) } #endif /* EOF */ +#endif diff --git a/reactos/lib/sdk/crt/stdio/lock_file.c b/reactos/lib/sdk/crt/stdio/lock_file.c new file mode 100644 index 00000000000..28c0265c36e --- /dev/null +++ b/reactos/lib/sdk/crt/stdio/lock_file.c @@ -0,0 +1,15 @@ + +#include + +void +_cdecl +_lock_file(FILE* file) +{ +} + +void +_cdecl +_unlock_file(FILE* file) +{ +} + diff --git a/reactos/lib/sdk/crt/string/wcs.c b/reactos/lib/sdk/crt/string/wcs.c index 00941292911..52446dcb82a 100644 --- a/reactos/lib/sdk/crt/string/wcs.c +++ b/reactos/lib/sdk/crt/string/wcs.c @@ -388,6 +388,7 @@ static inline int pf_output_format_A( pf_output *out, LPCSTR str, return r; } +#ifndef USE_NEW_SPRINTF static int pf_handle_string_format( pf_output *out, const void* str, int len, pf_flags *flags, BOOL capital_letter) { @@ -879,6 +880,7 @@ int CDECL vswprintf( wchar_t* str, const wchar_t* format, va_list args ) return _vsnwprintf( str, INT_MAX, format, args ); } #endif +#endif /********************************************************************* * wcscoll (MSVCRT.@) diff --git a/reactos/modules/directory.rbuild b/reactos/modules/directory.rbuild index 7c33c54cb7c..a4424fd98e1 100644 --- a/reactos/modules/directory.rbuild +++ b/reactos/modules/directory.rbuild @@ -22,4 +22,11 @@ +