3 ###########################################################################
5 # Copyright 2013 BMW Car IT GmbH
7 # Licensed under the Apache License, Version 2.0 (the "License");
8 # you may not use this file except in compliance with the License.
9 # You may obtain a copy of the License at
11 # http://www.apache.org/licenses/LICENSE-2.0
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS,
15 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 # See the License for the specific language governing permissions and
17 # limitations under the License.
19 ###########################################################################
21 import sys, re, string
22 from common_modules.common import *
24 def check_header_guards(filename, file_contents):
26 string_re = re.compile(r'"((?!((?<!((?<!\\)\\))")).)*"', re.DOTALL)
27 file_contents = clean_string_from_regex(file_contents, string_re, 'x')
29 #remove multi-line comments
30 ml_comment_re = re.compile(r'(\s*)/\*((?!\*/).)*\*/', re.DOTALL)
31 file_contents = clean_string_from_regex(file_contents, ml_comment_re, '')
33 #remove single line comments
34 sl_comment_re = re.compile("//.*$", re.MULTILINE)
35 file_contents = re.sub(sl_comment_re, '', file_contents)
37 file_contents = file_contents.strip(" \t\n\f\r")
40 def check_good_name(name):
44 #remove path from filename (if needed)
45 if good_name.count("/") > 0:
46 good_name = good_name[good_name.rfind("/") + 1:]
49 good_name = good_name[:good_name.find(".h")]
51 #good name is all uppercase
52 good_name = good_name.upper()
54 #a good name can start with underscores, and can end with underscores, can optionally have a capital H character
55 good_name_re = re.compile("(_*){0}(_+H?_*)?".format(good_name))
57 return re.match(good_name_re, name) != None
59 #find the ifndef guard
60 ifndef_re = re.compile(r"(\s*)#ifndef .*", re.MULTILINE)
61 ifndef_match = re.match(ifndef_re, file_contents)
62 if ifndef_match == None:
63 log_warning(filename, 1, "header file does not contain a valid #ifndef guard at the beginning")
66 ifndef_match_text = file_contents[:ifndef_match.end()]
67 ifndef_match_text = ifndef_match_text.strip(" \n\r\f\t")
68 splitted_match_text = ifndef_match_text.split(" ")
69 ifndef_guard_name = splitted_match_text[1] if len(splitted_match_text) > 1 else ""
71 if not check_good_name(ifndef_guard_name):
72 log_warning(filename, 1, "#ifndef {0} guard name does not follow convention, name has to contain file name in uppercase".format(ifndef_guard_name))
75 file_contents = file_contents[ifndef_match.end():]
77 #find the define guard
78 define_re = re.compile(r"(\s*)#define .*")
79 define_match = re.match(define_re, file_contents)
80 if define_match == None:
81 log_warning(filename, 1, "header file does not contain a #define guard at the beginning that matches #ifndef {0}".format(ifndef_guard_name))
84 define_match_text = file_contents[:define_match.end()]
85 define_match_text = define_match_text.strip(" \n\r\f\t")
86 splitted_match_text = define_match_text.split(" ")
87 define_guard_name = splitted_match_text[1] if len(splitted_match_text) > 1 else ""
89 if define_guard_name != ifndef_guard_name:
90 log_warning(filename, 1, "header guard names do not match :(#ifndef {0}) and (#define {1})".format(ifndef_guard_name, define_guard_name))
93 endif_re = re.compile(r"#endif.*(\s*)$")
94 endif_match = re.search(endif_re, file_contents)
95 if endif_match == None:
96 log_warning(filename, 1, "header file does not end with #endif at last line")
100 if __name__ == "__main__":
101 targets = sys.argv[1:]
102 targets = get_all_files(targets)
104 if len(targets) == 0:
106 \t**** No input provided ***
107 \tTakes a list of files/directories as input and performs specific style checking on all files/directories
109 \tGives warnings if header guards does not exist in header files. Header files must have a #ifndef and #define guards directly after the license.
110 \tThe names of the header guards must match together and match with the name of the file in uppercase letters.
116 file_contents, _, _, _ = read_file(t)
117 check_header_guards(t, file_contents)