1#!/usr/bin/env python3 2# Copyright (C) 2017 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16from __future__ import print_function 17 18import os 19import re 20import sys 21 22from codecs import open 23from compat import xrange 24 25EXCLUDED_FILES = [ 26 'src/trace_processor/perfetto_sql/preprocessor/preprocessor_grammar.h', 27 'src/trace_processor/perfetto_sql/grammar/perfettosql_grammar.h', 28] 29 30 31def fix_guards(fpath, checkonly): 32 with open(fpath, 'r', encoding='utf-8') as f: 33 lines = [l.strip('\n') for l in f.readlines()] 34 35 if any(x.startswith('// fix_include_guards: off') for x in lines): 36 return 0 37 38 res = [] 39 guard = re.sub(r'[^a-zA-Z0-9_-]', '_', fpath.upper()) + '_' 40 replacements = 0 41 42 endif_line_idx = -1 43 for line_idx in xrange(len(lines) - 1, -1, -1): 44 if lines[line_idx].startswith('#endif'): 45 endif_line_idx = line_idx 46 break 47 assert endif_line_idx > 0, fpath 48 49 line_idx = 0 50 for line in lines: 51 if replacements == 0 and line.startswith('#ifndef '): 52 line = '#ifndef ' + guard 53 replacements = 1 54 elif replacements == 1 and line.startswith('#define '): 55 line = '#define ' + guard 56 replacements = 2 57 elif line_idx == endif_line_idx and replacements == 2: 58 assert (line.startswith('#endif')) 59 line = '#endif // ' + guard 60 res.append(line) 61 line_idx += 1 62 if res == lines: 63 return 0 64 if checkonly: 65 print('Wrong #include guards in %s' % fpath, file=sys.stderr) 66 return 1 67 with open(fpath, 'w', encoding='utf-8') as f: 68 f.write('\n'.join(res) + '\n') 69 return 1 70 71 72def main(): 73 checkonly = '--check-only' in sys.argv 74 num_files_changed = 0 75 for topdir in ('src', 'include', 'src/profiling/memory/include', 'test', 76 'tools'): 77 for root, dirs, files in os.walk(topdir): 78 for name in files: 79 if not name.endswith('.h'): 80 continue 81 fpath = os.path.join(root, name) 82 if fpath in EXCLUDED_FILES: 83 continue 84 num_files_changed += fix_guards(fpath, checkonly) 85 if checkonly: 86 return 0 if num_files_changed == 0 else 1 87 else: 88 print('%d files changed' % num_files_changed) 89 90 91if __name__ == '__main__': 92 sys.exit(main()) 93