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 14import Common.LongFilePathOs as os 15from CommonDataClass.DataClass import * 16from EccToolError import * 17from Common.MultipleWorkspace import MultipleWorkspace as mws 18import EccGlobalData 19import 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# 26def 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# 58def 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# 71def 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# 89def 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# 218def _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# 238def 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 273