/// <summary> /// Recursive method used for generating the body of text representation of controlflow graph. /// It generates the result for globalcode and dureing the generation it calls /// itself resursivly on controlflow graphs of declared functions and methods. /// </summary> /// <param name="counter">Body of string representation in dot language of current conftrolflow graph.</param> /// <returns></returns> private string generateText(int counter) { string result = ""; List <BasicBlock> nodes = CollectAllBasicBlocks(); /* * generating text for all nodes */ string functionsResult = ""; int i = counter; int oldCounter = counter; foreach (var node in nodes) { string label = ""; foreach (var statement in node.Statements) { /* * recursive generating cfg and text representation for function */ if (statement.GetType() == typeof(FunctionDecl)) { FunctionDecl function = (FunctionDecl)statement; label += "function " + function.Function.Name + Environment.NewLine; try { ControlFlowGraph cfg = new ControlFlowGraph(globalCode, function, File); functionsResult += cfg.generateText((counter / 10000 + 1) * 10000); counter += 10000; } catch (Weverca.ControlFlowGraph.ControlFlowException e) { Console.WriteLine(e.Message); return(""); } } /* * recursive generating cfg and text representation for objects */ else if (statement.GetType() == typeof(TypeDecl)) { TypeDecl clas = (TypeDecl)statement; label += "class " + clas.Name.ToString() + Environment.NewLine; foreach (var method in clas.Members) { if (method.GetType() == typeof(MethodDecl)) { try { ControlFlowGraph cfg = new ControlFlowGraph(globalCode, method as MethodDecl, File); functionsResult += cfg.generateText((counter / 10000 + 1) * 10000); counter += 10000; } catch (Weverca.ControlFlowGraph.ControlFlowException e) { Console.WriteLine(e.Message); return(""); } } } } else if (statement is ForeachStmt) { var forEach = statement as ForeachStmt; Position foreachHeadPosition = new Position(forEach.Position.FirstLine, forEach.Position.FirstColumn, forEach.Position.FirstOffset, forEach.Body.Position.FirstLine, forEach.Body.Position.FirstColumn, forEach.Body.Position.FirstOffset - 1); label += globalCode.SourceUnit.GetSourceCode(foreachHeadPosition) + Environment.NewLine; } else { label += globalCode.SourceUnit.GetSourceCode(statement.Position) + Environment.NewLine; } } if (node.EndIngTryBlocks.Count > 0) { label += "//ending Try block"; } label = label.Replace("\"", "\\\""); result += "node" + i + "[label=\"" + label + "\"]" + Environment.NewLine; i++; } /* * drawing edges */ i = oldCounter; foreach (var node in nodes) { foreach (var e in node.OutgoingEdges) { int index = oldCounter + nodes.IndexOf(e.To); if (e.EdgeType == BasicBlockEdgeTypes.CONDITIONAL) { string label = ""; //in case a condition is not from original ast and hes been aded in constructiion of cfg, we need to write it in different way if (!e.Condition.Position.IsValid || this.cfgAddedElements.Contains(e.Condition)) { if (e.Condition.GetType() == typeof(BoolLiteral)) { label = e.Condition.Value.ToString(); } if (e.Condition.GetType() == typeof(BinaryEx)) { BinaryEx bin = (BinaryEx)e.Condition; //dirty trick how to acces internal field var a = bin.GetType().GetField("operation", BindingFlags.NonPublic | BindingFlags.Instance); if ((Operations)a.GetValue(bin) == Operations.Equal) { Expression l = (Expression)bin.GetType().GetField("leftExpr", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(bin); Expression r = (Expression)bin.GetType().GetField("rightExpr", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(bin); if (l.Position.IsValid == false) { if (l.GetType() == typeof(IntLiteral)) { label += "" + ((IntLiteral)l).Value; label += "="; label += globalCode.SourceUnit.GetSourceCode(r.Position); } else { label += "else"; } } else { label += globalCode.SourceUnit.GetSourceCode(l.Position); label += "="; label += globalCode.SourceUnit.GetSourceCode(r.Position); } } else { label += "else"; //label = globalCode.SourceUnit.GetSourceCode(edge.Condition.Position); } } if (e.Condition.GetType() == typeof(DirectFcnCall)) { DirectFcnCall functionCall = (DirectFcnCall)e.Condition; label += functionCall.QualifiedName + "("; foreach (var parameter in functionCall.CallSignature.Parameters) { if (parameter.Expression.GetType() == typeof(StringLiteral)) { StringLiteral literal = (StringLiteral)parameter.Expression; label += "\"" + literal.Value + "\"" + ","; } else { label += globalCode.SourceUnit.GetSourceCode(parameter.Expression.Position) + ","; } } label += ")"; } } else { label = globalCode.SourceUnit.GetSourceCode(e.Condition.Position); } label = label.Replace("\"", "\\\""); result += "node" + i + " -> node" + index + "[headport=n, tailport=s,label=\"" + label + "\"]" + Environment.NewLine; } else if (e.EdgeType == BasicBlockEdgeTypes.FOREACH) { result += "node" + i + " -> node" + index + "[headport=n, tailport=s,label=\"foreach special edge\"]" + Environment.NewLine; } else { result += "node" + i + " -> node" + index + "[headport=n, tailport=s,label=\"direct edge\"]" + Environment.NewLine; } } if (node.DefaultBranch != null) { string elseString = string.Empty; if (node.OutgoingEdges.Count > 0) { elseString = "else"; } int index = oldCounter + nodes.IndexOf(node.DefaultBranch.To); result += "node" + i + " -> node" + index + "[headport=n, tailport=s,label=\" " + elseString + " \"]" + Environment.NewLine; } if (node.EndIngTryBlocks.Count > 0) { foreach (var tryblock in node.EndIngTryBlocks) { foreach (var catchblock in tryblock.catchBlocks) { int index = oldCounter + nodes.IndexOf(catchblock); result += "node" + i + " -> node" + index + "[headport=n, tailport=s,label=\" catched " + catchblock.ClassName.QualifiedName.Name.Value + " \"]" + Environment.NewLine; } } } i++; } result += functionsResult; result += Environment.NewLine; return(result); }