2 # This file is used to parse DEC file. It will consumed by DecParser
4 # Copyright (c) 2011, 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
23 import Library
.DataType
as DT
24 from Library
.ParserValidate
import IsValidToken
25 from Library
.ParserValidate
import IsValidPath
26 from Library
.ParserValidate
import IsValidCFormatGuid
27 from Library
.ParserValidate
import IsValidIdString
28 from Library
.ParserValidate
import IsValidUserId
29 from Library
.ParserValidate
import IsValidArch
30 from Library
.ParserValidate
import IsValidWord
31 from Parser
.DecParserMisc
import TOOL_NAME
32 from Parser
.DecParserMisc
import CleanString
33 from Parser
.DecParserMisc
import IsValidPcdDatum
34 from Parser
.DecParserMisc
import ParserHelper
35 from Parser
.DecParserMisc
import StripRoot
36 from Parser
.DecParserMisc
import VERSION_PATTERN
37 from Parser
.DecParserMisc
import CVAR_PATTERN
38 from Parser
.DecParserMisc
import PCD_TOKEN_PATTERN
39 from Parser
.DecParserMisc
import MACRO_PATTERN
40 from Parser
.DecParserMisc
import FileContent
41 from Object
.Parser
.DecObject
import _DecComments
42 from Object
.Parser
.DecObject
import DecDefineObject
43 from Object
.Parser
.DecObject
import DecDefineItemObject
44 from Object
.Parser
.DecObject
import DecIncludeObject
45 from Object
.Parser
.DecObject
import DecIncludeItemObject
46 from Object
.Parser
.DecObject
import DecLibraryclassObject
47 from Object
.Parser
.DecObject
import DecLibraryclassItemObject
48 from Object
.Parser
.DecObject
import DecGuidObject
49 from Object
.Parser
.DecObject
import DecPpiObject
50 from Object
.Parser
.DecObject
import DecProtocolObject
51 from Object
.Parser
.DecObject
import DecGuidItemObject
52 from Object
.Parser
.DecObject
import DecUserExtensionObject
53 from Object
.Parser
.DecObject
import DecUserExtensionItemObject
54 from Object
.Parser
.DecObject
import DecPcdObject
55 from Object
.Parser
.DecObject
import DecPcdItemObject
56 from Library
.Misc
import GuidStructureStringToGuidString
57 from Library
.Misc
import CheckGuidRegFormat
58 from Library
.String
import ReplaceMacro
59 from Library
.String
import GetSplitValueList
60 from Library
.String
import gMACRO_PATTERN
61 from Library
.String
import ConvertSpecialChar
64 # _DecBase class for parsing
67 def __init__(self
, RawData
):
68 self
._RawData
= RawData
72 # Data parsed by 'self' are saved to this object
74 self
.ItemObject
= None
76 def GetDataObject(self
):
77 return self
.ItemObject
81 # Called if a new section starts
88 # @param Key: to be checked if multi-defined
89 # @param Scope: Format: [[SectionName, Arch], ...].
90 # If scope is none, use global scope
92 def _CheckReDefine(self
, Key
, Scope
= None):
94 Scope
= self
._RawData
.CurrentScope
99 # Copy scope to SecArch, avoid Scope be changed outside
101 SecArch
[0:1] = Scope
[:]
102 if Key
not in self
._ItemDict
:
103 self
._ItemDict
[Key
] = [[SecArch
, self
._RawData
.LineIndex
]]
106 for Value
in self
._ItemDict
[Key
]:
107 for SubValue
in Scope
:
109 # If current is common section
111 if SubValue
[-1] == 'COMMON':
112 for Other
in Value
[0]:
113 # Key in common cannot be redefined in other arches
114 # [:-1] means stripping arch info
115 if Other
[:-1] == SubValue
[:-1]:
116 self
._LoggerError
(ST
.ERR_DECPARSE_REDEFINE
% (Key
, Value
[1]))
120 CommonScope
[0:1] = SubValue
121 CommonScope
[-1] = 'COMMON'
123 # Cannot be redefined if this key already defined in COMMON Or defined in same arch
125 if SubValue
in Value
[0] or CommonScope
in Value
[0]:
126 self
._LoggerError
(ST
.ERR_DECPARSE_REDEFINE
% (Key
, Value
[1]))
128 self
._ItemDict
[Key
].append([SecArch
, self
._RawData
.LineIndex
])
130 ## CheckRequiredFields
131 # Some sections need to check if some fields exist, define section for example
132 # Derived class can re-implement, top parser will call this function after all parsing done
134 def CheckRequiredFields(self
):
140 # In DEC spec, sections must have at least one statement except user
142 # For example: "[guids" [<attribs>] "]" <EOL> <statements>+
143 # sub class can override this method to indicate if statement is a must.
145 def _IsStatementRequired(self
):
150 def _LoggerError(self
, ErrorString
):
151 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
152 Line
= self
._RawData
.LineIndex
,
153 ExtraData
=ErrorString
+ ST
.ERR_DECPARSE_LINE
% self
._RawData
.CurrentLine
)
155 def _ReplaceMacro(self
, String
):
156 if gMACRO_PATTERN
.findall(String
):
157 String
= ReplaceMacro(String
, self
._LocalMacro
, False,
158 FileName
= self
._RawData
.Filename
,
159 Line
= ['', self
._RawData
.LineIndex
])
160 String
= ReplaceMacro(String
, self
._RawData
.Macros
, False,
161 FileName
= self
._RawData
.Filename
,
162 Line
= ['', self
._RawData
.LineIndex
])
163 MacroUsed
= gMACRO_PATTERN
.findall(String
)
165 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
,
166 File
=self
._RawData
.Filename
,
167 Line
= self
._RawData
.LineIndex
,
168 ExtraData
= ST
.ERR_DECPARSE_MACRO_RESOLVE
% (str(MacroUsed
), String
))
171 def _MacroParser(self
, String
):
172 TokenList
= GetSplitValueList(String
, ' ', 1)
173 if len(TokenList
) < 2 or TokenList
[1] == '':
174 self
._LoggerError
(ST
.ERR_DECPARSE_MACRO_PAIR
)
176 TokenList
= GetSplitValueList(TokenList
[1], DT
.TAB_EQUAL_SPLIT
, 1)
177 if TokenList
[0] == '':
178 self
._LoggerError
(ST
.ERR_DECPARSE_MACRO_NAME
)
179 elif not IsValidToken(MACRO_PATTERN
, TokenList
[0]):
180 self
._LoggerError
(ST
.ERR_DECPARSE_MACRO_NAME_UPPER
% TokenList
[0])
182 if len(TokenList
) == 1:
183 self
._LocalMacro
[TokenList
[0]] = ''
185 self
._LocalMacro
[TokenList
[0]] = self
._ReplaceMacro
(TokenList
[1])
189 # Parse specified item, this function must be derived by subclass
191 def _ParseItem(self
):
195 # Should never be called
200 ## _TailCommentStrategy
202 # This function can be derived to parse tail comment
203 # default is it will not consume any lines
205 # @param Comment: Comment of current line
207 def _TailCommentStrategy(self
, Comment
):
214 ## _StopCurrentParsing
216 # Called in Parse if current parsing should be stopped when encounter some
218 # Default is section start and end
220 # @param Line: Current line
222 def _StopCurrentParsing(self
, Line
):
225 return Line
[0] == DT
.TAB_SECTION_START
and Line
[-1] == DT
.TAB_SECTION_END
229 # Split comment and DEC content, concatenate lines if end of char is '\'
231 # @param ProcessedLine: ProcessedLine line
232 # @param ProcessedComments: ProcessedComments line
234 def _TryBackSlash(self
, ProcessedLine
, ProcessedComments
):
238 CommentList
= ProcessedComments
239 while not self
._RawData
.IsEndOfFile():
241 self
._LoggerError
(ST
.ERR_DECPARSE_BACKSLASH_EMPTY
)
245 CommentList
.append((Comment
, self
._RawData
.LineIndex
))
246 if Line
[-1] != DT
.TAB_SLASH
:
249 elif len(Line
) < 2 or Line
[-2] != ' ':
250 self
._LoggerError
(ST
.ERR_DECPARSE_BACKSLASH
)
253 Line
, Comment
= CleanString(self
._RawData
.GetNextLine())
255 # Reach end of content
257 if self
._RawData
.IsEndOfFile():
259 if ProcessedLine
[-1] == DT
.TAB_SLASH
:
260 self
._LoggerError
(ST
.ERR_DECPARSE_BACKSLASH_EMPTY
)
261 CatLine
= ProcessedLine
263 if not Line
or Line
[-1] == DT
.TAB_SLASH
:
264 self
._LoggerError
(ST
.ERR_DECPARSE_BACKSLASH_EMPTY
)
267 self
._RawData
.CurrentLine
= self
._ReplaceMacro
(CatLine
)
268 return CatLine
, CommentList
271 # This is a template method in which other member functions which might
272 # override by sub class are called. It is responsible for reading file
273 # line by line, and call other member functions to parse. This function
274 # should not be re-implement by sub class.
280 #======================================================================
281 # CurComments may pointer to HeadComments or TailComments
282 #======================================================================
283 CurComments
= HeadComments
288 #======================================================================
289 # Used to report error information if empty section found
290 #======================================================================
291 Index
= self
._RawData
.LineIndex
292 LineStr
= self
._RawData
.CurrentLine
293 while not self
._RawData
.IsEndOfFile() or self
._RawData
.NextLine
:
294 if self
._RawData
.NextLine
:
295 #==============================================================
296 # Have processed line in buffer
297 #==============================================================
298 Line
= self
._RawData
.NextLine
299 HeadComments
.extend(self
._RawData
.HeadComment
)
300 TailComments
.extend(self
._RawData
.TailComment
)
301 self
._RawData
.ResetNext()
305 #==============================================================
306 # No line in buffer, read next line
307 #==============================================================
308 Line
, Comment
= CleanString(self
._RawData
.GetNextLine())
311 if not FromBuf
and CurObj
and TailComments
:
312 #==========================================================
313 # Set tail comments to previous statement if not empty.
314 #==========================================================
315 CurObj
.SetTailComment(CurObj
.GetTailComment()+TailComments
)
319 CurComments
= TailComments
322 Comments
= [(Comment
, self
._RawData
.LineIndex
)]
324 #==============================================================
325 # Try if last char of line has backslash
326 #==============================================================
327 Line
, Comments
= self
._TryBackSlash
(Line
, Comments
)
328 CurComments
.extend(Comments
)
330 #==============================================================
332 #==============================================================
333 if Line
.startswith('DEFINE '):
334 self
._MacroParser
(Line
)
337 CurComments
= HeadComments
340 if self
._StopCurrentParsing
(Line
):
341 #==========================================================
342 # This line does not belong to this parse,
343 # Save it, can be used by next parse
344 #==========================================================
345 self
._RawData
.SetNext(Line
, HeadComments
, TailComments
)
348 Obj
= self
._ParseItem
()
351 Obj
.SetHeadComment(Obj
.GetHeadComment()+HeadComments
)
352 Obj
.SetTailComment(Obj
.GetTailComment()+TailComments
)
359 if id(CurComments
) == id(TailComments
):
360 #==========================================================
361 # Check if this comment belongs to tail comment
362 #==========================================================
363 if not self
._TailCommentStrategy
(Comment
):
364 CurComments
= HeadComments
367 CurComments
.append(((Comment
, self
._RawData
.LineIndex
)))
371 if self
._IsStatementRequired
() and ItemNum
== 0:
373 TOOL_NAME
, FILE_PARSE_FAILURE
,
374 File
=self
._RawData
.Filename
,
376 ExtraData
=ST
.ERR_DECPARSE_STATEMENT_EMPTY
% LineStr
380 # Parse define section
382 class _DecDefine(_DecBase
):
383 def __init__(self
, RawData
):
384 _DecBase
.__init
__(self
, RawData
)
385 self
.ItemObject
= DecDefineObject(RawData
.Filename
)
386 self
._LocalMacro
= self
._RawData
.Macros
390 # Each field has a function to validate
392 self
.DefineValidation
= {
393 DT
.TAB_DEC_DEFINES_DEC_SPECIFICATION
: self
._SetDecSpecification
,
394 DT
.TAB_DEC_DEFINES_PACKAGE_NAME
: self
._SetPackageName
,
395 DT
.TAB_DEC_DEFINES_PACKAGE_GUID
: self
._SetPackageGuid
,
396 DT
.TAB_DEC_DEFINES_PACKAGE_VERSION
: self
._SetPackageVersion
,
399 def BlockStart(self
):
401 if self
._DefSecNum
> 1:
402 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_MULTISEC
)
404 ## CheckRequiredFields
406 # Check required fields: DEC_SPECIFICATION, PACKAGE_NAME
407 # PACKAGE_GUID, PACKAGE_VERSION
409 def CheckRequiredFields(self
):
411 if self
.ItemObject
.GetPackageSpecification() == '':
412 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
413 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_DEC_SPECIFICATION
)
414 elif self
.ItemObject
.GetPackageName() == '':
415 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
416 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_PACKAGE_NAME
)
417 elif self
.ItemObject
.GetPackageGuid() == '':
418 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
419 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_PACKAGE_GUID
)
420 elif self
.ItemObject
.GetPackageVersion() == '':
421 Logger
.Error(TOOL_NAME
, FILE_PARSE_FAILURE
, File
=self
._RawData
.Filename
,
422 ExtraData
=ST
.ERR_DECPARSE_DEFINE_REQUIRED
% DT
.TAB_DEC_DEFINES_PACKAGE_VERSION
)
427 def _ParseItem(self
):
428 Line
= self
._RawData
.CurrentLine
429 TokenList
= GetSplitValueList(Line
, DT
.TAB_EQUAL_SPLIT
, 1)
430 if TokenList
[0] == DT
.TAB_DEC_DEFINES_PKG_UNI_FILE
:
432 elif len(TokenList
) < 2:
433 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_FORMAT
)
434 elif TokenList
[0] not in self
.DefineValidation
:
435 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_UNKNOWKEY
% TokenList
[0])
437 self
.DefineValidation
[TokenList
[0]](TokenList
[1])
439 DefineItem
= DecDefineItemObject()
440 if TokenList
[0] != DT
.TAB_DEC_DEFINES_PKG_UNI_FILE
:
441 DefineItem
.Key
= TokenList
[0]
442 DefineItem
.Value
= TokenList
[1]
443 self
.ItemObject
.AddItem(DefineItem
, self
._RawData
.CurrentScope
)
446 def _SetDecSpecification(self
, Token
):
447 if self
.ItemObject
.GetPackageSpecification():
448 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_DEC_SPECIFICATION
)
449 if not IsValidToken('0[xX][0-9a-fA-F]{8}', Token
):
450 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_SPEC
)
451 self
.ItemObject
.SetPackageSpecification(Token
)
453 def _SetPackageName(self
, Token
):
454 if self
.ItemObject
.GetPackageName():
455 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PACKAGE_NAME
)
456 if not IsValidWord(Token
):
457 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGNAME
)
458 self
.ItemObject
.SetPackageName(Token
)
460 def _SetPackageGuid(self
, Token
):
461 if self
.ItemObject
.GetPackageGuid():
462 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PACKAGE_GUID
)
463 if not CheckGuidRegFormat(Token
):
464 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGGUID
)
465 self
.ItemObject
.SetPackageGuid(Token
)
467 def _SetPackageVersion(self
, Token
):
468 if self
.ItemObject
.GetPackageVersion():
469 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_DEFINED
% DT
.TAB_DEC_DEFINES_PACKAGE_VERSION
)
470 if not IsValidToken(VERSION_PATTERN
, Token
):
471 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGVERSION
)
473 if not DT
.TAB_SPLIT
in Token
:
475 self
.ItemObject
._PkgVersion
= Token
479 # Parse include section
481 class _DecInclude(_DecBase
):
482 def __init__(self
, RawData
):
483 _DecBase
.__init
__(self
, RawData
)
484 self
.ItemObject
= DecIncludeObject(RawData
.Filename
)
486 def _ParseItem(self
):
487 Line
= self
._RawData
.CurrentLine
489 if not IsValidPath(Line
, self
._RawData
.PackagePath
):
490 self
._LoggerError
(ST
.ERR_DECPARSE_INCLUDE
% Line
)
492 Item
= DecIncludeItemObject(StripRoot(self
._RawData
.PackagePath
, Line
), self
._RawData
.PackagePath
)
493 self
.ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
498 # Parse library class section
500 class _DecLibraryclass(_DecBase
):
501 def __init__(self
, RawData
):
502 _DecBase
.__init
__(self
, RawData
)
503 self
.ItemObject
= DecLibraryclassObject(RawData
.Filename
)
505 def _ParseItem(self
):
506 Line
= self
._RawData
.CurrentLine
507 TokenList
= GetSplitValueList(Line
, DT
.TAB_VALUE_SPLIT
)
508 if len(TokenList
) != 2:
509 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_SPLIT
)
510 if TokenList
[0] == '' or TokenList
[1] == '':
511 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_EMPTY
)
512 if not IsValidToken('[A-Z][0-9A-Za-z]*', TokenList
[0]):
513 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_LIB
)
515 self
._CheckReDefine
(TokenList
[0])
521 if not Value
.endswith('.h'):
522 self
._LoggerError
(ST
.ERR_DECPARSE_LIBCLASS_PATH_EXT
)
525 # Path must be existed
527 if not IsValidPath(Value
, self
._RawData
.PackagePath
):
528 self
._LoggerError
(ST
.ERR_DECPARSE_INCLUDE
% Value
)
530 Item
= DecLibraryclassItemObject(TokenList
[0], StripRoot(self
._RawData
.PackagePath
, Value
),
531 self
._RawData
.PackagePath
)
532 self
.ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
539 class _DecPcd(_DecBase
):
540 def __init__(self
, RawData
):
541 _DecBase
.__init
__(self
, RawData
)
542 self
.ItemObject
= DecPcdObject(RawData
.Filename
)
544 # Used to check duplicate token
545 # Key is token space and token number (integer), value is C name
549 def _ParseItem(self
):
550 Line
= self
._RawData
.CurrentLine
551 TokenList
= Line
.split(DT
.TAB_VALUE_SPLIT
)
552 if len(TokenList
) < 4:
553 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_SPLIT
)
556 # Token space guid C name
558 PcdName
= GetSplitValueList(TokenList
[0], DT
.TAB_SPLIT
)
559 if len(PcdName
) != 2 or PcdName
[0] == '' or PcdName
[1] == '':
560 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_NAME
)
563 if not IsValidToken(CVAR_PATTERN
, Guid
):
564 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_CVAR_GUID
)
570 if not IsValidToken(CVAR_PATTERN
, CName
):
571 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_CVAR_PCDCNAME
)
573 self
._CheckReDefine
(Guid
+ DT
.TAB_SPLIT
+ CName
)
576 # Default value, may be C array, string or number
578 Data
= DT
.TAB_VALUE_SPLIT
.join(TokenList
[1:-2]).strip()
583 DataType
= TokenList
[-2].strip()
584 Valid
, Cause
= IsValidPcdDatum(DataType
, Data
)
586 self
._LoggerError
(Cause
)
587 PcdType
= self
._RawData
.CurrentScope
[0][0]
588 if PcdType
== DT
.TAB_PCDS_FEATURE_FLAG_NULL
.upper() and DataType
!= 'BOOLEAN':
589 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_FEATUREFLAG
)
591 # Token value is the last element in list.
593 Token
= TokenList
[-1].strip()
594 if not IsValidToken(PCD_TOKEN_PATTERN
, Token
):
595 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_TOKEN
% Token
)
596 elif not Token
.startswith('0x') and not Token
.startswith('0X'):
597 if long(Token
) > 4294967295:
598 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_TOKEN_INT
% Token
)
599 Token
= hex(long(Token
))[:-1]
601 IntToken
= long(Token
, 0)
602 if (Guid
, IntToken
) in self
.TokenMap
:
603 if self
.TokenMap
[Guid
, IntToken
] != CName
:
604 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_TOKEN_UNIQUE
%(Token))
606 self
.TokenMap
[Guid
, IntToken
] = CName
608 Item
= DecPcdItemObject(Guid
, CName
, Data
, DataType
, Token
)
609 self
.ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
614 # Parse GUID, PPI, Protocol section
616 class _DecGuid(_DecBase
):
617 def __init__(self
, RawData
):
618 _DecBase
.__init
__(self
, RawData
)
619 self
.GuidObj
= DecGuidObject(RawData
.Filename
)
620 self
.PpiObj
= DecPpiObject(RawData
.Filename
)
621 self
.ProtocolObj
= DecProtocolObject(RawData
.Filename
)
624 DT
.TAB_GUIDS
.upper() : self
.GuidObj
,
625 DT
.TAB_PPIS
.upper() : self
.PpiObj
,
626 DT
.TAB_PROTOCOLS
.upper() : self
.ProtocolObj
629 def GetDataObject(self
):
630 if self
._RawData
.CurrentScope
:
631 return self
.ObjectDict
[self
._RawData
.CurrentScope
[0][0]]
634 def GetGuidObject(self
):
637 def GetPpiObject(self
):
640 def GetProtocolObject(self
):
641 return self
.ProtocolObj
643 def _ParseItem(self
):
644 Line
= self
._RawData
.CurrentLine
645 TokenList
= GetSplitValueList(Line
, DT
.TAB_EQUAL_SPLIT
, 1)
646 if len(TokenList
) < 2:
647 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID
)
648 if TokenList
[0] == '':
649 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_NAME
)
650 if TokenList
[1] == '':
651 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_GUID
)
652 if not IsValidToken(CVAR_PATTERN
, TokenList
[0]):
653 self
._LoggerError
(ST
.ERR_DECPARSE_PCD_CVAR_GUID
)
655 self
._CheckReDefine
(TokenList
[0])
657 if TokenList
[1][0] != '{':
658 if not CheckGuidRegFormat(TokenList
[1]):
659 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_PKGGUID
)
660 GuidString
= TokenList
[1]
663 # Convert C format GUID to GUID string and Simple error check
665 GuidString
= GuidStructureStringToGuidString(TokenList
[1])
666 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidString
== '':
667 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_GUIDFORMAT
)
670 # Check C format GUID
672 if not IsValidCFormatGuid(TokenList
[1]):
673 self
._LoggerError
(ST
.ERR_DECPARSE_CGUID_GUIDFORMAT
)
675 Item
= DecGuidItemObject(TokenList
[0], TokenList
[1], GuidString
)
676 ItemObject
= self
.ObjectDict
[self
._RawData
.CurrentScope
[0][0]]
677 ItemObject
.AddItem(Item
, self
._RawData
.CurrentScope
)
682 # Parse user extention section
684 class _DecUserExtension(_DecBase
):
685 def __init__(self
, RawData
):
686 _DecBase
.__init
__(self
, RawData
)
687 self
.ItemObject
= DecUserExtensionObject(RawData
.Filename
)
691 def BlockStart(self
):
693 for Header
in self
._RawData
.CurrentScope
:
694 if Header
in self
._Headers
:
695 self
._LoggerError
(ST
.ERR_DECPARSE_UE_DUPLICATE
)
697 self
._Headers
.append(Header
)
699 for Item
in self
._CurItems
:
700 if Item
.UserId
== Header
[1] and Item
.IdString
== Header
[2]:
701 Item
.ArchAndModuleType
.append(Header
[3])
704 Item
= DecUserExtensionItemObject()
705 Item
.UserId
= Header
[1]
706 Item
.IdString
= Header
[2]
707 Item
.ArchAndModuleType
.append(Header
[3])
708 self
._CurItems
.append(Item
)
709 self
.ItemObject
.AddItem(Item
, None)
710 self
._LocalMacro
= {}
712 def _ParseItem(self
):
713 Line
= self
._RawData
.CurrentLine
715 for Item
in self
._CurItems
:
717 Item
.UserString
= '\n'.join([Item
.UserString
, Line
])
719 Item
.UserString
= Line
726 class Dec(_DecBase
, _DecComments
):
727 def __init__(self
, DecFile
, Parse
= True):
729 Content
= ConvertSpecialChar(open(DecFile
, 'rb').readlines())
730 except BaseException
:
731 Logger
.Error(TOOL_NAME
, FILE_OPEN_FAILURE
, File
=DecFile
,
732 ExtraData
=ST
.ERR_DECPARSE_FILEOPEN
% DecFile
)
733 RawData
= FileContent(DecFile
, Content
)
735 _DecComments
.__init
__(self
)
736 _DecBase
.__init
__(self
, RawData
)
738 self
._Define
= _DecDefine(RawData
)
739 self
._Include
= _DecInclude(RawData
)
740 self
._Guid
= _DecGuid(RawData
)
741 self
._LibClass
= _DecLibraryclass(RawData
)
742 self
._Pcd
= _DecPcd(RawData
)
743 self
._UserEx
= _DecUserExtension(RawData
)
746 # DEC file supported data types (one type per section)
748 self
._SectionParser
= {
749 DT
.TAB_DEC_DEFINES
.upper() : self
._Define
,
750 DT
.TAB_INCLUDES
.upper() : self
._Include
,
751 DT
.TAB_LIBRARY_CLASSES
.upper() : self
._LibClass
,
752 DT
.TAB_GUIDS
.upper() : self
._Guid
,
753 DT
.TAB_PPIS
.upper() : self
._Guid
,
754 DT
.TAB_PROTOCOLS
.upper() : self
._Guid
,
755 DT
.TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : self
._Pcd
,
756 DT
.TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : self
._Pcd
,
757 DT
.TAB_PCDS_FEATURE_FLAG_NULL
.upper() : self
._Pcd
,
758 DT
.TAB_PCDS_DYNAMIC_NULL
.upper() : self
._Pcd
,
759 DT
.TAB_PCDS_DYNAMIC_EX_NULL
.upper() : self
._Pcd
,
760 DT
.TAB_USER_EXTENSIONS
.upper() : self
._UserEx
764 self
.ParseDecComment()
767 # Parsing done, check required fields
769 self
.CheckRequiredFields()
771 def CheckRequiredFields(self
):
772 for SectionParser
in self
._SectionParser
.values():
773 if not SectionParser
.CheckRequiredFields():
780 def ParseDecComment(self
):
781 while not self
._RawData
.IsEndOfFile():
782 Line
, Comment
= CleanString(self
._RawData
.GetNextLine())
784 # Header must be pure comment
787 self
._RawData
.UndoNextLine()
791 self
._HeadComment
.append((Comment
, self
._RawData
.LineIndex
))
793 # Double '#' indicates end of header comments
795 if not Comment
or Comment
== DT
.TAB_SPECIAL_COMMENT
:
800 def _StopCurrentParsing(self
, Line
):
803 def _ParseItem(self
):
804 self
._SectionHeaderParser
()
805 if len(self
._RawData
.CurrentScope
) == 0:
806 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_EMPTY
)
808 SectionObj
= self
._SectionParser
[self
._RawData
.CurrentScope
[0][0]]
810 SectionObj
.BlockStart()
813 return SectionObj
.GetDataObject()
815 def _UserExtentionSectionParser(self
):
816 self
._RawData
.CurrentScope
= []
818 Section
= self
._RawData
.CurrentLine
[1:-1]
820 Par
= ParserHelper(Section
, self
._RawData
.Filename
)
825 Token
= Par
.GetToken()
826 if Token
.upper() != DT
.TAB_USER_EXTENSIONS
.upper():
827 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE
)
828 UserExtension
= Token
.upper()
830 Par
.AssertChar(DT
.TAB_SPLIT
, ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
834 Token
= Par
.GetToken()
835 if not IsValidUserId(Token
):
836 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE_USERID
)
839 Par
.AssertChar(DT
.TAB_SPLIT
, ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
843 Token
= Par
.GetToken()
844 if not IsValidIdString(Token
):
845 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UE_IDSTRING
)
849 if Par
.Expect(DT
.TAB_SPLIT
):
850 Token
= Par
.GetToken()
852 if not IsValidArch(Arch
):
853 self
._LoggerError
(ST
.ERR_DECPARSE_ARCH
)
856 if [UserExtension
, UserId
, IdString
, Arch
] not in \
857 self
._RawData
.CurrentScope
:
858 self
._RawData
.CurrentScope
.append(
859 [UserExtension
, UserId
, IdString
, Arch
]
862 if not Par
.Expect(DT
.TAB_COMMA_SPLIT
):
865 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMA
)
867 Par
.AssertEnd(ST
.ERR_DECPARSE_SECTION_UE
, self
._RawData
.LineIndex
)
869 if 'COMMON' in ArchList
and len(ArchList
) > 1:
870 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMON
)
872 ## Section header parser
874 # The section header is always in following format:
876 # [section_name.arch<.platform|module_type>]
878 def _SectionHeaderParser(self
):
879 if self
._RawData
.CurrentLine
[0] != DT
.TAB_SECTION_START
or self
._RawData
.CurrentLine
[-1] != DT
.TAB_SECTION_END
:
880 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_IDENTIFY
)
882 RawSection
= self
._RawData
.CurrentLine
[1:-1].strip().upper()
885 # Check defines section which is only allowed to occur once and
886 # no arch can be followed
888 if RawSection
.startswith(DT
.TAB_DEC_DEFINES
.upper()):
889 if RawSection
!= DT
.TAB_DEC_DEFINES
.upper():
890 self
._LoggerError
(ST
.ERR_DECPARSE_DEFINE_SECNAME
)
893 # Check user extension section
895 if RawSection
.startswith(DT
.TAB_USER_EXTENSIONS
.upper()):
896 return self
._UserExtentionSectionParser
()
898 self
._RawData
.CurrentScope
= []
901 for Item
in GetSplitValueList(RawSection
, DT
.TAB_COMMA_SPLIT
):
903 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBEMPTY
% self
._RawData
.CurrentLine
)
905 ItemList
= GetSplitValueList(Item
, DT
.TAB_SPLIT
)
908 # different types of PCD are permissible in one section
910 SectionName
= ItemList
[0]
911 if SectionName
not in self
._SectionParser
:
912 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_UNKNOW
% SectionName
)
914 if SectionName
not in SectionNames
:
915 SectionNames
.append(SectionName
)
918 # In DEC specification, all section headers have at most two part:
919 # SectionName.Arch except UserExtention
921 if len(ItemList
) > 2:
922 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBTOOMANY
% Item
)
924 if DT
.TAB_PCDS_FEATURE_FLAG_NULL
.upper() in SectionNames
and len(SectionNames
) > 1:
925 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_FEATUREFLAG
% DT
.TAB_PCDS_FEATURE_FLAG_NULL
)
929 if len(ItemList
) > 1:
931 if not IsValidArch(Str1
):
932 self
._LoggerError
(ST
.ERR_DECPARSE_ARCH
)
937 if [SectionName
, Str1
] not in self
._RawData
.CurrentScope
:
938 self
._RawData
.CurrentScope
.append([SectionName
, Str1
])
940 # 'COMMON' must not be used with specific ARCHs at the same section
942 if 'COMMON' in ArchList
and len(ArchList
) > 1:
943 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_COMMON
)
945 if len(SectionNames
) == 0:
946 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_SUBEMPTY
% self
._RawData
.CurrentLine
)
947 if len(SectionNames
) != 1:
948 for Sec
in SectionNames
:
949 if not Sec
.startswith(DT
.TAB_PCDS
.upper()):
950 self
._LoggerError
(ST
.ERR_DECPARSE_SECTION_NAME
% str(SectionNames
))
952 def GetDefineSectionObject(self
):
953 return self
._Define
.GetDataObject()
955 def GetIncludeSectionObject(self
):
956 return self
._Include
.GetDataObject()
958 def GetGuidSectionObject(self
):
959 return self
._Guid
.GetGuidObject()
961 def GetProtocolSectionObject(self
):
962 return self
._Guid
.GetProtocolObject()
964 def GetPpiSectionObject(self
):
965 return self
._Guid
.GetPpiObject()
967 def GetLibraryClassSectionObject(self
):
968 return self
._LibClass
.GetDataObject()
970 def GetPcdSectionObject(self
):
971 return self
._Pcd
.GetDataObject()
973 def GetUserExtensionSectionObject(self
):
974 return self
._UserEx
.GetDataObject()
976 def GetPackageSpecification(self
):
977 return self
._Define
.GetDataObject().GetPackageSpecification()
979 def GetPackageName(self
):
980 return self
._Define
.GetDataObject().GetPackageName()
982 def GetPackageGuid(self
):
983 return self
._Define
.GetDataObject().GetPackageGuid()
985 def GetPackageVersion(self
):
986 return self
._Define
.GetDataObject().GetPackageVersion()
988 def GetPackageUniFile(self
):
989 return self
._Define
.GetDataObject().GetPackageUniFile()