2 // Compute the reverse partition of the chosen function
4 // Run with graph ... | return-paths | subg-rev -a functionname
8 // Find the immediate parent subgraph of this object
9 graph_t find_owner(obj_t o, graph_t g)
12 for (g1 = fstsubg(g); g1; g1 = nxtsubg(g1))
13 if(isIn(g1,o)) return g1;
19 graph_t calls[]; // Crude hash table for tracking who calls what
20 graph_t sg = subg ($, "reachable");
21 graph_t target, g, g2;
27 // find the ep corresponding to ARG[0]
28 for (g = fstsubg($G); g; g = nxtsubg(g)) {
29 if(g.fun == ARGV[0]) {
39 printf(2, "Function %s not found\n", ARGV[0]);
43 // Add the incoming call edges to the allowed call list
45 for(e = fstin(n); e; e = nxtin(e)) {
47 g2 = find_owner(e.tail, $G);
48 calls[sprintf("%s%d", g2.name, ++i)] = g;
56 // This is a return edge. Allow the corresponding call
57 g = find_owner(head, $G);
59 while(calls[sprintf("%s%d", g.name, ++i)]) {
61 calls[sprintf("%s%d", g.name, i)] = find_owner(tail, $G);
62 g2 = find_owner(tail, $G);
68 // Ignore returns back to the target function
69 for (e = fstin($); e; e = nxtin(e))
70 if (e.op == "ret" && isIn(target,e.tail))
77 for (e = fstin($); e; e = nxtin(e)) {
80 g = find_owner(e.tail, $G);
82 while(calls[sprintf("%s%d", g.name, ++i)]) {
83 if (isIn(calls[sprintf("%s%d", g.name, i)],e.head))
86 g2 = find_owner(e.head, $G);
87 if (!found) delete($G, e);
91 for (g = fstsubg($G); g; g = nxtsubg(g)) {
92 if(isIn(g,$) && g != sg) {
93 subnode (copy(sg, g), $);