Program Listing for File SimpleDirectedGraph.h

Program Listing for File SimpleDirectedGraph.h#

Return to documentation for file (src/midend/programAnalysis/staticInterproceduralSlicing/SimpleDirectedGraph.h)

#ifndef _SIMPLE_DIRECTED_GRAPH_H_
#define _SIMPLE_DIRECTED_GRAPH_H_

#include <iostream>
#include <fstream>
#include <set>
#include <map>
#include <stack>

// 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;

class SimpleDirectedGraphNode {


public:

        // Han: changed to virtual
        virtual ~SimpleDirectedGraphNode() {}

  std::set<SimpleDirectedGraphNode *> getSuccessors() {return _succs;}
  std::set<SimpleDirectedGraphNode *> getPredecessors() {return _preds;}

  void addSuccessor(SimpleDirectedGraphNode * n) {_succs.insert(n);}
  void addPredecessor(SimpleDirectedGraphNode * n) {_preds.insert(n);}

        void removeSuccessor(SimpleDirectedGraphNode * n) {_succs.erase(n);}
        void removePredecessor(SimpleDirectedGraphNode * n) {_preds.erase(n);}

  bool hasSuccessor(SimpleDirectedGraphNode * n) {return _succs.count(n) != 0;}
  bool hasPredecessor(SimpleDirectedGraphNode * n) {return _preds.count(n) != 0;}

  int numSuccessors() {return _succs.size();}
  int numPredecessors() {return _preds.size();}

  virtual void writeOut(std::ostream & os) {
    char buf[sizeof(SimpleDirectedGraphNode *)*2 + 3];
    sprintf(buf, "%p", this);
    os << buf;
  }


 private:

  std::set<SimpleDirectedGraphNode *> _succs;
  std::set<SimpleDirectedGraphNode *> _preds;

};


class SimpleDirectedGraph {

public:

  SimpleDirectedGraph() {}
        // Han: changed to virtual
        virtual ~SimpleDirectedGraph() {}

  std::set<SimpleDirectedGraphNode *> getNodes() {return _nodes;}

  virtual void addNode(SimpleDirectedGraphNode * node) {
    _nodes.insert(node);
  }
        virtual void removeNode(SimpleDirectedGraphNode * node)
        {
                _nodes.erase(node);
        }


        virtual void removeLink(SimpleDirectedGraphNode * from, SimpleDirectedGraphNode * to) {
                if(from != NULL && to != NULL)
                {
                        from->removeSuccessor(to);
                        to->removePredecessor(from);
                }
        }


  virtual void addLink(SimpleDirectedGraphNode * from, SimpleDirectedGraphNode * to) {

    // Add "to" to the successors of "from" and "from" to the
    // predecessors of "to" to initialize the edge in the graph
                //if(from != NULL && to != NULL)
                //{
                        from->addSuccessor(to);
                        to->addPredecessor(from);
                //}
  }

  bool nodeExists(SimpleDirectedGraphNode * node) {
    return _nodes.count(node) > 0;
  }

  bool linkExists(SimpleDirectedGraphNode * from, SimpleDirectedGraphNode * to) {
    return from->hasSuccessor(to);
  }

  void printGraph() {
    std::set<SimpleDirectedGraphNode *>::iterator i;
    for (i = _nodes.begin(); i != _nodes.end(); i++) {
      _displayData(*i, std::cout);
      std::cout << ":" << std::endl;
      std::set<SimpleDirectedGraphNode *> succs = (*i)->getSuccessors();
      std::set<SimpleDirectedGraphNode *>::iterator j;
      for (j = succs.begin(); j != succs.end(); j++) {
        std::cout << "    succ: ";
        _displayData(*j, std::cout);
        std::cout << std::endl;
      }
      std::set<SimpleDirectedGraphNode *> preds = (*i)->getPredecessors();
      for (j = preds.begin(); j != preds.end(); j++) {
        std::cout << "    pred: ";
        _displayData(*j, std::cout);
        std::cout << std::endl;
      }
      std::cout << std::endl;
    }
  }

  virtual void writeDot(char * filename) {

    std::ofstream f(filename);

    f << "digraph \"G" << filename << "\" {" << std::endl;
    //output all of the nodes
    std::set<SimpleDirectedGraphNode *>::iterator i;
    for (i = _nodes.begin(); i != _nodes.end(); i++) {
      SimpleDirectedGraphNode * d = *i;
      char buf[sizeof(SimpleDirectedGraphNode *)*2 + 3];
      sprintf(buf, "%p", d);
      f << "\"" << buf << "\" [label = \"";
      _displayData(d, f);
      f << "\"];" << std::endl;
    }

    //output all of the edges (we'll just use successor edges
    for (i = _nodes.begin(); i != _nodes.end(); i++) {
      SimpleDirectedGraphNode * d1 = *i;
      std::set<SimpleDirectedGraphNode *> succs = d1->getSuccessors();
      std::set<SimpleDirectedGraphNode *>::iterator j;
      for (j = succs.begin(); j != succs.end(); j++) {
        SimpleDirectedGraphNode * d2 = *j;

        char buf1[sizeof(SimpleDirectedGraphNode *)*2 + 3];
        char buf2[sizeof(SimpleDirectedGraphNode *)*2 + 3];

        sprintf(buf1, "%p", d1);
        sprintf(buf2, "%p", d2);

        f << "\"" << buf1 << "\" -> \"" << buf2 << "\";" << std::endl;
      }
    }

    f << "}" << std::endl;
  }

  enum TraverseDirection // NO_STRINGIFY
  {
    FORWARD  = 1,
    BACKWARD = 2
  };

  std::set<SimpleDirectedGraphNode *> getReachable(SimpleDirectedGraphNode * start, TraverseDirection dir) {

    std::set<SimpleDirectedGraphNode *> reachables;
    std::stack<SimpleDirectedGraphNode *> remaining;

    remaining.push(start);

    //Simple DFS on graph to find reachable nodes
    while (remaining.size() != 0) {
      //Get the first node on the stack
      SimpleDirectedGraphNode * curr = remaining.top();
      remaining.pop();

      //if we haven't already seen it, add it to our return list, and
      //push its children onto the stack
      if (reachables.count(curr) == 0) {
        reachables.insert(curr);

        //depending on TraverseDirection, children should either be
        //the successors or predecessors of curr
        std::set<SimpleDirectedGraphNode *> children;
        switch(dir) {
        case FORWARD:
          children = curr->getSuccessors();
          break;
        case BACKWARD:
          children = curr->getPredecessors();
          break;
        default:
          //This should never happen
          abort();
          break;
        }

        //push the children onto the stack
        std::set<SimpleDirectedGraphNode *>::iterator i;
        for (i = children.begin(); i != children.end(); i++) {
          remaining.push(*i);
        }
      } else {
        //Do nothing - we've already seen this node
      }
    }

    return reachables;
  }

protected:

  virtual void _displayData(SimpleDirectedGraphNode * node, std::ostream & os) {
    node->writeOut(os);
  }

  std::set<SimpleDirectedGraphNode *> _nodes;

};

#endif