]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Ecc/MetaDataParser.py
BaseTools: use set instead of list for a variable to be used with in
[mirror_edk2.git] / BaseTools / Source / Python / Ecc / MetaDataParser.py
1 ## @file
2 # This file is used to define common parser functions for meta-data
3 #
4 # Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
9 #
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 #
13
14 import Common.LongFilePathOs as os
15 from CommonDataClass.DataClass import *
16 from EccToolError import *
17 from Common.MultipleWorkspace import MultipleWorkspace as mws
18 import EccGlobalData
19 import re
20 ## Get the inlcude path list for a source file
21 #
22 # 1. Find the source file belongs to which inf file
23 # 2. Find the inf's package
24 # 3. Return the include path list of the package
25 #
26 def GetIncludeListOfFile(WorkSpace, Filepath, Db):
27 IncludeList = []
28 Filepath = os.path.normpath(Filepath)
29 SqlCommand = """
30 select Value1, FullPath from Inf, File where Inf.Model = %s and Inf.BelongsToFile in(
31 select distinct B.BelongsToFile from File as A left join Inf as B
32 where A.ID = B.BelongsToFile and B.Model = %s and (A.Path || '%s' || B.Value1) = '%s')
33 and Inf.BelongsToFile = File.ID""" \
34 % (MODEL_META_DATA_PACKAGE, MODEL_EFI_SOURCE_FILE, '\\', Filepath)
35 RecordSet = Db.TblFile.Exec(SqlCommand)
36 for Record in RecordSet:
37 DecFullPath = os.path.normpath(mws.join(WorkSpace, Record[0]))
38 InfFullPath = os.path.normpath(mws.join(WorkSpace, Record[1]))
39 (DecPath, DecName) = os.path.split(DecFullPath)
40 (InfPath, InfName) = os.path.split(InfFullPath)
41 SqlCommand = """select Value1 from Dec where BelongsToFile =
42 (select ID from File where FullPath = '%s') and Model = %s""" \
43 % (DecFullPath, MODEL_EFI_INCLUDE)
44 NewRecordSet = Db.TblDec.Exec(SqlCommand)
45 if InfPath not in IncludeList:
46 IncludeList.append(InfPath)
47 for NewRecord in NewRecordSet:
48 IncludePath = os.path.normpath(os.path.join(DecPath, NewRecord[0]))
49 if IncludePath not in IncludeList:
50 IncludeList.append(IncludePath)
51
52 return IncludeList
53
54 ## Get the file list
55 #
56 # Search table file and find all specific type files
57 #
58 def GetFileList(FileModel, Db):
59 FileList = []
60 SqlCommand = """select FullPath from File where Model = %s""" % str(FileModel)
61 RecordSet = Db.TblFile.Exec(SqlCommand)
62 for Record in RecordSet:
63 FileList.append(Record[0])
64
65 return FileList
66
67 ## Get the table list
68 #
69 # Search table file and find all small tables
70 #
71 def GetTableList(FileModelList, Table, Db):
72 TableList = []
73 SqlCommand = """select ID from File where Model in %s""" % str(FileModelList)
74 RecordSet = Db.TblFile.Exec(SqlCommand)
75 for Record in RecordSet:
76 TableName = Table + str(Record[0])
77 TableList.append(TableName)
78
79 return TableList
80
81 ## ParseHeaderCommentSection
82 #
83 # Parse Header comment section lines, extract Abstract, Description, Copyright
84 # , License lines
85 #
86 # @param CommentList: List of (Comment, LineNumber)
87 # @param FileName: FileName of the comment
88 #
89 def ParseHeaderCommentSection(CommentList, FileName = None):
90
91 Abstract = ''
92 Description = ''
93 Copyright = ''
94 License = ''
95 EndOfLine = "\n"
96 STR_HEADER_COMMENT_START = "@file"
97
98 #
99 # used to indicate the state of processing header comment section of dec,
100 # inf files
101 #
102 HEADER_COMMENT_NOT_STARTED = -1
103 HEADER_COMMENT_STARTED = 0
104 HEADER_COMMENT_FILE = 1
105 HEADER_COMMENT_ABSTRACT = 2
106 HEADER_COMMENT_DESCRIPTION = 3
107 HEADER_COMMENT_COPYRIGHT = 4
108 HEADER_COMMENT_LICENSE = 5
109 HEADER_COMMENT_END = 6
110 #
111 # first find the last copyright line
112 #
113 Last = 0
114 HeaderCommentStage = HEADER_COMMENT_NOT_STARTED
115 for Index in xrange(len(CommentList)-1, 0, -1):
116 Line = CommentList[Index][0]
117 if _IsCopyrightLine(Line):
118 Last = Index
119 break
120
121 for Item in CommentList:
122 Line = Item[0]
123 LineNo = Item[1]
124
125 if not Line.startswith('#') and Line:
126 SqlStatement = """ select ID from File where FullPath like '%s'""" % FileName
127 ResultSet = EccGlobalData.gDb.TblFile.Exec(SqlStatement)
128 for Result in ResultSet:
129 Msg = 'Comment must start with #'
130 EccGlobalData.gDb.TblReport.Insert(ERROR_DOXYGEN_CHECK_FILE_HEADER, Msg, "File", Result[0])
131 Comment = CleanString2(Line)[1]
132 Comment = Comment.strip()
133 #
134 # if there are blank lines between License or Description, keep them as they would be
135 # indication of different block; or in the position that Abstract should be, also keep it
136 # as it indicates that no abstract
137 #
138 if not Comment and HeaderCommentStage not in [HEADER_COMMENT_LICENSE, \
139 HEADER_COMMENT_DESCRIPTION, HEADER_COMMENT_ABSTRACT]:
140 continue
141
142 if HeaderCommentStage == HEADER_COMMENT_NOT_STARTED:
143 if Comment.startswith(STR_HEADER_COMMENT_START):
144 HeaderCommentStage = HEADER_COMMENT_ABSTRACT
145 else:
146 License += Comment + EndOfLine
147 else:
148 if HeaderCommentStage == HEADER_COMMENT_ABSTRACT:
149 #
150 # in case there is no abstract and description
151 #
152 if not Comment:
153 Abstract = ''
154 HeaderCommentStage = HEADER_COMMENT_DESCRIPTION
155 elif _IsCopyrightLine(Comment):
156 Copyright += Comment + EndOfLine
157 HeaderCommentStage = HEADER_COMMENT_COPYRIGHT
158 else:
159 Abstract += Comment + EndOfLine
160 HeaderCommentStage = HEADER_COMMENT_DESCRIPTION
161 elif HeaderCommentStage == HEADER_COMMENT_DESCRIPTION:
162 #
163 # in case there is no description
164 #
165 if _IsCopyrightLine(Comment):
166 Copyright += Comment + EndOfLine
167 HeaderCommentStage = HEADER_COMMENT_COPYRIGHT
168 else:
169 Description += Comment + EndOfLine
170 elif HeaderCommentStage == HEADER_COMMENT_COPYRIGHT:
171 if _IsCopyrightLine(Comment):
172 Copyright += Comment + EndOfLine
173 else:
174 #
175 # Contents after copyright line are license, those non-copyright lines in between
176 # copyright line will be discarded
177 #
178 if LineNo > Last:
179 if License:
180 License += EndOfLine
181 License += Comment + EndOfLine
182 HeaderCommentStage = HEADER_COMMENT_LICENSE
183 else:
184 if not Comment and not License:
185 continue
186 License += Comment + EndOfLine
187
188 if not Copyright.strip():
189 SqlStatement = """ select ID from File where FullPath like '%s'""" % FileName
190 ResultSet = EccGlobalData.gDb.TblFile.Exec(SqlStatement)
191 for Result in ResultSet:
192 Msg = 'Header comment section must have copyright information'
193 EccGlobalData.gDb.TblReport.Insert(ERROR_DOXYGEN_CHECK_FILE_HEADER, Msg, "File", Result[0])
194
195 if not License.strip():
196 SqlStatement = """ select ID from File where FullPath like '%s'""" % FileName
197 ResultSet = EccGlobalData.gDb.TblFile.Exec(SqlStatement)
198 for Result in ResultSet:
199 Msg = 'Header comment section must have license information'
200 EccGlobalData.gDb.TblReport.Insert(ERROR_DOXYGEN_CHECK_FILE_HEADER, Msg, "File", Result[0])
201
202 if not Abstract.strip() or Abstract.find('Component description file') > -1:
203 SqlStatement = """ select ID from File where FullPath like '%s'""" % FileName
204 ResultSet = EccGlobalData.gDb.TblFile.Exec(SqlStatement)
205 for Result in ResultSet:
206 Msg = 'Header comment section must have Abstract information.'
207 EccGlobalData.gDb.TblReport.Insert(ERROR_DOXYGEN_CHECK_FILE_HEADER, Msg, "File", Result[0])
208
209 return Abstract.strip(), Description.strip(), Copyright.strip(), License.strip()
210
211 ## _IsCopyrightLine
212 # check whether current line is copyright line, the criteria is whether there is case insensitive keyword "Copyright"
213 # followed by zero or more white space characters followed by a "(" character
214 #
215 # @param LineContent: the line need to be checked
216 # @return: True if current line is copyright line, False else
217 #
218 def _IsCopyrightLine (LineContent):
219 LineContent = LineContent.upper()
220 Result = False
221
222 ReIsCopyrightRe = re.compile(r"""(^|\s)COPYRIGHT *\(""", re.DOTALL)
223 if ReIsCopyrightRe.search(LineContent):
224 Result = True
225
226 return Result
227
228
229 ## CleanString2
230 #
231 # Split comments in a string
232 # Remove spaces
233 #
234 # @param Line: The string to be cleaned
235 # @param CommentCharacter: Comment char, used to ignore comment content,
236 # default is DataType.TAB_COMMENT_SPLIT
237 #
238 def CleanString2(Line, CommentCharacter='#', AllowCppStyleComment=False):
239 #
240 # remove whitespace
241 #
242 Line = Line.strip()
243 #
244 # Replace EDK1's comment character
245 #
246 if AllowCppStyleComment:
247 Line = Line.replace('//', CommentCharacter)
248 #
249 # separate comments and statements
250 #
251 LineParts = Line.split(CommentCharacter, 1)
252 #
253 # remove whitespace again
254 #
255 Line = LineParts[0].strip()
256 if len(LineParts) > 1:
257 Comment = LineParts[1].strip()
258 #
259 # Remove prefixed and trailing comment characters
260 #
261 Start = 0
262 End = len(Comment)
263 while Start < End and Comment.startswith(CommentCharacter, Start, End):
264 Start += 1
265 while End >= 0 and Comment.endswith(CommentCharacter, Start, End):
266 End -= 1
267 Comment = Comment[Start:End]
268 Comment = Comment.strip()
269 else:
270 Comment = ''
271
272 return Line, Comment