1## @file 2# This file is used to create/update/query/erase a meta file table 3# 4# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR> 5# SPDX-License-Identifier: BSD-2-Clause-Patent 6# 7 8## 9# Import Modules 10# 11from __future__ import absolute_import 12import uuid 13 14import Common.EdkLogger as EdkLogger 15from Common.BuildToolError import FORMAT_INVALID 16 17from CommonDataClass.DataClass import MODEL_FILE_DSC, MODEL_FILE_DEC, MODEL_FILE_INF, \ 18 MODEL_FILE_OTHERS 19from Common.DataType import * 20 21class MetaFileTable(): 22 # TRICK: use file ID as the part before '.' 23 _ID_STEP_ = 1 24 _ID_MAX_ = 99999999 25 26 ## Constructor 27 def __init__(self, DB, MetaFile, FileType, Temporary, FromItem=None): 28 self.MetaFile = MetaFile 29 self.TableName = "" 30 self.DB = DB 31 self._NumpyTab = None 32 33 self.CurrentContent = [] 34 DB.TblFile.append([MetaFile.Name, 35 MetaFile.Ext, 36 MetaFile.Dir, 37 MetaFile.Path, 38 FileType, 39 MetaFile.TimeStamp, 40 FromItem]) 41 self.FileId = len(DB.TblFile) 42 self.ID = self.FileId * 10**8 43 if Temporary: 44 self.TableName = "_%s_%s_%s" % (FileType, len(DB.TblFile), uuid.uuid4().hex) 45 else: 46 self.TableName = "_%s_%s" % (FileType, len(DB.TblFile)) 47 48 def IsIntegrity(self): 49 try: 50 TimeStamp = self.MetaFile.TimeStamp 51 if not self.CurrentContent: 52 Result = False 53 else: 54 Result = self.CurrentContent[-1][0] < 0 55 if not Result: 56 # update the timestamp in database 57 self.DB.SetFileTimeStamp(self.FileId, TimeStamp) 58 return False 59 60 if TimeStamp != self.DB.GetFileTimeStamp(self.FileId): 61 # update the timestamp in database 62 self.DB.SetFileTimeStamp(self.FileId, TimeStamp) 63 return False 64 except Exception as Exc: 65 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc)) 66 return False 67 return True 68 69 def SetEndFlag(self): 70 self.CurrentContent.append(self._DUMMY_) 71 72 def GetAll(self): 73 return [item for item in self.CurrentContent if item[0] >= 0 and item[-1]>=0] 74 75## Python class representation of table storing module data 76class ModuleTable(MetaFileTable): 77 _COLUMN_ = ''' 78 ID REAL PRIMARY KEY, 79 Model INTEGER NOT NULL, 80 Value1 TEXT NOT NULL, 81 Value2 TEXT, 82 Value3 TEXT, 83 Scope1 TEXT, 84 Scope2 TEXT, 85 BelongsToItem REAL NOT NULL, 86 StartLine INTEGER NOT NULL, 87 StartColumn INTEGER NOT NULL, 88 EndLine INTEGER NOT NULL, 89 EndColumn INTEGER NOT NULL, 90 Enabled INTEGER DEFAULT 0 91 ''' 92 # used as table end flag, in case the changes to database is not committed to db file 93 _DUMMY_ = [-1, -1, '====', '====', '====', '====', '====', -1, -1, -1, -1, -1, -1] 94 95 ## Constructor 96 def __init__(self, Db, MetaFile, Temporary): 97 MetaFileTable.__init__(self, Db, MetaFile, MODEL_FILE_INF, Temporary) 98 99 ## Insert a record into table Inf 100 # 101 # @param Model: Model of a Inf item 102 # @param Value1: Value1 of a Inf item 103 # @param Value2: Value2 of a Inf item 104 # @param Value3: Value3 of a Inf item 105 # @param Scope1: Arch of a Inf item 106 # @param Scope2 Platform os a Inf item 107 # @param BelongsToItem: The item belongs to which another item 108 # @param StartLine: StartLine of a Inf item 109 # @param StartColumn: StartColumn of a Inf item 110 # @param EndLine: EndLine of a Inf item 111 # @param EndColumn: EndColumn of a Inf item 112 # @param Enabled: If this item enabled 113 # 114 def Insert(self, Model, Value1, Value2, Value3, Scope1=TAB_ARCH_COMMON, Scope2=TAB_COMMON, 115 BelongsToItem=-1, StartLine=-1, StartColumn=-1, EndLine=-1, EndColumn=-1, Enabled=0): 116 117 (Value1, Value2, Value3, Scope1, Scope2) = (Value1.strip(), Value2.strip(), Value3.strip(), Scope1.strip(), Scope2.strip()) 118 self.ID = self.ID + self._ID_STEP_ 119 if self.ID >= (MODEL_FILE_INF + self._ID_MAX_): 120 self.ID = MODEL_FILE_INF + self._ID_STEP_ 121 122 row = [ self.ID, 123 Model, 124 Value1, 125 Value2, 126 Value3, 127 Scope1, 128 Scope2, 129 BelongsToItem, 130 StartLine, 131 StartColumn, 132 EndLine, 133 EndColumn, 134 Enabled 135 ] 136 self.CurrentContent.append(row) 137 return self.ID 138 139 ## Query table 140 # 141 # @param Model: The Model of Record 142 # @param Arch: The Arch attribute of Record 143 # @param Platform The Platform attribute of Record 144 # 145 # @retval: A recordSet of all found records 146 # 147 def Query(self, Model, Arch=None, Platform=None, BelongsToItem=None): 148 149 QueryTab = self.CurrentContent 150 result = [item for item in QueryTab if item[1] == Model and item[-1]>=0 ] 151 152 if Arch is not None and Arch != TAB_ARCH_COMMON: 153 ArchList = set(['COMMON']) 154 ArchList.add(Arch) 155 result = [item for item in result if item[5] in ArchList] 156 157 if Platform is not None and Platform != TAB_COMMON: 158 Platformlist = set( ['COMMON','DEFAULT']) 159 Platformlist.add(Platform) 160 result = [item for item in result if item[6] in Platformlist] 161 162 if BelongsToItem is not None: 163 result = [item for item in result if item[7] == BelongsToItem] 164 165 result = [ [r[2],r[3],r[4],r[5],r[6],r[0],r[9]] for r in result ] 166 return result 167 168## Python class representation of table storing package data 169class PackageTable(MetaFileTable): 170 _COLUMN_ = ''' 171 ID REAL PRIMARY KEY, 172 Model INTEGER NOT NULL, 173 Value1 TEXT NOT NULL, 174 Value2 TEXT, 175 Value3 TEXT, 176 Scope1 TEXT, 177 Scope2 TEXT, 178 BelongsToItem REAL NOT NULL, 179 StartLine INTEGER NOT NULL, 180 StartColumn INTEGER NOT NULL, 181 EndLine INTEGER NOT NULL, 182 EndColumn INTEGER NOT NULL, 183 Enabled INTEGER DEFAULT 0 184 ''' 185 # used as table end flag, in case the changes to database is not committed to db file 186 _DUMMY_ = [-1, -1, '====', '====', '====', '====', '====', -1, -1, -1, -1, -1, -1] 187 188 ## Constructor 189 def __init__(self, Cursor, MetaFile, Temporary): 190 MetaFileTable.__init__(self, Cursor, MetaFile, MODEL_FILE_DEC, Temporary) 191 192 ## Insert table 193 # 194 # Insert a record into table Dec 195 # 196 # @param Model: Model of a Dec item 197 # @param Value1: Value1 of a Dec item 198 # @param Value2: Value2 of a Dec item 199 # @param Value3: Value3 of a Dec item 200 # @param Scope1: Arch of a Dec item 201 # @param Scope2: Module type of a Dec item 202 # @param BelongsToItem: The item belongs to which another item 203 # @param StartLine: StartLine of a Dec item 204 # @param StartColumn: StartColumn of a Dec item 205 # @param EndLine: EndLine of a Dec item 206 # @param EndColumn: EndColumn of a Dec item 207 # @param Enabled: If this item enabled 208 # 209 def Insert(self, Model, Value1, Value2, Value3, Scope1=TAB_ARCH_COMMON, Scope2=TAB_COMMON, 210 BelongsToItem=-1, StartLine=-1, StartColumn=-1, EndLine=-1, EndColumn=-1, Enabled=0): 211 (Value1, Value2, Value3, Scope1, Scope2) = (Value1.strip(), Value2.strip(), Value3.strip(), Scope1.strip(), Scope2.strip()) 212 self.ID = self.ID + self._ID_STEP_ 213 214 row = [ self.ID, 215 Model, 216 Value1, 217 Value2, 218 Value3, 219 Scope1, 220 Scope2, 221 BelongsToItem, 222 StartLine, 223 StartColumn, 224 EndLine, 225 EndColumn, 226 Enabled 227 ] 228 self.CurrentContent.append(row) 229 return self.ID 230 231 ## Query table 232 # 233 # @param Model: The Model of Record 234 # @param Arch: The Arch attribute of Record 235 # 236 # @retval: A recordSet of all found records 237 # 238 def Query(self, Model, Arch=None): 239 240 QueryTab = self.CurrentContent 241 result = [item for item in QueryTab if item[1] == Model and item[-1]>=0 ] 242 243 if Arch is not None and Arch != TAB_ARCH_COMMON: 244 ArchList = set(['COMMON']) 245 ArchList.add(Arch) 246 result = [item for item in result if item[5] in ArchList] 247 248 return [[r[2], r[3], r[4], r[5], r[6], r[0], r[8]] for r in result] 249 250 def GetValidExpression(self, TokenSpaceGuid, PcdCName): 251 252 QueryTab = self.CurrentContent 253 result = [[item[2], item[8]] for item in QueryTab if item[3] == TokenSpaceGuid and item[4] == PcdCName] 254 validateranges = [] 255 validlists = [] 256 expressions = [] 257 try: 258 for row in result: 259 comment = row[0] 260 261 LineNum = row[1] 262 comment = comment.strip("#") 263 comment = comment.strip() 264 oricomment = comment 265 if comment.startswith("@ValidRange"): 266 comment = comment.replace("@ValidRange", "", 1) 267 validateranges.append(comment.split("|")[1].strip()) 268 if comment.startswith("@ValidList"): 269 comment = comment.replace("@ValidList", "", 1) 270 validlists.append(comment.split("|")[1].strip()) 271 if comment.startswith("@Expression"): 272 comment = comment.replace("@Expression", "", 1) 273 expressions.append(comment.split("|")[1].strip()) 274 except Exception as Exc: 275 ValidType = "" 276 if oricomment.startswith("@ValidRange"): 277 ValidType = "@ValidRange" 278 if oricomment.startswith("@ValidList"): 279 ValidType = "@ValidList" 280 if oricomment.startswith("@Expression"): 281 ValidType = "@Expression" 282 EdkLogger.error('Parser', FORMAT_INVALID, "The syntax for %s of PCD %s.%s is incorrect" % (ValidType, TokenSpaceGuid, PcdCName), 283 ExtraData=oricomment, File=self.MetaFile, Line=LineNum) 284 return set(), set(), set() 285 return set(validateranges), set(validlists), set(expressions) 286 287## Python class representation of table storing platform data 288class PlatformTable(MetaFileTable): 289 _COLUMN_ = ''' 290 ID REAL PRIMARY KEY, 291 Model INTEGER NOT NULL, 292 Value1 TEXT NOT NULL, 293 Value2 TEXT, 294 Value3 TEXT, 295 Scope1 TEXT, 296 Scope2 TEXT, 297 Scope3 TEXT, 298 BelongsToItem REAL NOT NULL, 299 FromItem REAL NOT NULL, 300 StartLine INTEGER NOT NULL, 301 StartColumn INTEGER NOT NULL, 302 EndLine INTEGER NOT NULL, 303 EndColumn INTEGER NOT NULL, 304 Enabled INTEGER DEFAULT 0 305 ''' 306 # used as table end flag, in case the changes to database is not committed to db file 307 _DUMMY_ = [-1, -1, '====', '====', '====', '====', '====','====', -1, -1, -1, -1, -1, -1, -1] 308 309 ## Constructor 310 def __init__(self, Cursor, MetaFile, Temporary, FromItem=0): 311 MetaFileTable.__init__(self, Cursor, MetaFile, MODEL_FILE_DSC, Temporary, FromItem) 312 313 ## Insert table 314 # 315 # Insert a record into table Dsc 316 # 317 # @param Model: Model of a Dsc item 318 # @param Value1: Value1 of a Dsc item 319 # @param Value2: Value2 of a Dsc item 320 # @param Value3: Value3 of a Dsc item 321 # @param Scope1: Arch of a Dsc item 322 # @param Scope2: Module type of a Dsc item 323 # @param BelongsToItem: The item belongs to which another item 324 # @param FromItem: The item belongs to which dsc file 325 # @param StartLine: StartLine of a Dsc item 326 # @param StartColumn: StartColumn of a Dsc item 327 # @param EndLine: EndLine of a Dsc item 328 # @param EndColumn: EndColumn of a Dsc item 329 # @param Enabled: If this item enabled 330 # 331 def Insert(self, Model, Value1, Value2, Value3, Scope1=TAB_ARCH_COMMON, Scope2=TAB_COMMON, Scope3=TAB_DEFAULT_STORES_DEFAULT,BelongsToItem=-1, 332 FromItem=-1, StartLine=-1, StartColumn=-1, EndLine=-1, EndColumn=-1, Enabled=1): 333 (Value1, Value2, Value3, Scope1, Scope2, Scope3) = (Value1.strip(), Value2.strip(), Value3.strip(), Scope1.strip(), Scope2.strip(), Scope3.strip()) 334 self.ID = self.ID + self._ID_STEP_ 335 336 row = [ self.ID, 337 Model, 338 Value1, 339 Value2, 340 Value3, 341 Scope1, 342 Scope2, 343 Scope3, 344 BelongsToItem, 345 FromItem, 346 StartLine, 347 StartColumn, 348 EndLine, 349 EndColumn, 350 Enabled 351 ] 352 self.CurrentContent.append(row) 353 return self.ID 354 355 356 ## Query table 357 # 358 # @param Model: The Model of Record 359 # @param Scope1: Arch of a Dsc item 360 # @param Scope2: Module type of a Dsc item 361 # @param BelongsToItem: The item belongs to which another item 362 # @param FromItem: The item belongs to which dsc file 363 # 364 # @retval: A recordSet of all found records 365 # 366 def Query(self, Model, Scope1=None, Scope2=None, BelongsToItem=None, FromItem=None): 367 368 QueryTab = self.CurrentContent 369 result = [item for item in QueryTab if item[1] == Model and item[-1]>0 ] 370 if Scope1 is not None and Scope1 != TAB_ARCH_COMMON: 371 Sc1 = set(['COMMON']) 372 Sc1.add(Scope1) 373 result = [item for item in result if item[5] in Sc1] 374 Sc2 = set( ['COMMON','DEFAULT']) 375 if Scope2 and Scope2 != TAB_COMMON: 376 if '.' in Scope2: 377 Index = Scope2.index('.') 378 NewScope = TAB_COMMON + Scope2[Index:] 379 Sc2.add(NewScope) 380 Sc2.add(Scope2) 381 result = [item for item in result if item[6] in Sc2] 382 383 if BelongsToItem is not None: 384 result = [item for item in result if item[8] == BelongsToItem] 385 else: 386 result = [item for item in result if item[8] < 0] 387 if FromItem is not None: 388 result = [item for item in result if item[9] == FromItem] 389 390 result = [ [r[2],r[3],r[4],r[5],r[6],r[7],r[0],r[10]] for r in result ] 391 return result 392 393 def DisableComponent(self,comp_id): 394 for item in self.CurrentContent: 395 if item[0] == comp_id or item[8] == comp_id: 396 item[-1] = -1 397 398## Factory class to produce different storage for different type of meta-file 399class MetaFileStorage(object): 400 _FILE_TABLE_ = { 401 MODEL_FILE_INF : ModuleTable, 402 MODEL_FILE_DEC : PackageTable, 403 MODEL_FILE_DSC : PlatformTable, 404 MODEL_FILE_OTHERS : MetaFileTable, 405 } 406 407 _FILE_TYPE_ = { 408 ".inf" : MODEL_FILE_INF, 409 ".dec" : MODEL_FILE_DEC, 410 ".dsc" : MODEL_FILE_DSC, 411 } 412 _ObjectCache = {} 413 ## Constructor 414 def __new__(Class, Cursor, MetaFile, FileType=None, Temporary=False, FromItem=None): 415 # no type given, try to find one 416 key = (MetaFile.Path, FileType,Temporary,FromItem) 417 if key in Class._ObjectCache: 418 return Class._ObjectCache[key] 419 if not FileType: 420 if MetaFile.Type in self._FILE_TYPE_: 421 FileType = Class._FILE_TYPE_[MetaFile.Type] 422 else: 423 FileType = MODEL_FILE_OTHERS 424 425 # don't pass the type around if it's well known 426 if FileType == MODEL_FILE_OTHERS: 427 Args = (Cursor, MetaFile, FileType, Temporary) 428 else: 429 Args = (Cursor, MetaFile, Temporary) 430 if FromItem: 431 Args = Args + (FromItem,) 432 433 # create the storage object and return it to caller 434 reval = Class._FILE_TABLE_[FileType](*Args) 435 if not Temporary: 436 Class._ObjectCache[key] = reval 437 return reval 438 439