Program Listing for File DOTGraphInterface.h

Program Listing for File DOTGraphInterface.h#

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

/******************************************************************************
 *
 * ROSE Global Database Connection
 *
 * Interface for DOT output of graphs
 *
 *****************************************************************************/

#ifndef DOTGRAPHINTERFACE_H
#define DOTGRAPHINTERFACE_H

// DQ (12/30/2005): This is a Bad Bad thing to do (I can explain)
// it hides names in the global namespace and causes errors in
// otherwise valid and useful code. Where it is needed it should
// appear only in *.C files (and only ones not included for template
// instantiation reasons) else they effect user who use ROSE unexpectedly.
// using namespace std;

#include <map>
#include <iterator>
#include <stack>
#include <iostream>
#include <string>

#include "DOTSubgraphRepresentation.h"

template<class VertexType, class EdgeType, class VertexIterator, class EdgeIterator>
class DOTGraphInterface
   {
     public:


    virtual ~DOTGraphInterface() { printf ("Inside of ~DOTGraphInterface() \n"); };

    void writeToDOTFile(std::string filename);

     protected:

    typedef enum {
      none = 1,
      target,
      source,
      both
    } EdgeDirection;


    // ---------
    // iterators

    virtual VertexIterator getVertices() = 0;

    virtual VertexIterator getVerticesEnd() = 0;

    virtual EdgeIterator getEdges(VertexType &v) = 0;

    virtual EdgeIterator getEdgesEnd(VertexType &v) = 0;


    // ----------------
    // vertex functions

    virtual std::string vertexToString(VertexType *v) = 0;

    virtual std::string getVertexName(VertexType &v) = 0;

    // -------------
    // edge functions

    virtual VertexType *getTargetVertex(EdgeType &e) = 0;


    // ----------------------------------------------
    // optional functions to improve the graph output
    // these do not necessarily have to be implemented

    virtual int getVertexSubgraphId(VertexType &v) {
      // assume there are no subgraphs
      return -1;
    }

    //  this function should construct a map containing the ID a the name as a string
    //  subgraph Id's have to be >0 to be valid
    //  only subgraphs entered in this list will be displayed (the name may also be empty)
    virtual std::map<int,std::string> getSubgraphList() {
      // none by default...
      std::map<int,std::string> temp;
      return temp;
    }

    virtual std::string getEdgeLabel(EdgeType &e) {
      // the default is no edge label
      return std::string("");
    }

    virtual EdgeDirection getEdgeDirection(EdgeType &e) {
      // normally its from the source to target
      return target;
    }

     public:
      // DQ (8/14/2004): Added support for subgraphs (also make this public)
     virtual int addSubgraph(std::string name)
         {
           return mDotRep.addSubgraph(name);
         }

     private:

    DOTSubgraphRepresentation< std::string > mDotRep;
   };

//-----------------------------------------------------------------------------

template<class VertexType, class EdgeType, class VertexIterator, class EdgeIterator>
void
DOTGraphInterface<VertexType, EdgeType, VertexIterator, EdgeIterator>::writeToDOTFile ( std::string filename )
   {
     bool debug = false;

     if (debug == true)
          std::cerr << " dot output to " << filename << std::endl; // debug

     mDotRep.clear();

  // init subgraphs (this might just be empty, that also works)
     std::map<int,std::string> subgraphs( getSubgraphList() );
     for(std::map<int,std::string>::iterator s=subgraphs.begin(); s!=subgraphs.end(); s++)
        {
       // cerr << " adding subgrph " << endl;
       // cerr << " adding " << (*s).first <<" as "<< (*s).second <<endl;
          mDotRep.addSubgraph( (*s).first, (*s).second );
        }

  // create all nodes
     for(VertexIterator i=getVertices(); i!=getVerticesEnd(); i++)
        {
          int subgraphId = getVertexSubgraphId( *i );
       // printf ("In writeToDOTFile(): subgraphId = %d \n",subgraphId);
          if(subgraphId>=0)
             {
               mDotRep.addNode( vertexToString(&(*i)), getVertexName( (*i) ), "", subgraphId );
             }
            else
             {
               mDotRep.addNode( vertexToString(&(*i)), getVertexName( (*i) ), "" );
             }

          if(debug)
             {
               std::cerr << " add node " << vertexToString(&(*i)) << " as " << getVertexName( (*i) ) << std::endl; // debug
             }
        }

  // create edges
     for (VertexIterator i=getVertices(); i!=getVerticesEnd(); i++)
        {
       // sort nodes? or problem of the user?

          if (debug)
               std::cerr << " add edge vertices ... " << std::endl; // debug

          EdgeIterator estart = getEdges(*i);
          EdgeIterator eend = getEdgesEnd(*i);

          for (EdgeIterator j=estart; j!=eend; j++)
             {
               EdgeType& e = *j;
               std::string label = getEdgeLabel( e );

            // AS(032006) Fixed it so that the corect edge is made. Earlier a call was made towards
            // mDotRep.addEdge( vertexToString(&(*i)),vertexToString(getTargetVertex(e)),"" ) which
            // would result in the second paramater implemented as a label and third as a node id.
            // Therefore I decided to simplify the implementation
               mDotRep.addEdge( vertexToString(&(*i)), label, vertexToString(getTargetVertex(e)) , "");
               if (debug)
                    std::cerr << " add edge from " << vertexToString(&(*i)) << " to " << vertexToString(getTargetVertex(e)) << " as " << label << std::endl; // debug
#if 0
            // AS(032006) There is no way to implement this logic in the current implementation of DOTSubgraphRepresentation.
            // Also as a design-desition I think it would be better to create an edge without a label when the label is of length
            // zero in the DOTSubgraphRepresentation. From my opinion that is a better design.

               if (label.length()>0)
                  {
                 // insert with label
                    mDotRep.addEdge( vertexToString(&(*i)), label, vertexToString(getTargetVertex(e)) , "");
                    if(debug)
                         std::cerr << " add edge from " << vertexToString(&(*i)) << " to " << vertexToString(getTargetVertex(e)) << " as " << label << std::endl; // debug
                  }
                 else
                  {
                 // insert without label
                 // AS(032006) Fixed it so that the corect edge is made. Earlier a call was made towards
                 // mDotRep.addEdge( vertexToString(&(*i)),vertexToString(getTargetVertex(e)),"" ) which
                 // would result in the second paramater implemented as a label and third as a node id.
                    mDotRep.addEdge( vertexToString(&(*i)),"", vertexToString(getTargetVertex(e)),"" );
                    if (debug)
                         std::cerr << " add edge from " << vertexToString(&(*i)) << " to " << vertexToString(getTargetVertex(e)) << " without label " << std::endl; // debug
                  }
#endif
               if (debug)
                    std::cerr << " edge added " << std::endl; // debug
             } // edges

          if (debug)
               std::cerr << " edge for vertex added " << std::endl; // debug
        } // nodes

     if (debug)
          std::cerr << " writing content to " << filename << std::endl; // debug

     mDotRep.writeToFileAsGraph( filename );

     if (debug)
          std::cerr << " output to " << filename << " done " << std::endl; // debug
   }

#endif