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