1695b41eeSopenharmony_ci// Copyright 2011 Google Inc. All Rights Reserved. 2695b41eeSopenharmony_ci// 3695b41eeSopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4695b41eeSopenharmony_ci// you may not use this file except in compliance with the License. 5695b41eeSopenharmony_ci// You may obtain a copy of the License at 6695b41eeSopenharmony_ci// 7695b41eeSopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8695b41eeSopenharmony_ci// 9695b41eeSopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10695b41eeSopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11695b41eeSopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12695b41eeSopenharmony_ci// See the License for the specific language governing permissions and 13695b41eeSopenharmony_ci// limitations under the License. 14695b41eeSopenharmony_ci 15695b41eeSopenharmony_ci#include "graphviz.h" 16695b41eeSopenharmony_ci 17695b41eeSopenharmony_ci#include <stdio.h> 18695b41eeSopenharmony_ci#include <algorithm> 19695b41eeSopenharmony_ci 20695b41eeSopenharmony_ci#include "dyndep.h" 21695b41eeSopenharmony_ci#include "graph.h" 22695b41eeSopenharmony_ci 23695b41eeSopenharmony_ciusing namespace std; 24695b41eeSopenharmony_ci 25695b41eeSopenharmony_civoid GraphViz::AddTarget(Node* node) { 26695b41eeSopenharmony_ci if (visited_nodes_.find(node) != visited_nodes_.end()) 27695b41eeSopenharmony_ci return; 28695b41eeSopenharmony_ci 29695b41eeSopenharmony_ci string pathstr = node->path(); 30695b41eeSopenharmony_ci replace(pathstr.begin(), pathstr.end(), '\\', '/'); 31695b41eeSopenharmony_ci printf("\"%p\" [label=\"%s\"]\n", node, pathstr.c_str()); 32695b41eeSopenharmony_ci visited_nodes_.insert(node); 33695b41eeSopenharmony_ci 34695b41eeSopenharmony_ci Edge* edge = node->in_edge(); 35695b41eeSopenharmony_ci 36695b41eeSopenharmony_ci if (!edge) { 37695b41eeSopenharmony_ci // Leaf node. 38695b41eeSopenharmony_ci // Draw as a rect? 39695b41eeSopenharmony_ci return; 40695b41eeSopenharmony_ci } 41695b41eeSopenharmony_ci 42695b41eeSopenharmony_ci if (visited_edges_.find(edge) != visited_edges_.end()) 43695b41eeSopenharmony_ci return; 44695b41eeSopenharmony_ci visited_edges_.insert(edge); 45695b41eeSopenharmony_ci 46695b41eeSopenharmony_ci if (edge->dyndep_ && edge->dyndep_->dyndep_pending()) { 47695b41eeSopenharmony_ci std::string err; 48695b41eeSopenharmony_ci if (!dyndep_loader_.LoadDyndeps(edge->dyndep_, &err)) { 49695b41eeSopenharmony_ci Warning("%s\n", err.c_str()); 50695b41eeSopenharmony_ci } 51695b41eeSopenharmony_ci } 52695b41eeSopenharmony_ci 53695b41eeSopenharmony_ci if (edge->inputs_.size() == 1 && edge->outputs_.size() == 1) { 54695b41eeSopenharmony_ci // Can draw simply. 55695b41eeSopenharmony_ci // Note extra space before label text -- this is cosmetic and feels 56695b41eeSopenharmony_ci // like a graphviz bug. 57695b41eeSopenharmony_ci printf("\"%p\" -> \"%p\" [label=\" %s\"]\n", 58695b41eeSopenharmony_ci edge->inputs_[0], edge->outputs_[0], edge->rule_->name().c_str()); 59695b41eeSopenharmony_ci } else { 60695b41eeSopenharmony_ci printf("\"%p\" [label=\"%s\", shape=ellipse]\n", 61695b41eeSopenharmony_ci edge, edge->rule_->name().c_str()); 62695b41eeSopenharmony_ci for (vector<Node*>::iterator out = edge->outputs_.begin(); 63695b41eeSopenharmony_ci out != edge->outputs_.end(); ++out) { 64695b41eeSopenharmony_ci printf("\"%p\" -> \"%p\"\n", edge, *out); 65695b41eeSopenharmony_ci } 66695b41eeSopenharmony_ci for (vector<Node*>::iterator in = edge->inputs_.begin(); 67695b41eeSopenharmony_ci in != edge->inputs_.end(); ++in) { 68695b41eeSopenharmony_ci const char* order_only = ""; 69695b41eeSopenharmony_ci if (edge->is_order_only(in - edge->inputs_.begin())) 70695b41eeSopenharmony_ci order_only = " style=dotted"; 71695b41eeSopenharmony_ci printf("\"%p\" -> \"%p\" [arrowhead=none%s]\n", (*in), edge, order_only); 72695b41eeSopenharmony_ci } 73695b41eeSopenharmony_ci } 74695b41eeSopenharmony_ci 75695b41eeSopenharmony_ci for (vector<Node*>::iterator in = edge->inputs_.begin(); 76695b41eeSopenharmony_ci in != edge->inputs_.end(); ++in) { 77695b41eeSopenharmony_ci AddTarget(*in); 78695b41eeSopenharmony_ci } 79695b41eeSopenharmony_ci} 80695b41eeSopenharmony_ci 81695b41eeSopenharmony_civoid GraphViz::Start() { 82695b41eeSopenharmony_ci printf("digraph ninja {\n"); 83695b41eeSopenharmony_ci printf("rankdir=\"LR\"\n"); 84695b41eeSopenharmony_ci printf("node [fontsize=10, shape=box, height=0.25]\n"); 85695b41eeSopenharmony_ci printf("edge [fontsize=10]\n"); 86695b41eeSopenharmony_ci} 87695b41eeSopenharmony_ci 88695b41eeSopenharmony_civoid GraphViz::Finish() { 89695b41eeSopenharmony_ci printf("}\n"); 90695b41eeSopenharmony_ci} 91