2 # This file is used to define common parsing related functions used in parsing
5 # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
7 # SPDX-License-Identifier: BSD-2-Clause-Patent
13 from __future__
import absolute_import
21 from Library
.StringUtils
import RaiseParserError
22 from Library
.StringUtils
import GetSplitValueList
23 from Library
.StringUtils
import CheckFileType
24 from Library
.StringUtils
import CheckFileExist
25 from Library
.StringUtils
import CleanString
26 from Library
.StringUtils
import NormPath
28 from Logger
.ToolError
import FILE_NOT_FOUND
29 from Logger
.ToolError
import FatalError
30 from Logger
.ToolError
import FORMAT_INVALID
32 from Library
import DataType
34 from Library
.Misc
import GuidStructureStringToGuidString
35 from Library
.Misc
import CheckGuidRegFormat
36 from Logger
import StringTable
as ST
37 import Logger
.Log
as Logger
39 from Parser
.DecParser
import Dec
40 from . import GlobalData
46 # Parse a string with format "[<Family>:]<ToolFlag>=Flag"
47 # Return (Family, ToolFlag, Flag)
49 # @param String: String with BuildOption statement
50 # @param File: The file which defines build option, used in error report
52 def GetBuildOption(String
, File
, LineNo
= -1):
53 (Family
, ToolChain
, Flag
) = ('', '', '')
54 if String
.find(DataType
.TAB_EQUAL_SPLIT
) < 0:
55 RaiseParserError(String
, 'BuildOptions', File
, \
56 '[<Family>:]<ToolFlag>=Flag', LineNo
)
58 List
= GetSplitValueList(String
, DataType
.TAB_EQUAL_SPLIT
, MaxSplit
=1)
59 if List
[0].find(':') > -1:
60 Family
= List
[0][ : List
[0].find(':')].strip()
61 ToolChain
= List
[0][List
[0].find(':') + 1 : ].strip()
63 ToolChain
= List
[0].strip()
64 Flag
= List
[1].strip()
65 return (Family
, ToolChain
, Flag
)
69 # Get Library of Dsc as <LibraryClassKeyWord>|<LibraryInstance>
71 # @param Item: String as <LibraryClassKeyWord>|<LibraryInstance>
72 # @param ContainerFile: The file which describes the library class, used for
75 def GetLibraryClass(Item
, ContainerFile
, WorkspaceDir
, LineNo
= -1):
76 List
= GetSplitValueList(Item
[0])
77 SupMod
= DataType
.SUP_MODULE_LIST_STRING
79 RaiseParserError(Item
[0], 'LibraryClasses', ContainerFile
, \
80 '<LibraryClassKeyWord>|<LibraryInstance>')
82 CheckFileType(List
[1], '.Inf', ContainerFile
, \
83 'library class instance', Item
[0], LineNo
)
84 CheckFileExist(WorkspaceDir
, List
[1], ContainerFile
, \
85 'LibraryClasses', Item
[0], LineNo
)
89 return (List
[0], List
[1], SupMod
)
93 # Get Library of Dsc as <LibraryClassKeyWord>[|<LibraryInstance>]
94 # [|<TokenSpaceGuidCName>.<PcdCName>]
96 # @param Item: String as <LibraryClassKeyWord>|<LibraryInstance>
97 # @param ContainerFile: The file which describes the library class, used for
100 def GetLibraryClassOfInf(Item
, ContainerFile
, WorkspaceDir
, LineNo
= -1):
101 ItemList
= GetSplitValueList((Item
[0] + DataType
.TAB_VALUE_SPLIT
* 2))
102 SupMod
= DataType
.SUP_MODULE_LIST_STRING
104 if len(ItemList
) > 5:
106 (Item
[0], 'LibraryClasses', ContainerFile
, \
107 '<LibraryClassKeyWord>[|<LibraryInstance>]\
108 [|<TokenSpaceGuidCName>.<PcdCName>]')
110 CheckFileType(ItemList
[1], '.Inf', ContainerFile
, 'LibraryClasses', \
112 CheckFileExist(WorkspaceDir
, ItemList
[1], ContainerFile
, \
113 'LibraryClasses', Item
[0], LineNo
)
114 if ItemList
[2] != '':
115 CheckPcdTokenInfo(ItemList
[2], 'LibraryClasses', \
116 ContainerFile
, LineNo
)
120 return (ItemList
[0], ItemList
[1], ItemList
[2], SupMod
)
124 # Check if PcdTokenInfo is following <TokenSpaceGuidCName>.<PcdCName>
126 # @param TokenInfoString: String to be checked
127 # @param Section: Used for error report
128 # @param File: Used for error report
130 def CheckPcdTokenInfo(TokenInfoString
, Section
, File
, LineNo
= -1):
131 Format
= '<TokenSpaceGuidCName>.<PcdCName>'
132 if TokenInfoString
!= '' and TokenInfoString
is not None:
133 TokenInfoList
= GetSplitValueList(TokenInfoString
, DataType
.TAB_SPLIT
)
134 if len(TokenInfoList
) == 2:
137 RaiseParserError(TokenInfoString
, Section
, File
, Format
, LineNo
)
141 # Get Pcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<Value>
142 # [|<Type>|<MaximumDatumSize>]
144 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|
145 # <Value>[|<Type>|<MaximumDatumSize>]
146 # @param ContainerFile: The file which describes the pcd, used for error
150 def GetPcd(Item
, Type
, ContainerFile
, LineNo
= -1):
151 TokenGuid
, TokenName
, Value
, MaximumDatumSize
, Token
= '', '', '', '', ''
152 List
= GetSplitValueList(Item
+ DataType
.TAB_VALUE_SPLIT
* 2)
154 if len(List
) < 4 or len(List
) > 6:
155 RaiseParserError(Item
, 'Pcds' + Type
, ContainerFile
, \
156 '<PcdTokenSpaceGuidCName>.<TokenCName>|<Value>\
157 [|<Type>|<MaximumDatumSize>]', LineNo
)
160 MaximumDatumSize
= List
[2]
163 if CheckPcdTokenInfo(List
[0], 'Pcds' + Type
, ContainerFile
, LineNo
):
164 (TokenGuid
, TokenName
) = GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
166 return (TokenName
, TokenGuid
, Value
, MaximumDatumSize
, Token
, Type
)
168 ## Get FeatureFlagPcd
170 # Get FeatureFlagPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE
172 # @param Item: String as <PcdTokenSpaceGuidCName>
173 # .<TokenCName>|TRUE/FALSE
174 # @param ContainerFile: The file which describes the pcd, used for error
177 def GetFeatureFlagPcd(Item
, Type
, ContainerFile
, LineNo
= -1):
178 TokenGuid
, TokenName
, Value
= '', '', ''
179 List
= GetSplitValueList(Item
)
181 RaiseParserError(Item
, 'Pcds' + Type
, ContainerFile
, \
182 '<PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE', \
186 if CheckPcdTokenInfo(List
[0], 'Pcds' + Type
, ContainerFile
, LineNo
):
187 (TokenGuid
, TokenName
) = GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
189 return (TokenName
, TokenGuid
, Value
, Type
)
191 ## Get DynamicDefaultPcd
193 # Get DynamicDefaultPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>
194 # |<Value>[|<DatumTyp>[|<MaxDatumSize>]]
196 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|
198 # @param ContainerFile: The file which describes the pcd, used for error
201 def GetDynamicDefaultPcd(Item
, Type
, ContainerFile
, LineNo
= -1):
202 TokenGuid
, TokenName
, Value
, DatumTyp
, MaxDatumSize
= '', '', '', '', ''
203 List
= GetSplitValueList(Item
+ DataType
.TAB_VALUE_SPLIT
* 2)
204 if len(List
) < 4 or len(List
) > 8:
205 RaiseParserError(Item
, 'Pcds' + Type
, ContainerFile
, \
206 '<PcdTokenSpaceGuidCName>.<TokenCName>|<Value>\
207 [|<DatumTyp>[|<MaxDatumSize>]]', LineNo
)
211 MaxDatumSize
= List
[3]
212 if CheckPcdTokenInfo(List
[0], 'Pcds' + Type
, ContainerFile
, LineNo
):
213 (TokenGuid
, TokenName
) = GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
215 return (TokenName
, TokenGuid
, Value
, DatumTyp
, MaxDatumSize
, Type
)
219 # Get DynamicHiiPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<String>|
220 # <VariableGuidCName>|<VariableOffset>[|<DefaultValue>[|<MaximumDatumSize>]]
222 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|
224 # @param ContainerFile: The file which describes the pcd, used for error
227 def GetDynamicHiiPcd(Item
, Type
, ContainerFile
, LineNo
= -1):
228 TokenGuid
, TokenName
, List1
, List2
, List3
, List4
, List5
= \
229 '', '', '', '', '', '', ''
230 List
= GetSplitValueList(Item
+ DataType
.TAB_VALUE_SPLIT
* 2)
231 if len(List
) < 6 or len(List
) > 8:
232 RaiseParserError(Item
, 'Pcds' + Type
, ContainerFile
, \
233 '<PcdTokenSpaceGuidCName>.<TokenCName>|<String>|\
234 <VariableGuidCName>|<VariableOffset>[|<DefaultValue>\
235 [|<MaximumDatumSize>]]', LineNo
)
237 List1
, List2
, List3
, List4
, List5
= \
238 List
[1], List
[2], List
[3], List
[4], List
[5]
239 if CheckPcdTokenInfo(List
[0], 'Pcds' + Type
, ContainerFile
, LineNo
):
240 (TokenGuid
, TokenName
) = GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
242 return (TokenName
, TokenGuid
, List1
, List2
, List3
, List4
, List5
, Type
)
246 # Get DynamicVpdPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|
247 # <VpdOffset>[|<MaximumDatumSize>]
249 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>
251 # @param ContainerFile: The file which describes the pcd, used for error
254 def GetDynamicVpdPcd(Item
, Type
, ContainerFile
, LineNo
= -1):
255 TokenGuid
, TokenName
, List1
, List2
= '', '', '', ''
256 List
= GetSplitValueList(Item
+ DataType
.TAB_VALUE_SPLIT
)
257 if len(List
) < 3 or len(List
) > 4:
258 RaiseParserError(Item
, 'Pcds' + Type
, ContainerFile
, \
259 '<PcdTokenSpaceGuidCName>.<TokenCName>|<VpdOffset>\
260 [|<MaximumDatumSize>]', LineNo
)
262 List1
, List2
= List
[1], List
[2]
263 if CheckPcdTokenInfo(List
[0], 'Pcds' + Type
, ContainerFile
, LineNo
):
264 (TokenGuid
, TokenName
) = GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
266 return (TokenName
, TokenGuid
, List1
, List2
, Type
)
270 # Parse block of the components defined in dsc file
271 # Set KeyValues as [ ['component name', [lib1, lib2, lib3],
272 # [bo1, bo2, bo3], [pcd1, pcd2, pcd3]], ...]
274 # @param Lines: The content to be parsed
275 # @param KeyValues: To store data after parsing
277 def GetComponent(Lines
, KeyValues
):
278 (FindBlock
, FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
279 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, FindPcdsDynamic
, \
280 FindPcdsDynamicEx
) = (False, False, False, False, False, False, False, \
283 LibraryClassItem
= []
290 # Ignore !include statement
292 if Line
.upper().find(DataType
.TAB_INCLUDE
.upper() + ' ') > -1 or \
293 Line
.upper().find(DataType
.TAB_DEFINE
+ ' ') > -1:
296 if FindBlock
== False:
299 # find '{' at line tail
301 if Line
.endswith('{'):
303 ListItem
= CleanString(Line
.rsplit('{', 1)[0], \
304 DataType
.TAB_COMMENT_SPLIT
)
307 # Parse a block content
310 if Line
.find('<LibraryClasses>') != -1:
311 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
312 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
313 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
314 (True, False, False, False, False, False, False)
316 if Line
.find('<BuildOptions>') != -1:
317 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
318 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
319 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
320 (False, True, False, False, False, False, False)
322 if Line
.find('<PcdsFeatureFlag>') != -1:
323 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
324 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
325 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
326 (False, False, True, False, False, False, False)
328 if Line
.find('<PcdsPatchableInModule>') != -1:
329 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
330 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
331 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
332 (False, False, False, True, False, False, False)
334 if Line
.find('<PcdsFixedAtBuild>') != -1:
335 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
336 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
337 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
338 (False, False, False, False, True, False, False)
340 if Line
.find('<PcdsDynamic>') != -1:
341 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
342 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
343 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
344 (False, False, False, False, False, True, False)
346 if Line
.find('<PcdsDynamicEx>') != -1:
347 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
348 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
349 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
350 (False, False, False, False, False, False, True)
352 if Line
.endswith('}'):
354 # find '}' at line tail
356 KeyValues
.append([ListItem
, LibraryClassItem
, \
358 (FindBlock
, FindLibraryClass
, FindBuildOption
, \
359 FindPcdsFeatureFlag
, FindPcdsPatchableInModule
, \
360 FindPcdsFixedAtBuild
, FindPcdsDynamic
, FindPcdsDynamicEx
) = \
361 (False, False, False, False, False, False, False, False)
362 LibraryClassItem
, BuildOption
, Pcd
= [], [], []
367 LibraryClassItem
.append(Line
)
368 elif FindBuildOption
:
369 BuildOption
.append(Line
)
370 elif FindPcdsFeatureFlag
:
371 Pcd
.append((DataType
.TAB_PCDS_FEATURE_FLAG_NULL
, Line
))
372 elif FindPcdsPatchableInModule
:
373 Pcd
.append((DataType
.TAB_PCDS_PATCHABLE_IN_MODULE_NULL
, Line
))
374 elif FindPcdsFixedAtBuild
:
375 Pcd
.append((DataType
.TAB_PCDS_FIXED_AT_BUILD_NULL
, Line
))
376 elif FindPcdsDynamic
:
377 Pcd
.append((DataType
.TAB_PCDS_DYNAMIC_DEFAULT_NULL
, Line
))
378 elif FindPcdsDynamicEx
:
379 Pcd
.append((DataType
.TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
, Line
))
381 KeyValues
.append([ListItem
, [], [], []])
387 # Parse a string with format "InfFilename [EXEC = ExecFilename]"
388 # Return (InfFilename, ExecFilename)
390 # @param String: String with EXEC statement
395 if String
.find('EXEC') > -1:
396 InfFilename
= String
[ : String
.find('EXEC')].strip()
397 ExecFilename
= String
[String
.find('EXEC') + len('EXEC') : ].strip()
399 InfFilename
= String
.strip()
401 return (InfFilename
, ExecFilename
)
405 # Parse block of the components defined in dsc file
406 # Set KeyValues as [ ['component name', [lib1, lib2, lib3], [bo1, bo2, bo3],
407 # [pcd1, pcd2, pcd3]], ...]
409 # @param Lines: The content to be parsed
410 # @param Key: Reserved
411 # @param KeyValues: To store data after parsing
412 # @param CommentCharacter: Comment char, used to ignore comment content
414 # @retval True Get component successfully
416 def GetComponents(Lines
, KeyValues
, CommentCharacter
):
417 if Lines
.find(DataType
.TAB_SECTION_END
) > -1:
418 Lines
= Lines
.split(DataType
.TAB_SECTION_END
, 1)[1]
419 (FindBlock
, FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
420 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, FindPcdsDynamic
, \
421 FindPcdsDynamicEx
) = \
422 (False, False, False, False, False, False, False, False)
424 LibraryClassItem
= []
428 LineList
= Lines
.split('\n')
429 for Line
in LineList
:
430 Line
= CleanString(Line
, CommentCharacter
)
431 if Line
is None or Line
== '':
434 if FindBlock
== False:
437 # find '{' at line tail
439 if Line
.endswith('{'):
441 ListItem
= CleanString(Line
.rsplit('{', 1)[0], CommentCharacter
)
444 # Parse a block content
447 if Line
.find('<LibraryClasses>') != -1:
448 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
449 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
450 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
451 (True, False, False, False, False, False, False)
453 if Line
.find('<BuildOptions>') != -1:
454 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
455 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
456 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
457 (False, True, False, False, False, False, False)
459 if Line
.find('<PcdsFeatureFlag>') != -1:
460 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
461 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
462 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
463 (False, False, True, False, False, False, False)
465 if Line
.find('<PcdsPatchableInModule>') != -1:
466 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
467 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
468 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
469 (False, False, False, True, False, False, False)
471 if Line
.find('<PcdsFixedAtBuild>') != -1:
472 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
473 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
474 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
475 (False, False, False, False, True, False, False)
477 if Line
.find('<PcdsDynamic>') != -1:
478 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
479 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
480 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
481 (False, False, False, False, False, True, False)
483 if Line
.find('<PcdsDynamicEx>') != -1:
484 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
485 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
486 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
487 (False, False, False, False, False, False, True)
489 if Line
.endswith('}'):
491 # find '}' at line tail
493 KeyValues
.append([ListItem
, LibraryClassItem
, BuildOption
, \
495 (FindBlock
, FindLibraryClass
, FindBuildOption
, \
496 FindPcdsFeatureFlag
, FindPcdsPatchableInModule
, \
497 FindPcdsFixedAtBuild
, FindPcdsDynamic
, FindPcdsDynamicEx
) = \
498 (False, False, False, False, False, False, False, False)
499 LibraryClassItem
, BuildOption
, Pcd
= [], [], []
504 LibraryClassItem
.append(Line
)
505 elif FindBuildOption
:
506 BuildOption
.append(Line
)
507 elif FindPcdsFeatureFlag
:
508 Pcd
.append((DataType
.TAB_PCDS_FEATURE_FLAG
, Line
))
509 elif FindPcdsPatchableInModule
:
510 Pcd
.append((DataType
.TAB_PCDS_PATCHABLE_IN_MODULE
, Line
))
511 elif FindPcdsFixedAtBuild
:
512 Pcd
.append((DataType
.TAB_PCDS_FIXED_AT_BUILD
, Line
))
513 elif FindPcdsDynamic
:
514 Pcd
.append((DataType
.TAB_PCDS_DYNAMIC
, Line
))
515 elif FindPcdsDynamicEx
:
516 Pcd
.append((DataType
.TAB_PCDS_DYNAMIC_EX
, Line
))
518 KeyValues
.append([ListItem
, [], [], []])
524 # Get Source of Inf as <Filename>[|<Family>[|<TagName>[|<ToolCode>
525 # [|<PcdFeatureFlag>]]]]
527 # @param Item: String as <Filename>[|<Family>[|<TagName>[|<ToolCode>
528 # [|<PcdFeatureFlag>]]]]
529 # @param ContainerFile: The file which describes the library class, used
532 def GetSource(Item
, ContainerFile
, FileRelativePath
, LineNo
= -1):
533 ItemNew
= Item
+ DataType
.TAB_VALUE_SPLIT
* 4
534 List
= GetSplitValueList(ItemNew
)
535 if len(List
) < 5 or len(List
) > 9:
536 RaiseParserError(Item
, 'Sources', ContainerFile
, \
537 '<Filename>[|<Family>[|<TagName>[|<ToolCode>\
538 [|<PcdFeatureFlag>]]]]', LineNo
)
539 List
[0] = NormPath(List
[0])
540 CheckFileExist(FileRelativePath
, List
[0], ContainerFile
, 'Sources', \
543 CheckPcdTokenInfo(List
[4], 'Sources', ContainerFile
, LineNo
)
545 return (List
[0], List
[1], List
[2], List
[3], List
[4])
549 # Get Binary of Inf as <Filename>[|<Family>[|<TagName>[|<ToolCode>
550 # [|<PcdFeatureFlag>]]]]
552 # @param Item: String as <Filename>[|<Family>[|<TagName>
553 # [|<ToolCode>[|<PcdFeatureFlag>]]]]
554 # @param ContainerFile: The file which describes the library class,
555 # used for error report
557 def GetBinary(Item
, ContainerFile
, LineNo
= -1):
558 ItemNew
= Item
+ DataType
.TAB_VALUE_SPLIT
559 List
= GetSplitValueList(ItemNew
)
560 if len(List
) < 3 or len(List
) > 5:
561 RaiseParserError(Item
, 'Binaries', ContainerFile
, \
562 "<FileType>|<Filename>[|<Target>\
563 [|<TokenSpaceGuidCName>.<PcdCName>]]", LineNo
)
567 CheckPcdTokenInfo(List
[3], 'Binaries', ContainerFile
, LineNo
)
568 return (List
[0], List
[1], List
[2], List
[3])
570 return (List
[0], List
[1], List
[2], '')
572 ## Get Guids/Protocols/Ppis
574 # Get Guids/Protocols/Ppis of Inf as <GuidCName>[|<PcdFeatureFlag>]
576 # @param Item: String as <GuidCName>[|<PcdFeatureFlag>]
577 # @param Type: Type of parsing string
578 # @param ContainerFile: The file which describes the library class,
579 # used for error report
581 def GetGuidsProtocolsPpisOfInf(Item
):
582 ItemNew
= Item
+ DataType
.TAB_VALUE_SPLIT
583 List
= GetSplitValueList(ItemNew
)
584 return (List
[0], List
[1])
586 ## Get Guids/Protocols/Ppis
588 # Get Guids/Protocols/Ppis of Dec as <GuidCName>=<GuidValue>
590 # @param Item: String as <GuidCName>=<GuidValue>
591 # @param Type: Type of parsing string
592 # @param ContainerFile: The file which describes the library class,
593 # used for error report
595 def GetGuidsProtocolsPpisOfDec(Item
, Type
, ContainerFile
, LineNo
= -1):
596 List
= GetSplitValueList(Item
, DataType
.TAB_EQUAL_SPLIT
)
598 RaiseParserError(Item
, Type
, ContainerFile
, '<CName>=<GuidValue>', \
601 #convert C-Format Guid to Register Format
603 if List
[1][0] == '{' and List
[1][-1] == '}':
604 RegisterFormatGuid
= GuidStructureStringToGuidString(List
[1])
605 if RegisterFormatGuid
== '':
606 RaiseParserError(Item
, Type
, ContainerFile
, \
607 'CFormat or RegisterFormat', LineNo
)
609 if CheckGuidRegFormat(List
[1]):
610 RegisterFormatGuid
= List
[1]
612 RaiseParserError(Item
, Type
, ContainerFile
, \
613 'CFormat or RegisterFormat', LineNo
)
615 return (List
[0], RegisterFormatGuid
)
619 # Get Package of Inf as <PackagePath>[|<PcdFeatureFlag>]
621 # @param Item: String as <PackagePath>[|<PcdFeatureFlag>]
622 # @param Type: Type of parsing string
623 # @param ContainerFile: The file which describes the library class,
624 # used for error report
626 def GetPackage(Item
, ContainerFile
, FileRelativePath
, LineNo
= -1):
627 ItemNew
= Item
+ DataType
.TAB_VALUE_SPLIT
628 List
= GetSplitValueList(ItemNew
)
629 CheckFileType(List
[0], '.Dec', ContainerFile
, 'package', List
[0], LineNo
)
630 CheckFileExist(FileRelativePath
, List
[0], ContainerFile
, 'Packages', \
633 CheckPcdTokenInfo(List
[1], 'Packages', ContainerFile
, LineNo
)
635 return (List
[0], List
[1])
637 ## Get Pcd Values of Inf
639 # Get Pcd of Inf as <TokenSpaceGuidCName>.<PcdCName>[|<Value>]
641 # @param Item: The string describes pcd
642 # @param Type: The type of Pcd
643 # @param File: The file which describes the pcd, used for error report
645 def GetPcdOfInf(Item
, Type
, File
, LineNo
):
646 Format
= '<TokenSpaceGuidCName>.<PcdCName>[|<Value>]'
647 TokenGuid
, TokenName
, Value
, InfType
= '', '', '', ''
649 if Type
== DataType
.TAB_PCDS_FIXED_AT_BUILD
:
650 InfType
= DataType
.TAB_INF_FIXED_PCD
651 elif Type
== DataType
.TAB_PCDS_PATCHABLE_IN_MODULE
:
652 InfType
= DataType
.TAB_INF_PATCH_PCD
653 elif Type
== DataType
.TAB_PCDS_FEATURE_FLAG
:
654 InfType
= DataType
.TAB_INF_FEATURE_PCD
655 elif Type
== DataType
.TAB_PCDS_DYNAMIC_EX
:
656 InfType
= DataType
.TAB_INF_PCD_EX
657 elif Type
== DataType
.TAB_PCDS_DYNAMIC
:
658 InfType
= DataType
.TAB_INF_PCD
659 List
= GetSplitValueList(Item
, DataType
.TAB_VALUE_SPLIT
, 1)
660 TokenInfo
= GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
661 if len(TokenInfo
) != 2:
662 RaiseParserError(Item
, InfType
, File
, Format
, LineNo
)
664 TokenGuid
= TokenInfo
[0]
665 TokenName
= TokenInfo
[1]
671 return (TokenGuid
, TokenName
, Value
, InfType
)
674 ## Get Pcd Values of Dec
676 # Get Pcd of Dec as <TokenSpcCName>.<TokenCName>|<Value>|<DatumType>|<Token>
677 # @param Item: Pcd item
678 # @param Type: Pcd type
679 # @param File: Dec file
680 # @param LineNo: Line number
682 def GetPcdOfDec(Item
, Type
, File
, LineNo
= -1):
683 Format
= '<TokenSpaceGuidCName>.<PcdCName>|<Value>|<DatumType>|<Token>'
684 TokenGuid
, TokenName
, Value
, DatumType
, Token
= '', '', '', '', ''
685 List
= GetSplitValueList(Item
)
687 RaiseParserError(Item
, 'Pcds' + Type
, File
, Format
, LineNo
)
692 TokenInfo
= GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
693 if len(TokenInfo
) != 2:
694 RaiseParserError(Item
, 'Pcds' + Type
, File
, Format
, LineNo
)
696 TokenGuid
= TokenInfo
[0]
697 TokenName
= TokenInfo
[1]
699 return (TokenGuid
, TokenName
, Value
, DatumType
, Token
, Type
)
701 ## Parse DEFINE statement
705 # @param LineValue: A DEFINE line value
706 # @param StartLine: A DEFINE start line
707 # @param Table: A table
708 # @param FileID: File ID
709 # @param Filename: File name
710 # @param SectionName: DEFINE section name
711 # @param SectionModel: DEFINE section model
712 # @param Arch: DEFINE arch
714 def ParseDefine(LineValue
, StartLine
, Table
, FileID
, SectionName
, \
716 Logger
.Debug(Logger
.DEBUG_2
, ST
.MSG_DEFINE_STATEMENT_FOUND
% (LineValue
, \
719 GetSplitValueList(CleanString\
720 (LineValue
[LineValue
.upper().\
721 find(DataType
.TAB_DEFINE
.upper() + ' ') + \
722 len(DataType
.TAB_DEFINE
+ ' ') : ]), \
723 DataType
.TAB_EQUAL_SPLIT
, 1)
724 Table
.Insert(DataType
.MODEL_META_DATA_DEFINE
, Define
[0], Define
[1], '', \
725 '', '', Arch
, SectionModel
, FileID
, StartLine
, -1, \
728 ## InsertSectionItems
730 # Insert item data of a section to a dict
732 # @param Model: A model
733 # @param CurrentSection: Current section
734 # @param SectionItemList: Section item list
735 # @param ArchList: Arch list
736 # @param ThirdList: Third list
737 # @param RecordSet: Record set
739 def InsertSectionItems(Model
, SectionItemList
, ArchList
, \
740 ThirdList
, RecordSet
):
742 # Insert each item data of a section
744 for Index
in range(0, len(ArchList
)):
745 Arch
= ArchList
[Index
]
746 Third
= ThirdList
[Index
]
748 Arch
= DataType
.TAB_ARCH_COMMON
750 Records
= RecordSet
[Model
]
751 for SectionItem
in SectionItemList
:
752 LineValue
, StartLine
, Comment
= SectionItem
[0], \
753 SectionItem
[1], SectionItem
[2]
755 Logger
.Debug(4, ST
.MSG_PARSING
% LineValue
)
757 # And then parse DEFINE statement
759 if LineValue
.upper().find(DataType
.TAB_DEFINE
.upper() + ' ') > -1:
762 # At last parse other sections
765 Records
.append([LineValue
, Arch
, StartLine
, IdNum
, Third
, Comment
])
768 RecordSet
[Model
] = Records
770 ## GenMetaDatSectionItem
773 # @param Value: A value
774 # @param List: A list
776 def GenMetaDatSectionItem(Key
, Value
, List
):
780 List
[Key
].append(Value
)
784 # get package name, guid, version info from dec files
786 # @param Path: File path
788 def GetPkgInfoFromDec(Path
):
793 Path
= Path
.replace('\\', '/')
795 if not os
.path
.exists(Path
):
796 Logger
.Error("\nUPT", FILE_NOT_FOUND
, File
=Path
)
798 if Path
in gPKG_INFO_DICT
:
799 return gPKG_INFO_DICT
[Path
]
803 if Path
not in GlobalData
.gPackageDict
:
804 DecParser
= Dec(Path
)
805 GlobalData
.gPackageDict
[Path
] = DecParser
807 DecParser
= GlobalData
.gPackageDict
[Path
]
809 PkgName
= DecParser
.GetPackageName()
810 PkgGuid
= DecParser
.GetPackageGuid()
811 PkgVersion
= DecParser
.GetPackageVersion()
812 gPKG_INFO_DICT
[Path
] = (PkgName
, PkgGuid
, PkgVersion
)
813 return PkgName
, PkgGuid
, PkgVersion
815 return None, None, None
818 ## GetWorkspacePackage
820 # Get a list of workspace package information.
822 def GetWorkspacePackage():
824 WorkspaceDir
= GlobalData
.gWORKSPACE
825 PackageDir
= GlobalData
.gPACKAGE_PATH
826 for PkgRoot
in [WorkspaceDir
] + PackageDir
:
827 for Root
, Dirs
, Files
in os
.walk(PkgRoot
):
833 if Dir
.startswith('.'):
836 if FileSp
.startswith('.'):
838 Ext
= os
.path
.splitext(FileSp
)[1]
839 if Ext
.lower() in ['.dec']:
841 (os
.path
.normpath(os
.path
.join(Root
, FileSp
)))
843 # abstract package guid, version info from DecFile List
846 for DecFile
in DecFileList
:
847 (PkgName
, PkgGuid
, PkgVersion
) = GetPkgInfoFromDec(DecFile
)
848 if PkgName
and PkgGuid
and PkgVersion
:
849 PkgList
.append((PkgName
, PkgGuid
, PkgVersion
, DecFile
))
853 ## GetWorkspaceModule
855 # Get a list of workspace modules.
857 def GetWorkspaceModule():
859 WorkspaceDir
= GlobalData
.gWORKSPACE
860 for Root
, Dirs
, Files
in os
.walk(WorkspaceDir
):
868 if Dir
.startswith('.'):
871 if FileSp
.startswith('.'):
873 Ext
= os
.path
.splitext(FileSp
)[1]
874 if Ext
.lower() in ['.inf']:
876 (os
.path
.normpath(os
.path
.join(Root
, FileSp
)))
880 ## MacroParser used to parse macro definition
882 # @param Line: The content contain linestring and line number
883 # @param FileName: The meta-file file name
884 # @param SectionType: Section for the Line belong to
885 # @param FileLocalMacros: A list contain Macro defined in [Defines] section.
887 def MacroParser(Line
, FileName
, SectionType
, FileLocalMacros
):
888 MacroDefPattern
= re
.compile("^(DEFINE)[ \t]+")
889 LineContent
= Line
[0]
891 Match
= MacroDefPattern
.match(LineContent
)
894 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
898 TokenList
= GetSplitValueList(LineContent
[Match
.end(1):], \
899 DataType
.TAB_EQUAL_SPLIT
, 1)
904 Logger
.Error('Parser', FORMAT_INVALID
, ST
.ERR_MACRONAME_NOGIVEN
,
905 ExtraData
=LineContent
, File
=FileName
, Line
=LineNo
)
906 if len(TokenList
) < 2:
907 Logger
.Error('Parser', FORMAT_INVALID
, ST
.ERR_MACROVALUE_NOGIVEN
,
908 ExtraData
=LineContent
, File
=FileName
, Line
=LineNo
)
910 Name
, Value
= TokenList
913 # DEFINE defined macros
915 if SectionType
== DataType
.MODEL_META_DATA_HEADER
:
916 FileLocalMacros
[Name
] = Value
918 ReIsValidMacroName
= re
.compile(r
"^[A-Z][A-Z0-9_]*$", re
.DOTALL
)
919 if ReIsValidMacroName
.match(Name
) is None:
920 Logger
.Error('Parser',
922 ST
.ERR_MACRONAME_INVALID
% (Name
),
923 ExtraData
=LineContent
,
927 # Validate MACRO Value
929 # <MacroDefinition> ::= [<Comments>]{0,}
930 # "DEFINE" <MACRO> "=" [{<PATH>} {<VALUE>}] <EOL>
931 # <Value> ::= {<NumVal>} {<Boolean>} {<AsciiString>} {<GUID>}
932 # {<CString>} {<UnicodeString>} {<CArray>}
934 # The definition of <NumVal>, <PATH>, <Boolean>, <GUID>, <CString>,
935 # <UnicodeString>, <CArray> are subset of <AsciiString>.
937 ReIsValidMacroValue
= re
.compile(r
"^[\x20-\x7e]*$", re
.DOTALL
)
938 if ReIsValidMacroValue
.match(Value
) is None:
939 Logger
.Error('Parser',
941 ST
.ERR_MACROVALUE_INVALID
% (Value
),
942 ExtraData
=LineContent
,
950 # generate section contents
952 # @param SectionName: indicate the name of the section, details refer to
954 # @param SectionDict: section statement dict, key is SectionAttrs(arch,
955 # moduletype or platform may exist as needed) list
956 # separated by space,
959 def GenSection(SectionName
, SectionDict
, SplitArch
=True, NeedBlankLine
=False):
961 for SectionAttrs
in SectionDict
:
962 StatementList
= SectionDict
[SectionAttrs
]
963 if SectionAttrs
and SectionName
!= 'Defines' and SectionAttrs
.strip().upper() != DataType
.TAB_ARCH_COMMON
:
965 ArchList
= GetSplitValueList(SectionAttrs
, DataType
.TAB_SPACE_SPLIT
)
967 if SectionName
!= 'UserExtensions':
968 ArchList
= GetSplitValueList(SectionAttrs
, DataType
.TAB_COMMENT_SPLIT
)
970 ArchList
= [SectionAttrs
]
971 for Index
in range(0, len(ArchList
)):
972 ArchList
[Index
] = ConvertArchForInstall(ArchList
[Index
])
973 Section
= '[' + SectionName
+ '.' + (', ' + SectionName
+ '.').join(ArchList
) + ']'
975 Section
= '[' + SectionName
+ ']'
976 Content
+= '\n' + Section
+ '\n'
977 if StatementList
is not None:
978 for Statement
in StatementList
:
979 LineList
= Statement
.split('\n')
981 for Line
in LineList
:
982 # ignore blank comment
983 if not Line
.replace("#", '').strip() and SectionName
not in ('Defines', 'Hob', 'Event', 'BootMode'):
985 # add two space before non-comments line except the comments in Defines section
986 if Line
.strip().startswith('#') and SectionName
== 'Defines':
987 NewStatement
+= "%s\n" % Line
989 NewStatement
+= " %s\n" % Line
991 Content
+= NewStatement
+ '\n'
993 Content
+= NewStatement
996 Content
= Content
[:-1]
997 if not Content
.replace('\\n', '').strip():
1001 ## ConvertArchForInstall
1002 # if Arch.upper() is in "IA32", "X64", "IPF", and "EBC", it must be upper case. "common" must be lower case.
1003 # Anything else, the case must be preserved
1005 # @param Arch: the arch string that need to be converted, it should be stripped before pass in
1006 # @return: the arch string that get converted
1008 def ConvertArchForInstall(Arch
):
1009 if Arch
.upper() in [DataType
.TAB_ARCH_IA32
, DataType
.TAB_ARCH_X64
,
1010 DataType
.TAB_ARCH_IPF
, DataType
.TAB_ARCH_EBC
]:
1012 elif Arch
.upper() == DataType
.TAB_ARCH_COMMON
: