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 25 26def fix_guards(fpath, checkonly): 27 with open(fpath, 'r', encoding='utf-8') as f: 28 lines = [l.strip('\n') for l in f.readlines()] 29 30 if any(x.startswith('// fix_include_guards: off') for x in lines): 31 return 0 32 33 res = [] 34 guard = re.sub(r'[^a-zA-Z0-9_-]', '_', fpath.upper()) + '_' 35 replacements = 0 36 37 endif_line_idx = -1 38 for line_idx in xrange(len(lines) - 1, -1, -1): 39 if lines[line_idx].startswith('#endif'): 40 endif_line_idx = line_idx 41 break 42 assert endif_line_idx > 0, fpath 43 44 line_idx = 0 45 for line in lines: 46 if replacements == 0 and line.startswith('#ifndef '): 47 line = '#ifndef ' + guard 48 replacements = 1 49 elif replacements == 1 and line.startswith('#define '): 50 line = '#define ' + guard 51 replacements = 2 52 elif line_idx == endif_line_idx and replacements == 2: 53 assert (line.startswith('#endif')) 54 line = '#endif // ' + guard 55 res.append(line) 56 line_idx += 1 57 if res == lines: 58 return 0 59 if checkonly: 60 print('Wrong #include guards in %s' % fpath, file=sys.stderr) 61 return 1 62 with open(fpath, 'w', encoding='utf-8') as f: 63 f.write('\n'.join(res) + '\n') 64 return 1 65 66 67def main(): 68 checkonly = '--check-only' in sys.argv 69 num_files_changed = 0 70 for topdir in ('src', 'include', 'src/profiling/memory/include', 'test', 71 'tools'): 72 for root, dirs, files in os.walk(topdir): 73 for name in files: 74 if not name.endswith('.h'): 75 continue 76 fpath = os.path.join(root, name) 77 num_files_changed += fix_guards(fpath, checkonly) 78 if checkonly: 79 return 0 if num_files_changed == 0 else 1 80 else: 81 print('%d files changed' % num_files_changed) 82 83 84if __name__ == '__main__': 85 sys.exit(main()) 86