libabigail
abg-viz-dot.cc
1// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2// -*- mode: C++ -*-
3//
4// Copyright (C) 2013-2025 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>
11ABG_BEGIN_EXPORT_DECLARATIONS
12
13#include "abg-viz-dot.h"
14
15ABG_END_EXPORT_DECLARATIONS
16// </headers defining libabigail's API>
17
18namespace abigail
19{
20
21using std::ostream;
22using std::ostringstream;
23
24// Constants.
25const style parent_sty = { color::white, color::black, "" };
26const style child_sty = { color::white, color::gray75, "" };
27
28// Define.
29units_type node_base::_M_count_total;
30
31void
32dot::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.
50void
51dot::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
67void
68dot::finish_element()
69{
70 _M_sstream << "}" << std::endl;
71}
72
73void
74dot::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
82void
83dot::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
100void
101dot::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
111void
112dot::add_parent(const parent_node& __p)
113{
114 add_node(__p);
115}
116
117void
118dot::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.