X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/52de37c78f31bc03f8b96090932c7ce8c3907d29..38534f596974042130716a26276e9564b0b72295:/include/wx/wxcrtvararg.h diff --git a/include/wx/wxcrtvararg.h b/include/wx/wxcrtvararg.h index 2fd54d4fed..959f88fcc1 100644 --- a/include/wx/wxcrtvararg.h +++ b/include/wx/wxcrtvararg.h @@ -2,7 +2,7 @@ // 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$ @@ -13,6 +13,9 @@ #ifndef _WX_WXCRTVARARG_H_ #define _WX_WXCRTVARARG_H_ +// NB: User code should include wx/crt.h instead of including this +// header directly. + #include "wx/wxcrt.h" #include "wx/strvararg.h" @@ -28,9 +31,12 @@ /* 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" @@ -49,6 +55,15 @@ 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 */ @@ -59,12 +74,27 @@ } #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 @@ -77,7 +107,7 @@ */ #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 @@ -93,7 +123,7 @@ */ #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 */ @@ -110,22 +140,18 @@ #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 - /* - All versions of CodeWarrior supported by wxWidgets apparently - have both snprintf() and vsnprintf() - */ #if defined(HAVE_VSNPRINTF) \ - || defined(__MWERKS__) || defined(__WATCOMC__) + || defined(__WATCOMC__) #ifdef HAVE_BROKEN_VSNPRINTF_DECL #define wxCRT_VsnprintfA wx_fixed_vsnprintf #else @@ -135,10 +161,10 @@ #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 @@ -172,35 +198,6 @@ #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 @@ -209,32 +206,33 @@ #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. */ @@ -243,16 +241,19 @@ #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 // ---------------------------------------------------------------------------- @@ -267,17 +268,6 @@ #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 specializations for char, -// wchar_t, wxUniChar and wxUniCharRef to handle this correctly - // FIXME-UTF8: remove this #if wxUSE_UNICODE #define wxCRT_PrintfNative wxCRT_PrintfW @@ -287,10 +277,20 @@ #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 @@ -432,47 +432,52 @@ wxVsnprintf(wchar_t *str, size_t size, const wxString& format, va_list argptr); } #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);