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 # SPDX-License-Identifier: BSD-2-Clause-Patent
12 import Logger
.Log
as Logger
13 from Logger
.ToolError
import FILE_PARSE_FAILURE
14 from Logger
.ToolError
import FILE_OPEN_FAILURE
15 from Logger
import StringTable
as ST
16 from Logger
.ToolError
import FORMAT_INVALID
18 import Library
.DataType
as DT
19 from Library
.ParserValidate
import IsValidToken
20 from Library
.ParserValidate
import IsValidPath
21 from Library
.ParserValidate
import IsValidCFormatGuid
22 from Library
.ParserValidate
import IsValidIdString
23 from Library
.ParserValidate
import IsValidUserId
24 from Library
.ParserValidate
import IsValidArch
25 from Library
.ParserValidate
import IsValidWord
26 from Library
.ParserValidate
import IsValidDecVersionVal
27 from Parser
.DecParserMisc
import TOOL_NAME
28 from Parser
.DecParserMisc
import CleanString
29 from Parser
.DecParserMisc
import IsValidPcdDatum
30 from Parser
.DecParserMisc
import ParserHelper
31 from Parser
.DecParserMisc
import StripRoot
32 from Parser
.DecParserMisc
import VERSION_PATTERN
33 from Parser
.DecParserMisc
import CVAR_PATTERN
34 from Parser
.DecParserMisc
import PCD_TOKEN_PATTERN
35 from Parser
.DecParserMisc
import MACRO_PATTERN
36 from Parser
.DecParserMisc
import FileContent
37 from Object
.Parser
.DecObject
import _DecComments
38 from Object
.Parser
.DecObject
import DecDefineObject
39 from Object
.Parser
.DecObject
import DecDefineItemObject
40 from Object
.Parser
.DecObject
import DecIncludeObject
41 from Object
.Parser
.DecObject
import DecIncludeItemObject
42 from Object
.Parser
.DecObject
import DecLibraryclassObject
43 from Object
.Parser
.DecObject
import DecLibraryclassItemObject
44 from Object
.Parser
.DecObject
import DecGuidObject
45 from Object
.Parser
.DecObject
import DecPpiObject
46 from Object
.Parser
.DecObject
import DecProtocolObject
47 from Object
.Parser
.DecObject
import DecGuidItemObject
48 from Object
.Parser
.DecObject
import DecUserExtensionObject
49 from Object
.Parser
.DecObject
import DecUserExtensionItemObject
50 from Object
.Parser
.DecObject
import DecPcdObject
51 from Object
.Parser
.DecObject
import DecPcdItemObject
52 from Library
.Misc
import GuidStructureStringToGuidString
53 from Library
.Misc
import CheckGuidRegFormat
54 from Library
.StringUtils
import ReplaceMacro
55 from Library
.StringUtils
import GetSplitValueList
56 from Library
.StringUtils
import gMACRO_PATTERN
57 from Library
.StringUtils
import ConvertSpecialChar
58 from Library
.CommentParsing
import ParsePcdErrorCode
61 # _DecBase class for parsing
64 def __init__(self
, RawData
):
65 self
._RawData
= RawData
69 # Data parsed by 'self' are saved to this object
71 self
.ItemObject
= None
73 def GetDataObject(self
):
74 return self
.ItemObject
76 def GetLocalMacro(self
):
77 return self
._LocalMacro
81 # Called if a new section starts
88 # @param Key: to be checked if multi-defined
89 # @param Scope: Format: [[SectionName, Arch], ...].
90 # If scope is none, use global scope
92 def _CheckReDefine(self
, Key
, Scope
= None):
94 Scope
= self
._RawData
.CurrentScope
99 # Copy scope to SecArch, avoid Scope be changed outside
101 SecArch
[0:1] = Scope
[:]
102 if Key
not in self
._ItemDict
:
103 self
._ItemDict
[Key
] = [[SecArch
, self
._RawData
.LineIndex
]]
106 for Value
in self
._ItemDict
[Key
]:
107 for SubValue
in Scope
:
109 # If current is common section
111 if SubValue
[-1] == 'COMMON':
112 for Other
in Value
[0]:
113 # Key in common cannot be redefined in other arches
114 # [:-1] means stripping arch info
115 if Other
[:-1] == SubValue
[:-1]:
116 self
._LoggerError
(ST
.ERR_DECPARSE_REDEFINE
% (Key
, Value
[1]))
120 CommonScope
[0:1] = SubValue
121 CommonScope
[-1] = 'COMMON'
123 # Cannot be redefined if this key already defined in COMMON Or defined in same arch
125 if SubValue
in Value
[0] or CommonScope
in Value
[0]:
126 self
._LoggerError
(ST
.ERR_DECPARSE_REDEFINE
% (Key
, Value
[1]))
128 self
._ItemDict
[Key
].append([SecArch
, self
._RawData
.LineIndex
])
130 ## CheckRequiredFields
131 # Some sections need to check if some fields exist, define section for example
132 # Derived class can re-implement, top parser will call this function after all parsing done
134 def CheckRequiredFields(self
):
140 # In DEC spec, sections must have at least one statement except user
142 # For example: "[guids" [<attribs>] "]" <EOL> <statements>+
143 # sub class can override this method to indicate if statement is a must.
145 def _IsStatementRequired(self
):
150 def _LoggerError(self
, ErrorString
):
151 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
152 Line
= self
._RawData
.LineIndex
,
153 ExtraData
=ErrorString
+ ST
.ERR_DECPARSE_LINE
% self
._RawData
.CurrentLine
)
155 def _ReplaceMacro(self
, String
):
156 if gMACRO_PATTERN
.findall(String
):
157 String
= ReplaceMacro(String
, self
._LocalMacro
, False,
158 FileName
= self
._RawData
.Filename
,
159 Line
= ['', self
._RawData
.LineIndex
])
160 String
= ReplaceMacro(String
, self
._RawData
.Macros
, False,
161 FileName
= self
._RawData
.Filename
,
162 Line
= ['', self
._RawData
.LineIndex
])
163 MacroUsed
= gMACRO_PATTERN
.findall(String
)
165 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
,
166 File
=self
._RawData
.Filename
,
167 Line
= self
._RawData
.LineIndex
,
168 ExtraData
= ST
.ERR_DECPARSE_MACRO_RESOLVE
% (str(MacroUsed
), String
))
171 def _MacroParser(self
, String
):
172 TokenList
= GetSplitValueList(String
, ' ', 1)
173 if len(TokenList
) < 2 or TokenList
[1] == '':
174 self
._LoggerError
(ST
.ERR_DECPARSE_MACRO_PAIR
)
176 TokenList
= GetSplitValueList(TokenList
[1], DT
.TAB_EQUAL_SPLIT
, 1)
177 if TokenList
[0] == '':
178 self
._LoggerError
(ST
.ERR_DECPARSE_MACRO_NAME
)
179 elif not IsValidToken(MACRO_PATTERN
, TokenList
[0]):
180 self
._LoggerError
(ST
.ERR_DECPARSE_MACRO_NAME_UPPER
% TokenList
[0])
182 if len(TokenList
) == 1:
183 self
._LocalMacro
[TokenList
[0]] = ''
185 self
._LocalMacro
[TokenList
[0]] = self
._ReplaceMacro
(TokenList
[1])
189 # Parse specified item, this function must be derived by subclass
191 def _ParseItem(self
):
195 # Should never be called
200 ## _TailCommentStrategy
202 # This function can be derived to parse tail comment
203 # default is it will not consume any lines
205 # @param Comment: Comment of current line
207 def _TailCommentStrategy(self
, Comment
):
214 ## _StopCurrentParsing
216 # Called in Parse if current parsing should be stopped when encounter some
218 # Default is section start and end
220 # @param Line: Current line
222 def _StopCurrentParsing(self
, Line
):
225 return Line
[0] == DT
.TAB_SECTION_START
and Line
[-1] == DT
.TAB_SECTION_END
229 # Split comment and DEC content, concatenate lines if end of char is '\'
231 # @param ProcessedLine: ProcessedLine line
232 # @param ProcessedComments: ProcessedComments line
234 def _TryBackSlash(self
, ProcessedLine
, ProcessedComments
):
238 CommentList
= ProcessedComments
239 while not self
._RawData
.IsEndOfFile():
241 self
._LoggerError
(ST
.ERR_DECPARSE_BACKSLASH_EMPTY
)
245 CommentList
.append((Comment
, self
._RawData
.LineIndex
))
246 if Line
[-1] != DT
.TAB_SLASH
:
249 elif len(Line
) < 2 or Line
[-2] != ' ':
250 self
._LoggerError
(ST
.ERR_DECPARSE_BACKSLASH
)
253 Line
, Comment
= CleanString(self
._RawData
.GetNextLine())
255 # Reach end of content
257 if self
._RawData
.IsEndOfFile():
259 if ProcessedLine
[-1] == DT
.TAB_SLASH
:
260 self
._LoggerError
(ST
.ERR_DECPARSE_BACKSLASH_EMPTY
)
261 CatLine
= ProcessedLine
263 if not Line
or Line
[-1] == DT
.TAB_SLASH
:
264 self
._LoggerError
(ST
.ERR_DECPARSE_BACKSLASH_EMPTY
)
268 # All MACRO values defined by the DEFINE statements in any section
269 # (except [Userextensions] sections for Intel) of the INF or DEC file
270 # must be expanded before processing of the file.
272 __IsReplaceMacro
= True
273 Header
= self
._RawData
.CurrentScope
[0] if self
._RawData
.CurrentScope
else None
274 if Header
and len(Header
) > 2:
275 if Header
[0].upper() == 'USEREXTENSIONS' and not (Header
[1] == 'TianoCore' and Header
[2] == '"ExtraFiles"'):
276 __IsReplaceMacro
= False
278 self
._RawData
.CurrentLine
= self
._ReplaceMacro
(CatLine
)
280 self
._RawData
.CurrentLine
= CatLine
282 return CatLine
, CommentList
285 # This is a template method in which other member functions which might
286 # override by sub class are called. It is responsible for reading file
287 # line by line, and call other member functions to parse. This function
288 # should not be re-implement by sub class.
294 #======================================================================
295 # CurComments may pointer to HeadComments or TailComments
296 #======================================================================
297 CurComments
= HeadComments
302 #======================================================================
303 # Used to report error information if empty section found
304 #======================================================================
305 Index
= self
._RawData
.LineIndex
306 LineStr
= self
._RawData
.CurrentLine
307 while not self
._RawData
.IsEndOfFile() or self
._RawData
.NextLine
:
308 if self
._RawData
.NextLine
:
309 #==============================================================
310 # Have processed line in buffer
311 #==============================================================
312 Line
= self
._RawData
.NextLine
313 HeadComments
.extend(self
._RawData
.HeadComment
)
314 TailComments
.extend(self
._RawData
.TailComment
)
315 self
._RawData
.ResetNext()
319 #==============================================================
320 # No line in buffer, read next line
321 #==============================================================
322 Line
, Comment
= CleanString(self
._RawData
.GetNextLine())
325 if not FromBuf
and CurObj
and TailComments
:
326 #==========================================================
327 # Set tail comments to previous statement if not empty.
328 #==========================================================
329 CurObj
.SetTailComment(CurObj
.GetTailComment()+TailComments
)
333 CurComments
= TailComments
336 Comments
= [(Comment
, self
._RawData
.LineIndex
)]
338 #==============================================================
339 # Try if last char of line has backslash
340 #==============================================================
341 Line
, Comments
= self
._TryBackSlash
(Line
, Comments
)
342 CurComments
.extend(Comments
)
344 #==============================================================
346 #==============================================================
347 if Line
.startswith('DEFINE '):
348 self
._MacroParser
(Line
)
351 CurComments
= HeadComments
354 if self
._StopCurrentParsing
(Line
):
355 #==========================================================
356 # This line does not belong to this parse,
357 # Save it, can be used by next parse
358 #==========================================================
359 self
._RawData
.SetNext(Line
, HeadComments
, TailComments
)
362 Obj
= self
._ParseItem
()
365 Obj
.SetHeadComment(Obj
.GetHeadComment()+HeadComments
)
366 Obj
.SetTailComment(Obj
.GetTailComment()+TailComments
)
373 if id(CurComments
) == id(TailComments
):
374 #==========================================================
375 # Check if this comment belongs to tail comment
376 #==========================================================
377 if not self
._TailCommentStrategy
(Comment
):
378 CurComments
= HeadComments
381 CurComments
.append(((Comment
, self
._RawData
.LineIndex
)))
385 if self
._IsStatementRequired
() and ItemNum
== 0:
387 TOOL_NAME
, FILE_PARSE_FAILURE
,
388 File
=self
._RawData
.Filename
,
390 ExtraData
=ST
.ERR_DECPARSE_STATEMENT_EMPTY
% LineStr
394 # Parse define section
396 class _DecDefine(_DecBase
):
397 def __init__(self
, RawData
):
398 _DecBase
.__init
__(self
, RawData
)
399 self
.ItemObject
= DecDefineObject(RawData
.Filename
)
400 self
._LocalMacro
= self
._RawData
.Macros
404 # Each field has a function to validate
406 self
.DefineValidation
= {
407 DT
.TAB_DEC_DEFINES_DEC_SPECIFICATION
: self
._SetDecSpecification
,
408 DT
.TAB_DEC_DEFINES_PACKAGE_NAME
: self
._SetPackageName
,
409 DT
.TAB_DEC_DEFINES_PACKAGE_GUID
: self
._SetPackageGuid
,
410 DT
.TAB_DEC_DEFINES_PACKAGE_VERSION
: self
._SetPackageVersion
,
411 DT
.TAB_DEC_DEFINES_PKG_UNI_FILE
: self
._SetPackageUni
,
414 def BlockStart(self
):
416 if self
._DefSecNum
> 1:
417 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_MULTISEC
)
419 ## CheckRequiredFields
421 # Check required fields: DEC_SPECIFICATION, PACKAGE_NAME
422 # PACKAGE_GUID, PACKAGE_VERSION
424 def CheckRequiredFields(self
):
426 if self
.ItemObject
.GetPackageSpecification() == '':
427 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
428 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_DEC_SPECIFICATION
)
429 elif self
.ItemObject
.GetPackageName() == '':
430 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
431 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_PACKAGE_NAME
)
432 elif self
.ItemObject
.GetPackageGuid() == '':
433 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
434 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_PACKAGE_GUID
)
435 elif self
.ItemObject
.GetPackageVersion() == '':
436 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
437 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_PACKAGE_VERSION
)
442 def _ParseItem(self
):
443 Line
= self
._RawData
.CurrentLine
444 TokenList
= GetSplitValueList(Line
, DT
.TAB_EQUAL_SPLIT
, 1)
445 if TokenList
[0] == DT
.TAB_DEC_DEFINES_PKG_UNI_FILE
:
446 self
.DefineValidation
[TokenList
[0]](TokenList
[1])
447 elif len(TokenList
) < 2:
448 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_FORMAT
)
449 elif TokenList
[0] not in self
.DefineValidation
:
450 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_UNKNOWKEY
% TokenList
[0])
452 self
.DefineValidation
[TokenList
[0]](TokenList
[1])
454 DefineItem
= DecDefineItemObject()
455 DefineItem
.Key
= TokenList
[0]
456 DefineItem
.Value
= TokenList
[1]
457 self
.ItemObject
.AddItem(DefineItem
, self
._RawData
.CurrentScope
)
460 def _SetDecSpecification(self
, Token
):
461 if self
.ItemObject
.GetPackageSpecification():
462 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_DEC_SPECIFICATION
)
463 if not IsValidToken('0[xX][0-9a-fA-F]{8}', Token
):
464 if not IsValidDecVersionVal(Token
):
465 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_SPEC
)
466 self
.ItemObject
.SetPackageSpecification(Token
)
468 def _SetPackageName(self
, Token
):
469 if self
.ItemObject
.GetPackageName():
470 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PACKAGE_NAME
)
471 if not IsValidWord(Token
):
472 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGNAME
)
473 self
.ItemObject
.SetPackageName(Token
)
475 def _SetPackageGuid(self
, Token
):
476 if self
.ItemObject
.GetPackageGuid():
477 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PACKAGE_GUID
)
478 if not CheckGuidRegFormat(Token
):
479 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGGUID
)
480 self
.ItemObject
.SetPackageGuid(Token
)
482 def _SetPackageVersion(self
, Token
):
483 if self
.ItemObject
.GetPackageVersion():
484 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PACKAGE_VERSION
)
485 if not IsValidToken(VERSION_PATTERN
, Token
):
486 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGVERSION
)
488 if not DT
.TAB_SPLIT
in Token
:
490 self
.ItemObject
.SetPackageVersion(Token
)
492 def _SetPackageUni(self
, Token
):
493 if self
.ItemObject
.GetPackageUniFile():
494 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PKG_UNI_FILE
)
495 self
.ItemObject
.SetPackageUniFile(Token
)
499 # Parse include section
501 class _DecInclude(_DecBase
):
502 def __init__(self
, RawData
):
503 _DecBase
.__init
__(self
, RawData
)
504 self
.ItemObject
= DecIncludeObject(RawData
.Filename
)
506 def _ParseItem(self
):
507 Line
= self
._RawData
.CurrentLine
509 if not IsValidPath(Line
, self
._RawData
.PackagePath
):
510 self
._LoggerError
(ST
.ERR_DECPARSE_INCLUDE
% Line
)
512 Item
= DecIncludeItemObject(StripRoot(self
._RawData
.PackagePath
, Line
), self
._RawData
.PackagePath
)
513 self
.ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
518 # Parse library class section
520 class _DecLibraryclass(_DecBase
):
521 def __init__(self
, RawData
):
522 _DecBase
.__init
__(self
, RawData
)
523 self
.ItemObject
= DecLibraryclassObject(RawData
.Filename
)
525 def _ParseItem(self
):
526 Line
= self
._RawData
.CurrentLine
527 TokenList
= GetSplitValueList(Line
, DT
.TAB_VALUE_SPLIT
)
528 if len(TokenList
) != 2:
529 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_SPLIT
)
530 if TokenList
[0] == '' or TokenList
[1] == '':
531 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_EMPTY
)
532 if not IsValidToken('[A-Z][0-9A-Za-z]*', TokenList
[0]):
533 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_LIB
)
535 self
._CheckReDefine
(TokenList
[0])
541 if not Value
.endswith('.h'):
542 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_PATH_EXT
)
545 # Path must be existed
547 if not IsValidPath(Value
, self
._RawData
.PackagePath
):
548 self
._LoggerError
(ST
.ERR_DECPARSE_INCLUDE
% Value
)
550 Item
= DecLibraryclassItemObject(TokenList
[0], StripRoot(self
._RawData
.PackagePath
, Value
),
551 self
._RawData
.PackagePath
)
552 self
.ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
559 class _DecPcd(_DecBase
):
560 def __init__(self
, RawData
):
561 _DecBase
.__init
__(self
, RawData
)
562 self
.ItemObject
= DecPcdObject(RawData
.Filename
)
564 # Used to check duplicate token
565 # Key is token space and token number (integer), value is C name
569 def _ParseItem(self
):
570 Line
= self
._RawData
.CurrentLine
571 TokenList
= Line
.split(DT
.TAB_VALUE_SPLIT
)
572 if len(TokenList
) < 4:
573 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_SPLIT
)
576 # Token space guid C name
578 PcdName
= GetSplitValueList(TokenList
[0], DT
.TAB_SPLIT
)
579 if len(PcdName
) != 2 or PcdName
[0] == '' or PcdName
[1] == '':
580 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_NAME
)
583 if not IsValidToken(CVAR_PATTERN
, Guid
):
584 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_CVAR_GUID
)
590 if not IsValidToken(CVAR_PATTERN
, CName
):
591 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_CVAR_PCDCNAME
)
593 self
._CheckReDefine
(Guid
+ DT
.TAB_SPLIT
+ CName
)
596 # Default value, may be C array, string or number
598 Data
= DT
.TAB_VALUE_SPLIT
.join(TokenList
[1:-2]).strip()
603 DataType
= TokenList
[-2].strip()
604 Valid
, Cause
= IsValidPcdDatum(DataType
, Data
)
606 self
._LoggerError
(Cause
)
607 PcdType
= self
._RawData
.CurrentScope
[0][0]
608 if PcdType
== DT
.TAB_PCDS_FEATURE_FLAG_NULL
.upper() and DataType
!= 'BOOLEAN':
609 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_FEATUREFLAG
)
611 # Token value is the last element in list.
613 Token
= TokenList
[-1].strip()
614 if not IsValidToken(PCD_TOKEN_PATTERN
, Token
):
615 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_TOKEN
% Token
)
616 elif not Token
.startswith('0x') and not Token
.startswith('0X'):
617 if int(Token
) > 4294967295:
618 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_TOKEN_INT
% Token
)
619 Token
= '0x%x' % int(Token
)
621 IntToken
= int(Token
, 0)
622 if (Guid
, IntToken
) in self
.TokenMap
:
623 if self
.TokenMap
[Guid
, IntToken
] != CName
:
624 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_TOKEN_UNIQUE
%(Token))
626 self
.TokenMap
[Guid
, IntToken
] = CName
628 Item
= DecPcdItemObject(Guid
, CName
, Data
, DataType
, Token
)
629 self
.ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
634 # Parse GUID, PPI, Protocol section
636 class _DecGuid(_DecBase
):
637 def __init__(self
, RawData
):
638 _DecBase
.__init
__(self
, RawData
)
639 self
.GuidObj
= DecGuidObject(RawData
.Filename
)
640 self
.PpiObj
= DecPpiObject(RawData
.Filename
)
641 self
.ProtocolObj
= DecProtocolObject(RawData
.Filename
)
644 DT
.TAB_GUIDS
.upper() : self
.GuidObj
,
645 DT
.TAB_PPIS
.upper() : self
.PpiObj
,
646 DT
.TAB_PROTOCOLS
.upper() : self
.ProtocolObj
649 def GetDataObject(self
):
650 if self
._RawData
.CurrentScope
:
651 return self
.ObjectDict
[self
._RawData
.CurrentScope
[0][0]]
654 def GetGuidObject(self
):
657 def GetPpiObject(self
):
660 def GetProtocolObject(self
):
661 return self
.ProtocolObj
663 def _ParseItem(self
):
664 Line
= self
._RawData
.CurrentLine
665 TokenList
= GetSplitValueList(Line
, DT
.TAB_EQUAL_SPLIT
, 1)
666 if len(TokenList
) < 2:
667 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID
)
668 if TokenList
[0] == '':
669 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_NAME
)
670 if TokenList
[1] == '':
671 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_GUID
)
672 if not IsValidToken(CVAR_PATTERN
, TokenList
[0]):
673 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_CVAR_GUID
)
675 self
._CheckReDefine
(TokenList
[0])
677 if TokenList
[1][0] != '{':
678 if not CheckGuidRegFormat(TokenList
[1]):
679 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGGUID
)
680 GuidString
= TokenList
[1]
683 # Convert C format GUID to GUID string and Simple error check
685 GuidString
= GuidStructureStringToGuidString(TokenList
[1])
686 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidString
== '':
687 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_GUIDFORMAT
)
690 # Check C format GUID
692 if not IsValidCFormatGuid(TokenList
[1]):
693 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_GUIDFORMAT
)
695 Item
= DecGuidItemObject(TokenList
[0], TokenList
[1], GuidString
)
696 ItemObject
= self
.ObjectDict
[self
._RawData
.CurrentScope
[0][0]]
697 ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
702 # Parse user extension section
704 class _DecUserExtension(_DecBase
):
705 def __init__(self
, RawData
):
706 _DecBase
.__init
__(self
, RawData
)
707 self
.ItemObject
= DecUserExtensionObject(RawData
.Filename
)
711 def BlockStart(self
):
713 for Header
in self
._RawData
.CurrentScope
:
714 if Header
in self
._Headers
:
715 self
._LoggerError
(ST
.ERR_DECPARSE_UE_DUPLICATE
)
717 self
._Headers
.append(Header
)
719 for Item
in self
._CurItems
:
720 if Item
.UserId
== Header
[1] and Item
.IdString
== Header
[2]:
721 Item
.ArchAndModuleType
.append(Header
[3])
724 Item
= DecUserExtensionItemObject()
725 Item
.UserId
= Header
[1]
726 Item
.IdString
= Header
[2]
727 Item
.ArchAndModuleType
.append(Header
[3])
728 self
._CurItems
.append(Item
)
729 self
.ItemObject
.AddItem(Item
, None)
730 self
._LocalMacro
= {}
732 def _ParseItem(self
):
733 Line
= self
._RawData
.CurrentLine
735 for Item
in self
._CurItems
:
737 Item
.UserString
= '\n'.join([Item
.UserString
, Line
])
739 Item
.UserString
= Line
746 class Dec(_DecBase
, _DecComments
):
747 def __init__(self
, DecFile
, Parse
= True):
749 Content
= ConvertSpecialChar(open(DecFile
, 'r').readlines())
750 except BaseException
:
751 Logger
.Error(TOOL_NAME
, FILE_OPEN_FAILURE
, File
=DecFile
,
752 ExtraData
=ST
.ERR_DECPARSE_FILEOPEN
% DecFile
)
755 # Pre-parser for Private section
758 __IsFoundPrivate
= False
762 if Line
.startswith(DT
.TAB_SECTION_START
) and Line
.endswith(DT
.TAB_PRIVATE
+ DT
.TAB_SECTION_END
):
763 __IsFoundPrivate
= True
764 if Line
.startswith(DT
.TAB_SECTION_START
) and Line
.endswith(DT
.TAB_SECTION_END
)\
765 and not Line
.endswith(DT
.TAB_PRIVATE
+ DT
.TAB_SECTION_END
):
766 __IsFoundPrivate
= False
768 self
._Private
+= Line
+ '\r'
769 if not __IsFoundPrivate
:
770 NewContent
.append(Line
+ '\r')
772 RawData
= FileContent(DecFile
, NewContent
)
774 _DecComments
.__init
__(self
)
775 _DecBase
.__init
__(self
, RawData
)
777 self
.BinaryHeadComment
= []
778 self
.PcdErrorCommentDict
= {}
780 self
._Define
= _DecDefine(RawData
)
781 self
._Include
= _DecInclude(RawData
)
782 self
._Guid
= _DecGuid(RawData
)
783 self
._LibClass
= _DecLibraryclass(RawData
)
784 self
._Pcd
= _DecPcd(RawData
)
785 self
._UserEx
= _DecUserExtension(RawData
)
788 # DEC file supported data types (one type per section)
790 self
._SectionParser
= {
791 DT
.TAB_DEC_DEFINES
.upper() : self
._Define
,
792 DT
.TAB_INCLUDES
.upper() : self
._Include
,
793 DT
.TAB_LIBRARY_CLASSES
.upper() : self
._LibClass
,
794 DT
.TAB_GUIDS
.upper() : self
._Guid
,
795 DT
.TAB_PPIS
.upper() : self
._Guid
,
796 DT
.TAB_PROTOCOLS
.upper() : self
._Guid
,
797 DT
.TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : self
._Pcd
,
798 DT
.TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : self
._Pcd
,
799 DT
.TAB_PCDS_FEATURE_FLAG_NULL
.upper() : self
._Pcd
,
800 DT
.TAB_PCDS_DYNAMIC_NULL
.upper() : self
._Pcd
,
801 DT
.TAB_PCDS_DYNAMIC_EX_NULL
.upper() : self
._Pcd
,
802 DT
.TAB_USER_EXTENSIONS
.upper() : self
._UserEx
806 self
.ParseDecComment()
809 # Parsing done, check required fields
811 self
.CheckRequiredFields()
813 def CheckRequiredFields(self
):
814 for SectionParser
in self
._SectionParser
.values():
815 if not SectionParser
.CheckRequiredFields():
822 def ParseDecComment(self
):
824 IsBinaryHeader
= False
825 FileHeaderLineIndex
= -1
826 BinaryHeaderLineIndex
= -1
827 TokenSpaceGuidCName
= ''
830 # Parse PCD error comment section
832 while not self
._RawData
.IsEndOfFile():
833 self
._RawData
.CurrentLine
= self
._RawData
.GetNextLine()
834 if self
._RawData
.CurrentLine
.startswith(DT
.TAB_COMMENT_SPLIT
) and \
835 DT
.TAB_SECTION_START
in self
._RawData
.CurrentLine
and \
836 DT
.TAB_SECTION_END
in self
._RawData
.CurrentLine
:
837 self
._RawData
.CurrentLine
= self
._RawData
.CurrentLine
.replace(DT
.TAB_COMMENT_SPLIT
, '').strip()
839 if self
._RawData
.CurrentLine
[0] == DT
.TAB_SECTION_START
and \
840 self
._RawData
.CurrentLine
[-1] == DT
.TAB_SECTION_END
:
841 RawSection
= self
._RawData
.CurrentLine
[1:-1].strip()
842 if RawSection
.upper().startswith(DT
.TAB_PCD_ERROR
.upper()+'.'):
843 TokenSpaceGuidCName
= RawSection
.split(DT
.TAB_PCD_ERROR
+'.')[1].strip()
846 if TokenSpaceGuidCName
and self
._RawData
.CurrentLine
.startswith(DT
.TAB_COMMENT_SPLIT
):
847 self
._RawData
.CurrentLine
= self
._RawData
.CurrentLine
.replace(DT
.TAB_COMMENT_SPLIT
, '').strip()
848 if self
._RawData
.CurrentLine
!= '':
849 if DT
.TAB_VALUE_SPLIT
not in self
._RawData
.CurrentLine
:
850 self
._LoggerError
(ST
.ERR_DECPARSE_PCDERRORMSG_MISS_VALUE_SPLIT
)
852 PcdErrorNumber
, PcdErrorMsg
= GetSplitValueList(self
._RawData
.CurrentLine
, DT
.TAB_VALUE_SPLIT
, 1)
853 PcdErrorNumber
= ParsePcdErrorCode(PcdErrorNumber
, self
._RawData
.Filename
, self
._RawData
.LineIndex
)
854 if not PcdErrorMsg
.strip():
855 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_MISS_ERRORMSG
)
857 self
.PcdErrorCommentDict
[(TokenSpaceGuidCName
, PcdErrorNumber
)] = PcdErrorMsg
.strip()
859 TokenSpaceGuidCName
= ''
861 self
._RawData
.LineIndex
= 0
862 self
._RawData
.CurrentLine
= ''
863 self
._RawData
.NextLine
= ''
865 while not self
._RawData
.IsEndOfFile():
866 Line
, Comment
= CleanString(self
._RawData
.GetNextLine())
869 # Header must be pure comment
872 self
._RawData
.UndoNextLine()
875 if Comment
and Comment
.startswith(DT
.TAB_SPECIAL_COMMENT
) and Comment
.find(DT
.TAB_HEADER_COMMENT
) > 0 \
876 and not Comment
[2:Comment
.find(DT
.TAB_HEADER_COMMENT
)].strip():
878 IsBinaryHeader
= False
879 FileHeaderLineIndex
= self
._RawData
.LineIndex
882 # Get license information before '@file'
884 if not IsFileHeader
and not IsBinaryHeader
and Comment
and Comment
.startswith(DT
.TAB_COMMENT_SPLIT
) and \
885 DT
.TAB_BINARY_HEADER_COMMENT
not in Comment
:
886 self
._HeadComment
.append((Comment
, self
._RawData
.LineIndex
))
888 if Comment
and IsFileHeader
and \
889 not(Comment
.startswith(DT
.TAB_SPECIAL_COMMENT
) \
890 and Comment
.find(DT
.TAB_BINARY_HEADER_COMMENT
) > 0):
891 self
._HeadComment
.append((Comment
, self
._RawData
.LineIndex
))
893 # Double '#' indicates end of header comments
895 if (not Comment
or Comment
== DT
.TAB_SPECIAL_COMMENT
) and IsFileHeader
:
899 if Comment
and Comment
.startswith(DT
.TAB_SPECIAL_COMMENT
) \
900 and Comment
.find(DT
.TAB_BINARY_HEADER_COMMENT
) > 0:
901 IsBinaryHeader
= True
903 BinaryHeaderLineIndex
= self
._RawData
.LineIndex
905 if Comment
and IsBinaryHeader
:
906 self
.BinaryHeadComment
.append((Comment
, self
._RawData
.LineIndex
))
908 # Double '#' indicates end of header comments
910 if (not Comment
or Comment
== DT
.TAB_SPECIAL_COMMENT
) and IsBinaryHeader
:
911 IsBinaryHeader
= False
914 if FileHeaderLineIndex
> -1 and not IsFileHeader
and not IsBinaryHeader
:
917 if FileHeaderLineIndex
> BinaryHeaderLineIndex
and FileHeaderLineIndex
> -1 and BinaryHeaderLineIndex
> -1:
918 self
._LoggerError
(ST
.ERR_BINARY_HEADER_ORDER
)
920 if FileHeaderLineIndex
== -1:
921 # self._LoggerError(ST.ERR_NO_SOURCE_HEADER)
922 Logger
.Error(TOOL_NAME
, FORMAT_INVALID
,
923 ST
.ERR_NO_SOURCE_HEADER
,
924 File
=self
._RawData
.Filename
)
927 def _StopCurrentParsing(self
, Line
):
930 def _ParseItem(self
):
931 self
._SectionHeaderParser
()
932 if len(self
._RawData
.CurrentScope
) == 0:
933 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_EMPTY
)
934 SectionObj
= self
._SectionParser
[self
._RawData
.CurrentScope
[0][0]]
935 SectionObj
.BlockStart()
937 return SectionObj
.GetDataObject()
939 def _UserExtentionSectionParser(self
):
940 self
._RawData
.CurrentScope
= []
942 Section
= self
._RawData
.CurrentLine
[1:-1]
943 Par
= ParserHelper(Section
, self
._RawData
.Filename
)
948 Token
= Par
.GetToken()
949 if Token
.upper() != DT
.TAB_USER_EXTENSIONS
.upper():
950 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE
)
951 UserExtension
= Token
.upper()
952 Par
.AssertChar(DT
.TAB_SPLIT
, ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
957 Token
= Par
.GetToken()
958 if not IsValidUserId(Token
):
959 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE_USERID
)
961 Par
.AssertChar(DT
.TAB_SPLIT
, ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
965 Token
= Par
.GetToken()
966 if not IsValidIdString(Token
):
967 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE_IDSTRING
)
970 if Par
.Expect(DT
.TAB_SPLIT
):
971 Token
= Par
.GetToken()
973 if not IsValidArch(Arch
):
974 self
._LoggerError
(ST
.ERR_DECPARSE_ARCH
)
976 if [UserExtension
, UserId
, IdString
, Arch
] not in \
977 self
._RawData
.CurrentScope
:
978 self
._RawData
.CurrentScope
.append(
979 [UserExtension
, UserId
, IdString
, Arch
]
981 if not Par
.Expect(DT
.TAB_COMMA_SPLIT
):
984 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMA
)
985 Par
.AssertEnd(ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
986 if 'COMMON' in ArchList
and len(ArchList
) > 1:
987 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMON
)
989 ## Section header parser
991 # The section header is always in following format:
993 # [section_name.arch<.platform|module_type>]
995 def _SectionHeaderParser(self
):
996 if self
._RawData
.CurrentLine
[0] != DT
.TAB_SECTION_START
or self
._RawData
.CurrentLine
[-1] != DT
.TAB_SECTION_END
:
997 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_IDENTIFY
)
999 RawSection
= self
._RawData
.CurrentLine
[1:-1].strip().upper()
1001 # Check defines section which is only allowed to occur once and
1002 # no arch can be followed
1004 if RawSection
.startswith(DT
.TAB_DEC_DEFINES
.upper()):
1005 if RawSection
!= DT
.TAB_DEC_DEFINES
.upper():
1006 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_SECNAME
)
1008 # Check user extension section
1010 if RawSection
.startswith(DT
.TAB_USER_EXTENSIONS
.upper()):
1011 return self
._UserExtentionSectionParser
()
1012 self
._RawData
.CurrentScope
= []
1015 for Item
in GetSplitValueList(RawSection
, DT
.TAB_COMMA_SPLIT
):
1017 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBEMPTY
% self
._RawData
.CurrentLine
)
1019 ItemList
= GetSplitValueList(Item
, DT
.TAB_SPLIT
)
1021 # different types of PCD are permissible in one section
1023 SectionName
= ItemList
[0]
1024 if SectionName
not in self
._SectionParser
:
1025 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UNKNOW
% SectionName
)
1026 if SectionName
not in SectionNames
:
1027 SectionNames
.append(SectionName
)
1029 # In DEC specification, all section headers have at most two part:
1030 # SectionName.Arch except UserExtension
1032 if len(ItemList
) > 2:
1033 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBTOOMANY
% Item
)
1035 if DT
.TAB_PCDS_FEATURE_FLAG_NULL
.upper() in SectionNames
and len(SectionNames
) > 1:
1036 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_FEATUREFLAG
% DT
.TAB_PCDS_FEATURE_FLAG_NULL
)
1040 if len(ItemList
) > 1:
1042 if not IsValidArch(Str1
):
1043 self
._LoggerError
(ST
.ERR_DECPARSE_ARCH
)
1048 if [SectionName
, Str1
] not in self
._RawData
.CurrentScope
:
1049 self
._RawData
.CurrentScope
.append([SectionName
, Str1
])
1051 # 'COMMON' must not be used with specific ARCHs at the same section
1053 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1054 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMON
)
1055 if len(SectionNames
) == 0:
1056 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBEMPTY
% self
._RawData
.CurrentLine
)
1057 if len(SectionNames
) != 1:
1058 for Sec
in SectionNames
:
1059 if not Sec
.startswith(DT
.TAB_PCDS
.upper()):
1060 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_NAME
% str(SectionNames
))
1062 def GetDefineSectionMacro(self
):
1063 return self
._Define
.GetLocalMacro()
1064 def GetDefineSectionObject(self
):
1065 return self
._Define
.GetDataObject()
1066 def GetIncludeSectionObject(self
):
1067 return self
._Include
.GetDataObject()
1068 def GetGuidSectionObject(self
):
1069 return self
._Guid
.GetGuidObject()
1070 def GetProtocolSectionObject(self
):
1071 return self
._Guid
.GetProtocolObject()
1072 def GetPpiSectionObject(self
):
1073 return self
._Guid
.GetPpiObject()
1074 def GetLibraryClassSectionObject(self
):
1075 return self
._LibClass
.GetDataObject()
1076 def GetPcdSectionObject(self
):
1077 return self
._Pcd
.GetDataObject()
1078 def GetUserExtensionSectionObject(self
):
1079 return self
._UserEx
.GetDataObject()
1080 def GetPackageSpecification(self
):
1081 return self
._Define
.GetDataObject().GetPackageSpecification()
1082 def GetPackageName(self
):
1083 return self
._Define
.GetDataObject().GetPackageName()
1084 def GetPackageGuid(self
):
1085 return self
._Define
.GetDataObject().GetPackageGuid()
1086 def GetPackageVersion(self
):
1087 return self
._Define
.GetDataObject().GetPackageVersion()
1088 def GetPackageUniFile(self
):
1089 return self
._Define
.GetDataObject().GetPackageUniFile()
1090 def GetPrivateSections(self
):
1091 return self
._Private