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