void () { class StatementStackEntry { public final Statement statement; public final LinkedList<StackEntry> stackFinally; public final List<Exprent> tailExprents; public int statementIndex; public int edgeIndex; public List<StatEdge> succEdges; StatementStackEntry(Statement statement, LinkedList<StackEntry> stackFinally, List<Exprent> tailExprents) { this.statement = statement; this.stackFinally = stackFinally; this.tailExprents = tailExprents; } } LinkedList<StatementStackEntry> lstStackStatements = new LinkedList<>(); lstStackStatements.add(new StatementStackEntry(root, new LinkedList<>(), null)); mainloop: while (!lstStackStatements.isEmpty()) { StatementStackEntry statEntry = lstStackStatements.removeFirst(); Statement stat = statEntry.statement; LinkedList<StackEntry> stackFinally = statEntry.stackFinally; int statementBreakIndex = statEntry.statementIndex; DirectNode node, nd; List<StatEdge> lstSuccEdges = new ArrayList<>(); DirectNode sourcenode = null; if (statEntry.succEdges == null) { switch (stat.type) { case BASIC_BLOCK -> { node = new DirectNode(DirectNodeType.DIRECT, stat, (BasicBlockStatement)stat); if (stat.getExprents() != null) { node.exprents = stat.getExprents(); } graph.nodes.putWithKey(node, node.id); mapDestinationNodes.put(stat.id, new String[]{node.id, null}); lstSuccEdges.addAll(stat.getSuccessorEdges(EdgeType.DIRECT_ALL)); sourcenode = node; List<Exprent> tailExprentList = statEntry.tailExprents; if (tailExprentList != null) { DirectNode tail = new DirectNode(DirectNodeType.TAIL, stat, stat.id + "_tail"); tail.exprents = tailExprentList; graph.nodes.putWithKey(tail, tail.id); mapDestinationNodes.put(-stat.id, new String[]{tail.id, null}); listEdges.add(new Edge(node.id, -stat.id, EdgeType.REGULAR)); sourcenode = tail; } // 'if' statement: record positive branch if (stat.getLastBasicType() == StatementType.IF) { mapPosIfBranch.put(sourcenode.id, lstSuccEdges.get(0).getDestination().id); } } case CATCH_ALL, TRY_CATCH -> { DirectNode firstnd = new DirectNode(DirectNodeType.TRY, stat, stat.id + "_try"); mapDestinationNodes.put(stat.id, new String[]{firstnd.id, null}); graph.nodes.putWithKey(firstnd, firstnd.id); LinkedList<StatementStackEntry> lst = new LinkedList<>(); for (Statement st : stat.getStats()) { listEdges.add(new Edge(firstnd.id, st.id, EdgeType.REGULAR)); LinkedList<StackEntry> stack = stackFinally; if (stat.type == StatementType.CATCH_ALL && ((CatchAllStatement)stat).isFinally()) { stack = new LinkedList<>(stackFinally); if (st == stat.getFirst()) { // catch head stack.add(new StackEntry((CatchAllStatement)stat, Boolean.FALSE)); } else { // handler stack.add(new StackEntry((CatchAllStatement)stat, Boolean.TRUE, EdgeType.BREAK, root.getDummyExit(), st, st, firstnd, firstnd, true)); } } lst.add(new StatementStackEntry(st, stack, null)); } lstStackStatements.addAll(0, lst); } case DO -> { if (statementBreakIndex == 0) { statEntry.statementIndex = 1; lstStackStatements.addFirst(statEntry); lstStackStatements.addFirst(new StatementStackEntry(stat.getFirst(), stackFinally, null)); continue mainloop; } nd = graph.nodes.getWithKey(mapDestinationNodes.get(stat.getFirst().id)[0]); DoStatement dostat = (DoStatement)stat; LoopType loopType = dostat.getLoopType(); if (loopType == LoopType.DO) { mapDestinationNodes.put(stat.id, new String[]{nd.id, nd.id}); break; } lstSuccEdges.add(stat.getSuccessorEdges(EdgeType.DIRECT_ALL).get(0)); // exactly one edge switch (loopType) { case WHILE, DO_WHILE -> { node = new DirectNode(DirectNodeType.CONDITION, stat, stat.id + "_cond"); node.exprents = dostat.getConditionExprentList(); graph.nodes.putWithKey(node, node.id); listEdges.add(new Edge(node.id, stat.getFirst().id, EdgeType.REGULAR)); if (loopType == LoopType.WHILE) { mapDestinationNodes.put(stat.id, new String[]{node.id, node.id}); } else { mapDestinationNodes.put(stat.id, new String[]{nd.id, node.id}); boolean found = false; for (Edge edge : listEdges) { if (edge.statid.equals(stat.id) && edge.edgetype == EdgeType.CONTINUE) { found = true; break; } } if (!found) { listEdges.add(new Edge(nd.id, stat.id, EdgeType.CONTINUE)); } } sourcenode = node; } case FOR -> { DirectNode nodeinit = new DirectNode(DirectNodeType.INIT, stat, stat.id + "_init"); if (dostat.getInitExprent() != null) { nodeinit.exprents = dostat.getInitExprentList(); } graph.nodes.putWithKey(nodeinit, nodeinit.id); DirectNode nodecond = new DirectNode(DirectNodeType.CONDITION, stat, stat.id + "_cond"); nodecond.exprents = dostat.getConditionExprentList(); graph.nodes.putWithKey(nodecond, nodecond.id); DirectNode nodeinc = new DirectNode(DirectNodeType.INCREMENT, stat, stat.id + "_inc"); nodeinc.exprents = dostat.getIncExprentList(); graph.nodes.putWithKey(nodeinc, nodeinc.id); mapDestinationNodes.put(stat.id, new String[]{nodeinit.id, nodeinc.id}); mapDestinationNodes.put(-stat.id, new String[]{nodecond.id, null}); listEdges.add(new Edge(nodecond.id, stat.getFirst().id, EdgeType.REGULAR)); listEdges.add(new Edge(nodeinit.id, -stat.id, EdgeType.REGULAR)); listEdges.add(new Edge(nodeinc.id, -stat.id, EdgeType.REGULAR)); boolean found = false; for (Edge edge : listEdges) { if (edge.statid.equals(stat.id) && edge.edgetype == EdgeType.CONTINUE) { found = true; break; } } if (!found) { listEdges.add(new Edge(nd.id, stat.id, EdgeType.CONTINUE)); } sourcenode = nodecond; } } } case SYNCHRONIZED, SWITCH, IF, SEQUENCE, ROOT -> { int statsize = stat.getStats().size(); if (stat.type == StatementType.SYNCHRONIZED) { statsize = 2; // exclude the handler if synchronized } if (statementBreakIndex <= statsize) { List<Exprent> tailexprlst = switch (stat.type) { case SYNCHRONIZED -> ((SynchronizedStatement)stat).getHeadexprentList(); case SWITCH -> ((SwitchStatement)stat).getHeadExprentList(); case IF -> ((IfStatement)stat).getHeadexprentList(); default -> null; }; for (int i = statementBreakIndex; i < statsize; i++) { statEntry.statementIndex = i + 1; lstStackStatements.addFirst(statEntry); lstStackStatements.addFirst( new StatementStackEntry(stat.getStats().get(i), stackFinally, (i == 0 && tailexprlst != null && tailexprlst.get(0) != null) ? tailexprlst : null)); continue mainloop; } node = graph.nodes.getWithKey(mapDestinationNodes.get(stat.getFirst().id)[0]); mapDestinationNodes.put(stat.id, new String[]{node.id, null}); if (stat.type == StatementType.IF && ((IfStatement)stat).iftype == IfStatement.IFTYPE_IF) { lstSuccEdges.add(stat.getSuccessorEdges(EdgeType.DIRECT_ALL).get(0)); // exactly one edge sourcenode = tailexprlst.get(0) == null ? node : graph.nodes.getWithKey(node.id + "_tail"); } } } } } // no successor edges if (sourcenode != null) { if (statEntry.succEdges != null) { lstSuccEdges = statEntry.succEdges; } for (int edgeindex = statEntry.edgeIndex; edgeindex < lstSuccEdges.size(); edgeindex++) { StatEdge edge = lstSuccEdges.get(edgeindex); LinkedList<StackEntry> stack = new LinkedList<>(stackFinally); EdgeType edgetype = edge.getType(); Statement destination = edge.getDestination(); DirectNode finallyShortRangeSource = sourcenode; DirectNode finallyLongRangeSource = sourcenode; Statement finallyShortRangeEntry = null; Statement finallyLongRangeEntry = null; boolean isFinallyMonitorExceptionPath = false; boolean isFinallyExit = false; while (true) { StackEntry entry = null; if (!stack.isEmpty()) { entry = stack.getLast(); } boolean created = true; if (entry == null) { saveEdge(sourcenode, destination, edgetype, isFinallyExit ? finallyShortRangeSource : null, finallyLongRangeSource, finallyShortRangeEntry, finallyLongRangeEntry, isFinallyMonitorExceptionPath); } else { CatchAllStatement catchall = entry.catchstatement; if (entry.state) { // finally handler statement if (edgetype == EdgeType.FINALLY_EXIT) { stack.removeLast(); destination = entry.destination; edgetype = entry.edgetype; finallyShortRangeSource = entry.finallyShortRangeSource; finallyLongRangeSource = entry.finallyLongRangeSource; finallyShortRangeEntry = entry.finallyShortRangeEntry; finallyLongRangeEntry = entry.finallyLongRangeEntry; isFinallyExit = true; isFinallyMonitorExceptionPath = (catchall.getMonitor() != null) & entry.isFinallyExceptionPath; created = false; } else { if (!catchall.containsStatementStrict(destination)) { stack.removeLast(); created = false; } else { saveEdge(sourcenode, destination, edgetype, isFinallyExit ? finallyShortRangeSource : null, finallyLongRangeSource, finallyShortRangeEntry, finallyLongRangeEntry, isFinallyMonitorExceptionPath); } } } else { // finally protected try statement if (!catchall.containsStatementStrict(destination)) { saveEdge(sourcenode, catchall.getHandler(), EdgeType.REGULAR, isFinallyExit ? finallyShortRangeSource : null, finallyLongRangeSource, finallyShortRangeEntry, finallyLongRangeEntry, isFinallyMonitorExceptionPath); stack.removeLast(); stack.add(new StackEntry(catchall, Boolean.TRUE, edgetype, destination, catchall.getHandler(), finallyLongRangeEntry == null ? catchall.getHandler() : finallyLongRangeEntry, sourcenode, finallyLongRangeSource, false)); statEntry.edgeIndex = edgeindex + 1; statEntry.succEdges = lstSuccEdges; lstStackStatements.addFirst(statEntry); lstStackStatements.addFirst(new StatementStackEntry(catchall.getHandler(), stack, null)); continue mainloop; } else { saveEdge(sourcenode, destination, edgetype, isFinallyExit ? finallyShortRangeSource : null, finallyLongRangeSource, finallyShortRangeEntry, finallyLongRangeEntry, isFinallyMonitorExceptionPath); } } } if (created) { break; } } } } } }