cprover
count_eloc.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Count effective lines of code
4 
5 Author: Michael Tautschnig
6 
7 Date: December 2012
8 
9 \*******************************************************************/
10 
13 
14 #include "count_eloc.h"
15 
16 #include <iostream>
17 #include <unordered_set>
18 
19 #include <util/prefix.h>
20 #include <util/file_util.h>
21 
22 #include <goto-programs/cfg.h>
23 
24 typedef std::unordered_set<irep_idt, irep_id_hash> linest;
25 typedef std::unordered_map<irep_idt, linest, irep_id_hash> filest;
26 typedef std::unordered_map<irep_idt, filest, irep_id_hash> working_dirst;
27 
28 static void collect_eloc(
29  const goto_functionst &goto_functions,
30  working_dirst &dest)
31 {
32  forall_goto_functions(f_it, goto_functions)
33  {
34  forall_goto_program_instructions(it, f_it->second.body)
35  {
36  filest &files=dest[it->source_location.get_working_directory()];
37  const irep_idt &file=it->source_location.get_file();
38 
39  if(!file.empty() &&
40  !it->source_location.is_built_in())
41  files[file].insert(it->source_location.get_line());
42  }
43  }
44 }
45 
46 void count_eloc(const goto_functionst &goto_functions)
47 {
48  std::size_t eloc=0;
49 
50  working_dirst eloc_map;
51  collect_eloc(goto_functions, eloc_map);
52 
53  for(const std::pair<irep_idt, filest> &files : eloc_map)
54  for(const std::pair<irep_idt, linest> &lines : files.second)
55  eloc+=lines.second.size();
56 
57  std::cout << "Effective lines of code: " << eloc << '\n';
58 }
59 
60 void list_eloc(const goto_functionst &goto_functions)
61 {
62  working_dirst eloc_map;
63  collect_eloc(goto_functions, eloc_map);
64 
65  for(const std::pair<irep_idt, filest> &files : eloc_map)
66  for(const std::pair<irep_idt, linest> &lines : files.second)
67  {
68  std::string file=id2string(lines.first);
69  if(!files.first.empty())
70  file=concat_dir_file(id2string(files.first), file);
71 
72  for(const irep_idt &line : lines.second)
73  std::cout << file << ':' << line << '\n';
74  }
75 }
76 
77 void print_path_lengths(const goto_functionst &goto_functions)
78 {
79  const irep_idt &entry_point=goto_functions.entry_point();
80  goto_functionst::function_mapt::const_iterator start=
81  goto_functions.function_map.find(entry_point);
82 
83  if(start==goto_functions.function_map.end() ||
84  !start->second.body_available())
85  {
86  std::cout << "No entry point found, path length undefined\n";
87  return;
88  }
89 
90  struct visited_cfg_nodet
91  {
92  bool visited;
93 
94  visited_cfg_nodet():visited(false)
95  {
96  }
97  };
98 
99  typedef cfg_baset<visited_cfg_nodet> cfgt;
100  cfgt cfg;
101  cfg(goto_functions);
102 
103  const goto_programt &start_program=start->second.body;
104 
105  const cfgt::entryt &start_node=
106  cfg.entry_map[start_program.instructions.begin()];
107  const cfgt::entryt &last_node=
108  cfg.entry_map[--start_program.instructions.end()];
109 
110  cfgt::patht shortest_path;
111  cfg.shortest_path(start_node, last_node, shortest_path);
112  std::cout << "Shortest control-flow path: " << shortest_path.size()
113  << " instructions\n";
114 
115  std::size_t n_loops=0, loop_ins=0;
116  forall_goto_functions(gf_it, goto_functions)
117  forall_goto_program_instructions(i_it, gf_it->second.body)
118  // loops or recursion
119  if(i_it->is_backwards_goto() ||
120  i_it==gf_it->second.body.instructions.begin())
121  {
122  const cfgt::entryt &node=cfg.entry_map[i_it];
123  cfgt::patht loop;
124  cfg.shortest_loop(node, loop);
125 
126  if(!loop.empty())
127  {
128  ++n_loops;
129  loop_ins+=loop.size()-1;
130  }
131  }
132 
133  if(n_loops>0)
134  std::cout << "Loop information: " << n_loops << " loops, "
135  << loop_ins << " instructions in shortest paths of loop bodies\n";
136 
137  std::size_t n_reachable=0;
138  cfg.visit_reachable(start_node);
139  for(std::size_t i=0; i<cfg.size(); ++i)
140  if(cfg[i].visited)
141  ++n_reachable;
142  std::cout << "Reachable instructions: " << n_reachable << "\n";
143 }
std::string concat_dir_file(const std::string &directory, const std::string &file_name)
Definition: file_util.cpp:128
const std::string & id2string(const irep_idt &d)
Definition: irep.h:44
Control Flow Graph.
instructionst instructions
The list of instructions in the goto program.
A multi-procedural control flow graph (CFG) whose nodes store references to instructions in a GOTO pr...
Definition: cfg.h:62
static void collect_eloc(const goto_functionst &goto_functions, working_dirst &dest)
Definition: count_eloc.cpp:28
std::unordered_map< irep_idt, filest, irep_id_hash > working_dirst
Definition: count_eloc.cpp:26
std::list< path_nodet > patht
Definition: path.h:45
void print_path_lengths(const goto_functionst &goto_functions)
Definition: count_eloc.cpp:77
std::unordered_set< irep_idt, irep_id_hash > linest
Definition: count_eloc.cpp:24
void count_eloc(const goto_functionst &goto_functions)
Definition: count_eloc.cpp:46
Count effective lines of code.
std::unordered_map< irep_idt, linest, irep_id_hash > filest
Definition: count_eloc.cpp:25
A specialization of goto_program_templatet over goto programs in which instructions have codet type...
Definition: goto_program.h:24
void list_eloc(const goto_functionst &goto_functions)
Definition: count_eloc.cpp:60
#define forall_goto_functions(it, functions)
#define forall_goto_program_instructions(it, program)
Definition: goto_program.h:68
bool empty() const
Definition: dstring.h:61
Definition: kdev_t.h:19