1    	/*
2    	 Formatting library for C++
3    	
4    	 Copyright (c) 2012 - 2016, Victor Zverovich
5    	 All rights reserved.
6    	
7    	 Redistribution and use in source and binary forms, with or without
8    	 modification, are permitted provided that the following conditions are met:
9    	
10   	 1. Redistributions of source code must retain the above copyright notice, this
11   	    list of conditions and the following disclaimer.
12   	 2. Redistributions in binary form must reproduce the above copyright notice,
13   	    this list of conditions and the following disclaimer in the documentation
14   	    and/or other materials provided with the distribution.
15   	
16   	 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17   	 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18   	 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19   	 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20   	 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21   	 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22   	 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23   	 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24   	 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25   	 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26   	 */
27   	
28   	#include "mp/format.h"
29   	
30   	#include <string.h>
31   	
32   	#include <cctype>
33   	#include <cerrno>
34   	#include <climits>
35   	#include <cmath>
36   	#include <cstdarg>
37   	#include <cstddef>  // for std::ptrdiff_t
38   	
39   	#if defined(_WIN32) && defined(__MINGW32__)
40   	# include <cstring>
41   	#endif
42   	
43   	#if FMT_USE_WINDOWS_H
44   	# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
45   	struct IUnknown; // Workaround for "combaseapi.h(229): error C2187: syntax error: 'identifier' was unexpected here" when using /permissive-
46   	#  include <windows.h>
47   	# else
48   	#  define NOMINMAX
49   	struct IUnknown; // Workaround for "combaseapi.h(229): error C2187: syntax error: 'identifier' was unexpected here" when using /permissive-
50   	#  include <windows.h>
51   	#  undef NOMINMAX
52   	# endif
53   	#endif
54   	
55   	using fmt::internal::Arg;
56   	
57   	#if FMT_EXCEPTIONS
58   	# define FMT_TRY try
59   	# define FMT_CATCH(x) catch (x)
60   	#else
61   	# define FMT_TRY if (true)
62   	# define FMT_CATCH(x) if (false)
63   	#endif
64   	
65   	#ifdef _MSC_VER
66   	# pragma warning(push)
67   	# pragma warning(disable: 4127)  // conditional expression is constant
68   	# pragma warning(disable: 4702)  // unreachable code
69   	// Disable deprecation warning for strerror. The latter is not called but
70   	// MSVC fails to detect it.
71   	# pragma warning(disable: 4996)
72   	#endif
73   	
74   	// Dummy implementations of strerror_r and strerror_s called if corresponding
75   	// system functions are not available.
76   	static inline fmt::internal::Null<> strerror_r(int, char *, ...) {
77   	  return fmt::internal::Null<>();
78   	}
79   	static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
80   	  return fmt::internal::Null<>();
81   	}
82   	
83   	namespace fmt {
84   	
85   	FMT_FUNC internal::RuntimeError::~RuntimeError() throw() {}
86   	FMT_FUNC FormatError::~FormatError() throw() {}
87   	FMT_FUNC SystemError::~SystemError() throw() {}
88   	
89   	namespace {
90   	
91   	#ifndef _MSC_VER
92   	# define FMT_SNPRINTF snprintf
93   	#else  // _MSC_VER
94   	inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
95   	  va_list args;
96   	  va_start(args, format);
97   	  int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
98   	  va_end(args);
99   	  return result;
100  	}
101  	# define FMT_SNPRINTF fmt::fmt_snprintf
102  	#endif  // _MSC_VER
103  	
104  	#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
105  	# define FMT_SWPRINTF snwprintf
106  	#else
107  	# define FMT_SWPRINTF swprintf
108  	#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
109  	
110  	// Checks if a value fits in int - used to avoid warnings about comparing
111  	// signed and unsigned integers.
112  	template <bool IsSigned>
113  	struct IntChecker {
114  	  template <typename T>
115  	  static bool fits_in_int(T value) {
116  	    unsigned max = INT_MAX;
117  	    return value <= max;
118  	  }
119  	  static bool fits_in_int(bool) { return true; }
120  	};
121  	
122  	template <>
123  	struct IntChecker<true> {
124  	  template <typename T>
125  	  static bool fits_in_int(T value) {
126  	    return value >= INT_MIN && value <= INT_MAX;
127  	  }
128  	  static bool fits_in_int(int) { return true; }
129  	};
130  	
131  	const char RESET_COLOR[] = "\x1b[0m";
132  	
133  	typedef void (*FormatFunc)(Writer &, int, StringRef);
134  	
135  	// Portable thread-safe version of strerror.
136  	// Sets buffer to point to a string describing the error code.
137  	// This can be either a pointer to a string stored in buffer,
138  	// or a pointer to some static immutable string.
139  	// Returns one of the following values:
140  	//   0      - success
141  	//   ERANGE - buffer is not large enough to store the error message
142  	//   other  - failure
143  	// Buffer should be at least of size 1.
144  	int safe_strerror(
145  	    int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
146  	  FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer");
147  	
148  	  class StrError {
149  	   private:
150  	    int error_code_;
151  	    char *&buffer_;
152  	    std::size_t buffer_size_;
153  	
154  	    // A noop assignment operator to avoid bogus warnings.
155  	    void operator=(const StrError &) {}
156  	
157  	    // Handle the result of XSI-compliant version of strerror_r.
158  	    int handle(int result) {
159  	      // glibc versions before 2.13 return result in errno.
160  	      return result == -1 ? errno : result;
161  	    }
162  	
163  	    // Handle the result of GNU-specific version of strerror_r.
164  	    int handle(char *message) {
165  	      // If the buffer is full then the message is probably truncated.
166  	      if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
167  	        return ERANGE;
168  	      buffer_ = message;
169  	      return 0;
170  	    }
171  	
172  	    // Handle the case when strerror_r is not available.
173  	    int handle(internal::Null<>) {
174  	      return fallback(strerror_s(buffer_, buffer_size_, error_code_));
175  	    }
176  	
177  	    // Fallback to strerror_s when strerror_r is not available.
178  	    int fallback(int result) {
179  	      // If the buffer is full then the message is probably truncated.
180  	      return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
181  	            ERANGE : result;
182  	    }
183  	
184  	    // Fallback to strerror if strerror_r and strerror_s are not available.
185  	    int fallback(internal::Null<>) {
186  	      errno = 0;
187  	      buffer_ = strerror(error_code_);
188  	      return errno;
189  	    }
190  	
191  	   public:
192  	    StrError(int err_code, char *&buf, std::size_t buf_size)
193  	      : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
194  	
195  	    int run() {
196  	      strerror_r(0, 0, "");  // Suppress a warning about unused strerror_r.
197  	      return handle(strerror_r(error_code_, buffer_, buffer_size_));
198  	    }
199  	  };
200  	  return StrError(error_code, buffer, buffer_size).run();
201  	}
202  	
203  	void format_error_code(Writer &out, int error_code,
204  	                       StringRef message) FMT_NOEXCEPT {
205  	  // Report error code making sure that the output fits into
206  	  // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
207  	  // bad_alloc.
208  	  out.clear();
209  	  static const char SEP[] = ": ";
210  	  static const char ERROR_STR[] = "error ";
211  	  // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
212  	  std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
213  	  typedef internal::IntTraits<int>::MainType MainType;
214  	  MainType abs_value = static_cast<MainType>(error_code);
215  	  if (internal::is_negative(error_code)) {
216  	    abs_value = 0 - abs_value;
217  	    ++error_code_size;
218  	  }
219  	  error_code_size += internal::count_digits(abs_value);
220  	  if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size)
221  	    out << message << SEP;
222  	  out << ERROR_STR << error_code;
223  	  assert(out.size() <= internal::INLINE_BUFFER_SIZE);
224  	}
225  	
226  	void report_error(FormatFunc func, int error_code,
227  	                  StringRef message) FMT_NOEXCEPT {
228  	  MemoryWriter full_message;
229  	  func(full_message, error_code, message);
230  	  // Use Writer::data instead of Writer::c_str to avoid potential memory
231  	  // allocation.
232  	  std::fwrite(full_message.data(), full_message.size(), 1, stderr);
233  	  std::fputc('\n', stderr);
234  	}
235  	
236  	// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
237  	class IsZeroInt : public ArgVisitor<IsZeroInt, bool> {
238  	 public:
239  	  template <typename T>
240  	  bool visit_any_int(T value) { return value == 0; }
241  	};
242  	
243  	// Checks if an argument is a valid printf width specifier and sets
244  	// left alignment if it is negative.
245  	class WidthHandler : public ArgVisitor<WidthHandler, unsigned> {
246  	 private:
247  	  FormatSpec &spec_;
248  	
249  	  FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
250  	
251  	 public:
252  	  explicit WidthHandler(FormatSpec &spec) : spec_(spec) {}
253  	
254  	  void report_unhandled_arg() {
255  	    FMT_THROW(FormatError("width is not integer"));
256  	  }
257  	
258  	  template <typename T>
259  	  unsigned visit_any_int(T value) {
260  	    typedef typename internal::IntTraits<T>::MainType UnsignedType;
261  	    UnsignedType width = static_cast<UnsignedType>(value);
262  	    if (internal::is_negative(value)) {
263  	      spec_.align_ = ALIGN_LEFT;
264  	      width = 0 - width;
265  	    }
266  	    if (width > INT_MAX)
267  	      FMT_THROW(FormatError("number is too big"));
268  	    return static_cast<unsigned>(width);
269  	  }
270  	};
271  	
272  	class PrecisionHandler : public ArgVisitor<PrecisionHandler, int> {
273  	 public:
274  	  void report_unhandled_arg() {
275  	    FMT_THROW(FormatError("precision is not integer"));
276  	  }
277  	
278  	  template <typename T>
279  	  int visit_any_int(T value) {
280  	    if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
281  	      FMT_THROW(FormatError("number is too big"));
282  	    return static_cast<int>(value);
283  	  }
284  	};
285  	
286  	template <typename T, typename U>
287  	struct is_same {
288  	  enum { value = 0 };
289  	};
290  	
291  	template <typename T>
292  	struct is_same<T, T> {
293  	  enum { value = 1 };
294  	};
295  	
296  	// An argument visitor that converts an integer argument to T for printf,
297  	// if T is an integral type. If T is void, the argument is converted to
298  	// corresponding signed or unsigned type depending on the type specifier:
299  	// 'd' and 'i' - signed, other - unsigned)
300  	template <typename T = void>
301  	class ArgConverter : public ArgVisitor<ArgConverter<T>, void> {
302  	 private:
303  	  internal::Arg &arg_;
304  	  wchar_t type_;
305  	
306  	  FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
307  	
308  	 public:
309  	  ArgConverter(internal::Arg &arg, wchar_t type)
310  	    : arg_(arg), type_(type) {}
311  	
312  	  void visit_bool(bool value) {
313  	    if (type_ != 's')
314  	      visit_any_int(value);
315  	  }
316  	
317  	  template <typename U>
318  	  void visit_any_int(U value) {
319  	    bool is_signed = type_ == 'd' || type_ == 'i';
320  	    using internal::Arg;
321  	    typedef typename internal::Conditional<
322  	        is_same<T, void>::value, U, T>::type TargetType;
323  	    if (sizeof(TargetType) <= sizeof(int)) {
324  	      // Extra casts are used to silence warnings.
325  	      if (is_signed) {
326  	        arg_.type = Arg::INT;
327  	        arg_.int_value = static_cast<int>(static_cast<TargetType>(value));
328  	      } else {
329  	        arg_.type = Arg::UINT;
330  	        typedef typename internal::MakeUnsigned<TargetType>::Type Unsigned;
331  	        arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value));
332  	      }
333  	    } else {
334  	      if (is_signed) {
335  	        arg_.type = Arg::LONG_LONG;
336  	        // glibc's printf doesn't sign extend arguments of smaller types:
337  	        //   std::printf("%lld", -42);  // prints "4294967254"
338  	        // but we don't have to do the same because it's a UB.
339  	        arg_.long_long_value = static_cast<LongLong>(value);
340  	      } else {
341  	        arg_.type = Arg::ULONG_LONG;
342  	        arg_.ulong_long_value =
343  	            static_cast<typename internal::MakeUnsigned<U>::Type>(value);
344  	      }
345  	    }
346  	  }
347  	};
348  	
349  	// Converts an integer argument to char for printf.
350  	class CharConverter : public ArgVisitor<CharConverter, void> {
351  	 private:
352  	  internal::Arg &arg_;
353  	
354  	  FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
355  	
356  	 public:
357  	  explicit CharConverter(internal::Arg &arg) : arg_(arg) {}
358  	
359  	  template <typename T>
360  	  void visit_any_int(T value) {
361  	    arg_.type = internal::Arg::CHAR;
362  	    arg_.int_value = static_cast<char>(value);
363  	  }
364  	};
365  	}  // namespace
366  	
367  	namespace internal {
368  	
369  	template <typename Char>
370  	class PrintfArgFormatter :
371  	    public ArgFormatterBase<PrintfArgFormatter<Char>, Char> {
372  	
373  	  void write_null_pointer() {
374  	    this->spec().type_ = 0;
375  	    this->write("(nil)");
376  	  }
377  	
378  	  typedef ArgFormatterBase<PrintfArgFormatter<Char>, Char> Base;
379  	
380  	 public:
381  	  PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
382  	  : ArgFormatterBase<PrintfArgFormatter<Char>, Char>(w, s) {}
383  	
384  	  void visit_bool(bool value) {
385  	    FormatSpec &fmt_spec = this->spec();
386  	    if (fmt_spec.type_ != 's')
387  	      return this->visit_any_int(value);
388  	    fmt_spec.type_ = 0;
389  	    this->write(value);
390  	  }
391  	
392  	  void visit_char(int value) {
393  	    const FormatSpec &fmt_spec = this->spec();
394  	    BasicWriter<Char> &w = this->writer();
395  	    if (fmt_spec.type_ && fmt_spec.type_ != 'c')
396  	      w.write_int(value, fmt_spec);
397  	    typedef typename BasicWriter<Char>::CharPtr CharPtr;
398  	    CharPtr out = CharPtr();
399  	    if (fmt_spec.width_ > 1) {
400  	      Char fill = ' ';
401  	      out = w.grow_buffer(fmt_spec.width_);
402  	      if (fmt_spec.align_ != ALIGN_LEFT) {
403  	        std::fill_n(out, fmt_spec.width_ - 1, fill);
404  	        out += fmt_spec.width_ - 1;
405  	      } else {
406  	        std::fill_n(out + 1, fmt_spec.width_ - 1, fill);
407  	      }
408  	    } else {
409  	      out = w.grow_buffer(1);
410  	    }
411  	    *out = static_cast<Char>(value);
412  	  }
413  	
414  	  void visit_cstring(const char *value) {
415  	    if (value)
416  	      Base::visit_cstring(value);
417  	    else if (this->spec().type_ == 'p')
418  	      write_null_pointer();
419  	    else
420  	      this->write("(null)");
421  	  }
422  	
423  	  void visit_pointer(const void *value) {
424  	    if (value)
425  	      return Base::visit_pointer(value);
426  	    this->spec().type_ = 0;
427  	    write_null_pointer();
428  	  }
429  	
430  	  void visit_custom(Arg::CustomValue c) {
431  	    BasicFormatter<Char> formatter(ArgList(), this->writer());
432  	    const Char format_str[] = {'}', 0};
433  	    const Char *format = format_str;
434  	    c.format(&formatter, c.value, &format);
435  	  }
436  	};
437  	}  // namespace internal
438  	}  // namespace fmt
439  	
440  	FMT_FUNC void fmt::SystemError::init(
441  	    int err_code, CStringRef format_str, ArgList args) {
442  	  error_code_ = err_code;
443  	  MemoryWriter w;
444  	  internal::format_system_error(w, err_code, format(format_str, args));
445  	  std::runtime_error &base = *this;
446  	  base = std::runtime_error(w.str());
447  	}
448  	
449  	template <typename T>
450  	int fmt::internal::CharTraits<char>::format_float(
451  	    char *buffer, std::size_t size, const char *format,
452  	    unsigned width, int precision, T value) {
453  	  if (width == 0) {
454  	    return precision < 0 ?
455  	        FMT_SNPRINTF(buffer, size, format, value) :
456  	        FMT_SNPRINTF(buffer, size, format, precision, value);
457  	  }
458  	  return precision < 0 ?
459  	      FMT_SNPRINTF(buffer, size, format, width, value) :
460  	      FMT_SNPRINTF(buffer, size, format, width, precision, value);
461  	}
462  	
463  	template <typename T>
464  	int fmt::internal::CharTraits<wchar_t>::format_float(
465  	    wchar_t *buffer, std::size_t size, const wchar_t *format,
466  	    unsigned width, int precision, T value) {
467  	  if (width == 0) {
468  	    return precision < 0 ?
469  	        FMT_SWPRINTF(buffer, size, format, value) :
470  	        FMT_SWPRINTF(buffer, size, format, precision, value);
471  	  }
472  	  return precision < 0 ?
473  	      FMT_SWPRINTF(buffer, size, format, width, value) :
474  	      FMT_SWPRINTF(buffer, size, format, width, precision, value);
475  	}
476  	
477  	template <typename T>
478  	const char fmt::internal::BasicData<T>::DIGITS[] =
479  	    "0001020304050607080910111213141516171819"
480  	    "2021222324252627282930313233343536373839"
481  	    "4041424344454647484950515253545556575859"
482  	    "6061626364656667686970717273747576777879"
483  	    "8081828384858687888990919293949596979899";
484  	
485  	#define FMT_POWERS_OF_10(factor) \
486  	  factor * 10, \
487  	  factor * 100, \
488  	  factor * 1000, \
489  	  factor * 10000, \
490  	  factor * 100000, \
491  	  factor * 1000000, \
492  	  factor * 10000000, \
493  	  factor * 100000000, \
494  	  factor * 1000000000
495  	
496  	template <typename T>
497  	const uint32_t fmt::internal::BasicData<T>::POWERS_OF_10_32[] = {
498  	  0, FMT_POWERS_OF_10(1)
499  	};
500  	
501  	template <typename T>
502  	const uint64_t fmt::internal::BasicData<T>::POWERS_OF_10_64[] = {
503  	  0,
504  	  FMT_POWERS_OF_10(1),
505  	  FMT_POWERS_OF_10(fmt::ULongLong(1000000000)),
506  	  // Multiply several constants instead of using a single long long constant
507  	  // to avoid warnings about C++98 not supporting long long.
508  	  fmt::ULongLong(1000000000) * fmt::ULongLong(1000000000) * 10
509  	};
510  	
511  	FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) {
512  	  (void)type;
513  	  if (std::isprint(static_cast<unsigned char>(code))) {
514  	    FMT_THROW(fmt::FormatError(
515  	        fmt::format("unknown format code '{}' for {}", code, type)));
516  	  }
517  	  FMT_THROW(fmt::FormatError(
518  	      fmt::format("unknown format code '\\x{:02x}' for {}",
519  	        static_cast<unsigned>(code), type)));
520  	}
521  	
522  	#if FMT_USE_WINDOWS_H
523  	
524  	FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
525  	  static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
526  	  if (s.size() > INT_MAX)
527  	    FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
528  	  int s_size = static_cast<int>(s.size());
529  	  int length = MultiByteToWideChar(
530  	      CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0);
531  	  if (length == 0)
532  	    FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
533  	  buffer_.resize(length + 1);
534  	  length = MultiByteToWideChar(
535  	    CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
536  	  if (length == 0)
537  	    FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
538  	  buffer_[length] = 0;
539  	}
540  	
541  	FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
542  	  if (int error_code = convert(s)) {
543  	    FMT_THROW(WindowsError(error_code,
544  	        "cannot convert string from UTF-16 to UTF-8"));
545  	  }
546  	}
547  	
548  	FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
549  	  if (s.size() > INT_MAX)
550  	    return ERROR_INVALID_PARAMETER;
551  	  int s_size = static_cast<int>(s.size());
552  	  int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0);
553  	  if (length == 0)
554  	    return GetLastError();
555  	  buffer_.resize(length + 1);
556  	  length = WideCharToMultiByte(
557  	    CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0);
558  	  if (length == 0)
559  	    return GetLastError();
560  	  buffer_[length] = 0;
561  	  return 0;
562  	}
563  	
564  	FMT_FUNC void fmt::WindowsError::init(
565  	    int err_code, CStringRef format_str, ArgList args) {
566  	  error_code_ = err_code;
567  	  MemoryWriter w;
568  	  internal::format_windows_error(w, err_code, format(format_str, args));
569  	  std::runtime_error &base = *this;
570  	  base = std::runtime_error(w.str());
571  	}
572  	
573  	FMT_FUNC void fmt::internal::format_windows_error(
574  	    fmt::Writer &out, int error_code,
575  	    fmt::StringRef message) FMT_NOEXCEPT {
576  	  FMT_TRY {
577  	    MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer;
578  	    buffer.resize(INLINE_BUFFER_SIZE);
579  	    for (;;) {
580  	      wchar_t *system_message = &buffer[0];
581  	      int result = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
582  	                                  0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
583  	                                  system_message, static_cast<uint32_t>(buffer.size()), 0);
584  	      if (result != 0) {
585  	        UTF16ToUTF8 utf8_message;
586  	        if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
587  	          out << message << ": " << utf8_message;
588  	          return;
589  	        }
590  	        break;
591  	      }
592  	      if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
593  	        break;  // Can't get error message, report error code instead.
594  	      buffer.resize(buffer.size() * 2);
595  	    }
596  	  } FMT_CATCH(...) {}
597  	  fmt::format_error_code(out, error_code, message);  // 'fmt::' is for bcc32.
598  	}
599  	
600  	#endif  // FMT_USE_WINDOWS_H
601  	
602  	FMT_FUNC void fmt::internal::format_system_error(
603  	    fmt::Writer &out, int error_code,
604  	    fmt::StringRef message) FMT_NOEXCEPT {
605  	  FMT_TRY {
606  	    MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer;
607  	    buffer.resize(INLINE_BUFFER_SIZE);
608  	    for (;;) {
609  	      char *system_message = &buffer[0];
610  	      int result = safe_strerror(error_code, system_message, buffer.size());
611  	      if (result == 0) {
612  	        out << message << ": " << system_message;
613  	        return;
614  	      }
615  	      if (result != ERANGE)
616  	        break;  // Can't get error message, report error code instead.
617  	      buffer.resize(buffer.size() * 2);
618  	    }
619  	  } FMT_CATCH(...) {}
620  	  fmt::format_error_code(out, error_code, message);  // 'fmt::' is for bcc32.
621  	}
622  	
623  	template <typename Char>
624  	void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
625  	  if (!map_.empty())
626  	    return;
627  	  typedef internal::NamedArg<Char> NamedArg;
628  	  const NamedArg *named_arg = 0;
629  	  bool use_values =
630  	      args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
631  	  if (use_values) {
632  	    for (unsigned i = 0;/*nothing*/; ++i) {
633  	      internal::Arg::Type arg_type = args.type(i);
634  	      switch (arg_type) {
635  	      case internal::Arg::NONE:
636  	        return;
637  	      case internal::Arg::NAMED_ARG:
638  	        named_arg = static_cast<const NamedArg*>(args.values_[i].pointer);
639  	        map_.push_back(Pair(named_arg->name, *named_arg));
640  	        break;
641  	      default:
642  	        /*nothing*/;
643  	      }
644  	    }
645  	    return;
646  	  }
647  	  for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) {
648  	    internal::Arg::Type arg_type = args.type(i);
649  	    if (arg_type == internal::Arg::NAMED_ARG) {
650  	      named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
651  	      map_.push_back(Pair(named_arg->name, *named_arg));
652  	    }
653  	  }
654  	  for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) {
655  	    switch (args.args_[i].type) {
656  	    case internal::Arg::NONE:
657  	      return;
658  	    case internal::Arg::NAMED_ARG:
659  	      named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
660  	      map_.push_back(Pair(named_arg->name, *named_arg));
661  	      break;
662  	    default:
663  	      /*nothing*/;
664  	    }
665  	  }
666  	}
667  	
668  	template <typename Char>
669  	void fmt::internal::FixedBuffer<Char>::grow(std::size_t) {
670  	  FMT_THROW(std::runtime_error("buffer overflow"));
671  	}
672  	
673  	FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
674  	    unsigned arg_index, const char *&error) {
675  	  Arg arg = args_[arg_index];
676  	  switch (arg.type) {
677  	  case Arg::NONE:
678  	    error = "argument index out of range";
679  	    break;
680  	  case Arg::NAMED_ARG:
681  	    arg = *static_cast<const internal::Arg*>(arg.pointer);
682  	    break;
683  	  default:
684  	    /*nothing*/;
685  	  }
686  	  return arg;
687  	}
688  	
689  	template <typename Char>
690  	void fmt::internal::PrintfFormatter<Char>::parse_flags(
691  	    FormatSpec &spec, const Char *&s) {
692  	  for (;;) {
(1) Event switch_selector_expr_is_constant: selector expression is constant
(2) Event caretline: ^
Also see events: [template_instantiation_context][template_instantiation_context]
693  	    switch (*s++) {
694  	      case '-':
695  	        spec.align_ = ALIGN_LEFT;
696  	        break;
697  	      case '+':
698  	        spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
699  	        break;
700  	      case '0':
701  	        spec.fill_ = '0';
702  	        break;
703  	      case ' ':
704  	        spec.flags_ |= SIGN_FLAG;
705  	        break;
706  	      case '#':
707  	        spec.flags_ |= HASH_FLAG;
708  	        break;
709  	      default:
710  	        --s;
711  	        return;
712  	    }
713  	  }
714  	}
715  	
716  	template <typename Char>
717  	Arg fmt::internal::PrintfFormatter<Char>::get_arg(
718  	    const Char *s, unsigned arg_index) {
719  	  (void)s;
720  	  const char *error = 0;
721  	  Arg arg = arg_index == UINT_MAX ?
722  	    next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
723  	  if (error)
724  	    FMT_THROW(FormatError(!*s ? "invalid format string" : error));
725  	  return arg;
726  	}
727  	
728  	template <typename Char>
729  	unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
730  	  const Char *&s, FormatSpec &spec) {
731  	  unsigned arg_index = UINT_MAX;
732  	  Char c = *s;
733  	  if (c >= '0' && c <= '9') {
734  	    // Parse an argument index (if followed by '$') or a width possibly
735  	    // preceded with '0' flag(s).
736  	    unsigned value = parse_nonnegative_int(s);
737  	    if (*s == '$') {  // value is an argument index
738  	      ++s;
739  	      arg_index = value;
740  	    } else {
741  	      if (c == '0')
742  	        spec.fill_ = '0';
743  	      if (value != 0) {
744  	        // Nonzero value means that we parsed width and don't need to
745  	        // parse it or flags again, so return now.
746  	        spec.width_ = value;
747  	        return arg_index;
748  	      }
749  	    }
750  	  }
751  	  parse_flags(spec, s);
752  	  // Parse width.
753  	  if (*s >= '0' && *s <= '9') {
754  	    spec.width_ = parse_nonnegative_int(s);
755  	  } else if (*s == '*') {
756  	    ++s;
757  	    spec.width_ = fmt::WidthHandler(spec).visit(get_arg(s));
758  	  }
759  	  return arg_index;
760  	}
761  	
762  	template <typename Char>
763  	void fmt::internal::PrintfFormatter<Char>::format(
764  	    BasicWriter<Char> &writer, BasicCStringRef<Char> format_str) {
765  	  const Char *start = format_str.c_str();
766  	  const Char *s = start;
767  	  while (*s) {
768  	    Char c = *s++;
769  	    if (c != '%') continue;
770  	    if (*s == c) {
771  	      write(writer, start, s);
772  	      start = ++s;
773  	      continue;
774  	    }
775  	    write(writer, start, s - 1);
776  	
777  	    FormatSpec spec;
778  	    spec.align_ = ALIGN_RIGHT;
779  	
780  	    // Parse argument index, flags and width.
(3) Event template_instantiation_context: instantiation of "unsigned int fmt::internal::PrintfFormatter<Char>::parse_header(const Char *&, fmt::FormatSpec &) [with Char=char]" at line 781
Also see events: [switch_selector_expr_is_constant][caretline][template_instantiation_context]
781  	    unsigned arg_index = parse_header(s, spec);
782  	
783  	    // Parse precision.
784  	    if (*s == '.') {
785  	      ++s;
786  	      if ('0' <= *s && *s <= '9') {
787  	        spec.precision_ = static_cast<int>(parse_nonnegative_int(s));
788  	      } else if (*s == '*') {
789  	        ++s;
790  	        spec.precision_ = fmt::PrecisionHandler().visit(get_arg(s));
791  	      }
792  	    }
793  	
794  	    Arg arg = get_arg(s, arg_index);
795  	    if (spec.flag(HASH_FLAG) && fmt::IsZeroInt().visit(arg))
796  	      spec.flags_ &= ~to_unsigned<int>(HASH_FLAG);
797  	    if (spec.fill_ == '0') {
798  	      if (arg.type <= Arg::LAST_NUMERIC_TYPE)
799  	        spec.align_ = ALIGN_NUMERIC;
800  	      else
801  	        spec.fill_ = ' ';  // Ignore '0' flag for non-numeric types.
802  	    }
803  	
804  	    // Parse length and convert the argument to the required type.
805  	    switch (*s++) {
806  	    case 'h':
807  	      if (*s == 'h')
808  	        fmt::ArgConverter<signed char>(arg, *++s).visit(arg);
809  	      else
810  	        fmt::ArgConverter<short>(arg, *s).visit(arg);
811  	      break;
812  	    case 'l':
813  	      if (*s == 'l')
814  	        fmt::ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
815  	      else
816  	        fmt::ArgConverter<long>(arg, *s).visit(arg);
817  	      break;
818  	    case 'j':
819  	      fmt::ArgConverter<intmax_t>(arg, *s).visit(arg);
820  	      break;
821  	    case 'z':
822  	      fmt::ArgConverter<std::size_t>(arg, *s).visit(arg);
823  	      break;
824  	    case 't':
825  	      fmt::ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg);
826  	      break;
827  	    case 'L':
828  	      // printf produces garbage when 'L' is omitted for long double, no
829  	      // need to do the same.
830  	      break;
831  	    default:
832  	      --s;
833  	      fmt::ArgConverter<void>(arg, *s).visit(arg);
834  	    }
835  	
836  	    // Parse type.
837  	    if (!*s)
838  	      FMT_THROW(FormatError("invalid format string"));
839  	    spec.type_ = static_cast<char>(*s++);
840  	    if (arg.type <= Arg::LAST_INTEGER_TYPE) {
841  	      // Normalize type.
842  	      switch (spec.type_) {
843  	      case 'i': case 'u':
844  	        spec.type_ = 'd';
845  	        break;
846  	      case 'c':
847  	        // TODO: handle wchar_t
848  	        fmt::CharConverter(arg).visit(arg);
849  	        break;
850  	      }
851  	    }
852  	
853  	    start = s;
854  	
855  	    // Format argument.
856  	    internal::PrintfArgFormatter<Char>(writer, spec).visit(arg);
857  	  }
858  	  write(writer, start, s);
859  	}
860  	
861  	FMT_FUNC void fmt::report_system_error(
862  	    int error_code, fmt::StringRef message) FMT_NOEXCEPT {
863  	  // 'fmt::' is for bcc32.
864  	  fmt::report_error(internal::format_system_error, error_code, message);
865  	}
866  	
867  	#if FMT_USE_WINDOWS_H
868  	FMT_FUNC void fmt::report_windows_error(
869  	    int error_code, fmt::StringRef message) FMT_NOEXCEPT {
870  	  // 'fmt::' is for bcc32.
871  	  fmt::report_error(internal::format_windows_error, error_code, message);
872  	}
873  	#endif
874  	
875  	FMT_FUNC void fmt::print(std::FILE *f, CStringRef format_str, ArgList args) {
876  	  MemoryWriter w;
877  	  w.write(format_str, args);
878  	  std::fwrite(w.data(), 1, w.size(), f);
879  	}
880  	
881  	FMT_FUNC void fmt::print(CStringRef format_str, ArgList args) {
882  	  print(stdout, format_str, args);
883  	}
884  	
885  	FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) {
886  	  char escape[] = "\x1b[30m";
887  	  escape[3] = static_cast<char>('0' + c);
888  	  std::fputs(escape, stdout);
889  	  print(format, args);
890  	  std::fputs(RESET_COLOR, stdout);
891  	}
892  	
893  	FMT_FUNC int fmt::fprintf(std::FILE *f, CStringRef format, ArgList args) {
894  	  MemoryWriter w;
895  	  printf(w, format, args);
896  	  std::size_t size = w.size();
897  	  return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
898  	}
899  	
900  	#ifndef FMT_HEADER_ONLY
901  	
902  	template struct fmt::internal::BasicData<void>;
903  	
904  	// Explicit instantiations for char.
905  	
906  	template void fmt::internal::FixedBuffer<char>::grow(std::size_t);
907  	
908  	template void fmt::internal::ArgMap<char>::init(const fmt::ArgList &args);
909  	
910  	template void fmt::internal::PrintfFormatter<char>::format(
911  	  BasicWriter<char> &writer, CStringRef format);
912  	
913  	template int fmt::internal::CharTraits<char>::format_float(
914  	    char *buffer, std::size_t size, const char *format,
915  	    unsigned width, int precision, double value);
916  	
917  	template int fmt::internal::CharTraits<char>::format_float(
918  	    char *buffer, std::size_t size, const char *format,
919  	    unsigned width, int precision, long double value);
920  	
921  	// Explicit instantiations for wchar_t.
922  	
923  	template void fmt::internal::FixedBuffer<wchar_t>::grow(std::size_t);
924  	
925  	template void fmt::internal::ArgMap<wchar_t>::init(const fmt::ArgList &args);
926  	
927  	template void fmt::internal::PrintfFormatter<wchar_t>::format(
928  	    BasicWriter<wchar_t> &writer, WCStringRef format);
929  	
930  	template int fmt::internal::CharTraits<wchar_t>::format_float(
931  	    wchar_t *buffer, std::size_t size, const wchar_t *format,
932  	    unsigned width, int precision, double value);
933  	
934  	template int fmt::internal::CharTraits<wchar_t>::format_float(
935  	    wchar_t *buffer, std::size_t size, const wchar_t *format,
936  	    unsigned width, int precision, long double value);
937  	
938  	#endif  // FMT_HEADER_ONLY
939  	
940  	#ifdef _MSC_VER
941  	# pragma warning(pop)
942  	#endif
943