CBMC
show_on_source.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: goto-analyzer
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
9 #include "show_on_source.h"
10 
11 #include <util/message.h>
12 #include <util/unicode.h>
13 
14 #include <analyses/ai.h>
15 
16 #include <fstream>
17 
20 static std::optional<std::string>
22 {
23  const auto abstract_state = ai.abstract_state_before(loc);
24  if(abstract_state->is_top())
25  return {};
26 
27  if(loc->source_location().get_line().empty())
28  return {};
29 
30  return loc->source_location().full_path();
31 }
32 
34 static std::set<std::string>
35 get_source_files(const goto_modelt &goto_model, const ai_baset &ai)
36 {
37  std::set<std::string> files;
38 
39  for(const auto &f : goto_model.goto_functions.function_map)
40  {
41  forall_goto_program_instructions(i_it, f.second.body)
42  {
43  const auto file = show_location(ai, i_it);
44  if(file.has_value())
45  files.insert(file.value());
46  }
47  }
48 
49  return files;
50 }
51 
53 static void print_with_indent(
54  const std::string &src,
55  const std::string &indent_line,
56  std::ostream &out)
57 {
58  const std::size_t p = indent_line.find_first_not_of(" \t");
59  const std::string indent =
60  p == std::string::npos ? std::string() : std::string(indent_line, 0, p);
61  std::istringstream in(src);
62  std::string src_line;
63  while(std::getline(in, src_line))
64  out << indent << src_line << '\n';
65 }
66 
69  const std::string &source_file,
70  const goto_modelt &goto_model,
71  const ai_baset &ai,
72  message_handlert &message_handler)
73 {
74  std::ifstream in(widen_if_needed(source_file));
75 
76  messaget message(message_handler);
77 
78  if(!in)
79  {
80  message.warning() << "Failed to open '" << source_file << "'"
81  << messaget::eom;
82  return;
83  }
84 
85  std::map<std::size_t, ai_baset::locationt> line_map;
86 
87  // Collect line numbers with non-top abstract states.
88  // We pick the _first_ state for each line.
89  for(const auto &f : goto_model.goto_functions.function_map)
90  {
91  forall_goto_program_instructions(i_it, f.second.body)
92  {
93  const auto file = show_location(ai, i_it);
94  if(file.has_value() && file.value() == source_file)
95  {
96  const std::size_t line_no =
97  stoull(id2string(i_it->source_location().get_line()));
98  if(line_map.find(line_no) == line_map.end())
99  line_map[line_no] = i_it;
100  }
101  }
102  }
103 
104  // now print file to message handler
105  const namespacet ns(goto_model.symbol_table);
106 
107  std::string line;
108  for(std::size_t line_no = 1; std::getline(in, line); line_no++)
109  {
110  const auto map_it = line_map.find(line_no);
111  if(map_it != line_map.end())
112  {
113  auto abstract_state = ai.abstract_state_before(map_it->second);
114  std::ostringstream state_str;
115  abstract_state->output(state_str, ai, ns);
116  if(!state_str.str().empty())
117  {
118  message.result() << messaget::blue;
119  print_with_indent(state_str.str(), line, message.result());
120  message.result() << messaget::reset;
121  }
122  }
123 
124  message.result() << line << messaget::eom;
125  }
126 }
127 
130  const goto_modelt &goto_model,
131  const ai_baset &ai,
132  message_handlert &message_handler)
133 {
134  // first gather the source files that have something to show
135  const auto source_files = get_source_files(goto_model, ai);
136 
137  // now show file-by-file
138  for(const auto &source_file : source_files)
139  show_on_source(source_file, goto_model, ai, message_handler);
140 }
Abstract Interpretation.
This is the basic interface of the abstract interpreter with default implementations of the core func...
Definition: ai.h:117
goto_programt::const_targett locationt
Definition: ai.h:124
virtual cstate_ptrt abstract_state_before(locationt l) const
Get a copy of the abstract state before the given instruction, without needing to know what kind of d...
Definition: ai.h:221
function_mapt function_map
symbol_tablet symbol_table
Symbol table.
Definition: goto_model.h:31
goto_functionst goto_functions
GOTO functions.
Definition: goto_model.h:34
Class that provides messages with a built-in verbosity 'level'.
Definition: message.h:155
mstreamt & warning() const
Definition: message.h:404
static const commandt reset
return to default formatting, as defined by the terminal
Definition: message.h:343
mstreamt & result() const
Definition: message.h:409
static eomt eom
Definition: message.h:297
static const commandt blue
render text with blue foreground color
Definition: message.h:355
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
#define forall_goto_program_instructions(it, program)
const std::string & id2string(const irep_idt &d)
Definition: irep.h:40
void show_on_source(const std::string &source_file, const goto_modelt &goto_model, const ai_baset &ai, message_handlert &message_handler)
output source code annotated with abstract states for given file
static std::optional< std::string > show_location(const ai_baset &ai, ai_baset::locationt loc)
get the name of the file referred to at a location loc, if any
static void print_with_indent(const std::string &src, const std::string &indent_line, std::ostream &out)
print a string with indent to match given sample line
static std::set< std::string > get_source_files(const goto_modelt &goto_model, const ai_baset &ai)
get the source files with non-top abstract states
#define widen_if_needed(s)
Definition: unicode.h:28