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