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
Use FMT_VARIADIC_ for FMT_VARIADIC_VOID and FMT_VARIADIC_CTOR
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+
This commit is contained in:
Mark Stapper 2019-02-21 17:01:51 +01:00 committed by Mark Stapper
parent b6d435b9a6
commit 159e12cbf5
7 changed files with 230 additions and 241 deletions

View File

@ -83,7 +83,10 @@ static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
namespace fmt { 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 FormatError::~FormatError() FMT_DTOR_NOEXCEPT {}
FMT_FUNC SystemError::~SystemError() 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()); base = std::runtime_error(w.str());
} }
namespace internal {
template <typename T> template <typename T>
int internal::CharTraits<char>::format_float( int CharTraits<char>::format_float(
char *buffer, std::size_t size, const char *format, char *buffer, std::size_t size, const char *format,
unsigned width, int precision, T value) { unsigned width, int precision, T value) {
if (width == 0) { if (width == 0) {
@ -246,7 +250,7 @@ int internal::CharTraits<char>::format_float(
} }
template <typename T> template <typename T>
int internal::CharTraits<wchar_t>::format_float( int CharTraits<wchar_t>::format_float(
wchar_t *buffer, std::size_t size, const wchar_t *format, wchar_t *buffer, std::size_t size, const wchar_t *format,
unsigned width, int precision, T value) { unsigned width, int precision, T value) {
if (width == 0) { if (width == 0) {
@ -260,7 +264,7 @@ int internal::CharTraits<wchar_t>::format_float(
} }
template <typename T> template <typename T>
const char internal::BasicData<T>::DIGITS[] = const char BasicData<T>::DIGITS[] =
"0001020304050607080910111213141516171819" "0001020304050607080910111213141516171819"
"2021222324252627282930313233343536373839" "2021222324252627282930313233343536373839"
"4041424344454647484950515253545556575859" "4041424344454647484950515253545556575859"
@ -279,12 +283,12 @@ const char internal::BasicData<T>::DIGITS[] =
factor * 1000000000 factor * 1000000000
template <typename T> template <typename T>
const uint32_t internal::BasicData<T>::POWERS_OF_10_32[] = { const uint32_t BasicData<T>::POWERS_OF_10_32[] = {
0, FMT_POWERS_OF_10(1) 0, FMT_POWERS_OF_10(1)
}; };
template <typename T> template <typename T>
const uint64_t internal::BasicData<T>::POWERS_OF_10_64[] = { const uint64_t BasicData<T>::POWERS_OF_10_64[] = {
0, 0,
FMT_POWERS_OF_10(1), FMT_POWERS_OF_10(1),
FMT_POWERS_OF_10(ULongLong(1000000000)), FMT_POWERS_OF_10(ULongLong(1000000000)),
@ -293,7 +297,7 @@ const uint64_t internal::BasicData<T>::POWERS_OF_10_64[] = {
ULongLong(1000000000) * ULongLong(1000000000) * 10 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; (void)type;
if (std::isprint(static_cast<unsigned char>(code))) { if (std::isprint(static_cast<unsigned char>(code))) {
FMT_THROW(FormatError( FMT_THROW(FormatError(
@ -306,7 +310,7 @@ FMT_FUNC void internal::report_unknown_type(char code, const char *type) {
#if FMT_USE_WINDOWS_H #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"; static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
if (s.size() > INT_MAX) if (s.size() > INT_MAX)
FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG)); FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
@ -323,14 +327,14 @@ FMT_FUNC internal::UTF8ToUTF16::UTF8ToUTF16(StringRef s) {
buffer_[length] = 0; buffer_[length] = 0;
} }
FMT_FUNC internal::UTF16ToUTF8::UTF16ToUTF8(WStringRef s) { FMT_FUNC UTF16ToUTF8::UTF16ToUTF8(WStringRef s) {
if (int error_code = convert(s)) { if (int error_code = convert(s)) {
FMT_THROW(WindowsError(error_code, FMT_THROW(WindowsError(error_code,
"cannot convert string from UTF-16 to UTF-8")); "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) if (s.size() > INT_MAX)
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
int s_size = static_cast<int>(s.size()); int s_size = static_cast<int>(s.size());
@ -346,6 +350,7 @@ FMT_FUNC int internal::UTF16ToUTF8::convert(WStringRef s) {
buffer_[length] = 0; buffer_[length] = 0;
return 0; return 0;
} }
} // namespace internal
FMT_FUNC void WindowsError::init( FMT_FUNC void WindowsError::init(
int err_code, CStringRef format_str, ArgList args) { int err_code, CStringRef format_str, ArgList args) {
@ -356,7 +361,8 @@ FMT_FUNC void WindowsError::init(
base = std::runtime_error(w.str()); 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 { Writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
FMT_TRY { FMT_TRY {
MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer; MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer;
@ -384,7 +390,7 @@ FMT_FUNC void internal::format_windows_error(
} }
#endif // FMT_USE_WINDOWS_H #endif // FMT_USE_WINDOWS_H
} // namespace internal
FMT_FUNC void format_system_error( FMT_FUNC void format_system_error(
Writer &out, int error_code, StringRef message) FMT_NOEXCEPT { Writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
FMT_TRY { FMT_TRY {
@ -404,38 +410,37 @@ FMT_FUNC void format_system_error(
} FMT_CATCH(...) {} } FMT_CATCH(...) {}
fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32. fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
} }
} // namespace fmt
template <typename Char> template <typename Char>
void internal::FixedBuffer<Char>::grow(std::size_t) { void fmt::internal::FixedBuffer<Char>::grow(std::size_t) {
FMT_THROW(std::runtime_error("buffer overflow")); 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) { unsigned arg_index, const char *&error) {
internal::Arg arg = args_[arg_index]; fmt::internal::Arg arg = args_[arg_index];
switch (arg.type) { switch (arg.type) {
case internal::Arg::NONE: case fmt::internal::Arg::NONE:
error = "argument index out of range"; error = "argument index out of range";
break; break;
case internal::Arg::NAMED_ARG: case fmt::internal::Arg::NAMED_ARG:
arg = *static_cast<const internal::Arg*>(arg.pointer); arg = *static_cast<const fmt::internal::Arg*>(arg.pointer);
break; break;
default: default:
/*nothing*/; /*nothing*/;
} }
return arg; return arg;
} }
namespace fmt {
FMT_FUNC void report_system_error( FMT_FUNC void report_system_error(
int error_code, fmt::StringRef message) FMT_NOEXCEPT { int error_code, StringRef message) FMT_NOEXCEPT {
// 'fmt::' is for bcc32.
report_error(format_system_error, error_code, message); report_error(format_system_error, error_code, message);
} }
#if FMT_USE_WINDOWS_H #if FMT_USE_WINDOWS_H
FMT_FUNC void report_windows_error( FMT_FUNC void report_windows_error(
int error_code, fmt::StringRef message) FMT_NOEXCEPT { int error_code, StringRef message) FMT_NOEXCEPT {
// 'fmt::' is for bcc32.
report_error(internal::format_windows_error, error_code, message); report_error(internal::format_windows_error, error_code, message);
} }
#endif #endif
@ -463,28 +468,29 @@ FMT_FUNC void print_colored(Color c, CStringRef format, ArgList args) {
template struct internal::BasicData<void>; template struct internal::BasicData<void>;
// Explicit instantiations for char. // Explicit instantiations for char.
namespace internal {
template void FixedBuffer<char>::grow(std::size_t);
template void internal::FixedBuffer<char>::grow(std::size_t); template FMT_API int CharTraits<char>::format_float(
template FMT_API int internal::CharTraits<char>::format_float(
char *buffer, std::size_t size, const char *format, char *buffer, std::size_t size, const char *format,
unsigned width, int precision, double value); unsigned width, int precision, double value);
template FMT_API int internal::CharTraits<char>::format_float( template FMT_API int CharTraits<char>::format_float(
char *buffer, std::size_t size, const char *format, char *buffer, std::size_t size, const char *format,
unsigned width, int precision, long double value); unsigned width, int precision, long double value);
// Explicit instantiations for wchar_t. // Explicit instantiations for wchar_t.
template void internal::FixedBuffer<wchar_t>::grow(std::size_t); template void FixedBuffer<wchar_t>::grow(std::size_t);
template FMT_API int internal::CharTraits<wchar_t>::format_float( template FMT_API int CharTraits<wchar_t>::format_float(
wchar_t *buffer, std::size_t size, const wchar_t *format, wchar_t *buffer, std::size_t size, const wchar_t *format,
unsigned width, int precision, double value); unsigned width, int precision, double value);
template FMT_API int internal::CharTraits<wchar_t>::format_float( template FMT_API int CharTraits<wchar_t>::format_float(
wchar_t *buffer, std::size_t size, const wchar_t *format, wchar_t *buffer, std::size_t size, const wchar_t *format,
unsigned width, int precision, long double value); unsigned width, int precision, long double value);
} //namespace internal
#endif // FMT_HEADER_ONLY #endif // FMT_HEADER_ONLY

View File

@ -130,6 +130,11 @@ typedef __int64 intmax_t;
# define FMT_HAS_GXX_CXX11 0 # define FMT_HAS_GXX_CXX11 0
#endif #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) #if defined(__INTEL_COMPILER)
# define FMT_ICC_VERSION __INTEL_COMPILER # define FMT_ICC_VERSION __INTEL_COMPILER
#elif defined(__ICL) #elif defined(__ICL)
@ -1328,6 +1333,7 @@ template <typename T, T> struct LConvCheck {
LConvCheck(int) {} LConvCheck(int) {}
}; };
#ifndef __BORLANDC__
// Returns the thousands separator for the current locale. // Returns the thousands separator for the current locale.
// We check if ``lconv`` contains ``thousands_sep`` because on Android // We check if ``lconv`` contains ``thousands_sep`` because on Android
// ``lconv`` is stubbed as an empty struct. // ``lconv`` is stubbed as an empty struct.
@ -1336,6 +1342,7 @@ inline StringRef thousands_sep(
LConv *lc, LConvCheck<char *LConv::*, &LConv::thousands_sep> = 0) { LConv *lc, LConvCheck<char *LConv::*, &LConv::thousands_sep> = 0) {
return lc->thousands_sep; return lc->thousands_sep;
} }
#endif
inline fmt::StringRef thousands_sep(...) { return ""; } inline fmt::StringRef thousands_sep(...) { return ""; }
@ -2138,6 +2145,8 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
// workaround MSVC two-phase lookup issue // workaround MSVC two-phase lookup issue
typedef internal::Arg Arg; typedef internal::Arg Arg;
typedef Char CharType;
typedef BasicWriter<Char> WriterType;
protected: protected:
BasicWriter<Char> &writer() { return writer_; } BasicWriter<Char> &writer() { return writer_; }
@ -2182,8 +2191,8 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
} }
if (spec_.align_ == ALIGN_NUMERIC || spec_.flags_ != 0) if (spec_.align_ == ALIGN_NUMERIC || spec_.flags_ != 0)
FMT_THROW(FormatError("invalid format specifier for char")); FMT_THROW(FormatError("invalid format specifier for char"));
typedef typename BasicWriter<Char>::CharPtr CharPtr; typedef typename WriterType::CharPtr CharPtr;
Char fill = internal::CharTraits<Char>::cast(spec_.fill()); CharType fill = internal::CharTraits<CharType>::cast(spec_.fill());
CharPtr out = CharPtr(); CharPtr out = CharPtr();
const unsigned CHAR_SIZE = 1; const unsigned CHAR_SIZE = 1;
if (spec_.width_ > CHAR_SIZE) { if (spec_.width_ > CHAR_SIZE) {
@ -2201,7 +2210,7 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
} else { } else {
out = writer_.grow_buffer(CHAR_SIZE); out = writer_.grow_buffer(CHAR_SIZE);
} }
*out = internal::CharTraits<Char>::cast(value); *out = internal::CharTraits<CharType>::cast(value);
} }
void visit_cstring(const char *value) { void visit_cstring(const char *value) {
@ -2403,6 +2412,7 @@ inline uint64_t make_type(const T &arg) {
return MakeValue< BasicFormatter<char> >::type(arg); return MakeValue< BasicFormatter<char> >::type(arg);
} }
#ifndef __BORLANDC__
template <std::size_t N, bool/*IsPacked*/= (N < ArgList::MAX_PACKED_ARGS)> template <std::size_t N, bool/*IsPacked*/= (N < ArgList::MAX_PACKED_ARGS)>
struct ArgArray; struct ArgArray;
@ -2432,6 +2442,25 @@ struct ArgArray<N, false/*IsPacked*/> {
template <typename Formatter, typename T> template <typename Formatter, typename T>
static Arg make(const T &value) { return MakeArg<Formatter>(value); } static Arg make(const T &value) { return MakeArg<Formatter>(value); }
}; };
#else
template <std::size_t N>
struct ArgArray {
typedef Value Type[N > 0 ? N : 1];
template <typename Formatter, typename T>
static Value make(const T & value) {
#ifdef __clang__
Value result = MakeValue<Formatter>(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<Formatter>(value);
#endif
}
};
#endif
#if FMT_USE_VARIADIC_TEMPLATES #if FMT_USE_VARIADIC_TEMPLATES
template <typename Arg, typename... Args> template <typename Arg, typename... Args>
@ -2469,74 +2498,6 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
# define FMT_ASSIGN_wchar_t(n) \ # define FMT_ASSIGN_wchar_t(n) \
arr[n] = fmt::internal::MakeValue< fmt::BasicFormatter<wchar_t> >(v##n) arr[n] = fmt::internal::MakeValue< fmt::BasicFormatter<wchar_t> >(v##n)
#if FMT_USE_VARIADIC_TEMPLATES
// Defines a variadic function returning void.
# define FMT_VARIADIC_VOID(func, arg_type) \
template <typename... Args> \
void func(arg_type arg0, const Args & ... args) { \
typedef fmt::internal::ArgArray<sizeof...(Args)> ArgArray; \
typename ArgArray::Type array{ \
ArgArray::template make<fmt::BasicFormatter<Char> >(args)...}; \
func(arg0, fmt::ArgList(fmt::internal::make_type(args...), array)); \
}
// Defines a variadic constructor.
# define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \
template <typename... Args> \
ctor(arg0_type arg0, arg1_type arg1, const Args & ... args) { \
typedef fmt::internal::ArgArray<sizeof...(Args)> ArgArray; \
typename ArgArray::Type array{ \
ArgArray::template make<fmt::BasicFormatter<Char> >(args)...}; \
func(arg0, arg1, fmt::ArgList(fmt::internal::make_type(args...), array)); \
}
#else
# define FMT_MAKE_REF(n) \
fmt::internal::MakeValue< fmt::BasicFormatter<Char> >(v##n)
# define FMT_MAKE_REF2(n) v##n
// Defines a wrapper for a function taking one argument of type arg_type
// and n additional arguments of arbitrary types.
# define FMT_WRAP1(func, arg_type, n) \
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
inline void func(arg_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \
const fmt::internal::ArgArray<n>::Type array = {FMT_GEN(n, FMT_MAKE_REF)}; \
func(arg1, fmt::ArgList( \
fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), array)); \
}
// Emulates a variadic function returning void on a pre-C++11 compiler.
# define FMT_VARIADIC_VOID(func, arg_type) \
inline void func(arg_type arg) { func(arg, fmt::ArgList()); } \
FMT_WRAP1(func, arg_type, 1) FMT_WRAP1(func, arg_type, 2) \
FMT_WRAP1(func, arg_type, 3) FMT_WRAP1(func, arg_type, 4) \
FMT_WRAP1(func, arg_type, 5) FMT_WRAP1(func, arg_type, 6) \
FMT_WRAP1(func, arg_type, 7) FMT_WRAP1(func, arg_type, 8) \
FMT_WRAP1(func, arg_type, 9) FMT_WRAP1(func, arg_type, 10)
# define FMT_CTOR(ctor, func, arg0_type, arg1_type, n) \
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
ctor(arg0_type arg0, arg1_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \
const fmt::internal::ArgArray<n>::Type array = {FMT_GEN(n, FMT_MAKE_REF)}; \
func(arg0, arg1, fmt::ArgList( \
fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), array)); \
}
// Emulates a variadic constructor on a pre-C++11 compiler.
# define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \
FMT_CTOR(ctor, func, arg0_type, arg1_type, 1) \
FMT_CTOR(ctor, func, arg0_type, arg1_type, 2) \
FMT_CTOR(ctor, func, arg0_type, arg1_type, 3) \
FMT_CTOR(ctor, func, arg0_type, arg1_type, 4) \
FMT_CTOR(ctor, func, arg0_type, arg1_type, 5) \
FMT_CTOR(ctor, func, arg0_type, arg1_type, 6) \
FMT_CTOR(ctor, func, arg0_type, arg1_type, 7) \
FMT_CTOR(ctor, func, arg0_type, arg1_type, 8) \
FMT_CTOR(ctor, func, arg0_type, arg1_type, 9) \
FMT_CTOR(ctor, func, arg0_type, arg1_type, 10)
#endif
// Generates a comma-separated list with results of applying f to pairs // Generates a comma-separated list with results of applying f to pairs
// (argument, index). // (argument, index).
#define FMT_FOR_EACH1(f, x0) f(x0, 0) #define FMT_FOR_EACH1(f, x0) f(x0, 0)
@ -2559,6 +2520,147 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
#define FMT_FOR_EACH10(f, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) \ #define FMT_FOR_EACH10(f, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) \
FMT_FOR_EACH9(f, x0, x1, x2, x3, x4, x5, x6, x7, x8), f(x9, 9) FMT_FOR_EACH9(f, x0, x1, x2, x3, x4, x5, x6, x7, x8), f(x9, 9)
// This is used to work around VC++ bugs in handling variadic macros.
#define FMT_EXPAND(args) args
// Returns the number of arguments.
// Based on https://groups.google.com/forum/#!topic/comp.std.c/d-6Mj5Lko_s.
#define FMT_NARG(...) FMT_NARG_(__VA_ARGS__, FMT_RSEQ_N())
#define FMT_NARG_(...) FMT_EXPAND(FMT_ARG_N(__VA_ARGS__))
#define FMT_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define FMT_RSEQ_N() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
#define FMT_FOR_EACH_(N, f, ...) \
FMT_EXPAND(FMT_CONCAT(FMT_FOR_EACH, N)(f, __VA_ARGS__))
#define FMT_FOR_EACH(f, ...) \
FMT_EXPAND(FMT_FOR_EACH_(FMT_NARG(__VA_ARGS__), f, __VA_ARGS__))
#define FMT_ADD_ARG_NAME(type, index) type arg##index
#define FMT_GET_ARG_NAME(type, index) arg##index
#if FMT_USE_VARIADIC_TEMPLATES
# define FMT_VARIADIC_(Const, Char, ReturnType, func, call, ...) \
template <typename... Args> \
ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
const Args & ... args) Const { \
typedef fmt::internal::ArgArray<sizeof...(Args)> ArgArray; \
typename ArgArray::Type array{ \
ArgArray::template make<fmt::BasicFormatter<Char> >(args)...}; \
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
fmt::ArgList(fmt::internal::make_type(args...), array)); \
}
# define FMT_VARIADIC_VAR_ARG(Const, Char, ReturnType, func, call, ...) \
FMT_VARIADIC_(Const, Char, ReturnType, func, call, __VA_ARGS__)
#else
# define FMT_MAKE_REF(n) \
fmt::internal::MakeValue< fmt::BasicFormatter<Char> >(v##n)
# define FMT_MAKE_REF2(n) v##n
// Defines a wrapper for a function taking __VA_ARGS__ arguments
// and n additional arguments of arbitrary types.
# define FMT_WRAP(Const, Char, ReturnType, func, call, n, ...) \
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
FMT_GEN(n, FMT_MAKE_ARG)) Const { \
fmt::internal::ArgArray<n>::Type arr; \
FMT_GEN(n, FMT_ASSIGN_##Char); \
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList( \
fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), arr)); \
}
# define FMT_VARIADIC_ZERO_ARG(Const, Char, ReturnType, func, call, ...) \
inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__)) Const { \
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList()); \
}
# define FMT_VARIADIC_VAR_ARG(Const, Char, ReturnType, func, call, ...)\
FMT_WRAP(Const, Char, ReturnType, func, call, 1, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 2, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 3, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 4, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 5, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 6, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 7, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 8, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 9, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 10, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 11, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 12, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 13, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 14, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 15, __VA_ARGS__)
# define FMT_VARIADIC_(Const, Char, ReturnType, func, call, ...) \
FMT_VARIADIC_ZERO_ARG(Const, Char, ReturnType, func, call, __VA_ARGS__) \
FMT_VARIADIC_VAR_ARG(Const, Char, ReturnType, func, call, __VA_ARGS__)
#endif // FMT_USE_VARIADIC_TEMPLATES
/**
\rst
Defines a variadic function with the specified return type, function name
and argument types passed as variable arguments to this macro.
**Example**::
void print_error(const char *file, int line, const char *format,
fmt::ArgList args) {
fmt::print("{}: {}: ", file, line);
fmt::print(format, args);
}
FMT_VARIADIC(void, print_error, const char *, int, const char *)
``FMT_VARIADIC`` is used for compatibility with legacy C++ compilers that
don't implement variadic templates. You don't have to use this macro if
you don't need legacy compiler support and can use variadic templates
directly::
template <typename... Args>
void print_error(const char *file, int line, const char *format,
const Args & ... args) {
fmt::print("{}: {}: ", file, line);
fmt::print(format, args...);
}
\endrst
*/
#define FMT_VARIADIC(ReturnType, func, ...) \
FMT_VARIADIC_(, char, ReturnType, func, return func, __VA_ARGS__)
#define FMT_VARIADIC_CONST(ReturnType, func, ...) \
FMT_VARIADIC_(const, char, ReturnType, func, return func, __VA_ARGS__)
#define FMT_VARIADIC_W(ReturnType, func, ...) \
FMT_VARIADIC_(, wchar_t, ReturnType, func, return func, __VA_ARGS__)
#define FMT_VARIADIC_CONST_W(ReturnType, func, ...) \
FMT_VARIADIC_(const, wchar_t, ReturnType, func, return func, __VA_ARGS__)
#define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \
FMT_VARIADIC_VAR_ARG(, char, , ctor, func, arg0_type, arg1_type)
#define FMT_VARIADIC_VOID(func, arg_type) \
FMT_VARIADIC(void,func, arg_type)
#define FMT_CAPTURE_ARG_(id, index) ::fmt::arg(#id, id)
#define FMT_CAPTURE_ARG_W_(id, index) ::fmt::arg(L## #id, id)
/**
\rst
Convenient macro to capture the arguments' names and values into several
``fmt::arg(name, value)``.
**Example**::
int x = 1, y = 2;
print("point: ({x}, {y})", FMT_CAPTURE(x, y));
// same as:
// print("point: ({x}, {y})", arg("x", x), arg("y", y));
\endrst
*/
#define FMT_CAPTURE(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_, __VA_ARGS__)
#define FMT_CAPTURE_W(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_W_, __VA_ARGS__)
/** /**
An error returned by an operating system or a language runtime, An error returned by an operating system or a language runtime,
for example a file opening error. for example a file opening error.
@ -3653,130 +3755,6 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
# pragma GCC system_header # pragma GCC system_header
#endif #endif
// This is used to work around VC++ bugs in handling variadic macros.
#define FMT_EXPAND(args) args
// Returns the number of arguments.
// Based on https://groups.google.com/forum/#!topic/comp.std.c/d-6Mj5Lko_s.
#define FMT_NARG(...) FMT_NARG_(__VA_ARGS__, FMT_RSEQ_N())
#define FMT_NARG_(...) FMT_EXPAND(FMT_ARG_N(__VA_ARGS__))
#define FMT_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define FMT_RSEQ_N() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
#define FMT_FOR_EACH_(N, f, ...) \
FMT_EXPAND(FMT_CONCAT(FMT_FOR_EACH, N)(f, __VA_ARGS__))
#define FMT_FOR_EACH(f, ...) \
FMT_EXPAND(FMT_FOR_EACH_(FMT_NARG(__VA_ARGS__), f, __VA_ARGS__))
#define FMT_ADD_ARG_NAME(type, index) type arg##index
#define FMT_GET_ARG_NAME(type, index) arg##index
#if FMT_USE_VARIADIC_TEMPLATES
# define FMT_VARIADIC_(Const, Char, ReturnType, func, call, ...) \
template <typename... Args> \
ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
const Args & ... args) Const { \
typedef fmt::internal::ArgArray<sizeof...(Args)> ArgArray; \
typename ArgArray::Type array{ \
ArgArray::template make<fmt::BasicFormatter<Char> >(args)...}; \
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
fmt::ArgList(fmt::internal::make_type(args...), array)); \
}
#else
// Defines a wrapper for a function taking __VA_ARGS__ arguments
// and n additional arguments of arbitrary types.
# define FMT_WRAP(Const, Char, ReturnType, func, call, n, ...) \
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
FMT_GEN(n, FMT_MAKE_ARG)) Const { \
fmt::internal::ArgArray<n>::Type arr; \
FMT_GEN(n, FMT_ASSIGN_##Char); \
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList( \
fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), arr)); \
}
# define FMT_VARIADIC_(Const, Char, ReturnType, func, call, ...) \
inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__)) Const { \
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList()); \
} \
FMT_WRAP(Const, Char, ReturnType, func, call, 1, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 2, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 3, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 4, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 5, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 6, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 7, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 8, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 9, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 10, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 11, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 12, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 13, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 14, __VA_ARGS__) \
FMT_WRAP(Const, Char, ReturnType, func, call, 15, __VA_ARGS__)
#endif // FMT_USE_VARIADIC_TEMPLATES
/**
\rst
Defines a variadic function with the specified return type, function name
and argument types passed as variable arguments to this macro.
**Example**::
void print_error(const char *file, int line, const char *format,
fmt::ArgList args) {
fmt::print("{}: {}: ", file, line);
fmt::print(format, args);
}
FMT_VARIADIC(void, print_error, const char *, int, const char *)
``FMT_VARIADIC`` is used for compatibility with legacy C++ compilers that
don't implement variadic templates. You don't have to use this macro if
you don't need legacy compiler support and can use variadic templates
directly::
template <typename... Args>
void print_error(const char *file, int line, const char *format,
const Args & ... args) {
fmt::print("{}: {}: ", file, line);
fmt::print(format, args...);
}
\endrst
*/
#define FMT_VARIADIC(ReturnType, func, ...) \
FMT_VARIADIC_(, char, ReturnType, func, return func, __VA_ARGS__)
#define FMT_VARIADIC_CONST(ReturnType, func, ...) \
FMT_VARIADIC_(const, char, ReturnType, func, return func, __VA_ARGS__)
#define FMT_VARIADIC_W(ReturnType, func, ...) \
FMT_VARIADIC_(, wchar_t, ReturnType, func, return func, __VA_ARGS__)
#define FMT_VARIADIC_CONST_W(ReturnType, func, ...) \
FMT_VARIADIC_(const, wchar_t, ReturnType, func, return func, __VA_ARGS__)
#define FMT_CAPTURE_ARG_(id, index) ::fmt::arg(#id, id)
#define FMT_CAPTURE_ARG_W_(id, index) ::fmt::arg(L###id, id)
/**
\rst
Convenient macro to capture the arguments' names and values into several
``fmt::arg(name, value)``.
**Example**::
int x = 1, y = 2;
print("point: ({x}, {y})", FMT_CAPTURE(x, y));
// same as:
// print("point: ({x}, {y})", arg("x", x), arg("y", y));
\endrst
*/
#define FMT_CAPTURE(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_, __VA_ARGS__)
#define FMT_CAPTURE_W(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_W_, __VA_ARGS__)
namespace fmt { namespace fmt {
FMT_VARIADIC(std::string, format, CStringRef) FMT_VARIADIC(std::string, format, CStringRef)
FMT_VARIADIC_W(std::wstring, format, WCStringRef) FMT_VARIADIC_W(std::wstring, format, WCStringRef)
@ -4213,4 +4191,9 @@ operator"" _a(const wchar_t *s, std::size_t) { return {s}; }
# define FMT_FUNC # define FMT_FUNC
#endif #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_ #endif // FMT_FORMAT_H_

View File

@ -26,10 +26,13 @@
# endif # endif
# include <windows.h> # include <windows.h>
# include <io.h> # include <io.h>
#include <algorithm>
# define O_CREAT _O_CREAT # ifndef O_CREAT
# define O_TRUNC _O_TRUNC # define O_CREAT _O_CREAT
# endif
# ifndef O_TRUNC
# define O_TRUNC _O_TRUNC
# endif
# ifndef S_IRUSR # ifndef S_IRUSR
# define S_IRUSR _S_IREAD # define S_IRUSR _S_IREAD
# endif # endif
@ -56,7 +59,7 @@ typedef int RWResult;
// On Windows the count argument to read and write is unsigned, so convert // On Windows the count argument to read and write is unsigned, so convert
// it from size_t preventing integer overflow. // it from size_t preventing integer overflow.
inline unsigned convert_rwcount(std::size_t count) { inline unsigned convert_rwcount(std::size_t count) {
return count <= UINT_MAX ? static_cast<unsigned>(count) : UINT_MAX; return static_cast<unsigned>(std::min<std::size_t>(count, UINT_MAX));
} }
#else #else
// Return type of read and write functions. // Return type of read and write functions.
@ -99,7 +102,7 @@ int fmt::BufferedFile::fileno() const {
fmt::File::File(fmt::CStringRef path, int oflag) { fmt::File::File(fmt::CStringRef path, int oflag) {
int mode = S_IRUSR | S_IWUSR; int mode = S_IRUSR | S_IWUSR;
#if defined(_WIN32) && !defined(__MINGW32__) #if defined(_WIN32) && !defined(__MINGW32__) && !defined(__BORLANDC__)
fd_ = -1; fd_ = -1;
FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode)); FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode));
#else #else

View File

@ -46,6 +46,10 @@
# ifdef _WIN32 # ifdef _WIN32
// Fix warnings about deprecated symbols. // Fix warnings about deprecated symbols.
# define FMT_POSIX_CALL(call) ::_##call # 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 # else
# define FMT_POSIX_CALL(call) ::call # define FMT_POSIX_CALL(call) ::call
# endif # endif

View File

@ -333,7 +333,7 @@ class PrintfFormatter : private internal::FormatterBase {
\endrst \endrst
*/ */
explicit PrintfFormatter(const ArgList &al, BasicWriter<Char> &w) explicit PrintfFormatter(const ArgList &al, BasicWriter<Char> &w)
: FormatterBase(al), writer_(w) {} : internal::FormatterBase(al), writer_(w) {}
/** Formats stored arguments and writes the output to the writer. */ /** Formats stored arguments and writes the output to the writer. */
void format(BasicCStringRef<Char> format_str); void format(BasicCStringRef<Char> format_str);
@ -371,7 +371,7 @@ internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s,
(void)s; (void)s;
const char *error = FMT_NULL; const char *error = FMT_NULL;
internal::Arg arg = arg_index == std::numeric_limits<unsigned>::max() ? internal::Arg arg = arg_index == std::numeric_limits<unsigned>::max() ?
next_arg(error) : FormatterBase::get_arg(arg_index - 1, error); next_arg(error) : internal::FormatterBase::get_arg(arg_index - 1, error);
if (error) if (error)
FMT_THROW(FormatError(!*s ? "invalid format string" : error)); FMT_THROW(FormatError(!*s ? "invalid format string" : error));
return arg; return arg;

View File

@ -8,7 +8,7 @@ build = os.environ['BUILD']
config = os.environ['CONFIGURATION'] config = os.environ['CONFIGURATION']
platform = os.environ.get('PLATFORM') platform = os.environ.get('PLATFORM')
path = os.environ['PATH'] 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': if build == 'mingw':
cmake_command.append('-GMinGW Makefiles') cmake_command.append('-GMinGW Makefiles')
build_command = ['mingw32-make', '-j4'] build_command = ['mingw32-make', '-j4']

View File

@ -76,13 +76,6 @@ int result;
MAKE_TEST(test_func) MAKE_TEST(test_func)
typedef char Char; typedef char Char;
FMT_WRAP1(test_func, const char *, 1)
TEST(UtilTest, Wrap1) {
result = 0;
test_func("", 42);
EXPECT_EQ(42, result);
}
MAKE_TEST(test_variadic_void) MAKE_TEST(test_variadic_void)
FMT_VARIADIC_VOID(test_variadic_void, const char *) FMT_VARIADIC_VOID(test_variadic_void, const char *)