]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Ecc/MetaFileWorkspace/MetaFileParser.py
2d98ac5eadb2532fce7e03374360003d41856e89
[mirror_edk2.git] / BaseTools / Source / Python / Ecc / MetaFileWorkspace / MetaFileParser.py
1 ## @file
2 # This file is used to parse meta files
3 #
4 # Copyright (c) 2008 - 2020, Intel Corporation. All rights reserved.<BR>
5 # SPDX-License-Identifier: BSD-2-Clause-Patent
6 #
7
8 ##
9 # Import Modules
10 #
11 from __future__ import absolute_import
12 import Common.LongFilePathOs as os
13 import re
14 import time
15 import copy
16 from hashlib import md5
17 import Common.EdkLogger as EdkLogger
18 import Common.GlobalData as GlobalData
19 import Ecc.EccGlobalData as EccGlobalData
20 import Ecc.EccToolError as EccToolError
21
22 from CommonDataClass.DataClass import *
23 from Common.DataType import *
24 from Common.StringUtils import *
25 from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData
26 from Common.Expression import *
27 from CommonDataClass.Exceptions import *
28
29 from Ecc.MetaFileWorkspace.MetaFileTable import MetaFileStorage
30 from GenFds.FdfParser import FdfParser
31 from Common.LongFilePathSupport import OpenLongFilePath as open
32 from Common.LongFilePathSupport import CodecOpenLongFilePath
33
34 ## RegEx for finding file versions
35 hexVersionPattern = re.compile(r'0[xX][\da-f-A-F]{5,8}')
36 decVersionPattern = re.compile(r'\d+\.\d+')
37
38 ## A decorator used to parse macro definition
39 def ParseMacro(Parser):
40 def MacroParser(self):
41 Match = GlobalData.gMacroDefPattern.match(self._CurrentLine)
42 if not Match:
43 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
44 Parser(self)
45 return
46
47 TokenList = GetSplitValueList(self._CurrentLine[Match.end(1):], TAB_EQUAL_SPLIT, 1)
48 # Syntax check
49 if not TokenList[0]:
50 EdkLogger.error('Parser', FORMAT_INVALID, "No macro name given",
51 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
52 if len(TokenList) < 2:
53 TokenList.append('')
54
55 Type = Match.group(1)
56 Name, Value = TokenList
57 # Global macros can be only defined via environment variable
58 if Name in GlobalData.gGlobalDefines:
59 EdkLogger.error('Parser', FORMAT_INVALID, "%s can only be defined via environment variable" % Name,
60 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
61 # Only upper case letters, digit and '_' are allowed
62 if not GlobalData.gMacroNamePattern.match(Name):
63 EdkLogger.error('Parser', FORMAT_INVALID, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
64 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
65
66 Value = ReplaceMacro(Value, self._Macros)
67 self._ItemType = MODEL_META_DATA_DEFINE
68 # DEFINE defined macros
69 if Type == TAB_DSC_DEFINES_DEFINE:
70 if isinstance(self, DecParser):
71 if MODEL_META_DATA_HEADER in self._SectionType:
72 self._FileLocalMacros[Name] = Value
73 else:
74 for Scope in self._Scope:
75 self._SectionsMacroDict.setdefault((Scope[2], Scope[0], Scope[1]), {})[Name] = Value
76 elif self._SectionType == MODEL_META_DATA_HEADER:
77 self._FileLocalMacros[Name] = Value
78 else:
79 SectionDictKey = self._SectionType, self._Scope[0][0], self._Scope[0][1]
80 if SectionDictKey not in self._SectionsMacroDict:
81 self._SectionsMacroDict[SectionDictKey] = {}
82 SectionLocalMacros = self._SectionsMacroDict[SectionDictKey]
83 SectionLocalMacros[Name] = Value
84 # EDK_GLOBAL defined macros
85 elif not isinstance(self, DscParser):
86 EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used in .dsc file",
87 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
88 elif self._SectionType != MODEL_META_DATA_HEADER:
89 EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used under [Defines] section",
90 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
91 elif (Name in self._FileLocalMacros) and (self._FileLocalMacros[Name] != Value):
92 EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
93 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
94
95 self._ValueList = [Type, Name, Value]
96
97 return MacroParser
98
99 ## Base class of parser
100 #
101 # This class is used for derivation purpose. The specific parser for one kind
102 # type file must derive this class and implement some public interfaces.
103 #
104 # @param FilePath The path of platform description file
105 # @param FileType The raw data of DSC file
106 # @param Table Database used to retrieve module/package information
107 # @param Macros Macros used for replacement in file
108 # @param Owner Owner ID (for sub-section parsing)
109 # @param From ID from which the data comes (for !INCLUDE directive)
110 #
111 class MetaFileParser(object):
112 # data type (file content) for specific file type
113 DataType = {}
114
115 # Parser objects used to implement singleton
116 MetaFiles = {}
117
118 ## Factory method
119 #
120 # One file, one parser object. This factory method makes sure that there's
121 # only one object constructed for one meta file.
122 #
123 # @param Class class object of real AutoGen class
124 # (InfParser, DecParser or DscParser)
125 # @param FilePath The path of meta file
126 # @param *args The specific class related parameters
127 # @param **kwargs The specific class related dict parameters
128 #
129 def __new__(Class, FilePath, *args, **kwargs):
130 if FilePath in Class.MetaFiles:
131 return Class.MetaFiles[FilePath]
132 else:
133 ParserObject = super(MetaFileParser, Class).__new__(Class)
134 Class.MetaFiles[FilePath] = ParserObject
135 return ParserObject
136
137 ## Constructor of MetaFileParser
138 #
139 # Initialize object of MetaFileParser
140 #
141 # @param FilePath The path of platform description file
142 # @param FileType The raw data of DSC file
143 # @param Table Database used to retrieve module/package information
144 # @param Macros Macros used for replacement in file
145 # @param Owner Owner ID (for sub-section parsing)
146 # @param From ID from which the data comes (for !INCLUDE directive)
147 #
148 def __init__(self, FilePath, FileType, Table, Owner=-1, From=-1):
149 self._Table = Table
150 self._RawTable = Table
151 self._FileType = FileType
152 self.MetaFile = FilePath
153 self._Defines = {}
154 self._FileLocalMacros = {}
155 self._SectionsMacroDict = {}
156
157 # for recursive parsing
158 self._Owner = [Owner]
159 self._From = From
160
161 # parsr status for parsing
162 self._ValueList = ['', '', '', '', '']
163 self._Scope = []
164 self._LineIndex = 0
165 self._CurrentLine = ''
166 self._SectionType = MODEL_UNKNOWN
167 self._SectionName = ''
168 self._InSubsection = False
169 self._SubsectionType = MODEL_UNKNOWN
170 self._SubsectionName = ''
171 self._ItemType = MODEL_UNKNOWN
172 self._LastItem = -1
173 self._Enabled = 0
174 self._Finished = False
175 self._PostProcessed = False
176 # Different version of meta-file has different way to parse.
177 self._Version = 0
178 # UNI object and extra UNI object
179 self._UniObj = None
180 self._UniExtraObj = None
181
182 ## Store the parsed data in table
183 def _Store(self, *Args):
184 return self._Table.Insert(*Args)
185
186 ## Virtual method for starting parse
187 def Start(self):
188 raise NotImplementedError
189
190 ## Notify a post-process is needed
191 def DoPostProcess(self):
192 self._PostProcessed = False
193
194 ## Set parsing complete flag in both class and table
195 def _Done(self):
196 self._Finished = True
197 ## Do not set end flag when processing included files
198 if self._From == -1:
199 self._Table.SetEndFlag()
200
201 def _PostProcess(self):
202 self._PostProcessed = True
203
204 ## Get the parse complete flag
205 def _GetFinished(self):
206 return self._Finished
207
208 ## Set the complete flag
209 def _SetFinished(self, Value):
210 self._Finished = Value
211
212 ## Use [] style to query data in table, just for readability
213 #
214 # DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]
215 #
216 def __getitem__(self, DataInfo):
217 if not isinstance(DataInfo, type(())):
218 DataInfo = (DataInfo,)
219
220 # Parse the file first, if necessary
221 if not self._Finished:
222 if self._RawTable.IsIntegrity():
223 self._Finished = True
224 else:
225 self._Table = self._RawTable
226 self._PostProcessed = False
227 self.Start()
228
229 # No specific ARCH or Platform given, use raw data
230 if self._RawTable and (len(DataInfo) == 1 or DataInfo[1] is None):
231 return self._RawTable.Query(*DataInfo)
232
233 # Do post-process if necessary
234 if not self._PostProcessed:
235 self._PostProcess()
236
237 return self._Table.Query(*DataInfo)
238
239 ## Data parser for the common format in different type of file
240 #
241 # The common format in the meatfile is like
242 #
243 # xxx1 | xxx2 | xxx3
244 #
245 @ParseMacro
246 def _CommonParser(self):
247 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
248 self._ValueList[0:len(TokenList)] = TokenList
249
250 ## Data parser for the format in which there's path
251 #
252 # Only path can have macro used. So we need to replace them before use.
253 #
254 @ParseMacro
255 def _PathParser(self):
256 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
257 self._ValueList[0:len(TokenList)] = TokenList
258 # Don't do macro replacement for dsc file at this point
259 if not isinstance(self, DscParser):
260 Macros = self._Macros
261 self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]
262
263 ## Skip unsupported data
264 def _Skip(self):
265 if self._SectionName == TAB_USER_EXTENSIONS.upper() and self._CurrentLine.upper().endswith('.UNI'):
266 if EccGlobalData.gConfig.UniCheckHelpInfo == '1' or EccGlobalData.gConfig.UniCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
267 ExtraUni = self._CurrentLine.strip()
268 ExtraUniFile = os.path.join(os.path.dirname(self.MetaFile), ExtraUni)
269 IsModuleUni = self.MetaFile.upper().endswith('.INF')
270 self._UniExtraObj = UniParser(ExtraUniFile, IsExtraUni=True, IsModuleUni=IsModuleUni)
271 self._UniExtraObj.Start()
272 else:
273 EdkLogger.warn("Parser", "Unrecognized content", File=self.MetaFile,
274 Line=self._LineIndex + 1, ExtraData=self._CurrentLine);
275 self._ValueList[0:1] = [self._CurrentLine]
276
277 ## Section header parser
278 #
279 # The section header is always in following format:
280 #
281 # [section_name.arch<.platform|module_type>]
282 #
283 def _SectionHeaderParser(self):
284 self._Scope = []
285 self._SectionName = ''
286 ArchList = set()
287 for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):
288 if Item == '':
289 continue
290 ItemList = GetSplitValueList(Item, TAB_SPLIT)
291 # different section should not mix in one section
292 if self._SectionName != '' and self._SectionName != ItemList[0].upper():
293 EdkLogger.error('Parser', FORMAT_INVALID, "Different section names in the same section",
294 File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine)
295 self._SectionName = ItemList[0].upper()
296 if self._SectionName in self.DataType:
297 self._SectionType = self.DataType[self._SectionName]
298 else:
299 self._SectionType = MODEL_UNKNOWN
300 EdkLogger.warn("Parser", "Unrecognized section", File=self.MetaFile,
301 Line=self._LineIndex+1, ExtraData=self._CurrentLine)
302 # S1 is always Arch
303 if len(ItemList) > 1:
304 S1 = ItemList[1].upper()
305 else:
306 S1 = 'COMMON'
307 ArchList.add(S1)
308 # S2 may be Platform or ModuleType
309 if len(ItemList) > 2:
310 S2 = ItemList[2].upper()
311 else:
312 S2 = 'COMMON'
313 self._Scope.append([S1, S2])
314
315 # 'COMMON' must not be used with specific ARCHs at the same section
316 if 'COMMON' in ArchList and len(ArchList) > 1:
317 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
318 File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine)
319 # If the section information is needed later, it should be stored in database
320 self._ValueList[0] = self._SectionName
321
322 ## [defines] section parser
323 @ParseMacro
324 def _DefineParser(self):
325 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
326 self._ValueList[1:len(TokenList)] = TokenList
327 if not self._ValueList[1]:
328 EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
329 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
330 if not self._ValueList[2]:
331 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
332 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
333
334 self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
335 Name, Value = self._ValueList[1], self._ValueList[2]
336 # Sometimes, we need to make differences between EDK and EDK2 modules
337 if Name == 'INF_VERSION':
338 if hexVersionPattern.match(Value):
339 self._Version = int(Value, 0)
340 elif decVersionPattern.match(Value):
341 ValueList = Value.split('.')
342 Major = int(ValueList[0], 0)
343 Minor = int(ValueList[1], 0)
344 if Major > 0xffff or Minor > 0xffff:
345 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",
346 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
347 self._Version = int('0x{0:04x}{1:04x}'.format(Major, Minor), 0)
348 else:
349 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",
350 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
351 elif Name == 'MODULE_UNI_FILE':
352 UniFile = os.path.join(os.path.dirname(self.MetaFile), Value)
353 if os.path.exists(UniFile):
354 self._UniObj = UniParser(UniFile, IsExtraUni=False, IsModuleUni=True)
355 self._UniObj.Start()
356 else:
357 EdkLogger.error('Parser', FILE_NOT_FOUND, "Module UNI file %s is missing." % Value,
358 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1,
359 RaiseError=False)
360 elif Name == 'PACKAGE_UNI_FILE':
361 UniFile = os.path.join(os.path.dirname(self.MetaFile), Value)
362 if os.path.exists(UniFile):
363 self._UniObj = UniParser(UniFile, IsExtraUni=False, IsModuleUni=False)
364
365 if isinstance(self, InfParser) and self._Version < 0x00010005:
366 # EDK module allows using defines as macros
367 self._FileLocalMacros[Name] = Value
368 self._Defines[Name] = Value
369
370 ## [BuildOptions] section parser
371 @ParseMacro
372 def _BuildOptionParser(self):
373 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
374 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
375 if len(TokenList2) == 2:
376 self._ValueList[0] = TokenList2[0] # toolchain family
377 self._ValueList[1] = TokenList2[1] # keys
378 else:
379 self._ValueList[1] = TokenList[0]
380 if len(TokenList) == 2 and not isinstance(self, DscParser): # value
381 self._ValueList[2] = ReplaceMacro(TokenList[1], self._Macros)
382
383 if self._ValueList[1].count('_') != 4:
384 EdkLogger.error(
385 'Parser',
386 FORMAT_INVALID,
387 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
388 ExtraData=self._CurrentLine,
389 File=self.MetaFile,
390 Line=self._LineIndex+1
391 )
392
393 def _GetMacros(self):
394 Macros = {}
395 Macros.update(self._FileLocalMacros)
396 Macros.update(self._GetApplicableSectionMacro())
397 return Macros
398
399
400 ## Get section Macros that are applicable to current line, which may come from other sections
401 ## that share the same name while scope is wider
402 def _GetApplicableSectionMacro(self):
403 Macros = {}
404 for Scope1, Scope2 in [("COMMON", "COMMON"), ("COMMON", self._Scope[0][1]),
405 (self._Scope[0][0], "COMMON"), (self._Scope[0][0], self._Scope[0][1])]:
406 if (self._SectionType, Scope1, Scope2) in self._SectionsMacroDict:
407 Macros.update(self._SectionsMacroDict[(self._SectionType, Scope1, Scope2)])
408 return Macros
409
410 _SectionParser = {}
411 Finished = property(_GetFinished, _SetFinished)
412 _Macros = property(_GetMacros)
413
414
415 ## INF file parser class
416 #
417 # @param FilePath The path of platform description file
418 # @param FileType The raw data of DSC file
419 # @param Table Database used to retrieve module/package information
420 # @param Macros Macros used for replacement in file
421 #
422 class InfParser(MetaFileParser):
423 # INF file supported data types (one type per section)
424 DataType = {
425 TAB_UNKNOWN.upper() : MODEL_UNKNOWN,
426 TAB_INF_DEFINES.upper() : MODEL_META_DATA_HEADER,
427 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
428 TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,
429 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
430 TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,
431 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
432 TAB_PACKAGES.upper() : MODEL_META_DATA_PACKAGE,
433 TAB_NMAKE.upper() : MODEL_META_DATA_NMAKE,
434 TAB_INF_FIXED_PCD.upper() : MODEL_PCD_FIXED_AT_BUILD,
435 TAB_INF_PATCH_PCD.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
436 TAB_INF_FEATURE_PCD.upper() : MODEL_PCD_FEATURE_FLAG,
437 TAB_INF_PCD_EX.upper() : MODEL_PCD_DYNAMIC_EX,
438 TAB_INF_PCD.upper() : MODEL_PCD_DYNAMIC,
439 TAB_SOURCES.upper() : MODEL_EFI_SOURCE_FILE,
440 TAB_GUIDS.upper() : MODEL_EFI_GUID,
441 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
442 TAB_PPIS.upper() : MODEL_EFI_PPI,
443 TAB_DEPEX.upper() : MODEL_EFI_DEPEX,
444 TAB_BINARIES.upper() : MODEL_EFI_BINARY_FILE,
445 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION
446 }
447
448 ## Constructor of InfParser
449 #
450 # Initialize object of InfParser
451 #
452 # @param FilePath The path of module description file
453 # @param FileType The raw data of DSC file
454 # @param Table Database used to retrieve module/package information
455 # @param Macros Macros used for replacement in file
456 #
457 def __init__(self, FilePath, FileType, Table):
458 # prevent re-initialization
459 if hasattr(self, "_Table"):
460 return
461 MetaFileParser.__init__(self, FilePath, FileType, Table)
462 self.TblFile = EccGlobalData.gDb.TblFile
463 self.FileID = -1
464
465 ## Parser starter
466 def Start(self):
467 NmakeLine = ''
468 Content = ''
469 Usage = ''
470 try:
471 Content = open(str(self.MetaFile), 'r').readlines()
472 except:
473 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
474 #
475 # Insert a record for file
476 #
477 Filename = NormPath(self.MetaFile)
478 FileID = self.TblFile.GetFileId(Filename)
479 if FileID:
480 self.FileID = FileID
481 else:
482 self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_INF)
483
484 # parse the file line by line
485 IsFindBlockComment = False
486
487 for Index in range(0, len(Content)):
488 if self._SectionType in [MODEL_EFI_GUID,
489 MODEL_EFI_PROTOCOL,
490 MODEL_EFI_PPI,
491 MODEL_PCD_FIXED_AT_BUILD,
492 MODEL_PCD_PATCHABLE_IN_MODULE,
493 MODEL_PCD_FEATURE_FLAG,
494 MODEL_PCD_DYNAMIC_EX,
495 MODEL_PCD_DYNAMIC]:
496 Line = Content[Index].strip()
497 if Line.startswith(TAB_SPECIAL_COMMENT):
498 Usage += ' ' + Line[Line.find(TAB_SPECIAL_COMMENT):]
499 continue
500 elif Line.startswith(TAB_COMMENT_SPLIT):
501 continue
502 elif Line.find(TAB_COMMENT_SPLIT) > 0:
503 Usage += ' ' + Line[Line.find(TAB_COMMENT_SPLIT):]
504 Line = Line[:Line.find(TAB_COMMENT_SPLIT)]
505 else:
506 # skip empty, commented, block commented lines
507 Line = CleanString(Content[Index], AllowCppStyleComment=True)
508 Usage = ''
509 NextLine = ''
510 if Index + 1 < len(Content):
511 NextLine = CleanString(Content[Index + 1])
512 if Line == '':
513 continue
514 if Line.find(DataType.TAB_COMMENT_EDK_START) > -1:
515 IsFindBlockComment = True
516 continue
517 if Line.find(DataType.TAB_COMMENT_EDK_END) > -1:
518 IsFindBlockComment = False
519 continue
520 if IsFindBlockComment:
521 continue
522
523 self._LineIndex = Index
524 self._CurrentLine = Line
525
526 # section header
527 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
528 self._SectionHeaderParser()
529 # Check invalid sections
530 if self._Version < 0x00010005:
531 if self._SectionType in [MODEL_META_DATA_BUILD_OPTION,
532 MODEL_EFI_LIBRARY_CLASS,
533 MODEL_META_DATA_PACKAGE,
534 MODEL_PCD_FIXED_AT_BUILD,
535 MODEL_PCD_PATCHABLE_IN_MODULE,
536 MODEL_PCD_FEATURE_FLAG,
537 MODEL_PCD_DYNAMIC_EX,
538 MODEL_PCD_DYNAMIC,
539 MODEL_EFI_GUID,
540 MODEL_EFI_PROTOCOL,
541 MODEL_EFI_PPI,
542 MODEL_META_DATA_USER_EXTENSION]:
543 EdkLogger.error('Parser', FORMAT_INVALID,
544 "Section [%s] is not allowed in inf file without version" % (self._SectionName),
545 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
546 elif self._SectionType in [MODEL_EFI_INCLUDE,
547 MODEL_EFI_LIBRARY_INSTANCE,
548 MODEL_META_DATA_NMAKE]:
549 EdkLogger.error('Parser', FORMAT_INVALID,
550 "Section [%s] is not allowed in inf file with version 0x%08x" % (self._SectionName, self._Version),
551 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
552 continue
553 # merge two lines specified by '\' in section NMAKE
554 elif self._SectionType == MODEL_META_DATA_NMAKE:
555 if Line[-1] == '\\':
556 if NextLine == '':
557 self._CurrentLine = NmakeLine + Line[0:-1]
558 NmakeLine = ''
559 else:
560 if NextLine[0] == TAB_SECTION_START and NextLine[-1] == TAB_SECTION_END:
561 self._CurrentLine = NmakeLine + Line[0:-1]
562 NmakeLine = ''
563 else:
564 NmakeLine = NmakeLine + ' ' + Line[0:-1]
565 continue
566 else:
567 self._CurrentLine = NmakeLine + Line
568 NmakeLine = ''
569
570 # section content
571 self._ValueList = ['', '', '']
572 # parse current line, result will be put in self._ValueList
573 self._SectionParser[self._SectionType](self)
574 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:
575 self._ItemType = -1
576 continue
577 #
578 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
579 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
580 #
581 self._ValueList[0] = self._ValueList[0].replace('/', '\\')
582 Usage = Usage.strip()
583 for Arch, Platform in self._Scope:
584 self._Store(self._SectionType,
585 self._ValueList[0],
586 self._ValueList[1],
587 self._ValueList[2],
588 Arch,
589 Platform,
590 self._Owner[-1],
591 self.FileID,
592 self._LineIndex+1,
593 -1,
594 self._LineIndex+1,
595 -1,
596 0,
597 Usage
598 )
599 Usage = ''
600 if IsFindBlockComment:
601 EdkLogger.error("Parser", FORMAT_INVALID, "Open block comments (starting with /*) are expected to end with */",
602 File=self.MetaFile)
603 self._Done()
604
605 ## Data parser for the format in which there's path
606 #
607 # Only path can have macro used. So we need to replace them before use.
608 #
609 def _IncludeParser(self):
610 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
611 self._ValueList[0:len(TokenList)] = TokenList
612 Macros = self._Macros
613 if Macros:
614 for Index in range(0, len(self._ValueList)):
615 Value = self._ValueList[Index]
616 if not Value:
617 continue
618
619 self._ValueList[Index] = ReplaceMacro(Value, Macros)
620
621 ## Parse [Sources] section
622 #
623 # Only path can have macro used. So we need to replace them before use.
624 #
625 @ParseMacro
626 def _SourceFileParser(self):
627 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
628 self._ValueList[0:len(TokenList)] = TokenList
629 Macros = self._Macros
630 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
631 if 'COMPONENT_TYPE' in Macros:
632 if self._Defines['COMPONENT_TYPE'].upper() == 'ACPITABLE':
633 self._ValueList[0] = GetSplitValueList(self._ValueList[0], ' ', 1)[0]
634 if self._Defines['BASE_NAME'] == 'Microcode':
635 pass
636 self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]
637
638 ## Parse [Binaries] section
639 #
640 # Only path can have macro used. So we need to replace them before use.
641 #
642 @ParseMacro
643 def _BinaryFileParser(self):
644 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 2)
645 if len(TokenList) < 2:
646 EdkLogger.error('Parser', FORMAT_INVALID, "No file type or path specified",
647 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
648 File=self.MetaFile, Line=self._LineIndex+1)
649 if not TokenList[0]:
650 EdkLogger.error('Parser', FORMAT_INVALID, "No file type specified",
651 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
652 File=self.MetaFile, Line=self._LineIndex+1)
653 if not TokenList[1]:
654 EdkLogger.error('Parser', FORMAT_INVALID, "No file path specified",
655 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
656 File=self.MetaFile, Line=self._LineIndex+1)
657 self._ValueList[0:len(TokenList)] = TokenList
658 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)
659
660 ## [nmake] section parser (Edk.x style only)
661 def _NmakeParser(self):
662 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
663 self._ValueList[0:len(TokenList)] = TokenList
664 # remove macros
665 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)
666 # remove self-reference in macro setting
667 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
668
669 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
670 @ParseMacro
671 def _PcdParser(self):
672 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
673 ValueList = GetSplitValueList(TokenList[0], TAB_SPLIT)
674 if len(ValueList) != 2:
675 EdkLogger.error('Parser', FORMAT_INVALID, "Illegal token space GUID and PCD name format",
676 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
677 File=self.MetaFile, Line=self._LineIndex+1)
678 self._ValueList[0:1] = ValueList
679 if len(TokenList) > 1:
680 self._ValueList[2] = TokenList[1]
681 if self._ValueList[0] == '' or self._ValueList[1] == '':
682 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
683 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
684 File=self.MetaFile, Line=self._LineIndex+1)
685
686 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
687 if self._ValueList[2] != '':
688 InfPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
689 if InfPcdValueList[0] in ['True', 'true', 'TRUE']:
690 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '1', 1);
691 elif InfPcdValueList[0] in ['False', 'false', 'FALSE']:
692 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '0', 1);
693
694 ## [depex] section parser
695 @ParseMacro
696 def _DepexParser(self):
697 self._ValueList[0:1] = [self._CurrentLine]
698
699 _SectionParser = {
700 MODEL_UNKNOWN : MetaFileParser._Skip,
701 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,
702 MODEL_META_DATA_BUILD_OPTION : MetaFileParser._BuildOptionParser,
703 MODEL_EFI_INCLUDE : _IncludeParser, # for Edk.x modules
704 MODEL_EFI_LIBRARY_INSTANCE : MetaFileParser._CommonParser, # for Edk.x modules
705 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,
706 MODEL_META_DATA_PACKAGE : MetaFileParser._PathParser,
707 MODEL_META_DATA_NMAKE : _NmakeParser, # for Edk.x modules
708 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
709 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
710 MODEL_PCD_FEATURE_FLAG : _PcdParser,
711 MODEL_PCD_DYNAMIC_EX : _PcdParser,
712 MODEL_PCD_DYNAMIC : _PcdParser,
713 MODEL_EFI_SOURCE_FILE : _SourceFileParser,
714 MODEL_EFI_GUID : MetaFileParser._CommonParser,
715 MODEL_EFI_PROTOCOL : MetaFileParser._CommonParser,
716 MODEL_EFI_PPI : MetaFileParser._CommonParser,
717 MODEL_EFI_DEPEX : _DepexParser,
718 MODEL_EFI_BINARY_FILE : _BinaryFileParser,
719 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip,
720 }
721
722 ## DSC file parser class
723 #
724 # @param FilePath The path of platform description file
725 # @param FileType The raw data of DSC file
726 # @param Table Database used to retrieve module/package information
727 # @param Macros Macros used for replacement in file
728 # @param Owner Owner ID (for sub-section parsing)
729 # @param From ID from which the data comes (for !INCLUDE directive)
730 #
731 class DscParser(MetaFileParser):
732 # DSC file supported data types (one type per section)
733 DataType = {
734 TAB_SKUIDS.upper() : MODEL_EFI_SKU_ID,
735 TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,
736 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
737 TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,
738 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,
739 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
740 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,
741 TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_DEFAULT,
742 TAB_PCDS_DYNAMIC_HII_NULL.upper() : MODEL_PCD_DYNAMIC_HII,
743 TAB_PCDS_DYNAMIC_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_VPD,
744 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT,
745 TAB_PCDS_DYNAMIC_EX_HII_NULL.upper() : MODEL_PCD_DYNAMIC_EX_HII,
746 TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_EX_VPD,
747 TAB_COMPONENTS.upper() : MODEL_META_DATA_COMPONENT,
748 TAB_DSC_DEFINES.upper() : MODEL_META_DATA_HEADER,
749 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
750 TAB_DSC_DEFINES_EDKGLOBAL : MODEL_META_DATA_GLOBAL_DEFINE,
751 TAB_INCLUDE.upper() : MODEL_META_DATA_INCLUDE,
752 TAB_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
753 TAB_IF_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
754 TAB_IF_N_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF,
755 TAB_ELSE_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF,
756 TAB_ELSE.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,
757 TAB_END_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF,
758 TAB_ERROR.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR,
759 }
760
761 # Valid names in define section
762 DefineKeywords = [
763 "DSC_SPECIFICATION",
764 "PLATFORM_NAME",
765 "PLATFORM_GUID",
766 "PLATFORM_VERSION",
767 "SKUID_IDENTIFIER",
768 "PCD_INFO_GENERATION",
769 "SUPPORTED_ARCHITECTURES",
770 "BUILD_TARGETS",
771 "OUTPUT_DIRECTORY",
772 "FLASH_DEFINITION",
773 "BUILD_NUMBER",
774 "RFC_LANGUAGES",
775 "ISO_LANGUAGES",
776 "TIME_STAMP_FILE",
777 "VPD_TOOL_GUID",
778 "FIX_LOAD_TOP_MEMORY_ADDRESS"
779 ]
780
781 SubSectionDefineKeywords = [
782 "FILE_GUID"
783 ]
784
785 SymbolPattern = ValueExpression.SymbolPattern
786
787 ## Constructor of DscParser
788 #
789 # Initialize object of DscParser
790 #
791 # @param FilePath The path of platform description file
792 # @param FileType The raw data of DSC file
793 # @param Table Database used to retrieve module/package information
794 # @param Macros Macros used for replacement in file
795 # @param Owner Owner ID (for sub-section parsing)
796 # @param From ID from which the data comes (for !INCLUDE directive)
797 #
798 def __init__(self, FilePath, FileType, Table, Owner=-1, From=-1):
799 # prevent re-initialization
800 if hasattr(self, "_Table"):
801 return
802 MetaFileParser.__init__(self, FilePath, FileType, Table, Owner, From)
803 self._Version = 0x00010005 # Only EDK2 dsc file is supported
804 # to store conditional directive evaluation result
805 self._DirectiveStack = []
806 self._DirectiveEvalStack = []
807 self._Enabled = 1
808
809 # Final valid replacable symbols
810 self._Symbols = {}
811 #
812 # Map the ID between the original table and new table to track
813 # the owner item
814 #
815 self._IdMapping = {-1:-1}
816
817 self.TblFile = EccGlobalData.gDb.TblFile
818 self.FileID = -1
819
820 ## Parser starter
821 def Start(self):
822 Content = ''
823 try:
824 Content = open(str(self.MetaFile.Path), 'r').readlines()
825 except:
826 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
827 #
828 # Insert a record for file
829 #
830 Filename = NormPath(self.MetaFile.Path)
831 FileID = self.TblFile.GetFileId(Filename)
832 if FileID:
833 self.FileID = FileID
834 else:
835 self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_DSC)
836
837
838 for Index in range(0, len(Content)):
839 Line = CleanString(Content[Index])
840 # skip empty line
841 if Line == '':
842 continue
843
844 self._CurrentLine = Line
845 self._LineIndex = Index
846 if self._InSubsection and self._Owner[-1] == -1:
847 self._Owner.append(self._LastItem)
848
849 # section header
850 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
851 self._SectionType = MODEL_META_DATA_SECTION_HEADER
852 # subsection ending
853 elif Line[0] == '}' and self._InSubsection:
854 self._InSubsection = False
855 self._SubsectionType = MODEL_UNKNOWN
856 self._SubsectionName = ''
857 self._Owner[-1] = -1
858 continue
859 # subsection header
860 elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:
861 self._SubsectionType = MODEL_META_DATA_SUBSECTION_HEADER
862 # directive line
863 elif Line[0] == '!':
864 self._DirectiveParser()
865 continue
866
867 if self._InSubsection:
868 SectionType = self._SubsectionType
869 else:
870 SectionType = self._SectionType
871 self._ItemType = SectionType
872
873 self._ValueList = ['', '', '']
874 self._SectionParser[SectionType](self)
875 if self._ValueList is None:
876 continue
877 #
878 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
879 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
880 #
881 for Arch, ModuleType in self._Scope:
882 self._LastItem = self._Store(
883 self._ItemType,
884 self._ValueList[0],
885 self._ValueList[1],
886 self._ValueList[2],
887 Arch,
888 ModuleType,
889 self._Owner[-1],
890 self.FileID,
891 self._From,
892 self._LineIndex+1,
893 -1,
894 self._LineIndex+1,
895 -1,
896 self._Enabled
897 )
898
899 if self._DirectiveStack:
900 Type, Line, Text = self._DirectiveStack[-1]
901 EdkLogger.error('Parser', FORMAT_INVALID, "No matching '!endif' found",
902 ExtraData=Text, File=self.MetaFile, Line=Line)
903 self._Done()
904
905 ## <subsection_header> parser
906 def _SubsectionHeaderParser(self):
907 self._SubsectionName = self._CurrentLine[1:-1].upper()
908 if self._SubsectionName in self.DataType:
909 self._SubsectionType = self.DataType[self._SubsectionName]
910 else:
911 self._SubsectionType = MODEL_UNKNOWN
912 EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile,
913 Line=self._LineIndex+1, ExtraData=self._CurrentLine)
914 self._ValueList[0] = self._SubsectionName
915
916 ## Directive statement parser
917 def _DirectiveParser(self):
918 self._ValueList = ['', '', '']
919 TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)
920 self._ValueList[0:len(TokenList)] = TokenList
921
922 # Syntax check
923 DirectiveName = self._ValueList[0].upper()
924 if DirectiveName not in self.DataType:
925 EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName,
926 File=self.MetaFile, Line=self._LineIndex+1)
927 if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '':
928 EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression",
929 File=self.MetaFile, Line=self._LineIndex+1,
930 ExtraData=self._CurrentLine)
931
932 ItemType = self.DataType[DirectiveName]
933 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
934 # Remove all directives between !if and !endif, including themselves
935 while self._DirectiveStack:
936 # Remove any !else or !elseif
937 DirectiveInfo = self._DirectiveStack.pop()
938 if DirectiveInfo[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
939 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
940 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
941 break
942 else:
943 EdkLogger.error("Parser", FORMAT_INVALID, "Redundant '!endif'",
944 File=self.MetaFile, Line=self._LineIndex+1,
945 ExtraData=self._CurrentLine)
946 elif ItemType != MODEL_META_DATA_INCLUDE:
947 # Break if there's a !else is followed by a !elseif
948 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF and \
949 self._DirectiveStack and \
950 self._DirectiveStack[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
951 EdkLogger.error("Parser", FORMAT_INVALID, "'!elseif' after '!else'",
952 File=self.MetaFile, Line=self._LineIndex+1,
953 ExtraData=self._CurrentLine)
954 self._DirectiveStack.append((ItemType, self._LineIndex+1, self._CurrentLine))
955 elif self._From > 0:
956 EdkLogger.error('Parser', FORMAT_INVALID,
957 "No '!include' allowed in included file",
958 ExtraData=self._CurrentLine, File=self.MetaFile,
959 Line=self._LineIndex+1)
960
961 #
962 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
963 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
964 #
965 self._LastItem = self._Store(
966 ItemType,
967 self._ValueList[0],
968 self._ValueList[1],
969 self._ValueList[2],
970 'COMMON',
971 'COMMON',
972 self._Owner[-1],
973 self.FileID,
974 self._From,
975 self._LineIndex+1,
976 -1,
977 self._LineIndex+1,
978 -1,
979 0
980 )
981
982 ## [defines] section parser
983 @ParseMacro
984 def _DefineParser(self):
985 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
986 self._ValueList[1:len(TokenList)] = TokenList
987
988 # Syntax check
989 if not self._ValueList[1]:
990 EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
991 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
992 if not self._ValueList[2]:
993 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
994 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
995 if (not self._ValueList[1] in self.DefineKeywords and
996 (self._InSubsection and self._ValueList[1] not in self.SubSectionDefineKeywords)):
997 EdkLogger.error('Parser', FORMAT_INVALID,
998 "Unknown keyword found: %s. "
999 "If this is a macro you must "
1000 "add it as a DEFINE in the DSC" % self._ValueList[1],
1001 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
1002 self._Defines[self._ValueList[1]] = self._ValueList[2]
1003 self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]
1004
1005 @ParseMacro
1006 def _SkuIdParser(self):
1007 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
1008 if len(TokenList) != 2:
1009 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Integer>|<UiName>'",
1010 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
1011 self._ValueList[0:len(TokenList)] = TokenList
1012
1013 ## Parse Edk style of library modules
1014 def _LibraryInstanceParser(self):
1015 self._ValueList[0] = self._CurrentLine
1016
1017 ## PCD sections parser
1018 #
1019 # [PcdsFixedAtBuild]
1020 # [PcdsPatchableInModule]
1021 # [PcdsFeatureFlag]
1022 # [PcdsDynamicEx
1023 # [PcdsDynamicExDefault]
1024 # [PcdsDynamicExVpd]
1025 # [PcdsDynamicExHii]
1026 # [PcdsDynamic]
1027 # [PcdsDynamicDefault]
1028 # [PcdsDynamicVpd]
1029 # [PcdsDynamicHii]
1030 #
1031 @ParseMacro
1032 def _PcdParser(self):
1033 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
1034 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
1035 if len(TokenList) == 2:
1036 self._ValueList[2] = TokenList[1]
1037 if self._ValueList[0] == '' or self._ValueList[1] == '':
1038 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
1039 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1040 File=self.MetaFile, Line=self._LineIndex+1)
1041 if self._ValueList[2] == '':
1042 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",
1043 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1044 File=self.MetaFile, Line=self._LineIndex+1)
1045 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1046 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
1047 if DscPcdValueList[0] in ['True', 'true', 'TRUE']:
1048 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1);
1049 elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:
1050 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);
1051
1052 ## [components] section parser
1053 @ParseMacro
1054 def _ComponentParser(self):
1055 if self._CurrentLine[-1] == '{':
1056 self._ValueList[0] = self._CurrentLine[0:-1].strip()
1057 self._InSubsection = True
1058 else:
1059 self._ValueList[0] = self._CurrentLine
1060
1061 ## [LibraryClasses] section
1062 @ParseMacro
1063 def _LibraryClassParser(self):
1064 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
1065 if len(TokenList) < 2:
1066 EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",
1067 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1068 File=self.MetaFile, Line=self._LineIndex+1)
1069 if TokenList[0] == '':
1070 EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",
1071 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1072 File=self.MetaFile, Line=self._LineIndex+1)
1073 if TokenList[1] == '':
1074 EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",
1075 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1076 File=self.MetaFile, Line=self._LineIndex+1)
1077
1078 self._ValueList[0:len(TokenList)] = TokenList
1079
1080
1081 ## [BuildOptions] section parser
1082 @ParseMacro
1083 def _BuildOptionParser(self):
1084 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1085 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
1086 if len(TokenList2) == 2:
1087 self._ValueList[0] = TokenList2[0] # toolchain family
1088 self._ValueList[1] = TokenList2[1] # keys
1089 else:
1090 self._ValueList[1] = TokenList[0]
1091 if len(TokenList) == 2: # value
1092 self._ValueList[2] = TokenList[1]
1093
1094 if self._ValueList[1].count('_') != 4:
1095 EdkLogger.error(
1096 'Parser',
1097 FORMAT_INVALID,
1098 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
1099 ExtraData=self._CurrentLine,
1100 File=self.MetaFile,
1101 Line=self._LineIndex+1
1102 )
1103
1104 ## Override parent's method since we'll do all macro replacements in parser
1105 def _GetMacros(self):
1106 Macros = dict( [('ARCH', 'IA32'), ('FAMILY', TAB_COMPILER_MSFT), ('TOOL_CHAIN_TAG', 'VS2008x86'), ('TARGET', 'DEBUG')])
1107 Macros.update(self._FileLocalMacros)
1108 Macros.update(self._GetApplicableSectionMacro())
1109 Macros.update(GlobalData.gEdkGlobal)
1110 Macros.update(GlobalData.gPlatformDefines)
1111 Macros.update(GlobalData.gCommandLineDefines)
1112 # PCD cannot be referenced in macro definition
1113 if self._ItemType not in [MODEL_META_DATA_DEFINE, MODEL_META_DATA_GLOBAL_DEFINE]:
1114 Macros.update(self._Symbols)
1115 return Macros
1116
1117 def _PostProcess(self):
1118 Processer = {
1119 MODEL_META_DATA_SECTION_HEADER : self.__ProcessSectionHeader,
1120 MODEL_META_DATA_SUBSECTION_HEADER : self.__ProcessSubsectionHeader,
1121 MODEL_META_DATA_HEADER : self.__ProcessDefine,
1122 MODEL_META_DATA_DEFINE : self.__ProcessDefine,
1123 MODEL_META_DATA_GLOBAL_DEFINE : self.__ProcessDefine,
1124 MODEL_META_DATA_INCLUDE : self.__ProcessDirective,
1125 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF : self.__ProcessDirective,
1126 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE : self.__ProcessDirective,
1127 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF : self.__ProcessDirective,
1128 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF : self.__ProcessDirective,
1129 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF : self.__ProcessDirective,
1130 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF : self.__ProcessDirective,
1131 MODEL_EFI_SKU_ID : self.__ProcessSkuId,
1132 MODEL_EFI_LIBRARY_INSTANCE : self.__ProcessLibraryInstance,
1133 MODEL_EFI_LIBRARY_CLASS : self.__ProcessLibraryClass,
1134 MODEL_PCD_FIXED_AT_BUILD : self.__ProcessPcd,
1135 MODEL_PCD_PATCHABLE_IN_MODULE : self.__ProcessPcd,
1136 MODEL_PCD_FEATURE_FLAG : self.__ProcessPcd,
1137 MODEL_PCD_DYNAMIC_DEFAULT : self.__ProcessPcd,
1138 MODEL_PCD_DYNAMIC_HII : self.__ProcessPcd,
1139 MODEL_PCD_DYNAMIC_VPD : self.__ProcessPcd,
1140 MODEL_PCD_DYNAMIC_EX_DEFAULT : self.__ProcessPcd,
1141 MODEL_PCD_DYNAMIC_EX_HII : self.__ProcessPcd,
1142 MODEL_PCD_DYNAMIC_EX_VPD : self.__ProcessPcd,
1143 MODEL_META_DATA_COMPONENT : self.__ProcessComponent,
1144 MODEL_META_DATA_BUILD_OPTION : self.__ProcessBuildOption,
1145 MODEL_UNKNOWN : self._Skip,
1146 MODEL_META_DATA_USER_EXTENSION : self._Skip,
1147 MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR : self._Skip,
1148 }
1149
1150 self._RawTable = self._Table
1151 self._Table = MetaFileStorage(self._RawTable.Cur, self.MetaFile, MODEL_FILE_DSC, True)
1152 self._DirectiveStack = []
1153 self._DirectiveEvalStack = []
1154 self._FileWithError = self.MetaFile
1155 self._FileLocalMacros = {}
1156 self._SectionsMacroDict = {}
1157 GlobalData.gPlatformDefines = {}
1158
1159 # Get all macro and PCD which has straitforward value
1160 self.__RetrievePcdValue()
1161 self._Content = self._RawTable.GetAll()
1162 self._ContentIndex = 0
1163 while self._ContentIndex < len(self._Content) :
1164 Id, self._ItemType, V1, V2, V3, S1, S2, Owner, BelongsToFile, self._From, \
1165 LineStart, ColStart, LineEnd, ColEnd, Enabled = self._Content[self._ContentIndex]
1166
1167 if self._From < 0:
1168 self._FileWithError = self.MetaFile
1169
1170 self._ContentIndex += 1
1171
1172 self._Scope = [[S1, S2]]
1173 self._LineIndex = LineStart - 1
1174 self._ValueList = [V1, V2, V3]
1175
1176 try:
1177 Processer[self._ItemType]()
1178 except EvaluationException as Excpt:
1179 #
1180 # Only catch expression evaluation error here. We need to report
1181 # the precise number of line on which the error occurred
1182 #
1183 pass
1184 # EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
1185 # File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1186 # Line=self._LineIndex+1)
1187 except MacroException as Excpt:
1188 EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt),
1189 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1190 Line=self._LineIndex+1)
1191
1192 if self._ValueList is None:
1193 continue
1194
1195 NewOwner = self._IdMapping.get(Owner, -1)
1196 self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack))
1197 self._LastItem = self._Store(
1198 self._ItemType,
1199 self._ValueList[0],
1200 self._ValueList[1],
1201 self._ValueList[2],
1202 S1,
1203 S2,
1204 NewOwner,
1205 BelongsToFile,
1206 self._From,
1207 self._LineIndex+1,
1208 -1,
1209 self._LineIndex+1,
1210 -1,
1211 self._Enabled
1212 )
1213 self._IdMapping[Id] = self._LastItem
1214
1215 RecordList = self._Table.GetAll()
1216
1217 self._RawTable.Drop()
1218 self._Table.Drop()
1219 for Record in RecordList:
1220 EccGlobalData.gDb.TblDsc.Insert(Record[1], Record[2], Record[3], Record[4], Record[5], Record[6], Record[7], Record[8], Record[9], Record[10], Record[11], Record[12], Record[13], Record[14])
1221 GlobalData.gPlatformDefines.update(self._FileLocalMacros)
1222 self._PostProcessed = True
1223 self._Content = None
1224
1225 def __ProcessSectionHeader(self):
1226 self._SectionName = self._ValueList[0]
1227 if self._SectionName in self.DataType:
1228 self._SectionType = self.DataType[self._SectionName]
1229 else:
1230 self._SectionType = MODEL_UNKNOWN
1231
1232 def __ProcessSubsectionHeader(self):
1233 self._SubsectionName = self._ValueList[0]
1234 if self._SubsectionName in self.DataType:
1235 self._SubsectionType = self.DataType[self._SubsectionName]
1236 else:
1237 self._SubsectionType = MODEL_UNKNOWN
1238
1239 def __RetrievePcdValue(self):
1240 Records = self._RawTable.Query(MODEL_PCD_FEATURE_FLAG, BelongsToItem=-1.0)
1241 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, ID, Line in Records:
1242 Value, DatumType, MaxDatumSize = AnalyzePcdData(Value)
1243 # Only use PCD whose value is straitforward (no macro and PCD)
1244 if self.SymbolPattern.findall(Value):
1245 continue
1246 Name = TokenSpaceGuid + '.' + PcdName
1247 # Don't use PCD with different values.
1248 if Name in self._Symbols and self._Symbols[Name] != Value:
1249 self._Symbols.pop(Name)
1250 continue
1251 self._Symbols[Name] = Value
1252
1253 Records = self._RawTable.Query(MODEL_PCD_FIXED_AT_BUILD, BelongsToItem=-1.0)
1254 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, ID, Line in Records:
1255 Value, DatumType, MaxDatumSize = AnalyzePcdData(Value)
1256 # Only use PCD whose value is straitforward (no macro and PCD)
1257 if self.SymbolPattern.findall(Value):
1258 continue
1259 Name = TokenSpaceGuid+'.'+PcdName
1260 # Don't use PCD with different values.
1261 if Name in self._Symbols and self._Symbols[Name] != Value:
1262 self._Symbols.pop(Name)
1263 continue
1264 self._Symbols[Name] = Value
1265
1266 def __ProcessDefine(self):
1267 if not self._Enabled:
1268 return
1269
1270 Type, Name, Value = self._ValueList
1271 Value = ReplaceMacro(Value, self._Macros, False)
1272 if self._ItemType == MODEL_META_DATA_DEFINE:
1273 if self._SectionType == MODEL_META_DATA_HEADER:
1274 self._FileLocalMacros[Name] = Value
1275 else:
1276 SectionDictKey = self._SectionType, self._Scope[0][0], self._Scope[0][1]
1277 if SectionDictKey not in self._SectionsMacroDict:
1278 self._SectionsMacroDict[SectionDictKey] = {}
1279 SectionLocalMacros = self._SectionsMacroDict[SectionDictKey]
1280 SectionLocalMacros[Name] = Value
1281 elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE:
1282 GlobalData.gEdkGlobal[Name] = Value
1283
1284 #
1285 # Keyword in [Defines] section can be used as Macros
1286 #
1287 if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER):
1288 self._FileLocalMacros[Name] = Value
1289
1290 self._ValueList = [Type, Name, Value]
1291
1292 def __ProcessDirective(self):
1293 Result = None
1294 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1295 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF]:
1296 Macros = self._Macros
1297 Macros.update(GlobalData.gGlobalDefines)
1298 try:
1299 Result = ValueExpression(self._ValueList[1], Macros)()
1300 except SymbolNotFound as Exc:
1301 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])
1302 Result = False
1303 except WrnExpression as Excpt:
1304 #
1305 # Catch expression evaluation warning here. We need to report
1306 # the precise number of line and return the evaluation result
1307 #
1308 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),
1309 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1310 Line=self._LineIndex+1)
1311 Result = Excpt.result
1312 except BadExpression as Exc:
1313 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])
1314 Result = False
1315
1316 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1317 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
1318 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
1319 self._DirectiveStack.append(self._ItemType)
1320 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF:
1321 Result = bool(Result)
1322 else:
1323 Macro = self._ValueList[1]
1324 Macro = Macro[2:-1] if (Macro.startswith("$(") and Macro.endswith(")")) else Macro
1325 Result = Macro in self._Macros
1326 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF:
1327 Result = not Result
1328 self._DirectiveEvalStack.append(Result)
1329 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF:
1330 self._DirectiveStack.append(self._ItemType)
1331 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
1332 self._DirectiveEvalStack.append(bool(Result))
1333 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
1334 self._DirectiveStack[-1] = self._ItemType
1335 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
1336 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
1337 # Back to the nearest !if/!ifdef/!ifndef
1338 while self._DirectiveStack:
1339 self._DirectiveEvalStack.pop()
1340 Directive = self._DirectiveStack.pop()
1341 if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1342 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
1343 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,
1344 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
1345 break
1346 elif self._ItemType == MODEL_META_DATA_INCLUDE:
1347 # The included file must be relative to workspace or same directory as DSC file
1348 __IncludeMacros = {}
1349 #
1350 # Allow using system environment variables in path after !include
1351 #
1352 __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE']
1353
1354 #
1355 # Allow using MACROs comes from [Defines] section to keep compatible.
1356 #
1357 __IncludeMacros.update(self._Macros)
1358
1359 IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True))
1360 #
1361 # First search the include file under the same directory as DSC file
1362 #
1363 IncludedFile1 = PathClass(IncludedFile, self.MetaFile.Dir)
1364 ErrorCode, ErrorInfo1 = IncludedFile1.Validate()
1365 if ErrorCode != 0:
1366 #
1367 # Also search file under the WORKSPACE directory
1368 #
1369 IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)
1370 ErrorCode, ErrorInfo2 = IncludedFile1.Validate()
1371 if ErrorCode != 0:
1372 EdkLogger.error('parser', ErrorCode, File=self._FileWithError,
1373 Line=self._LineIndex+1, ExtraData=ErrorInfo1 + "\n"+ ErrorInfo2)
1374
1375 self._FileWithError = IncludedFile1
1376
1377 IncludedFileTable = MetaFileStorage(self._Table.Cur, IncludedFile1, MODEL_FILE_DSC, True)
1378 Owner = self._Content[self._ContentIndex-1][0]
1379 Parser = DscParser(IncludedFile1, self._FileType, IncludedFileTable,
1380 Owner=Owner, From=Owner)
1381
1382 # set the parser status with current status
1383 Parser._SectionName = self._SectionName
1384 Parser._SectionType = self._SectionType
1385 Parser._Scope = self._Scope
1386 Parser._Enabled = self._Enabled
1387 # Parse the included file
1388 Parser.Start()
1389
1390 # update current status with sub-parser's status
1391 self._SectionName = Parser._SectionName
1392 self._SectionType = Parser._SectionType
1393 self._Scope = Parser._Scope
1394 self._Enabled = Parser._Enabled
1395
1396 # Insert all records in the table for the included file into dsc file table
1397 Records = IncludedFileTable.GetAll()
1398 if Records:
1399 self._Content[self._ContentIndex:self._ContentIndex] = Records
1400 self._Content.pop(self._ContentIndex-1)
1401 self._ValueList = None
1402 self._ContentIndex -= 1
1403
1404 def __ProcessSkuId(self):
1405 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)
1406 for Value in self._ValueList]
1407
1408 def __ProcessLibraryInstance(self):
1409 self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
1410
1411 def __ProcessLibraryClass(self):
1412 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True)
1413
1414 def __ProcessPcd(self):
1415 ValueList = GetSplitValueList(self._ValueList[2])
1416 #
1417 # PCD value can be an expression
1418 #
1419 if len(ValueList) > 1 and ValueList[1] == TAB_VOID:
1420 PcdValue = ValueList[0]
1421 try:
1422 ValueList[0] = ValueExpression(PcdValue, self._Macros)(True)
1423 except WrnExpression as Value:
1424 ValueList[0] = Value.result
1425 else:
1426 PcdValue = ValueList[-1]
1427 try:
1428 ValueList[-1] = ValueExpression(PcdValue, self._Macros)(True)
1429 except WrnExpression as Value:
1430 ValueList[-1] = Value.result
1431
1432 if ValueList[-1] == 'True':
1433 ValueList[-1] = '1'
1434 if ValueList[-1] == 'False':
1435 ValueList[-1] = '0'
1436
1437 self._ValueList[2] = '|'.join(ValueList)
1438
1439 def __ProcessComponent(self):
1440 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
1441
1442 def __ProcessBuildOption(self):
1443 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False)
1444 for Value in self._ValueList]
1445
1446 _SectionParser = {
1447 MODEL_META_DATA_HEADER : _DefineParser,
1448 MODEL_EFI_SKU_ID : _SkuIdParser,
1449 MODEL_EFI_LIBRARY_INSTANCE : _LibraryInstanceParser,
1450 MODEL_EFI_LIBRARY_CLASS : _LibraryClassParser,
1451 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
1452 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
1453 MODEL_PCD_FEATURE_FLAG : _PcdParser,
1454 MODEL_PCD_DYNAMIC_DEFAULT : _PcdParser,
1455 MODEL_PCD_DYNAMIC_HII : _PcdParser,
1456 MODEL_PCD_DYNAMIC_VPD : _PcdParser,
1457 MODEL_PCD_DYNAMIC_EX_DEFAULT : _PcdParser,
1458 MODEL_PCD_DYNAMIC_EX_HII : _PcdParser,
1459 MODEL_PCD_DYNAMIC_EX_VPD : _PcdParser,
1460 MODEL_META_DATA_COMPONENT : _ComponentParser,
1461 MODEL_META_DATA_BUILD_OPTION : _BuildOptionParser,
1462 MODEL_UNKNOWN : MetaFileParser._Skip,
1463 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip,
1464 MODEL_META_DATA_SECTION_HEADER : MetaFileParser._SectionHeaderParser,
1465 MODEL_META_DATA_SUBSECTION_HEADER : _SubsectionHeaderParser,
1466 }
1467
1468 _Macros = property(_GetMacros)
1469
1470 ## DEC file parser class
1471 #
1472 # @param FilePath The path of platform description file
1473 # @param FileType The raw data of DSC file
1474 # @param Table Database used to retrieve module/package information
1475 # @param Macros Macros used for replacement in file
1476 #
1477 class DecParser(MetaFileParser):
1478 # DEC file supported data types (one type per section)
1479 DataType = {
1480 TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER,
1481 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
1482 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
1483 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
1484 TAB_GUIDS.upper() : MODEL_EFI_GUID,
1485 TAB_PPIS.upper() : MODEL_EFI_PPI,
1486 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
1487 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,
1488 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
1489 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,
1490 TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC,
1491 TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX,
1492 }
1493
1494 ## Constructor of DecParser
1495 #
1496 # Initialize object of DecParser
1497 #
1498 # @param FilePath The path of platform description file
1499 # @param FileType The raw data of DSC file
1500 # @param Table Database used to retrieve module/package information
1501 # @param Macros Macros used for replacement in file
1502 #
1503 def __init__(self, FilePath, FileType, Table):
1504 # prevent re-initialization
1505 if hasattr(self, "_Table"):
1506 return
1507 MetaFileParser.__init__(self, FilePath, FileType, Table)
1508 self._Comments = []
1509 self._Version = 0x00010005 # Only EDK2 dec file is supported
1510 self.TblFile = EccGlobalData.gDb.TblFile
1511 self.FileID = -1
1512
1513 self._CurrentStructurePcdName = ""
1514 self._include_flag = False
1515 self._package_flag = False
1516
1517 ## Parser starter
1518 def Start(self):
1519 Content = ''
1520 try:
1521 Content = open(str(self.MetaFile), 'r').readlines()
1522 except:
1523 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
1524
1525 #
1526 # Insert a record for file
1527 #
1528 Filename = NormPath(self.MetaFile)
1529 FileID = self.TblFile.GetFileId(Filename)
1530 if FileID:
1531 self.FileID = FileID
1532 else:
1533 self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_DEC)
1534
1535 for Index in range(0, len(Content)):
1536 Line, Comment = CleanString2(Content[Index])
1537 self._CurrentLine = Line
1538 self._LineIndex = Index
1539
1540 # save comment for later use
1541 if Comment:
1542 self._Comments.append((Comment, self._LineIndex+1))
1543 # skip empty line
1544 if Line == '':
1545 continue
1546
1547 # section header
1548 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
1549 self._SectionHeaderParser()
1550 self._Comments = []
1551 continue
1552 elif len(self._SectionType) == 0:
1553 self._Comments = []
1554 continue
1555
1556 # section content
1557 self._ValueList = ['', '', '']
1558 self._SectionParser[self._SectionType[0]](self)
1559 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:
1560 self._ItemType = -1
1561 self._Comments = []
1562 continue
1563
1564 #
1565 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1566 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1567 #
1568 for Arch, ModuleType, Type in self._Scope:
1569 self._LastItem = self._Store(
1570 Type,
1571 self._ValueList[0],
1572 self._ValueList[1],
1573 self._ValueList[2],
1574 Arch,
1575 ModuleType,
1576 self._Owner[-1],
1577 self.FileID,
1578 self._LineIndex+1,
1579 -1,
1580 self._LineIndex+1,
1581 -1,
1582 0
1583 )
1584 for Comment, LineNo in self._Comments:
1585 self._Store(
1586 MODEL_META_DATA_COMMENT,
1587 Comment,
1588 self._ValueList[0],
1589 self._ValueList[1],
1590 Arch,
1591 ModuleType,
1592 self._LastItem,
1593 self.FileID,
1594 LineNo,
1595 -1,
1596 LineNo,
1597 -1,
1598 0
1599 )
1600 self._Comments = []
1601 self._Done()
1602
1603 def _GetApplicableSectionMacro(self):
1604 Macros = {}
1605 for S1, S2, SectionType in self._Scope:
1606 for Scope1, Scope2 in [("COMMON", "COMMON"), ("COMMON", S2), (S1, "COMMON"), (S1, S2)]:
1607 if (SectionType, Scope1, Scope2) in self._SectionsMacroDict:
1608 Macros.update(self._SectionsMacroDict[(SectionType, Scope1, Scope2)])
1609 return Macros
1610
1611 ## Section header parser
1612 #
1613 # The section header is always in following format:
1614 #
1615 # [section_name.arch<.platform|module_type>]
1616 #
1617 def _SectionHeaderParser(self):
1618 self._Scope = []
1619 self._SectionName = ''
1620 self._SectionType = []
1621 ArchList = set()
1622 for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):
1623 if Item == '':
1624 continue
1625 ItemList = GetSplitValueList(Item, TAB_SPLIT)
1626
1627 # different types of PCD are permissible in one section
1628 self._SectionName = ItemList[0].upper()
1629 if self._SectionName in self.DataType:
1630 if self.DataType[self._SectionName] not in self._SectionType:
1631 self._SectionType.append(self.DataType[self._SectionName])
1632 else:
1633 EdkLogger.warn("Parser", "Unrecognized section", File=self.MetaFile,
1634 Line=self._LineIndex+1, ExtraData=self._CurrentLine)
1635 continue
1636
1637 if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:
1638 EdkLogger.error(
1639 'Parser',
1640 FORMAT_INVALID,
1641 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,
1642 File=self.MetaFile,
1643 Line=self._LineIndex+1,
1644 ExtraData=self._CurrentLine
1645 )
1646 # S1 is always Arch
1647 if len(ItemList) > 1:
1648 S1 = ItemList[1].upper()
1649 else:
1650 S1 = 'COMMON'
1651 ArchList.add(S1)
1652 # S2 may be Platform or ModuleType
1653 if len(ItemList) > 2:
1654 S2 = ItemList[2].upper()
1655 else:
1656 S2 = 'COMMON'
1657 if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:
1658 self._Scope.append([S1, S2, self.DataType[self._SectionName]])
1659
1660 # 'COMMON' must not be used with specific ARCHs at the same section
1661 if 'COMMON' in ArchList and len(ArchList) > 1:
1662 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
1663 File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine)
1664
1665 ## [guids], [ppis] and [protocols] section parser
1666 @ParseMacro
1667 def _GuidParser(self):
1668 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1669 if len(TokenList) < 2:
1670 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",
1671 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1672 File=self.MetaFile, Line=self._LineIndex+1)
1673 if TokenList[0] == '':
1674 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",
1675 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1676 File=self.MetaFile, Line=self._LineIndex+1)
1677 if TokenList[1] == '':
1678 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",
1679 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1680 File=self.MetaFile, Line=self._LineIndex+1)
1681 if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':
1682 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",
1683 ExtraData=self._CurrentLine + \
1684 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1685 File=self.MetaFile, Line=self._LineIndex+1)
1686 self._ValueList[0] = TokenList[0]
1687 #Parse the Guid value format
1688 GuidValueList = TokenList[1].strip(' {}').split(',')
1689 Index = 0
1690 HexList = []
1691 if len(GuidValueList) == 11:
1692 for GuidValue in GuidValueList:
1693 GuidValue = GuidValue.strip()
1694 if GuidValue.startswith('0x') or GuidValue.startswith('0X'):
1695 HexList.append('0x' + str(GuidValue[2:]))
1696 Index += 1
1697 continue
1698 else:
1699 if GuidValue.startswith('{'):
1700 GuidValue = GuidValue.lstrip(' {')
1701 HexList.append('0x' + str(GuidValue[2:]))
1702 Index += 1
1703 self._ValueList[1] = "{ %s, %s, %s, { %s, %s, %s, %s, %s, %s, %s, %s }}" % (HexList[0], HexList[1], HexList[2], HexList[3], HexList[4], HexList[5], HexList[6], HexList[7], HexList[8], HexList[9], HexList[10])
1704 else:
1705 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",
1706 ExtraData=self._CurrentLine + \
1707 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1708 File=self.MetaFile, Line=self._LineIndex+1)
1709 self._ValueList[0] = ''
1710
1711 def ParsePcdName(self,namelist):
1712 if "[" in namelist[1]:
1713 pcdname = namelist[1][:namelist[1].index("[")]
1714 arrayindex = namelist[1][namelist[1].index("["):]
1715 namelist[1] = pcdname
1716 if len(namelist) == 2:
1717 namelist.append(arrayindex)
1718 else:
1719 namelist[2] = ".".join((arrayindex,namelist[2]))
1720 return namelist
1721
1722 def StructPcdParser(self):
1723 self._ValueList[0] = self._CurrentStructurePcdName
1724
1725 if "|" not in self._CurrentLine:
1726 if "<HeaderFiles>" == self._CurrentLine:
1727 self._include_flag = True
1728 self._package_flag = False
1729 self._ValueList = None
1730 return
1731 if "<Packages>" == self._CurrentLine:
1732 self._package_flag = True
1733 self._ValueList = None
1734 self._include_flag = False
1735 return
1736
1737 if self._include_flag:
1738 self._ValueList[1] = "<HeaderFiles>_" + md5(self._CurrentLine.encode('utf-8')).hexdigest()
1739 self._ValueList[2] = self._CurrentLine
1740 if self._package_flag and "}" != self._CurrentLine:
1741 self._ValueList[1] = "<Packages>_" + md5(self._CurrentLine.encode('utf-8')).hexdigest()
1742 self._ValueList[2] = self._CurrentLine
1743 if self._CurrentLine == "}":
1744 self._package_flag = False
1745 self._include_flag = False
1746 self._ValueList = None
1747 else:
1748 PcdTockens = self._CurrentLine.split(TAB_VALUE_SPLIT)
1749 PcdNames = self.ParsePcdName(PcdTockens[0].split(TAB_SPLIT))
1750 if len(PcdNames) == 2:
1751 if PcdNames[1].strip().endswith("]"):
1752 PcdName = PcdNames[1][:PcdNames[1].index('[')]
1753 Index = PcdNames[1][PcdNames[1].index('['):]
1754 self._ValueList[0] = TAB_SPLIT.join((PcdNames[0], PcdName))
1755 self._ValueList[1] = Index
1756 self._ValueList[2] = PcdTockens[1]
1757 else:
1758 self._CurrentStructurePcdName = ""
1759 else:
1760 if self._CurrentStructurePcdName != TAB_SPLIT.join(PcdNames[:2]):
1761 EdkLogger.error('Parser', FORMAT_INVALID, "Pcd Name does not match: %s and %s " % (
1762 self._CurrentStructurePcdName, TAB_SPLIT.join(PcdNames[:2])),
1763 File=self.MetaFile, Line=self._LineIndex + 1)
1764 self._ValueList[1] = TAB_SPLIT.join(PcdNames[2:])
1765 self._ValueList[2] = PcdTockens[1]
1766
1767 ## PCD sections parser
1768 #
1769 # [PcdsFixedAtBuild]
1770 # [PcdsPatchableInModule]
1771 # [PcdsFeatureFlag]
1772 # [PcdsDynamicEx
1773 # [PcdsDynamic]
1774 #
1775 @ParseMacro
1776 def _PcdParser(self):
1777 if self._CurrentStructurePcdName:
1778 self.StructPcdParser()
1779 return
1780 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
1781 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
1782 # check PCD information
1783 if self._ValueList[0] == '' or self._ValueList[1] == '':
1784 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
1785 ExtraData=self._CurrentLine + \
1786 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1787 File=self.MetaFile, Line=self._LineIndex+1)
1788 # check PCD datum information
1789 if len(TokenList) < 2 or TokenList[1] == '':
1790 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",
1791 ExtraData=self._CurrentLine + \
1792 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1793 File=self.MetaFile, Line=self._LineIndex+1)
1794
1795
1796 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')
1797 PtrValue = ValueRe.findall(TokenList[1])
1798
1799 # Has VOID* type string, may contain "|" character in the string.
1800 if len(PtrValue) != 0:
1801 ptrValueList = re.sub(ValueRe, '', TokenList[1])
1802 ValueList = GetSplitValueList(ptrValueList)
1803 ValueList[0] = PtrValue[0]
1804 else:
1805 ValueList = GetSplitValueList(TokenList[1])
1806
1807
1808 # check if there's enough datum information given
1809 if len(ValueList) != 3:
1810 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",
1811 ExtraData=self._CurrentLine + \
1812 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1813 File=self.MetaFile, Line=self._LineIndex+1)
1814 # check default value
1815 if ValueList[0] == '':
1816 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",
1817 ExtraData=self._CurrentLine + \
1818 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1819 File=self.MetaFile, Line=self._LineIndex+1)
1820 # check datum type
1821 if ValueList[1] == '':
1822 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",
1823 ExtraData=self._CurrentLine + \
1824 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1825 File=self.MetaFile, Line=self._LineIndex+1)
1826 # check token of the PCD
1827 if ValueList[2] == '':
1828 EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",
1829 ExtraData=self._CurrentLine + \
1830 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1831 File=self.MetaFile, Line=self._LineIndex+1)
1832 # check format of default value against the datum type
1833 IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])
1834 if not IsValid:
1835 EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,
1836 File=self.MetaFile, Line=self._LineIndex+1)
1837 if Cause == "StructurePcd":
1838 self._CurrentStructurePcdName = TAB_SPLIT.join(self._ValueList[0:2])
1839 self._ValueList[0] = self._CurrentStructurePcdName
1840 self._ValueList[1] = ValueList[1].strip()
1841
1842 if EccGlobalData.gConfig.UniCheckPCDInfo == '1' or EccGlobalData.gConfig.UniCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
1843 # check Description, Prompt information
1844 PatternDesc = re.compile('##\s*([\x21-\x7E\s]*)', re.S)
1845 PatternPrompt = re.compile('#\s+@Prompt\s+([\x21-\x7E\s]*)', re.S)
1846 Description = None
1847 Prompt = None
1848 # check @ValidRange, @ValidList and @Expression format valid
1849 ErrorCodeValid = '0x0 <= %s <= 0xFFFFFFFF'
1850 PatternValidRangeIn = '(NOT)?\s*(\d+\s*-\s*\d+|0[xX][a-fA-F0-9]+\s*-\s*0[xX][a-fA-F0-9]+|LT\s*\d+|LT\s*0[xX][a-fA-F0-9]+|GT\s*\d+|GT\s*0[xX][a-fA-F0-9]+|LE\s*\d+|LE\s*0[xX][a-fA-F0-9]+|GE\s*\d+|GE\s*0[xX][a-fA-F0-9]+|XOR\s*\d+|XOR\s*0[xX][a-fA-F0-9]+|EQ\s*\d+|EQ\s*0[xX][a-fA-F0-9]+)'
1851 PatternValidRng = re.compile('^' + '(NOT)?\s*' + PatternValidRangeIn + '$')
1852 for Comment in self._Comments:
1853 Comm = Comment[0].strip()
1854 if not Comm:
1855 continue
1856 if not Description:
1857 Description = PatternDesc.findall(Comm)
1858 if not Prompt:
1859 Prompt = PatternPrompt.findall(Comm)
1860 if Comm[0] == '#':
1861 ValidFormt = Comm.lstrip('#')
1862 ValidFormt = ValidFormt.lstrip()
1863 if ValidFormt[0:11] == '@ValidRange':
1864 ValidFormt = ValidFormt[11:]
1865 ValidFormt = ValidFormt.lstrip()
1866 try:
1867 ErrorCode, Expression = ValidFormt.split('|', 1)
1868 except ValueError:
1869 ErrorCode = '0x0'
1870 Expression = ValidFormt
1871 ErrorCode, Expression = ErrorCode.strip(), Expression.strip()
1872 try:
1873 if not eval(ErrorCodeValid % ErrorCode):
1874 EdkLogger.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))
1875 except:
1876 EdkLogger.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))
1877 if not PatternValidRng.search(Expression):
1878 EdkLogger.warn('Parser', '@ValidRange Expression(%s) of PCD %s is incorrect format.' % (Expression, TokenList[0]))
1879 if ValidFormt[0:10] == '@ValidList':
1880 ValidFormt = ValidFormt[10:]
1881 ValidFormt = ValidFormt.lstrip()
1882 try:
1883 ErrorCode, Expression = ValidFormt.split('|', 1)
1884 except ValueError:
1885 ErrorCode = '0x0'
1886 Expression = ValidFormt
1887 ErrorCode, Expression = ErrorCode.strip(), Expression.strip()
1888 try:
1889 if not eval(ErrorCodeValid % ErrorCode):
1890 EdkLogger.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))
1891 except:
1892 EdkLogger.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))
1893 Values = Expression.split(',')
1894 for Value in Values:
1895 Value = Value.strip()
1896 try:
1897 eval(Value)
1898 except:
1899 EdkLogger.warn('Parser', '@ValidList Expression of PCD %s include a invalid value(%s).' % (TokenList[0], Value))
1900 break
1901 if ValidFormt[0:11] == '@Expression':
1902 ValidFormt = ValidFormt[11:]
1903 ValidFormt = ValidFormt.lstrip()
1904 try:
1905 ErrorCode, Expression = ValidFormt.split('|', 1)
1906 except ValueError:
1907 ErrorCode = '0x0'
1908 Expression = ValidFormt
1909 ErrorCode, Expression = ErrorCode.strip(), Expression.strip()
1910 try:
1911 if not eval(ErrorCodeValid % ErrorCode):
1912 EdkLogger.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))
1913 except:
1914 EdkLogger.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode, TokenList[0]))
1915 if not Expression:
1916 EdkLogger.warn('Parser', '@Expression Expression of PCD %s is incorrect format.' % TokenList[0])
1917 if not Description:
1918 EdkLogger.warn('Parser', 'PCD %s Description information is not provided.' % TokenList[0])
1919 if not Prompt:
1920 EdkLogger.warn('Parser', 'PCD %s Prompt information is not provided.' % TokenList[0])
1921 # check Description, Prompt localization information
1922 if self._UniObj:
1923 self._UniObj.CheckPcdInfo(TokenList[0])
1924
1925 if ValueList[0] in ['True', 'true', 'TRUE']:
1926 ValueList[0] = '1'
1927 elif ValueList[0] in ['False', 'false', 'FALSE']:
1928 ValueList[0] = '0'
1929
1930 self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()
1931
1932 _SectionParser = {
1933 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,
1934 MODEL_EFI_INCLUDE : MetaFileParser._PathParser,
1935 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,
1936 MODEL_EFI_GUID : _GuidParser,
1937 MODEL_EFI_PPI : _GuidParser,
1938 MODEL_EFI_PROTOCOL : _GuidParser,
1939 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
1940 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
1941 MODEL_PCD_FEATURE_FLAG : _PcdParser,
1942 MODEL_PCD_DYNAMIC : _PcdParser,
1943 MODEL_PCD_DYNAMIC_EX : _PcdParser,
1944 MODEL_UNKNOWN : MetaFileParser._Skip,
1945 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip,
1946 }
1947
1948
1949 ## Fdf
1950 #
1951 # This class defined the structure used in Fdf object
1952 #
1953 # @param Filename: Input value for Ffilename of Fdf file, default is None
1954 # @param WorkspaceDir: Input value for current workspace directory, default is None
1955 #
1956 class Fdf(object):
1957 def __init__(self, Filename = None, IsToDatabase = False, WorkspaceDir = None, Database = None):
1958 self.WorkspaceDir = WorkspaceDir
1959 self.IsToDatabase = IsToDatabase
1960
1961 self.Cur = Database.Cur
1962 self.TblFile = Database.TblFile
1963 self.TblFdf = Database.TblFdf
1964 self.FileID = -1
1965 self.FileList = {}
1966
1967 #
1968 # Load Fdf file if filename is not None
1969 #
1970 if Filename is not None:
1971 try:
1972 self.LoadFdfFile(Filename)
1973 except Exception:
1974 pass
1975
1976 #
1977 # Insert a FDF file record into database
1978 #
1979 def InsertFile(self, Filename):
1980 FileID = -1
1981 Filename = NormPath(Filename)
1982 if Filename not in self.FileList:
1983 FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_FDF)
1984 self.FileList[Filename] = FileID
1985
1986 return self.FileList[Filename]
1987
1988
1989 ## Load Fdf file
1990 #
1991 # Load the file if it exists
1992 #
1993 # @param Filename: Input value for filename of Fdf file
1994 #
1995 def LoadFdfFile(self, Filename):
1996 FileList = []
1997 #
1998 # Parse Fdf file
1999 #
2000 Filename = NormPath(Filename)
2001 Fdf = FdfParser(Filename)
2002 Fdf.ParseFile()
2003
2004 #
2005 # Insert inf file and pcd information
2006 #
2007 if self.IsToDatabase:
2008 (Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled) = \
2009 (0, '', '', '', 'COMMON', 'COMMON', -1, -1, -1, -1, -1, -1, 0)
2010 for Index in range(0, len(Fdf.Profile.PcdDict)):
2011 pass
2012 for Key in Fdf.Profile.PcdDict.keys():
2013 Model = MODEL_PCD
2014 Value1 = Key[1]
2015 Value2 = Key[0]
2016 FileName = Fdf.Profile.PcdFileLineDict[Key][0]
2017 StartLine = Fdf.Profile.PcdFileLineDict[Key][1]
2018 BelongsToFile = self.InsertFile(FileName)
2019 self.TblFdf.Insert(Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled)
2020 for Index in range(0, len(Fdf.Profile.InfList)):
2021 Model = MODEL_META_DATA_COMPONENT
2022 Value1 = Fdf.Profile.InfList[Index]
2023 Value2 = ''
2024 FileName = Fdf.Profile.InfFileLineList[Index][0]
2025 StartLine = Fdf.Profile.InfFileLineList[Index][1]
2026 BelongsToFile = self.InsertFile(FileName)
2027 self.TblFdf.Insert(Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled)
2028
2029 class UniParser(object):
2030 # IsExtraUni defined the UNI file is Module UNI or extra Module UNI
2031 # IsModuleUni defined the UNI file is Module UNI or Package UNI
2032 def __init__(self, FilePath, IsExtraUni=False, IsModuleUni=True):
2033 self.FilePath = FilePath
2034 self.FileName = os.path.basename(FilePath)
2035 self.IsExtraUni = IsExtraUni
2036 self.IsModuleUni = IsModuleUni
2037 self.FileIn = None
2038 self.Missing = []
2039 self.__read()
2040
2041 def __read(self):
2042 try:
2043 self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_8').read()
2044 except UnicodeError:
2045 self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_16').read()
2046 except UnicodeError:
2047 self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode='rb', Encoding='utf_16_le').read()
2048 except IOError:
2049 self.FileIn = ""
2050
2051 def Start(self):
2052 if self.IsModuleUni:
2053 if self.IsExtraUni:
2054 ModuleName = self.CheckKeyValid('STR_PROPERTIES_MODULE_NAME')
2055 self.PrintLog('STR_PROPERTIES_MODULE_NAME', ModuleName)
2056 else:
2057 ModuleAbstract = self.CheckKeyValid('STR_MODULE_ABSTRACT')
2058 self.PrintLog('STR_MODULE_ABSTRACT', ModuleAbstract)
2059 ModuleDescription = self.CheckKeyValid('STR_MODULE_DESCRIPTION')
2060 self.PrintLog('STR_MODULE_DESCRIPTION', ModuleDescription)
2061 else:
2062 if self.IsExtraUni:
2063 PackageName = self.CheckKeyValid('STR_PROPERTIES_PACKAGE_NAME')
2064 self.PrintLog('STR_PROPERTIES_PACKAGE_NAME', PackageName)
2065 else:
2066 PackageAbstract = self.CheckKeyValid('STR_PACKAGE_ABSTRACT')
2067 self.PrintLog('STR_PACKAGE_ABSTRACT', PackageAbstract)
2068 PackageDescription = self.CheckKeyValid('STR_PACKAGE_DESCRIPTION')
2069 self.PrintLog('STR_PACKAGE_DESCRIPTION', PackageDescription)
2070
2071 def CheckKeyValid(self, Key, Contents=None):
2072 if not Contents:
2073 Contents = self.FileIn
2074 KeyPattern = re.compile('#string\s+%s\s+.*?#language.*?".*?"' % Key, re.S)
2075 if KeyPattern.search(Contents):
2076 return True
2077 return False
2078
2079 def CheckPcdInfo(self, PcdCName):
2080 PromptKey = 'STR_%s_PROMPT' % PcdCName.replace('.', '_')
2081 PcdPrompt = self.CheckKeyValid(PromptKey)
2082 self.PrintLog(PromptKey, PcdPrompt)
2083 HelpKey = 'STR_%s_HELP' % PcdCName.replace('.', '_')
2084 PcdHelp = self.CheckKeyValid(HelpKey)
2085 self.PrintLog(HelpKey, PcdHelp)
2086
2087 def PrintLog(self, Key, Value):
2088 if not Value and Key not in self.Missing:
2089 Msg = '%s is missing in the %s file.' % (Key, self.FileName)
2090 EdkLogger.warn('Parser', Msg)
2091 EccGlobalData.gDb.TblReport.Insert(EccToolError.ERROR_GENERAL_CHECK_UNI_HELP_INFO, OtherMsg=Msg, BelongsToTable='File', BelongsToItem=-2)
2092 self.Missing.append(Key)
2093
2094 ##
2095 #
2096 # This acts like the main() function for the script, unless it is 'import'ed into another
2097 # script.
2098 #
2099 if __name__ == '__main__':
2100 pass
2101