user_data2: if users can only specify a single value that's not a user rl
[smatch.git] / gvpr / subg-fwd
blobc40721303533c125cdaa526d58dd987ee8bcdbdb
1 #!/usr/bin/gvpr -f
2 // Compute the forward partition of the chosen function
3 //
4 // Run with graph ... | return-paths | subg-fwd -a functionname
5 //       or graph ... | subg-fwd
8 BEGIN {
9         // Find the immediate parent subgraph of this object
10         graph_t find_owner(obj_t o, graph_t g)
11         {
12                 graph_t g1;
13                 for (g1 = fstsubg(g); g1; g1 = nxtsubg(g1))
14                         if(isIn(g1,o)) return g1;
15                 return NULL;
16         }
19 BEG_G {
20         graph_t sg = subg ($, sprintf("incoming-%s", ARGV[0]));
21         graph_t returns = graph("return-edges", ""); // Temporary graph to hold return edges
22         graph_t target, g, g2;
23         node_t n;
24         edge_t e;
25         int i;
27         $tvtype = TV_fwd;
29         // find the ep corresponding to ARG[0]
30         for (g = fstsubg($G); g; g = nxtsubg(g)) {
31                 if(g.fun == ARGV[0]) {
32                         n = node($,g.ep);
33                         $tvroot = n;
34                         n.style = "filled";
35                         target = g;
36                         break;
37                 }
38         }
39         if(!target) {
40                 printf(2, "Function %s not found\n", ARGV[0]);
41                 exit(1);
42         }
45 // Preserve external functions
46 E [op == "extern"] {
47         subnode (sg, head);
50 // Move unused return edges into a separate graph so they don't get followed
51 N [op == "ret"] {
52         for (e = fstout($); e; e = nxtout(e))
53                 if (e.op == "ret" && !isIn(sg, e.head)) {
54                         clone(returns, e);
55                         delete($G, e);
56                 }
59 // Recover elided return edge for this target node
60 N [op == "target" && indegree == 1] {
61         n = copy(returns, $);
62         e = fstin(n); // each target node can only have one return edge
63         e = edge(copy(sg, e.tail), $, "recovered"); // clone should work here, but doesn't
64         copyA(fstin(n), e);
67 // Copy relevant nodes
68 N {
69         $tvroot = NULL;
71         g = find_owner($, $G);
72         if(g && g != sg)
73                 subnode (copy(sg, g), $);
76 END_G {
77         induce(sg);
78         write(sg);