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