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