2 # This file is used to parse DEC file. It will consumed by DecParser
4 # Copyright (c) 2011 - 2014, 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
)
745 RawData
= FileContent(DecFile
, Content
)
747 _DecComments
.__init
__(self
)
748 _DecBase
.__init
__(self
, RawData
)
750 self
.BinaryHeadComment
= []
751 self
.PcdErrorCommentDict
= {}
753 self
._Define
= _DecDefine(RawData
)
754 self
._Include
= _DecInclude(RawData
)
755 self
._Guid
= _DecGuid(RawData
)
756 self
._LibClass
= _DecLibraryclass(RawData
)
757 self
._Pcd
= _DecPcd(RawData
)
758 self
._UserEx
= _DecUserExtension(RawData
)
761 # DEC file supported data types (one type per section)
763 self
._SectionParser
= {
764 DT
.TAB_DEC_DEFINES
.upper() : self
._Define
,
765 DT
.TAB_INCLUDES
.upper() : self
._Include
,
766 DT
.TAB_LIBRARY_CLASSES
.upper() : self
._LibClass
,
767 DT
.TAB_GUIDS
.upper() : self
._Guid
,
768 DT
.TAB_PPIS
.upper() : self
._Guid
,
769 DT
.TAB_PROTOCOLS
.upper() : self
._Guid
,
770 DT
.TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : self
._Pcd
,
771 DT
.TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : self
._Pcd
,
772 DT
.TAB_PCDS_FEATURE_FLAG_NULL
.upper() : self
._Pcd
,
773 DT
.TAB_PCDS_DYNAMIC_NULL
.upper() : self
._Pcd
,
774 DT
.TAB_PCDS_DYNAMIC_EX_NULL
.upper() : self
._Pcd
,
775 DT
.TAB_USER_EXTENSIONS
.upper() : self
._UserEx
779 self
.ParseDecComment()
782 # Parsing done, check required fields
784 self
.CheckRequiredFields()
786 def CheckRequiredFields(self
):
787 for SectionParser
in self
._SectionParser
.values():
788 if not SectionParser
.CheckRequiredFields():
795 def ParseDecComment(self
):
797 IsBinaryHeader
= False
798 FileHeaderLineIndex
= -1
799 BinaryHeaderLineIndex
= -1
800 TokenSpaceGuidCName
= ''
803 # Parse PCD error comment section
805 while not self
._RawData
.IsEndOfFile():
806 self
._RawData
.CurrentLine
= self
._RawData
.GetNextLine()
807 if self
._RawData
.CurrentLine
.startswith(DT
.TAB_COMMENT_SPLIT
) and \
808 DT
.TAB_SECTION_START
in self
._RawData
.CurrentLine
and \
809 DT
.TAB_SECTION_END
in self
._RawData
.CurrentLine
:
810 self
._RawData
.CurrentLine
= self
._RawData
.CurrentLine
.replace(DT
.TAB_COMMENT_SPLIT
, '').strip()
812 if self
._RawData
.CurrentLine
[0] == DT
.TAB_SECTION_START
and \
813 self
._RawData
.CurrentLine
[-1] == DT
.TAB_SECTION_END
:
814 RawSection
= self
._RawData
.CurrentLine
[1:-1].strip()
815 if RawSection
.upper().startswith(DT
.TAB_PCD_ERROR
.upper()+'.'):
816 TokenSpaceGuidCName
= RawSection
.split(DT
.TAB_PCD_ERROR
+'.')[1].strip()
819 if TokenSpaceGuidCName
and self
._RawData
.CurrentLine
.startswith(DT
.TAB_COMMENT_SPLIT
):
820 self
._RawData
.CurrentLine
= self
._RawData
.CurrentLine
.replace(DT
.TAB_COMMENT_SPLIT
, '').strip()
821 if self
._RawData
.CurrentLine
!= '':
822 if DT
.TAB_VALUE_SPLIT
not in self
._RawData
.CurrentLine
:
823 self
._LoggerError
(ST
.ERR_DECPARSE_PCDERRORMSG_MISS_VALUE_SPLIT
)
825 PcdErrorNumber
, PcdErrorMsg
= GetSplitValueList(self
._RawData
.CurrentLine
, DT
.TAB_VALUE_SPLIT
, 1)
826 PcdErrorNumber
= ParsePcdErrorCode(PcdErrorNumber
, self
._RawData
.Filename
, self
._RawData
.LineIndex
)
827 if not PcdErrorMsg
.strip():
828 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_MISS_ERRORMSG
)
830 self
.PcdErrorCommentDict
[(TokenSpaceGuidCName
, PcdErrorNumber
)] = PcdErrorMsg
.strip()
832 TokenSpaceGuidCName
= ''
834 self
._RawData
.LineIndex
= 0
835 self
._RawData
.CurrentLine
= ''
836 self
._RawData
.NextLine
= ''
838 while not self
._RawData
.IsEndOfFile():
839 Line
, Comment
= CleanString(self
._RawData
.GetNextLine())
842 # Header must be pure comment
845 self
._RawData
.UndoNextLine()
848 if Comment
and Comment
.startswith(DT
.TAB_SPECIAL_COMMENT
) and Comment
.find(DT
.TAB_HEADER_COMMENT
) > 0 \
849 and not Comment
[2:Comment
.find(DT
.TAB_HEADER_COMMENT
)].strip():
851 IsBinaryHeader
= False
852 FileHeaderLineIndex
= self
._RawData
.LineIndex
855 # Get license information before '@file'
857 if not IsFileHeader
and not IsBinaryHeader
and Comment
and Comment
.startswith(DT
.TAB_COMMENT_SPLIT
) and \
858 DT
.TAB_BINARY_HEADER_COMMENT
not in Comment
:
859 self
._HeadComment
.append((Comment
, self
._RawData
.LineIndex
))
861 if Comment
and IsFileHeader
and \
862 not(Comment
.startswith(DT
.TAB_SPECIAL_COMMENT
) \
863 and Comment
.find(DT
.TAB_BINARY_HEADER_COMMENT
) > 0):
864 self
._HeadComment
.append((Comment
, self
._RawData
.LineIndex
))
866 # Double '#' indicates end of header comments
868 if (not Comment
or Comment
== DT
.TAB_SPECIAL_COMMENT
) and IsFileHeader
:
872 if Comment
and Comment
.startswith(DT
.TAB_SPECIAL_COMMENT
) \
873 and Comment
.find(DT
.TAB_BINARY_HEADER_COMMENT
) > 0:
874 IsBinaryHeader
= True
876 BinaryHeaderLineIndex
= self
._RawData
.LineIndex
878 if Comment
and IsBinaryHeader
:
879 self
.BinaryHeadComment
.append((Comment
, self
._RawData
.LineIndex
))
881 # Double '#' indicates end of header comments
883 if (not Comment
or Comment
== DT
.TAB_SPECIAL_COMMENT
) and IsBinaryHeader
:
884 IsBinaryHeader
= False
887 if FileHeaderLineIndex
> -1 and not IsFileHeader
and not IsBinaryHeader
:
890 if FileHeaderLineIndex
> BinaryHeaderLineIndex
and FileHeaderLineIndex
> -1 and BinaryHeaderLineIndex
> -1:
891 self
._LoggerError
(ST
.ERR_BINARY_HEADER_ORDER
)
893 if FileHeaderLineIndex
== -1:
894 # self._LoggerError(ST.ERR_NO_SOURCE_HEADER)
895 Logger
.Error(TOOL_NAME
, FORMAT_INVALID
,
896 ST
.ERR_NO_SOURCE_HEADER
,
897 File
=self
._RawData
.Filename
)
900 def _StopCurrentParsing(self
, Line
):
903 def _ParseItem(self
):
904 self
._SectionHeaderParser
()
905 if len(self
._RawData
.CurrentScope
) == 0:
906 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_EMPTY
)
907 SectionObj
= self
._SectionParser
[self
._RawData
.CurrentScope
[0][0]]
908 SectionObj
.BlockStart()
910 return SectionObj
.GetDataObject()
912 def _UserExtentionSectionParser(self
):
913 self
._RawData
.CurrentScope
= []
915 Section
= self
._RawData
.CurrentLine
[1:-1]
916 Par
= ParserHelper(Section
, self
._RawData
.Filename
)
921 Token
= Par
.GetToken()
922 if Token
.upper() != DT
.TAB_USER_EXTENSIONS
.upper():
923 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE
)
924 UserExtension
= Token
.upper()
925 Par
.AssertChar(DT
.TAB_SPLIT
, ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
930 Token
= Par
.GetToken()
931 if not IsValidUserId(Token
):
932 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE_USERID
)
934 Par
.AssertChar(DT
.TAB_SPLIT
, ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
938 Token
= Par
.GetToken()
939 if not IsValidIdString(Token
):
940 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE_IDSTRING
)
943 if Par
.Expect(DT
.TAB_SPLIT
):
944 Token
= Par
.GetToken()
946 if not IsValidArch(Arch
):
947 self
._LoggerError
(ST
.ERR_DECPARSE_ARCH
)
949 if [UserExtension
, UserId
, IdString
, Arch
] not in \
950 self
._RawData
.CurrentScope
:
951 self
._RawData
.CurrentScope
.append(
952 [UserExtension
, UserId
, IdString
, Arch
]
954 if not Par
.Expect(DT
.TAB_COMMA_SPLIT
):
957 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMA
)
958 Par
.AssertEnd(ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
959 if 'COMMON' in ArchList
and len(ArchList
) > 1:
960 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMON
)
962 ## Section header parser
964 # The section header is always in following format:
966 # [section_name.arch<.platform|module_type>]
968 def _SectionHeaderParser(self
):
969 if self
._RawData
.CurrentLine
[0] != DT
.TAB_SECTION_START
or self
._RawData
.CurrentLine
[-1] != DT
.TAB_SECTION_END
:
970 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_IDENTIFY
)
972 RawSection
= self
._RawData
.CurrentLine
[1:-1].strip().upper()
974 # Check defines section which is only allowed to occur once and
975 # no arch can be followed
977 if RawSection
.startswith(DT
.TAB_DEC_DEFINES
.upper()):
978 if RawSection
!= DT
.TAB_DEC_DEFINES
.upper():
979 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_SECNAME
)
981 # Check user extension section
983 if RawSection
.startswith(DT
.TAB_USER_EXTENSIONS
.upper()):
984 return self
._UserExtentionSectionParser
()
985 self
._RawData
.CurrentScope
= []
988 for Item
in GetSplitValueList(RawSection
, DT
.TAB_COMMA_SPLIT
):
990 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBEMPTY
% self
._RawData
.CurrentLine
)
992 ItemList
= GetSplitValueList(Item
, DT
.TAB_SPLIT
)
994 # different types of PCD are permissible in one section
996 SectionName
= ItemList
[0]
997 if SectionName
not in self
._SectionParser
:
998 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UNKNOW
% SectionName
)
999 if SectionName
not in SectionNames
:
1000 SectionNames
.append(SectionName
)
1002 # In DEC specification, all section headers have at most two part:
1003 # SectionName.Arch except UserExtention
1005 if len(ItemList
) > 2:
1006 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBTOOMANY
% Item
)
1008 if DT
.TAB_PCDS_FEATURE_FLAG_NULL
.upper() in SectionNames
and len(SectionNames
) > 1:
1009 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_FEATUREFLAG
% DT
.TAB_PCDS_FEATURE_FLAG_NULL
)
1013 if len(ItemList
) > 1:
1015 if not IsValidArch(Str1
):
1016 self
._LoggerError
(ST
.ERR_DECPARSE_ARCH
)
1021 if [SectionName
, Str1
] not in self
._RawData
.CurrentScope
:
1022 self
._RawData
.CurrentScope
.append([SectionName
, Str1
])
1024 # 'COMMON' must not be used with specific ARCHs at the same section
1026 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1027 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMON
)
1028 if len(SectionNames
) == 0:
1029 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBEMPTY
% self
._RawData
.CurrentLine
)
1030 if len(SectionNames
) != 1:
1031 for Sec
in SectionNames
:
1032 if not Sec
.startswith(DT
.TAB_PCDS
.upper()):
1033 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_NAME
% str(SectionNames
))
1035 def GetDefineSectionMacro(self
):
1036 return self
._Define
.GetLocalMacro()
1037 def GetDefineSectionObject(self
):
1038 return self
._Define
.GetDataObject()
1039 def GetIncludeSectionObject(self
):
1040 return self
._Include
.GetDataObject()
1041 def GetGuidSectionObject(self
):
1042 return self
._Guid
.GetGuidObject()
1043 def GetProtocolSectionObject(self
):
1044 return self
._Guid
.GetProtocolObject()
1045 def GetPpiSectionObject(self
):
1046 return self
._Guid
.GetPpiObject()
1047 def GetLibraryClassSectionObject(self
):
1048 return self
._LibClass
.GetDataObject()
1049 def GetPcdSectionObject(self
):
1050 return self
._Pcd
.GetDataObject()
1051 def GetUserExtensionSectionObject(self
):
1052 return self
._UserEx
.GetDataObject()
1053 def GetPackageSpecification(self
):
1054 return self
._Define
.GetDataObject().GetPackageSpecification()
1055 def GetPackageName(self
):
1056 return self
._Define
.GetDataObject().GetPackageName()
1057 def GetPackageGuid(self
):
1058 return self
._Define
.GetDataObject().GetPackageGuid()
1059 def GetPackageVersion(self
):
1060 return self
._Define
.GetDataObject().GetPackageVersion()
1061 def GetPackageUniFile(self
):
1062 return self
._Define
.GetDataObject().GetPackageUniFile()