libabigail
abg-viz-dot.cc
1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- mode: C++ -*-
3 //
4 // Copyright (C) 2013-2023 Red Hat, Inc.
5 
6 #include <stdexcept>
7 #include <fstream>
8 
9 #include "abg-internal.h"
10 // <headers defining libabigail's API go under here>
11 ABG_BEGIN_EXPORT_DECLARATIONS
12 
13 #include "abg-viz-dot.h"
14 
15 ABG_END_EXPORT_DECLARATIONS
16 // </headers defining libabigail's API>
17 
18 namespace abigail
19 {
20 
21 using std::ostream;
22 using std::ostringstream;
23 
24 // Constants.
25 const style parent_sty = { color::white, color::black, "" };
26 const style child_sty = { color::white, color::gray75, "" };
27 
28 // Define.
29 units_type node_base::_M_count_total;
30 
31 void
32 dot::write()
33 {
34  try
35  {
36  std::string filename(_M_title + ".gv");
37  std::ofstream f(filename);
38  if (!f.is_open() || !f.good())
39  throw std::runtime_error("abigail::dot::write fail");
40 
41  f << _M_sstream.str() << std::endl;
42  }
43  catch(std::exception& e)
44  {
45  throw e;
46  }
47 }
48 
49 // DOT element beginning boilerplate.
50 void
51 dot::start_element()
52 {
53  // Open up digraph.
54  _M_sstream << "digraph ";
55  add_title();
56  _M_sstream << "{" << std::endl;
57 
58  // Defaults.
59  // XXX typo control
60  const std::string edge_default = R"_delimiter_(edge [fontname="FreeSans",fontsize="9",labelfontname="FreeSans",labelfontsize="9"];)_delimiter_";
61  const std::string node_default = R"_delimiter_(node [fontname="FreeSans",fontsize="9",shape=record];)_delimiter_";
62 
63  _M_sstream << edge_default << std::endl;
64  _M_sstream << node_default << std::endl;
65 }
66 
67 void
68 dot::finish_element()
69 {
70  _M_sstream << "}" << std::endl;
71 }
72 
73 void
74 dot::add_title()
75 {
76 
77  _M_sstream << '"' << _M_title << '"' << std::endl;
78 }
79 
80 // See test 19, class-decl to base-class
81 // Variable: height, width
82 void
83 dot::add_node(const node_base& __node)
84 {
85  _M_sstream << "Node" << __node._M_count << " ";
86 
87  const std::string label("__label");
88  const std::string height("__height");
89  const std::string width("__width");
90 
91  std::string strip = R"_delimiter_([label="__label", height=__height, width=__width, color="black", fillcolor="white", style="filled"];)_delimiter_";
92 
93  string_replace(strip, label, __node._M_id);
94  string_replace(strip, height, std::to_string(__node._M_y_space));
95  string_replace(strip, width, std::to_string(__node._M_x_space));
96 
97  _M_sstream << strip << std::endl;
98 }
99 
100 void
101 dot::add_edge(const node_base& __parent, const node_base& __child)
102 {
103  // XX typo control
104  std::string style = R"_delimiter_([dir="forward",color="midnightblue",fontsize="9",style="solid",fontname="FreeSans"];)_delimiter_";
105 
106  _M_sstream << "Node" << __parent._M_count << "->";
107  _M_sstream << "Node" << __child._M_count;
108  _M_sstream << style << std::endl;
109 }
110 
111 void
112 dot::add_parent(const parent_node& __p)
113 {
114  add_node(__p);
115 }
116 
117 void
118 dot::add_child_to_node(const child_node& __c, const node_base& __p)
119 {
120  // XX remove duplicates
121  add_node(__c);
122  add_edge(__p, __c);
123 }
124 
125 }//end namespace abigail
Toplevel namespace for libabigail.
void string_replace(std::string &target, const std::string &match, const std::string &replace)
Utility function, like regex_replace.
const style parent_sty
Useful constants.
Definition: abg-viz-dot.cc:25
Datum consolidating style preferences.