xref: /aosp_15_r20/external/perfetto/tools/fix_include_guards (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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