mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-04-24 14:24:54 +00:00
79 lines
2.5 KiB
Python
Executable file
79 lines
2.5 KiB
Python
Executable file
#! /usr/bin/env python3
|
|
|
|
'''
|
|
Run this script from Source/Core/ to find all the #include cycles.
|
|
'''
|
|
|
|
from typing import Iterator
|
|
from pathlib import Path
|
|
|
|
def get_local_includes_for(path: Path) -> Iterator[str]:
|
|
with path.open() as file:
|
|
for line in file:
|
|
line = line.strip()
|
|
if line.startswith("#include") and '"' in line:
|
|
yield line.split()[1].strip(' "')
|
|
|
|
def strongly_connected_components(graph: dict[str, list[str]]) -> list[tuple[str, ...]]:
|
|
"""
|
|
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: str) -> None:
|
|
# 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__':
|
|
paths = Path(".").glob("**/*.h")
|
|
graph = {
|
|
path.as_posix(): list(get_local_includes_for(path))
|
|
for path in paths
|
|
}
|
|
components = strongly_connected_components(graph)
|
|
for component in components:
|
|
if len(component) != 1:
|
|
print(component)
|