2 # This file is used to parse DEC file. It will consumed by DecParser
4 # Copyright (c) 2011 - 2016, 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
.String
import ReplaceMacro
61 from Library
.String
import GetSplitValueList
62 from Library
.String
import gMACRO_PATTERN
63 from Library
.String
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
)
273 self
._RawData
.CurrentLine
= self
._ReplaceMacro
(CatLine
)
274 return CatLine
, CommentList
277 # This is a template method in which other member functions which might
278 # override by sub class are called. It is responsible for reading file
279 # line by line, and call other member functions to parse. This function
280 # should not be re-implement by sub class.
286 #======================================================================
287 # CurComments may pointer to HeadComments or TailComments
288 #======================================================================
289 CurComments
= HeadComments
294 #======================================================================
295 # Used to report error information if empty section found
296 #======================================================================
297 Index
= self
._RawData
.LineIndex
298 LineStr
= self
._RawData
.CurrentLine
299 while not self
._RawData
.IsEndOfFile() or self
._RawData
.NextLine
:
300 if self
._RawData
.NextLine
:
301 #==============================================================
302 # Have processed line in buffer
303 #==============================================================
304 Line
= self
._RawData
.NextLine
305 HeadComments
.extend(self
._RawData
.HeadComment
)
306 TailComments
.extend(self
._RawData
.TailComment
)
307 self
._RawData
.ResetNext()
311 #==============================================================
312 # No line in buffer, read next line
313 #==============================================================
314 Line
, Comment
= CleanString(self
._RawData
.GetNextLine())
317 if not FromBuf
and CurObj
and TailComments
:
318 #==========================================================
319 # Set tail comments to previous statement if not empty.
320 #==========================================================
321 CurObj
.SetTailComment(CurObj
.GetTailComment()+TailComments
)
325 CurComments
= TailComments
328 Comments
= [(Comment
, self
._RawData
.LineIndex
)]
330 #==============================================================
331 # Try if last char of line has backslash
332 #==============================================================
333 Line
, Comments
= self
._TryBackSlash
(Line
, Comments
)
334 CurComments
.extend(Comments
)
336 #==============================================================
338 #==============================================================
339 if Line
.startswith('DEFINE '):
340 self
._MacroParser
(Line
)
343 CurComments
= HeadComments
346 if self
._StopCurrentParsing
(Line
):
347 #==========================================================
348 # This line does not belong to this parse,
349 # Save it, can be used by next parse
350 #==========================================================
351 self
._RawData
.SetNext(Line
, HeadComments
, TailComments
)
354 Obj
= self
._ParseItem
()
357 Obj
.SetHeadComment(Obj
.GetHeadComment()+HeadComments
)
358 Obj
.SetTailComment(Obj
.GetTailComment()+TailComments
)
365 if id(CurComments
) == id(TailComments
):
366 #==========================================================
367 # Check if this comment belongs to tail comment
368 #==========================================================
369 if not self
._TailCommentStrategy
(Comment
):
370 CurComments
= HeadComments
373 CurComments
.append(((Comment
, self
._RawData
.LineIndex
)))
377 if self
._IsStatementRequired
() and ItemNum
== 0:
379 TOOL_NAME
, FILE_PARSE_FAILURE
,
380 File
=self
._RawData
.Filename
,
382 ExtraData
=ST
.ERR_DECPARSE_STATEMENT_EMPTY
% LineStr
386 # Parse define section
388 class _DecDefine(_DecBase
):
389 def __init__(self
, RawData
):
390 _DecBase
.__init
__(self
, RawData
)
391 self
.ItemObject
= DecDefineObject(RawData
.Filename
)
392 self
._LocalMacro
= self
._RawData
.Macros
396 # Each field has a function to validate
398 self
.DefineValidation
= {
399 DT
.TAB_DEC_DEFINES_DEC_SPECIFICATION
: self
._SetDecSpecification
,
400 DT
.TAB_DEC_DEFINES_PACKAGE_NAME
: self
._SetPackageName
,
401 DT
.TAB_DEC_DEFINES_PACKAGE_GUID
: self
._SetPackageGuid
,
402 DT
.TAB_DEC_DEFINES_PACKAGE_VERSION
: self
._SetPackageVersion
,
403 DT
.TAB_DEC_DEFINES_PKG_UNI_FILE
: self
._SetPackageUni
,
406 def BlockStart(self
):
408 if self
._DefSecNum
> 1:
409 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_MULTISEC
)
411 ## CheckRequiredFields
413 # Check required fields: DEC_SPECIFICATION, PACKAGE_NAME
414 # PACKAGE_GUID, PACKAGE_VERSION
416 def CheckRequiredFields(self
):
418 if self
.ItemObject
.GetPackageSpecification() == '':
419 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
420 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_DEC_SPECIFICATION
)
421 elif self
.ItemObject
.GetPackageName() == '':
422 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
423 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_PACKAGE_NAME
)
424 elif self
.ItemObject
.GetPackageGuid() == '':
425 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
426 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_PACKAGE_GUID
)
427 elif self
.ItemObject
.GetPackageVersion() == '':
428 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
429 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_PACKAGE_VERSION
)
434 def _ParseItem(self
):
435 Line
= self
._RawData
.CurrentLine
436 TokenList
= GetSplitValueList(Line
, DT
.TAB_EQUAL_SPLIT
, 1)
437 if TokenList
[0] == DT
.TAB_DEC_DEFINES_PKG_UNI_FILE
:
438 self
.DefineValidation
[TokenList
[0]](TokenList
[1])
439 elif len(TokenList
) < 2:
440 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_FORMAT
)
441 elif TokenList
[0] not in self
.DefineValidation
:
442 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_UNKNOWKEY
% TokenList
[0])
444 self
.DefineValidation
[TokenList
[0]](TokenList
[1])
446 DefineItem
= DecDefineItemObject()
447 DefineItem
.Key
= TokenList
[0]
448 DefineItem
.Value
= TokenList
[1]
449 self
.ItemObject
.AddItem(DefineItem
, self
._RawData
.CurrentScope
)
452 def _SetDecSpecification(self
, Token
):
453 if self
.ItemObject
.GetPackageSpecification():
454 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_DEC_SPECIFICATION
)
455 if not IsValidToken('0[xX][0-9a-fA-F]{8}', Token
):
456 if not IsValidDecVersionVal(Token
):
457 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_SPEC
)
458 self
.ItemObject
.SetPackageSpecification(Token
)
460 def _SetPackageName(self
, Token
):
461 if self
.ItemObject
.GetPackageName():
462 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PACKAGE_NAME
)
463 if not IsValidWord(Token
):
464 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGNAME
)
465 self
.ItemObject
.SetPackageName(Token
)
467 def _SetPackageGuid(self
, Token
):
468 if self
.ItemObject
.GetPackageGuid():
469 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PACKAGE_GUID
)
470 if not CheckGuidRegFormat(Token
):
471 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGGUID
)
472 self
.ItemObject
.SetPackageGuid(Token
)
474 def _SetPackageVersion(self
, Token
):
475 if self
.ItemObject
.GetPackageVersion():
476 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PACKAGE_VERSION
)
477 if not IsValidToken(VERSION_PATTERN
, Token
):
478 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGVERSION
)
480 if not DT
.TAB_SPLIT
in Token
:
482 self
.ItemObject
.SetPackageVersion(Token
)
484 def _SetPackageUni(self
, Token
):
485 if self
.ItemObject
.GetPackageUniFile():
486 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PKG_UNI_FILE
)
487 self
.ItemObject
.SetPackageUniFile(Token
)
491 # Parse include section
493 class _DecInclude(_DecBase
):
494 def __init__(self
, RawData
):
495 _DecBase
.__init
__(self
, RawData
)
496 self
.ItemObject
= DecIncludeObject(RawData
.Filename
)
498 def _ParseItem(self
):
499 Line
= self
._RawData
.CurrentLine
501 if not IsValidPath(Line
, self
._RawData
.PackagePath
):
502 self
._LoggerError
(ST
.ERR_DECPARSE_INCLUDE
% Line
)
504 Item
= DecIncludeItemObject(StripRoot(self
._RawData
.PackagePath
, Line
), self
._RawData
.PackagePath
)
505 self
.ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
510 # Parse library class section
512 class _DecLibraryclass(_DecBase
):
513 def __init__(self
, RawData
):
514 _DecBase
.__init
__(self
, RawData
)
515 self
.ItemObject
= DecLibraryclassObject(RawData
.Filename
)
517 def _ParseItem(self
):
518 Line
= self
._RawData
.CurrentLine
519 TokenList
= GetSplitValueList(Line
, DT
.TAB_VALUE_SPLIT
)
520 if len(TokenList
) != 2:
521 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_SPLIT
)
522 if TokenList
[0] == '' or TokenList
[1] == '':
523 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_EMPTY
)
524 if not IsValidToken('[A-Z][0-9A-Za-z]*', TokenList
[0]):
525 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_LIB
)
527 self
._CheckReDefine
(TokenList
[0])
533 if not Value
.endswith('.h'):
534 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_PATH_EXT
)
537 # Path must be existed
539 if not IsValidPath(Value
, self
._RawData
.PackagePath
):
540 self
._LoggerError
(ST
.ERR_DECPARSE_INCLUDE
% Value
)
542 Item
= DecLibraryclassItemObject(TokenList
[0], StripRoot(self
._RawData
.PackagePath
, Value
),
543 self
._RawData
.PackagePath
)
544 self
.ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
551 class _DecPcd(_DecBase
):
552 def __init__(self
, RawData
):
553 _DecBase
.__init
__(self
, RawData
)
554 self
.ItemObject
= DecPcdObject(RawData
.Filename
)
556 # Used to check duplicate token
557 # Key is token space and token number (integer), value is C name
561 def _ParseItem(self
):
562 Line
= self
._RawData
.CurrentLine
563 TokenList
= Line
.split(DT
.TAB_VALUE_SPLIT
)
564 if len(TokenList
) < 4:
565 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_SPLIT
)
568 # Token space guid C name
570 PcdName
= GetSplitValueList(TokenList
[0], DT
.TAB_SPLIT
)
571 if len(PcdName
) != 2 or PcdName
[0] == '' or PcdName
[1] == '':
572 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_NAME
)
575 if not IsValidToken(CVAR_PATTERN
, Guid
):
576 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_CVAR_GUID
)
582 if not IsValidToken(CVAR_PATTERN
, CName
):
583 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_CVAR_PCDCNAME
)
585 self
._CheckReDefine
(Guid
+ DT
.TAB_SPLIT
+ CName
)
588 # Default value, may be C array, string or number
590 Data
= DT
.TAB_VALUE_SPLIT
.join(TokenList
[1:-2]).strip()
595 DataType
= TokenList
[-2].strip()
596 Valid
, Cause
= IsValidPcdDatum(DataType
, Data
)
598 self
._LoggerError
(Cause
)
599 PcdType
= self
._RawData
.CurrentScope
[0][0]
600 if PcdType
== DT
.TAB_PCDS_FEATURE_FLAG_NULL
.upper() and DataType
!= 'BOOLEAN':
601 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_FEATUREFLAG
)
603 # Token value is the last element in list.
605 Token
= TokenList
[-1].strip()
606 if not IsValidToken(PCD_TOKEN_PATTERN
, Token
):
607 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_TOKEN
% Token
)
608 elif not Token
.startswith('0x') and not Token
.startswith('0X'):
609 if long(Token
) > 4294967295:
610 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_TOKEN_INT
% Token
)
611 Token
= hex(long(Token
))[:-1]
613 IntToken
= long(Token
, 0)
614 if (Guid
, IntToken
) in self
.TokenMap
:
615 if self
.TokenMap
[Guid
, IntToken
] != CName
:
616 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_TOKEN_UNIQUE
%(Token))
618 self
.TokenMap
[Guid
, IntToken
] = CName
620 Item
= DecPcdItemObject(Guid
, CName
, Data
, DataType
, Token
)
621 self
.ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
626 # Parse GUID, PPI, Protocol section
628 class _DecGuid(_DecBase
):
629 def __init__(self
, RawData
):
630 _DecBase
.__init
__(self
, RawData
)
631 self
.GuidObj
= DecGuidObject(RawData
.Filename
)
632 self
.PpiObj
= DecPpiObject(RawData
.Filename
)
633 self
.ProtocolObj
= DecProtocolObject(RawData
.Filename
)
636 DT
.TAB_GUIDS
.upper() : self
.GuidObj
,
637 DT
.TAB_PPIS
.upper() : self
.PpiObj
,
638 DT
.TAB_PROTOCOLS
.upper() : self
.ProtocolObj
641 def GetDataObject(self
):
642 if self
._RawData
.CurrentScope
:
643 return self
.ObjectDict
[self
._RawData
.CurrentScope
[0][0]]
646 def GetGuidObject(self
):
649 def GetPpiObject(self
):
652 def GetProtocolObject(self
):
653 return self
.ProtocolObj
655 def _ParseItem(self
):
656 Line
= self
._RawData
.CurrentLine
657 TokenList
= GetSplitValueList(Line
, DT
.TAB_EQUAL_SPLIT
, 1)
658 if len(TokenList
) < 2:
659 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID
)
660 if TokenList
[0] == '':
661 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_NAME
)
662 if TokenList
[1] == '':
663 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_GUID
)
664 if not IsValidToken(CVAR_PATTERN
, TokenList
[0]):
665 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_CVAR_GUID
)
667 self
._CheckReDefine
(TokenList
[0])
669 if TokenList
[1][0] != '{':
670 if not CheckGuidRegFormat(TokenList
[1]):
671 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGGUID
)
672 GuidString
= TokenList
[1]
675 # Convert C format GUID to GUID string and Simple error check
677 GuidString
= GuidStructureStringToGuidString(TokenList
[1])
678 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidString
== '':
679 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_GUIDFORMAT
)
682 # Check C format GUID
684 if not IsValidCFormatGuid(TokenList
[1]):
685 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_GUIDFORMAT
)
687 Item
= DecGuidItemObject(TokenList
[0], TokenList
[1], GuidString
)
688 ItemObject
= self
.ObjectDict
[self
._RawData
.CurrentScope
[0][0]]
689 ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
694 # Parse user extention section
696 class _DecUserExtension(_DecBase
):
697 def __init__(self
, RawData
):
698 _DecBase
.__init
__(self
, RawData
)
699 self
.ItemObject
= DecUserExtensionObject(RawData
.Filename
)
703 def BlockStart(self
):
705 for Header
in self
._RawData
.CurrentScope
:
706 if Header
in self
._Headers
:
707 self
._LoggerError
(ST
.ERR_DECPARSE_UE_DUPLICATE
)
709 self
._Headers
.append(Header
)
711 for Item
in self
._CurItems
:
712 if Item
.UserId
== Header
[1] and Item
.IdString
== Header
[2]:
713 Item
.ArchAndModuleType
.append(Header
[3])
716 Item
= DecUserExtensionItemObject()
717 Item
.UserId
= Header
[1]
718 Item
.IdString
= Header
[2]
719 Item
.ArchAndModuleType
.append(Header
[3])
720 self
._CurItems
.append(Item
)
721 self
.ItemObject
.AddItem(Item
, None)
722 self
._LocalMacro
= {}
724 def _ParseItem(self
):
725 Line
= self
._RawData
.CurrentLine
727 for Item
in self
._CurItems
:
729 Item
.UserString
= '\n'.join([Item
.UserString
, Line
])
731 Item
.UserString
= Line
738 class Dec(_DecBase
, _DecComments
):
739 def __init__(self
, DecFile
, Parse
= True):
741 Content
= ConvertSpecialChar(open(DecFile
, 'rb').readlines())
742 except BaseException
:
743 Logger
.Error(TOOL_NAME
, FILE_OPEN_FAILURE
, File
=DecFile
,
744 ExtraData
=ST
.ERR_DECPARSE_FILEOPEN
% DecFile
)
747 # Pre-parser for Private section
750 __IsFoundPrivate
= False
754 if Line
.startswith(DT
.TAB_SECTION_START
) and Line
.endswith(DT
.TAB_PRIVATE
+ DT
.TAB_SECTION_END
):
755 __IsFoundPrivate
= True
756 if Line
.startswith(DT
.TAB_SECTION_START
) and Line
.endswith(DT
.TAB_SECTION_END
)\
757 and not Line
.endswith(DT
.TAB_PRIVATE
+ DT
.TAB_SECTION_END
):
758 __IsFoundPrivate
= False
760 self
._Private
+= Line
+ '\r'
761 if not __IsFoundPrivate
:
762 NewContent
.append(Line
+ '\r')
764 RawData
= FileContent(DecFile
, NewContent
)
766 _DecComments
.__init
__(self
)
767 _DecBase
.__init
__(self
, RawData
)
769 self
.BinaryHeadComment
= []
770 self
.PcdErrorCommentDict
= {}
772 self
._Define
= _DecDefine(RawData
)
773 self
._Include
= _DecInclude(RawData
)
774 self
._Guid
= _DecGuid(RawData
)
775 self
._LibClass
= _DecLibraryclass(RawData
)
776 self
._Pcd
= _DecPcd(RawData
)
777 self
._UserEx
= _DecUserExtension(RawData
)
780 # DEC file supported data types (one type per section)
782 self
._SectionParser
= {
783 DT
.TAB_DEC_DEFINES
.upper() : self
._Define
,
784 DT
.TAB_INCLUDES
.upper() : self
._Include
,
785 DT
.TAB_LIBRARY_CLASSES
.upper() : self
._LibClass
,
786 DT
.TAB_GUIDS
.upper() : self
._Guid
,
787 DT
.TAB_PPIS
.upper() : self
._Guid
,
788 DT
.TAB_PROTOCOLS
.upper() : self
._Guid
,
789 DT
.TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : self
._Pcd
,
790 DT
.TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : self
._Pcd
,
791 DT
.TAB_PCDS_FEATURE_FLAG_NULL
.upper() : self
._Pcd
,
792 DT
.TAB_PCDS_DYNAMIC_NULL
.upper() : self
._Pcd
,
793 DT
.TAB_PCDS_DYNAMIC_EX_NULL
.upper() : self
._Pcd
,
794 DT
.TAB_USER_EXTENSIONS
.upper() : self
._UserEx
798 self
.ParseDecComment()
801 # Parsing done, check required fields
803 self
.CheckRequiredFields()
805 def CheckRequiredFields(self
):
806 for SectionParser
in self
._SectionParser
.values():
807 if not SectionParser
.CheckRequiredFields():
814 def ParseDecComment(self
):
816 IsBinaryHeader
= False
817 FileHeaderLineIndex
= -1
818 BinaryHeaderLineIndex
= -1
819 TokenSpaceGuidCName
= ''
822 # Parse PCD error comment section
824 while not self
._RawData
.IsEndOfFile():
825 self
._RawData
.CurrentLine
= self
._RawData
.GetNextLine()
826 if self
._RawData
.CurrentLine
.startswith(DT
.TAB_COMMENT_SPLIT
) and \
827 DT
.TAB_SECTION_START
in self
._RawData
.CurrentLine
and \
828 DT
.TAB_SECTION_END
in self
._RawData
.CurrentLine
:
829 self
._RawData
.CurrentLine
= self
._RawData
.CurrentLine
.replace(DT
.TAB_COMMENT_SPLIT
, '').strip()
831 if self
._RawData
.CurrentLine
[0] == DT
.TAB_SECTION_START
and \
832 self
._RawData
.CurrentLine
[-1] == DT
.TAB_SECTION_END
:
833 RawSection
= self
._RawData
.CurrentLine
[1:-1].strip()
834 if RawSection
.upper().startswith(DT
.TAB_PCD_ERROR
.upper()+'.'):
835 TokenSpaceGuidCName
= RawSection
.split(DT
.TAB_PCD_ERROR
+'.')[1].strip()
838 if TokenSpaceGuidCName
and self
._RawData
.CurrentLine
.startswith(DT
.TAB_COMMENT_SPLIT
):
839 self
._RawData
.CurrentLine
= self
._RawData
.CurrentLine
.replace(DT
.TAB_COMMENT_SPLIT
, '').strip()
840 if self
._RawData
.CurrentLine
!= '':
841 if DT
.TAB_VALUE_SPLIT
not in self
._RawData
.CurrentLine
:
842 self
._LoggerError
(ST
.ERR_DECPARSE_PCDERRORMSG_MISS_VALUE_SPLIT
)
844 PcdErrorNumber
, PcdErrorMsg
= GetSplitValueList(self
._RawData
.CurrentLine
, DT
.TAB_VALUE_SPLIT
, 1)
845 PcdErrorNumber
= ParsePcdErrorCode(PcdErrorNumber
, self
._RawData
.Filename
, self
._RawData
.LineIndex
)
846 if not PcdErrorMsg
.strip():
847 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_MISS_ERRORMSG
)
849 self
.PcdErrorCommentDict
[(TokenSpaceGuidCName
, PcdErrorNumber
)] = PcdErrorMsg
.strip()
851 TokenSpaceGuidCName
= ''
853 self
._RawData
.LineIndex
= 0
854 self
._RawData
.CurrentLine
= ''
855 self
._RawData
.NextLine
= ''
857 while not self
._RawData
.IsEndOfFile():
858 Line
, Comment
= CleanString(self
._RawData
.GetNextLine())
861 # Header must be pure comment
864 self
._RawData
.UndoNextLine()
867 if Comment
and Comment
.startswith(DT
.TAB_SPECIAL_COMMENT
) and Comment
.find(DT
.TAB_HEADER_COMMENT
) > 0 \
868 and not Comment
[2:Comment
.find(DT
.TAB_HEADER_COMMENT
)].strip():
870 IsBinaryHeader
= False
871 FileHeaderLineIndex
= self
._RawData
.LineIndex
874 # Get license information before '@file'
876 if not IsFileHeader
and not IsBinaryHeader
and Comment
and Comment
.startswith(DT
.TAB_COMMENT_SPLIT
) and \
877 DT
.TAB_BINARY_HEADER_COMMENT
not in Comment
:
878 self
._HeadComment
.append((Comment
, self
._RawData
.LineIndex
))
880 if Comment
and IsFileHeader
and \
881 not(Comment
.startswith(DT
.TAB_SPECIAL_COMMENT
) \
882 and Comment
.find(DT
.TAB_BINARY_HEADER_COMMENT
) > 0):
883 self
._HeadComment
.append((Comment
, self
._RawData
.LineIndex
))
885 # Double '#' indicates end of header comments
887 if (not Comment
or Comment
== DT
.TAB_SPECIAL_COMMENT
) and IsFileHeader
:
891 if Comment
and Comment
.startswith(DT
.TAB_SPECIAL_COMMENT
) \
892 and Comment
.find(DT
.TAB_BINARY_HEADER_COMMENT
) > 0:
893 IsBinaryHeader
= True
895 BinaryHeaderLineIndex
= self
._RawData
.LineIndex
897 if Comment
and IsBinaryHeader
:
898 self
.BinaryHeadComment
.append((Comment
, self
._RawData
.LineIndex
))
900 # Double '#' indicates end of header comments
902 if (not Comment
or Comment
== DT
.TAB_SPECIAL_COMMENT
) and IsBinaryHeader
:
903 IsBinaryHeader
= False
906 if FileHeaderLineIndex
> -1 and not IsFileHeader
and not IsBinaryHeader
:
909 if FileHeaderLineIndex
> BinaryHeaderLineIndex
and FileHeaderLineIndex
> -1 and BinaryHeaderLineIndex
> -1:
910 self
._LoggerError
(ST
.ERR_BINARY_HEADER_ORDER
)
912 if FileHeaderLineIndex
== -1:
913 # self._LoggerError(ST.ERR_NO_SOURCE_HEADER)
914 Logger
.Error(TOOL_NAME
, FORMAT_INVALID
,
915 ST
.ERR_NO_SOURCE_HEADER
,
916 File
=self
._RawData
.Filename
)
919 def _StopCurrentParsing(self
, Line
):
922 def _ParseItem(self
):
923 self
._SectionHeaderParser
()
924 if len(self
._RawData
.CurrentScope
) == 0:
925 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_EMPTY
)
926 SectionObj
= self
._SectionParser
[self
._RawData
.CurrentScope
[0][0]]
927 SectionObj
.BlockStart()
929 return SectionObj
.GetDataObject()
931 def _UserExtentionSectionParser(self
):
932 self
._RawData
.CurrentScope
= []
934 Section
= self
._RawData
.CurrentLine
[1:-1]
935 Par
= ParserHelper(Section
, self
._RawData
.Filename
)
940 Token
= Par
.GetToken()
941 if Token
.upper() != DT
.TAB_USER_EXTENSIONS
.upper():
942 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE
)
943 UserExtension
= Token
.upper()
944 Par
.AssertChar(DT
.TAB_SPLIT
, ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
949 Token
= Par
.GetToken()
950 if not IsValidUserId(Token
):
951 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE_USERID
)
953 Par
.AssertChar(DT
.TAB_SPLIT
, ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
957 Token
= Par
.GetToken()
958 if not IsValidIdString(Token
):
959 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE_IDSTRING
)
962 if Par
.Expect(DT
.TAB_SPLIT
):
963 Token
= Par
.GetToken()
965 if not IsValidArch(Arch
):
966 self
._LoggerError
(ST
.ERR_DECPARSE_ARCH
)
968 if [UserExtension
, UserId
, IdString
, Arch
] not in \
969 self
._RawData
.CurrentScope
:
970 self
._RawData
.CurrentScope
.append(
971 [UserExtension
, UserId
, IdString
, Arch
]
973 if not Par
.Expect(DT
.TAB_COMMA_SPLIT
):
976 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMA
)
977 Par
.AssertEnd(ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
978 if 'COMMON' in ArchList
and len(ArchList
) > 1:
979 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMON
)
981 ## Section header parser
983 # The section header is always in following format:
985 # [section_name.arch<.platform|module_type>]
987 def _SectionHeaderParser(self
):
988 if self
._RawData
.CurrentLine
[0] != DT
.TAB_SECTION_START
or self
._RawData
.CurrentLine
[-1] != DT
.TAB_SECTION_END
:
989 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_IDENTIFY
)
991 RawSection
= self
._RawData
.CurrentLine
[1:-1].strip().upper()
993 # Check defines section which is only allowed to occur once and
994 # no arch can be followed
996 if RawSection
.startswith(DT
.TAB_DEC_DEFINES
.upper()):
997 if RawSection
!= DT
.TAB_DEC_DEFINES
.upper():
998 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_SECNAME
)
1000 # Check user extension section
1002 if RawSection
.startswith(DT
.TAB_USER_EXTENSIONS
.upper()):
1003 return self
._UserExtentionSectionParser
()
1004 self
._RawData
.CurrentScope
= []
1007 for Item
in GetSplitValueList(RawSection
, DT
.TAB_COMMA_SPLIT
):
1009 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBEMPTY
% self
._RawData
.CurrentLine
)
1011 ItemList
= GetSplitValueList(Item
, DT
.TAB_SPLIT
)
1013 # different types of PCD are permissible in one section
1015 SectionName
= ItemList
[0]
1016 if SectionName
not in self
._SectionParser
:
1017 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UNKNOW
% SectionName
)
1018 if SectionName
not in SectionNames
:
1019 SectionNames
.append(SectionName
)
1021 # In DEC specification, all section headers have at most two part:
1022 # SectionName.Arch except UserExtention
1024 if len(ItemList
) > 2:
1025 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBTOOMANY
% Item
)
1027 if DT
.TAB_PCDS_FEATURE_FLAG_NULL
.upper() in SectionNames
and len(SectionNames
) > 1:
1028 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_FEATUREFLAG
% DT
.TAB_PCDS_FEATURE_FLAG_NULL
)
1032 if len(ItemList
) > 1:
1034 if not IsValidArch(Str1
):
1035 self
._LoggerError
(ST
.ERR_DECPARSE_ARCH
)
1040 if [SectionName
, Str1
] not in self
._RawData
.CurrentScope
:
1041 self
._RawData
.CurrentScope
.append([SectionName
, Str1
])
1043 # 'COMMON' must not be used with specific ARCHs at the same section
1045 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1046 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMON
)
1047 if len(SectionNames
) == 0:
1048 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBEMPTY
% self
._RawData
.CurrentLine
)
1049 if len(SectionNames
) != 1:
1050 for Sec
in SectionNames
:
1051 if not Sec
.startswith(DT
.TAB_PCDS
.upper()):
1052 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_NAME
% str(SectionNames
))
1054 def GetDefineSectionMacro(self
):
1055 return self
._Define
.GetLocalMacro()
1056 def GetDefineSectionObject(self
):
1057 return self
._Define
.GetDataObject()
1058 def GetIncludeSectionObject(self
):
1059 return self
._Include
.GetDataObject()
1060 def GetGuidSectionObject(self
):
1061 return self
._Guid
.GetGuidObject()
1062 def GetProtocolSectionObject(self
):
1063 return self
._Guid
.GetProtocolObject()
1064 def GetPpiSectionObject(self
):
1065 return self
._Guid
.GetPpiObject()
1066 def GetLibraryClassSectionObject(self
):
1067 return self
._LibClass
.GetDataObject()
1068 def GetPcdSectionObject(self
):
1069 return self
._Pcd
.GetDataObject()
1070 def GetUserExtensionSectionObject(self
):
1071 return self
._UserEx
.GetDataObject()
1072 def GetPackageSpecification(self
):
1073 return self
._Define
.GetDataObject().GetPackageSpecification()
1074 def GetPackageName(self
):
1075 return self
._Define
.GetDataObject().GetPackageName()
1076 def GetPackageGuid(self
):
1077 return self
._Define
.GetDataObject().GetPackageGuid()
1078 def GetPackageVersion(self
):
1079 return self
._Define
.GetDataObject().GetPackageVersion()
1080 def GetPackageUniFile(self
):
1081 return self
._Define
.GetDataObject().GetPackageUniFile()
1082 def GetPrivateSections(self
):
1083 return self
._Private