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