/* * Copyright 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.gwt.dev.jjs.impl.gflow.cfg; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * Control flow graph printer. Prints all nodes and all their edges. */ public class CfgPrinter { private final Cfg graph; public CfgPrinter(Cfg graph) { this.graph = graph; } public String print() { StringBuffer result = new StringBuffer(); List<CfgNode<?>> nodes = graph.getNodes(); // Determine nodes which have edges incoming not from previous node. Set<CfgNode<?>> targetNodes = new HashSet<CfgNode<?>>(); for (int i = 1; i < nodes.size(); ++i) { CfgNode<?> node = nodes.get(i); List<CfgEdge> inEdges = graph.getInEdges(node); for (CfgEdge inEdge : inEdges) { if (inEdge.getStart() != null && inEdge.getStart() != nodes.get(i - 1)) { targetNodes.add(node); } } } Map<CfgNode<?>, String> labels = new HashMap<CfgNode<?>, String>(); for (int i = 0, j = 1; i < nodes.size(); ++i) { if (targetNodes.contains(nodes.get(i))) { labels.put(nodes.get(i), String.valueOf(j)); ++j; } } for (int i = 0; i < nodes.size(); ++i) { CfgNode<?> node = nodes.get(i); if (i != 0) { result.append("\n"); } if (labels.containsKey(node)) { result.append(labels.get(node)); result.append(": "); } result.append(node.toDebugString()); { List<CfgEdge> out = graph.getOutEdges(node); if (!out.isEmpty()) { result.append(" -> ["); for (int j = 0; j < out.size(); ++j) { if (j > 0) { result.append(", "); } CfgEdge edge = out.get(j); if (edge.getRole() != null) { result.append(edge.getRole()); result.append("="); } if (i + 1 < nodes.size() && edge.getEnd() != nodes.get(i + 1)) { result.append(labels.get(edge.getEnd())); } else { result.append("*"); } appendEdgeInfo(result, edge); } result.append("]"); } } } return result.toString(); } /** * Template method to append arbitrary edge information. */ protected void appendEdgeInfo(@SuppressWarnings("unused") StringBuffer result, @SuppressWarnings("unused") CfgEdge edge) { // Overridden by ancestors. } }