forked from dolphin-emu/dolphin
		
	
		
			
	
	
		
			81 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			81 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 
								 | 
							
								#! /usr/bin/env python
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								'''
							 | 
						||
| 
								 | 
							
								Run this script from Source/Core/ to find all the #include cycles.
							 | 
						||
| 
								 | 
							
								'''
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import subprocess
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def get_local_includes_for(path):
							 | 
						||
| 
								 | 
							
								    lines = open(path).read().split('\n')
							 | 
						||
| 
								 | 
							
								    includes = [l.strip() for l in lines if l.strip().startswith('#include')]
							 | 
						||
| 
								 | 
							
								    return [i.split()[1][1:-1] for i in includes if '"' in i.split()[1]]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def find_all_files():
							 | 
						||
| 
								 | 
							
								    '''Could probably use os.walk, but meh.'''
							 | 
						||
| 
								 | 
							
								    f = subprocess.check_output(['find', '.', '-name', '*.h'],
							 | 
						||
| 
								 | 
							
								                                universal_newlines=True).strip().split('\n')
							 | 
						||
| 
								 | 
							
								    return [p[2:] for p in f]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def make_include_graph():
							 | 
						||
| 
								 | 
							
								    return { f: get_local_includes_for(f) for f in find_all_files() }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def strongly_connected_components(graph):
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Tarjan's Algorithm (named for its discoverer, Robert Tarjan) is a graph theory algorithm
							 | 
						||
| 
								 | 
							
								    for finding the strongly connected components of a graph.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Based on: http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    index_counter = [0]
							 | 
						||
| 
								 | 
							
								    stack = []
							 | 
						||
| 
								 | 
							
								    lowlinks = {}
							 | 
						||
| 
								 | 
							
								    index = {}
							 | 
						||
| 
								 | 
							
								    result = []
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def strongconnect(node):
							 | 
						||
| 
								 | 
							
								        # set the depth index for this node to the smallest unused index
							 | 
						||
| 
								 | 
							
								        index[node] = index_counter[0]
							 | 
						||
| 
								 | 
							
								        lowlinks[node] = index_counter[0]
							 | 
						||
| 
								 | 
							
								        index_counter[0] += 1
							 | 
						||
| 
								 | 
							
								        stack.append(node)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # Consider successors of `node`
							 | 
						||
| 
								 | 
							
								        try:
							 | 
						||
| 
								 | 
							
								            successors = graph[node]
							 | 
						||
| 
								 | 
							
								        except:
							 | 
						||
| 
								 | 
							
								            successors = []
							 | 
						||
| 
								 | 
							
								        for successor in successors:
							 | 
						||
| 
								 | 
							
								            if successor not in lowlinks:
							 | 
						||
| 
								 | 
							
								                # Successor has not yet been visited; recurse on it
							 | 
						||
| 
								 | 
							
								                strongconnect(successor)
							 | 
						||
| 
								 | 
							
								                lowlinks[node] = min(lowlinks[node],lowlinks[successor])
							 | 
						||
| 
								 | 
							
								            elif successor in stack:
							 | 
						||
| 
								 | 
							
								                # the successor is in the stack and hence in the current strongly connected component (SCC)
							 | 
						||
| 
								 | 
							
								                lowlinks[node] = min(lowlinks[node],index[successor])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # If `node` is a root node, pop the stack and generate an SCC
							 | 
						||
| 
								 | 
							
								        if lowlinks[node] == index[node]:
							 | 
						||
| 
								 | 
							
								            connected_component = []
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            while True:
							 | 
						||
| 
								 | 
							
								                successor = stack.pop()
							 | 
						||
| 
								 | 
							
								                connected_component.append(successor)
							 | 
						||
| 
								 | 
							
								                if successor == node: break
							 | 
						||
| 
								 | 
							
								            component = tuple(connected_component)
							 | 
						||
| 
								 | 
							
								            # storing the result
							 | 
						||
| 
								 | 
							
								            result.append(component)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for node in graph:
							 | 
						||
| 
								 | 
							
								        if node not in lowlinks:
							 | 
						||
| 
								 | 
							
								            strongconnect(node)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return result
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if __name__ == '__main__':
							 | 
						||
| 
								 | 
							
								    comp = strongly_connected_components(make_include_graph())
							 | 
						||
| 
								 | 
							
								    for c in comp:
							 | 
						||
| 
								 | 
							
								        if len(c) != 1:
							 | 
						||
| 
								 | 
							
								            print(c)
							 |