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