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