1#!/usr/bin/env python3 2# 3# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 4# 5# SPDX-License-Identifier: BSD-2-Clause 6# 7 8""" 9Script for reporting circular #includes in pre-processed sel4 source. 10Exits with a status of 0 if no circular dependencies are found, otherwise 11prints circular dependency and exits with a status of -1. 12""" 13 14import sys 15import re 16import argparse 17 18 19def main(parse_args): 20 """ 21 Reads pre-processed sel4 source from standard input. 22 If a circular dependency is found, the chain of includes 23 resulting in the loop is printed out. 24 """ 25 26 ignore_re = None 27 ignore_args = parse_args.ignore 28 if ignore_args and len(ignore_args): 29 ignore_args = [re.escape(ignore) for ignore in ignore_args] 30 ignore_re_string = '(' + '|'.join(ignore_args) + ')' 31 ignore_re = re.compile(r'^# [01] ".*' + ignore_re_string + '"') 32 33 header_re = re.compile(r'^# (\d+) "(.*\..)"') 34 35 file_stack = [] 36 37 for line in sys.stdin: 38 39 if ignore_re and ignore_re.match(line): 40 continue 41 42 match = header_re.match(line) 43 44 if match is None: 45 continue 46 47 depth = int(match.group(1)) 48 header = match.group(2) 49 50 if depth == 1: 51 # found a new header 52 if header in file_stack: 53 print("Circular includes found:") 54 print("\n".join(file_stack)) 55 print(header) 56 return -1 57 else: 58 file_stack.append(header) 59 else: 60 # popped back up to an earlier header 61 while (len(file_stack) > 0) and (file_stack[-1] != header): 62 file_stack.pop() 63 64 return 0 65 66 67if __name__ == "__main__": 68 69 parser = argparse.ArgumentParser() 70 parser.add_argument('--ignore', nargs='+', 71 help="Files to ignore when parsing the sel4 source") 72 args = parser.parse_args() 73 74 sys.exit(main(args)) 75