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