2 # This file is used to parse DEC file. It will consumed by DecParser
4 # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
6 # This program and the accompanying materials are licensed and made available
7 # under the terms and conditions of the BSD License which accompanies this
8 # distribution. The full text of the license may be found at
9 # http://opensource.org/licenses/bsd-license.php
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.
18 import Logger
.Log
as Logger
19 from Logger
.ToolError
import FILE_PARSE_FAILURE
20 from Logger
.ToolError
import FILE_OPEN_FAILURE
21 from Logger
import StringTable
as ST
22 from Logger
.ToolError
import FORMAT_INVALID
24 import Library
.DataType
as DT
25 from Library
.ParserValidate
import IsValidToken
26 from Library
.ParserValidate
import IsValidPath
27 from Library
.ParserValidate
import IsValidCFormatGuid
28 from Library
.ParserValidate
import IsValidIdString
29 from Library
.ParserValidate
import IsValidUserId
30 from Library
.ParserValidate
import IsValidArch
31 from Library
.ParserValidate
import IsValidWord
32 from Library
.ParserValidate
import IsValidDecVersionVal
33 from Parser
.DecParserMisc
import TOOL_NAME
34 from Parser
.DecParserMisc
import CleanString
35 from Parser
.DecParserMisc
import IsValidPcdDatum
36 from Parser
.DecParserMisc
import ParserHelper
37 from Parser
.DecParserMisc
import StripRoot
38 from Parser
.DecParserMisc
import VERSION_PATTERN
39 from Parser
.DecParserMisc
import CVAR_PATTERN
40 from Parser
.DecParserMisc
import PCD_TOKEN_PATTERN
41 from Parser
.DecParserMisc
import MACRO_PATTERN
42 from Parser
.DecParserMisc
import FileContent
43 from Object
.Parser
.DecObject
import _DecComments
44 from Object
.Parser
.DecObject
import DecDefineObject
45 from Object
.Parser
.DecObject
import DecDefineItemObject
46 from Object
.Parser
.DecObject
import DecIncludeObject
47 from Object
.Parser
.DecObject
import DecIncludeItemObject
48 from Object
.Parser
.DecObject
import DecLibraryclassObject
49 from Object
.Parser
.DecObject
import DecLibraryclassItemObject
50 from Object
.Parser
.DecObject
import DecGuidObject
51 from Object
.Parser
.DecObject
import DecPpiObject
52 from Object
.Parser
.DecObject
import DecProtocolObject
53 from Object
.Parser
.DecObject
import DecGuidItemObject
54 from Object
.Parser
.DecObject
import DecUserExtensionObject
55 from Object
.Parser
.DecObject
import DecUserExtensionItemObject
56 from Object
.Parser
.DecObject
import DecPcdObject
57 from Object
.Parser
.DecObject
import DecPcdItemObject
58 from Library
.Misc
import GuidStructureStringToGuidString
59 from Library
.Misc
import CheckGuidRegFormat
60 from Library
.StringUtils
import ReplaceMacro
61 from Library
.StringUtils
import GetSplitValueList
62 from Library
.StringUtils
import gMACRO_PATTERN
63 from Library
.StringUtils
import ConvertSpecialChar
64 from Library
.CommentParsing
import ParsePcdErrorCode
67 # _DecBase class for parsing
70 def __init__(self
, RawData
):
71 self
._RawData
= RawData
75 # Data parsed by 'self' are saved to this object
77 self
.ItemObject
= None
79 def GetDataObject(self
):
80 return self
.ItemObject
82 def GetLocalMacro(self
):
83 return self
._LocalMacro
87 # Called if a new section starts
94 # @param Key: to be checked if multi-defined
95 # @param Scope: Format: [[SectionName, Arch], ...].
96 # If scope is none, use global scope
98 def _CheckReDefine(self
, Key
, Scope
= None):
100 Scope
= self
._RawData
.CurrentScope
105 # Copy scope to SecArch, avoid Scope be changed outside
107 SecArch
[0:1] = Scope
[:]
108 if Key
not in self
._ItemDict
:
109 self
._ItemDict
[Key
] = [[SecArch
, self
._RawData
.LineIndex
]]
112 for Value
in self
._ItemDict
[Key
]:
113 for SubValue
in Scope
:
115 # If current is common section
117 if SubValue
[-1] == 'COMMON':
118 for Other
in Value
[0]:
119 # Key in common cannot be redefined in other arches
120 # [:-1] means stripping arch info
121 if Other
[:-1] == SubValue
[:-1]:
122 self
._LoggerError
(ST
.ERR_DECPARSE_REDEFINE
% (Key
, Value
[1]))
126 CommonScope
[0:1] = SubValue
127 CommonScope
[-1] = 'COMMON'
129 # Cannot be redefined if this key already defined in COMMON Or defined in same arch
131 if SubValue
in Value
[0] or CommonScope
in Value
[0]:
132 self
._LoggerError
(ST
.ERR_DECPARSE_REDEFINE
% (Key
, Value
[1]))
134 self
._ItemDict
[Key
].append([SecArch
, self
._RawData
.LineIndex
])
136 ## CheckRequiredFields
137 # Some sections need to check if some fields exist, define section for example
138 # Derived class can re-implement, top parser will call this function after all parsing done
140 def CheckRequiredFields(self
):
146 # In DEC spec, sections must have at least one statement except user
148 # For example: "[guids" [<attribs>] "]" <EOL> <statements>+
149 # sub class can override this method to indicate if statement is a must.
151 def _IsStatementRequired(self
):
156 def _LoggerError(self
, ErrorString
):
157 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
158 Line
= self
._RawData
.LineIndex
,
159 ExtraData
=ErrorString
+ ST
.ERR_DECPARSE_LINE
% self
._RawData
.CurrentLine
)
161 def _ReplaceMacro(self
, String
):
162 if gMACRO_PATTERN
.findall(String
):
163 String
= ReplaceMacro(String
, self
._LocalMacro
, False,
164 FileName
= self
._RawData
.Filename
,
165 Line
= ['', self
._RawData
.LineIndex
])
166 String
= ReplaceMacro(String
, self
._RawData
.Macros
, False,
167 FileName
= self
._RawData
.Filename
,
168 Line
= ['', self
._RawData
.LineIndex
])
169 MacroUsed
= gMACRO_PATTERN
.findall(String
)
171 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
,
172 File
=self
._RawData
.Filename
,
173 Line
= self
._RawData
.LineIndex
,
174 ExtraData
= ST
.ERR_DECPARSE_MACRO_RESOLVE
% (str(MacroUsed
), String
))
177 def _MacroParser(self
, String
):
178 TokenList
= GetSplitValueList(String
, ' ', 1)
179 if len(TokenList
) < 2 or TokenList
[1] == '':
180 self
._LoggerError
(ST
.ERR_DECPARSE_MACRO_PAIR
)
182 TokenList
= GetSplitValueList(TokenList
[1], DT
.TAB_EQUAL_SPLIT
, 1)
183 if TokenList
[0] == '':
184 self
._LoggerError
(ST
.ERR_DECPARSE_MACRO_NAME
)
185 elif not IsValidToken(MACRO_PATTERN
, TokenList
[0]):
186 self
._LoggerError
(ST
.ERR_DECPARSE_MACRO_NAME_UPPER
% TokenList
[0])
188 if len(TokenList
) == 1:
189 self
._LocalMacro
[TokenList
[0]] = ''
191 self
._LocalMacro
[TokenList
[0]] = self
._ReplaceMacro
(TokenList
[1])
195 # Parse specified item, this function must be derived by subclass
197 def _ParseItem(self
):
201 # Should never be called
206 ## _TailCommentStrategy
208 # This function can be derived to parse tail comment
209 # default is it will not consume any lines
211 # @param Comment: Comment of current line
213 def _TailCommentStrategy(self
, Comment
):
220 ## _StopCurrentParsing
222 # Called in Parse if current parsing should be stopped when encounter some
224 # Default is section start and end
226 # @param Line: Current line
228 def _StopCurrentParsing(self
, Line
):
231 return Line
[0] == DT
.TAB_SECTION_START
and Line
[-1] == DT
.TAB_SECTION_END
235 # Split comment and DEC content, concatenate lines if end of char is '\'
237 # @param ProcessedLine: ProcessedLine line
238 # @param ProcessedComments: ProcessedComments line
240 def _TryBackSlash(self
, ProcessedLine
, ProcessedComments
):
244 CommentList
= ProcessedComments
245 while not self
._RawData
.IsEndOfFile():
247 self
._LoggerError
(ST
.ERR_DECPARSE_BACKSLASH_EMPTY
)
251 CommentList
.append((Comment
, self
._RawData
.LineIndex
))
252 if Line
[-1] != DT
.TAB_SLASH
:
255 elif len(Line
) < 2 or Line
[-2] != ' ':
256 self
._LoggerError
(ST
.ERR_DECPARSE_BACKSLASH
)
259 Line
, Comment
= CleanString(self
._RawData
.GetNextLine())
261 # Reach end of content
263 if self
._RawData
.IsEndOfFile():
265 if ProcessedLine
[-1] == DT
.TAB_SLASH
:
266 self
._LoggerError
(ST
.ERR_DECPARSE_BACKSLASH_EMPTY
)
267 CatLine
= ProcessedLine
269 if not Line
or Line
[-1] == DT
.TAB_SLASH
:
270 self
._LoggerError
(ST
.ERR_DECPARSE_BACKSLASH_EMPTY
)
274 # All MACRO values defined by the DEFINE statements in any section
275 # (except [Userextensions] sections for Intel) of the INF or DEC file
276 # must be expanded before processing of the file.
278 __IsReplaceMacro
= True
279 Header
= self
._RawData
.CurrentScope
[0] if self
._RawData
.CurrentScope
else None
280 if Header
and len(Header
) > 2:
281 if Header
[0].upper() == 'USEREXTENSIONS' and not (Header
[1] == 'TianoCore' and Header
[2] == '"ExtraFiles"'):
282 __IsReplaceMacro
= False
284 self
._RawData
.CurrentLine
= self
._ReplaceMacro
(CatLine
)
286 self
._RawData
.CurrentLine
= CatLine
288 return CatLine
, CommentList
291 # This is a template method in which other member functions which might
292 # override by sub class are called. It is responsible for reading file
293 # line by line, and call other member functions to parse. This function
294 # should not be re-implement by sub class.
300 #======================================================================
301 # CurComments may pointer to HeadComments or TailComments
302 #======================================================================
303 CurComments
= HeadComments
308 #======================================================================
309 # Used to report error information if empty section found
310 #======================================================================
311 Index
= self
._RawData
.LineIndex
312 LineStr
= self
._RawData
.CurrentLine
313 while not self
._RawData
.IsEndOfFile() or self
._RawData
.NextLine
:
314 if self
._RawData
.NextLine
:
315 #==============================================================
316 # Have processed line in buffer
317 #==============================================================
318 Line
= self
._RawData
.NextLine
319 HeadComments
.extend(self
._RawData
.HeadComment
)
320 TailComments
.extend(self
._RawData
.TailComment
)
321 self
._RawData
.ResetNext()
325 #==============================================================
326 # No line in buffer, read next line
327 #==============================================================
328 Line
, Comment
= CleanString(self
._RawData
.GetNextLine())
331 if not FromBuf
and CurObj
and TailComments
:
332 #==========================================================
333 # Set tail comments to previous statement if not empty.
334 #==========================================================
335 CurObj
.SetTailComment(CurObj
.GetTailComment()+TailComments
)
339 CurComments
= TailComments
342 Comments
= [(Comment
, self
._RawData
.LineIndex
)]
344 #==============================================================
345 # Try if last char of line has backslash
346 #==============================================================
347 Line
, Comments
= self
._TryBackSlash
(Line
, Comments
)
348 CurComments
.extend(Comments
)
350 #==============================================================
352 #==============================================================
353 if Line
.startswith('DEFINE '):
354 self
._MacroParser
(Line
)
357 CurComments
= HeadComments
360 if self
._StopCurrentParsing
(Line
):
361 #==========================================================
362 # This line does not belong to this parse,
363 # Save it, can be used by next parse
364 #==========================================================
365 self
._RawData
.SetNext(Line
, HeadComments
, TailComments
)
368 Obj
= self
._ParseItem
()
371 Obj
.SetHeadComment(Obj
.GetHeadComment()+HeadComments
)
372 Obj
.SetTailComment(Obj
.GetTailComment()+TailComments
)
379 if id(CurComments
) == id(TailComments
):
380 #==========================================================
381 # Check if this comment belongs to tail comment
382 #==========================================================
383 if not self
._TailCommentStrategy
(Comment
):
384 CurComments
= HeadComments
387 CurComments
.append(((Comment
, self
._RawData
.LineIndex
)))
391 if self
._IsStatementRequired
() and ItemNum
== 0:
393 TOOL_NAME
, FILE_PARSE_FAILURE
,
394 File
=self
._RawData
.Filename
,
396 ExtraData
=ST
.ERR_DECPARSE_STATEMENT_EMPTY
% LineStr
400 # Parse define section
402 class _DecDefine(_DecBase
):
403 def __init__(self
, RawData
):
404 _DecBase
.__init
__(self
, RawData
)
405 self
.ItemObject
= DecDefineObject(RawData
.Filename
)
406 self
._LocalMacro
= self
._RawData
.Macros
410 # Each field has a function to validate
412 self
.DefineValidation
= {
413 DT
.TAB_DEC_DEFINES_DEC_SPECIFICATION
: self
._SetDecSpecification
,
414 DT
.TAB_DEC_DEFINES_PACKAGE_NAME
: self
._SetPackageName
,
415 DT
.TAB_DEC_DEFINES_PACKAGE_GUID
: self
._SetPackageGuid
,
416 DT
.TAB_DEC_DEFINES_PACKAGE_VERSION
: self
._SetPackageVersion
,
417 DT
.TAB_DEC_DEFINES_PKG_UNI_FILE
: self
._SetPackageUni
,
420 def BlockStart(self
):
422 if self
._DefSecNum
> 1:
423 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_MULTISEC
)
425 ## CheckRequiredFields
427 # Check required fields: DEC_SPECIFICATION, PACKAGE_NAME
428 # PACKAGE_GUID, PACKAGE_VERSION
430 def CheckRequiredFields(self
):
432 if self
.ItemObject
.GetPackageSpecification() == '':
433 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
434 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_DEC_SPECIFICATION
)
435 elif self
.ItemObject
.GetPackageName() == '':
436 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
437 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_PACKAGE_NAME
)
438 elif self
.ItemObject
.GetPackageGuid() == '':
439 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
440 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_PACKAGE_GUID
)
441 elif self
.ItemObject
.GetPackageVersion() == '':
442 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
443 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_PACKAGE_VERSION
)
448 def _ParseItem(self
):
449 Line
= self
._RawData
.CurrentLine
450 TokenList
= GetSplitValueList(Line
, DT
.TAB_EQUAL_SPLIT
, 1)
451 if TokenList
[0] == DT
.TAB_DEC_DEFINES_PKG_UNI_FILE
:
452 self
.DefineValidation
[TokenList
[0]](TokenList
[1])
453 elif len(TokenList
) < 2:
454 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_FORMAT
)
455 elif TokenList
[0] not in self
.DefineValidation
:
456 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_UNKNOWKEY
% TokenList
[0])
458 self
.DefineValidation
[TokenList
[0]](TokenList
[1])
460 DefineItem
= DecDefineItemObject()
461 DefineItem
.Key
= TokenList
[0]
462 DefineItem
.Value
= TokenList
[1]
463 self
.ItemObject
.AddItem(DefineItem
, self
._RawData
.CurrentScope
)
466 def _SetDecSpecification(self
, Token
):
467 if self
.ItemObject
.GetPackageSpecification():
468 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_DEC_SPECIFICATION
)
469 if not IsValidToken('0[xX][0-9a-fA-F]{8}', Token
):
470 if not IsValidDecVersionVal(Token
):
471 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_SPEC
)
472 self
.ItemObject
.SetPackageSpecification(Token
)
474 def _SetPackageName(self
, Token
):
475 if self
.ItemObject
.GetPackageName():
476 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PACKAGE_NAME
)
477 if not IsValidWord(Token
):
478 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGNAME
)
479 self
.ItemObject
.SetPackageName(Token
)
481 def _SetPackageGuid(self
, Token
):
482 if self
.ItemObject
.GetPackageGuid():
483 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PACKAGE_GUID
)
484 if not CheckGuidRegFormat(Token
):
485 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGGUID
)
486 self
.ItemObject
.SetPackageGuid(Token
)
488 def _SetPackageVersion(self
, Token
):
489 if self
.ItemObject
.GetPackageVersion():
490 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PACKAGE_VERSION
)
491 if not IsValidToken(VERSION_PATTERN
, Token
):
492 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGVERSION
)
494 if not DT
.TAB_SPLIT
in Token
:
496 self
.ItemObject
.SetPackageVersion(Token
)
498 def _SetPackageUni(self
, Token
):
499 if self
.ItemObject
.GetPackageUniFile():
500 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PKG_UNI_FILE
)
501 self
.ItemObject
.SetPackageUniFile(Token
)
505 # Parse include section
507 class _DecInclude(_DecBase
):
508 def __init__(self
, RawData
):
509 _DecBase
.__init
__(self
, RawData
)
510 self
.ItemObject
= DecIncludeObject(RawData
.Filename
)
512 def _ParseItem(self
):
513 Line
= self
._RawData
.CurrentLine
515 if not IsValidPath(Line
, self
._RawData
.PackagePath
):
516 self
._LoggerError
(ST
.ERR_DECPARSE_INCLUDE
% Line
)
518 Item
= DecIncludeItemObject(StripRoot(self
._RawData
.PackagePath
, Line
), self
._RawData
.PackagePath
)
519 self
.ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
524 # Parse library class section
526 class _DecLibraryclass(_DecBase
):
527 def __init__(self
, RawData
):
528 _DecBase
.__init
__(self
, RawData
)
529 self
.ItemObject
= DecLibraryclassObject(RawData
.Filename
)
531 def _ParseItem(self
):
532 Line
= self
._RawData
.CurrentLine
533 TokenList
= GetSplitValueList(Line
, DT
.TAB_VALUE_SPLIT
)
534 if len(TokenList
) != 2:
535 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_SPLIT
)
536 if TokenList
[0] == '' or TokenList
[1] == '':
537 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_EMPTY
)
538 if not IsValidToken('[A-Z][0-9A-Za-z]*', TokenList
[0]):
539 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_LIB
)
541 self
._CheckReDefine
(TokenList
[0])
547 if not Value
.endswith('.h'):
548 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_PATH_EXT
)
551 # Path must be existed
553 if not IsValidPath(Value
, self
._RawData
.PackagePath
):
554 self
._LoggerError
(ST
.ERR_DECPARSE_INCLUDE
% Value
)
556 Item
= DecLibraryclassItemObject(TokenList
[0], StripRoot(self
._RawData
.PackagePath
, Value
),
557 self
._RawData
.PackagePath
)
558 self
.ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
565 class _DecPcd(_DecBase
):
566 def __init__(self
, RawData
):
567 _DecBase
.__init
__(self
, RawData
)
568 self
.ItemObject
= DecPcdObject(RawData
.Filename
)
570 # Used to check duplicate token
571 # Key is token space and token number (integer), value is C name
575 def _ParseItem(self
):
576 Line
= self
._RawData
.CurrentLine
577 TokenList
= Line
.split(DT
.TAB_VALUE_SPLIT
)
578 if len(TokenList
) < 4:
579 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_SPLIT
)
582 # Token space guid C name
584 PcdName
= GetSplitValueList(TokenList
[0], DT
.TAB_SPLIT
)
585 if len(PcdName
) != 2 or PcdName
[0] == '' or PcdName
[1] == '':
586 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_NAME
)
589 if not IsValidToken(CVAR_PATTERN
, Guid
):
590 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_CVAR_GUID
)
596 if not IsValidToken(CVAR_PATTERN
, CName
):
597 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_CVAR_PCDCNAME
)
599 self
._CheckReDefine
(Guid
+ DT
.TAB_SPLIT
+ CName
)
602 # Default value, may be C array, string or number
604 Data
= DT
.TAB_VALUE_SPLIT
.join(TokenList
[1:-2]).strip()
609 DataType
= TokenList
[-2].strip()
610 Valid
, Cause
= IsValidPcdDatum(DataType
, Data
)
612 self
._LoggerError
(Cause
)
613 PcdType
= self
._RawData
.CurrentScope
[0][0]
614 if PcdType
== DT
.TAB_PCDS_FEATURE_FLAG_NULL
.upper() and DataType
!= 'BOOLEAN':
615 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_FEATUREFLAG
)
617 # Token value is the last element in list.
619 Token
= TokenList
[-1].strip()
620 if not IsValidToken(PCD_TOKEN_PATTERN
, Token
):
621 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_TOKEN
% Token
)
622 elif not Token
.startswith('0x') and not Token
.startswith('0X'):
623 if int(Token
) > 4294967295:
624 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_TOKEN_INT
% Token
)
625 Token
= hex(int(Token
))[:-1]
627 IntToken
= int(Token
, 0)
628 if (Guid
, IntToken
) in self
.TokenMap
:
629 if self
.TokenMap
[Guid
, IntToken
] != CName
:
630 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_TOKEN_UNIQUE
%(Token))
632 self
.TokenMap
[Guid
, IntToken
] = CName
634 Item
= DecPcdItemObject(Guid
, CName
, Data
, DataType
, Token
)
635 self
.ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
640 # Parse GUID, PPI, Protocol section
642 class _DecGuid(_DecBase
):
643 def __init__(self
, RawData
):
644 _DecBase
.__init
__(self
, RawData
)
645 self
.GuidObj
= DecGuidObject(RawData
.Filename
)
646 self
.PpiObj
= DecPpiObject(RawData
.Filename
)
647 self
.ProtocolObj
= DecProtocolObject(RawData
.Filename
)
650 DT
.TAB_GUIDS
.upper() : self
.GuidObj
,
651 DT
.TAB_PPIS
.upper() : self
.PpiObj
,
652 DT
.TAB_PROTOCOLS
.upper() : self
.ProtocolObj
655 def GetDataObject(self
):
656 if self
._RawData
.CurrentScope
:
657 return self
.ObjectDict
[self
._RawData
.CurrentScope
[0][0]]
660 def GetGuidObject(self
):
663 def GetPpiObject(self
):
666 def GetProtocolObject(self
):
667 return self
.ProtocolObj
669 def _ParseItem(self
):
670 Line
= self
._RawData
.CurrentLine
671 TokenList
= GetSplitValueList(Line
, DT
.TAB_EQUAL_SPLIT
, 1)
672 if len(TokenList
) < 2:
673 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID
)
674 if TokenList
[0] == '':
675 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_NAME
)
676 if TokenList
[1] == '':
677 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_GUID
)
678 if not IsValidToken(CVAR_PATTERN
, TokenList
[0]):
679 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_CVAR_GUID
)
681 self
._CheckReDefine
(TokenList
[0])
683 if TokenList
[1][0] != '{':
684 if not CheckGuidRegFormat(TokenList
[1]):
685 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGGUID
)
686 GuidString
= TokenList
[1]
689 # Convert C format GUID to GUID string and Simple error check
691 GuidString
= GuidStructureStringToGuidString(TokenList
[1])
692 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidString
== '':
693 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_GUIDFORMAT
)
696 # Check C format GUID
698 if not IsValidCFormatGuid(TokenList
[1]):
699 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_GUIDFORMAT
)
701 Item
= DecGuidItemObject(TokenList
[0], TokenList
[1], GuidString
)
702 ItemObject
= self
.ObjectDict
[self
._RawData
.CurrentScope
[0][0]]
703 ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
708 # Parse user extention section
710 class _DecUserExtension(_DecBase
):
711 def __init__(self
, RawData
):
712 _DecBase
.__init
__(self
, RawData
)
713 self
.ItemObject
= DecUserExtensionObject(RawData
.Filename
)
717 def BlockStart(self
):
719 for Header
in self
._RawData
.CurrentScope
:
720 if Header
in self
._Headers
:
721 self
._LoggerError
(ST
.ERR_DECPARSE_UE_DUPLICATE
)
723 self
._Headers
.append(Header
)
725 for Item
in self
._CurItems
:
726 if Item
.UserId
== Header
[1] and Item
.IdString
== Header
[2]:
727 Item
.ArchAndModuleType
.append(Header
[3])
730 Item
= DecUserExtensionItemObject()
731 Item
.UserId
= Header
[1]
732 Item
.IdString
= Header
[2]
733 Item
.ArchAndModuleType
.append(Header
[3])
734 self
._CurItems
.append(Item
)
735 self
.ItemObject
.AddItem(Item
, None)
736 self
._LocalMacro
= {}
738 def _ParseItem(self
):
739 Line
= self
._RawData
.CurrentLine
741 for Item
in self
._CurItems
:
743 Item
.UserString
= '\n'.join([Item
.UserString
, Line
])
745 Item
.UserString
= Line
752 class Dec(_DecBase
, _DecComments
):
753 def __init__(self
, DecFile
, Parse
= True):
755 Content
= ConvertSpecialChar(open(DecFile
, 'rb').readlines())
756 except BaseException
:
757 Logger
.Error(TOOL_NAME
, FILE_OPEN_FAILURE
, File
=DecFile
,
758 ExtraData
=ST
.ERR_DECPARSE_FILEOPEN
% DecFile
)
761 # Pre-parser for Private section
764 __IsFoundPrivate
= False
768 if Line
.startswith(DT
.TAB_SECTION_START
) and Line
.endswith(DT
.TAB_PRIVATE
+ DT
.TAB_SECTION_END
):
769 __IsFoundPrivate
= True
770 if Line
.startswith(DT
.TAB_SECTION_START
) and Line
.endswith(DT
.TAB_SECTION_END
)\
771 and not Line
.endswith(DT
.TAB_PRIVATE
+ DT
.TAB_SECTION_END
):
772 __IsFoundPrivate
= False
774 self
._Private
+= Line
+ '\r'
775 if not __IsFoundPrivate
:
776 NewContent
.append(Line
+ '\r')
778 RawData
= FileContent(DecFile
, NewContent
)
780 _DecComments
.__init
__(self
)
781 _DecBase
.__init
__(self
, RawData
)
783 self
.BinaryHeadComment
= []
784 self
.PcdErrorCommentDict
= {}
786 self
._Define
= _DecDefine(RawData
)
787 self
._Include
= _DecInclude(RawData
)
788 self
._Guid
= _DecGuid(RawData
)
789 self
._LibClass
= _DecLibraryclass(RawData
)
790 self
._Pcd
= _DecPcd(RawData
)
791 self
._UserEx
= _DecUserExtension(RawData
)
794 # DEC file supported data types (one type per section)
796 self
._SectionParser
= {
797 DT
.TAB_DEC_DEFINES
.upper() : self
._Define
,
798 DT
.TAB_INCLUDES
.upper() : self
._Include
,
799 DT
.TAB_LIBRARY_CLASSES
.upper() : self
._LibClass
,
800 DT
.TAB_GUIDS
.upper() : self
._Guid
,
801 DT
.TAB_PPIS
.upper() : self
._Guid
,
802 DT
.TAB_PROTOCOLS
.upper() : self
._Guid
,
803 DT
.TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : self
._Pcd
,
804 DT
.TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : self
._Pcd
,
805 DT
.TAB_PCDS_FEATURE_FLAG_NULL
.upper() : self
._Pcd
,
806 DT
.TAB_PCDS_DYNAMIC_NULL
.upper() : self
._Pcd
,
807 DT
.TAB_PCDS_DYNAMIC_EX_NULL
.upper() : self
._Pcd
,
808 DT
.TAB_USER_EXTENSIONS
.upper() : self
._UserEx
812 self
.ParseDecComment()
815 # Parsing done, check required fields
817 self
.CheckRequiredFields()
819 def CheckRequiredFields(self
):
820 for SectionParser
in self
._SectionParser
.values():
821 if not SectionParser
.CheckRequiredFields():
828 def ParseDecComment(self
):
830 IsBinaryHeader
= False
831 FileHeaderLineIndex
= -1
832 BinaryHeaderLineIndex
= -1
833 TokenSpaceGuidCName
= ''
836 # Parse PCD error comment section
838 while not self
._RawData
.IsEndOfFile():
839 self
._RawData
.CurrentLine
= self
._RawData
.GetNextLine()
840 if self
._RawData
.CurrentLine
.startswith(DT
.TAB_COMMENT_SPLIT
) and \
841 DT
.TAB_SECTION_START
in self
._RawData
.CurrentLine
and \
842 DT
.TAB_SECTION_END
in self
._RawData
.CurrentLine
:
843 self
._RawData
.CurrentLine
= self
._RawData
.CurrentLine
.replace(DT
.TAB_COMMENT_SPLIT
, '').strip()
845 if self
._RawData
.CurrentLine
[0] == DT
.TAB_SECTION_START
and \
846 self
._RawData
.CurrentLine
[-1] == DT
.TAB_SECTION_END
:
847 RawSection
= self
._RawData
.CurrentLine
[1:-1].strip()
848 if RawSection
.upper().startswith(DT
.TAB_PCD_ERROR
.upper()+'.'):
849 TokenSpaceGuidCName
= RawSection
.split(DT
.TAB_PCD_ERROR
+'.')[1].strip()
852 if TokenSpaceGuidCName
and self
._RawData
.CurrentLine
.startswith(DT
.TAB_COMMENT_SPLIT
):
853 self
._RawData
.CurrentLine
= self
._RawData
.CurrentLine
.replace(DT
.TAB_COMMENT_SPLIT
, '').strip()
854 if self
._RawData
.CurrentLine
!= '':
855 if DT
.TAB_VALUE_SPLIT
not in self
._RawData
.CurrentLine
:
856 self
._LoggerError
(ST
.ERR_DECPARSE_PCDERRORMSG_MISS_VALUE_SPLIT
)
858 PcdErrorNumber
, PcdErrorMsg
= GetSplitValueList(self
._RawData
.CurrentLine
, DT
.TAB_VALUE_SPLIT
, 1)
859 PcdErrorNumber
= ParsePcdErrorCode(PcdErrorNumber
, self
._RawData
.Filename
, self
._RawData
.LineIndex
)
860 if not PcdErrorMsg
.strip():
861 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_MISS_ERRORMSG
)
863 self
.PcdErrorCommentDict
[(TokenSpaceGuidCName
, PcdErrorNumber
)] = PcdErrorMsg
.strip()
865 TokenSpaceGuidCName
= ''
867 self
._RawData
.LineIndex
= 0
868 self
._RawData
.CurrentLine
= ''
869 self
._RawData
.NextLine
= ''
871 while not self
._RawData
.IsEndOfFile():
872 Line
, Comment
= CleanString(self
._RawData
.GetNextLine())
875 # Header must be pure comment
878 self
._RawData
.UndoNextLine()
881 if Comment
and Comment
.startswith(DT
.TAB_SPECIAL_COMMENT
) and Comment
.find(DT
.TAB_HEADER_COMMENT
) > 0 \
882 and not Comment
[2:Comment
.find(DT
.TAB_HEADER_COMMENT
)].strip():
884 IsBinaryHeader
= False
885 FileHeaderLineIndex
= self
._RawData
.LineIndex
888 # Get license information before '@file'
890 if not IsFileHeader
and not IsBinaryHeader
and Comment
and Comment
.startswith(DT
.TAB_COMMENT_SPLIT
) and \
891 DT
.TAB_BINARY_HEADER_COMMENT
not in Comment
:
892 self
._HeadComment
.append((Comment
, self
._RawData
.LineIndex
))
894 if Comment
and IsFileHeader
and \
895 not(Comment
.startswith(DT
.TAB_SPECIAL_COMMENT
) \
896 and Comment
.find(DT
.TAB_BINARY_HEADER_COMMENT
) > 0):
897 self
._HeadComment
.append((Comment
, self
._RawData
.LineIndex
))
899 # Double '#' indicates end of header comments
901 if (not Comment
or Comment
== DT
.TAB_SPECIAL_COMMENT
) and IsFileHeader
:
905 if Comment
and Comment
.startswith(DT
.TAB_SPECIAL_COMMENT
) \
906 and Comment
.find(DT
.TAB_BINARY_HEADER_COMMENT
) > 0:
907 IsBinaryHeader
= True
909 BinaryHeaderLineIndex
= self
._RawData
.LineIndex
911 if Comment
and IsBinaryHeader
:
912 self
.BinaryHeadComment
.append((Comment
, self
._RawData
.LineIndex
))
914 # Double '#' indicates end of header comments
916 if (not Comment
or Comment
== DT
.TAB_SPECIAL_COMMENT
) and IsBinaryHeader
:
917 IsBinaryHeader
= False
920 if FileHeaderLineIndex
> -1 and not IsFileHeader
and not IsBinaryHeader
:
923 if FileHeaderLineIndex
> BinaryHeaderLineIndex
and FileHeaderLineIndex
> -1 and BinaryHeaderLineIndex
> -1:
924 self
._LoggerError
(ST
.ERR_BINARY_HEADER_ORDER
)
926 if FileHeaderLineIndex
== -1:
927 # self._LoggerError(ST.ERR_NO_SOURCE_HEADER)
928 Logger
.Error(TOOL_NAME
, FORMAT_INVALID
,
929 ST
.ERR_NO_SOURCE_HEADER
,
930 File
=self
._RawData
.Filename
)
933 def _StopCurrentParsing(self
, Line
):
936 def _ParseItem(self
):
937 self
._SectionHeaderParser
()
938 if len(self
._RawData
.CurrentScope
) == 0:
939 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_EMPTY
)
940 SectionObj
= self
._SectionParser
[self
._RawData
.CurrentScope
[0][0]]
941 SectionObj
.BlockStart()
943 return SectionObj
.GetDataObject()
945 def _UserExtentionSectionParser(self
):
946 self
._RawData
.CurrentScope
= []
948 Section
= self
._RawData
.CurrentLine
[1:-1]
949 Par
= ParserHelper(Section
, self
._RawData
.Filename
)
954 Token
= Par
.GetToken()
955 if Token
.upper() != DT
.TAB_USER_EXTENSIONS
.upper():
956 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE
)
957 UserExtension
= Token
.upper()
958 Par
.AssertChar(DT
.TAB_SPLIT
, ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
963 Token
= Par
.GetToken()
964 if not IsValidUserId(Token
):
965 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE_USERID
)
967 Par
.AssertChar(DT
.TAB_SPLIT
, ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
971 Token
= Par
.GetToken()
972 if not IsValidIdString(Token
):
973 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE_IDSTRING
)
976 if Par
.Expect(DT
.TAB_SPLIT
):
977 Token
= Par
.GetToken()
979 if not IsValidArch(Arch
):
980 self
._LoggerError
(ST
.ERR_DECPARSE_ARCH
)
982 if [UserExtension
, UserId
, IdString
, Arch
] not in \
983 self
._RawData
.CurrentScope
:
984 self
._RawData
.CurrentScope
.append(
985 [UserExtension
, UserId
, IdString
, Arch
]
987 if not Par
.Expect(DT
.TAB_COMMA_SPLIT
):
990 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMA
)
991 Par
.AssertEnd(ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
992 if 'COMMON' in ArchList
and len(ArchList
) > 1:
993 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMON
)
995 ## Section header parser
997 # The section header is always in following format:
999 # [section_name.arch<.platform|module_type>]
1001 def _SectionHeaderParser(self
):
1002 if self
._RawData
.CurrentLine
[0] != DT
.TAB_SECTION_START
or self
._RawData
.CurrentLine
[-1] != DT
.TAB_SECTION_END
:
1003 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_IDENTIFY
)
1005 RawSection
= self
._RawData
.CurrentLine
[1:-1].strip().upper()
1007 # Check defines section which is only allowed to occur once and
1008 # no arch can be followed
1010 if RawSection
.startswith(DT
.TAB_DEC_DEFINES
.upper()):
1011 if RawSection
!= DT
.TAB_DEC_DEFINES
.upper():
1012 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_SECNAME
)
1014 # Check user extension section
1016 if RawSection
.startswith(DT
.TAB_USER_EXTENSIONS
.upper()):
1017 return self
._UserExtentionSectionParser
()
1018 self
._RawData
.CurrentScope
= []
1021 for Item
in GetSplitValueList(RawSection
, DT
.TAB_COMMA_SPLIT
):
1023 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBEMPTY
% self
._RawData
.CurrentLine
)
1025 ItemList
= GetSplitValueList(Item
, DT
.TAB_SPLIT
)
1027 # different types of PCD are permissible in one section
1029 SectionName
= ItemList
[0]
1030 if SectionName
not in self
._SectionParser
:
1031 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UNKNOW
% SectionName
)
1032 if SectionName
not in SectionNames
:
1033 SectionNames
.append(SectionName
)
1035 # In DEC specification, all section headers have at most two part:
1036 # SectionName.Arch except UserExtention
1038 if len(ItemList
) > 2:
1039 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBTOOMANY
% Item
)
1041 if DT
.TAB_PCDS_FEATURE_FLAG_NULL
.upper() in SectionNames
and len(SectionNames
) > 1:
1042 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_FEATUREFLAG
% DT
.TAB_PCDS_FEATURE_FLAG_NULL
)
1046 if len(ItemList
) > 1:
1048 if not IsValidArch(Str1
):
1049 self
._LoggerError
(ST
.ERR_DECPARSE_ARCH
)
1054 if [SectionName
, Str1
] not in self
._RawData
.CurrentScope
:
1055 self
._RawData
.CurrentScope
.append([SectionName
, Str1
])
1057 # 'COMMON' must not be used with specific ARCHs at the same section
1059 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1060 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMON
)
1061 if len(SectionNames
) == 0:
1062 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBEMPTY
% self
._RawData
.CurrentLine
)
1063 if len(SectionNames
) != 1:
1064 for Sec
in SectionNames
:
1065 if not Sec
.startswith(DT
.TAB_PCDS
.upper()):
1066 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_NAME
% str(SectionNames
))
1068 def GetDefineSectionMacro(self
):
1069 return self
._Define
.GetLocalMacro()
1070 def GetDefineSectionObject(self
):
1071 return self
._Define
.GetDataObject()
1072 def GetIncludeSectionObject(self
):
1073 return self
._Include
.GetDataObject()
1074 def GetGuidSectionObject(self
):
1075 return self
._Guid
.GetGuidObject()
1076 def GetProtocolSectionObject(self
):
1077 return self
._Guid
.GetProtocolObject()
1078 def GetPpiSectionObject(self
):
1079 return self
._Guid
.GetPpiObject()
1080 def GetLibraryClassSectionObject(self
):
1081 return self
._LibClass
.GetDataObject()
1082 def GetPcdSectionObject(self
):
1083 return self
._Pcd
.GetDataObject()
1084 def GetUserExtensionSectionObject(self
):
1085 return self
._UserEx
.GetDataObject()
1086 def GetPackageSpecification(self
):
1087 return self
._Define
.GetDataObject().GetPackageSpecification()
1088 def GetPackageName(self
):
1089 return self
._Define
.GetDataObject().GetPackageName()
1090 def GetPackageGuid(self
):
1091 return self
._Define
.GetDataObject().GetPackageGuid()
1092 def GetPackageVersion(self
):
1093 return self
._Define
.GetDataObject().GetPackageVersion()
1094 def GetPackageUniFile(self
):
1095 return self
._Define
.GetDataObject().GetPackageUniFile()
1096 def GetPrivateSections(self
):
1097 return self
._Private