ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
staticInterproceduralSlicing/SimpleDirectedGraph.h
Go to the documentation of this file.
1 #ifndef _SIMPLE_DIRECTED_GRAPH_H_
2 #define _SIMPLE_DIRECTED_GRAPH_H_
3 
4 #include <iostream>
5 #include <fstream>
6 #include <set>
7 #include <map>
8 #include <stack>
9 
10 // DQ (12/30/2005): This is a Bad Bad thing to do (I can explain)
11 // it hides names in the global namespace and causes errors in
12 // otherwise valid and useful code. Where it is needed it should
13 // appear only in *.C files (and only ones not included for template
14 // instantiation reasons) else they effect user who use ROSE unexpectedly.
15 // using namespace std;
16 
28 
29 
30 public:
31 
32  // Han: changed to virtual
34 
36  std::set<SimpleDirectedGraphNode *> getSuccessors() {return _succs;}
38  std::set<SimpleDirectedGraphNode *> getPredecessors() {return _preds;}
39 
44 
47 
49  bool hasSuccessor(SimpleDirectedGraphNode * n) {return _succs.count(n) != 0;}
51  bool hasPredecessor(SimpleDirectedGraphNode * n) {return _preds.count(n) != 0;}
52 
54  int numSuccessors() {return _succs.size();}
56  int numPredecessors() {return _preds.size();}
57 
59  virtual void writeOut(std::ostream & os) {
60  char buf[sizeof(SimpleDirectedGraphNode *)*2 + 3];
61  sprintf(buf, "%p", this);
62  os << buf;
63  }
64 
65 
66  private:
67 
69  std::set<SimpleDirectedGraphNode *> _succs;
71  std::set<SimpleDirectedGraphNode *> _preds;
72 
73 };
74 
75 
83 class SimpleDirectedGraph {
84 
85 public:
86 
88  // Han: changed to virtual
89  virtual ~SimpleDirectedGraph() {}
90 
92  std::set<SimpleDirectedGraphNode *> getNodes() {return _nodes;}
93 
95  virtual void addNode(SimpleDirectedGraphNode * node) {
96  _nodes.insert(node);
97  }
98  virtual void removeNode(SimpleDirectedGraphNode * node)
99  {
100  _nodes.erase(node);
101  }
102 
103 
106  if(from != NULL && to != NULL)
107  {
108  from->removeSuccessor(to);
109  to->removePredecessor(from);
110  }
111  }
112 
113 
116 
117  // Add "to" to the successors of "from" and "from" to the
118  // predecessors of "to" to initialize the edge in the graph
119  //if(from != NULL && to != NULL)
120  //{
121  from->addSuccessor(to);
122  to->addPredecessor(from);
123  //}
124  }
125 
128  return _nodes.count(node) > 0;
129  }
130 
133  return from->hasSuccessor(to);
134  }
135 
136  void printGraph() {
137  std::set<SimpleDirectedGraphNode *>::iterator i;
138  for (i = _nodes.begin(); i != _nodes.end(); i++) {
139  _displayData(*i, std::cout);
140  std::cout << ":" << std::endl;
141  std::set<SimpleDirectedGraphNode *> succs = (*i)->getSuccessors();
142  std::set<SimpleDirectedGraphNode *>::iterator j;
143  for (j = succs.begin(); j != succs.end(); j++) {
144  std::cout << " succ: ";
145  _displayData(*j, std::cout);
146  std::cout << std::endl;
147  }
148  std::set<SimpleDirectedGraphNode *> preds = (*i)->getPredecessors();
149  for (j = preds.begin(); j != preds.end(); j++) {
150  std::cout << " pred: ";
151  _displayData(*j, std::cout);
152  std::cout << std::endl;
153  }
154  std::cout << std::endl;
155  }
156  }
157 
158  virtual void writeDot(char * filename) {
159 
160  std::ofstream f(filename);
161 
162  f << "digraph \"G" << filename << "\" {" << std::endl;
163  //output all of the nodes
164  std::set<SimpleDirectedGraphNode *>::iterator i;
165  for (i = _nodes.begin(); i != _nodes.end(); i++) {
166  SimpleDirectedGraphNode * d = *i;
167  char buf[sizeof(SimpleDirectedGraphNode *)*2 + 3];
168  sprintf(buf, "%p", d);
169  f << "\"" << buf << "\" [label = \"";
170  _displayData(d, f);
171  f << "\"];" << std::endl;
172  }
173 
174  //output all of the edges (we'll just use successor edges
175  for (i = _nodes.begin(); i != _nodes.end(); i++) {
176  SimpleDirectedGraphNode * d1 = *i;
177  std::set<SimpleDirectedGraphNode *> succs = d1->getSuccessors();
178  std::set<SimpleDirectedGraphNode *>::iterator j;
179  for (j = succs.begin(); j != succs.end(); j++) {
180  SimpleDirectedGraphNode * d2 = *j;
181 
182  char buf1[sizeof(SimpleDirectedGraphNode *)*2 + 3];
183  char buf2[sizeof(SimpleDirectedGraphNode *)*2 + 3];
184 
185  sprintf(buf1, "%p", d1);
186  sprintf(buf2, "%p", d2);
187 
188  f << "\"" << buf1 << "\" -> \"" << buf2 << "\";" << std::endl;
189  }
190  }
191 
192  f << "}" << std::endl;
193  }
194 
199  enum TraverseDirection // NO_STRINGIFY
200  {
201  FORWARD = 1,
202  BACKWARD = 2
203  };
204 
205  std::set<SimpleDirectedGraphNode *> getReachable(SimpleDirectedGraphNode * start, TraverseDirection dir) {
206 
207  std::set<SimpleDirectedGraphNode *> reachables;
208  std::stack<SimpleDirectedGraphNode *> remaining;
209 
210  remaining.push(start);
211 
212  //Simple DFS on graph to find reachable nodes
213  while (remaining.size() != 0) {
214  //Get the first node on the stack
215  SimpleDirectedGraphNode * curr = remaining.top();
216  remaining.pop();
217 
218  //if we haven't already seen it, add it to our return list, and
219  //push its children onto the stack
220  if (reachables.count(curr) == 0) {
221  reachables.insert(curr);
222 
223  //depending on TraverseDirection, children should either be
224  //the successors or predecessors of curr
225  std::set<SimpleDirectedGraphNode *> children;
226  switch(dir) {
227  case FORWARD:
228  children = curr->getSuccessors();
229  break;
230  case BACKWARD:
231  children = curr->getPredecessors();
232  break;
233  default:
234  //This should never happen
235  abort();
236  break;
237  }
238 
239  //push the children onto the stack
240  std::set<SimpleDirectedGraphNode *>::iterator i;
241  for (i = children.begin(); i != children.end(); i++) {
242  remaining.push(*i);
243  }
244  } else {
245  //Do nothing - we've already seen this node
246  }
247  }
248 
249  return reachables;
250  }
251 
252 protected:
253 
258  virtual void _displayData(SimpleDirectedGraphNode * node, std::ostream & os) {
259  node->writeOut(os);
260  }
261 
262  std::set<SimpleDirectedGraphNode *> _nodes;
263 
264 };
265 
266 #endif