#!/usr/bin/gvpr -f // Compute the forward partition of the chosen function // // Run with graph ... | return-paths | subg-fwd -a functionname // or graph ... | subg-fwd BEGIN { // Find the immediate parent subgraph of this object graph_t find_owner(obj_t o, graph_t g) { graph_t g1; for (g1 = fstsubg(g); g1; g1 = nxtsubg(g1)) if(isIn(g1,o)) return g1; return NULL; } } BEG_G { graph_t sg = subg ($, sprintf("incoming-%s", ARGV[0])); graph_t returns = graph("return-edges", ""); // Temporary graph to hold return edges graph_t target, g, g2; node_t n; edge_t e; int i; $tvtype = TV_fwd; // find the ep corresponding to ARG[0] for (g = fstsubg($G); g; g = nxtsubg(g)) { if(g.fun == ARGV[0]) { n = node($,g.ep); $tvroot = n; n.style = "filled"; target = g; break; } } if(!target) { printf(2, "Function %s not found\n", ARGV[0]); exit(1); } } // Preserve external functions E [op == "extern"] { subnode (sg, head); } // Move unused return edges into a separate graph so they don't get followed N [op == "ret"] { for (e = fstout($); e; e = nxtout(e)) if (e.op == "ret" && !isIn(sg, e.head)) { clone(returns, e); delete($G, e); } } // Recover elided return edge for this target node N [op == "target" && indegree == 1] { n = copy(returns, $); e = fstin(n); // each target node can only have one return edge e = edge(copy(sg, e.tail), $, "recovered"); // clone should work here, but doesn't copyA(fstin(n), e); } // Copy relevant nodes N { $tvroot = NULL; g = find_owner($, $G); if(g && g != sg) subnode (copy(sg, g), $); } END_G { induce(sg); write(sg); }