2 # This file is used to parse DEC file. It will consumed by DecParser
4 # Copyright (c) 2011 - 2013, 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 Parser
.DecParserMisc
import TOOL_NAME
33 from Parser
.DecParserMisc
import CleanString
34 from Parser
.DecParserMisc
import IsValidPcdDatum
35 from Parser
.DecParserMisc
import ParserHelper
36 from Parser
.DecParserMisc
import StripRoot
37 from Parser
.DecParserMisc
import VERSION_PATTERN
38 from Parser
.DecParserMisc
import CVAR_PATTERN
39 from Parser
.DecParserMisc
import PCD_TOKEN_PATTERN
40 from Parser
.DecParserMisc
import MACRO_PATTERN
41 from Parser
.DecParserMisc
import FileContent
42 from Object
.Parser
.DecObject
import _DecComments
43 from Object
.Parser
.DecObject
import DecDefineObject
44 from Object
.Parser
.DecObject
import DecDefineItemObject
45 from Object
.Parser
.DecObject
import DecIncludeObject
46 from Object
.Parser
.DecObject
import DecIncludeItemObject
47 from Object
.Parser
.DecObject
import DecLibraryclassObject
48 from Object
.Parser
.DecObject
import DecLibraryclassItemObject
49 from Object
.Parser
.DecObject
import DecGuidObject
50 from Object
.Parser
.DecObject
import DecPpiObject
51 from Object
.Parser
.DecObject
import DecProtocolObject
52 from Object
.Parser
.DecObject
import DecGuidItemObject
53 from Object
.Parser
.DecObject
import DecUserExtensionObject
54 from Object
.Parser
.DecObject
import DecUserExtensionItemObject
55 from Object
.Parser
.DecObject
import DecPcdObject
56 from Object
.Parser
.DecObject
import DecPcdItemObject
57 from Library
.Misc
import GuidStructureStringToGuidString
58 from Library
.Misc
import CheckGuidRegFormat
59 from Library
.String
import ReplaceMacro
60 from Library
.String
import GetSplitValueList
61 from Library
.String
import gMACRO_PATTERN
62 from Library
.String
import ConvertSpecialChar
65 # _DecBase class for parsing
68 def __init__(self
, RawData
):
69 self
._RawData
= RawData
73 # Data parsed by 'self' are saved to this object
75 self
.ItemObject
= None
77 def GetDataObject(self
):
78 return self
.ItemObject
82 # Called if a new section starts
89 # @param Key: to be checked if multi-defined
90 # @param Scope: Format: [[SectionName, Arch], ...].
91 # If scope is none, use global scope
93 def _CheckReDefine(self
, Key
, Scope
= None):
95 Scope
= self
._RawData
.CurrentScope
100 # Copy scope to SecArch, avoid Scope be changed outside
102 SecArch
[0:1] = Scope
[:]
103 if Key
not in self
._ItemDict
:
104 self
._ItemDict
[Key
] = [[SecArch
, self
._RawData
.LineIndex
]]
107 for Value
in self
._ItemDict
[Key
]:
108 for SubValue
in Scope
:
110 # If current is common section
112 if SubValue
[-1] == 'COMMON':
113 for Other
in Value
[0]:
114 # Key in common cannot be redefined in other arches
115 # [:-1] means stripping arch info
116 if Other
[:-1] == SubValue
[:-1]:
117 self
._LoggerError
(ST
.ERR_DECPARSE_REDEFINE
% (Key
, Value
[1]))
121 CommonScope
[0:1] = SubValue
122 CommonScope
[-1] = 'COMMON'
124 # Cannot be redefined if this key already defined in COMMON Or defined in same arch
126 if SubValue
in Value
[0] or CommonScope
in Value
[0]:
127 self
._LoggerError
(ST
.ERR_DECPARSE_REDEFINE
% (Key
, Value
[1]))
129 self
._ItemDict
[Key
].append([SecArch
, self
._RawData
.LineIndex
])
131 ## CheckRequiredFields
132 # Some sections need to check if some fields exist, define section for example
133 # Derived class can re-implement, top parser will call this function after all parsing done
135 def CheckRequiredFields(self
):
141 # In DEC spec, sections must have at least one statement except user
143 # For example: "[guids" [<attribs>] "]" <EOL> <statements>+
144 # sub class can override this method to indicate if statement is a must.
146 def _IsStatementRequired(self
):
151 def _LoggerError(self
, ErrorString
):
152 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
153 Line
= self
._RawData
.LineIndex
,
154 ExtraData
=ErrorString
+ ST
.ERR_DECPARSE_LINE
% self
._RawData
.CurrentLine
)
156 def _ReplaceMacro(self
, String
):
157 if gMACRO_PATTERN
.findall(String
):
158 String
= ReplaceMacro(String
, self
._LocalMacro
, False,
159 FileName
= self
._RawData
.Filename
,
160 Line
= ['', self
._RawData
.LineIndex
])
161 String
= ReplaceMacro(String
, self
._RawData
.Macros
, False,
162 FileName
= self
._RawData
.Filename
,
163 Line
= ['', self
._RawData
.LineIndex
])
164 MacroUsed
= gMACRO_PATTERN
.findall(String
)
166 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
,
167 File
=self
._RawData
.Filename
,
168 Line
= self
._RawData
.LineIndex
,
169 ExtraData
= ST
.ERR_DECPARSE_MACRO_RESOLVE
% (str(MacroUsed
), String
))
172 def _MacroParser(self
, String
):
173 TokenList
= GetSplitValueList(String
, ' ', 1)
174 if len(TokenList
) < 2 or TokenList
[1] == '':
175 self
._LoggerError
(ST
.ERR_DECPARSE_MACRO_PAIR
)
177 TokenList
= GetSplitValueList(TokenList
[1], DT
.TAB_EQUAL_SPLIT
, 1)
178 if TokenList
[0] == '':
179 self
._LoggerError
(ST
.ERR_DECPARSE_MACRO_NAME
)
180 elif not IsValidToken(MACRO_PATTERN
, TokenList
[0]):
181 self
._LoggerError
(ST
.ERR_DECPARSE_MACRO_NAME_UPPER
% TokenList
[0])
183 if len(TokenList
) == 1:
184 self
._LocalMacro
[TokenList
[0]] = ''
186 self
._LocalMacro
[TokenList
[0]] = self
._ReplaceMacro
(TokenList
[1])
190 # Parse specified item, this function must be derived by subclass
192 def _ParseItem(self
):
196 # Should never be called
201 ## _TailCommentStrategy
203 # This function can be derived to parse tail comment
204 # default is it will not consume any lines
206 # @param Comment: Comment of current line
208 def _TailCommentStrategy(self
, Comment
):
215 ## _StopCurrentParsing
217 # Called in Parse if current parsing should be stopped when encounter some
219 # Default is section start and end
221 # @param Line: Current line
223 def _StopCurrentParsing(self
, Line
):
226 return Line
[0] == DT
.TAB_SECTION_START
and Line
[-1] == DT
.TAB_SECTION_END
230 # Split comment and DEC content, concatenate lines if end of char is '\'
232 # @param ProcessedLine: ProcessedLine line
233 # @param ProcessedComments: ProcessedComments line
235 def _TryBackSlash(self
, ProcessedLine
, ProcessedComments
):
239 CommentList
= ProcessedComments
240 while not self
._RawData
.IsEndOfFile():
242 self
._LoggerError
(ST
.ERR_DECPARSE_BACKSLASH_EMPTY
)
246 CommentList
.append((Comment
, self
._RawData
.LineIndex
))
247 if Line
[-1] != DT
.TAB_SLASH
:
250 elif len(Line
) < 2 or Line
[-2] != ' ':
251 self
._LoggerError
(ST
.ERR_DECPARSE_BACKSLASH
)
254 Line
, Comment
= CleanString(self
._RawData
.GetNextLine())
256 # Reach end of content
258 if self
._RawData
.IsEndOfFile():
260 if ProcessedLine
[-1] == DT
.TAB_SLASH
:
261 self
._LoggerError
(ST
.ERR_DECPARSE_BACKSLASH_EMPTY
)
262 CatLine
= ProcessedLine
264 if not Line
or Line
[-1] == DT
.TAB_SLASH
:
265 self
._LoggerError
(ST
.ERR_DECPARSE_BACKSLASH_EMPTY
)
268 self
._RawData
.CurrentLine
= self
._ReplaceMacro
(CatLine
)
269 return CatLine
, CommentList
272 # This is a template method in which other member functions which might
273 # override by sub class are called. It is responsible for reading file
274 # line by line, and call other member functions to parse. This function
275 # should not be re-implement by sub class.
281 #======================================================================
282 # CurComments may pointer to HeadComments or TailComments
283 #======================================================================
284 CurComments
= HeadComments
289 #======================================================================
290 # Used to report error information if empty section found
291 #======================================================================
292 Index
= self
._RawData
.LineIndex
293 LineStr
= self
._RawData
.CurrentLine
294 while not self
._RawData
.IsEndOfFile() or self
._RawData
.NextLine
:
295 if self
._RawData
.NextLine
:
296 #==============================================================
297 # Have processed line in buffer
298 #==============================================================
299 Line
= self
._RawData
.NextLine
300 HeadComments
.extend(self
._RawData
.HeadComment
)
301 TailComments
.extend(self
._RawData
.TailComment
)
302 self
._RawData
.ResetNext()
306 #==============================================================
307 # No line in buffer, read next line
308 #==============================================================
309 Line
, Comment
= CleanString(self
._RawData
.GetNextLine())
312 if not FromBuf
and CurObj
and TailComments
:
313 #==========================================================
314 # Set tail comments to previous statement if not empty.
315 #==========================================================
316 CurObj
.SetTailComment(CurObj
.GetTailComment()+TailComments
)
320 CurComments
= TailComments
323 Comments
= [(Comment
, self
._RawData
.LineIndex
)]
325 #==============================================================
326 # Try if last char of line has backslash
327 #==============================================================
328 Line
, Comments
= self
._TryBackSlash
(Line
, Comments
)
329 CurComments
.extend(Comments
)
331 #==============================================================
333 #==============================================================
334 if Line
.startswith('DEFINE '):
335 self
._MacroParser
(Line
)
338 CurComments
= HeadComments
341 if self
._StopCurrentParsing
(Line
):
342 #==========================================================
343 # This line does not belong to this parse,
344 # Save it, can be used by next parse
345 #==========================================================
346 self
._RawData
.SetNext(Line
, HeadComments
, TailComments
)
349 Obj
= self
._ParseItem
()
352 Obj
.SetHeadComment(Obj
.GetHeadComment()+HeadComments
)
353 Obj
.SetTailComment(Obj
.GetTailComment()+TailComments
)
360 if id(CurComments
) == id(TailComments
):
361 #==========================================================
362 # Check if this comment belongs to tail comment
363 #==========================================================
364 if not self
._TailCommentStrategy
(Comment
):
365 CurComments
= HeadComments
368 CurComments
.append(((Comment
, self
._RawData
.LineIndex
)))
372 if self
._IsStatementRequired
() and ItemNum
== 0:
374 TOOL_NAME
, FILE_PARSE_FAILURE
,
375 File
=self
._RawData
.Filename
,
377 ExtraData
=ST
.ERR_DECPARSE_STATEMENT_EMPTY
% LineStr
381 # Parse define section
383 class _DecDefine(_DecBase
):
384 def __init__(self
, RawData
):
385 _DecBase
.__init
__(self
, RawData
)
386 self
.ItemObject
= DecDefineObject(RawData
.Filename
)
387 self
._LocalMacro
= self
._RawData
.Macros
391 # Each field has a function to validate
393 self
.DefineValidation
= {
394 DT
.TAB_DEC_DEFINES_DEC_SPECIFICATION
: self
._SetDecSpecification
,
395 DT
.TAB_DEC_DEFINES_PACKAGE_NAME
: self
._SetPackageName
,
396 DT
.TAB_DEC_DEFINES_PACKAGE_GUID
: self
._SetPackageGuid
,
397 DT
.TAB_DEC_DEFINES_PACKAGE_VERSION
: self
._SetPackageVersion
,
400 def BlockStart(self
):
402 if self
._DefSecNum
> 1:
403 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_MULTISEC
)
405 ## CheckRequiredFields
407 # Check required fields: DEC_SPECIFICATION, PACKAGE_NAME
408 # PACKAGE_GUID, PACKAGE_VERSION
410 def CheckRequiredFields(self
):
412 if self
.ItemObject
.GetPackageSpecification() == '':
413 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
414 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_DEC_SPECIFICATION
)
415 elif self
.ItemObject
.GetPackageName() == '':
416 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
417 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_PACKAGE_NAME
)
418 elif self
.ItemObject
.GetPackageGuid() == '':
419 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
420 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_PACKAGE_GUID
)
421 elif self
.ItemObject
.GetPackageVersion() == '':
422 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
423 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_PACKAGE_VERSION
)
428 def _ParseItem(self
):
429 Line
= self
._RawData
.CurrentLine
430 TokenList
= GetSplitValueList(Line
, DT
.TAB_EQUAL_SPLIT
, 1)
431 if TokenList
[0] == DT
.TAB_DEC_DEFINES_PKG_UNI_FILE
:
433 elif len(TokenList
) < 2:
434 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_FORMAT
)
435 elif TokenList
[0] not in self
.DefineValidation
:
436 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_UNKNOWKEY
% TokenList
[0])
438 self
.DefineValidation
[TokenList
[0]](TokenList
[1])
440 DefineItem
= DecDefineItemObject()
441 if TokenList
[0] != DT
.TAB_DEC_DEFINES_PKG_UNI_FILE
:
442 DefineItem
.Key
= TokenList
[0]
443 DefineItem
.Value
= TokenList
[1]
444 self
.ItemObject
.AddItem(DefineItem
, self
._RawData
.CurrentScope
)
447 def _SetDecSpecification(self
, Token
):
448 if self
.ItemObject
.GetPackageSpecification():
449 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_DEC_SPECIFICATION
)
450 if not IsValidToken('0[xX][0-9a-fA-F]{8}', Token
):
451 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_SPEC
)
452 self
.ItemObject
.SetPackageSpecification(Token
)
454 def _SetPackageName(self
, Token
):
455 if self
.ItemObject
.GetPackageName():
456 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PACKAGE_NAME
)
457 if not IsValidWord(Token
):
458 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGNAME
)
459 self
.ItemObject
.SetPackageName(Token
)
461 def _SetPackageGuid(self
, Token
):
462 if self
.ItemObject
.GetPackageGuid():
463 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PACKAGE_GUID
)
464 if not CheckGuidRegFormat(Token
):
465 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGGUID
)
466 self
.ItemObject
.SetPackageGuid(Token
)
468 def _SetPackageVersion(self
, Token
):
469 if self
.ItemObject
.GetPackageVersion():
470 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PACKAGE_VERSION
)
471 if not IsValidToken(VERSION_PATTERN
, Token
):
472 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGVERSION
)
474 if not DT
.TAB_SPLIT
in Token
:
476 self
.ItemObject
._PkgVersion
= Token
480 # Parse include section
482 class _DecInclude(_DecBase
):
483 def __init__(self
, RawData
):
484 _DecBase
.__init
__(self
, RawData
)
485 self
.ItemObject
= DecIncludeObject(RawData
.Filename
)
487 def _ParseItem(self
):
488 Line
= self
._RawData
.CurrentLine
490 if not IsValidPath(Line
, self
._RawData
.PackagePath
):
491 self
._LoggerError
(ST
.ERR_DECPARSE_INCLUDE
% Line
)
493 Item
= DecIncludeItemObject(StripRoot(self
._RawData
.PackagePath
, Line
), self
._RawData
.PackagePath
)
494 self
.ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
499 # Parse library class section
501 class _DecLibraryclass(_DecBase
):
502 def __init__(self
, RawData
):
503 _DecBase
.__init
__(self
, RawData
)
504 self
.ItemObject
= DecLibraryclassObject(RawData
.Filename
)
506 def _ParseItem(self
):
507 Line
= self
._RawData
.CurrentLine
508 TokenList
= GetSplitValueList(Line
, DT
.TAB_VALUE_SPLIT
)
509 if len(TokenList
) != 2:
510 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_SPLIT
)
511 if TokenList
[0] == '' or TokenList
[1] == '':
512 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_EMPTY
)
513 if not IsValidToken('[A-Z][0-9A-Za-z]*', TokenList
[0]):
514 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_LIB
)
516 self
._CheckReDefine
(TokenList
[0])
522 if not Value
.endswith('.h'):
523 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_PATH_EXT
)
526 # Path must be existed
528 if not IsValidPath(Value
, self
._RawData
.PackagePath
):
529 self
._LoggerError
(ST
.ERR_DECPARSE_INCLUDE
% Value
)
531 Item
= DecLibraryclassItemObject(TokenList
[0], StripRoot(self
._RawData
.PackagePath
, Value
),
532 self
._RawData
.PackagePath
)
533 self
.ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
540 class _DecPcd(_DecBase
):
541 def __init__(self
, RawData
):
542 _DecBase
.__init
__(self
, RawData
)
543 self
.ItemObject
= DecPcdObject(RawData
.Filename
)
545 # Used to check duplicate token
546 # Key is token space and token number (integer), value is C name
550 def _ParseItem(self
):
551 Line
= self
._RawData
.CurrentLine
552 TokenList
= Line
.split(DT
.TAB_VALUE_SPLIT
)
553 if len(TokenList
) < 4:
554 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_SPLIT
)
557 # Token space guid C name
559 PcdName
= GetSplitValueList(TokenList
[0], DT
.TAB_SPLIT
)
560 if len(PcdName
) != 2 or PcdName
[0] == '' or PcdName
[1] == '':
561 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_NAME
)
564 if not IsValidToken(CVAR_PATTERN
, Guid
):
565 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_CVAR_GUID
)
571 if not IsValidToken(CVAR_PATTERN
, CName
):
572 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_CVAR_PCDCNAME
)
574 self
._CheckReDefine
(Guid
+ DT
.TAB_SPLIT
+ CName
)
577 # Default value, may be C array, string or number
579 Data
= DT
.TAB_VALUE_SPLIT
.join(TokenList
[1:-2]).strip()
584 DataType
= TokenList
[-2].strip()
585 Valid
, Cause
= IsValidPcdDatum(DataType
, Data
)
587 self
._LoggerError
(Cause
)
588 PcdType
= self
._RawData
.CurrentScope
[0][0]
589 if PcdType
== DT
.TAB_PCDS_FEATURE_FLAG_NULL
.upper() and DataType
!= 'BOOLEAN':
590 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_FEATUREFLAG
)
592 # Token value is the last element in list.
594 Token
= TokenList
[-1].strip()
595 if not IsValidToken(PCD_TOKEN_PATTERN
, Token
):
596 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_TOKEN
% Token
)
597 elif not Token
.startswith('0x') and not Token
.startswith('0X'):
598 if long(Token
) > 4294967295:
599 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_TOKEN_INT
% Token
)
600 Token
= hex(long(Token
))[:-1]
602 IntToken
= long(Token
, 0)
603 if (Guid
, IntToken
) in self
.TokenMap
:
604 if self
.TokenMap
[Guid
, IntToken
] != CName
:
605 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_TOKEN_UNIQUE
%(Token))
607 self
.TokenMap
[Guid
, IntToken
] = CName
609 Item
= DecPcdItemObject(Guid
, CName
, Data
, DataType
, Token
)
610 self
.ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
615 # Parse GUID, PPI, Protocol section
617 class _DecGuid(_DecBase
):
618 def __init__(self
, RawData
):
619 _DecBase
.__init
__(self
, RawData
)
620 self
.GuidObj
= DecGuidObject(RawData
.Filename
)
621 self
.PpiObj
= DecPpiObject(RawData
.Filename
)
622 self
.ProtocolObj
= DecProtocolObject(RawData
.Filename
)
625 DT
.TAB_GUIDS
.upper() : self
.GuidObj
,
626 DT
.TAB_PPIS
.upper() : self
.PpiObj
,
627 DT
.TAB_PROTOCOLS
.upper() : self
.ProtocolObj
630 def GetDataObject(self
):
631 if self
._RawData
.CurrentScope
:
632 return self
.ObjectDict
[self
._RawData
.CurrentScope
[0][0]]
635 def GetGuidObject(self
):
638 def GetPpiObject(self
):
641 def GetProtocolObject(self
):
642 return self
.ProtocolObj
644 def _ParseItem(self
):
645 Line
= self
._RawData
.CurrentLine
646 TokenList
= GetSplitValueList(Line
, DT
.TAB_EQUAL_SPLIT
, 1)
647 if len(TokenList
) < 2:
648 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID
)
649 if TokenList
[0] == '':
650 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_NAME
)
651 if TokenList
[1] == '':
652 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_GUID
)
653 if not IsValidToken(CVAR_PATTERN
, TokenList
[0]):
654 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_CVAR_GUID
)
656 self
._CheckReDefine
(TokenList
[0])
658 if TokenList
[1][0] != '{':
659 if not CheckGuidRegFormat(TokenList
[1]):
660 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGGUID
)
661 GuidString
= TokenList
[1]
664 # Convert C format GUID to GUID string and Simple error check
666 GuidString
= GuidStructureStringToGuidString(TokenList
[1])
667 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidString
== '':
668 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_GUIDFORMAT
)
671 # Check C format GUID
673 if not IsValidCFormatGuid(TokenList
[1]):
674 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_GUIDFORMAT
)
676 Item
= DecGuidItemObject(TokenList
[0], TokenList
[1], GuidString
)
677 ItemObject
= self
.ObjectDict
[self
._RawData
.CurrentScope
[0][0]]
678 ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
683 # Parse user extention section
685 class _DecUserExtension(_DecBase
):
686 def __init__(self
, RawData
):
687 _DecBase
.__init
__(self
, RawData
)
688 self
.ItemObject
= DecUserExtensionObject(RawData
.Filename
)
692 def BlockStart(self
):
694 for Header
in self
._RawData
.CurrentScope
:
695 if Header
in self
._Headers
:
696 self
._LoggerError
(ST
.ERR_DECPARSE_UE_DUPLICATE
)
698 self
._Headers
.append(Header
)
700 for Item
in self
._CurItems
:
701 if Item
.UserId
== Header
[1] and Item
.IdString
== Header
[2]:
702 Item
.ArchAndModuleType
.append(Header
[3])
705 Item
= DecUserExtensionItemObject()
706 Item
.UserId
= Header
[1]
707 Item
.IdString
= Header
[2]
708 Item
.ArchAndModuleType
.append(Header
[3])
709 self
._CurItems
.append(Item
)
710 self
.ItemObject
.AddItem(Item
, None)
711 self
._LocalMacro
= {}
713 def _ParseItem(self
):
714 Line
= self
._RawData
.CurrentLine
716 for Item
in self
._CurItems
:
718 Item
.UserString
= '\n'.join([Item
.UserString
, Line
])
720 Item
.UserString
= Line
727 class Dec(_DecBase
, _DecComments
):
728 def __init__(self
, DecFile
, Parse
= True):
730 Content
= ConvertSpecialChar(open(DecFile
, 'rb').readlines())
731 except BaseException
:
732 Logger
.Error(TOOL_NAME
, FILE_OPEN_FAILURE
, File
=DecFile
,
733 ExtraData
=ST
.ERR_DECPARSE_FILEOPEN
% DecFile
)
734 RawData
= FileContent(DecFile
, Content
)
736 _DecComments
.__init
__(self
)
737 _DecBase
.__init
__(self
, RawData
)
739 self
.BinaryHeadComment
= []
740 self
._Define
= _DecDefine(RawData
)
741 self
._Include
= _DecInclude(RawData
)
742 self
._Guid
= _DecGuid(RawData
)
743 self
._LibClass
= _DecLibraryclass(RawData
)
744 self
._Pcd
= _DecPcd(RawData
)
745 self
._UserEx
= _DecUserExtension(RawData
)
748 # DEC file supported data types (one type per section)
750 self
._SectionParser
= {
751 DT
.TAB_DEC_DEFINES
.upper() : self
._Define
,
752 DT
.TAB_INCLUDES
.upper() : self
._Include
,
753 DT
.TAB_LIBRARY_CLASSES
.upper() : self
._LibClass
,
754 DT
.TAB_GUIDS
.upper() : self
._Guid
,
755 DT
.TAB_PPIS
.upper() : self
._Guid
,
756 DT
.TAB_PROTOCOLS
.upper() : self
._Guid
,
757 DT
.TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : self
._Pcd
,
758 DT
.TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : self
._Pcd
,
759 DT
.TAB_PCDS_FEATURE_FLAG_NULL
.upper() : self
._Pcd
,
760 DT
.TAB_PCDS_DYNAMIC_NULL
.upper() : self
._Pcd
,
761 DT
.TAB_PCDS_DYNAMIC_EX_NULL
.upper() : self
._Pcd
,
762 DT
.TAB_USER_EXTENSIONS
.upper() : self
._UserEx
766 self
.ParseDecComment()
769 # Parsing done, check required fields
771 self
.CheckRequiredFields()
773 def CheckRequiredFields(self
):
774 for SectionParser
in self
._SectionParser
.values():
775 if not SectionParser
.CheckRequiredFields():
782 def ParseDecComment(self
):
784 IsBinaryHeader
= False
785 FileHeaderLineIndex
= -1
786 BinaryHeaderLineIndex
= -1
787 while not self
._RawData
.IsEndOfFile():
788 Line
, Comment
= CleanString(self
._RawData
.GetNextLine())
791 # Header must be pure comment
794 self
._RawData
.UndoNextLine()
797 if Comment
and Comment
.startswith(DT
.TAB_SPECIAL_COMMENT
) and Comment
.find(DT
.TAB_HEADER_COMMENT
) > 0 \
798 and not Comment
[2:Comment
.find(DT
.TAB_HEADER_COMMENT
)].strip():
800 IsBinaryHeader
= False
801 FileHeaderLineIndex
= self
._RawData
.LineIndex
804 # Get license information before '@file'
806 if not IsFileHeader
and not IsBinaryHeader
and Comment
and Comment
.startswith(DT
.TAB_COMMENT_SPLIT
) and \
807 DT
.TAB_BINARY_HEADER_COMMENT
not in Comment
:
808 self
._HeadComment
.append((Comment
, self
._RawData
.LineIndex
))
810 if Comment
and IsFileHeader
and \
811 not(Comment
.startswith(DT
.TAB_SPECIAL_COMMENT
) \
812 and Comment
.find(DT
.TAB_BINARY_HEADER_COMMENT
) > 0):
813 self
._HeadComment
.append((Comment
, self
._RawData
.LineIndex
))
815 # Double '#' indicates end of header comments
817 if (not Comment
or Comment
== DT
.TAB_SPECIAL_COMMENT
) and IsFileHeader
:
821 if Comment
and Comment
.startswith(DT
.TAB_SPECIAL_COMMENT
) \
822 and Comment
.find(DT
.TAB_BINARY_HEADER_COMMENT
) > 0:
823 IsBinaryHeader
= True
825 BinaryHeaderLineIndex
= self
._RawData
.LineIndex
827 if Comment
and IsBinaryHeader
:
828 self
.BinaryHeadComment
.append((Comment
, self
._RawData
.LineIndex
))
830 # Double '#' indicates end of header comments
832 if (not Comment
or Comment
== DT
.TAB_SPECIAL_COMMENT
) and IsBinaryHeader
:
833 IsBinaryHeader
= False
836 if FileHeaderLineIndex
> -1 and not IsFileHeader
and not IsBinaryHeader
:
839 if FileHeaderLineIndex
> BinaryHeaderLineIndex
and FileHeaderLineIndex
> -1 and BinaryHeaderLineIndex
> -1:
840 self
._LoggerError
(ST
.ERR_BINARY_HEADER_ORDER
)
842 if FileHeaderLineIndex
== -1:
843 Logger
.Error(TOOL_NAME
, FORMAT_INVALID
,
844 ST
.ERR_NO_SOURCE_HEADER
,
845 File
=self
._RawData
.Filename
)
848 def _StopCurrentParsing(self
, Line
):
851 def _ParseItem(self
):
852 self
._SectionHeaderParser
()
853 if len(self
._RawData
.CurrentScope
) == 0:
854 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_EMPTY
)
856 SectionObj
= self
._SectionParser
[self
._RawData
.CurrentScope
[0][0]]
858 SectionObj
.BlockStart()
861 return SectionObj
.GetDataObject()
863 def _UserExtentionSectionParser(self
):
864 self
._RawData
.CurrentScope
= []
866 Section
= self
._RawData
.CurrentLine
[1:-1]
868 Par
= ParserHelper(Section
, self
._RawData
.Filename
)
873 Token
= Par
.GetToken()
874 if Token
.upper() != DT
.TAB_USER_EXTENSIONS
.upper():
875 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE
)
876 UserExtension
= Token
.upper()
878 Par
.AssertChar(DT
.TAB_SPLIT
, ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
882 Token
= Par
.GetToken()
883 if not IsValidUserId(Token
):
884 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE_USERID
)
887 Par
.AssertChar(DT
.TAB_SPLIT
, ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
891 Token
= Par
.GetToken()
892 if not IsValidIdString(Token
):
893 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE_IDSTRING
)
897 if Par
.Expect(DT
.TAB_SPLIT
):
898 Token
= Par
.GetToken()
900 if not IsValidArch(Arch
):
901 self
._LoggerError
(ST
.ERR_DECPARSE_ARCH
)
904 if [UserExtension
, UserId
, IdString
, Arch
] not in \
905 self
._RawData
.CurrentScope
:
906 self
._RawData
.CurrentScope
.append(
907 [UserExtension
, UserId
, IdString
, Arch
]
910 if not Par
.Expect(DT
.TAB_COMMA_SPLIT
):
913 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMA
)
915 Par
.AssertEnd(ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
917 if 'COMMON' in ArchList
and len(ArchList
) > 1:
918 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMON
)
920 ## Section header parser
922 # The section header is always in following format:
924 # [section_name.arch<.platform|module_type>]
926 def _SectionHeaderParser(self
):
927 if self
._RawData
.CurrentLine
[0] != DT
.TAB_SECTION_START
or self
._RawData
.CurrentLine
[-1] != DT
.TAB_SECTION_END
:
928 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_IDENTIFY
)
930 RawSection
= self
._RawData
.CurrentLine
[1:-1].strip().upper()
933 # Check defines section which is only allowed to occur once and
934 # no arch can be followed
936 if RawSection
.startswith(DT
.TAB_DEC_DEFINES
.upper()):
937 if RawSection
!= DT
.TAB_DEC_DEFINES
.upper():
938 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_SECNAME
)
941 # Check user extension section
943 if RawSection
.startswith(DT
.TAB_USER_EXTENSIONS
.upper()):
944 return self
._UserExtentionSectionParser
()
946 self
._RawData
.CurrentScope
= []
949 for Item
in GetSplitValueList(RawSection
, DT
.TAB_COMMA_SPLIT
):
951 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBEMPTY
% self
._RawData
.CurrentLine
)
953 ItemList
= GetSplitValueList(Item
, DT
.TAB_SPLIT
)
956 # different types of PCD are permissible in one section
958 SectionName
= ItemList
[0]
959 if SectionName
not in self
._SectionParser
:
960 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UNKNOW
% SectionName
)
962 if SectionName
not in SectionNames
:
963 SectionNames
.append(SectionName
)
966 # In DEC specification, all section headers have at most two part:
967 # SectionName.Arch except UserExtention
969 if len(ItemList
) > 2:
970 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBTOOMANY
% Item
)
972 if DT
.TAB_PCDS_FEATURE_FLAG_NULL
.upper() in SectionNames
and len(SectionNames
) > 1:
973 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_FEATUREFLAG
% DT
.TAB_PCDS_FEATURE_FLAG_NULL
)
977 if len(ItemList
) > 1:
979 if not IsValidArch(Str1
):
980 self
._LoggerError
(ST
.ERR_DECPARSE_ARCH
)
985 if [SectionName
, Str1
] not in self
._RawData
.CurrentScope
:
986 self
._RawData
.CurrentScope
.append([SectionName
, Str1
])
988 # 'COMMON' must not be used with specific ARCHs at the same section
990 if 'COMMON' in ArchList
and len(ArchList
) > 1:
991 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMON
)
993 if len(SectionNames
) == 0:
994 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBEMPTY
% self
._RawData
.CurrentLine
)
995 if len(SectionNames
) != 1:
996 for Sec
in SectionNames
:
997 if not Sec
.startswith(DT
.TAB_PCDS
.upper()):
998 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_NAME
% str(SectionNames
))
1000 def GetDefineSectionObject(self
):
1001 return self
._Define
.GetDataObject()
1003 def GetIncludeSectionObject(self
):
1004 return self
._Include
.GetDataObject()
1006 def GetGuidSectionObject(self
):
1007 return self
._Guid
.GetGuidObject()
1009 def GetProtocolSectionObject(self
):
1010 return self
._Guid
.GetProtocolObject()
1012 def GetPpiSectionObject(self
):
1013 return self
._Guid
.GetPpiObject()
1015 def GetLibraryClassSectionObject(self
):
1016 return self
._LibClass
.GetDataObject()
1018 def GetPcdSectionObject(self
):
1019 return self
._Pcd
.GetDataObject()
1021 def GetUserExtensionSectionObject(self
):
1022 return self
._UserEx
.GetDataObject()
1024 def GetPackageSpecification(self
):
1025 return self
._Define
.GetDataObject().GetPackageSpecification()
1027 def GetPackageName(self
):
1028 return self
._Define
.GetDataObject().GetPackageName()
1030 def GetPackageGuid(self
):
1031 return self
._Define
.GetDataObject().GetPackageGuid()
1033 def GetPackageVersion(self
):
1034 return self
._Define
.GetDataObject().GetPackageVersion()
1036 def GetPackageUniFile(self
):
1037 return self
._Define
.GetDataObject().GetPackageUniFile()