1. In same include file checkpoint, remove "\" of the beginning of file path
[mirror/efi/basetools/.git] / Source / Python / Ecc / Check.py
1 ## @file\r
2 # This file is used to define checkpoints used by ECC tool\r
3 #\r
4 # Copyright (c) 2008 - 2010, Intel Corporation\r
5 # All rights reserved. This program and the accompanying materials\r
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
13 import os\r
14 import re\r
15 from CommonDataClass.DataClass import *\r
16 from Common.DataType import SUP_MODULE_LIST_STRING, TAB_VALUE_SPLIT\r
17 from EccToolError import *\r
18 import EccGlobalData\r
19 import 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
27 class 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
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
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
344                     if os.path.splitext(F)[1] in ('.h', '.c'):\r
345                         FullName = os.path.join(Dirpath, F)\r
346                         MsgList = c.CheckFileHeaderDoxygenComments(FullName)\r
347 \r
348     # Check whether the function headers are followed Doxygen special documentation blocks in section 2.3.5\r
349     def DoxygenCheckFunctionHeader(self):\r
350         if EccGlobalData.gConfig.DoxygenCheckFunctionHeader == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
351             EdkLogger.quiet("Checking Doxygen function header ...")\r
352 \r
353             for Dirpath, Dirnames, Filenames in self.WalkTree():\r
354                 for F in Filenames:\r
355                     if os.path.splitext(F)[1] in ('.h', '.c'):\r
356                         FullName = os.path.join(Dirpath, F)\r
357                         MsgList = c.CheckFuncHeaderDoxygenComments(FullName)\r
358 \r
359     # Check whether the first line of text in a comment block is a brief description of the element being documented.\r
360     # The brief description must end with a period.\r
361     def DoxygenCheckCommentDescription(self):\r
362         if EccGlobalData.gConfig.DoxygenCheckCommentDescription == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
363             pass\r
364 \r
365     # Check whether comment lines with '///< ... text ...' format, if it is used, it should be after the code section.\r
366     def DoxygenCheckCommentFormat(self):\r
367         if EccGlobalData.gConfig.DoxygenCheckCommentFormat == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
368             EdkLogger.quiet("Checking Doxygen comment ///< ...")\r
369 \r
370             for Dirpath, Dirnames, Filenames in self.WalkTree():\r
371                 for F in Filenames:\r
372                     if os.path.splitext(F)[1] in ('.h', '.c'):\r
373                         FullName = os.path.join(Dirpath, F)\r
374                         MsgList = c.CheckDoxygenTripleForwardSlash(FullName)\r
375 \r
376     # Check whether only Doxygen commands allowed to mark the code are @bug and @todo.\r
377     def DoxygenCheckCommand(self):\r
378         if EccGlobalData.gConfig.DoxygenCheckCommand == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
379             EdkLogger.quiet("Checking Doxygen command ...")\r
380 \r
381             for Dirpath, Dirnames, Filenames in self.WalkTree():\r
382                 for F in Filenames:\r
383                     if os.path.splitext(F)[1] in ('.h', '.c'):\r
384                         FullName = os.path.join(Dirpath, F)\r
385                         MsgList = c.CheckDoxygenCommand(FullName)\r
386 \r
387     # Meta-Data File Processing Checking\r
388     def MetaDataFileCheck(self):\r
389         self.MetaDataFileCheckPathName()\r
390         self.MetaDataFileCheckGenerateFileList()\r
391         self.MetaDataFileCheckLibraryInstance()\r
392         self.MetaDataFileCheckLibraryInstanceDependent()\r
393         self.MetaDataFileCheckLibraryInstanceOrder()\r
394         self.MetaDataFileCheckLibraryNoUse()\r
395         self.MetaDataFileCheckBinaryInfInFdf()\r
396         self.MetaDataFileCheckPcdDuplicate()\r
397         self.MetaDataFileCheckPcdFlash()\r
398         self.MetaDataFileCheckPcdNoUse()\r
399         self.MetaDataFileCheckGuidDuplicate()\r
400         self.MetaDataFileCheckModuleFileNoUse()\r
401         self.MetaDataFileCheckPcdType()\r
402 \r
403     # Check whether each file defined in meta-data exists\r
404     def MetaDataFileCheckPathName(self):\r
405         if EccGlobalData.gConfig.MetaDataFileCheckPathName == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
406             # This item is covered when parsing Inf/Dec/Dsc files\r
407             pass\r
408 \r
409     # Generate a list for all files defined in meta-data files\r
410     def MetaDataFileCheckGenerateFileList(self):\r
411         if EccGlobalData.gConfig.MetaDataFileCheckGenerateFileList == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
412             # This item is covered when parsing Inf/Dec/Dsc files\r
413             pass\r
414 \r
415     # Check whether all Library Instances defined for a given module (or dependent library instance) match the module's type.\r
416     # Each Library Instance must specify the Supported Module Types in its Inf file,\r
417     # and any module specifying the library instance must be one of the supported types.\r
418     def MetaDataFileCheckLibraryInstance(self):\r
419         if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstance == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
420             EdkLogger.quiet("Checking for library instance type issue ...")\r
421             SqlCommand = """select A.ID, A.Value2, B.Value2 from Inf as A left join Inf as B\r
422                             where A.Value1 = 'LIBRARY_CLASS' and A.Model = %s\r
423                             and B.Value1 = 'MODULE_TYPE' and B.Model = %s and A.BelongsToFile = B.BelongsToFile\r
424                             group by A.BelongsToFile""" % (MODEL_META_DATA_HEADER, MODEL_META_DATA_HEADER)\r
425             RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
426             LibraryClasses = {}\r
427             for Record in RecordSet:\r
428                 List = Record[1].split('|', 1)\r
429                 SupModType = []\r
430                 if len(List) == 1:\r
431                     SupModType = SUP_MODULE_LIST_STRING.split(TAB_VALUE_SPLIT)\r
432                 elif len(List) == 2:\r
433                     SupModType = List[1].split()\r
434 \r
435                 if List[0] not in LibraryClasses:\r
436                     LibraryClasses[List[0]] = SupModType\r
437                 else:\r
438                     for Item in SupModType:\r
439                         if Item not in LibraryClasses[List[0]]:\r
440                             LibraryClasses[List[0]].append(Item)\r
441 \r
442                 if Record[2] != 'BASE' and Record[2] not in SupModType:\r
443                     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
444 \r
445             SqlCommand = """select A.ID, A.Value1, B.Value2 from Inf as A left join Inf as B\r
446                             where A.Model = %s and B.Value1 = '%s' and B.Model = %s\r
447                             and B.BelongsToFile = A.BelongsToFile""" \\r
448                             % (MODEL_EFI_LIBRARY_CLASS, 'MODULE_TYPE', MODEL_META_DATA_HEADER)\r
449             RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
450             # Merge all LibraryClasses' supmodlist\r
451             RecordDict = {}\r
452             for Record in RecordSet:\r
453                 if Record[1] not in RecordDict:\r
454                     RecordDict[Record[1]] = [str(Record[2])]\r
455                 else:\r
456                     if Record[2] not in RecordDict[Record[1]]:\r
457                         RecordDict[Record[1]].append(Record[2])\r
458 \r
459             for Record in RecordSet:\r
460                 if Record[1] in LibraryClasses:\r
461                     if Record[2] not in LibraryClasses[Record[1]] and 'BASE' not in RecordDict[Record[1]]:\r
462                         if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_1, Record[1]):\r
463                             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
464                 else:\r
465                     if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_1, Record[1]):\r
466                         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
467 \r
468     # Check whether a Library Instance has been defined for all dependent library classes\r
469     def MetaDataFileCheckLibraryInstanceDependent(self):\r
470         if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstanceDependent == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
471             EdkLogger.quiet("Checking for library instance dependent issue ...")\r
472             SqlCommand = """select ID, Value1, Value2 from Dsc where Model = %s""" % MODEL_EFI_LIBRARY_CLASS\r
473             LibraryClasses = EccGlobalData.gDb.TblDsc.Exec(SqlCommand)\r
474             for LibraryClass in LibraryClasses:\r
475                 if LibraryClass[1].upper() != 'NULL':\r
476                     LibraryIns = os.path.normpath(os.path.join(EccGlobalData.gWorkspace, LibraryClass[2]))\r
477                     SqlCommand = """select Value2 from Inf where BelongsToFile =\r
478                                     (select ID from File where lower(FullPath) = lower('%s'))\r
479                                     and Value1 = '%s'""" % (LibraryIns, 'LIBRARY_CLASS')\r
480                     RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
481                     IsFound = False\r
482                     for Record in RecordSet:\r
483                         LibName = Record[0].split('|', 1)[0]\r
484                         if LibraryClass[1] == LibName:\r
485                             IsFound = True\r
486                     if not IsFound:\r
487                         if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_DEPENDENT, LibraryClass[1]):\r
488                             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
489 \r
490     # Check whether the Library Instances specified by the LibraryClasses sections are listed in order of dependencies\r
491     def MetaDataFileCheckLibraryInstanceOrder(self):\r
492         if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstanceOrder == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
493             # This checkpoint is not necessary for Ecc check\r
494             pass\r
495 \r
496     # Check whether the unnecessary inclusion of library classes in the Inf file\r
497     def MetaDataFileCheckLibraryNoUse(self):\r
498         if EccGlobalData.gConfig.MetaDataFileCheckLibraryNoUse == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
499             EdkLogger.quiet("Checking for library instance not used ...")\r
500             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
501             RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
502             for Record in RecordSet:\r
503                 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_NO_USE, Record[1]):\r
504                     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
505 \r
506     # 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
507     def MetaDataFileCheckBinaryInfInFdf(self):\r
508         if EccGlobalData.gConfig.MetaDataFileCheckBinaryInfInFdf == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
509             EdkLogger.quiet("Checking for non-binary modules defined in FDF files ...")\r
510             SqlCommand = """select A.ID, A.Value1 from Fdf as A\r
511                          where A.Model = %s\r
512                          and A.Enabled > -1\r
513                          and A.Value1 not in\r
514                          (select B.Value1 from Dsc as B\r
515                          where B.Model = %s\r
516                          and B.Enabled > -1)""" % (MODEL_META_DATA_COMPONENT, MODEL_META_DATA_COMPONENT)\r
517             RecordSet = EccGlobalData.gDb.TblFdf.Exec(SqlCommand)\r
518             for Record in RecordSet:\r
519                 FdfID = Record[0]\r
520                 FilePath = Record[1]\r
521                 FilePath = os.path.normpath(os.path.join(EccGlobalData.gWorkspace, FilePath))\r
522                 SqlCommand = """select ID from Inf where Model = %s and BelongsToFile = (select ID from File where FullPath like '%s')\r
523                                 """ % (MODEL_EFI_SOURCE_FILE, FilePath)\r
524                 NewRecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
525                 if NewRecordSet!= []:\r
526                     if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_BINARY_INF_IN_FDF, FilePath):\r
527                         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
528 \r
529     # Check whether a PCD is set in a Dsc file or the FDF file, but not in both.\r
530     def MetaDataFileCheckPcdDuplicate(self):\r
531         if EccGlobalData.gConfig.MetaDataFileCheckPcdDuplicate == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
532             EdkLogger.quiet("Checking for duplicate PCDs defined in both DSC and FDF files ...")\r
533             SqlCommand = """\r
534                          select A.ID, A.Value2, A.BelongsToFile, B.ID, B.Value2, B.BelongsToFile from Dsc as A, Fdf as B\r
535                          where A.Model >= %s and A.Model < %s\r
536                          and B.Model >= %s and B.Model < %s\r
537                          and A.Value2 = B.Value2\r
538                          and A.Enabled > -1\r
539                          and B.Enabled > -1\r
540                          group by A.ID\r
541                          """% (MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER)\r
542             RecordSet = EccGlobalData.gDb.TblDsc.Exec(SqlCommand)\r
543             for Record in RecordSet:\r
544                 SqlCommand1 = """select Name from File where ID = %s""" %Record[2]\r
545                 SqlCommand2 = """select Name from File where ID = %s""" %Record[5]\r
546                 DscFileName = os.path.splitext(EccGlobalData.gDb.TblDsc.Exec(SqlCommand1)[0][0])[0]\r
547                 FdfFileName = os.path.splitext(EccGlobalData.gDb.TblDsc.Exec(SqlCommand2)[0][0])[0]\r
548                 print DscFileName, 111, FdfFileName\r
549                 if DscFileName != FdfFileName:\r
550                     continue\r
551                 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, Record[1]):\r
552                     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
553                 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, Record[3]):\r
554                     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
555 \r
556             EdkLogger.quiet("Checking for duplicate PCDs defined in DEC files ...")\r
557             SqlCommand = """\r
558                          select A.ID, A.Value2 from Dec as A, Dec as B\r
559                          where A.Model >= %s and A.Model < %s\r
560                          and B.Model >= %s and B.Model < %s\r
561                          and A.Value2 = B.Value2\r
562                          and ((A.Arch = B.Arch) and (A.Arch != 'COMMON' or B.Arch != 'COMMON'))\r
563                          and A.ID != B.ID\r
564                          and A.Enabled > -1\r
565                          and B.Enabled > -1\r
566                          and A.BelongsToFile = B.BelongsToFile\r
567                          group by A.ID\r
568                          """% (MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER)\r
569             RecordSet = EccGlobalData.gDb.TblDsc.Exec(SqlCommand)\r
570             for Record in RecordSet:\r
571                 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, Record[1]):\r
572                     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
573 \r
574     # Check whether PCD settings in the FDF file can only be related to flash.\r
575     def MetaDataFileCheckPcdFlash(self):\r
576         if EccGlobalData.gConfig.MetaDataFileCheckPcdFlash == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
577             EdkLogger.quiet("Checking only Flash related PCDs are used in FDF ...")\r
578             SqlCommand = """\r
579                          select ID, Value2, BelongsToFile from Fdf as A\r
580                          where A.Model >= %s and Model < %s\r
581                          and A.Enabled > -1\r
582                          and A.Value2 not like '%%Flash%%'\r
583                          """% (MODEL_PCD, MODEL_META_DATA_HEADER)\r
584             RecordSet = EccGlobalData.gDb.TblFdf.Exec(SqlCommand)\r
585             for Record in RecordSet:\r
586                 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_FLASH, Record[1]):\r
587                     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
588 \r
589     # Check whether PCDs used in Inf files but not specified in Dsc or FDF files\r
590     def MetaDataFileCheckPcdNoUse(self):\r
591         if EccGlobalData.gConfig.MetaDataFileCheckPcdNoUse == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
592             EdkLogger.quiet("Checking for non-specified PCDs ...")\r
593             SqlCommand = """\r
594                          select ID, Value2, BelongsToFile from Inf as A\r
595                          where A.Model >= %s and Model < %s\r
596                          and A.Enabled > -1\r
597                          and A.Value2 not in\r
598                              (select Value2 from Dsc as B\r
599                               where B.Model >= %s and B.Model < %s\r
600                               and B.Enabled > -1)\r
601                          and A.Value2 not in\r
602                              (select Value2 from Fdf as C\r
603                               where C.Model >= %s and C.Model < %s\r
604                               and C.Enabled > -1)\r
605                          """% (MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER)\r
606             RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
607             for Record in RecordSet:\r
608                 if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_NO_USE, Record[1]):\r
609                     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
610 \r
611     # Check whether having duplicate guids defined for Guid/Protocol/Ppi\r
612     def MetaDataFileCheckGuidDuplicate(self):\r
613         if EccGlobalData.gConfig.MetaDataFileCheckGuidDuplicate == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
614             EdkLogger.quiet("Checking for duplicate GUID/PPI/PROTOCOL ...")\r
615             # Check Guid\r
616             self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID, EccGlobalData.gDb.TblDec)\r
617             self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID, EccGlobalData.gDb.TblDsc)\r
618             self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID)\r
619             # Check protocol\r
620             self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL, EccGlobalData.gDb.TblDec)\r
621             self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL, EccGlobalData.gDb.TblDsc)\r
622             self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL)\r
623             # Check ppi\r
624             self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI, EccGlobalData.gDb.TblDec)\r
625             self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI, EccGlobalData.gDb.TblDsc)\r
626             self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI)\r
627 \r
628     # Check whether all files under module directory are described in INF files\r
629     def MetaDataFileCheckModuleFileNoUse(self):\r
630         if EccGlobalData.gConfig.MetaDataFileCheckModuleFileNoUse == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
631             EdkLogger.quiet("Checking for no used module files ...")\r
632             SqlCommand = """\r
633                          select upper(Path) from File where ID in (select BelongsToFile from INF where BelongsToFile != -1)\r
634                          """\r
635             InfPathSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
636             InfPathList = []\r
637             for Item in InfPathSet:\r
638                 if Item[0] not in InfPathList:\r
639                     InfPathList.append(Item[0])\r
640             SqlCommand = """\r
641                          select ID, Path, FullPath from File where upper(FullPath) not in\r
642                             (select upper(A.Path) || '\\' || upper(B.Value1) from File as A, INF as B\r
643                             where A.ID in (select BelongsToFile from INF where Model = %s group by BelongsToFile) and\r
644                             B.BelongsToFile = A.ID and B.Model = %s)\r
645                             and (Model = %s or Model = %s)\r
646                         """ % (MODEL_EFI_SOURCE_FILE, MODEL_EFI_SOURCE_FILE, MODEL_FILE_C, MODEL_FILE_H)\r
647             RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
648             for Record in RecordSet:\r
649                 Path = Record[1]\r
650                 Path = Path.upper().replace('\X64', '').replace('\IA32', '').replace('\EBC', '').replace('\IPF', '').replace('\ARM', '')\r
651                 if Path in InfPathList:\r
652                     if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_MODULE_FILE_NO_USE, Record[2]):\r
653                         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
654 \r
655     # Check whether the PCD is correctly used in C function via its type\r
656     def MetaDataFileCheckPcdType(self):\r
657         if EccGlobalData.gConfig.MetaDataFileCheckPcdType == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
658             EdkLogger.quiet("Checking for pcd type in c code function usage ...")\r
659             SqlCommand = """\r
660                          select ID, Model, Value1, BelongsToFile from INF where Model > %s and Model < %s\r
661                          """ % (MODEL_PCD, MODEL_META_DATA_HEADER)\r
662             PcdSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
663             for Pcd in PcdSet:\r
664                 Model = Pcd[1]\r
665                 PcdName = Pcd[2]\r
666                 if len(Pcd[2].split(".")) > 1:\r
667                     PcdName = Pcd[2].split(".")[1]\r
668                 BelongsToFile = Pcd[3]\r
669                 SqlCommand = """\r
670                              select ID from File where FullPath in\r
671                             (select B.Path || '\\' || A.Value1 from INF as A, File as B where A.Model = %s and A.BelongsToFile = %s\r
672                              and B.ID = %s)\r
673                              """ %(MODEL_EFI_SOURCE_FILE, BelongsToFile, BelongsToFile)\r
674                 TableSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
675                 for Tbl in TableSet:\r
676                     TblName = 'Identifier' + str(Tbl[0])\r
677                     SqlCommand = """\r
678                                  select Name, ID from %s where value like '%s' and Model = %s\r
679                                  """ % (TblName, PcdName, MODEL_IDENTIFIER_FUNCTION_CALLING)\r
680                     RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
681                     TblNumber = TblName.replace('Identifier', '')\r
682                     for Record in RecordSet:\r
683                         FunName = Record[0]\r
684                         if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_TYPE, FunName):\r
685                             if Model in [MODEL_PCD_FIXED_AT_BUILD] and not FunName.startswith('FixedPcdGet'):\r
686                                 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
687                             if Model in [MODEL_PCD_FEATURE_FLAG] and (not FunName.startswith('FeaturePcdGet') and not FunName.startswith('FeaturePcdSet')):\r
688                                 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
689                             if Model in [MODEL_PCD_PATCHABLE_IN_MODULE] and (not FunName.startswith('PatchablePcdGet') and not FunName.startswith('PatchablePcdSet')):\r
690                                 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
691 \r
692             #ERROR_META_DATA_FILE_CHECK_PCD_TYPE\r
693         pass\r
694 \r
695     # Check whether these is duplicate Guid/Ppi/Protocol name\r
696     def CheckGuidProtocolPpi(self, ErrorID, Model, Table):\r
697         Name = ''\r
698         if Model == MODEL_EFI_GUID:\r
699             Name = 'guid'\r
700         if Model == MODEL_EFI_PROTOCOL:\r
701             Name = 'protocol'\r
702         if Model == MODEL_EFI_PPI:\r
703             Name = 'ppi'\r
704         SqlCommand = """\r
705                      select A.ID, A.Value1 from %s as A, %s as B\r
706                      where A.Model = %s and B.Model = %s\r
707                      and A.Value1 = B.Value1 and A.ID <> B.ID\r
708                      and A.Enabled > -1\r
709                      and B.Enabled > -1\r
710                      group by A.ID\r
711                      """ % (Table.Table, Table.Table, Model, Model)\r
712         RecordSet = Table.Exec(SqlCommand)\r
713         for Record in RecordSet:\r
714             if not EccGlobalData.gException.IsException(ErrorID, Record[1]):\r
715                 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
716 \r
717     # Check whether these is duplicate Guid/Ppi/Protocol value\r
718     def CheckGuidProtocolPpiValue(self, ErrorID, Model):\r
719         Name = ''\r
720         Table = EccGlobalData.gDb.TblDec\r
721         if Model == MODEL_EFI_GUID:\r
722             Name = 'guid'\r
723         if Model == MODEL_EFI_PROTOCOL:\r
724             Name = 'protocol'\r
725         if Model == MODEL_EFI_PPI:\r
726             Name = 'ppi'\r
727         SqlCommand = """\r
728                      select A.ID, A.Value2 from %s as A, %s as B\r
729                      where A.Model = %s and B.Model = %s\r
730                      and A.Value2 = B.Value2 and A.ID <> B.ID\r
731                      group by A.ID\r
732                      """ % (Table.Table, Table.Table, Model, Model)\r
733         RecordSet = Table.Exec(SqlCommand)\r
734         for Record in RecordSet:\r
735             if not EccGlobalData.gException.IsException(ErrorID, Record[1]):\r
736                 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
737 \r
738     # Naming Convention Check\r
739     def NamingConventionCheck(self):\r
740         if EccGlobalData.gConfig.NamingConventionCheckDefineStatement == '1' \\r
741         or EccGlobalData.gConfig.NamingConventionCheckTypedefStatement == '1' \\r
742         or EccGlobalData.gConfig.NamingConventionCheckIfndefStatement == '1' \\r
743         or EccGlobalData.gConfig.NamingConventionCheckVariableName == '1' \\r
744         or EccGlobalData.gConfig.NamingConventionCheckSingleCharacterVariable == '1' \\r
745         or EccGlobalData.gConfig.NamingConventionCheckAll == '1'\\r
746         or EccGlobalData.gConfig.CheckAll == '1':\r
747             for Dirpath, Dirnames, Filenames in self.WalkTree():\r
748                 for F in Filenames:\r
749                     if os.path.splitext(F)[1] in ('.h', '.c'):\r
750                         FullName = os.path.join(Dirpath, F)\r
751                         Id = c.GetTableID(FullName)\r
752                         if Id < 0:\r
753                             continue\r
754                         FileTable = 'Identifier' + str(Id)\r
755                         self.NamingConventionCheckDefineStatement(FileTable)\r
756                         self.NamingConventionCheckTypedefStatement(FileTable)\r
757                         self.NamingConventionCheckIfndefStatement(FileTable)\r
758                         self.NamingConventionCheckVariableName(FileTable)\r
759                         self.NamingConventionCheckSingleCharacterVariable(FileTable)\r
760 \r
761         self.NamingConventionCheckPathName()\r
762         self.NamingConventionCheckFunctionName()\r
763 \r
764     # Check whether only capital letters are used for #define declarations\r
765     def NamingConventionCheckDefineStatement(self, FileTable):\r
766         if EccGlobalData.gConfig.NamingConventionCheckDefineStatement == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
767             EdkLogger.quiet("Checking naming covention of #define statement ...")\r
768 \r
769             SqlCommand = """select ID, Value from %s where Model = %s""" %(FileTable, MODEL_IDENTIFIER_MACRO_DEFINE)\r
770             RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
771             for Record in RecordSet:\r
772                 Name = Record[1].strip().split()[1]\r
773                 if Name.find('(') != -1:\r
774                     Name = Name[0:Name.find('(')]\r
775                 if Name.upper() != Name:\r
776                     if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_DEFINE_STATEMENT, Name):\r
777                         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
778 \r
779     # Check whether only capital letters are used for typedef declarations\r
780     def NamingConventionCheckTypedefStatement(self, FileTable):\r
781         if EccGlobalData.gConfig.NamingConventionCheckTypedefStatement == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
782             EdkLogger.quiet("Checking naming covention of #typedef statement ...")\r
783 \r
784             SqlCommand = """select ID, Name from %s where Model = %s""" %(FileTable, MODEL_IDENTIFIER_TYPEDEF)\r
785             RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
786             for Record in RecordSet:\r
787                 Name = Record[1].strip()\r
788                 if Name != '' and Name != None:\r
789                     if Name[0] == '(':\r
790                         Name = Name[1:Name.find(')')]\r
791                     if Name.find('(') > -1:\r
792                         Name = Name[Name.find('(') + 1 : Name.find(')')]\r
793                     Name = Name.replace('WINAPI', '')\r
794                     Name = Name.replace('*', '').strip()\r
795                     if Name.upper() != Name:\r
796                         if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_TYPEDEF_STATEMENT, Name):\r
797                             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
798 \r
799     # Check whether the #ifndef at the start of an include file uses both prefix and postfix underscore characters, '_'.\r
800     def NamingConventionCheckIfndefStatement(self, FileTable):\r
801         if EccGlobalData.gConfig.NamingConventionCheckTypedefStatement == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
802             EdkLogger.quiet("Checking naming covention of #ifndef statement ...")\r
803 \r
804             SqlCommand = """select ID, Value from %s where Model = %s""" %(FileTable, MODEL_IDENTIFIER_MACRO_IFNDEF)\r
805             RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
806             for Record in RecordSet:\r
807                 Name = Record[1].replace('#ifndef', '').strip()\r
808                 if Name[0] != '_' or Name[-1] != '_':\r
809                     if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_IFNDEF_STATEMENT, Name):\r
810                         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
811 \r
812     # Rule for path name, variable name and function name\r
813     # 1. First character should be upper case\r
814     # 2. Existing lower case in a word\r
815     # 3. No space existence\r
816     # Check whether the path name followed the rule\r
817     def NamingConventionCheckPathName(self):\r
818         if EccGlobalData.gConfig.NamingConventionCheckPathName == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
819             EdkLogger.quiet("Checking naming covention of file path name ...")\r
820             Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')\r
821             SqlCommand = """select ID, Name from File"""\r
822             RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
823             for Record in RecordSet:\r
824                 if not Pattern.match(Record[1]):\r
825                     if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_PATH_NAME, Record[1]):\r
826                         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
827 \r
828     # Rule for path name, variable name and function name\r
829     # 1. First character should be upper case\r
830     # 2. Existing lower case in a word\r
831     # 3. No space existence\r
832     # 4. Global variable name must start with a 'g'\r
833     # Check whether the variable name followed the rule\r
834     def NamingConventionCheckVariableName(self, FileTable):\r
835         if EccGlobalData.gConfig.NamingConventionCheckVariableName == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
836             EdkLogger.quiet("Checking naming covention of variable name ...")\r
837             Pattern = re.compile(r'^[A-Zgm]+\S*[a-z]\S*$')\r
838 \r
839             SqlCommand = """select ID, Name from %s where Model = %s""" %(FileTable, MODEL_IDENTIFIER_VARIABLE)\r
840             RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
841             for Record in RecordSet:\r
842                 if not Pattern.match(Record[1]):\r
843                     if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Record[1]):\r
844                         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
845 \r
846     # Rule for path name, variable name and function name\r
847     # 1. First character should be upper case\r
848     # 2. Existing lower case in a word\r
849     # 3. No space existence\r
850     # Check whether the function name followed the rule\r
851     def NamingConventionCheckFunctionName(self):\r
852         if EccGlobalData.gConfig.NamingConventionCheckFunctionName == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
853             EdkLogger.quiet("Checking naming covention of function name ...")\r
854             Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')\r
855             SqlCommand = """select ID, Name from Function"""\r
856             RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
857             for Record in RecordSet:\r
858                 if not Pattern.match(Record[1]):\r
859                     if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_FUNCTION_NAME, Record[1]):\r
860                         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
861 \r
862     # Check whether NO use short variable name with single character\r
863     def NamingConventionCheckSingleCharacterVariable(self, FileTable):\r
864         if EccGlobalData.gConfig.NamingConventionCheckSingleCharacterVariable == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
865             EdkLogger.quiet("Checking naming covention of single character variable name ...")\r
866 \r
867             SqlCommand = """select ID, Name from %s where Model = %s""" %(FileTable, MODEL_IDENTIFIER_VARIABLE)\r
868             RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
869             for Record in RecordSet:\r
870                 Variable = Record[1].replace('*', '')\r
871                 if len(Variable) == 1:\r
872                     if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_SINGLE_CHARACTER_VARIABLE, Record[1]):\r
873                         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
874 \r
875 ##\r
876 #\r
877 # This acts like the main() function for the script, unless it is 'import'ed into another\r
878 # script.\r
879 #\r
880 if __name__ == '__main__':\r
881     Check = Check()\r
882     Check.Check()\r