CBMC
console.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Console
4 
5 Author: Daniel Kroening, dkr@amazon.com
6 
7 \*******************************************************************/
8 
9 #include "console.h"
10 
11 #include <cctype>
12 #include <iostream>
13 
14 #ifdef _WIN32
15 # include <io.h>
16 # include <windows.h>
17 # define isatty _isatty
18 # include <util/unicode.h>
19 #else
20 # include <unistd.h>
21 #endif
22 
23 #include <util/invariant.h>
24 #include <util/run.h>
25 #include <util/string_utils.h>
26 
27 #ifdef _WIN32
28 class windows_coutt : public std::streambuf
29 {
30 public:
31  // this turns UTF8 into Windows UTF16
32  std::streamsize xsputn(const char_type *s, std::streamsize n) override
33  {
35  {
36  auto wide_string = widen(std::string(s, n));
37  DWORD number_written;
38  HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
39  WriteConsoleW(
40  h,
41  wide_string.c_str(),
42  (DWORD)wide_string.size(),
43  &number_written,
44  nullptr);
45  }
46  else
47  {
48  std::cout.write(s, n);
49  }
50 
51  return n;
52  }
53 
54  int_type overflow(int_type c) override
55  {
57  std::wcout << wchar_t(c);
58  else
59  std::cout << char(c);
60  return wchar_t(c);
61  }
62 } windows_cout;
63 #endif
64 
65 bool consolet::_is_terminal = false;
66 bool consolet::_use_SGR = false;
67 bool consolet::_init_done = false;
68 bool consolet::_width_is_set = false;
69 std::size_t consolet::_width;
70 std::ostream *consolet::_out = nullptr;
71 std::ostream *consolet::_err = nullptr;
72 
74 {
75  if(_init_done)
76  return;
77 
78  _init_done = true;
79  _is_terminal = isatty(1);
80 
81  _out = &std::cout;
82  _err = &std::cerr;
83 
84 #ifdef _WIN32
85  if(_is_terminal)
86  {
87  HANDLE out_handle = GetStdHandle(STD_OUTPUT_HANDLE);
88 
89  DWORD consoleMode;
90  if(GetConsoleMode(out_handle, &consoleMode))
91  {
92  consoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
93  if(SetConsoleMode(out_handle, consoleMode))
94  _use_SGR = true;
95  }
96 
97  std::cout.rdbuf(&windows_cout);
98  }
99 #else
100  _use_SGR = true;
101 #endif
102 }
103 
104 std::ostream &consolet::blue(std::ostream &str)
105 {
106  if(is_terminal() && use_SGR())
107  return str << "\x1b[34m";
108  else
109  return str;
110 }
111 
112 std::ostream &consolet::cyan(std::ostream &str)
113 {
114  if(is_terminal() && use_SGR())
115  return str << "\x1b[36m";
116  else
117  return str;
118 }
119 
120 std::ostream &consolet::green(std::ostream &str)
121 {
122  if(is_terminal() && use_SGR())
123  return str << "\x1b[32m";
124  else
125  return str;
126 }
127 
128 std::ostream &consolet::red(std::ostream &str)
129 {
130  if(is_terminal() && use_SGR())
131  return str << "\x1b[31m";
132  else
133  return str;
134 }
135 
136 std::ostream &consolet::yellow(std::ostream &str)
137 {
138  if(is_terminal() && use_SGR())
139  return str << "\x1b[33m";
140  else
141  return str;
142 }
143 
144 std::ostream &consolet::orange(std::ostream &str)
145 {
146  if(is_terminal() && use_SGR())
147  return str << "\x1b[38;5;214m";
148  else
149  return str;
150 }
151 
152 std::ostream &consolet::bold(std::ostream &str)
153 {
154  if(is_terminal() && use_SGR())
155  return str << "\x1b[1m";
156  else
157  return str;
158 }
159 
160 std::ostream &consolet::faint(std::ostream &str)
161 {
162  if(is_terminal() && use_SGR())
163  return str << "\x1b[2m";
164  else
165  return str;
166 }
167 
168 std::ostream &consolet::underline(std::ostream &str)
169 {
170  if(is_terminal() && use_SGR())
171  return str << "\x1b[4m";
172  else
173  return str;
174 }
175 
176 std::ostream &consolet::reset(std::ostream &str)
177 {
178  if(is_terminal() && use_SGR())
179  return str << "\x1b[m";
180  else
181  return str;
182 }
183 
184 std::ostream &consolet::cursorup(std::ostream &str)
185 {
187  return str << "\x1b[1A";
188 }
189 
190 std::ostream &consolet::cleareol(std::ostream &str)
191 {
193  return str << "\x1b[0K";
194 }
195 
196 std::size_t consolet::width()
197 {
198  if(_width_is_set)
199  return _width;
200 
201  _width_is_set = true;
202  _width = 80; // default
203 
204  if(is_terminal())
205  {
206 #ifdef _WIN32
207  HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
208  CONSOLE_SCREEN_BUFFER_INFO info;
209  GetConsoleScreenBufferInfo(h, &info);
210  _width = info.srWindow.Right - info.srWindow.Left + 1;
211 #else
212  std::ostringstream width_stream;
213  run("stty", {"stty", "size"}, "", width_stream, "");
214  auto stty_output = split_string(width_stream.str(), ' ');
215  if(
216  stty_output.size() >= 1 && !stty_output[1].empty() &&
217  isdigit(stty_output[1][0]))
218  {
219  auto width_l = atol(stty_output[1].c_str());
220  if(width_l >= 10 && width_l <= 400)
221  _width = width_l;
222  }
223 #endif
224  }
225 
226  return _width;
227 }
228 
230  std::ostream &__console_out,
231  std::ostream &__console_err)
232 {
233  consolet::init();
237  consolet::_out = &__console_out;
238  consolet::_err = &__console_err;
239  consolet::_is_terminal = false;
240 }
241 
243 {
244  consolet::_out = old_out;
245  consolet::_err = old_err;
246  consolet::_is_terminal = old_is_terminal;
247 }
bitvector_typet char_type()
Definition: c_types.cpp:106
std::ostream * old_out
Definition: console.h:78
redirectt(std::ostream &__console_out, std::ostream &__console_err)
Definition: console.cpp:229
std::ostream * old_err
Definition: console.h:78
bool old_is_terminal
Definition: console.h:79
static std::size_t _width
Definition: console.h:86
static bool use_SGR()
Definition: console.h:49
static void init()
Definition: console.cpp:73
static std::ostream & cursorup(std::ostream &)
Definition: console.cpp:184
static std::ostream & yellow(std::ostream &)
Definition: console.cpp:136
static bool _init_done
Definition: console.h:85
static bool _is_terminal
Definition: console.h:83
static std::ostream * _err
Definition: console.h:89
static std::ostream & blue(std::ostream &)
Definition: console.cpp:104
static std::ostream & underline(std::ostream &)
Definition: console.cpp:168
static std::ostream * _out
Definition: console.h:88
static std::ostream & reset(std::ostream &)
Definition: console.cpp:176
static std::ostream & cyan(std::ostream &)
Definition: console.cpp:112
static std::ostream & green(std::ostream &)
Definition: console.cpp:120
static std::size_t width()
Definition: console.cpp:196
static bool is_terminal()
Definition: console.h:43
static std::ostream & faint(std::ostream &)
Definition: console.cpp:160
static std::ostream & bold(std::ostream &)
Definition: console.cpp:152
static std::ostream & red(std::ostream &)
Definition: console.cpp:128
static bool _use_SGR
Definition: console.h:84
static bool _width_is_set
Definition: console.h:87
static std::ostream & orange(std::ostream &)
Definition: console.cpp:144
static std::ostream & cleareol(std::ostream &)
Definition: console.cpp:190
Console.
int isdigit(int c)
Definition: ctype.c:24
int run(const std::string &what, const std::vector< std::string > &argv)
Definition: run.cpp:48
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
long atol(const char *nptr)
Definition: stdlib.c:478
void split_string(const std::string &s, char delim, std::vector< std::string > &result, bool strip, bool remove_empty)
std::wstring widen(const char *s)
Definition: unicode.cpp:49