]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/Ecc/Check.py
Sync EDKII BaseTools to BaseTools project r1971
[mirror_edk2.git] / BaseTools / Source / Python / Ecc / Check.py
CommitLineData
30fdf114
LG
1## @file\r
2# This file is used to define checkpoints used by ECC tool\r
3#\r
40d841f6
LG
4# Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>\r
5# This program and the accompanying materials\r
30fdf114
LG
6# are licensed and made available under the terms and conditions of the BSD License\r
7# which accompanies this distribution. The full text of the license may be found at\r
8# http://opensource.org/licenses/bsd-license.php\r
9#\r
10# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12#\r
13import os\r
14import re\r
15from CommonDataClass.DataClass import *\r
16from Common.DataType import SUP_MODULE_LIST_STRING, TAB_VALUE_SPLIT\r
17from EccToolError import *\r
18import EccGlobalData\r
19import c\r
20\r
21## Check\r
22#\r
23# This class is to define checkpoints used by ECC tool\r
24#\r
25# @param object: Inherited from object class\r
26#\r
27class Check(object):\r
28 def __init__(self):\r
29 pass\r
30\r
31 # Check all required checkpoints\r
32 def Check(self):\r
33 self.MetaDataFileCheck()\r
34 self.DoxygenCheck()\r
35 self.IncludeFileCheck()\r
36 self.PredicateExpressionCheck()\r
37 self.DeclAndDataTypeCheck()\r
38 self.FunctionLayoutCheck()\r
39 self.NamingConventionCheck()\r
40\r
41 # C Function Layout Checking\r
42 def FunctionLayoutCheck(self):\r
43 self.FunctionLayoutCheckReturnType()\r
44 self.FunctionLayoutCheckModifier()\r
45 self.FunctionLayoutCheckName()\r
46 self.FunctionLayoutCheckPrototype()\r
47 self.FunctionLayoutCheckBody()\r
48 self.FunctionLayoutCheckLocalVariable()\r
49\r
50 def WalkTree(self):\r
51 IgnoredPattern = c.GetIgnoredDirListPattern()\r
52 for Dirpath, Dirnames, Filenames in os.walk(EccGlobalData.gTarget):\r
53 for Dir in Dirnames:\r
54 Dirname = os.path.join(Dirpath, Dir)\r
55 if os.path.islink(Dirname):\r
56 Dirname = os.path.realpath(Dirname)\r
57 if os.path.isdir(Dirname):\r
58 # symlinks to directories are treated as directories\r
59 Dirnames.remove(Dir)\r
60 Dirnames.append(Dirname)\r
61 if IgnoredPattern.match(Dirpath.upper()):\r
62 continue\r
63 yield (Dirpath, Dirnames, Filenames)\r
64\r
65 # Check whether return type exists and in the first line\r
66 def FunctionLayoutCheckReturnType(self):\r
67 if EccGlobalData.gConfig.CFunctionLayoutCheckReturnType == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
68 EdkLogger.quiet("Checking function layout return type ...")\r
69\r
70 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
71 for F in Filenames:\r
72 if os.path.splitext(F)[1] in ('.c', '.h'):\r
73 FullName = os.path.join(Dirpath, F)\r
74 c.CheckFuncLayoutReturnType(FullName)\r
75\r
76 # Check whether any optional functional modifiers exist and next to the return type\r
77 def FunctionLayoutCheckModifier(self):\r
78 if EccGlobalData.gConfig.CFunctionLayoutCheckOptionalFunctionalModifier == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
79 EdkLogger.quiet("Checking function layout modifier ...")\r
80\r
81 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
82 for F in Filenames:\r
83 if os.path.splitext(F)[1] in ('.c', '.h'):\r
84 FullName = os.path.join(Dirpath, F)\r
85 c.CheckFuncLayoutModifier(FullName)\r
86\r
87 # Check whether the next line contains the function name, left justified, followed by the beginning of the parameter list\r
88 # Check whether the closing parenthesis is on its own line and also indented two spaces\r
89 def FunctionLayoutCheckName(self):\r
90 if EccGlobalData.gConfig.CFunctionLayoutCheckFunctionName == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
91 EdkLogger.quiet("Checking function layout function name ...")\r
92\r
93 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
94 for F in Filenames:\r
95 if os.path.splitext(F)[1] in ('.c', '.h'):\r
96 FullName = os.path.join(Dirpath, F)\r
97 c.CheckFuncLayoutName(FullName)\r
98 # Check whether the function prototypes in include files have the same form as function definitions\r
99 def FunctionLayoutCheckPrototype(self):\r
100 if EccGlobalData.gConfig.CFunctionLayoutCheckFunctionPrototype == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
101 EdkLogger.quiet("Checking function layout function prototype ...")\r
102\r
103 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
104 for F in Filenames:\r
105 if os.path.splitext(F)[1] in ('.c'):\r
106 FullName = os.path.join(Dirpath, F)\r
107 EdkLogger.quiet("[PROTOTYPE]" + FullName)\r
108 c.CheckFuncLayoutPrototype(FullName)\r
109\r
110 # Check whether the body of a function is contained by open and close braces that must be in the first column\r
111 def FunctionLayoutCheckBody(self):\r
112 if EccGlobalData.gConfig.CFunctionLayoutCheckFunctionBody == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
113 EdkLogger.quiet("Checking function layout function body ...")\r
114\r
115 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
116 for F in Filenames:\r
117 if os.path.splitext(F)[1] in ('.c'):\r
118 FullName = os.path.join(Dirpath, F)\r
119 c.CheckFuncLayoutBody(FullName)\r
120\r
121 # Check whether the data declarations is the first code in a module.\r
122 # self.CFunctionLayoutCheckDataDeclaration = 1\r
123 # Check whether no initialization of a variable as part of its declaration\r
124 def FunctionLayoutCheckLocalVariable(self):\r
125 if EccGlobalData.gConfig.CFunctionLayoutCheckNoInitOfVariable == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
126 EdkLogger.quiet("Checking function layout local variables ...")\r
127\r
128 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
129 for F in Filenames:\r
130 if os.path.splitext(F)[1] in ('.c'):\r
131 FullName = os.path.join(Dirpath, F)\r
132 c.CheckFuncLayoutLocalVariable(FullName)\r
133\r
134 # Check whether no use of STATIC for functions\r
135 # self.CFunctionLayoutCheckNoStatic = 1\r
136\r
137 # Declarations and Data Types Checking\r
138 def DeclAndDataTypeCheck(self):\r
139 self.DeclCheckNoUseCType()\r
140 self.DeclCheckInOutModifier()\r
141 self.DeclCheckEFIAPIModifier()\r
142 self.DeclCheckEnumeratedType()\r
143 self.DeclCheckStructureDeclaration()\r
144 self.DeclCheckSameStructure()\r
145 self.DeclCheckUnionType()\r
146\r
147\r
148 # Check whether no use of int, unsigned, char, void, static, long in any .c, .h or .asl files.\r
149 def DeclCheckNoUseCType(self):\r
150 if EccGlobalData.gConfig.DeclarationDataTypeCheckNoUseCType == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
151 EdkLogger.quiet("Checking Declaration No use C type ...")\r
152\r
153 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
154 for F in Filenames:\r
155 if os.path.splitext(F)[1] in ('.h', '.c'):\r
156 FullName = os.path.join(Dirpath, F)\r
157 c.CheckDeclNoUseCType(FullName)\r
158\r
159 # Check whether the modifiers IN, OUT, OPTIONAL, and UNALIGNED are used only to qualify arguments to a function and should not appear in a data type declaration\r
160 def DeclCheckInOutModifier(self):\r
161 if EccGlobalData.gConfig.DeclarationDataTypeCheckInOutModifier == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
162 EdkLogger.quiet("Checking Declaration argument modifier ...")\r
163\r
164 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
165 for F in Filenames:\r
166 if os.path.splitext(F)[1] in ('.h', '.c'):\r
167 FullName = os.path.join(Dirpath, F)\r
168 c.CheckDeclArgModifier(FullName)\r
169\r
170 # Check whether the EFIAPI modifier should be used at the entry of drivers, events, and member functions of protocols\r
171 def DeclCheckEFIAPIModifier(self):\r
172 if EccGlobalData.gConfig.DeclarationDataTypeCheckEFIAPIModifier == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
173 pass\r
174\r
175 # Check whether Enumerated Type has a 'typedef' and the name is capital\r
176 def DeclCheckEnumeratedType(self):\r
177 if EccGlobalData.gConfig.DeclarationDataTypeCheckEnumeratedType == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
178 EdkLogger.quiet("Checking Declaration enum typedef ...")\r
179\r
180 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
181 for F in Filenames:\r
182 if os.path.splitext(F)[1] in ('.h', '.c'):\r
183 FullName = os.path.join(Dirpath, F)\r
184 EdkLogger.quiet("[ENUM]" + FullName)\r
185 c.CheckDeclEnumTypedef(FullName)\r
186\r
187 # Check whether Structure Type has a 'typedef' and the name is capital\r
188 def DeclCheckStructureDeclaration(self):\r
189 if EccGlobalData.gConfig.DeclarationDataTypeCheckStructureDeclaration == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
190 EdkLogger.quiet("Checking Declaration struct typedef ...")\r
191\r
192 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
193 for F in Filenames:\r
194 if os.path.splitext(F)[1] in ('.h', '.c'):\r
195 FullName = os.path.join(Dirpath, F)\r
196 EdkLogger.quiet("[STRUCT]" + FullName)\r
197 c.CheckDeclStructTypedef(FullName)\r
198\r
199 # Check whether having same Structure\r
200 def DeclCheckSameStructure(self):\r
201 if EccGlobalData.gConfig.DeclarationDataTypeCheckSameStructure == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
202 EdkLogger.quiet("Checking same struct ...")\r
203 AllStructure = {}\r
204 for IdentifierTable in EccGlobalData.gIdentifierTableList:\r
205 SqlCommand = """select ID, Name, BelongsToFile from %s where Model = %s""" %(IdentifierTable, MODEL_IDENTIFIER_STRUCTURE)\r
206 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
207 for Record in RecordSet:\r
208 if Record[1] != '':\r
209 if Record[1] not in AllStructure.keys():\r
210 AllStructure[Record[1]] = Record[2]\r
211 else:\r
212 ID = AllStructure[Record[1]]\r
213 SqlCommand = """select FullPath from File where ID = %s """ % ID\r
214 NewRecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
215 OtherMsg = "The structure name '%s' is duplicate" % Record[1]\r
216 if NewRecordSet != []:\r
217 OtherMsg = "The structure name [%s] is duplicate with the one defined in %s, maybe struct NOT typedefed or the typedef new type NOT used to qualify variables" % (Record[1], NewRecordSet[0][0])\r
218 if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_SAME_STRUCTURE, Record[1]):\r
219 EccGlobalData.gDb.TblReport.Insert(ERROR_DECLARATION_DATA_TYPE_CHECK_SAME_STRUCTURE, OtherMsg = OtherMsg, BelongsToTable = IdentifierTable, BelongsToItem = Record[0])\r
220\r
221 # Check whether Union Type has a 'typedef' and the name is capital\r
222 def DeclCheckUnionType(self):\r
223 if EccGlobalData.gConfig.DeclarationDataTypeCheckUnionType == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
224 EdkLogger.quiet("Checking Declaration union typedef ...")\r
225\r
226 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
227 for F in Filenames:\r
228 if os.path.splitext(F)[1] in ('.h', '.c'):\r
229 FullName = os.path.join(Dirpath, F)\r
230 EdkLogger.quiet("[UNION]" + FullName)\r
231 c.CheckDeclUnionTypedef(FullName)\r
232\r
233 # Predicate Expression Checking\r
234 def PredicateExpressionCheck(self):\r
235 self.PredicateExpressionCheckBooleanValue()\r
236 self.PredicateExpressionCheckNonBooleanOperator()\r
237 self.PredicateExpressionCheckComparisonNullType()\r
238\r
239 # Check whether Boolean values, variable type BOOLEAN not use explicit comparisons to TRUE or FALSE\r
240 def PredicateExpressionCheckBooleanValue(self):\r
241 if EccGlobalData.gConfig.PredicateExpressionCheckBooleanValue == '1' or EccGlobalData.gConfig.PredicateExpressionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
242 EdkLogger.quiet("Checking predicate expression Boolean value ...")\r
243\r
244 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
245 for F in Filenames:\r
246 if os.path.splitext(F)[1] in ('.c'):\r
247 FullName = os.path.join(Dirpath, F)\r
248 EdkLogger.quiet("[BOOLEAN]" + FullName)\r
249 c.CheckBooleanValueComparison(FullName)\r
250\r
251 # Check whether Non-Boolean comparisons use a compare operator (==, !=, >, < >=, <=).\r
252 def PredicateExpressionCheckNonBooleanOperator(self):\r
253 if EccGlobalData.gConfig.PredicateExpressionCheckNonBooleanOperator == '1' or EccGlobalData.gConfig.PredicateExpressionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
254 EdkLogger.quiet("Checking predicate expression Non-Boolean variable...")\r
255\r
256 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
257 for F in Filenames:\r
258 if os.path.splitext(F)[1] in ('.c'):\r
259 FullName = os.path.join(Dirpath, F)\r
260 EdkLogger.quiet("[NON-BOOLEAN]" + FullName)\r
261 c.CheckNonBooleanValueComparison(FullName)\r
262 # Check whether a comparison of any pointer to zero must be done via the NULL type\r
263 def PredicateExpressionCheckComparisonNullType(self):\r
264 if EccGlobalData.gConfig.PredicateExpressionCheckComparisonNullType == '1' or EccGlobalData.gConfig.PredicateExpressionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
265 EdkLogger.quiet("Checking predicate expression NULL pointer ...")\r
266\r
267 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
268 for F in Filenames:\r
269 if os.path.splitext(F)[1] in ('.c'):\r
270 FullName = os.path.join(Dirpath, F)\r
271 EdkLogger.quiet("[POINTER]" + FullName)\r
272 c.CheckPointerNullComparison(FullName)\r
273 # Include file checking\r
274 def IncludeFileCheck(self):\r
275 self.IncludeFileCheckIfndef()\r
276 self.IncludeFileCheckData()\r
277 self.IncludeFileCheckSameName()\r
278\r
279 # Check whether having include files with same name\r
280 def IncludeFileCheckSameName(self):\r
281 if EccGlobalData.gConfig.IncludeFileCheckSameName == '1' or EccGlobalData.gConfig.IncludeFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
282 EdkLogger.quiet("Checking same header file name ...")\r
283 SqlCommand = """select ID, FullPath from File\r
284 where Model = 1002 order by Name """\r
285 RecordDict = {}\r
286 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
287 for Record in RecordSet:\r
288 List = Record[1].replace('/', '\\').split('\\')\r
289 if len(List) >= 2:\r
290 Key = List[-2] + '\\' + List[-1]\r
291 else:\r
292 Key = List[0]\r
293 if Key not in RecordDict:\r
294 RecordDict[Key] = [Record]\r
295 else:\r
296 RecordDict[Key].append(Record)\r
297\r
298 for Key in RecordDict:\r
299 if len(RecordDict[Key]) > 1:\r
300 for Item in RecordDict[Key]:\r
52302d4d
LG
301 Path = Item[1].replace(EccGlobalData.gWorkspace, '')\r
302 if Path.startswith('\\') or Path.startswith('/'):\r
303 Path = Path[1:]\r
304 if not EccGlobalData.gException.IsException(ERROR_INCLUDE_FILE_CHECK_NAME, Path):\r
305 EccGlobalData.gDb.TblReport.Insert(ERROR_INCLUDE_FILE_CHECK_NAME, OtherMsg = "The file name for [%s] is duplicate" % Path, BelongsToTable = 'File', BelongsToItem = Item[0])\r
30fdf114
LG
306\r
307 # Check whether all include file contents is guarded by a #ifndef statement.\r
308 def IncludeFileCheckIfndef(self):\r
309 if EccGlobalData.gConfig.IncludeFileCheckIfndefStatement == '1' or EccGlobalData.gConfig.IncludeFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
310 EdkLogger.quiet("Checking header file ifndef ...")\r
311\r
312 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
313 for F in Filenames:\r
314 if os.path.splitext(F)[1] in ('.h'):\r
315 FullName = os.path.join(Dirpath, F)\r
316 MsgList = c.CheckHeaderFileIfndef(FullName)\r
317\r
318 # Check whether include files NOT contain code or define data variables\r
319 def IncludeFileCheckData(self):\r
320 if EccGlobalData.gConfig.IncludeFileCheckData == '1' or EccGlobalData.gConfig.IncludeFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
321 EdkLogger.quiet("Checking header file data ...")\r
322\r
323 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
324 for F in Filenames:\r
325 if os.path.splitext(F)[1] in ('.h'):\r
326 FullName = os.path.join(Dirpath, F)\r
327 MsgList = c.CheckHeaderFileData(FullName)\r
328\r
329 # Doxygen document checking\r
330 def DoxygenCheck(self):\r
331 self.DoxygenCheckFileHeader()\r
332 self.DoxygenCheckFunctionHeader()\r
333 self.DoxygenCheckCommentDescription()\r
334 self.DoxygenCheckCommentFormat()\r
335 self.DoxygenCheckCommand()\r
336\r
337 # Check whether the file headers are followed Doxygen special documentation blocks in section 2.3.5\r
338 def DoxygenCheckFileHeader(self):\r
339 if EccGlobalData.gConfig.DoxygenCheckFileHeader == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
340 EdkLogger.quiet("Checking Doxygen file header ...")\r
341\r
342 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
343 for F in Filenames:\r
40d841f6
LG
344 Ext = os.path.splitext(F)[1]\r
345 if Ext in ('.h', '.c'):\r
30fdf114
LG
346 FullName = os.path.join(Dirpath, F)\r
347 MsgList = c.CheckFileHeaderDoxygenComments(FullName)\r
40d841f6
LG
348 elif Ext in ('.inf', '.dec', '.dsc', '.fdf'):\r
349 FullName = os.path.join(Dirpath, F)\r
350 if not open(FullName).read().startswith('## @file'):\r
351 SqlStatement = """ select ID from File where FullPath like '%s'""" % FullName\r
352 ResultSet = EccGlobalData.gDb.TblFile.Exec(SqlStatement)\r
353 for Result in ResultSet:\r
354 Msg = 'INF/DEC/DSC/FDF file header comment should begin with ""## @file""'\r
355 EccGlobalData.gDb.TblReport.Insert(ERROR_DOXYGEN_CHECK_FILE_HEADER, Msg, "File", Result[0])\r
356 \r
30fdf114
LG
357\r
358 # Check whether the function headers are followed Doxygen special documentation blocks in section 2.3.5\r
359 def DoxygenCheckFunctionHeader(self):\r
360 if EccGlobalData.gConfig.DoxygenCheckFunctionHeader == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
361 EdkLogger.quiet("Checking Doxygen function header ...")\r
362\r
363 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
364 for F in Filenames:\r
365 if os.path.splitext(F)[1] in ('.h', '.c'):\r
366 FullName = os.path.join(Dirpath, F)\r
367 MsgList = c.CheckFuncHeaderDoxygenComments(FullName)\r
368\r
369 # Check whether the first line of text in a comment block is a brief description of the element being documented.\r
370 # The brief description must end with a period.\r
371 def DoxygenCheckCommentDescription(self):\r
372 if EccGlobalData.gConfig.DoxygenCheckCommentDescription == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
373 pass\r
374\r
375 # Check whether comment lines with '///< ... text ...' format, if it is used, it should be after the code section.\r
376 def DoxygenCheckCommentFormat(self):\r
377 if EccGlobalData.gConfig.DoxygenCheckCommentFormat == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
378 EdkLogger.quiet("Checking Doxygen comment ///< ...")\r
379\r
380 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
381 for F in Filenames:\r
382 if os.path.splitext(F)[1] in ('.h', '.c'):\r
383 FullName = os.path.join(Dirpath, F)\r
384 MsgList = c.CheckDoxygenTripleForwardSlash(FullName)\r
385\r
386 # Check whether only Doxygen commands allowed to mark the code are @bug and @todo.\r
387 def DoxygenCheckCommand(self):\r
388 if EccGlobalData.gConfig.DoxygenCheckCommand == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
389 EdkLogger.quiet("Checking Doxygen command ...")\r
390\r
391 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
392 for F in Filenames:\r
393 if os.path.splitext(F)[1] in ('.h', '.c'):\r
394 FullName = os.path.join(Dirpath, F)\r
395 MsgList = c.CheckDoxygenCommand(FullName)\r
396\r
397 # Meta-Data File Processing Checking\r
398 def MetaDataFileCheck(self):\r
399 self.MetaDataFileCheckPathName()\r
400 self.MetaDataFileCheckGenerateFileList()\r
401 self.MetaDataFileCheckLibraryInstance()\r
402 self.MetaDataFileCheckLibraryInstanceDependent()\r
403 self.MetaDataFileCheckLibraryInstanceOrder()\r
404 self.MetaDataFileCheckLibraryNoUse()\r
405 self.MetaDataFileCheckBinaryInfInFdf()\r
406 self.MetaDataFileCheckPcdDuplicate()\r
407 self.MetaDataFileCheckPcdFlash()\r
408 self.MetaDataFileCheckPcdNoUse()\r
409 self.MetaDataFileCheckGuidDuplicate()\r
410 self.MetaDataFileCheckModuleFileNoUse()\r
411 self.MetaDataFileCheckPcdType()\r
40d841f6 412 self.MetaDataFileCheckModuleFileGuidDuplication()\r
30fdf114
LG
413\r
414 # Check whether each file defined in meta-data exists\r
415 def MetaDataFileCheckPathName(self):\r
416 if EccGlobalData.gConfig.MetaDataFileCheckPathName == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
417 # This item is covered when parsing Inf/Dec/Dsc files\r
418 pass\r
419\r
420 # Generate a list for all files defined in meta-data files\r
421 def MetaDataFileCheckGenerateFileList(self):\r
422 if EccGlobalData.gConfig.MetaDataFileCheckGenerateFileList == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
423 # This item is covered when parsing Inf/Dec/Dsc files\r
424 pass\r
425\r
426 # Check whether all Library Instances defined for a given module (or dependent library instance) match the module's type.\r
427 # Each Library Instance must specify the Supported Module Types in its Inf file,\r
428 # and any module specifying the library instance must be one of the supported types.\r
429 def MetaDataFileCheckLibraryInstance(self):\r
430 if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstance == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
431 EdkLogger.quiet("Checking for library instance type issue ...")\r
432 SqlCommand = """select A.ID, A.Value2, B.Value2 from Inf as A left join Inf as B\r
433 where A.Value1 = 'LIBRARY_CLASS' and A.Model = %s\r
434 and B.Value1 = 'MODULE_TYPE' and B.Model = %s and A.BelongsToFile = B.BelongsToFile\r
435 group by A.BelongsToFile""" % (MODEL_META_DATA_HEADER, MODEL_META_DATA_HEADER)\r
436 RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
437 LibraryClasses = {}\r
438 for Record in RecordSet:\r
439 List = Record[1].split('|', 1)\r
440 SupModType = []\r
441 if len(List) == 1:\r
442 SupModType = SUP_MODULE_LIST_STRING.split(TAB_VALUE_SPLIT)\r
443 elif len(List) == 2:\r
444 SupModType = List[1].split()\r
445\r
446 if List[0] not in LibraryClasses:\r
447 LibraryClasses[List[0]] = SupModType\r
448 else:\r
449 for Item in SupModType:\r
450 if Item not in LibraryClasses[List[0]]:\r
451 LibraryClasses[List[0]].append(Item)\r
452\r
453 if Record[2] != 'BASE' and Record[2] not in SupModType:\r
454 EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_2, OtherMsg = "The Library Class '%s' does not specify its supported module types" % (List[0]), BelongsToTable = 'Inf', BelongsToItem = Record[0])\r
455\r
456 SqlCommand = """select A.ID, A.Value1, B.Value2 from Inf as A left join Inf as B\r
457 where A.Model = %s and B.Value1 = '%s' and B.Model = %s\r
458 and B.BelongsToFile = A.BelongsToFile""" \\r
459 % (MODEL_EFI_LIBRARY_CLASS, 'MODULE_TYPE', MODEL_META_DATA_HEADER)\r
460 RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
461 # Merge all LibraryClasses' supmodlist\r
462 RecordDict = {}\r
463 for Record in RecordSet:\r
464 if Record[1] not in RecordDict:\r
465 RecordDict[Record[1]] = [str(Record[2])]\r
466 else:\r
467 if Record[2] not in RecordDict[Record[1]]:\r
468 RecordDict[Record[1]].append(Record[2])\r
469\r
470 for Record in RecordSet:\r
471 if Record[1] in LibraryClasses:\r
472 if Record[2] not in LibraryClasses[Record[1]] and 'BASE' not in RecordDict[Record[1]]:\r
473 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_1, Record[1]):\r
474 EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_1, OtherMsg = "The type of Library Class [%s] defined in Inf file does not match the type of the module" % (Record[1]), BelongsToTable = 'Inf', BelongsToItem = Record[0])\r
475 else:\r
476 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_1, Record[1]):\r
477 EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_1, OtherMsg = "The type of Library Class [%s] defined in Inf file does not match the type of the module" % (Record[1]), BelongsToTable = 'Inf', BelongsToItem = Record[0])\r
478\r
479 # Check whether a Library Instance has been defined for all dependent library classes\r
480 def MetaDataFileCheckLibraryInstanceDependent(self):\r
481 if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstanceDependent == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
482 EdkLogger.quiet("Checking for library instance dependent issue ...")\r
483 SqlCommand = """select ID, Value1, Value2 from Dsc where Model = %s""" % MODEL_EFI_LIBRARY_CLASS\r
484 LibraryClasses = EccGlobalData.gDb.TblDsc.Exec(SqlCommand)\r
485 for LibraryClass in LibraryClasses:\r
486 if LibraryClass[1].upper() != 'NULL':\r
487 LibraryIns = os.path.normpath(os.path.join(EccGlobalData.gWorkspace, LibraryClass[2]))\r
488 SqlCommand = """select Value2 from Inf where BelongsToFile =\r
489 (select ID from File where lower(FullPath) = lower('%s'))\r
490 and Value1 = '%s'""" % (LibraryIns, 'LIBRARY_CLASS')\r
491 RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
492 IsFound = False\r
493 for Record in RecordSet:\r
494 LibName = Record[0].split('|', 1)[0]\r
495 if LibraryClass[1] == LibName:\r
496 IsFound = True\r
497 if not IsFound:\r
498 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_DEPENDENT, LibraryClass[1]):\r
499 EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_DEPENDENT, OtherMsg = "The Library Class [%s] is not specified in '%s'" % (LibraryClass[1], LibraryClass[2]), BelongsToTable = 'Dsc', BelongsToItem = LibraryClass[0])\r
500\r
501 # Check whether the Library Instances specified by the LibraryClasses sections are listed in order of dependencies\r
502 def MetaDataFileCheckLibraryInstanceOrder(self):\r
503 if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstanceOrder == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
504 # This checkpoint is not necessary for Ecc check\r
505 pass\r
506\r
507 # Check whether the unnecessary inclusion of library classes in the Inf file\r
508 def MetaDataFileCheckLibraryNoUse(self):\r
509 if EccGlobalData.gConfig.MetaDataFileCheckLibraryNoUse == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
510 EdkLogger.quiet("Checking for library instance not used ...")\r
511 SqlCommand = """select ID, Value1 from Inf as A where A.Model = %s and A.Value1 not in (select B.Value1 from Dsc as B where Model = %s)""" % (MODEL_EFI_LIBRARY_CLASS, MODEL_EFI_LIBRARY_CLASS)\r
512 RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
513 for Record in RecordSet:\r
514 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_NO_USE, Record[1]):\r
515 EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_LIBRARY_NO_USE, OtherMsg = "The Library Class [%s] is not used in any platform" % (Record[1]), BelongsToTable = 'Inf', BelongsToItem = Record[0])\r
516\r
517 # Check whether an Inf file is specified in the FDF file, but not in the Dsc file, then the Inf file must be for a Binary module only\r
518 def MetaDataFileCheckBinaryInfInFdf(self):\r
519 if EccGlobalData.gConfig.MetaDataFileCheckBinaryInfInFdf == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
520 EdkLogger.quiet("Checking for non-binary modules defined in FDF files ...")\r
521 SqlCommand = """select A.ID, A.Value1 from Fdf as A\r
522 where A.Model = %s\r
523 and A.Enabled > -1\r
524 and A.Value1 not in\r
525 (select B.Value1 from Dsc as B\r
526 where B.Model = %s\r
527 and B.Enabled > -1)""" % (MODEL_META_DATA_COMPONENT, MODEL_META_DATA_COMPONENT)\r
528 RecordSet = EccGlobalData.gDb.TblFdf.Exec(SqlCommand)\r
529 for Record in RecordSet:\r
530 FdfID = Record[0]\r
531 FilePath = Record[1]\r
532 FilePath = os.path.normpath(os.path.join(EccGlobalData.gWorkspace, FilePath))\r
533 SqlCommand = """select ID from Inf where Model = %s and BelongsToFile = (select ID from File where FullPath like '%s')\r
534 """ % (MODEL_EFI_SOURCE_FILE, FilePath)\r
535 NewRecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
536 if NewRecordSet!= []:\r
537 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_BINARY_INF_IN_FDF, FilePath):\r
538 EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_BINARY_INF_IN_FDF, OtherMsg = "File [%s] defined in FDF file and not in DSC file must be a binary module" % (FilePath), BelongsToTable = 'Fdf', BelongsToItem = FdfID)\r
539\r
540 # Check whether a PCD is set in a Dsc file or the FDF file, but not in both.\r
541 def MetaDataFileCheckPcdDuplicate(self):\r
542 if EccGlobalData.gConfig.MetaDataFileCheckPcdDuplicate == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
543 EdkLogger.quiet("Checking for duplicate PCDs defined in both DSC and FDF files ...")\r
544 SqlCommand = """\r
52302d4d 545 select A.ID, A.Value2, A.BelongsToFile, B.ID, B.Value2, B.BelongsToFile from Dsc as A, Fdf as B\r
30fdf114
LG
546 where A.Model >= %s and A.Model < %s\r
547 and B.Model >= %s and B.Model < %s\r
548 and A.Value2 = B.Value2\r
549 and A.Enabled > -1\r
550 and B.Enabled > -1\r
551 group by A.ID\r
552 """% (MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER)\r
553 RecordSet = EccGlobalData.gDb.TblDsc.Exec(SqlCommand)\r
554 for Record in RecordSet:\r
52302d4d
LG
555 SqlCommand1 = """select Name from File where ID = %s""" %Record[2]\r
556 SqlCommand2 = """select Name from File where ID = %s""" %Record[5]\r
557 DscFileName = os.path.splitext(EccGlobalData.gDb.TblDsc.Exec(SqlCommand1)[0][0])[0]\r
558 FdfFileName = os.path.splitext(EccGlobalData.gDb.TblDsc.Exec(SqlCommand2)[0][0])[0]\r
559 print DscFileName, 111, FdfFileName\r
560 if DscFileName != FdfFileName:\r
561 continue\r
30fdf114
LG
562 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, Record[1]):\r
563 EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, OtherMsg = "The PCD [%s] is defined in both FDF file and DSC file" % (Record[1]), BelongsToTable = 'Dsc', BelongsToItem = Record[0])\r
564 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, Record[3]):\r
52302d4d 565 EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, OtherMsg = "The PCD [%s] is defined in both FDF file and DSC file" % (Record[4]), BelongsToTable = 'Fdf', BelongsToItem = Record[3])\r
30fdf114
LG
566\r
567 EdkLogger.quiet("Checking for duplicate PCDs defined in DEC files ...")\r
568 SqlCommand = """\r
569 select A.ID, A.Value2 from Dec as A, Dec as B\r
570 where A.Model >= %s and A.Model < %s\r
571 and B.Model >= %s and B.Model < %s\r
572 and A.Value2 = B.Value2\r
573 and ((A.Arch = B.Arch) and (A.Arch != 'COMMON' or B.Arch != 'COMMON'))\r
574 and A.ID != B.ID\r
575 and A.Enabled > -1\r
576 and B.Enabled > -1\r
577 and A.BelongsToFile = B.BelongsToFile\r
578 group by A.ID\r
579 """% (MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER)\r
580 RecordSet = EccGlobalData.gDb.TblDsc.Exec(SqlCommand)\r
581 for Record in RecordSet:\r
582 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, Record[1]):\r
583 EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, OtherMsg = "The PCD [%s] is defined duplicated in DEC file" % (Record[1]), BelongsToTable = 'Dec', BelongsToItem = Record[0])\r
584\r
585 # Check whether PCD settings in the FDF file can only be related to flash.\r
586 def MetaDataFileCheckPcdFlash(self):\r
587 if EccGlobalData.gConfig.MetaDataFileCheckPcdFlash == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
588 EdkLogger.quiet("Checking only Flash related PCDs are used in FDF ...")\r
589 SqlCommand = """\r
590 select ID, Value2, BelongsToFile from Fdf as A\r
591 where A.Model >= %s and Model < %s\r
592 and A.Enabled > -1\r
593 and A.Value2 not like '%%Flash%%'\r
594 """% (MODEL_PCD, MODEL_META_DATA_HEADER)\r
595 RecordSet = EccGlobalData.gDb.TblFdf.Exec(SqlCommand)\r
596 for Record in RecordSet:\r
597 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_FLASH, Record[1]):\r
598 EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_FLASH, OtherMsg = "The PCD [%s] defined in FDF file is not related to Flash" % (Record[1]), BelongsToTable = 'Fdf', BelongsToItem = Record[0])\r
599\r
600 # Check whether PCDs used in Inf files but not specified in Dsc or FDF files\r
601 def MetaDataFileCheckPcdNoUse(self):\r
602 if EccGlobalData.gConfig.MetaDataFileCheckPcdNoUse == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
603 EdkLogger.quiet("Checking for non-specified PCDs ...")\r
604 SqlCommand = """\r
605 select ID, Value2, BelongsToFile from Inf as A\r
606 where A.Model >= %s and Model < %s\r
607 and A.Enabled > -1\r
608 and A.Value2 not in\r
609 (select Value2 from Dsc as B\r
610 where B.Model >= %s and B.Model < %s\r
611 and B.Enabled > -1)\r
612 and A.Value2 not in\r
613 (select Value2 from Fdf as C\r
614 where C.Model >= %s and C.Model < %s\r
615 and C.Enabled > -1)\r
616 """% (MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER)\r
617 RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
618 for Record in RecordSet:\r
619 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_NO_USE, Record[1]):\r
620 EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_NO_USE, OtherMsg = "The PCD [%s] defined in INF file is not specified in either DSC or FDF files" % (Record[1]), BelongsToTable = 'Inf', BelongsToItem = Record[0])\r
621\r
622 # Check whether having duplicate guids defined for Guid/Protocol/Ppi\r
623 def MetaDataFileCheckGuidDuplicate(self):\r
624 if EccGlobalData.gConfig.MetaDataFileCheckGuidDuplicate == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
625 EdkLogger.quiet("Checking for duplicate GUID/PPI/PROTOCOL ...")\r
626 # Check Guid\r
627 self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID, EccGlobalData.gDb.TblDec)\r
628 self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID, EccGlobalData.gDb.TblDsc)\r
629 self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID)\r
630 # Check protocol\r
631 self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL, EccGlobalData.gDb.TblDec)\r
632 self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL, EccGlobalData.gDb.TblDsc)\r
633 self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL)\r
634 # Check ppi\r
635 self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI, EccGlobalData.gDb.TblDec)\r
636 self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI, EccGlobalData.gDb.TblDsc)\r
637 self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI)\r
638\r
639 # Check whether all files under module directory are described in INF files\r
640 def MetaDataFileCheckModuleFileNoUse(self):\r
641 if EccGlobalData.gConfig.MetaDataFileCheckModuleFileNoUse == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
642 EdkLogger.quiet("Checking for no used module files ...")\r
643 SqlCommand = """\r
644 select upper(Path) from File where ID in (select BelongsToFile from INF where BelongsToFile != -1)\r
645 """\r
646 InfPathSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
647 InfPathList = []\r
648 for Item in InfPathSet:\r
649 if Item[0] not in InfPathList:\r
650 InfPathList.append(Item[0])\r
651 SqlCommand = """\r
652 select ID, Path, FullPath from File where upper(FullPath) not in\r
653 (select upper(A.Path) || '\\' || upper(B.Value1) from File as A, INF as B\r
654 where A.ID in (select BelongsToFile from INF where Model = %s group by BelongsToFile) and\r
655 B.BelongsToFile = A.ID and B.Model = %s)\r
656 and (Model = %s or Model = %s)\r
657 """ % (MODEL_EFI_SOURCE_FILE, MODEL_EFI_SOURCE_FILE, MODEL_FILE_C, MODEL_FILE_H)\r
658 RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
659 for Record in RecordSet:\r
660 Path = Record[1]\r
661 Path = Path.upper().replace('\X64', '').replace('\IA32', '').replace('\EBC', '').replace('\IPF', '').replace('\ARM', '')\r
662 if Path in InfPathList:\r
663 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_MODULE_FILE_NO_USE, Record[2]):\r
664 EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_MODULE_FILE_NO_USE, OtherMsg = "The source file [%s] is existing in module directory but it is not described in INF file." % (Record[2]), BelongsToTable = 'File', BelongsToItem = Record[0])\r
665\r
666 # Check whether the PCD is correctly used in C function via its type\r
667 def MetaDataFileCheckPcdType(self):\r
668 if EccGlobalData.gConfig.MetaDataFileCheckPcdType == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
669 EdkLogger.quiet("Checking for pcd type in c code function usage ...")\r
670 SqlCommand = """\r
671 select ID, Model, Value1, BelongsToFile from INF where Model > %s and Model < %s\r
672 """ % (MODEL_PCD, MODEL_META_DATA_HEADER)\r
673 PcdSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
674 for Pcd in PcdSet:\r
675 Model = Pcd[1]\r
676 PcdName = Pcd[2]\r
677 if len(Pcd[2].split(".")) > 1:\r
678 PcdName = Pcd[2].split(".")[1]\r
679 BelongsToFile = Pcd[3]\r
680 SqlCommand = """\r
681 select ID from File where FullPath in\r
682 (select B.Path || '\\' || A.Value1 from INF as A, File as B where A.Model = %s and A.BelongsToFile = %s\r
683 and B.ID = %s)\r
684 """ %(MODEL_EFI_SOURCE_FILE, BelongsToFile, BelongsToFile)\r
685 TableSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
686 for Tbl in TableSet:\r
687 TblName = 'Identifier' + str(Tbl[0])\r
688 SqlCommand = """\r
52302d4d 689 select Name, ID from %s where value like '%s' and Model = %s\r
30fdf114
LG
690 """ % (TblName, PcdName, MODEL_IDENTIFIER_FUNCTION_CALLING)\r
691 RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
692 TblNumber = TblName.replace('Identifier', '')\r
693 for Record in RecordSet:\r
694 FunName = Record[0]\r
695 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_TYPE, FunName):\r
696 if Model in [MODEL_PCD_FIXED_AT_BUILD] and not FunName.startswith('FixedPcdGet'):\r
697 EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_TYPE, OtherMsg = "The pcd '%s' is defined as a FixPcd but now it is called by c function [%s]" % (PcdName, FunName), BelongsToTable = TblName, BelongsToItem = Record[1])\r
698 if Model in [MODEL_PCD_FEATURE_FLAG] and (not FunName.startswith('FeaturePcdGet') and not FunName.startswith('FeaturePcdSet')):\r
699 EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_TYPE, OtherMsg = "The pcd '%s' is defined as a FeaturePcd but now it is called by c function [%s]" % (PcdName, FunName), BelongsToTable = TblName, BelongsToItem = Record[1])\r
700 if Model in [MODEL_PCD_PATCHABLE_IN_MODULE] and (not FunName.startswith('PatchablePcdGet') and not FunName.startswith('PatchablePcdSet')):\r
701 EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_TYPE, OtherMsg = "The pcd '%s' is defined as a PatchablePcd but now it is called by c function [%s]" % (PcdName, FunName), BelongsToTable = TblName, BelongsToItem = Record[1])\r
702\r
703 #ERROR_META_DATA_FILE_CHECK_PCD_TYPE\r
704 pass\r
705\r
40d841f6
LG
706 # Internal worker function to get the INF workspace relative path from FileID\r
707 def GetInfFilePathFromID(self, FileID):\r
708 Table = EccGlobalData.gDb.TblFile\r
709 SqlCommand = """select A.FullPath from %s as A where A.ID = %s""" % (Table.Table, FileID)\r
710 RecordSet = Table.Exec(SqlCommand)\r
711 Path = ""\r
712 for Record in RecordSet:\r
713 Path = Record[0].replace(EccGlobalData.gWorkspace, '')\r
714 if Path.startswith('\\') or Path.startswith('/'):\r
715 Path = Path[1:]\r
716 return Path\r
717 \r
718 # Check whether two module INFs under one workspace has the same FILE_GUID value\r
719 def MetaDataFileCheckModuleFileGuidDuplication(self):\r
720 if EccGlobalData.gConfig.MetaDataFileCheckModuleFileGuidDuplication == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
721 EdkLogger.quiet("Checking for pcd type in c code function usage ...")\r
722 Table = EccGlobalData.gDb.TblInf\r
723 SqlCommand = """\r
724 select A.ID, A.Value2, A.BelongsToFile, B.BelongsToFile from %s as A, %s as B\r
725 where A.Value1 = 'FILE_GUID' and B.Value1 = 'FILE_GUID' and\r
726 A.Value2 = B.Value2 and A.ID <> B.ID group by A.ID\r
727 """ % (Table.Table, Table.Table)\r
728 RecordSet = Table.Exec(SqlCommand)\r
729 for Record in RecordSet:\r
730 InfPath1 = self.GetInfFilePathFromID(Record[2])\r
731 InfPath2 = self.GetInfFilePathFromID(Record[3])\r
732 if InfPath1 and InfPath2:\r
733 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_MODULE_FILE_GUID_DUPLICATION, InfPath1):\r
734 Msg = "The FILE_GUID of INF file [%s] is duplicated with that of %s" % (InfPath1, InfPath2)\r
735 EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_MODULE_FILE_GUID_DUPLICATION, OtherMsg = Msg, BelongsToTable = Table.Table, BelongsToItem = Record[0])\r
736 \r
737\r
30fdf114
LG
738 # Check whether these is duplicate Guid/Ppi/Protocol name\r
739 def CheckGuidProtocolPpi(self, ErrorID, Model, Table):\r
740 Name = ''\r
741 if Model == MODEL_EFI_GUID:\r
742 Name = 'guid'\r
743 if Model == MODEL_EFI_PROTOCOL:\r
744 Name = 'protocol'\r
745 if Model == MODEL_EFI_PPI:\r
746 Name = 'ppi'\r
747 SqlCommand = """\r
748 select A.ID, A.Value1 from %s as A, %s as B\r
749 where A.Model = %s and B.Model = %s\r
750 and A.Value1 = B.Value1 and A.ID <> B.ID\r
751 and A.Enabled > -1\r
752 and B.Enabled > -1\r
753 group by A.ID\r
754 """ % (Table.Table, Table.Table, Model, Model)\r
755 RecordSet = Table.Exec(SqlCommand)\r
756 for Record in RecordSet:\r
757 if not EccGlobalData.gException.IsException(ErrorID, Record[1]):\r
758 EccGlobalData.gDb.TblReport.Insert(ErrorID, OtherMsg = "The %s name [%s] is defined more than one time" % (Name.upper(), Record[1]), BelongsToTable = Table.Table, BelongsToItem = Record[0])\r
759\r
760 # Check whether these is duplicate Guid/Ppi/Protocol value\r
761 def CheckGuidProtocolPpiValue(self, ErrorID, Model):\r
762 Name = ''\r
763 Table = EccGlobalData.gDb.TblDec\r
764 if Model == MODEL_EFI_GUID:\r
765 Name = 'guid'\r
766 if Model == MODEL_EFI_PROTOCOL:\r
767 Name = 'protocol'\r
768 if Model == MODEL_EFI_PPI:\r
769 Name = 'ppi'\r
770 SqlCommand = """\r
771 select A.ID, A.Value2 from %s as A, %s as B\r
772 where A.Model = %s and B.Model = %s\r
773 and A.Value2 = B.Value2 and A.ID <> B.ID\r
774 group by A.ID\r
775 """ % (Table.Table, Table.Table, Model, Model)\r
776 RecordSet = Table.Exec(SqlCommand)\r
777 for Record in RecordSet:\r
778 if not EccGlobalData.gException.IsException(ErrorID, Record[1]):\r
779 EccGlobalData.gDb.TblReport.Insert(ErrorID, OtherMsg = "The %s value [%s] is used more than one time" % (Name.upper(), Record[1]), BelongsToTable = Table.Table, BelongsToItem = Record[0])\r
780\r
781 # Naming Convention Check\r
782 def NamingConventionCheck(self):\r
52302d4d
LG
783 if EccGlobalData.gConfig.NamingConventionCheckDefineStatement == '1' \\r
784 or EccGlobalData.gConfig.NamingConventionCheckTypedefStatement == '1' \\r
785 or EccGlobalData.gConfig.NamingConventionCheckIfndefStatement == '1' \\r
786 or EccGlobalData.gConfig.NamingConventionCheckVariableName == '1' \\r
787 or EccGlobalData.gConfig.NamingConventionCheckSingleCharacterVariable == '1' \\r
788 or EccGlobalData.gConfig.NamingConventionCheckAll == '1'\\r
789 or EccGlobalData.gConfig.CheckAll == '1':\r
790 for Dirpath, Dirnames, Filenames in self.WalkTree():\r
791 for F in Filenames:\r
792 if os.path.splitext(F)[1] in ('.h', '.c'):\r
793 FullName = os.path.join(Dirpath, F)\r
794 Id = c.GetTableID(FullName)\r
795 if Id < 0:\r
796 continue\r
797 FileTable = 'Identifier' + str(Id)\r
798 self.NamingConventionCheckDefineStatement(FileTable)\r
799 self.NamingConventionCheckTypedefStatement(FileTable)\r
800 self.NamingConventionCheckIfndefStatement(FileTable)\r
801 self.NamingConventionCheckVariableName(FileTable)\r
802 self.NamingConventionCheckSingleCharacterVariable(FileTable)\r
30fdf114
LG
803\r
804 self.NamingConventionCheckPathName()\r
805 self.NamingConventionCheckFunctionName()\r
52302d4d 806\r
30fdf114
LG
807 # Check whether only capital letters are used for #define declarations\r
808 def NamingConventionCheckDefineStatement(self, FileTable):\r
809 if EccGlobalData.gConfig.NamingConventionCheckDefineStatement == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
810 EdkLogger.quiet("Checking naming covention of #define statement ...")\r
52302d4d 811\r
30fdf114
LG
812 SqlCommand = """select ID, Value from %s where Model = %s""" %(FileTable, MODEL_IDENTIFIER_MACRO_DEFINE)\r
813 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
814 for Record in RecordSet:\r
815 Name = Record[1].strip().split()[1]\r
816 if Name.find('(') != -1:\r
817 Name = Name[0:Name.find('(')]\r
818 if Name.upper() != Name:\r
819 if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_DEFINE_STATEMENT, Name):\r
820 EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_DEFINE_STATEMENT, OtherMsg = "The #define name [%s] does not follow the rules" % (Name), BelongsToTable = FileTable, BelongsToItem = Record[0])\r
821\r
822 # Check whether only capital letters are used for typedef declarations\r
823 def NamingConventionCheckTypedefStatement(self, FileTable):\r
824 if EccGlobalData.gConfig.NamingConventionCheckTypedefStatement == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
825 EdkLogger.quiet("Checking naming covention of #typedef statement ...")\r
52302d4d 826\r
30fdf114
LG
827 SqlCommand = """select ID, Name from %s where Model = %s""" %(FileTable, MODEL_IDENTIFIER_TYPEDEF)\r
828 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
829 for Record in RecordSet:\r
830 Name = Record[1].strip()\r
831 if Name != '' and Name != None:\r
832 if Name[0] == '(':\r
833 Name = Name[1:Name.find(')')]\r
834 if Name.find('(') > -1:\r
835 Name = Name[Name.find('(') + 1 : Name.find(')')]\r
836 Name = Name.replace('WINAPI', '')\r
837 Name = Name.replace('*', '').strip()\r
838 if Name.upper() != Name:\r
839 if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_TYPEDEF_STATEMENT, Name):\r
840 EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_TYPEDEF_STATEMENT, OtherMsg = "The #typedef name [%s] does not follow the rules" % (Name), BelongsToTable = FileTable, BelongsToItem = Record[0])\r
841\r
842 # Check whether the #ifndef at the start of an include file uses both prefix and postfix underscore characters, '_'.\r
843 def NamingConventionCheckIfndefStatement(self, FileTable):\r
844 if EccGlobalData.gConfig.NamingConventionCheckTypedefStatement == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
845 EdkLogger.quiet("Checking naming covention of #ifndef statement ...")\r
52302d4d 846\r
30fdf114
LG
847 SqlCommand = """select ID, Value from %s where Model = %s""" %(FileTable, MODEL_IDENTIFIER_MACRO_IFNDEF)\r
848 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
849 for Record in RecordSet:\r
850 Name = Record[1].replace('#ifndef', '').strip()\r
851 if Name[0] != '_' or Name[-1] != '_':\r
852 if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_IFNDEF_STATEMENT, Name):\r
853 EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_IFNDEF_STATEMENT, OtherMsg = "The #ifndef name [%s] does not follow the rules" % (Name), BelongsToTable = FileTable, BelongsToItem = Record[0])\r
854\r
855 # Rule for path name, variable name and function name\r
856 # 1. First character should be upper case\r
857 # 2. Existing lower case in a word\r
858 # 3. No space existence\r
859 # Check whether the path name followed the rule\r
860 def NamingConventionCheckPathName(self):\r
861 if EccGlobalData.gConfig.NamingConventionCheckPathName == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
862 EdkLogger.quiet("Checking naming covention of file path name ...")\r
863 Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')\r
864 SqlCommand = """select ID, Name from File"""\r
865 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
866 for Record in RecordSet:\r
867 if not Pattern.match(Record[1]):\r
868 if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_PATH_NAME, Record[1]):\r
869 EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_PATH_NAME, OtherMsg = "The file path [%s] does not follow the rules" % (Record[1]), BelongsToTable = 'File', BelongsToItem = Record[0])\r
870\r
871 # Rule for path name, variable name and function name\r
872 # 1. First character should be upper case\r
873 # 2. Existing lower case in a word\r
874 # 3. No space existence\r
875 # 4. Global variable name must start with a 'g'\r
876 # Check whether the variable name followed the rule\r
877 def NamingConventionCheckVariableName(self, FileTable):\r
878 if EccGlobalData.gConfig.NamingConventionCheckVariableName == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
879 EdkLogger.quiet("Checking naming covention of variable name ...")\r
880 Pattern = re.compile(r'^[A-Zgm]+\S*[a-z]\S*$')\r
52302d4d 881\r
30fdf114
LG
882 SqlCommand = """select ID, Name from %s where Model = %s""" %(FileTable, MODEL_IDENTIFIER_VARIABLE)\r
883 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
884 for Record in RecordSet:\r
885 if not Pattern.match(Record[1]):\r
886 if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Record[1]):\r
887 EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, OtherMsg = "The variable name [%s] does not follow the rules" % (Record[1]), BelongsToTable = FileTable, BelongsToItem = Record[0])\r
888\r
889 # Rule for path name, variable name and function name\r
890 # 1. First character should be upper case\r
891 # 2. Existing lower case in a word\r
892 # 3. No space existence\r
893 # Check whether the function name followed the rule\r
894 def NamingConventionCheckFunctionName(self):\r
895 if EccGlobalData.gConfig.NamingConventionCheckFunctionName == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
896 EdkLogger.quiet("Checking naming covention of function name ...")\r
897 Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')\r
898 SqlCommand = """select ID, Name from Function"""\r
899 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
900 for Record in RecordSet:\r
901 if not Pattern.match(Record[1]):\r
902 if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_FUNCTION_NAME, Record[1]):\r
903 EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_FUNCTION_NAME, OtherMsg = "The function name [%s] does not follow the rules" % (Record[1]), BelongsToTable = 'Function', BelongsToItem = Record[0])\r
904\r
905 # Check whether NO use short variable name with single character\r
906 def NamingConventionCheckSingleCharacterVariable(self, FileTable):\r
907 if EccGlobalData.gConfig.NamingConventionCheckSingleCharacterVariable == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
908 EdkLogger.quiet("Checking naming covention of single character variable name ...")\r
52302d4d 909\r
30fdf114
LG
910 SqlCommand = """select ID, Name from %s where Model = %s""" %(FileTable, MODEL_IDENTIFIER_VARIABLE)\r
911 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
912 for Record in RecordSet:\r
913 Variable = Record[1].replace('*', '')\r
914 if len(Variable) == 1:\r
915 if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_SINGLE_CHARACTER_VARIABLE, Record[1]):\r
916 EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_SINGLE_CHARACTER_VARIABLE, OtherMsg = "The variable name [%s] does not follow the rules" % (Record[1]), BelongsToTable = FileTable, BelongsToItem = Record[0])\r
917\r
918##\r
919#\r
920# This acts like the main() function for the script, unless it is 'import'ed into another\r
921# script.\r
922#\r
923if __name__ == '__main__':\r
924 Check = Check()\r
925 Check.Check()\r