1b6acf807SRob Herring#!/usr/bin/env python3 2b6acf807SRob Herring# SPDX-License-Identifier: GPL-2.0-only 3b6acf807SRob Herring 4b6acf807SRob Herringimport os 5b6acf807SRob Herringimport glob 6b6acf807SRob Herringimport re 7b6acf807SRob Herringimport argparse 8b6acf807SRob Herring 9b6acf807SRob Herring 10b6acf807SRob Herringdef parse_of_declare_macros(data): 11b6acf807SRob Herring """ Find all compatible strings in OF_DECLARE() style macros """ 12b6acf807SRob Herring compat_list = [] 13b6acf807SRob Herring # CPU_METHOD_OF_DECLARE does not have a compatible string 14b6acf807SRob Herring for m in re.finditer(r'(?<!CPU_METHOD_)(IRQCHIP|OF)_(DECLARE|MATCH)(_DRIVER)?\(.*?\)', data): 15b6acf807SRob Herring try: 16b6acf807SRob Herring compat = re.search(r'"(.*?)"', m[0])[1] 17b6acf807SRob Herring except: 18b6acf807SRob Herring # Fails on compatible strings in #define, so just skip 19b6acf807SRob Herring continue 20b6acf807SRob Herring compat_list += [compat] 21b6acf807SRob Herring 22b6acf807SRob Herring return compat_list 23b6acf807SRob Herring 24b6acf807SRob Herring 25b6acf807SRob Herringdef parse_of_device_id(data): 26b6acf807SRob Herring """ Find all compatible strings in of_device_id structs """ 27b6acf807SRob Herring compat_list = [] 28abe916c5SRob Herring for m in re.finditer(r'of_device_id(\s+\S+)?\s+\S+\[\](\s+\S+)?\s*=\s*({.*?);', data): 29abe916c5SRob Herring compat_list += re.findall(r'\.compatible\s+=\s+"(\S+)"', m[3]) 30b6acf807SRob Herring 31b6acf807SRob Herring return compat_list 32b6acf807SRob Herring 33b6acf807SRob Herring 34b6acf807SRob Herringdef parse_compatibles(file): 35b6acf807SRob Herring with open(file, 'r', encoding='utf-8') as f: 36b6acf807SRob Herring data = f.read().replace('\n', '') 37b6acf807SRob Herring 38b6acf807SRob Herring compat_list = parse_of_declare_macros(data) 39b6acf807SRob Herring compat_list += parse_of_device_id(data) 40b6acf807SRob Herring 41b6acf807SRob Herring return compat_list 42b6acf807SRob Herring 43b6acf807SRob Herringdef print_compat(filename, compatibles): 44b6acf807SRob Herring if not compatibles: 45b6acf807SRob Herring return 46b6acf807SRob Herring if show_filename: 47b6acf807SRob Herring compat_str = ' '.join(compatibles) 48b6acf807SRob Herring print(filename + ": compatible(s): " + compat_str) 49b6acf807SRob Herring else: 50b6acf807SRob Herring print(*compatibles, sep='\n') 51b6acf807SRob Herring 52*c35bcedeSNícolas F. R. A. Pradodef files_to_parse(path_args): 53*c35bcedeSNícolas F. R. A. Prado for f in path_args: 54*c35bcedeSNícolas F. R. A. Prado if os.path.isdir(f): 55*c35bcedeSNícolas F. R. A. Prado for filename in glob.iglob(f + "/**/*.c", recursive=True): 56*c35bcedeSNícolas F. R. A. Prado yield filename 57*c35bcedeSNícolas F. R. A. Prado else: 58*c35bcedeSNícolas F. R. A. Prado yield f 59*c35bcedeSNícolas F. R. A. Prado 60b6acf807SRob Herringshow_filename = False 61b6acf807SRob Herring 62b6acf807SRob Herringif __name__ == "__main__": 63b6acf807SRob Herring ap = argparse.ArgumentParser() 64b6acf807SRob Herring ap.add_argument("cfile", type=str, nargs='*', help="C source files or directories to parse") 65b6acf807SRob Herring ap.add_argument('-H', '--with-filename', help="Print filename with compatibles", action="store_true") 66b6acf807SRob Herring args = ap.parse_args() 67b6acf807SRob Herring 68b6acf807SRob Herring show_filename = args.with_filename 69b6acf807SRob Herring 70*c35bcedeSNícolas F. R. A. Prado for f in files_to_parse(args.cfile): 71b6acf807SRob Herring compat_list = parse_compatibles(f) 72b6acf807SRob Herring print_compat(f, compat_list) 73