// Name: wx/wxcrtvararg.h
// Purpose: Type-safe ANSI and Unicode builds compatible wrappers for
// printf(), scanf() and related CRT functions
-// Author: Joel Farley, Ove Kåven
+// Author: Joel Farley, Ove Kåven
// Modified by: Vadim Zeitlin, Robert Roebling, Ron Lee
// Created: 2007-02-19
// RCS-ID: $Id$
/* printf() family saga */
/*
- For some systems [v]snprintf() exists in the system libraries but not in the
- headers, so we need to declare it ourselves to be able to use it.
+ For many old Unix systems [v]snprintf()/vsscanf() exists in the system
+ libraries but not in the headers, so we need to declare it ourselves to be
+ able to use it.
*/
+#ifdef __UNIX__
+
#if defined(HAVE_VSNPRINTF) && !defined(HAVE_VSNPRINTF_DECL)
#ifdef __cplusplus
extern "C"
int snprintf(char *str, size_t size, const char *format, ...);
#endif /* !HAVE_SNPRINTF_DECL */
+#if defined(HAVE_VSSCANF) && !defined(HAVE_VSSCANF_DECL)
+#ifdef __cplusplus
+ extern "C"
+#else
+ extern
+#endif
+ int vsscanf(const char *str, const char *format, va_list ap);
+#endif /* !HAVE_VSSCANF_DECL */
+
/* Wrapper for vsnprintf if it's 3rd parameter is non-const. Note: the
* same isn't done for snprintf below, the builtin wxSnprintf_ is used
* instead since it's already a simple wrapper */
}
#endif
+#endif /* __UNIX__ */
+
/*
- MinGW MSVCRT has non-standard vswprintf() (for MSVC compatibility
- presumably) and normally _vsnwprintf() is used instead
+ mingw32 normally uses MSVCRT which has non-standard vswprintf() and so
+ normally _vsnwprintf() is used instead, the only exception is when mingw32
+ is used with STLPort which does have a standard vswprintf() starting from
+ version 5.1 which we can use.
*/
-#if defined(HAVE_VSWPRINTF) && defined(__MINGW32__)
- #undef HAVE_VSWPRINTF
+#ifdef __MINGW32__
+ #if defined(_STLPORT_VERSION) && _STLPORT_VERSION >= 0x510
+ #ifndef HAVE_VSWPRINTF
+ #define HAVE_VSWPRINTF
+ #endif
+ #elif defined(HAVE_VSWPRINTF)
+ /* can't use non-standard vswprintf() */
+ #undef HAVE_VSWPRINTF
+ #endif
+#endif /* __MINGW32__ */
+
+#if defined(__WATCOMC__)
+ #define HAVE_VSWPRINTF 1
#endif
#if wxUSE_PRINTF_POS_PARAMS
*/
#if defined(HAVE_UNIX98_PRINTF)
#ifdef HAVE_VSWPRINTF
- #define wxCRT_VsnprintfW_ vswprintf
+ #define wxCRT_VsnprintfW vswprintf
#endif
#ifdef HAVE_BROKEN_VSNPRINTF_DECL
#define wxCRT_VsnprintfA wx_fixed_vsnprintf
*/
#if defined _MSC_FULL_VER && _MSC_FULL_VER >= 140050727 && !defined __WXWINCE__
#define wxCRT_VsnprintfA _vsprintf_p
- #define wxCRT_VsnprintfW_ _vswprintf_p
+ #define wxCRT_VsnprintfW _vswprintf_p
#endif
#endif /* HAVE_UNIX98_PRINTF/!HAVE_UNIX98_PRINTF */
#else /* !wxUSE_PRINTF_POS_PARAMS */
#if defined(__VISUALC__) || \
(defined(__BORLANDC__) && __BORLANDC__ >= 0x540)
#define wxCRT_VsnprintfA _vsnprintf
- #define wxCRT_VsnprintfW_ _vsnwprintf
+ #define wxCRT_VsnprintfW _vsnwprintf
#else
#if defined(HAVE__VSNWPRINTF)
- #define wxCRT_VsnprintfW_ _vsnwprintf
+ #define wxCRT_VsnprintfW _vsnwprintf
#elif defined(HAVE_VSWPRINTF)
- #define wxCRT_VsnprintfW_ vswprintf
+ #define wxCRT_VsnprintfW vswprintf
#elif defined(__WATCOMC__)
- #define wxCRT_VsnprintfW_ _vsnwprintf
+ #define wxCRT_VsnprintfW _vsnwprintf
#endif
/*
#endif
#endif /* wxUSE_PRINTF_POS_PARAMS/!wxUSE_PRINTF_POS_PARAMS */
-#ifndef wxCRT_VsnprintfW_
+#ifndef wxCRT_VsnprintfW
/* no (suitable) vsnprintf(), cook our own */
WXDLLIMPEXP_BASE int
- wxCRT_VsnprintfW_(wchar_t *buf, size_t len, const wchar_t *format, va_list argptr);
+ wxCRT_VsnprintfW(wchar_t *buf, size_t len, const wchar_t *format, va_list argptr);
#define wxUSE_WXVSNPRINTFW 1
#else
#define wxUSE_WXVSNPRINTFW 0
#define wxCRT_VprintfA vprintf
#define wxCRT_VsprintfA vsprintf
-/*
- More Unicode complications: although both ANSI C and C++ define a number of
- wide character functions such as wprintf(), not all environments have them.
- Worse, those which do have different behaviours: under Windows, %s format
- specifier changes its meaning in Unicode build and expects a Unicode string
- while under Unix/POSIX it still means an ASCII string even for wprintf() and
- %ls has to be used for wide strings.
-
- We choose to always emulate Windows behaviour as more useful for us so even
- if we have wprintf() we still must wrap it in a non trivial wxPrintf().
-
-*/
-#ifndef __WINDOWS__
- #define wxNEED_PRINTF_CONVERSION
-#endif
-
-// FIXME-UTF8: format conversion should be moved outside of wxCRT_* and to the
-// vararg templates; after then, wxNEED_PRINTF_CONVERSION should
-// be removed and this code simplified
-#ifndef wxNEED_PRINTF_CONVERSION
- #ifdef wxHAVE_TCHAR_SUPPORT
- #define wxCRT_FprintfW fwprintf
- #define wxCRT_PrintfW wprintf
- #define wxCRT_VfprintfW vfwprintf
- #define wxCRT_VprintfW vwprintf
- #define wxCRT_VsprintfW vswprintf
- #endif
-#endif // !defined(wxNEED_PRINTF_CONVERSION)
-
/*
In Unicode mode we need to have all standard functions such as wprintf() and
so on but not all systems have them so use our own implementations in this
#if wxUSE_UNICODE && !defined(wxHAVE_TCHAR_SUPPORT) && !defined(HAVE_WPRINTF)
#define wxNEED_WPRINTF
#endif
+#if wxUSE_UNICODE && !defined(wxHAVE_TCHAR_SUPPORT) && !defined(HAVE_VSWSCANF)
+ #define wxNEED_VSWSCANF
+#endif
-#if defined(wxNEED_PRINTF_CONVERSION) || defined(wxNEED_WPRINTF)
+#if defined(wxNEED_WPRINTF)
/*
we need to implement all wide character printf functions either because
we don't have them at all or because they don't have the semantics we
need
*/
- int wxCRT_PrintfW( const wchar_t *format, ... ) ATTRIBUTE_PRINTF_1;
- int wxCRT_FprintfW( FILE *stream, const wchar_t *format, ... ) ATTRIBUTE_PRINTF_2;
+ int wxCRT_PrintfW( const wchar_t *format, ... );
+ int wxCRT_FprintfW( FILE *stream, const wchar_t *format, ... );
int wxCRT_VfprintfW( FILE *stream, const wchar_t *format, va_list ap );
int wxCRT_VprintfW( const wchar_t *format, va_list ap );
int wxCRT_VsprintfW( wchar_t *str, const wchar_t *format, va_list ap );
-#endif /* wxNEED_PRINTF_CONVERSION */
-
-/* these 2 can be simply mapped to the versions with underscore at the end */
-/* if we don't have to do the conversion */
-/*
- However, if we don't have any vswprintf() at all we don't need to redefine
- anything as our own wxCRT_VsnprintfW_() already behaves as needed.
-*/
-#if defined(wxNEED_PRINTF_CONVERSION) && defined(wxCRT_VsnprintfW_)
- int wxCRT_VsnprintfW( wchar_t *str, size_t size, const wchar_t *format, va_list ap );
-#else
- #define wxCRT_VsnprintfW wxCRT_VsnprintfW_
-#endif
+#else /* !wxNEED_WPRINTF */
+ #define wxCRT_FprintfW fwprintf
+ #define wxCRT_PrintfW wprintf
+ #define wxCRT_VfprintfW vfwprintf
+ #define wxCRT_VprintfW vwprintf
+
+ #if defined(__WINDOWS__) && !defined(HAVE_VSWPRINTF)
+ // only non-standard vswprintf() without buffer size argument can be used here
+ #define wxCRT_VsprintfW vswprintf
+ #endif
+#endif /* wxNEED_WPRINTF */
/* Required for wxScanf() etc. */
#define wxCRT_FscanfA fscanf
#define wxCRT_VsscanfA vsscanf
-#if defined(wxNEED_PRINTF_CONVERSION) || defined(wxNEED_WPRINTF)
- int wxCRT_ScanfW(const wchar_t *format, ...) ATTRIBUTE_PRINTF_1;
- int wxCRT_SscanfW(const wchar_t *str, const wchar_t *format, ...) ATTRIBUTE_PRINTF_2;
- int wxCRT_FscanfW(FILE *stream, const wchar_t *format, ...) ATTRIBUTE_PRINTF_2;
+#if defined(wxNEED_WPRINTF)
+ int wxCRT_ScanfW(const wchar_t *format, ...);
+ int wxCRT_SscanfW(const wchar_t *str, const wchar_t *format, ...);
+ int wxCRT_FscanfW(FILE *stream, const wchar_t *format, ...);
+#else
+ #define wxCRT_ScanfW wxVMS_USE_STD wscanf
+ #define wxCRT_SscanfW wxVMS_USE_STD swscanf
+ #define wxCRT_FscanfW wxVMS_USE_STD fwscanf
+#endif
+#ifdef wxNEED_VSWSCANF
int wxCRT_VsscanfW(const wchar_t *str, const wchar_t *format, va_list ap);
#else
- #define wxCRT_ScanfW wscanf
- #define wxCRT_SscanfW swscanf
- #define wxCRT_FscanfW fwscanf
- #define wxCRT_VsscanfW vswscanf
+ #define wxCRT_VsscanfW wxVMS_USE_STD vswscanf
#endif
// ----------------------------------------------------------------------------
#define wxSnprintf wxSnprintf_Impl
#endif
-// FIXME-UTF8: explicit wide-string and short-string format specifiers
-// (%hs, %ls and variants) are currently broken, only %s works
-// as expected (regardless of the build)
-
-// FIXME-UTF8: %c (and %hc, %lc) don't work as expected either: in UTF-8 build,
-// we should replace them with %s (as some Unicode chars may be
-// encoded with >1 bytes) and in all builds, we should use wchar_t
-// for all characters and convert char to it;
-// we'll also need wxArgNormalizer<T> specializations for char,
-// wchar_t, wxUniChar and wxUniCharRef to handle this correctly
-
// FIXME-UTF8: remove this
#if wxUSE_UNICODE
#define wxCRT_PrintfNative wxCRT_PrintfW
#define wxCRT_FprintfNative wxCRT_FprintfA
#endif
-WX_DEFINE_VARARG_FUNC(int, wxPrintf, 1, (const wxFormatString&),
- wxCRT_PrintfNative, wxCRT_PrintfA)
-WX_DEFINE_VARARG_FUNC(int, wxFprintf, 2, (FILE*, const wxFormatString&),
- wxCRT_FprintfNative, wxCRT_FprintfA)
+
+WX_DEFINE_VARARG_FUNC_SANS_N0(int, wxPrintf, 1, (const wxFormatString&),
+ wxCRT_PrintfNative, wxCRT_PrintfA)
+inline int wxPrintf(const wxFormatString& s)
+{
+ return wxPrintf("%s", s.InputAsString());
+}
+
+WX_DEFINE_VARARG_FUNC_SANS_N0(int, wxFprintf, 2, (FILE*, const wxFormatString&),
+ wxCRT_FprintfNative, wxCRT_FprintfA)
+inline int wxFprintf(FILE *f, const wxFormatString& s)
+{
+ return wxFprintf(f, "%s", s.InputAsString());
+}
// va_list versions of printf functions simply forward to the respective
// CRT function; note that they assume that va_list was created using
}
#define WX_DEFINE_SCANFUNC(name, numfixed, fixed, impl, passfixed) \
- inline int name(_WX_SCANFUNC_EXTRACT_ARGS(numfixed, fixed)) \
- { \
- return impl(_WX_SCANFUNC_EXTRACT_ARGS(numfixed, passfixed)); \
- } \
_WX_VARARG_ITER(_WX_VARARG_MAX_ARGS, \
_WX_DEFINE_SCANFUNC, \
dummy1, name, impl, passfixed, numfixed, fixed)
+// this is needed to normalize the format string, see src/common/strvararg.cpp
+// for more details
+#ifdef __WINDOWS__
+ #define wxScanfConvertFormatW(fmt) fmt
+#else
+ const wxScopedWCharBuffer
+ WXDLLIMPEXP_BASE wxScanfConvertFormatW(const wchar_t *format);
+#endif
+
WX_DEFINE_SCANFUNC(wxScanf, 1, (const char *format),
wxCRT_ScanfA, (format))
WX_DEFINE_SCANFUNC(wxScanf, 1, (const wchar_t *format),
- wxCRT_ScanfW, (format))
+ wxCRT_ScanfW, (wxScanfConvertFormatW(format)))
WX_DEFINE_SCANFUNC(wxFscanf, 2, (FILE *stream, const char *format),
wxCRT_FscanfA, (stream, format))
WX_DEFINE_SCANFUNC(wxFscanf, 2, (FILE *stream, const wchar_t *format),
- wxCRT_FscanfW, (stream, format))
+ wxCRT_FscanfW, (stream, wxScanfConvertFormatW(format)))
WX_DEFINE_SCANFUNC(wxSscanf, 2, (const char *str, const char *format),
wxCRT_SscanfA, (str, format))
WX_DEFINE_SCANFUNC(wxSscanf, 2, (const wchar_t *str, const wchar_t *format),
- wxCRT_SscanfW, (str, format))
-WX_DEFINE_SCANFUNC(wxSscanf, 2, (const wxCharBuffer& str, const char *format),
+ wxCRT_SscanfW, (str, wxScanfConvertFormatW(format)))
+WX_DEFINE_SCANFUNC(wxSscanf, 2, (const wxScopedCharBuffer& str, const char *format),
wxCRT_SscanfA, (str.data(), format))
-WX_DEFINE_SCANFUNC(wxSscanf, 2, (const wxWCharBuffer& str, const wchar_t *format),
- wxCRT_SscanfW, (str.data(), format))
+WX_DEFINE_SCANFUNC(wxSscanf, 2, (const wxScopedWCharBuffer& str, const wchar_t *format),
+ wxCRT_SscanfW, (str.data(), wxScanfConvertFormatW(format)))
WX_DEFINE_SCANFUNC(wxSscanf, 2, (const wxString& str, const char *format),
wxCRT_SscanfA, (str.mb_str(), format))
WX_DEFINE_SCANFUNC(wxSscanf, 2, (const wxString& str, const wchar_t *format),
- wxCRT_SscanfW, (str.wc_str(), format))
+ wxCRT_SscanfW, (str.wc_str(), wxScanfConvertFormatW(format)))
WX_DEFINE_SCANFUNC(wxSscanf, 2, (const wxCStrData& str, const char *format),
wxCRT_SscanfA, (str.AsCharBuf(), format))
WX_DEFINE_SCANFUNC(wxSscanf, 2, (const wxCStrData& str, const wchar_t *format),
- wxCRT_SscanfW, (str.AsWCharBuf(), format))
+ wxCRT_SscanfW, (str.AsWCharBuf(), wxScanfConvertFormatW(format)))
// Visual C++ doesn't provide vsscanf()
#ifndef __VISUALC___
int WXDLLIMPEXP_BASE wxVsscanf(const char *str, const char *format, va_list ap);
int WXDLLIMPEXP_BASE wxVsscanf(const wchar_t *str, const wchar_t *format, va_list ap);
-int WXDLLIMPEXP_BASE wxVsscanf(const wxCharBuffer& str, const char *format, va_list ap);
-int WXDLLIMPEXP_BASE wxVsscanf(const wxWCharBuffer& str, const wchar_t *format, va_list ap);
+int WXDLLIMPEXP_BASE wxVsscanf(const wxScopedCharBuffer& str, const char *format, va_list ap);
+int WXDLLIMPEXP_BASE wxVsscanf(const wxScopedWCharBuffer& str, const wchar_t *format, va_list ap);
int WXDLLIMPEXP_BASE wxVsscanf(const wxString& str, const char *format, va_list ap);
int WXDLLIMPEXP_BASE wxVsscanf(const wxString& str, const wchar_t *format, va_list ap);
int WXDLLIMPEXP_BASE wxVsscanf(const wxCStrData& str, const char *format, va_list ap);