Added python scripts to check code style
[profile/ivi/layer-management.git] / scripts / check_header_guards.py
1 #!/usr/bin/python
2
3 ###########################################################################
4 #
5 # Copyright 2013 BMW Car IT GmbH
6 #
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
10 #
11 #        http://www.apache.org/licenses/LICENSE-2.0
12 #
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.
18 #
19 ###########################################################################
20
21 import sys, re, string
22 from common_modules.common import *
23
24 def check_header_guards(filename, file_contents):
25     #remove strings
26     string_re = re.compile(r'"((?!((?<!((?<!\\)\\))")).)*"', re.DOTALL)
27     file_contents = clean_string_from_regex(file_contents, string_re, 'x')
28
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, '')
32     
33     #remove single line comments
34     sl_comment_re = re.compile("//.*$", re.MULTILINE)
35     file_contents = re.sub(sl_comment_re, '', file_contents)
36     
37     file_contents = file_contents.strip(" \t\n\f\r")
38
39     
40     def check_good_name(name):
41         #good name
42         good_name = filename
43         
44         #remove path from filename (if needed)
45         if good_name.count("/") > 0:
46             good_name = good_name[good_name.rfind("/") + 1:]
47         
48         #remove .h extension
49         good_name = good_name[:good_name.find(".h")]
50         
51         #good name is all uppercase
52         good_name = good_name.upper()
53         
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))
56         
57         return re.match(good_name_re, name) != None
58     
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")
64         return None
65     
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 ""
70     
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))
73         return None
74     
75     file_contents = file_contents[ifndef_match.end():]
76     
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))
82         return None
83     
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 ""
88     
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))
91     
92     #find the endif guard
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")
97         return None
98
99
100 if __name__ == "__main__":
101     targets = sys.argv[1:]
102     targets = get_all_files(targets)
103     
104     if len(targets) == 0:
105         print """
106 \t**** No input provided ***
107 \tTakes a list of files/directories as input and performs specific style checking on all files/directories
108
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.
111 """
112         exit(0)
113     
114     for t in targets:
115         if t[-2:] == ".h":
116             file_contents, _, _, _ = read_file(t)
117             check_header_guards(t, file_contents)