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 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
63 from Library
.CommentParsing
import ParsePcdErrorCode
66 # _DecBase class for parsing
69 def __init__(self
, RawData
):
70 self
._RawData
= RawData
74 # Data parsed by 'self' are saved to this object
76 self
.ItemObject
= None
78 def GetDataObject(self
):
79 return self
.ItemObject
81 def GetLocalMacro(self
):
82 return self
._LocalMacro
86 # Called if a new section starts
93 # @param Key: to be checked if multi-defined
94 # @param Scope: Format: [[SectionName, Arch], ...].
95 # If scope is none, use global scope
97 def _CheckReDefine(self
, Key
, Scope
= None):
99 Scope
= self
._RawData
.CurrentScope
104 # Copy scope to SecArch, avoid Scope be changed outside
106 SecArch
[0:1] = Scope
[:]
107 if Key
not in self
._ItemDict
:
108 self
._ItemDict
[Key
] = [[SecArch
, self
._RawData
.LineIndex
]]
111 for Value
in self
._ItemDict
[Key
]:
112 for SubValue
in Scope
:
114 # If current is common section
116 if SubValue
[-1] == 'COMMON':
117 for Other
in Value
[0]:
118 # Key in common cannot be redefined in other arches
119 # [:-1] means stripping arch info
120 if Other
[:-1] == SubValue
[:-1]:
121 self
._LoggerError
(ST
.ERR_DECPARSE_REDEFINE
% (Key
, Value
[1]))
125 CommonScope
[0:1] = SubValue
126 CommonScope
[-1] = 'COMMON'
128 # Cannot be redefined if this key already defined in COMMON Or defined in same arch
130 if SubValue
in Value
[0] or CommonScope
in Value
[0]:
131 self
._LoggerError
(ST
.ERR_DECPARSE_REDEFINE
% (Key
, Value
[1]))
133 self
._ItemDict
[Key
].append([SecArch
, self
._RawData
.LineIndex
])
135 ## CheckRequiredFields
136 # Some sections need to check if some fields exist, define section for example
137 # Derived class can re-implement, top parser will call this function after all parsing done
139 def CheckRequiredFields(self
):
145 # In DEC spec, sections must have at least one statement except user
147 # For example: "[guids" [<attribs>] "]" <EOL> <statements>+
148 # sub class can override this method to indicate if statement is a must.
150 def _IsStatementRequired(self
):
155 def _LoggerError(self
, ErrorString
):
156 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
157 Line
= self
._RawData
.LineIndex
,
158 ExtraData
=ErrorString
+ ST
.ERR_DECPARSE_LINE
% self
._RawData
.CurrentLine
)
160 def _ReplaceMacro(self
, String
):
161 if gMACRO_PATTERN
.findall(String
):
162 String
= ReplaceMacro(String
, self
._LocalMacro
, False,
163 FileName
= self
._RawData
.Filename
,
164 Line
= ['', self
._RawData
.LineIndex
])
165 String
= ReplaceMacro(String
, self
._RawData
.Macros
, False,
166 FileName
= self
._RawData
.Filename
,
167 Line
= ['', self
._RawData
.LineIndex
])
168 MacroUsed
= gMACRO_PATTERN
.findall(String
)
170 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
,
171 File
=self
._RawData
.Filename
,
172 Line
= self
._RawData
.LineIndex
,
173 ExtraData
= ST
.ERR_DECPARSE_MACRO_RESOLVE
% (str(MacroUsed
), String
))
176 def _MacroParser(self
, String
):
177 TokenList
= GetSplitValueList(String
, ' ', 1)
178 if len(TokenList
) < 2 or TokenList
[1] == '':
179 self
._LoggerError
(ST
.ERR_DECPARSE_MACRO_PAIR
)
181 TokenList
= GetSplitValueList(TokenList
[1], DT
.TAB_EQUAL_SPLIT
, 1)
182 if TokenList
[0] == '':
183 self
._LoggerError
(ST
.ERR_DECPARSE_MACRO_NAME
)
184 elif not IsValidToken(MACRO_PATTERN
, TokenList
[0]):
185 self
._LoggerError
(ST
.ERR_DECPARSE_MACRO_NAME_UPPER
% TokenList
[0])
187 if len(TokenList
) == 1:
188 self
._LocalMacro
[TokenList
[0]] = ''
190 self
._LocalMacro
[TokenList
[0]] = self
._ReplaceMacro
(TokenList
[1])
194 # Parse specified item, this function must be derived by subclass
196 def _ParseItem(self
):
200 # Should never be called
205 ## _TailCommentStrategy
207 # This function can be derived to parse tail comment
208 # default is it will not consume any lines
210 # @param Comment: Comment of current line
212 def _TailCommentStrategy(self
, Comment
):
219 ## _StopCurrentParsing
221 # Called in Parse if current parsing should be stopped when encounter some
223 # Default is section start and end
225 # @param Line: Current line
227 def _StopCurrentParsing(self
, Line
):
230 return Line
[0] == DT
.TAB_SECTION_START
and Line
[-1] == DT
.TAB_SECTION_END
234 # Split comment and DEC content, concatenate lines if end of char is '\'
236 # @param ProcessedLine: ProcessedLine line
237 # @param ProcessedComments: ProcessedComments line
239 def _TryBackSlash(self
, ProcessedLine
, ProcessedComments
):
243 CommentList
= ProcessedComments
244 while not self
._RawData
.IsEndOfFile():
246 self
._LoggerError
(ST
.ERR_DECPARSE_BACKSLASH_EMPTY
)
250 CommentList
.append((Comment
, self
._RawData
.LineIndex
))
251 if Line
[-1] != DT
.TAB_SLASH
:
254 elif len(Line
) < 2 or Line
[-2] != ' ':
255 self
._LoggerError
(ST
.ERR_DECPARSE_BACKSLASH
)
258 Line
, Comment
= CleanString(self
._RawData
.GetNextLine())
260 # Reach end of content
262 if self
._RawData
.IsEndOfFile():
264 if ProcessedLine
[-1] == DT
.TAB_SLASH
:
265 self
._LoggerError
(ST
.ERR_DECPARSE_BACKSLASH_EMPTY
)
266 CatLine
= ProcessedLine
268 if not Line
or Line
[-1] == DT
.TAB_SLASH
:
269 self
._LoggerError
(ST
.ERR_DECPARSE_BACKSLASH_EMPTY
)
272 self
._RawData
.CurrentLine
= self
._ReplaceMacro
(CatLine
)
273 return CatLine
, CommentList
276 # This is a template method in which other member functions which might
277 # override by sub class are called. It is responsible for reading file
278 # line by line, and call other member functions to parse. This function
279 # should not be re-implement by sub class.
285 #======================================================================
286 # CurComments may pointer to HeadComments or TailComments
287 #======================================================================
288 CurComments
= HeadComments
293 #======================================================================
294 # Used to report error information if empty section found
295 #======================================================================
296 Index
= self
._RawData
.LineIndex
297 LineStr
= self
._RawData
.CurrentLine
298 while not self
._RawData
.IsEndOfFile() or self
._RawData
.NextLine
:
299 if self
._RawData
.NextLine
:
300 #==============================================================
301 # Have processed line in buffer
302 #==============================================================
303 Line
= self
._RawData
.NextLine
304 HeadComments
.extend(self
._RawData
.HeadComment
)
305 TailComments
.extend(self
._RawData
.TailComment
)
306 self
._RawData
.ResetNext()
310 #==============================================================
311 # No line in buffer, read next line
312 #==============================================================
313 Line
, Comment
= CleanString(self
._RawData
.GetNextLine())
316 if not FromBuf
and CurObj
and TailComments
:
317 #==========================================================
318 # Set tail comments to previous statement if not empty.
319 #==========================================================
320 CurObj
.SetTailComment(CurObj
.GetTailComment()+TailComments
)
324 CurComments
= TailComments
327 Comments
= [(Comment
, self
._RawData
.LineIndex
)]
329 #==============================================================
330 # Try if last char of line has backslash
331 #==============================================================
332 Line
, Comments
= self
._TryBackSlash
(Line
, Comments
)
333 CurComments
.extend(Comments
)
335 #==============================================================
337 #==============================================================
338 if Line
.startswith('DEFINE '):
339 self
._MacroParser
(Line
)
342 CurComments
= HeadComments
345 if self
._StopCurrentParsing
(Line
):
346 #==========================================================
347 # This line does not belong to this parse,
348 # Save it, can be used by next parse
349 #==========================================================
350 self
._RawData
.SetNext(Line
, HeadComments
, TailComments
)
353 Obj
= self
._ParseItem
()
356 Obj
.SetHeadComment(Obj
.GetHeadComment()+HeadComments
)
357 Obj
.SetTailComment(Obj
.GetTailComment()+TailComments
)
364 if id(CurComments
) == id(TailComments
):
365 #==========================================================
366 # Check if this comment belongs to tail comment
367 #==========================================================
368 if not self
._TailCommentStrategy
(Comment
):
369 CurComments
= HeadComments
372 CurComments
.append(((Comment
, self
._RawData
.LineIndex
)))
376 if self
._IsStatementRequired
() and ItemNum
== 0:
378 TOOL_NAME
, FILE_PARSE_FAILURE
,
379 File
=self
._RawData
.Filename
,
381 ExtraData
=ST
.ERR_DECPARSE_STATEMENT_EMPTY
% LineStr
385 # Parse define section
387 class _DecDefine(_DecBase
):
388 def __init__(self
, RawData
):
389 _DecBase
.__init
__(self
, RawData
)
390 self
.ItemObject
= DecDefineObject(RawData
.Filename
)
391 self
._LocalMacro
= self
._RawData
.Macros
395 # Each field has a function to validate
397 self
.DefineValidation
= {
398 DT
.TAB_DEC_DEFINES_DEC_SPECIFICATION
: self
._SetDecSpecification
,
399 DT
.TAB_DEC_DEFINES_PACKAGE_NAME
: self
._SetPackageName
,
400 DT
.TAB_DEC_DEFINES_PACKAGE_GUID
: self
._SetPackageGuid
,
401 DT
.TAB_DEC_DEFINES_PACKAGE_VERSION
: self
._SetPackageVersion
,
402 DT
.TAB_DEC_DEFINES_PKG_UNI_FILE
: self
._SetPackageUni
,
405 def BlockStart(self
):
407 if self
._DefSecNum
> 1:
408 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_MULTISEC
)
410 ## CheckRequiredFields
412 # Check required fields: DEC_SPECIFICATION, PACKAGE_NAME
413 # PACKAGE_GUID, PACKAGE_VERSION
415 def CheckRequiredFields(self
):
417 if self
.ItemObject
.GetPackageSpecification() == '':
418 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
419 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_DEC_SPECIFICATION
)
420 elif self
.ItemObject
.GetPackageName() == '':
421 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
422 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_PACKAGE_NAME
)
423 elif self
.ItemObject
.GetPackageGuid() == '':
424 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
425 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_PACKAGE_GUID
)
426 elif self
.ItemObject
.GetPackageVersion() == '':
427 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
428 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_PACKAGE_VERSION
)
433 def _ParseItem(self
):
434 Line
= self
._RawData
.CurrentLine
435 TokenList
= GetSplitValueList(Line
, DT
.TAB_EQUAL_SPLIT
, 1)
436 if TokenList
[0] == DT
.TAB_DEC_DEFINES_PKG_UNI_FILE
:
437 self
.DefineValidation
[TokenList
[0]](TokenList
[1])
438 elif len(TokenList
) < 2:
439 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_FORMAT
)
440 elif TokenList
[0] not in self
.DefineValidation
:
441 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_UNKNOWKEY
% TokenList
[0])
443 self
.DefineValidation
[TokenList
[0]](TokenList
[1])
445 DefineItem
= DecDefineItemObject()
446 DefineItem
.Key
= TokenList
[0]
447 DefineItem
.Value
= TokenList
[1]
448 self
.ItemObject
.AddItem(DefineItem
, self
._RawData
.CurrentScope
)
451 def _SetDecSpecification(self
, Token
):
452 if self
.ItemObject
.GetPackageSpecification():
453 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_DEC_SPECIFICATION
)
454 if not IsValidToken('0[xX][0-9a-fA-F]{8}', Token
):
455 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_SPEC
)
456 self
.ItemObject
.SetPackageSpecification(Token
)
458 def _SetPackageName(self
, Token
):
459 if self
.ItemObject
.GetPackageName():
460 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PACKAGE_NAME
)
461 if not IsValidWord(Token
):
462 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGNAME
)
463 self
.ItemObject
.SetPackageName(Token
)
465 def _SetPackageGuid(self
, Token
):
466 if self
.ItemObject
.GetPackageGuid():
467 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PACKAGE_GUID
)
468 if not CheckGuidRegFormat(Token
):
469 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGGUID
)
470 self
.ItemObject
.SetPackageGuid(Token
)
472 def _SetPackageVersion(self
, Token
):
473 if self
.ItemObject
.GetPackageVersion():
474 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PACKAGE_VERSION
)
475 if not IsValidToken(VERSION_PATTERN
, Token
):
476 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGVERSION
)
478 if not DT
.TAB_SPLIT
in Token
:
480 self
.ItemObject
.SetPackageVersion(Token
)
482 def _SetPackageUni(self
, Token
):
483 if self
.ItemObject
.GetPackageUniFile():
484 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PKG_UNI_FILE
)
485 self
.ItemObject
.SetPackageUniFile(Token
)
489 # Parse include section
491 class _DecInclude(_DecBase
):
492 def __init__(self
, RawData
):
493 _DecBase
.__init
__(self
, RawData
)
494 self
.ItemObject
= DecIncludeObject(RawData
.Filename
)
496 def _ParseItem(self
):
497 Line
= self
._RawData
.CurrentLine
499 if not IsValidPath(Line
, self
._RawData
.PackagePath
):
500 self
._LoggerError
(ST
.ERR_DECPARSE_INCLUDE
% Line
)
502 Item
= DecIncludeItemObject(StripRoot(self
._RawData
.PackagePath
, Line
), self
._RawData
.PackagePath
)
503 self
.ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
508 # Parse library class section
510 class _DecLibraryclass(_DecBase
):
511 def __init__(self
, RawData
):
512 _DecBase
.__init
__(self
, RawData
)
513 self
.ItemObject
= DecLibraryclassObject(RawData
.Filename
)
515 def _ParseItem(self
):
516 Line
= self
._RawData
.CurrentLine
517 TokenList
= GetSplitValueList(Line
, DT
.TAB_VALUE_SPLIT
)
518 if len(TokenList
) != 2:
519 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_SPLIT
)
520 if TokenList
[0] == '' or TokenList
[1] == '':
521 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_EMPTY
)
522 if not IsValidToken('[A-Z][0-9A-Za-z]*', TokenList
[0]):
523 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_LIB
)
525 self
._CheckReDefine
(TokenList
[0])
531 if not Value
.endswith('.h'):
532 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_PATH_EXT
)
535 # Path must be existed
537 if not IsValidPath(Value
, self
._RawData
.PackagePath
):
538 self
._LoggerError
(ST
.ERR_DECPARSE_INCLUDE
% Value
)
540 Item
= DecLibraryclassItemObject(TokenList
[0], StripRoot(self
._RawData
.PackagePath
, Value
),
541 self
._RawData
.PackagePath
)
542 self
.ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
549 class _DecPcd(_DecBase
):
550 def __init__(self
, RawData
):
551 _DecBase
.__init
__(self
, RawData
)
552 self
.ItemObject
= DecPcdObject(RawData
.Filename
)
554 # Used to check duplicate token
555 # Key is token space and token number (integer), value is C name
559 def _ParseItem(self
):
560 Line
= self
._RawData
.CurrentLine
561 TokenList
= Line
.split(DT
.TAB_VALUE_SPLIT
)
562 if len(TokenList
) < 4:
563 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_SPLIT
)
566 # Token space guid C name
568 PcdName
= GetSplitValueList(TokenList
[0], DT
.TAB_SPLIT
)
569 if len(PcdName
) != 2 or PcdName
[0] == '' or PcdName
[1] == '':
570 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_NAME
)
573 if not IsValidToken(CVAR_PATTERN
, Guid
):
574 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_CVAR_GUID
)
580 if not IsValidToken(CVAR_PATTERN
, CName
):
581 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_CVAR_PCDCNAME
)
583 self
._CheckReDefine
(Guid
+ DT
.TAB_SPLIT
+ CName
)
586 # Default value, may be C array, string or number
588 Data
= DT
.TAB_VALUE_SPLIT
.join(TokenList
[1:-2]).strip()
593 DataType
= TokenList
[-2].strip()
594 Valid
, Cause
= IsValidPcdDatum(DataType
, Data
)
596 self
._LoggerError
(Cause
)
597 PcdType
= self
._RawData
.CurrentScope
[0][0]
598 if PcdType
== DT
.TAB_PCDS_FEATURE_FLAG_NULL
.upper() and DataType
!= 'BOOLEAN':
599 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_FEATUREFLAG
)
601 # Token value is the last element in list.
603 Token
= TokenList
[-1].strip()
604 if not IsValidToken(PCD_TOKEN_PATTERN
, Token
):
605 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_TOKEN
% Token
)
606 elif not Token
.startswith('0x') and not Token
.startswith('0X'):
607 if long(Token
) > 4294967295:
608 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_TOKEN_INT
% Token
)
609 Token
= hex(long(Token
))[:-1]
611 IntToken
= long(Token
, 0)
612 if (Guid
, IntToken
) in self
.TokenMap
:
613 if self
.TokenMap
[Guid
, IntToken
] != CName
:
614 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_TOKEN_UNIQUE
%(Token))
616 self
.TokenMap
[Guid
, IntToken
] = CName
618 Item
= DecPcdItemObject(Guid
, CName
, Data
, DataType
, Token
)
619 self
.ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
624 # Parse GUID, PPI, Protocol section
626 class _DecGuid(_DecBase
):
627 def __init__(self
, RawData
):
628 _DecBase
.__init
__(self
, RawData
)
629 self
.GuidObj
= DecGuidObject(RawData
.Filename
)
630 self
.PpiObj
= DecPpiObject(RawData
.Filename
)
631 self
.ProtocolObj
= DecProtocolObject(RawData
.Filename
)
634 DT
.TAB_GUIDS
.upper() : self
.GuidObj
,
635 DT
.TAB_PPIS
.upper() : self
.PpiObj
,
636 DT
.TAB_PROTOCOLS
.upper() : self
.ProtocolObj
639 def GetDataObject(self
):
640 if self
._RawData
.CurrentScope
:
641 return self
.ObjectDict
[self
._RawData
.CurrentScope
[0][0]]
644 def GetGuidObject(self
):
647 def GetPpiObject(self
):
650 def GetProtocolObject(self
):
651 return self
.ProtocolObj
653 def _ParseItem(self
):
654 Line
= self
._RawData
.CurrentLine
655 TokenList
= GetSplitValueList(Line
, DT
.TAB_EQUAL_SPLIT
, 1)
656 if len(TokenList
) < 2:
657 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID
)
658 if TokenList
[0] == '':
659 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_NAME
)
660 if TokenList
[1] == '':
661 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_GUID
)
662 if not IsValidToken(CVAR_PATTERN
, TokenList
[0]):
663 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_CVAR_GUID
)
665 self
._CheckReDefine
(TokenList
[0])
667 if TokenList
[1][0] != '{':
668 if not CheckGuidRegFormat(TokenList
[1]):
669 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGGUID
)
670 GuidString
= TokenList
[1]
673 # Convert C format GUID to GUID string and Simple error check
675 GuidString
= GuidStructureStringToGuidString(TokenList
[1])
676 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidString
== '':
677 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_GUIDFORMAT
)
680 # Check C format GUID
682 if not IsValidCFormatGuid(TokenList
[1]):
683 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_GUIDFORMAT
)
685 Item
= DecGuidItemObject(TokenList
[0], TokenList
[1], GuidString
)
686 ItemObject
= self
.ObjectDict
[self
._RawData
.CurrentScope
[0][0]]
687 ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
692 # Parse user extention section
694 class _DecUserExtension(_DecBase
):
695 def __init__(self
, RawData
):
696 _DecBase
.__init
__(self
, RawData
)
697 self
.ItemObject
= DecUserExtensionObject(RawData
.Filename
)
701 def BlockStart(self
):
703 for Header
in self
._RawData
.CurrentScope
:
704 if Header
in self
._Headers
:
705 self
._LoggerError
(ST
.ERR_DECPARSE_UE_DUPLICATE
)
707 self
._Headers
.append(Header
)
709 for Item
in self
._CurItems
:
710 if Item
.UserId
== Header
[1] and Item
.IdString
== Header
[2]:
711 Item
.ArchAndModuleType
.append(Header
[3])
714 Item
= DecUserExtensionItemObject()
715 Item
.UserId
= Header
[1]
716 Item
.IdString
= Header
[2]
717 Item
.ArchAndModuleType
.append(Header
[3])
718 self
._CurItems
.append(Item
)
719 self
.ItemObject
.AddItem(Item
, None)
720 self
._LocalMacro
= {}
722 def _ParseItem(self
):
723 Line
= self
._RawData
.CurrentLine
725 for Item
in self
._CurItems
:
727 Item
.UserString
= '\n'.join([Item
.UserString
, Line
])
729 Item
.UserString
= Line
736 class Dec(_DecBase
, _DecComments
):
737 def __init__(self
, DecFile
, Parse
= True):
739 Content
= ConvertSpecialChar(open(DecFile
, 'rb').readlines())
740 except BaseException
:
741 Logger
.Error(TOOL_NAME
, FILE_OPEN_FAILURE
, File
=DecFile
,
742 ExtraData
=ST
.ERR_DECPARSE_FILEOPEN
% DecFile
)
743 RawData
= FileContent(DecFile
, Content
)
745 _DecComments
.__init
__(self
)
746 _DecBase
.__init
__(self
, RawData
)
748 self
.BinaryHeadComment
= []
749 self
.PcdErrorCommentDict
= {}
751 self
._Define
= _DecDefine(RawData
)
752 self
._Include
= _DecInclude(RawData
)
753 self
._Guid
= _DecGuid(RawData
)
754 self
._LibClass
= _DecLibraryclass(RawData
)
755 self
._Pcd
= _DecPcd(RawData
)
756 self
._UserEx
= _DecUserExtension(RawData
)
759 # DEC file supported data types (one type per section)
761 self
._SectionParser
= {
762 DT
.TAB_DEC_DEFINES
.upper() : self
._Define
,
763 DT
.TAB_INCLUDES
.upper() : self
._Include
,
764 DT
.TAB_LIBRARY_CLASSES
.upper() : self
._LibClass
,
765 DT
.TAB_GUIDS
.upper() : self
._Guid
,
766 DT
.TAB_PPIS
.upper() : self
._Guid
,
767 DT
.TAB_PROTOCOLS
.upper() : self
._Guid
,
768 DT
.TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : self
._Pcd
,
769 DT
.TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : self
._Pcd
,
770 DT
.TAB_PCDS_FEATURE_FLAG_NULL
.upper() : self
._Pcd
,
771 DT
.TAB_PCDS_DYNAMIC_NULL
.upper() : self
._Pcd
,
772 DT
.TAB_PCDS_DYNAMIC_EX_NULL
.upper() : self
._Pcd
,
773 DT
.TAB_USER_EXTENSIONS
.upper() : self
._UserEx
777 self
.ParseDecComment()
780 # Parsing done, check required fields
782 self
.CheckRequiredFields()
784 def CheckRequiredFields(self
):
785 for SectionParser
in self
._SectionParser
.values():
786 if not SectionParser
.CheckRequiredFields():
793 def ParseDecComment(self
):
795 IsBinaryHeader
= False
796 FileHeaderLineIndex
= -1
797 BinaryHeaderLineIndex
= -1
798 TokenSpaceGuidCName
= ''
801 # Parse PCD error comment section
803 while not self
._RawData
.IsEndOfFile():
804 self
._RawData
.CurrentLine
= self
._RawData
.GetNextLine()
805 if self
._RawData
.CurrentLine
.startswith(DT
.TAB_COMMENT_SPLIT
) and \
806 DT
.TAB_SECTION_START
in self
._RawData
.CurrentLine
and \
807 DT
.TAB_SECTION_END
in self
._RawData
.CurrentLine
:
808 self
._RawData
.CurrentLine
= self
._RawData
.CurrentLine
.replace(DT
.TAB_COMMENT_SPLIT
, '').strip()
810 if self
._RawData
.CurrentLine
[0] == DT
.TAB_SECTION_START
and \
811 self
._RawData
.CurrentLine
[-1] == DT
.TAB_SECTION_END
:
812 RawSection
= self
._RawData
.CurrentLine
[1:-1].strip()
813 if RawSection
.upper().startswith(DT
.TAB_PCD_ERROR
.upper()+'.'):
814 TokenSpaceGuidCName
= RawSection
.split(DT
.TAB_PCD_ERROR
+'.')[1].strip()
817 if TokenSpaceGuidCName
and self
._RawData
.CurrentLine
.startswith(DT
.TAB_COMMENT_SPLIT
):
818 self
._RawData
.CurrentLine
= self
._RawData
.CurrentLine
.replace(DT
.TAB_COMMENT_SPLIT
, '').strip()
819 if self
._RawData
.CurrentLine
!= '':
820 if DT
.TAB_VALUE_SPLIT
not in self
._RawData
.CurrentLine
:
821 self
._LoggerError
(ST
.ERR_DECPARSE_PCDERRORMSG_MISS_VALUE_SPLIT
)
823 PcdErrorNumber
, PcdErrorMsg
= GetSplitValueList(self
._RawData
.CurrentLine
, DT
.TAB_VALUE_SPLIT
, 1)
824 PcdErrorNumber
= ParsePcdErrorCode(PcdErrorNumber
, self
._RawData
.Filename
, self
._RawData
.LineIndex
)
825 if not PcdErrorMsg
.strip():
826 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_MISS_ERRORMSG
)
828 self
.PcdErrorCommentDict
[(TokenSpaceGuidCName
, PcdErrorNumber
)] = PcdErrorMsg
.strip()
830 TokenSpaceGuidCName
= ''
832 self
._RawData
.LineIndex
= 0
833 self
._RawData
.CurrentLine
= ''
834 self
._RawData
.NextLine
= ''
836 while not self
._RawData
.IsEndOfFile():
837 Line
, Comment
= CleanString(self
._RawData
.GetNextLine())
840 # Header must be pure comment
843 self
._RawData
.UndoNextLine()
846 if Comment
and Comment
.startswith(DT
.TAB_SPECIAL_COMMENT
) and Comment
.find(DT
.TAB_HEADER_COMMENT
) > 0 \
847 and not Comment
[2:Comment
.find(DT
.TAB_HEADER_COMMENT
)].strip():
849 IsBinaryHeader
= False
850 FileHeaderLineIndex
= self
._RawData
.LineIndex
853 # Get license information before '@file'
855 if not IsFileHeader
and not IsBinaryHeader
and Comment
and Comment
.startswith(DT
.TAB_COMMENT_SPLIT
) and \
856 DT
.TAB_BINARY_HEADER_COMMENT
not in Comment
:
857 self
._HeadComment
.append((Comment
, self
._RawData
.LineIndex
))
859 if Comment
and IsFileHeader
and \
860 not(Comment
.startswith(DT
.TAB_SPECIAL_COMMENT
) \
861 and Comment
.find(DT
.TAB_BINARY_HEADER_COMMENT
) > 0):
862 self
._HeadComment
.append((Comment
, self
._RawData
.LineIndex
))
864 # Double '#' indicates end of header comments
866 if (not Comment
or Comment
== DT
.TAB_SPECIAL_COMMENT
) and IsFileHeader
:
870 if Comment
and Comment
.startswith(DT
.TAB_SPECIAL_COMMENT
) \
871 and Comment
.find(DT
.TAB_BINARY_HEADER_COMMENT
) > 0:
872 IsBinaryHeader
= True
874 BinaryHeaderLineIndex
= self
._RawData
.LineIndex
876 if Comment
and IsBinaryHeader
:
877 self
.BinaryHeadComment
.append((Comment
, self
._RawData
.LineIndex
))
879 # Double '#' indicates end of header comments
881 if (not Comment
or Comment
== DT
.TAB_SPECIAL_COMMENT
) and IsBinaryHeader
:
882 IsBinaryHeader
= False
885 if FileHeaderLineIndex
> -1 and not IsFileHeader
and not IsBinaryHeader
:
888 if FileHeaderLineIndex
> BinaryHeaderLineIndex
and FileHeaderLineIndex
> -1 and BinaryHeaderLineIndex
> -1:
889 self
._LoggerError
(ST
.ERR_BINARY_HEADER_ORDER
)
891 if FileHeaderLineIndex
== -1:
892 # self._LoggerError(ST.ERR_NO_SOURCE_HEADER)
893 Logger
.Error(TOOL_NAME
, FORMAT_INVALID
,
894 ST
.ERR_NO_SOURCE_HEADER
,
895 File
=self
._RawData
.Filename
)
898 def _StopCurrentParsing(self
, Line
):
901 def _ParseItem(self
):
902 self
._SectionHeaderParser
()
903 if len(self
._RawData
.CurrentScope
) == 0:
904 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_EMPTY
)
905 SectionObj
= self
._SectionParser
[self
._RawData
.CurrentScope
[0][0]]
906 SectionObj
.BlockStart()
908 return SectionObj
.GetDataObject()
910 def _UserExtentionSectionParser(self
):
911 self
._RawData
.CurrentScope
= []
913 Section
= self
._RawData
.CurrentLine
[1:-1]
914 Par
= ParserHelper(Section
, self
._RawData
.Filename
)
919 Token
= Par
.GetToken()
920 if Token
.upper() != DT
.TAB_USER_EXTENSIONS
.upper():
921 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE
)
922 UserExtension
= Token
.upper()
923 Par
.AssertChar(DT
.TAB_SPLIT
, ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
928 Token
= Par
.GetToken()
929 if not IsValidUserId(Token
):
930 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE_USERID
)
932 Par
.AssertChar(DT
.TAB_SPLIT
, ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
936 Token
= Par
.GetToken()
937 if not IsValidIdString(Token
):
938 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE_IDSTRING
)
941 if Par
.Expect(DT
.TAB_SPLIT
):
942 Token
= Par
.GetToken()
944 if not IsValidArch(Arch
):
945 self
._LoggerError
(ST
.ERR_DECPARSE_ARCH
)
947 if [UserExtension
, UserId
, IdString
, Arch
] not in \
948 self
._RawData
.CurrentScope
:
949 self
._RawData
.CurrentScope
.append(
950 [UserExtension
, UserId
, IdString
, Arch
]
952 if not Par
.Expect(DT
.TAB_COMMA_SPLIT
):
955 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMA
)
956 Par
.AssertEnd(ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
957 if 'COMMON' in ArchList
and len(ArchList
) > 1:
958 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMON
)
960 ## Section header parser
962 # The section header is always in following format:
964 # [section_name.arch<.platform|module_type>]
966 def _SectionHeaderParser(self
):
967 if self
._RawData
.CurrentLine
[0] != DT
.TAB_SECTION_START
or self
._RawData
.CurrentLine
[-1] != DT
.TAB_SECTION_END
:
968 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_IDENTIFY
)
970 RawSection
= self
._RawData
.CurrentLine
[1:-1].strip().upper()
972 # Check defines section which is only allowed to occur once and
973 # no arch can be followed
975 if RawSection
.startswith(DT
.TAB_DEC_DEFINES
.upper()):
976 if RawSection
!= DT
.TAB_DEC_DEFINES
.upper():
977 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_SECNAME
)
979 # Check user extension section
981 if RawSection
.startswith(DT
.TAB_USER_EXTENSIONS
.upper()):
982 return self
._UserExtentionSectionParser
()
983 self
._RawData
.CurrentScope
= []
986 for Item
in GetSplitValueList(RawSection
, DT
.TAB_COMMA_SPLIT
):
988 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBEMPTY
% self
._RawData
.CurrentLine
)
990 ItemList
= GetSplitValueList(Item
, DT
.TAB_SPLIT
)
992 # different types of PCD are permissible in one section
994 SectionName
= ItemList
[0]
995 if SectionName
not in self
._SectionParser
:
996 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UNKNOW
% SectionName
)
997 if SectionName
not in SectionNames
:
998 SectionNames
.append(SectionName
)
1000 # In DEC specification, all section headers have at most two part:
1001 # SectionName.Arch except UserExtention
1003 if len(ItemList
) > 2:
1004 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBTOOMANY
% Item
)
1006 if DT
.TAB_PCDS_FEATURE_FLAG_NULL
.upper() in SectionNames
and len(SectionNames
) > 1:
1007 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_FEATUREFLAG
% DT
.TAB_PCDS_FEATURE_FLAG_NULL
)
1011 if len(ItemList
) > 1:
1013 if not IsValidArch(Str1
):
1014 self
._LoggerError
(ST
.ERR_DECPARSE_ARCH
)
1019 if [SectionName
, Str1
] not in self
._RawData
.CurrentScope
:
1020 self
._RawData
.CurrentScope
.append([SectionName
, Str1
])
1022 # 'COMMON' must not be used with specific ARCHs at the same section
1024 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1025 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMON
)
1026 if len(SectionNames
) == 0:
1027 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBEMPTY
% self
._RawData
.CurrentLine
)
1028 if len(SectionNames
) != 1:
1029 for Sec
in SectionNames
:
1030 if not Sec
.startswith(DT
.TAB_PCDS
.upper()):
1031 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_NAME
% str(SectionNames
))
1033 def GetDefineSectionMacro(self
):
1034 return self
._Define
.GetLocalMacro()
1035 def GetDefineSectionObject(self
):
1036 return self
._Define
.GetDataObject()
1037 def GetIncludeSectionObject(self
):
1038 return self
._Include
.GetDataObject()
1039 def GetGuidSectionObject(self
):
1040 return self
._Guid
.GetGuidObject()
1041 def GetProtocolSectionObject(self
):
1042 return self
._Guid
.GetProtocolObject()
1043 def GetPpiSectionObject(self
):
1044 return self
._Guid
.GetPpiObject()
1045 def GetLibraryClassSectionObject(self
):
1046 return self
._LibClass
.GetDataObject()
1047 def GetPcdSectionObject(self
):
1048 return self
._Pcd
.GetDataObject()
1049 def GetUserExtensionSectionObject(self
):
1050 return self
._UserEx
.GetDataObject()
1051 def GetPackageSpecification(self
):
1052 return self
._Define
.GetDataObject().GetPackageSpecification()
1053 def GetPackageName(self
):
1054 return self
._Define
.GetDataObject().GetPackageName()
1055 def GetPackageGuid(self
):
1056 return self
._Define
.GetDataObject().GetPackageGuid()
1057 def GetPackageVersion(self
):
1058 return self
._Define
.GetDataObject().GetPackageVersion()
1059 def GetPackageUniFile(self
):
1060 return self
._Define
.GetDataObject().GetPackageUniFile()