package cfg.C; import java.util.Map.Entry; import ast.ASTNode; import ast.functionDef.FunctionDef; import ast.functionDef.Parameter; import ast.functionDef.ParameterList; import ast.statements.BreakStatement; import ast.statements.CompoundStatement; import ast.statements.ContinueStatement; import ast.statements.DoStatement; import ast.statements.ForStatement; import ast.statements.GotoStatement; import ast.statements.IfStatement; import ast.statements.Label; import ast.statements.ReturnStatement; import ast.statements.SwitchStatement; import ast.statements.WhileStatement; import cfg.CFG; import cfg.CFGEdge; import cfg.CFGFactory; import cfg.nodes.ASTNodeContainer; import cfg.nodes.CFGErrorNode; import cfg.nodes.CFGNode; import cfg.nodes.InfiniteForNode; public class CCFGFactory extends CFGFactory { private static StructuredFlowVisitor structuredFlowVisitior = new StructuredFlowVisitor(); @Override public CFG newInstance(FunctionDef functionDefinition) { try { CCFG function = newInstance(); CCFG parameterBlock = convert(functionDefinition.getParameterList()); CCFG functionBody = convert(functionDefinition.getContent()); parameterBlock.appendCFG(functionBody); function.appendCFG(parameterBlock); fixGotoStatements(function); fixReturnStatements(function); if (!function.getBreakStatements().isEmpty()) { System.err.println("warning: unresolved break statement"); fixBreakStatements(function, function.getErrorNode()); } if (!function.getContinueStatements().isEmpty()) { System.err.println("warning: unresolved continue statement"); fixContinueStatement(function, function.getErrorNode()); } return function; } catch (Exception e) { // e.printStackTrace(); return newErrorInstance(); } } public static CCFG newInstance(ASTNode... nodes) { try { CCFG block = new CCFG(); CFGNode last = block.getEntryNode(); for (ASTNode node : nodes) { CFGNode container = new ASTNodeContainer(node); block.addVertex(container); block.addEdge(last, container); last = container; } block.addEdge(last, block.getExitNode()); return block; } catch (Exception e) { // e.printStackTrace(); return newErrorInstance(); } } public static CCFG newErrorInstance() { CCFG errorBlock = new CCFG(); CFGNode errorNode = new CFGErrorNode(); errorBlock.addVertex(errorNode); errorBlock.addEdge(errorBlock.getEntryNode(), errorNode); errorBlock.addEdge(errorNode, errorBlock.getExitNode()); return errorBlock; } public static CFG newInstance(IfStatement ifStatement) { try { CCFG block = new CCFG(); CFGNode conditionContainer = new ASTNodeContainer( ifStatement.getCondition()); block.addVertex(conditionContainer); block.addEdge(block.getEntryNode(), conditionContainer); CFG ifBlock = convert(ifStatement.getStatement()); block.mountCFG(conditionContainer, block.getExitNode(), ifBlock, CFGEdge.TRUE_LABEL); if (ifStatement.getElseNode() != null) { CFG elseBlock = convert(ifStatement.getElseNode() .getStatement()); block.mountCFG(conditionContainer, block.getExitNode(), elseBlock, CFGEdge.FALSE_LABEL); } else { block.addEdge(conditionContainer, block.getExitNode(), CFGEdge.FALSE_LABEL); } return block; } catch (Exception e) { // e.printStackTrace(); return newErrorInstance(); } } public static CFG newInstance(WhileStatement whileStatement) { try { CCFG whileBlock = new CCFG(); CFGNode conditionContainer = new ASTNodeContainer( whileStatement.getCondition()); whileBlock.addVertex(conditionContainer); whileBlock.addEdge(whileBlock.getEntryNode(), conditionContainer); CFG whileBody = convert(whileStatement.getStatement()); whileBlock.mountCFG(conditionContainer, conditionContainer, whileBody, CFGEdge.TRUE_LABEL); whileBlock.addEdge(conditionContainer, whileBlock.getExitNode(), CFGEdge.FALSE_LABEL); fixBreakStatements(whileBlock, whileBlock.getExitNode()); fixContinueStatement(whileBlock, conditionContainer); return whileBlock; } catch (Exception e) { // e.printStackTrace(); return newErrorInstance(); } } public static CFG newInstance(ForStatement forStatement) { try { CCFG forBlock = new CCFG(); ASTNode initialization = forStatement.getForInitStatement(); ASTNode condition = forStatement.getCondition(); ASTNode expression = forStatement.getExpression(); CFG forBody = convert(forStatement.getStatement()); CFGNode conditionContainer; if (condition != null) { conditionContainer = new ASTNodeContainer(condition); } else { conditionContainer = new InfiniteForNode(); } forBlock.addVertex(conditionContainer); forBlock.addEdge(conditionContainer, forBlock.getExitNode(), CFGEdge.FALSE_LABEL); if (initialization != null) { CFGNode initializationContainer = new ASTNodeContainer( initialization); forBlock.addVertex(initializationContainer); forBlock.addEdge(forBlock.getEntryNode(), initializationContainer); forBlock.addEdge(initializationContainer, conditionContainer); } else { forBlock.addEdge(forBlock.getEntryNode(), conditionContainer); } if (expression != null) { CFGNode expressionContainer = new ASTNodeContainer(expression); forBlock.addVertex(expressionContainer); forBlock.addEdge(expressionContainer, conditionContainer); forBlock.mountCFG(conditionContainer, expressionContainer, forBody, CFGEdge.TRUE_LABEL); } else { forBlock.mountCFG(conditionContainer, conditionContainer, forBody, CFGEdge.TRUE_LABEL); } fixBreakStatements(forBlock, forBlock.getExitNode()); fixContinueStatement(forBlock, conditionContainer); return forBlock; } catch (Exception e) { // e.printStackTrace(); return newErrorInstance(); } } public static CFG newInstance(DoStatement doStatement) { try { CCFG doBlock = new CCFG(); CFGNode conditionContainer = new ASTNodeContainer( doStatement.getCondition()); doBlock.addVertex(conditionContainer); doBlock.addEdge(conditionContainer, doBlock.getExitNode(), CFGEdge.FALSE_LABEL); CFG doBody = convert(doStatement.getStatement()); doBlock.mountCFG(doBlock.getEntryNode(), conditionContainer, doBody, CFGEdge.EMPTY_LABEL); for (CFGEdge edge : doBody.outgoingEdges(doBody.getEntryNode())) { doBlock.addEdge(conditionContainer, edge.getDestination(), CFGEdge.TRUE_LABEL); } fixBreakStatements(doBlock, doBlock.getExitNode()); fixContinueStatement(doBlock, conditionContainer); return doBlock; } catch (Exception e) { // e.printStackTrace(); return newErrorInstance(); } } public static CFG newInstance(SwitchStatement switchStatement) { try { CCFG switchBlock = new CCFG(); CFGNode conditionContainer = new ASTNodeContainer( switchStatement.getCondition()); switchBlock.addVertex(conditionContainer); switchBlock.addEdge(switchBlock.getEntryNode(), conditionContainer); CCFG switchBody = convert(switchStatement.getStatement()); switchBlock.addCFG(switchBody); boolean defaultLabel = false; for (Entry<String, CFGNode> block : switchBody.getLabels().entrySet()) { if (block.getKey().equals("default")) { defaultLabel = true; } switchBlock.addEdge(conditionContainer, block.getValue(), block.getKey()); } for (CFGEdge edge : switchBody.ingoingEdges(switchBody .getExitNode())) { switchBlock .addEdge(edge.getSource(), switchBlock.getExitNode()); } if (!defaultLabel) { switchBlock.addEdge(conditionContainer, switchBlock.getExitNode()); } fixBreakStatements(switchBlock, switchBlock.getExitNode()); return switchBlock; } catch (Exception e) { // e.printStackTrace(); return newErrorInstance(); } } public static CFG newInstance(ParameterList paramList) { try { CFG parameterListBlock = newInstance(); for (Parameter parameter : paramList.getParameters()) { parameterListBlock.appendCFG(convert(parameter)); } return parameterListBlock; } catch (Exception e) { // e.printStackTrace(); return newErrorInstance(); } } public static CFG newInstance(CompoundStatement content) { try { CFG compoundBlock = newInstance(); for (ASTNode statement : content.getStatements()) { compoundBlock.appendCFG(convert(statement)); } return compoundBlock; } catch (Exception e) { // e.printStackTrace(); return newErrorInstance(); } } public static CFG newInstance(ReturnStatement returnStatement) { try { CCFG returnBlock = new CCFG(); CFGNode returnContainer = new ASTNodeContainer(returnStatement); returnBlock.addVertex(returnContainer); returnBlock.addEdge(returnBlock.getEntryNode(), returnContainer); returnBlock.addEdge(returnContainer, returnBlock.getExitNode()); returnBlock.addReturnStatement(returnContainer); return returnBlock; } catch (Exception e) { // e.printStackTrace(); return newErrorInstance(); } } public static CFG newInstance(GotoStatement gotoStatement) { try { CCFG gotoBlock = new CCFG(); CFGNode gotoContainer = new ASTNodeContainer(gotoStatement); gotoBlock.addVertex(gotoContainer); gotoBlock.addEdge(gotoBlock.getEntryNode(), gotoContainer); gotoBlock.addEdge(gotoContainer, gotoBlock.getExitNode()); gotoBlock .addGotoStatement(gotoContainer, gotoStatement.getTarget()); return gotoBlock; } catch (Exception e) { // e.printStackTrace(); return newErrorInstance(); } } public static CFG newInstance(Label labelStatement) { try { CCFG continueBlock = new CCFG(); CFGNode labelContainer = new ASTNodeContainer(labelStatement); continueBlock.addVertex(labelContainer); continueBlock.addEdge(continueBlock.getEntryNode(), labelContainer); continueBlock.addEdge(labelContainer, continueBlock.getExitNode()); String label = labelStatement.getEscapedCodeStr(); label = label.substring(0, label.length() - 2); continueBlock.addBlockLabel(label, labelContainer); return continueBlock; } catch (Exception e) { // e.printStackTrace(); return newErrorInstance(); } } public static CFG newInstance(ContinueStatement continueStatement) { try { CCFG continueBlock = new CCFG(); CFGNode continueContainer = new ASTNodeContainer(continueStatement); continueBlock.addVertex(continueContainer); continueBlock.addEdge(continueBlock.getEntryNode(), continueContainer); continueBlock.addEdge(continueContainer, continueBlock.getExitNode()); continueBlock.addContinueStatement(continueContainer); return continueBlock; } catch (Exception e) { // e.printStackTrace(); return newErrorInstance(); } } public static CFG newInstance(BreakStatement breakStatement) { try { CCFG breakBlock = new CCFG(); CFGNode breakContainer = new ASTNodeContainer(breakStatement); breakBlock.addVertex(breakContainer); breakBlock.addEdge(breakBlock.getEntryNode(), breakContainer); breakBlock.addEdge(breakContainer, breakBlock.getExitNode()); breakBlock.addBreakStatement(breakContainer); return breakBlock; } catch (Exception e) { // e.printStackTrace(); return newErrorInstance(); } } public static CCFG convert(ASTNode node) { CCFG cfg; if (node != null) { node.accept(structuredFlowVisitior); cfg = (CCFG) structuredFlowVisitior.getCFG(); } else { cfg = newInstance(); } return cfg; } public static void fixBreakStatements(CCFG thisCFG, CFGNode target) { for (CFGNode breakStatement : thisCFG.getBreakStatements()) { thisCFG.removeEdgesFrom(breakStatement); thisCFG.addEdge(breakStatement, target); } thisCFG.getBreakStatements().clear(); } public static void fixContinueStatement(CCFG thisCFG, CFGNode target) { for (CFGNode continueStatement : thisCFG.getContinueStatements()) { thisCFG.removeEdgesFrom(continueStatement); thisCFG.addEdge(continueStatement, target); } thisCFG.getContinueStatements().clear(); } public static void fixGotoStatements(CCFG thisCFG) { for (Entry<CFGNode, String> entry : thisCFG.getGotoStatements().entrySet()) { CFGNode gotoStatement = entry.getKey(); String label = entry.getValue(); thisCFG.removeEdgesFrom(gotoStatement); thisCFG.addEdge(gotoStatement, thisCFG.getBlockByLabel(label)); } thisCFG.getGotoStatements().clear(); } public static void fixReturnStatements(CCFG thisCFG) { for (CFGNode returnStatement : thisCFG.getReturnStatements()) { thisCFG.removeEdgesFrom(returnStatement); thisCFG.addEdge(returnStatement, thisCFG.getExitNode()); } thisCFG.getReturnStatements().clear(); } }