Program Listing for File DOTSubgraphRepresentationImpl.h

Program Listing for File DOTSubgraphRepresentationImpl.h#

↰ Return to documentation for file (src/midend/astDump/DOTSubgraphRepresentationImpl.h)

/******************************************************************************
 *
 * DOT Graph output, similar to DOTGraphRepresentation
 * also supports subgraph clustering - inc constrast to above it
 * does buffer the graph information until writeDotoutStream is
 * called
 *
 *****************************************************************************/
// Author: Markus Schordan, Nils Thuerey
// $Id: DOTSubgraphRepresentation.C,v 1.6 2008/01/08 02:56:19 dquinlan Exp $

#include <iostream>
#include <fstream>
#include <sstream>
#include <typeinfo>
#include <assert.h>
#include "sage3basic.h"
#include <inttypes.h>
#include "DOTSubgraphRepresentation.h"

// DQ (12/31/2005): This is OK if not declared in a header file
using namespace std;

template<class NodeType>
DOTSubgraphRepresentation<NodeType>::DOTSubgraphRepresentation() {
   dotout = new ostringstream();
   assert(dotout != NULL);
  mSubgraphIds = -1;
  mAutoSubgraphIds   = false;
  mManualSubgraphIds = false;
}

template<class NodeType>
DOTSubgraphRepresentation<NodeType>::~DOTSubgraphRepresentation() {
  // DQ (8/14/2004):
  // This fixes an long outstanding bug in the use of the DOT interface classes with Qing's graph
  // interface. The DOTSubgraphRepresentation<> class does not have a dotout data member
  // the DOTRepresentation<> (the base class) does have a dotout data member and direived class
  // should not delete the base class's data member.  It would work if we had set the pointer to
  // NULL after deleting it (a habit that I very much like and which would have avoided the
  // bug, but it is better that the derived class not delete the base class data members.
  // delete dotout;
}

template<class NodeType>
void
DOTSubgraphRepresentation<NodeType>::resetWriteFlags( void )
   {
  // clear flags
     for (typename vector<NodeStorageType>::iterator i=mNodes.begin(); i!=mNodes.end(); i++)
        {
          (*i).written = false;
        }
     for (typename vector<EdgeStorageType>::iterator i=mEdges.begin(); i!=mEdges.end(); i++)
        {
          (*i).written = false;
        }
     for (typename vector<NodeAdditionalStorage>::iterator i=mAdds.begin(); i!=mAdds.end(); i++)
        {
          (*i).written = false;
        }
   }


template<class NodeType>
void
DOTSubgraphRepresentation<NodeType>::writeOutSubgraph( typename map<int,string>::iterator i )
   {
     int sid             = (*i).first;
     string internalName = (*i).second;

  // default look for subgraphs
  // char *defaultSubgraphStyle =  " color=lightgrey; ";
    string defaultSubgraphStyle =  " color=blue; ";

     printf ("Handling subgraph %s ... (sid=%d) \n",internalName.c_str(),sid);

  // remove possible . from filenames
     for (size_t l=0; l<internalName.length(); l++)
        {
          if (internalName[l] == '.')
             {
               printf ("replacing . with _ in %s \n",internalName.c_str());
               internalName[l] = '_';
             }
        }

     (*dotout) << "subgraph " << "cluster_"<<sid <<" { " << endl;
     (*dotout) << "label=\"" << (*i).second << "\"; " << endl;
  // (*dotout) << "color=lightgrey; " << endl;
     (*dotout) << defaultSubgraphStyle << endl;
  // write all components of this subgraph
     for (typename vector<NodeStorageType>::iterator i=mNodes.begin(); i!=mNodes.end(); i++)
        {
          if ( (*i).subgraph == sid )
             {
               (*dotout) << this->nodeName( (*i).node ) << " [label=\"BLA" <<  (*i).label  << "\" " <<  (*i).option  << "];" << endl;
               (*i).written = true;
             }
        }
     for (typename vector<EdgeStorageType>::iterator i=mEdges.begin(); i!=mEdges.end(); i++)
        {
       // check if both nodes are in this subgraph
          bool isinthis = true;
          for (typename vector<NodeStorageType>::iterator j=mNodes.begin(); j!=mNodes.end(); j++)
             {
               if ( (*j).node == (*i).node1 )
                  {
                    if ((*j).subgraph != sid) isinthis = false;
                  }
             }

          for (typename vector<NodeStorageType>::iterator j=mNodes.begin(); j!=mNodes.end(); j++)
             {
               if ( (*j).node == (*i).node2 )
                  {
                    if ((*j).subgraph != sid) isinthis = false;
                  }
             }

          if( isinthis  )
             {
               (*dotout) << this->nodeName( (*i).node1 )
                         << " -> "
                         << this->nodeName( (*i).node2 )
                         << " [label=\"" <<  (*i).label << "\" " <<  (*i).option  << " ];" << endl;
               (*i).written = true;
             }

          for (typename vector<NodeAdditionalStorage>::iterator i=mAdds.begin(); i!=mAdds.end(); i++)
             {
            // check if the node is in this subgraph
               bool isinthis = true;
               for (typename vector<NodeStorageType>::iterator j=mNodes.begin(); j!=mNodes.end(); j++)
                  {
                    if ( (*j).node == (*i).node )
                       {
                         if ((*j).subgraph != sid) isinthis = false;
                       }
                  }
               if ( isinthis  )
                  {
                    (*dotout) << (*i).add;
                    (*i).written = true;
                  }
             }
        }

       // end this subgraph
     (*dotout) << "} " << endl;
   }

// This is the old code which is being refactored to support nested subgraphs
template<class NodeType>
void
DOTSubgraphRepresentation<NodeType>::writeDotoutStream( void )
   {
  // default look for subgraphs
  // char *defaultSubgraphStyle =  " color=lightgrey; ";
    string defaultSubgraphStyle =  " color=red; ";

  // clear flags
     resetWriteFlags();

     printf ("DOTSubgraphRepresentation<NodeType>::writeDotoutStream(): mSubgraphNames.size() = %" PRIuPTR " \n",mSubgraphNames.size());

  // write normally if there are no subgraphs
     if (mSubgraphNames.size() == 0)
        {
       // write nodes
          for (typename vector<NodeStorageType>::iterator i=mNodes.begin(); i!=mNodes.end(); i++)
             {
               (*dotout) << this->nodeName( (*i).node ) << "[label=\"" <<  (*i).label  << "\" " <<  (*i).option  << "];" << endl;
               (*i).written = true;
             }
       // write edges
          for (typename vector<EdgeStorageType>::iterator i=mEdges.begin(); i!=mEdges.end(); i++)
             {
               (*dotout) << this->nodeName( (*i).node1 )
                         << " -> "
                         << this->nodeName( (*i).node2 )
                         << "[label=\"" <<  (*i).label << "\" " <<  (*i).option  << " ];" << endl;
               (*i).written = true;
             }

          for (typename vector<NodeAdditionalStorage>::iterator i=mAdds.begin(); i!=mAdds.end(); i++)
             {
               (*dotout) << (*i).add;
               (*i).written = true;
             }

        }
       else
        {
       // print each sbugraph, then other stuff
          for(typename map<int,string>::iterator i=mSubgraphNames.begin(); i!=mSubgraphNames.end(); i++)
             {
      int sid = (*i).first;

         printf ("Handling subgraph ... (sid=%d) \n",sid);

      // remove possible . from filenames
      string internalName = (*i).second;
      for(size_t l=0; l<internalName.length(); l++) {
        if(internalName[l]=='.') internalName[l] = '_';
      }

      (*dotout) << "subgraph " << "cluster_"<<sid <<" { " << endl;
      (*dotout) << "label=\"" << (*i).second << "\"; " << endl;
      // (*dotout) << "color=lightgrey; " << endl;
         (*dotout) << defaultSubgraphStyle << endl;
      // write all components of this subgraph
      for(typename vector<NodeStorageType>::iterator i=mNodes.begin(); i!=mNodes.end(); i++) {
        if( (*i).subgraph == sid ) {
        (*dotout) << this->nodeName( (*i).node ) << " [label=\"BLA" <<  (*i).label  << "\" " <<  (*i).option  << "];" << endl;
        (*i).written = true; }
      }
      for(typename vector<EdgeStorageType>::iterator i=mEdges.begin(); i!=mEdges.end(); i++) {
        // check if both nodes are in this subgraph
        bool isinthis = true;
        for(typename vector<NodeStorageType>::iterator j=mNodes.begin(); j!=mNodes.end(); j++) {
          if( (*j).node == (*i).node1 ) {
            if((*j).subgraph != sid) isinthis = false; }
        }
        for(typename vector<NodeStorageType>::iterator j=mNodes.begin(); j!=mNodes.end(); j++) {
          if( (*j).node == (*i).node2 ) {
            if((*j).subgraph != sid) isinthis = false; }
        }

        if( isinthis  ) {
        (*dotout) << this->nodeName( (*i).node1 )
          << " -> "
          << this->nodeName( (*i).node2 )
          << " [label=\"" <<  (*i).label << "\" " <<  (*i).option  << " ];" << endl;
        (*i).written = true; }
      }
      for(typename vector<NodeAdditionalStorage>::iterator i=mAdds.begin(); i!=mAdds.end(); i++) {
        // check if the node is in this subgraph
        bool isinthis = true;
        for(typename vector<NodeStorageType>::iterator j=mNodes.begin(); j!=mNodes.end(); j++) {
          if( (*j).node == (*i).node ) {
            if((*j).subgraph != sid) isinthis = false; }
        }
        if( isinthis  ) {
        (*dotout) << (*i).add;
        (*i).written = true; }
      }
      // end this subgraph
      (*dotout) << "} " << endl;
    }

      // DQ (8/16/2004): These nodes will appear outside of the subgraph (as intended by the user)
    // write everything that wasnt written yet
    for(typename vector<NodeStorageType>::iterator i=mNodes.begin(); i!=mNodes.end(); i++) {
      if(!(*i).written) (*dotout) << this->nodeName( (*i).node ) << "[label=\"BLA" <<  (*i).label  << "\" " <<  (*i).option  << "];" << endl;
    }
    // write edges
    for(typename vector<EdgeStorageType>::iterator i=mEdges.begin(); i!=mEdges.end(); i++) {
      if(!(*i).written) (*dotout) << this->nodeName( (*i).node1 )
        << " -> "
        << this->nodeName( (*i).node2 )
        << "[label=\"" <<  (*i).label << "\" " <<  (*i).option  << " ];" << endl;
    }
    for(typename vector<NodeAdditionalStorage>::iterator i=mAdds.begin(); i!=mAdds.end(); i++) {
      if(!(*i).written) (*dotout) << (*i).add;
    }

    // subgraphs done
  }
}

template<class NodeType>
void
DOTSubgraphRepresentation<NodeType>::writeToFileAsGraph(string filename) {
  writeDotoutStream();
  DOTRepresentation<NodeType>::writeToFileAsGraph(filename);
}

template<class NodeType>
void
DOTSubgraphRepresentation<NodeType>::writeToFile(string filename) {
  writeDotoutStream();
  DOTRepresentation<NodeType>::writeToFile(filename);
}

template<class NodeType>
void
DOTSubgraphRepresentation<NodeType>::addNode(NodeType node, string nodelabel, string option) {
  addNode(node,nodelabel,option, -1);
}

template<class NodeType>
void
DOTSubgraphRepresentation<NodeType>::addNode(NodeType node, string nodelabel, string option, int subgraph) {
  NodeStorageType sn;
  sn.node = node;
  sn.label = nodelabel;
  sn.option = option;
  sn.subgraph = subgraph;
  mNodes.push_back( sn );
  return;
}

template<class NodeType>
void DOTSubgraphRepresentation<NodeType>::
addEdge(NodeType node1, TraceType downtrace, TraceType uptrace, string edgelabel, NodeType node2, string option) {
  EdgeStorageType edge;
  edge.node1 = node1;
  edge.node2 = node2;
  ostringstream strs;
        strs << downtrace << ":" << uptrace << ":"<< edgelabel;
  edge.label = strs.str();
  string diropt(" dir=both ");
  edge.option = option + diropt;
  mEdges.push_back(edge);
  return;
}

// for edges to revisited nodes (there is no uptrace)
template<class NodeType>
void DOTSubgraphRepresentation<NodeType>::
addEdge(NodeType node1, TraceType downtrace, string edgelabel, NodeType node2, string option) {
  EdgeStorageType edge;
  edge.node1 = node1;
  edge.node2 = node2;
  ostringstream strs;
        strs << downtrace << ":" << edgelabel;
  edge.label = strs.str();
  string diropt(" arrowhead=odot ");
  edge.option = option + diropt;
  mEdges.push_back(edge);
  return;
}

// for edges to revisited nodes (there is no uptrace)
template<class NodeType>
void DOTSubgraphRepresentation<NodeType>::
addEdge(NodeType node1, string edgelabel, NodeType node2, string option) {
  EdgeStorageType edge;
  edge.node1 = node1;
  edge.node2 = node2;
  edge.label = edgelabel;
  edge.option = option;
  mEdges.push_back(edge);
  return;
}

template<class NodeType>
void DOTSubgraphRepresentation<NodeType>::
addNullValue(NodeType node, TraceType trace, string varname, string option) {
  NodeAdditionalStorage add;
  add.node = node;
  ostringstream strs;
  // a null value is represented by an edge to a diamond node, with the variable name as edge label
  // edge
  (strs) << "n_" << node
      << " -> "
      << "n_" << node << "__" << varname << "__null"
      << "[label=\"" << trace << ":" << varname << "\" " << "dir=none "<< option << "];" << endl;
  // node
  (strs) << "n_" << node << "__" << varname << "__null"
      << "[label=\""<< trace << ":\" shape=diamond "<< option <<"];" << endl;
  add.add = strs.str();
  mAdds.push_back( add );
  return;
}

template<class NodeType>
void DOTSubgraphRepresentation<NodeType>::
addEmptyContainer(NodeType node, TraceType trace, string varname, string option) {
  NodeAdditionalStorage add;
  add.node = node;
  ostringstream strs;
  (strs) << "n_" << node // node: holding null-reference to STL container, using [] to represent container-reference
      << " -> "
      << "n_" << node << "__" << varname << "__null"
      << "["<< "label=\"" << trace << ":" << varname << "[]\"" << " dir=none ];" << endl;
  (strs) << "n_" << node << "__" << varname << "__null"
      << "[label=\"\" shape=diamond ];" << endl; // dot-null node
  add.add = strs.str();
  mAdds.push_back( add );
  return;
}

// add new subgraph, returns id of the subgraph
template<class NodeType>
int DOTSubgraphRepresentation<NodeType>::addSubgraph(string name)
{
  assert(!mManualSubgraphIds);
  mAutoSubgraphIds = true;
  mSubgraphIds++;
  mSubgraphNames[ mSubgraphIds ] = name;
  return mSubgraphIds;
}

template<class NodeType>
void DOTSubgraphRepresentation<NodeType>::addSubgraph(int id, string name)
      {
        assert(!mAutoSubgraphIds);
        mManualSubgraphIds = true;
        mSubgraphNames[id] = name;
      };