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