CBMC
Loading...
Searching...
No Matches
ui_message.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module:
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
9#include "ui_message.h"
10
11#include "cmdline.h"
12#include "cout_message.h"
13#include "json.h"
14#include "json_irep.h"
15#include "json_stream.h"
16#include "structured_data.h"
17#include "xml.h"
18#include "xml_irep.h"
19
20#include <fstream> // IWYU pragma: keep
21#include <iostream>
22
25 uit __ui,
26 const std::string &program,
27 bool always_flush,
28 timestampert::clockt clock_type)
29 : message_handler(_message_handler),
30 _ui(__ui),
31 always_flush(always_flush),
32 time(timestampert::make(clock_type)),
33 out(std::cout),
34 json_stream(nullptr)
35{
36 switch(_ui)
37 {
38 case uit::PLAIN:
39 break;
40
41 case uit::XML_UI:
42 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
43 << "\n";
44 out << "<cprover>"
45 << "\n";
46
47 {
49 program_xml.name="program";
50 program_xml.data=program;
51
53 }
54 break;
55
56 case uit::JSON_UI:
57 {
59 std::unique_ptr<json_stream_arrayt>(new json_stream_arrayt(out));
60 json_stream->push_back().make_object()["program"] = json_stringt(program);
61 }
62 break;
63 }
64}
65
67 const class cmdlinet &cmdline,
68 const std::string &program)
70 nullptr,
71 cmdline.isset("xml-ui") || cmdline.isset("xml-interface")
72 ? uit::XML_UI
73 : cmdline.isset("json-ui") || cmdline.isset("json-interface")
74 ? uit::JSON_UI
75 : uit::PLAIN,
76 program,
77 cmdline.isset("flush"),
78 cmdline.isset("timestamp") ? cmdline.get_value("timestamp") == "monotonic"
79 ? timestampert::clockt::MONOTONIC
80 : cmdline.get_value("timestamp") == "wall"
81 ? timestampert::clockt::WALL_CLOCK
82 : timestampert::clockt::NONE
83 : timestampert::clockt::NONE)
84{
85 if(get_ui() == uit::PLAIN)
86 {
88 std::make_unique<console_message_handlert>(always_flush);
90 }
91}
92
95 &message_handler, uit::PLAIN, "", false, timestampert::clockt::NONE)
96{
97}
98
100{
101 switch(get_ui())
102 {
103 case uit::XML_UI:
104
105 out << "</cprover>"
106 << "\n";
107 break;
108
109 case uit::JSON_UI:
110 INVARIANT(json_stream, "JSON stream must be initialized before use");
111 json_stream->close();
112 out << '\n';
113 break;
114
115 case uit::PLAIN:
116 break;
117 }
118}
119
120std::string ui_message_handlert::command(unsigned c) const
121{
122 // quote_begin / quote_end render as a single quote on every currently
123 // supported UI. Handled before the message_handler null-check so this
124 // also applies when the handler is constructed via the cmdlinet ctor,
125 // which leaves message_handler null for XML_UI / JSON_UI. We
126 // considered emitting `<quote>` / `</quote>` tags for XML output (see
127 // PR #5696 discussion) but kept single quotes for backwards
128 // compatibility; messages reach the XML serialiser through xmlt::data
129 // and would be escaped, so any tag-based quoting would have to bypass
130 // the message-text plumbing entirely.
131 if(c == '<' || c == '>')
132 return "'";
133
134 if(!message_handler)
135 return std::string();
136
137 // SGR (Select Graphic Rendition) style codes carry no useful
138 // information for machine-consumable output, so the structured UIs
139 // strip them entirely. Centralised here so future additions or
140 // removals of formatting commands only need to be made in one place.
142 return std::string();
143
144 return message_handler->command(c);
145}
146
148{
149 switch(c)
150 {
151 case 0: // reset
152 case 1: // bold
153 case 2: // faint
154 case 3: // italic
155 case 4: // underline
156 case 31: // red
157 case 32: // green
158 case 33: // yellow
159 case 34: // blue
160 case 35: // magenta
161 case 36: // cyan
162 case 91: // bright_red
163 case 92: // bright_green
164 case 93: // bright_yellow
165 case 94: // bright_blue
166 case 95: // bright_magenta
167 case 96: // bright_cyan
168 return true;
169 default:
170 return false;
171 }
172}
173
174const char *ui_message_handlert::level_string(unsigned level)
175{
176 if(level==1)
177 return "ERROR";
178 else if(level==2)
179 return "WARNING";
180 else
181 return "STATUS-MESSAGE";
182}
183
185 unsigned level,
186 const std::string &message)
187{
188 if(verbosity>=level)
189 {
190 switch(get_ui())
191 {
192 case uit::PLAIN:
193 {
194 std::stringstream ss;
195 const std::string timestamp = time->stamp();
196 ss << timestamp << (timestamp.empty() ? "" : " ") << message;
197 message_handler->print(level, ss.str());
198 if(always_flush)
199 message_handler->flush(level);
200 }
201 break;
202
203 case uit::XML_UI:
204 case uit::JSON_UI:
205 {
206 source_locationt location;
207 location.make_nil();
208 print(level, message, location);
209 if(always_flush)
210 flush(level);
211 }
212 break;
213 }
214 }
215}
216
218 unsigned level,
219 const xmlt &data)
220{
221 if(verbosity>=level)
222 {
223 switch(get_ui())
224 {
225 case uit::PLAIN:
226 INVARIANT(false, "Cannot print xml data on PLAIN UI");
227 break;
228 case uit::XML_UI:
229 out << data << '\n';
230 flush(level);
231 break;
232 case uit::JSON_UI:
233 INVARIANT(false, "Cannot print xml data on JSON UI");
234 break;
235 }
236 }
237}
238
240 unsigned level,
241 const jsont &data)
242{
243 if(verbosity>=level)
244 {
245 switch(get_ui())
246 {
247 case uit::PLAIN:
248 INVARIANT(false, "Cannot print json data on PLAIN UI");
249 break;
250 case uit::XML_UI:
251 INVARIANT(false, "Cannot print json data on XML UI");
252 break;
253 case uit::JSON_UI:
254 INVARIANT(json_stream, "JSON stream must be initialized before use");
255 json_stream->push_back(data);
256 flush(level);
257 break;
258 }
259 }
260}
261
263 unsigned level,
264 const std::string &message,
265 const source_locationt &location)
266{
267 message_handlert::print(level, message);
268
269 if(verbosity>=level)
270 {
271 switch(get_ui())
272 {
273 case uit::PLAIN:
275 level, message, location);
276 break;
277
278 case uit::XML_UI:
279 case uit::JSON_UI:
280 {
281 std::string tmp_message(message);
282
283 if(!tmp_message.empty() && *tmp_message.rbegin()=='\n')
284 tmp_message.resize(tmp_message.size()-1);
285
286 const char *type=level_string(level);
287
288 ui_msg(type, tmp_message, location);
289 }
290 break;
291 }
292 }
293}
294
296 const std::string &type,
297 const std::string &msg,
298 const source_locationt &location)
299{
300 switch(get_ui())
301 {
302 case uit::PLAIN:
303 break;
304
305 case uit::XML_UI:
306 xml_ui_msg(type, msg, location);
307 break;
308
309 case uit::JSON_UI:
310 json_ui_msg(type, msg, location);
311 break;
312 }
313}
314
316 const std::string &type,
317 const std::string &msg1,
318 const source_locationt &location)
319{
320 xmlt result;
321 result.name="message";
322
323 if(location.is_not_nil() &&
324 !location.get_file().empty())
325 result.new_element(xml(location));
326
327 result.new_element("text").data=msg1;
328 result.set_attribute("type", type);
329 const std::string timestamp = time->stamp();
330 if(!timestamp.empty())
331 result.set_attribute("timestamp", timestamp);
332
333 out << result;
334 out << '\n';
335}
336
338 const std::string &type,
339 const std::string &msg1,
340 const source_locationt &location)
341{
342 INVARIANT(json_stream, "JSON stream must be initialized before use");
343 json_objectt &result = json_stream->push_back().make_object();
344
345 if(location.is_not_nil() &&
346 !location.get_file().empty())
347 result["sourceLocation"] = json(location);
348
349 result["messageType"] = json_stringt(type);
350 result["messageText"] = json_stringt(msg1);
351 const std::string timestamp = time->stamp();
352 if(!timestamp.empty())
353 result["timestamp"] = json_stringt(timestamp);
354}
355
356void ui_message_handlert::flush(unsigned level)
357{
358 switch(get_ui())
359 {
360 case uit::PLAIN:
361 message_handler->flush(level);
362 break;
363
364 case uit::XML_UI:
365 case uit::JSON_UI:
366 out << std::flush;
367 break;
368 }
369}
370void ui_message_handlert::print(unsigned level, const structured_datat &data)
371{
372 switch(get_ui())
373 {
374 case uit::PLAIN:
375 print(level, to_pretty(data));
376 break;
377 case uit::XML_UI:
378 print(level, to_xml(data));
379 break;
380 case uit::JSON_UI:
381 print(level, to_json(data));
382 break;
383 }
384}
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:566
bool is_not_nil() const
Definition irep.h:372
void make_nil()
Definition irep.h:446
Provides methods for streaming JSON arrays.
Definition json_stream.h:93
Definition json.h:27
json_objectt & make_object()
Definition json.h:436
virtual void print(unsigned level, const std::string &message)=0
Definition message.cpp:60
virtual std::string command(unsigned) const
Create an ECMA-48 SGR (Select Graphic Rendition) command.
Definition message.h:65
unsigned verbosity
Definition message.h:71
virtual void flush(unsigned)=0
const irep_idt & get_file() const
A way of representing nested key/value data.
Timestamp class hierarchy.
Definition timestamper.h:42
clockt
Derived types of timestampert.
Definition timestamper.h:46
void print(unsigned level, const structured_datat &data) override
virtual void json_ui_msg(const std::string &type, const std::string &msg, const source_locationt &location)
const char * level_string(unsigned level)
std::string command(unsigned c) const override
Create an ECMA-48 SGR (Select Graphic Rendition) command.
virtual uit get_ui() const
Definition ui_message.h:33
std::ostream & out
Definition ui_message.h:53
static bool is_sgr_style_command(unsigned c)
Returns true iff c is a Select Graphic Rendition (SGR) parameter value used by messaget for terminal ...
const bool always_flush
Definition ui_message.h:51
message_handlert * message_handler
Definition ui_message.h:49
std::unique_ptr< const timestampert > time
Definition ui_message.h:52
virtual void flush(unsigned level) override
virtual void xml_ui_msg(const std::string &type, const std::string &msg, const source_locationt &location)
std::unique_ptr< json_stream_arrayt > json_stream
Definition ui_message.h:54
virtual ~ui_message_handlert()
ui_message_handlert(const class cmdlinet &, const std::string &program)
virtual void ui_msg(const std::string &type, const std::string &msg, const source_locationt &location)
std::unique_ptr< console_message_handlert > console_message_handler
Definition ui_message.h:48
Definition xml.h:21
xmlt & new_element(const std::string &key)
Definition xml.h:95
void set_attribute(const std::string &attribute, unsigned value)
Definition xml.cpp:198
std::string data
Definition xml.h:39
std::string name
Definition xml.h:39
jsont to_json(const structured_datat &data)
Convert the structured_datat into an json object.
Definition json.cpp:225
STL namespace.
static void json(json_objectT &result, const irep_idt &property_id, const property_infot &property_info)
xmlt xml(const irep_idt &property_id, const property_infot &property_info)
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
std::string to_pretty(const structured_datat &data)
Convert the structured_data into plain text.
time_t time(time_t *tloc)
Definition time.c:13
xmlt to_xml(const structured_datat &data)
Convert the structured_datat into an xml object.
Definition xml.cpp:303