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