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