From d2744bc848f63b222ed9bab3d93a9a3472f63eca Mon Sep 17 00:00:00 2001 From: Mark Stapper Date: Thu, 21 Feb 2019 17:01:51 +0100 Subject: [PATCH] Fix compatibility with bcc32 compiler Resolve namespace issues Add workaround for compile error on bool template argument of ArgArray struct Squelch bcc32 warning on accessing the digits array Squelch bcc32 warning on unused values Fix warnings about redefinig macros and conditions always true Disable "LConv" block for bcc32 compiler Remove macro test for deprecated macro Fix appveyor-build for cmake v3.13+ --- fmt/format.cc | 66 +++++++++++++++++++++------------------ fmt/format.h | 40 ++++++++++++++++++++++-- fmt/posix.cc | 15 +++++---- fmt/posix.h | 4 +++ fmt/printf.h | 4 +-- support/appveyor-build.py | 2 +- 6 files changed, 89 insertions(+), 42 deletions(-) diff --git a/fmt/format.cc b/fmt/format.cc index f5481fbb..de969dc8 100644 --- a/fmt/format.cc +++ b/fmt/format.cc @@ -83,7 +83,10 @@ static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) { namespace fmt { -FMT_FUNC internal::RuntimeError::~RuntimeError() FMT_DTOR_NOEXCEPT {} +namespace internal { +FMT_FUNC RuntimeError::~RuntimeError() FMT_DTOR_NOEXCEPT {} +} // namespace internal + FMT_FUNC FormatError::~FormatError() FMT_DTOR_NOEXCEPT {} FMT_FUNC SystemError::~SystemError() FMT_DTOR_NOEXCEPT {} @@ -231,8 +234,9 @@ FMT_FUNC void SystemError::init( base = std::runtime_error(w.str()); } +namespace internal { template -int internal::CharTraits::format_float( +int CharTraits::format_float( char *buffer, std::size_t size, const char *format, unsigned width, int precision, T value) { if (width == 0) { @@ -246,7 +250,7 @@ int internal::CharTraits::format_float( } template -int internal::CharTraits::format_float( +int CharTraits::format_float( wchar_t *buffer, std::size_t size, const wchar_t *format, unsigned width, int precision, T value) { if (width == 0) { @@ -260,7 +264,7 @@ int internal::CharTraits::format_float( } template -const char internal::BasicData::DIGITS[] = +const char BasicData::DIGITS[] = "0001020304050607080910111213141516171819" "2021222324252627282930313233343536373839" "4041424344454647484950515253545556575859" @@ -279,12 +283,12 @@ const char internal::BasicData::DIGITS[] = factor * 1000000000 template -const uint32_t internal::BasicData::POWERS_OF_10_32[] = { +const uint32_t BasicData::POWERS_OF_10_32[] = { 0, FMT_POWERS_OF_10(1) }; template -const uint64_t internal::BasicData::POWERS_OF_10_64[] = { +const uint64_t BasicData::POWERS_OF_10_64[] = { 0, FMT_POWERS_OF_10(1), FMT_POWERS_OF_10(ULongLong(1000000000)), @@ -293,7 +297,7 @@ const uint64_t internal::BasicData::POWERS_OF_10_64[] = { ULongLong(1000000000) * ULongLong(1000000000) * 10 }; -FMT_FUNC void internal::report_unknown_type(char code, const char *type) { +FMT_FUNC void report_unknown_type(char code, const char *type) { (void)type; if (std::isprint(static_cast(code))) { FMT_THROW(FormatError( @@ -306,7 +310,7 @@ FMT_FUNC void internal::report_unknown_type(char code, const char *type) { #if FMT_USE_WINDOWS_H -FMT_FUNC internal::UTF8ToUTF16::UTF8ToUTF16(StringRef s) { +FMT_FUNC UTF8ToUTF16::UTF8ToUTF16(StringRef s) { static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16"; if (s.size() > INT_MAX) FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG)); @@ -323,14 +327,14 @@ FMT_FUNC internal::UTF8ToUTF16::UTF8ToUTF16(StringRef s) { buffer_[length] = 0; } -FMT_FUNC internal::UTF16ToUTF8::UTF16ToUTF8(WStringRef s) { +FMT_FUNC UTF16ToUTF8::UTF16ToUTF8(WStringRef s) { if (int error_code = convert(s)) { FMT_THROW(WindowsError(error_code, "cannot convert string from UTF-16 to UTF-8")); } } -FMT_FUNC int internal::UTF16ToUTF8::convert(WStringRef s) { +FMT_FUNC int UTF16ToUTF8::convert(WStringRef s) { if (s.size() > INT_MAX) return ERROR_INVALID_PARAMETER; int s_size = static_cast(s.size()); @@ -346,6 +350,7 @@ FMT_FUNC int internal::UTF16ToUTF8::convert(WStringRef s) { buffer_[length] = 0; return 0; } +} // namespace internal FMT_FUNC void WindowsError::init( int err_code, CStringRef format_str, ArgList args) { @@ -356,7 +361,8 @@ FMT_FUNC void WindowsError::init( base = std::runtime_error(w.str()); } -FMT_FUNC void internal::format_windows_error( +namespace internal { +FMT_FUNC void format_windows_error( Writer &out, int error_code, StringRef message) FMT_NOEXCEPT { FMT_TRY { MemoryBuffer buffer; @@ -384,7 +390,7 @@ FMT_FUNC void internal::format_windows_error( } #endif // FMT_USE_WINDOWS_H - +} // namespace internal FMT_FUNC void format_system_error( Writer &out, int error_code, StringRef message) FMT_NOEXCEPT { FMT_TRY { @@ -404,38 +410,37 @@ FMT_FUNC void format_system_error( } FMT_CATCH(...) {} fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32. } +} // namespace fmt template -void internal::FixedBuffer::grow(std::size_t) { +void fmt::internal::FixedBuffer::grow(std::size_t) { FMT_THROW(std::runtime_error("buffer overflow")); } -FMT_FUNC internal::Arg internal::FormatterBase::do_get_arg( +FMT_FUNC fmt::internal::Arg fmt::internal::FormatterBase::do_get_arg( unsigned arg_index, const char *&error) { - internal::Arg arg = args_[arg_index]; + fmt::internal::Arg arg = args_[arg_index]; switch (arg.type) { - case internal::Arg::NONE: + case fmt::internal::Arg::NONE: error = "argument index out of range"; break; - case internal::Arg::NAMED_ARG: - arg = *static_cast(arg.pointer); + case fmt::internal::Arg::NAMED_ARG: + arg = *static_cast(arg.pointer); break; default: /*nothing*/; } return arg; } - +namespace fmt { FMT_FUNC void report_system_error( - int error_code, fmt::StringRef message) FMT_NOEXCEPT { - // 'fmt::' is for bcc32. + int error_code, StringRef message) FMT_NOEXCEPT { report_error(format_system_error, error_code, message); } #if FMT_USE_WINDOWS_H FMT_FUNC void report_windows_error( - int error_code, fmt::StringRef message) FMT_NOEXCEPT { - // 'fmt::' is for bcc32. + int error_code, StringRef message) FMT_NOEXCEPT { report_error(internal::format_windows_error, error_code, message); } #endif @@ -463,28 +468,29 @@ FMT_FUNC void print_colored(Color c, CStringRef format, ArgList args) { template struct internal::BasicData; // Explicit instantiations for char. +namespace internal { +template void FixedBuffer::grow(std::size_t); -template void internal::FixedBuffer::grow(std::size_t); - -template FMT_API int internal::CharTraits::format_float( +template FMT_API int CharTraits::format_float( char *buffer, std::size_t size, const char *format, unsigned width, int precision, double value); -template FMT_API int internal::CharTraits::format_float( +template FMT_API int CharTraits::format_float( char *buffer, std::size_t size, const char *format, unsigned width, int precision, long double value); // Explicit instantiations for wchar_t. -template void internal::FixedBuffer::grow(std::size_t); +template void FixedBuffer::grow(std::size_t); -template FMT_API int internal::CharTraits::format_float( +template FMT_API int CharTraits::format_float( wchar_t *buffer, std::size_t size, const wchar_t *format, unsigned width, int precision, double value); -template FMT_API int internal::CharTraits::format_float( +template FMT_API int CharTraits::format_float( wchar_t *buffer, std::size_t size, const wchar_t *format, unsigned width, int precision, long double value); +} //namespace internal #endif // FMT_HEADER_ONLY diff --git a/fmt/format.h b/fmt/format.h index fce1511b..37e298ed 100644 --- a/fmt/format.h +++ b/fmt/format.h @@ -130,6 +130,11 @@ typedef __int64 intmax_t; # define FMT_HAS_GXX_CXX11 0 #endif +#ifdef __BORLANDC__ +#pragma warn -8072 // disable "suspicious pointer arithmetic" warning on access of the digits array +#pragma warn -8004 // disable "assigned value that is never used" warning +#endif + #if defined(__INTEL_COMPILER) # define FMT_ICC_VERSION __INTEL_COMPILER #elif defined(__ICL) @@ -1328,6 +1333,7 @@ template struct LConvCheck { LConvCheck(int) {} }; +#ifndef __BORLANDC__ // Returns the thousands separator for the current locale. // We check if ``lconv`` contains ``thousands_sep`` because on Android // ``lconv`` is stubbed as an empty struct. @@ -1336,6 +1342,7 @@ inline StringRef thousands_sep( LConv *lc, LConvCheck = 0) { return lc->thousands_sep; } +#endif inline fmt::StringRef thousands_sep(...) { return ""; } @@ -2138,6 +2145,8 @@ class ArgFormatterBase : public ArgVisitor { // workaround MSVC two-phase lookup issue typedef internal::Arg Arg; + typedef Char CharType; + typedef BasicWriter WriterType; protected: BasicWriter &writer() { return writer_; } @@ -2182,8 +2191,8 @@ class ArgFormatterBase : public ArgVisitor { } if (spec_.align_ == ALIGN_NUMERIC || spec_.flags_ != 0) FMT_THROW(FormatError("invalid format specifier for char")); - typedef typename BasicWriter::CharPtr CharPtr; - Char fill = internal::CharTraits::cast(spec_.fill()); + typedef typename WriterType::CharPtr CharPtr; + CharType fill = internal::CharTraits::cast(spec_.fill()); CharPtr out = CharPtr(); const unsigned CHAR_SIZE = 1; if (spec_.width_ > CHAR_SIZE) { @@ -2201,7 +2210,7 @@ class ArgFormatterBase : public ArgVisitor { } else { out = writer_.grow_buffer(CHAR_SIZE); } - *out = internal::CharTraits::cast(value); + *out = internal::CharTraits::cast(value); } void visit_cstring(const char *value) { @@ -2403,6 +2412,7 @@ inline uint64_t make_type(const T &arg) { return MakeValue< BasicFormatter >::type(arg); } +#ifndef __BORLANDC__ template struct ArgArray; @@ -2432,6 +2442,25 @@ struct ArgArray { template static Arg make(const T &value) { return MakeArg(value); } }; +#else +template +struct ArgArray { + typedef Value Type[N > 0 ? N : 1]; + + template + static Value make(const T & value) { +#ifdef __clang__ + Value result = MakeValue(value); + // Workaround a bug in Apple LLVM version 4.2 (clang-425.0.28) of clang: + // https://github.com/fmtlib/fmt/issues/276 + (void)result.custom.format; + return result; +#else + return MakeValue(value); +#endif + } +}; +#endif #if FMT_USE_VARIADIC_TEMPLATES template @@ -4213,4 +4242,9 @@ operator"" _a(const wchar_t *s, std::size_t) { return {s}; } # define FMT_FUNC #endif +#ifdef __BORLANDC__ +#pragma warn .8072 // restore "suspicious pointer arithmetic" warning on access of the digits array +#pragma warn .8004 // restore "assigned value that is never used" warning +#endif + #endif // FMT_FORMAT_H_ diff --git a/fmt/posix.cc b/fmt/posix.cc index 356668c1..e7b57769 100644 --- a/fmt/posix.cc +++ b/fmt/posix.cc @@ -26,10 +26,13 @@ # endif # include # include - -# define O_CREAT _O_CREAT -# define O_TRUNC _O_TRUNC - +#include +# ifndef O_CREAT +# define O_CREAT _O_CREAT +# endif +# ifndef O_TRUNC +# define O_TRUNC _O_TRUNC +# endif # ifndef S_IRUSR # define S_IRUSR _S_IREAD # endif @@ -56,7 +59,7 @@ typedef int RWResult; // On Windows the count argument to read and write is unsigned, so convert // it from size_t preventing integer overflow. inline unsigned convert_rwcount(std::size_t count) { - return count <= UINT_MAX ? static_cast(count) : UINT_MAX; + return static_cast(std::min(count, UINT_MAX)); } #else // Return type of read and write functions. @@ -99,7 +102,7 @@ int fmt::BufferedFile::fileno() const { fmt::File::File(fmt::CStringRef path, int oflag) { int mode = S_IRUSR | S_IWUSR; -#if defined(_WIN32) && !defined(__MINGW32__) +#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__BORLANDC__) fd_ = -1; FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode)); #else diff --git a/fmt/posix.h b/fmt/posix.h index 88512de5..c3ce964a 100644 --- a/fmt/posix.h +++ b/fmt/posix.h @@ -46,6 +46,10 @@ # ifdef _WIN32 // Fix warnings about deprecated symbols. # define FMT_POSIX_CALL(call) ::_##call +# if defined(__BORLANDC__) && !defined(_dup2) +// for some reason the borland headers do define _dup but not _dup2 +# define _dup2 dup2 +# endif # else # define FMT_POSIX_CALL(call) ::call # endif diff --git a/fmt/printf.h b/fmt/printf.h index 46205a78..736d9d39 100644 --- a/fmt/printf.h +++ b/fmt/printf.h @@ -333,7 +333,7 @@ class PrintfFormatter : private internal::FormatterBase { \endrst */ explicit PrintfFormatter(const ArgList &al, BasicWriter &w) - : FormatterBase(al), writer_(w) {} + : internal::FormatterBase(al), writer_(w) {} /** Formats stored arguments and writes the output to the writer. */ void format(BasicCStringRef format_str); @@ -371,7 +371,7 @@ internal::Arg PrintfFormatter::get_arg(const Char *s, (void)s; const char *error = FMT_NULL; internal::Arg arg = arg_index == std::numeric_limits::max() ? - next_arg(error) : FormatterBase::get_arg(arg_index - 1, error); + next_arg(error) : internal::FormatterBase::get_arg(arg_index - 1, error); if (error) FMT_THROW(FormatError(!*s ? "invalid format string" : error)); return arg; diff --git a/support/appveyor-build.py b/support/appveyor-build.py index 3b747f3c..a5dbbb3e 100755 --- a/support/appveyor-build.py +++ b/support/appveyor-build.py @@ -8,7 +8,7 @@ build = os.environ['BUILD'] config = os.environ['CONFIGURATION'] platform = os.environ.get('PLATFORM') path = os.environ['PATH'] -cmake_command = ['cmake', '-DFMT_PEDANTIC=ON', '-DCMAKE_BUILD_TYPE=' + config] +cmake_command = ['cmake', '-DFMT_PEDANTIC=ON', '-DCMAKE_BUILD_TYPE=' + config, '.'] if build == 'mingw': cmake_command.append('-GMinGW Makefiles') build_command = ['mingw32-make', '-j4']