CBMC
cout_message.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module:
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
9 #include "cout_message.h"
10 
11 #include <iostream>
12 
13 // clang-format off
14 // clang-format must not re-order includes here to avoid pragma_push/pragma_pop
15 // being moved around
16 #ifdef _WIN32
17 #include <util/pragma_push.def>
18 #ifdef _MSC_VER
19 #pragma warning(disable:4668)
20  // using #if/#elif on undefined macro
21 #pragma warning(disable : 5039)
22 // pointer or reference to potentially throwing function passed to extern C
23 #endif
24 #include <windows.h>
25 #include <fcntl.h>
26 #include <io.h>
27 #include <cstdio>
28 #include <util/pragma_pop.def>
29 #include "unicode.h"
30 // clang-format on
31 #else
32 #include <unistd.h>
33 #endif
34 
36  stream_message_handlert(std::cout)
37 {
38 }
39 
42 {
43 }
44 
46  : always_flush(_always_flush), is_a_tty(false), use_SGR(false)
47 {
48 #ifdef _WIN32
49  HANDLE out_handle=GetStdHandle(STD_OUTPUT_HANDLE);
50 
51  DWORD consoleMode;
52  if(GetConsoleMode(out_handle, &consoleMode))
53  {
54  is_a_tty = true;
55 
56 #ifdef ENABLE_VIRTUAL_TERMINAL_PROCESSING
57  consoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
58  if(SetConsoleMode(out_handle, consoleMode))
59  use_SGR = true;
60 #endif
61  }
62 #else
63  is_a_tty = isatty(STDOUT_FILENO);
64  use_SGR = is_a_tty;
65 #endif
66 }
67 
71 std::string console_message_handlert::command(unsigned c) const
72 {
73  if(!use_SGR)
74  return std::string();
75 
76  return "\x1b[" + std::to_string(c) + 'm';
77 }
78 
80  unsigned level,
81  const std::string &message)
82 {
83  message_handlert::print(level, message);
84 
85  if(verbosity<level)
86  return;
87 
88  #ifdef _WIN32
89  HANDLE out_handle=
90  GetStdHandle((level>1)?STD_OUTPUT_HANDLE:STD_ERROR_HANDLE);
91 
92  // We use UTF16 when we write to the console,
93  // but we write UTF8 otherwise.
94 
95  DWORD consoleMode;
96  if(GetConsoleMode(out_handle, &consoleMode))
97  {
98  // writing to the console
99  std::wstring wide_message=widen(message);
100 
101  DWORD number_written;
102 
103  WriteConsoleW(
104  out_handle, wide_message.c_str(),
105  (DWORD)wide_message.size(), &number_written, NULL);
106 
107  WriteConsoleW(out_handle, L"\r\n", 2, &number_written, NULL);
108  }
109  else
110  {
111  // writing to a file
112 
113  if(level>=4)
114  {
115  std::cout << message << '\n';
116  }
117  else
118  std::cerr << message << '\n';
119  }
120  #else
121  // Messages level 3 or lower go to cerr, messages level 4 or
122  // above go to cout.
123 
124  if(level>=4)
125  {
126  std::cout << message << '\n';
127  }
128  else
129  std::cerr << message << '\n';
130  #endif
131 }
132 
134 {
135  // We flush after messages of level 6 or lower.
136  // We don't for messages of level 7 or higher to improve performance,
137  // in particular when writing to NFS.
138  if(level>=4)
139  {
140  if(level <= 6 || always_flush)
141  std::cout << std::flush;
142  }
143  else
144  std::cerr << std::flush;
145 }
bool use_SGR
true if we use ECMA-48 SGR to render colors
Definition: cout_message.h:62
bool is_a_tty
true if we are outputting to a proper console
Definition: cout_message.h:59
std::string command(unsigned c) const override
Create an ECMA-48 SGR (Select Graphic Rendition) command with given code.
void print(unsigned, const xmlt &) override
Definition: cout_message.h:32
virtual void flush(unsigned level) override
virtual void print(unsigned level, const std::string &message)=0
Definition: message.cpp:60
unsigned verbosity
Definition: message.h:71
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
std::wstring widen(const char *s)
Definition: unicode.cpp:49