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