1. Update Dsc table for the library instance defined component section
[people/mcb30/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, 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 EccToolError import *\r
17 import EccGlobalData\r
18 import c\r
19 \r
20 ## Check\r
21 #\r
22 # This class is to define checkpoints used by ECC tool\r
23 #\r
24 # @param object:          Inherited from object class\r
25 #\r
26 class Check(object):\r
27     def __init__(self):\r
28         pass\r
29      \r
30     #\r
31     # Check all required checkpoints\r
32     #   \r
33     def Check(self):\r
34         self.MetaDataFileCheck()\r
35         self.DoxygenCheck()\r
36         self.IncludeFileCheck()\r
37         self.PredicateExpressionCheck()\r
38         self.DeclAndDataTypeCheck()\r
39         self.NamingConventionCheck()\r
40     \r
41     #\r
42     # Declarations and Data Types Checking\r
43     #\r
44     def DeclAndDataTypeCheck(self):\r
45         self.DeclCheckNoUseCType()\r
46         self.DeclCheckInOutModifier()\r
47         self.DeclCheckEFIAPIModifier()\r
48         self.DeclCheckEnumeratedType()\r
49         self.DeclCheckStructureDeclaration()\r
50         self.DeclCheckUnionType()\r
51     \r
52     \r
53     # Check whether no use of int, unsigned, char, void, static, long in any .c, .h or .asl files.\r
54     def DeclCheckNoUseCType(self):\r
55         if EccGlobalData.gConfig.DeclarationDataTypeCheckNoUseCType == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1':\r
56             EdkLogger.quiet("Checking Declaration No use C type ...")\r
57             Tuple = os.walk(EccGlobalData.gTarget)\r
58             IgnoredPattern = re.compile(r'.*[\\/](?:BUILD|CVS|\.SVN|INTELRESTRICTEDTOOLS|INTELRESTRICTEDPKG)[\\/].*')\r
59         \r
60             for Dirpath, Dirnames, Filenames in Tuple:\r
61                 if IgnoredPattern.match(Dirpath.upper()) or Dirpath.find('.svn') != -1:\r
62                     continue\r
63                 for F in Filenames:\r
64                     if os.path.splitext(F)[1] in ('.h', '.c'):\r
65                         FullName = os.path.join(Dirpath, F)\r
66                         c.CheckDeclNoUseCType(FullName)\r
67     \r
68     # 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
69     def DeclCheckInOutModifier(self):\r
70         if EccGlobalData.gConfig.DeclarationDataTypeCheckInOutModifier == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1':\r
71             EdkLogger.quiet("Checking Declaration argument modifier ...")\r
72             Tuple = os.walk(EccGlobalData.gTarget)\r
73             IgnoredPattern = re.compile(r'.*[\\/](?:BUILD|CVS|\.SVN|INTELRESTRICTEDTOOLS|INTELRESTRICTEDPKG)[\\/].*')\r
74         \r
75             for Dirpath, Dirnames, Filenames in Tuple:\r
76                 if IgnoredPattern.match(Dirpath.upper()) or Dirpath.find('.svn') != -1:\r
77                     continue\r
78                 for F in Filenames:\r
79                     if os.path.splitext(F)[1] in ('.h', '.c'):\r
80                         FullName = os.path.join(Dirpath, F)\r
81                         c.CheckDeclArgModifier(FullName)\r
82     \r
83     # Check whether the EFIAPI modifier should be used at the entry of drivers, events, and member functions of protocols\r
84     def DeclCheckEFIAPIModifier(self):\r
85         if EccGlobalData.gConfig.DeclarationDataTypeCheckEFIAPIModifier == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1':\r
86             pass\r
87     \r
88     # Check whether Enumerated Type has a 'typedef' and the name is capital\r
89     def DeclCheckEnumeratedType(self):\r
90         if EccGlobalData.gConfig.DeclarationDataTypeCheckEnumeratedType == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1':\r
91             pass\r
92     \r
93     # Check whether Structure Type has a 'typedef' and the name is capital\r
94     def DeclCheckStructureDeclaration(self):\r
95         if EccGlobalData.gConfig.DeclarationDataTypeCheckStructureDeclaration == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1':\r
96             pass\r
97     \r
98     # Check whether Union Type has a 'typedef' and the name is capital\r
99     def DeclCheckUnionType(self):\r
100         if EccGlobalData.gConfig.DeclarationDataTypeCheckUnionType == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1':\r
101             pass\r
102     \r
103     #\r
104     # Predicate Expression Checking\r
105     #\r
106     def PredicateExpressionCheck(self):\r
107         self.PredicateExpressionCheckBooleanValue()\r
108         self.PredicateExpressionCheckNonBooleanOperator()\r
109         self.PredicateExpressionCheckComparisonNullType()\r
110     \r
111     # Check whether Boolean values, variable type BOOLEAN not use explicit comparisons to TRUE or FALSE\r
112     def PredicateExpressionCheckBooleanValue(self):\r
113         if EccGlobalData.gConfig.PredicateExpressionCheckBooleanValue == '1' or EccGlobalData.gConfig.PredicateExpressionCheckAll == '1':\r
114             EdkLogger.quiet("Checking predicate expression Boolean value ...")\r
115             Tuple = os.walk(EccGlobalData.gTarget)\r
116             IgnoredPattern = re.compile(r'.*[\\/](?:BUILD|CVS|\.SVN|INTELRESTRICTEDTOOLS|INTELRESTRICTEDPKG)[\\/].*')\r
117         \r
118             for Dirpath, Dirnames, Filenames in Tuple:\r
119                 if IgnoredPattern.match(Dirpath.upper()) or Dirpath.find('.svn') != -1:\r
120                     continue\r
121                 for F in Filenames:\r
122                     if os.path.splitext(F)[1] in ('.c'):\r
123                         FullName = os.path.join(Dirpath, F)\r
124                         c.CheckBooleanValueComparison(FullName)\r
125     # Check whether Non-Boolean comparisons use a compare operator (==, !=, >, < >=, <=). \r
126     def PredicateExpressionCheckNonBooleanOperator(self):\r
127         if EccGlobalData.gConfig.PredicateExpressionCheckNonBooleanOperator == '1' or EccGlobalData.gConfig.PredicateExpressionCheckAll == '1':\r
128             EdkLogger.quiet("Checking predicate expression Non-Boolean variable...")\r
129             Tuple = os.walk(EccGlobalData.gTarget)\r
130             IgnoredPattern = re.compile(r'.*[\\/](?:BUILD|CVS|\.SVN|INTELRESTRICTEDTOOLS|INTELRESTRICTEDPKG)[\\/].*')\r
131         \r
132             for Dirpath, Dirnames, Filenames in Tuple:\r
133                 if IgnoredPattern.match(Dirpath.upper()) or Dirpath.find('.svn') != -1:\r
134                     continue\r
135                 for F in Filenames:\r
136                     if os.path.splitext(F)[1] in ('.c'):\r
137                         FullName = os.path.join(Dirpath, F)\r
138                         c.CheckNonBooleanValueComparison(FullName)\r
139     # Check whether a comparison of any pointer to zero must be done via the NULL type\r
140     def PredicateExpressionCheckComparisonNullType(self):\r
141         if EccGlobalData.gConfig.PredicateExpressionCheckComparisonNullType == '1' or EccGlobalData.gConfig.PredicateExpressionCheckAll == '1':\r
142             EdkLogger.quiet("Checking predicate expression NULL pointer ...")\r
143             Tuple = os.walk(EccGlobalData.gTarget)\r
144             IgnoredPattern = re.compile(r'.*[\\/](?:BUILD|CVS|\.SVN|INTELRESTRICTEDTOOLS|INTELRESTRICTEDPKG)[\\/].*')\r
145         \r
146             for Dirpath, Dirnames, Filenames in Tuple:\r
147                 if IgnoredPattern.match(Dirpath.upper()) or Dirpath.find('.svn') != -1:\r
148                     continue\r
149                 for F in Filenames:\r
150                     if os.path.splitext(F)[1] in ('.c'):\r
151                         FullName = os.path.join(Dirpath, F)\r
152                         c.CheckPointerNullComparison(FullName)\r
153     #\r
154     # Include file checking\r
155     #\r
156     def IncludeFileCheck(self):\r
157         self.IncludeFileCheckIfndef()\r
158         self.IncludeFileCheckData()\r
159     \r
160     #\r
161     # Check whether all include file contents is guarded by a #ifndef statement.\r
162     #\r
163     def IncludeFileCheckIfndef(self):\r
164         if EccGlobalData.gConfig.IncludeFileCheckIfndefStatement == '1' or EccGlobalData.gConfig.IncludeFileCheckAll == '1':\r
165             EdkLogger.quiet("Checking header file ifndef ...")\r
166             Tuple = os.walk(EccGlobalData.gTarget)\r
167             IgnoredPattern = re.compile(r'.*[\\/](?:BUILD|CVS|\.SVN|INTELRESTRICTEDTOOLS|INTELRESTRICTEDPKG)[\\/].*')\r
168         \r
169             for Dirpath, Dirnames, Filenames in Tuple:\r
170                 if IgnoredPattern.match(Dirpath.upper()) or Dirpath.find('.svn') != -1:\r
171                     continue\r
172                 for F in Filenames:\r
173                     if os.path.splitext(F)[1] in ('.h'):\r
174                         FullName = os.path.join(Dirpath, F)\r
175                         MsgList = c.CheckHeaderFileIfndef(FullName)\r
176     \r
177     #\r
178     # Check whether include files NOT contain code or define data variables\r
179     #\r
180     def IncludeFileCheckData(self):\r
181         if EccGlobalData.gConfig.IncludeFileCheckData == '1' or EccGlobalData.gConfig.IncludeFileCheckAll == '1':\r
182             EdkLogger.quiet("Checking header file data ...")\r
183             Tuple = os.walk(EccGlobalData.gTarget)\r
184             IgnoredPattern = re.compile(r'.*[\\/](?:BUILD|CVS|\.SVN|INTELRESTRICTEDTOOLS|INTELRESTRICTEDPKG)[\\/].*')\r
185         \r
186             for Dirpath, Dirnames, Filenames in Tuple:\r
187                 if IgnoredPattern.match(Dirpath.upper()) or Dirpath.find('.svn') != -1:\r
188                     continue\r
189                 for F in Filenames:\r
190                     if os.path.splitext(F)[1] in ('.h'):\r
191                         FullName = os.path.join(Dirpath, F)\r
192                         MsgList = c.CheckHeaderFileData(FullName)\r
193         \r
194     #\r
195     # Doxygen document checking\r
196     #\r
197     def DoxygenCheck(self):\r
198         self.DoxygenCheckFileHeader()\r
199         self.DoxygenCheckFunctionHeader()\r
200         self.DoxygenCheckCommentDescription()\r
201         self.DoxygenCheckCommentFormat()\r
202         self.DoxygenCheckCommand()\r
203     \r
204     #\r
205     # Check whether the file headers are followed Doxygen special documentation blocks in section 2.3.5\r
206     #\r
207     def DoxygenCheckFileHeader(self):\r
208         if EccGlobalData.gConfig.DoxygenCheckFileHeader == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1':\r
209             EdkLogger.quiet("Checking Doxygen file header ...")\r
210             Tuple = os.walk(EccGlobalData.gTarget)\r
211             IgnoredPattern = re.compile(r'.*[\\/](?:BUILD|CVS|\.SVN|INTELRESTRICTEDTOOLS|INTELRESTRICTEDPKG)[\\/].*')\r
212         \r
213             for Dirpath, Dirnames, Filenames in Tuple:\r
214                 if IgnoredPattern.match(Dirpath.upper()) or Dirpath.find('.svn') != -1:\r
215                     continue\r
216                 for F in Filenames:\r
217                     if os.path.splitext(F)[1] in ('.h', '.c'):\r
218                         FullName = os.path.join(Dirpath, F)\r
219                         MsgList = c.CheckFileHeaderDoxygenComments(FullName)\r
220     \r
221     #\r
222     # Check whether the function headers are followed Doxygen special documentation blocks in section 2.3.5\r
223     #\r
224     def DoxygenCheckFunctionHeader(self):\r
225         if EccGlobalData.gConfig.DoxygenCheckFunctionHeader == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1':\r
226             EdkLogger.quiet("Checking Doxygen function header ...")\r
227             Tuple = os.walk(EccGlobalData.gTarget)\r
228             IgnoredPattern = re.compile(r'.*[\\/](?:BUILD|CVS|\.SVN|INTELRESTRICTEDTOOLS|INTELRESTRICTEDPKG)[\\/].*')\r
229 #            ParseErrorFileList = []\r
230         \r
231             for Dirpath, Dirnames, Filenames in Tuple:\r
232                 if IgnoredPattern.match(Dirpath.upper()) or Dirpath.find('.svn') != -1:\r
233                     continue\r
234                 for F in Filenames:\r
235                     if os.path.splitext(F)[1] in ('.h', '.c'):\r
236                         FullName = os.path.join(Dirpath, F)\r
237                         MsgList = c.CheckFuncHeaderDoxygenComments(FullName)\r
238 #                        for Msg in MsgList:\r
239 #                            print Msg                \r
240                             \r
241     #\r
242     # Check whether the first line of text in a comment block is a brief description of the element being documented. \r
243     # The brief description must end with a period.\r
244     #\r
245     def DoxygenCheckCommentDescription(self):\r
246         if EccGlobalData.gConfig.DoxygenCheckCommentDescription == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1':\r
247             pass\r
248 \r
249     #\r
250     # Check whether comment lines with '///< ... text ...' format, if it is used, it should be after the code section.\r
251     #\r
252     def DoxygenCheckCommentFormat(self):\r
253         if EccGlobalData.gConfig.DoxygenCheckCommentFormat == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1':\r
254             EdkLogger.quiet("Checking Doxygen comment ///< ...")\r
255             Tuple = os.walk(EccGlobalData.gTarget)\r
256             IgnoredPattern = re.compile(r'.*[\\/](?:BUILD|CVS|\.SVN|INTELRESTRICTEDTOOLS|INTELRESTRICTEDPKG)[\\/].*')\r
257         \r
258             for Dirpath, Dirnames, Filenames in Tuple:\r
259                 if IgnoredPattern.match(Dirpath.upper()) or Dirpath.find('.svn') != -1:\r
260                     continue\r
261                 for F in Filenames:\r
262                     if os.path.splitext(F)[1] in ('.h', '.c'):\r
263                         FullName = os.path.join(Dirpath, F)\r
264                         MsgList = c.CheckDoxygenTripleForwardSlash(FullName)\r
265         \r
266     #\r
267     # Check whether only Doxygen commands allowed to mark the code are @bug and @todo.\r
268     #\r
269     def DoxygenCheckCommand(self):\r
270         if EccGlobalData.gConfig.DoxygenCheckCommand == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1':\r
271             EdkLogger.quiet("Checking Doxygen command ...")\r
272             Tuple = os.walk(EccGlobalData.gTarget)\r
273             IgnoredPattern = re.compile(r'.*[\\/](?:BUILD|CVS|\.SVN|INTELRESTRICTEDTOOLS|INTELRESTRICTEDPKG)[\\/].*')\r
274         \r
275             for Dirpath, Dirnames, Filenames in Tuple:\r
276                 if IgnoredPattern.match(Dirpath.upper()) or Dirpath.find('.svn') != -1:\r
277                     continue\r
278                 for F in Filenames:\r
279                     if os.path.splitext(F)[1] in ('.h', '.c'):\r
280                         FullName = os.path.join(Dirpath, F)\r
281                         MsgList = c.CheckDoxygenCommand(FullName)\r
282     \r
283     #\r
284     # Meta-Data File Processing Checking\r
285     #\r
286     def MetaDataFileCheck(self):\r
287         self.MetaDataFileCheckPathName()\r
288         self.MetaDataFileCheckGenerateFileList()\r
289         self.MetaDataFileCheckLibraryInstance()\r
290         self.MetaDataFileCheckLibraryInstanceDependent()\r
291         self.MetaDataFileCheckLibraryInstanceOrder()\r
292         self.MetaDataFileCheckLibraryNoUse()\r
293         self.MetaDataFileCheckBinaryInfInFdf()\r
294         self.MetaDataFileCheckPcdDuplicate()\r
295         self.MetaDataFileCheckPcdFlash()\r
296         self.MetaDataFileCheckPcdNoUse()\r
297         self.MetaDataFileCheckGuidDuplicate()\r
298 \r
299     #\r
300     # Check whether each file defined in meta-data exists\r
301     #\r
302     def MetaDataFileCheckPathName(self):\r
303         if EccGlobalData.gConfig.MetaDataFileCheckPathName == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
304             # This item is covered when parsing Inf/Dec/Dsc files\r
305             pass\r
306     \r
307     #\r
308     # Generate a list for all files defined in meta-data files\r
309     #\r
310     def MetaDataFileCheckGenerateFileList(self):\r
311         if EccGlobalData.gConfig.MetaDataFileCheckGenerateFileList == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
312             # This item is covered when parsing Inf/Dec/Dsc files\r
313             pass\r
314     \r
315     #\r
316     # Check whether all Library Instances defined for a given module (or dependent library instance) match the module's type.  \r
317     # Each Library Instance must specify the Supported Module Types in its Inf file, \r
318     # and any module specifying the library instance must be one of the supported types.\r
319     #\r
320     def MetaDataFileCheckLibraryInstance(self):\r
321         if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstance == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
322             EdkLogger.quiet("Checking for library instance type issue ...")\r
323             SqlCommand = """select ID, Value2 from Inf where Value1 = 'LIBRARY_CLASS' and Model = %s group by BelongsToFile""" % MODEL_META_DATA_HEADER\r
324             RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
325             LibraryClasses = {}\r
326             for Record in RecordSet:\r
327                 List = Record[1].split('|', 1)\r
328                 if len(List) != 2:\r
329                     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
330                 else:\r
331                     LibraryClasses[List[0]] = List[1]\r
332             SqlCommand = """select A.ID, A.Value1, B.Value2 from Inf as A left join Inf as B \r
333                             where A.Model = %s and B.Value1 = '%s' and B.Model = %s and B.BelongsToFile = A.BelongsToFile""" \\r
334                             % (MODEL_EFI_LIBRARY_CLASS, 'MODULE_TYPE', MODEL_META_DATA_HEADER)\r
335             RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
336             for Record in RecordSet:\r
337                 if Record[1] in LibraryClasses and LibraryClasses[Record[1]].find(Record[2]) < 0:\r
338                     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
339     #\r
340     # Check whether a Library Instance has been defined for all dependent library classes\r
341     #\r
342     def MetaDataFileCheckLibraryInstanceDependent(self):\r
343         if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstanceDependent == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
344             EdkLogger.quiet("Checking for library instance dependent issue ...")\r
345             SqlCommand = """select ID, Value1, Value2 from Dsc where Model = %s""" % MODEL_EFI_LIBRARY_CLASS\r
346             LibraryClasses = EccGlobalData.gDb.TblDsc.Exec(SqlCommand)\r
347             for LibraryClass in LibraryClasses:\r
348                 if LibraryClass[1].upper() != 'NULL':\r
349                     LibraryIns = os.path.normpath(os.path.join(EccGlobalData.gWorkspace, LibraryClass[2]))\r
350                     SqlCommand = """select Value2 from Inf where BelongsToFile = \r
351                                     (select ID from File where lower(FullPath) = lower('%s'))\r
352                                     and Value1 = '%s'""" % (LibraryIns, 'LIBRARY_CLASS')\r
353                     RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
354                     IsFound = False\r
355                     for Record in RecordSet:\r
356                         LibName = Record[0].split('|', 1)[0]\r
357                         if LibraryClass[1] == LibName:\r
358                             IsFound = True\r
359                     if not IsFound:\r
360                         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
361     #\r
362     # Check whether the Library Instances specified by the LibraryClasses sections are listed in order of dependencies\r
363     #\r
364     def MetaDataFileCheckLibraryInstanceOrder(self):\r
365         if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstanceOrder == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
366             # This checkpoint is not necessary for Ecc check\r
367             pass\r
368 \r
369     #\r
370     # Check whether the unnecessary inclusion of library classes in the Inf file\r
371     #\r
372     def MetaDataFileCheckLibraryNoUse(self):\r
373         if EccGlobalData.gConfig.MetaDataFileCheckLibraryNoUse == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
374             EdkLogger.quiet("Checking for library instance not used ...")\r
375             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
376             RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
377             for Record in RecordSet:\r
378                 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
379 \r
380     #\r
381     # 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
382     #\r
383     def MetaDataFileCheckBinaryInfInFdf(self):\r
384         if EccGlobalData.gConfig.MetaDataFileCheckBinaryInfInFdf == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
385             EdkLogger.quiet("Checking for non-binary modules defined in FDF files ...")\r
386             SqlCommand = """select A.ID, A.Value1 from Fdf as A\r
387                          where A.Model = %s\r
388                          and A.Enabled > -1\r
389                          and A.Value1 not in \r
390                          (select B.Value1 from Dsc as B\r
391                          where B.Model = %s\r
392                          and B.Enabled > -1)""" % (MODEL_META_DATA_COMPONENT, MODEL_META_DATA_COMPONENT)\r
393             RecordSet = EccGlobalData.gDb.TblFdf.Exec(SqlCommand)\r
394             for Record in RecordSet:\r
395                 FdfID = Record[0]\r
396                 FilePath = Record[1]\r
397                 FilePath = os.path.normpath(os.path.join(EccGlobalData.gWorkspace, FilePath))\r
398                 SqlCommand = """select ID from Inf where Model = %s and BelongsToFile = (select ID from File where FullPath like '%s')\r
399                                 """ % (MODEL_EFI_SOURCE_FILE, FilePath)\r
400                 NewRecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
401                 if NewRecordSet!= []:\r
402                     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
403 \r
404     #\r
405     # Check whether a PCD is set in a Dsc file or the FDF file, but not in both.\r
406     #\r
407     def MetaDataFileCheckPcdDuplicate(self):\r
408         if EccGlobalData.gConfig.MetaDataFileCheckPcdDuplicate == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
409             EdkLogger.quiet("Checking for duplicate PCDs defined in both DSC and FDF files ...")\r
410             SqlCommand = """\r
411                          select A.ID, A.Value2, B.ID, B.Value2 from Dsc as A, Fdf as B \r
412                          where A.Model >= %s and A.Model < %s \r
413                          and B.Model >= %s and B.Model < %s \r
414                          and A.Value2 = B.Value2\r
415                          and A.Enabled > -1\r
416                          and B.Enabled > -1\r
417                          """% (MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER)\r
418             RecordSet = EccGlobalData.gDb.TblDsc.Exec(SqlCommand)\r
419             for Record in RecordSet:\r
420                 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
421                 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[3]), BelongsToTable = 'Fdf', BelongsToItem = Record[2])\r
422 \r
423     #\r
424     # Check whether PCD settings in the FDF file can only be related to flash.\r
425     #\r
426     def MetaDataFileCheckPcdFlash(self):\r
427         if EccGlobalData.gConfig.MetaDataFileCheckPcdFlash == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
428             EdkLogger.quiet("Checking only Flash related PCDs are used in FDF ...")\r
429             SqlCommand = """\r
430                          select ID, Value2, BelongsToFile from Fdf as A\r
431                          where A.Model >= %s and Model < %s\r
432                          and A.Enabled > -1\r
433                          and A.Value2 not like '%%Flash%%'\r
434                          """% (MODEL_PCD, MODEL_META_DATA_HEADER)\r
435             RecordSet = EccGlobalData.gDb.TblFdf.Exec(SqlCommand)\r
436             for Record in RecordSet:\r
437                 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
438         \r
439     #\r
440     # Check whether PCDs used in Inf files but not specified in Dsc or FDF files\r
441     #\r
442     def MetaDataFileCheckPcdNoUse(self):\r
443         if EccGlobalData.gConfig.MetaDataFileCheckPcdNoUse == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
444             EdkLogger.quiet("Checking for non-specified PCDs ...")\r
445             SqlCommand = """\r
446                          select ID, Value2, BelongsToFile from Inf as A \r
447                          where A.Model >= %s and Model < %s\r
448                          and A.Enabled > -1\r
449                          and A.Value2 not in \r
450                              (select Value2 from Dsc as B \r
451                               where B.Model >= %s and B.Model < %s\r
452                               and B.Enabled > -1)\r
453                          and A.Value2 not in\r
454                              (select Value2 from Fdf as C \r
455                               where C.Model >= %s and C.Model < %s\r
456                               and C.Enabled > -1)\r
457                          """% (MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER)\r
458             RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)\r
459             for Record in RecordSet:\r
460                 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
461         \r
462     #\r
463     # Check whether having duplicate guids defined for Guid/Protocol/Ppi\r
464     #\r
465     def MetaDataFileCheckGuidDuplicate(self):\r
466         if EccGlobalData.gConfig.MetaDataFileCheckGuidDuplicate == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1':\r
467             EdkLogger.quiet("Checking for duplicate GUID/PPI/PROTOCOL ...")\r
468             #\r
469             # Check Guid\r
470             #\r
471             self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID, EccGlobalData.gDb.TblDec)\r
472             self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID, EccGlobalData.gDb.TblDsc)\r
473             self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID)\r
474             #\r
475             # Check protocol\r
476             #\r
477             self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL, EccGlobalData.gDb.TblDec)\r
478             self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL, EccGlobalData.gDb.TblDsc)\r
479             self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL)\r
480             #\r
481             # Check ppi\r
482             #\r
483             self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI, EccGlobalData.gDb.TblDec)\r
484             self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI, EccGlobalData.gDb.TblDsc)\r
485             self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI)\r
486 \r
487             #EdkLogger.quiet("Checking duplicate guid/ppi/protocol done!")\r
488     \r
489     #\r
490     # Check whether these is duplicate Guid/Ppi/Protocol name\r
491     #\r
492     def CheckGuidProtocolPpi(self, ErrorID, Model, Table):\r
493         Name = ''\r
494         if Model == MODEL_EFI_GUID:\r
495             Name = 'guid'\r
496         if Model == MODEL_EFI_PROTOCOL:\r
497             Name = 'protocol'\r
498         if Model == MODEL_EFI_PPI:\r
499             Name = 'ppi'\r
500         SqlCommand = """\r
501                      select A.ID, A.Value1 from %s as A, %s as B \r
502                      where A.Model = %s and B.Model = %s \r
503                      and A.Value1 = B.Value1 and A.ID <> B.ID \r
504                      and A.Enabled > -1\r
505                      and B.Enabled > -1\r
506                      group by A.ID\r
507                      """ % (Table.Table, Table.Table, Model, Model)\r
508         RecordSet = Table.Exec(SqlCommand)\r
509         for Record in RecordSet:\r
510             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
511 \r
512     #\r
513     # Check whether these is duplicate Guid/Ppi/Protocol value\r
514     #\r
515     def CheckGuidProtocolPpiValue(self, ErrorID, Model):\r
516         Name = ''\r
517         Table = EccGlobalData.gDb.TblDec\r
518         if Model == MODEL_EFI_GUID:\r
519             Name = 'guid'\r
520         if Model == MODEL_EFI_PROTOCOL:\r
521             Name = 'protocol'\r
522         if Model == MODEL_EFI_PPI:\r
523             Name = 'ppi'\r
524         SqlCommand = """\r
525                      select A.ID, A.Value2 from %s as A, %s as B \r
526                      where A.Model = %s and B.Model = %s \r
527                      and A.Value2 = B.Value2 and A.ID <> B.ID \r
528                      group by A.ID\r
529                      """ % (Table.Table, Table.Table, Model, Model)\r
530         RecordSet = Table.Exec(SqlCommand)\r
531         for Record in RecordSet:\r
532             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
533 \r
534     #\r
535     # Naming Convention Check\r
536     #\r
537     def NamingConventionCheck(self):\r
538         self.NamingConventionCheckDefineStatement()\r
539         self.NamingConventionCheckTypedefStatement()\r
540         self.NamingConventionCheckIfndefStatement()\r
541         self.NamingConventionCheckPathName()\r
542         self.NamingConventionCheckVariableName()\r
543         self.NamingConventionCheckFunctionName()\r
544         self.NamingConventionCheckSingleCharacterVariable()\r
545         \r
546     #\r
547     # Check whether only capital letters are used for #define declarations\r
548     #\r
549     def NamingConventionCheckDefineStatement(self):\r
550         if EccGlobalData.gConfig.NamingConventionCheckDefineStatement == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1':\r
551             EdkLogger.quiet("Checking naming covention of #define statement ...")\r
552             for IdentifierTable in EccGlobalData.gIdentifierTableList:\r
553                 SqlCommand = """select ID, Value from %s where Model = %s""" %(IdentifierTable, MODEL_IDENTIFIER_MACRO_DEFINE)\r
554                 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
555                 for Record in RecordSet:\r
556                     Name = Record[1].strip().split()[1]\r
557                     Name = Name[0:Name.find('(')]\r
558                     if Name.upper() != Name:\r
559                         EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_DEFINE_STATEMENT, OtherMsg = "The #define name '%s' does not follow the rules" % (Name), BelongsToTable = IdentifierTable, BelongsToItem = Record[0])\r
560     \r
561     #\r
562     # Check whether only capital letters are used for typedef declarations\r
563     #\r
564     def NamingConventionCheckTypedefStatement(self):\r
565         if EccGlobalData.gConfig.NamingConventionCheckTypedefStatement == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1':\r
566             EdkLogger.quiet("Checking naming covention of #typedef statement ...")\r
567             for IdentifierTable in EccGlobalData.gIdentifierTableList:\r
568                 SqlCommand = """select ID, Name from %s where Model = %s""" %(IdentifierTable, MODEL_IDENTIFIER_TYPEDEF)\r
569                 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
570                 for Record in RecordSet:\r
571                     Name = Record[1].strip()\r
572                     if Name[0] == '(':\r
573                         Name = Name[1:Name.find(')')]\r
574                     if Name.find('(') > -1:\r
575                         Name = Name[Name.find('(') + 1 : Name.find(')')]\r
576                     Name = Name.replace('WINAPI', '')\r
577                     Name = Name.replace('*', '').strip()\r
578                     if Name.upper() != Name:\r
579                         EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_TYPEDEF_STATEMENT, OtherMsg = "The #typedef name '%s' does not follow the rules" % (Name), BelongsToTable = IdentifierTable, BelongsToItem = Record[0])\r
580     \r
581     #\r
582     # Check whether the #ifndef at the start of an include file uses both prefix and postfix underscore characters, '_'.\r
583     #\r
584     def NamingConventionCheckIfndefStatement(self):\r
585         if EccGlobalData.gConfig.NamingConventionCheckTypedefStatement == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1':\r
586             EdkLogger.quiet("Checking naming covention of #ifndef statement ...")\r
587             for IdentifierTable in EccGlobalData.gIdentifierTableList:\r
588                 SqlCommand = """select ID, Value from %s where Model = %s""" %(IdentifierTable, MODEL_IDENTIFIER_MACRO_IFNDEF)\r
589                 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
590                 for Record in RecordSet:\r
591                     Name = Record[1].replace('#ifndef', '').strip()\r
592                     if Name[0] != '_' or Name[-1] != '_':\r
593                         EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_IFNDEF_STATEMENT, OtherMsg = "The #ifndef name '%s' does not follow the rules" % (Name), BelongsToTable = IdentifierTable, BelongsToItem = Record[0])\r
594     \r
595     #\r
596     # Rule for path name, variable name and function name\r
597     # 1. First character should be upper case\r
598     # 2. Existing lower case in a word\r
599     # 3. No space existence\r
600     # Check whether the path name followed the rule\r
601     #\r
602     def NamingConventionCheckPathName(self):\r
603         if EccGlobalData.gConfig.NamingConventionCheckPathName == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1':\r
604             EdkLogger.quiet("Checking naming covention of file path name ...")\r
605             Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')\r
606             SqlCommand = """select ID, Name from File"""\r
607             RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
608             for Record in RecordSet:\r
609                 if not Pattern.match(Record[1]):\r
610                     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
611     \r
612     #\r
613     # Rule for path name, variable name and function name\r
614     # 1. First character should be upper case\r
615     # 2. Existing lower case in a word\r
616     # 3. No space existence\r
617     # 4. Global variable name must start with a 'g'\r
618     # Check whether the variable name followed the rule\r
619     #\r
620     def NamingConventionCheckVariableName(self):\r
621         if EccGlobalData.gConfig.NamingConventionCheckVariableName == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1':\r
622             EdkLogger.quiet("Checking naming covention of variable name ...")\r
623             Pattern = re.compile(r'^[A-Zgm]+\S*[a-z]\S*$')\r
624             for IdentifierTable in EccGlobalData.gIdentifierTableList:\r
625                 SqlCommand = """select ID, Name from %s where Model = %s""" %(IdentifierTable, MODEL_IDENTIFIER_VARIABLE)\r
626                 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
627                 for Record in RecordSet:\r
628                     if not Pattern.match(Record[1]):\r
629                         EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, OtherMsg = "The variable name '%s' does not follow the rules" % (Record[1]), BelongsToTable = IdentifierTable, BelongsToItem = Record[0])\r
630 \r
631     #\r
632     # Rule for path name, variable name and function name\r
633     # 1. First character should be upper case\r
634     # 2. Existing lower case in a word\r
635     # 3. No space existence\r
636     # Check whether the function name followed the rule\r
637     #\r
638     def NamingConventionCheckFunctionName(self):\r
639         if EccGlobalData.gConfig.NamingConventionCheckFunctionName == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1':\r
640             EdkLogger.quiet("Checking naming covention of function name ...")\r
641             Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')\r
642             SqlCommand = """select ID, Name from Function"""\r
643             RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
644             for Record in RecordSet:\r
645                 if not Pattern.match(Record[1]):\r
646                     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
647 \r
648     #\r
649     # Check whether NO use short variable name with single character\r
650     #\r
651     def NamingConventionCheckSingleCharacterVariable(self):\r
652         if EccGlobalData.gConfig.NamingConventionCheckSingleCharacterVariable == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1':\r
653             EdkLogger.quiet("Checking naming covention of single character variable name ...")\r
654             for IdentifierTable in EccGlobalData.gIdentifierTableList:\r
655                 SqlCommand = """select ID, Name from %s where Model = %s""" %(IdentifierTable, MODEL_IDENTIFIER_VARIABLE)\r
656                 RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)\r
657                 for Record in RecordSet:\r
658                     Variable = Record[1].replace('*', '')\r
659                     if len(Variable) == 1:\r
660                         EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_SINGLE_CHARACTER_VARIABLE, OtherMsg = "The variable name '%s' does not follow the rules" % (Record[1]), BelongsToTable = IdentifierTable, BelongsToItem = Record[0])\r
661 \r
662 ##\r
663 #\r
664 # This acts like the main() function for the script, unless it is 'import'ed into another\r
665 # script.\r
666 #\r
667 if __name__ == '__main__':\r
668     Check = Check()\r
669     Check.Check()\r