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 # This program and the accompanying materials are licensed and made available
8 # under the terms and conditions of the BSD License which accompanies this
9 # distribution. The full text of the license may be found at
10 # http://opensource.org/licenses/bsd-license.php
12 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
26 from Library
.StringUtils
import RaiseParserError
27 from Library
.StringUtils
import GetSplitValueList
28 from Library
.StringUtils
import CheckFileType
29 from Library
.StringUtils
import CheckFileExist
30 from Library
.StringUtils
import CleanString
31 from Library
.StringUtils
import NormPath
33 from Logger
.ToolError
import FILE_NOT_FOUND
34 from Logger
.ToolError
import FatalError
35 from Logger
.ToolError
import FORMAT_INVALID
37 from Library
import DataType
39 from Library
.Misc
import GuidStructureStringToGuidString
40 from Library
.Misc
import CheckGuidRegFormat
41 from Logger
import StringTable
as ST
42 import Logger
.Log
as Logger
44 from Parser
.DecParser
import Dec
45 from . import GlobalData
51 # Parse a string with format "[<Family>:]<ToolFlag>=Flag"
52 # Return (Family, ToolFlag, Flag)
54 # @param String: String with BuildOption statement
55 # @param File: The file which defines build option, used in error report
57 def GetBuildOption(String
, File
, LineNo
= -1):
58 (Family
, ToolChain
, Flag
) = ('', '', '')
59 if String
.find(DataType
.TAB_EQUAL_SPLIT
) < 0:
60 RaiseParserError(String
, 'BuildOptions', File
, \
61 '[<Family>:]<ToolFlag>=Flag', LineNo
)
63 List
= GetSplitValueList(String
, DataType
.TAB_EQUAL_SPLIT
, MaxSplit
=1)
64 if List
[0].find(':') > -1:
65 Family
= List
[0][ : List
[0].find(':')].strip()
66 ToolChain
= List
[0][List
[0].find(':') + 1 : ].strip()
68 ToolChain
= List
[0].strip()
69 Flag
= List
[1].strip()
70 return (Family
, ToolChain
, Flag
)
74 # Get Library of Dsc as <LibraryClassKeyWord>|<LibraryInstance>
76 # @param Item: String as <LibraryClassKeyWord>|<LibraryInstance>
77 # @param ContainerFile: The file which describes the library class, used for
80 def GetLibraryClass(Item
, ContainerFile
, WorkspaceDir
, LineNo
= -1):
81 List
= GetSplitValueList(Item
[0])
82 SupMod
= DataType
.SUP_MODULE_LIST_STRING
84 RaiseParserError(Item
[0], 'LibraryClasses', ContainerFile
, \
85 '<LibraryClassKeyWord>|<LibraryInstance>')
87 CheckFileType(List
[1], '.Inf', ContainerFile
, \
88 'library class instance', Item
[0], LineNo
)
89 CheckFileExist(WorkspaceDir
, List
[1], ContainerFile
, \
90 'LibraryClasses', Item
[0], LineNo
)
94 return (List
[0], List
[1], SupMod
)
98 # Get Library of Dsc as <LibraryClassKeyWord>[|<LibraryInstance>]
99 # [|<TokenSpaceGuidCName>.<PcdCName>]
101 # @param Item: String as <LibraryClassKeyWord>|<LibraryInstance>
102 # @param ContainerFile: The file which describes the library class, used for
105 def GetLibraryClassOfInf(Item
, ContainerFile
, WorkspaceDir
, LineNo
= -1):
106 ItemList
= GetSplitValueList((Item
[0] + DataType
.TAB_VALUE_SPLIT
* 2))
107 SupMod
= DataType
.SUP_MODULE_LIST_STRING
109 if len(ItemList
) > 5:
111 (Item
[0], 'LibraryClasses', ContainerFile
, \
112 '<LibraryClassKeyWord>[|<LibraryInstance>]\
113 [|<TokenSpaceGuidCName>.<PcdCName>]')
115 CheckFileType(ItemList
[1], '.Inf', ContainerFile
, 'LibraryClasses', \
117 CheckFileExist(WorkspaceDir
, ItemList
[1], ContainerFile
, \
118 'LibraryClasses', Item
[0], LineNo
)
119 if ItemList
[2] != '':
120 CheckPcdTokenInfo(ItemList
[2], 'LibraryClasses', \
121 ContainerFile
, LineNo
)
125 return (ItemList
[0], ItemList
[1], ItemList
[2], SupMod
)
129 # Check if PcdTokenInfo is following <TokenSpaceGuidCName>.<PcdCName>
131 # @param TokenInfoString: String to be checked
132 # @param Section: Used for error report
133 # @param File: Used for error report
135 def CheckPcdTokenInfo(TokenInfoString
, Section
, File
, LineNo
= -1):
136 Format
= '<TokenSpaceGuidCName>.<PcdCName>'
137 if TokenInfoString
!= '' and TokenInfoString
is not None:
138 TokenInfoList
= GetSplitValueList(TokenInfoString
, DataType
.TAB_SPLIT
)
139 if len(TokenInfoList
) == 2:
142 RaiseParserError(TokenInfoString
, Section
, File
, Format
, LineNo
)
146 # Get Pcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<Value>
147 # [|<Type>|<MaximumDatumSize>]
149 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|
150 # <Value>[|<Type>|<MaximumDatumSize>]
151 # @param ContainerFile: The file which describes the pcd, used for error
155 def GetPcd(Item
, Type
, ContainerFile
, LineNo
= -1):
156 TokenGuid
, TokenName
, Value
, MaximumDatumSize
, Token
= '', '', '', '', ''
157 List
= GetSplitValueList(Item
+ DataType
.TAB_VALUE_SPLIT
* 2)
159 if len(List
) < 4 or len(List
) > 6:
160 RaiseParserError(Item
, 'Pcds' + Type
, ContainerFile
, \
161 '<PcdTokenSpaceGuidCName>.<TokenCName>|<Value>\
162 [|<Type>|<MaximumDatumSize>]', LineNo
)
165 MaximumDatumSize
= List
[2]
168 if CheckPcdTokenInfo(List
[0], 'Pcds' + Type
, ContainerFile
, LineNo
):
169 (TokenGuid
, TokenName
) = GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
171 return (TokenName
, TokenGuid
, Value
, MaximumDatumSize
, Token
, Type
)
173 ## Get FeatureFlagPcd
175 # Get FeatureFlagPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE
177 # @param Item: String as <PcdTokenSpaceGuidCName>
178 # .<TokenCName>|TRUE/FALSE
179 # @param ContainerFile: The file which describes the pcd, used for error
182 def GetFeatureFlagPcd(Item
, Type
, ContainerFile
, LineNo
= -1):
183 TokenGuid
, TokenName
, Value
= '', '', ''
184 List
= GetSplitValueList(Item
)
186 RaiseParserError(Item
, 'Pcds' + Type
, ContainerFile
, \
187 '<PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE', \
191 if CheckPcdTokenInfo(List
[0], 'Pcds' + Type
, ContainerFile
, LineNo
):
192 (TokenGuid
, TokenName
) = GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
194 return (TokenName
, TokenGuid
, Value
, Type
)
196 ## Get DynamicDefaultPcd
198 # Get DynamicDefaultPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>
199 # |<Value>[|<DatumTyp>[|<MaxDatumSize>]]
201 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|
203 # @param ContainerFile: The file which describes the pcd, used for error
206 def GetDynamicDefaultPcd(Item
, Type
, ContainerFile
, LineNo
= -1):
207 TokenGuid
, TokenName
, Value
, DatumTyp
, MaxDatumSize
= '', '', '', '', ''
208 List
= GetSplitValueList(Item
+ DataType
.TAB_VALUE_SPLIT
* 2)
209 if len(List
) < 4 or len(List
) > 8:
210 RaiseParserError(Item
, 'Pcds' + Type
, ContainerFile
, \
211 '<PcdTokenSpaceGuidCName>.<TokenCName>|<Value>\
212 [|<DatumTyp>[|<MaxDatumSize>]]', LineNo
)
216 MaxDatumSize
= List
[3]
217 if CheckPcdTokenInfo(List
[0], 'Pcds' + Type
, ContainerFile
, LineNo
):
218 (TokenGuid
, TokenName
) = GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
220 return (TokenName
, TokenGuid
, Value
, DatumTyp
, MaxDatumSize
, Type
)
224 # Get DynamicHiiPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<String>|
225 # <VariableGuidCName>|<VariableOffset>[|<DefaultValue>[|<MaximumDatumSize>]]
227 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|
229 # @param ContainerFile: The file which describes the pcd, used for error
232 def GetDynamicHiiPcd(Item
, Type
, ContainerFile
, LineNo
= -1):
233 TokenGuid
, TokenName
, List1
, List2
, List3
, List4
, List5
= \
234 '', '', '', '', '', '', ''
235 List
= GetSplitValueList(Item
+ DataType
.TAB_VALUE_SPLIT
* 2)
236 if len(List
) < 6 or len(List
) > 8:
237 RaiseParserError(Item
, 'Pcds' + Type
, ContainerFile
, \
238 '<PcdTokenSpaceGuidCName>.<TokenCName>|<String>|\
239 <VariableGuidCName>|<VariableOffset>[|<DefaultValue>\
240 [|<MaximumDatumSize>]]', LineNo
)
242 List1
, List2
, List3
, List4
, List5
= \
243 List
[1], List
[2], List
[3], List
[4], List
[5]
244 if CheckPcdTokenInfo(List
[0], 'Pcds' + Type
, ContainerFile
, LineNo
):
245 (TokenGuid
, TokenName
) = GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
247 return (TokenName
, TokenGuid
, List1
, List2
, List3
, List4
, List5
, Type
)
251 # Get DynamicVpdPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|
252 # <VpdOffset>[|<MaximumDatumSize>]
254 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>
256 # @param ContainerFile: The file which describes the pcd, used for error
259 def GetDynamicVpdPcd(Item
, Type
, ContainerFile
, LineNo
= -1):
260 TokenGuid
, TokenName
, List1
, List2
= '', '', '', ''
261 List
= GetSplitValueList(Item
+ DataType
.TAB_VALUE_SPLIT
)
262 if len(List
) < 3 or len(List
) > 4:
263 RaiseParserError(Item
, 'Pcds' + Type
, ContainerFile
, \
264 '<PcdTokenSpaceGuidCName>.<TokenCName>|<VpdOffset>\
265 [|<MaximumDatumSize>]', LineNo
)
267 List1
, List2
= List
[1], List
[2]
268 if CheckPcdTokenInfo(List
[0], 'Pcds' + Type
, ContainerFile
, LineNo
):
269 (TokenGuid
, TokenName
) = GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
271 return (TokenName
, TokenGuid
, List1
, List2
, Type
)
275 # Parse block of the components defined in dsc file
276 # Set KeyValues as [ ['component name', [lib1, lib2, lib3],
277 # [bo1, bo2, bo3], [pcd1, pcd2, pcd3]], ...]
279 # @param Lines: The content to be parsed
280 # @param KeyValues: To store data after parsing
282 def GetComponent(Lines
, KeyValues
):
283 (FindBlock
, FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
284 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, FindPcdsDynamic
, \
285 FindPcdsDynamicEx
) = (False, False, False, False, False, False, False, \
288 LibraryClassItem
= []
295 # Ignore !include statement
297 if Line
.upper().find(DataType
.TAB_INCLUDE
.upper() + ' ') > -1 or \
298 Line
.upper().find(DataType
.TAB_DEFINE
+ ' ') > -1:
301 if FindBlock
== False:
304 # find '{' at line tail
306 if Line
.endswith('{'):
308 ListItem
= CleanString(Line
.rsplit('{', 1)[0], \
309 DataType
.TAB_COMMENT_SPLIT
)
312 # Parse a block content
315 if Line
.find('<LibraryClasses>') != -1:
316 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
317 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
318 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
319 (True, False, False, False, False, False, False)
321 if Line
.find('<BuildOptions>') != -1:
322 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
323 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
324 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
325 (False, True, False, False, False, False, False)
327 if Line
.find('<PcdsFeatureFlag>') != -1:
328 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
329 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
330 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
331 (False, False, True, False, False, False, False)
333 if Line
.find('<PcdsPatchableInModule>') != -1:
334 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
335 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
336 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
337 (False, False, False, True, False, False, False)
339 if Line
.find('<PcdsFixedAtBuild>') != -1:
340 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
341 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
342 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
343 (False, False, False, False, True, False, False)
345 if Line
.find('<PcdsDynamic>') != -1:
346 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
347 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
348 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
349 (False, False, False, False, False, True, False)
351 if Line
.find('<PcdsDynamicEx>') != -1:
352 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
353 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
354 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
355 (False, False, False, False, False, False, True)
357 if Line
.endswith('}'):
359 # find '}' at line tail
361 KeyValues
.append([ListItem
, LibraryClassItem
, \
363 (FindBlock
, FindLibraryClass
, FindBuildOption
, \
364 FindPcdsFeatureFlag
, FindPcdsPatchableInModule
, \
365 FindPcdsFixedAtBuild
, FindPcdsDynamic
, FindPcdsDynamicEx
) = \
366 (False, False, False, False, False, False, False, False)
367 LibraryClassItem
, BuildOption
, Pcd
= [], [], []
372 LibraryClassItem
.append(Line
)
373 elif FindBuildOption
:
374 BuildOption
.append(Line
)
375 elif FindPcdsFeatureFlag
:
376 Pcd
.append((DataType
.TAB_PCDS_FEATURE_FLAG_NULL
, Line
))
377 elif FindPcdsPatchableInModule
:
378 Pcd
.append((DataType
.TAB_PCDS_PATCHABLE_IN_MODULE_NULL
, Line
))
379 elif FindPcdsFixedAtBuild
:
380 Pcd
.append((DataType
.TAB_PCDS_FIXED_AT_BUILD_NULL
, Line
))
381 elif FindPcdsDynamic
:
382 Pcd
.append((DataType
.TAB_PCDS_DYNAMIC_DEFAULT_NULL
, Line
))
383 elif FindPcdsDynamicEx
:
384 Pcd
.append((DataType
.TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
, Line
))
386 KeyValues
.append([ListItem
, [], [], []])
392 # Parse a string with format "InfFilename [EXEC = ExecFilename]"
393 # Return (InfFilename, ExecFilename)
395 # @param String: String with EXEC statement
400 if String
.find('EXEC') > -1:
401 InfFilename
= String
[ : String
.find('EXEC')].strip()
402 ExecFilename
= String
[String
.find('EXEC') + len('EXEC') : ].strip()
404 InfFilename
= String
.strip()
406 return (InfFilename
, ExecFilename
)
410 # Parse block of the components defined in dsc file
411 # Set KeyValues as [ ['component name', [lib1, lib2, lib3], [bo1, bo2, bo3],
412 # [pcd1, pcd2, pcd3]], ...]
414 # @param Lines: The content to be parsed
415 # @param Key: Reserved
416 # @param KeyValues: To store data after parsing
417 # @param CommentCharacter: Comment char, used to ignore comment content
419 # @retval True Get component successfully
421 def GetComponents(Lines
, KeyValues
, CommentCharacter
):
422 if Lines
.find(DataType
.TAB_SECTION_END
) > -1:
423 Lines
= Lines
.split(DataType
.TAB_SECTION_END
, 1)[1]
424 (FindBlock
, FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
425 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, FindPcdsDynamic
, \
426 FindPcdsDynamicEx
) = \
427 (False, False, False, False, False, False, False, False)
429 LibraryClassItem
= []
433 LineList
= Lines
.split('\n')
434 for Line
in LineList
:
435 Line
= CleanString(Line
, CommentCharacter
)
436 if Line
is None or Line
== '':
439 if FindBlock
== False:
442 # find '{' at line tail
444 if Line
.endswith('{'):
446 ListItem
= CleanString(Line
.rsplit('{', 1)[0], CommentCharacter
)
449 # Parse a block content
452 if Line
.find('<LibraryClasses>') != -1:
453 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
454 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
455 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
456 (True, False, False, False, False, False, False)
458 if Line
.find('<BuildOptions>') != -1:
459 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
460 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
461 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
462 (False, True, False, False, False, False, False)
464 if Line
.find('<PcdsFeatureFlag>') != -1:
465 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
466 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
467 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
468 (False, False, True, False, False, False, False)
470 if Line
.find('<PcdsPatchableInModule>') != -1:
471 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
472 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
473 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
474 (False, False, False, True, False, False, False)
476 if Line
.find('<PcdsFixedAtBuild>') != -1:
477 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
478 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
479 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
480 (False, False, False, False, True, False, False)
482 if Line
.find('<PcdsDynamic>') != -1:
483 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
484 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
485 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
486 (False, False, False, False, False, True, False)
488 if Line
.find('<PcdsDynamicEx>') != -1:
489 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
490 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
491 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
492 (False, False, False, False, False, False, True)
494 if Line
.endswith('}'):
496 # find '}' at line tail
498 KeyValues
.append([ListItem
, LibraryClassItem
, BuildOption
, \
500 (FindBlock
, FindLibraryClass
, FindBuildOption
, \
501 FindPcdsFeatureFlag
, FindPcdsPatchableInModule
, \
502 FindPcdsFixedAtBuild
, FindPcdsDynamic
, FindPcdsDynamicEx
) = \
503 (False, False, False, False, False, False, False, False)
504 LibraryClassItem
, BuildOption
, Pcd
= [], [], []
509 LibraryClassItem
.append(Line
)
510 elif FindBuildOption
:
511 BuildOption
.append(Line
)
512 elif FindPcdsFeatureFlag
:
513 Pcd
.append((DataType
.TAB_PCDS_FEATURE_FLAG
, Line
))
514 elif FindPcdsPatchableInModule
:
515 Pcd
.append((DataType
.TAB_PCDS_PATCHABLE_IN_MODULE
, Line
))
516 elif FindPcdsFixedAtBuild
:
517 Pcd
.append((DataType
.TAB_PCDS_FIXED_AT_BUILD
, Line
))
518 elif FindPcdsDynamic
:
519 Pcd
.append((DataType
.TAB_PCDS_DYNAMIC
, Line
))
520 elif FindPcdsDynamicEx
:
521 Pcd
.append((DataType
.TAB_PCDS_DYNAMIC_EX
, Line
))
523 KeyValues
.append([ListItem
, [], [], []])
529 # Get Source of Inf as <Filename>[|<Family>[|<TagName>[|<ToolCode>
530 # [|<PcdFeatureFlag>]]]]
532 # @param Item: String as <Filename>[|<Family>[|<TagName>[|<ToolCode>
533 # [|<PcdFeatureFlag>]]]]
534 # @param ContainerFile: The file which describes the library class, used
537 def GetSource(Item
, ContainerFile
, FileRelativePath
, LineNo
= -1):
538 ItemNew
= Item
+ DataType
.TAB_VALUE_SPLIT
* 4
539 List
= GetSplitValueList(ItemNew
)
540 if len(List
) < 5 or len(List
) > 9:
541 RaiseParserError(Item
, 'Sources', ContainerFile
, \
542 '<Filename>[|<Family>[|<TagName>[|<ToolCode>\
543 [|<PcdFeatureFlag>]]]]', LineNo
)
544 List
[0] = NormPath(List
[0])
545 CheckFileExist(FileRelativePath
, List
[0], ContainerFile
, 'Sources', \
548 CheckPcdTokenInfo(List
[4], 'Sources', ContainerFile
, LineNo
)
550 return (List
[0], List
[1], List
[2], List
[3], List
[4])
554 # Get Binary of Inf as <Filename>[|<Family>[|<TagName>[|<ToolCode>
555 # [|<PcdFeatureFlag>]]]]
557 # @param Item: String as <Filename>[|<Family>[|<TagName>
558 # [|<ToolCode>[|<PcdFeatureFlag>]]]]
559 # @param ContainerFile: The file which describes the library class,
560 # used for error report
562 def GetBinary(Item
, ContainerFile
, LineNo
= -1):
563 ItemNew
= Item
+ DataType
.TAB_VALUE_SPLIT
564 List
= GetSplitValueList(ItemNew
)
565 if len(List
) < 3 or len(List
) > 5:
566 RaiseParserError(Item
, 'Binaries', ContainerFile
, \
567 "<FileType>|<Filename>[|<Target>\
568 [|<TokenSpaceGuidCName>.<PcdCName>]]", LineNo
)
572 CheckPcdTokenInfo(List
[3], 'Binaries', ContainerFile
, LineNo
)
573 return (List
[0], List
[1], List
[2], List
[3])
575 return (List
[0], List
[1], List
[2], '')
577 ## Get Guids/Protocols/Ppis
579 # Get Guids/Protocols/Ppis of Inf as <GuidCName>[|<PcdFeatureFlag>]
581 # @param Item: String as <GuidCName>[|<PcdFeatureFlag>]
582 # @param Type: Type of parsing string
583 # @param ContainerFile: The file which describes the library class,
584 # used for error report
586 def GetGuidsProtocolsPpisOfInf(Item
):
587 ItemNew
= Item
+ DataType
.TAB_VALUE_SPLIT
588 List
= GetSplitValueList(ItemNew
)
589 return (List
[0], List
[1])
591 ## Get Guids/Protocols/Ppis
593 # Get Guids/Protocols/Ppis of Dec as <GuidCName>=<GuidValue>
595 # @param Item: String as <GuidCName>=<GuidValue>
596 # @param Type: Type of parsing string
597 # @param ContainerFile: The file which describes the library class,
598 # used for error report
600 def GetGuidsProtocolsPpisOfDec(Item
, Type
, ContainerFile
, LineNo
= -1):
601 List
= GetSplitValueList(Item
, DataType
.TAB_EQUAL_SPLIT
)
603 RaiseParserError(Item
, Type
, ContainerFile
, '<CName>=<GuidValue>', \
606 #convert C-Format Guid to Register Format
608 if List
[1][0] == '{' and List
[1][-1] == '}':
609 RegisterFormatGuid
= GuidStructureStringToGuidString(List
[1])
610 if RegisterFormatGuid
== '':
611 RaiseParserError(Item
, Type
, ContainerFile
, \
612 'CFormat or RegisterFormat', LineNo
)
614 if CheckGuidRegFormat(List
[1]):
615 RegisterFormatGuid
= List
[1]
617 RaiseParserError(Item
, Type
, ContainerFile
, \
618 'CFormat or RegisterFormat', LineNo
)
620 return (List
[0], RegisterFormatGuid
)
624 # Get Package of Inf as <PackagePath>[|<PcdFeatureFlag>]
626 # @param Item: String as <PackagePath>[|<PcdFeatureFlag>]
627 # @param Type: Type of parsing string
628 # @param ContainerFile: The file which describes the library class,
629 # used for error report
631 def GetPackage(Item
, ContainerFile
, FileRelativePath
, LineNo
= -1):
632 ItemNew
= Item
+ DataType
.TAB_VALUE_SPLIT
633 List
= GetSplitValueList(ItemNew
)
634 CheckFileType(List
[0], '.Dec', ContainerFile
, 'package', List
[0], LineNo
)
635 CheckFileExist(FileRelativePath
, List
[0], ContainerFile
, 'Packages', \
638 CheckPcdTokenInfo(List
[1], 'Packages', ContainerFile
, LineNo
)
640 return (List
[0], List
[1])
642 ## Get Pcd Values of Inf
644 # Get Pcd of Inf as <TokenSpaceGuidCName>.<PcdCName>[|<Value>]
646 # @param Item: The string describes pcd
647 # @param Type: The type of Pcd
648 # @param File: The file which describes the pcd, used for error report
650 def GetPcdOfInf(Item
, Type
, File
, LineNo
):
651 Format
= '<TokenSpaceGuidCName>.<PcdCName>[|<Value>]'
652 TokenGuid
, TokenName
, Value
, InfType
= '', '', '', ''
654 if Type
== DataType
.TAB_PCDS_FIXED_AT_BUILD
:
655 InfType
= DataType
.TAB_INF_FIXED_PCD
656 elif Type
== DataType
.TAB_PCDS_PATCHABLE_IN_MODULE
:
657 InfType
= DataType
.TAB_INF_PATCH_PCD
658 elif Type
== DataType
.TAB_PCDS_FEATURE_FLAG
:
659 InfType
= DataType
.TAB_INF_FEATURE_PCD
660 elif Type
== DataType
.TAB_PCDS_DYNAMIC_EX
:
661 InfType
= DataType
.TAB_INF_PCD_EX
662 elif Type
== DataType
.TAB_PCDS_DYNAMIC
:
663 InfType
= DataType
.TAB_INF_PCD
664 List
= GetSplitValueList(Item
, DataType
.TAB_VALUE_SPLIT
, 1)
665 TokenInfo
= GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
666 if len(TokenInfo
) != 2:
667 RaiseParserError(Item
, InfType
, File
, Format
, LineNo
)
669 TokenGuid
= TokenInfo
[0]
670 TokenName
= TokenInfo
[1]
676 return (TokenGuid
, TokenName
, Value
, InfType
)
679 ## Get Pcd Values of Dec
681 # Get Pcd of Dec as <TokenSpcCName>.<TokenCName>|<Value>|<DatumType>|<Token>
682 # @param Item: Pcd item
683 # @param Type: Pcd type
684 # @param File: Dec file
685 # @param LineNo: Line number
687 def GetPcdOfDec(Item
, Type
, File
, LineNo
= -1):
688 Format
= '<TokenSpaceGuidCName>.<PcdCName>|<Value>|<DatumType>|<Token>'
689 TokenGuid
, TokenName
, Value
, DatumType
, Token
= '', '', '', '', ''
690 List
= GetSplitValueList(Item
)
692 RaiseParserError(Item
, 'Pcds' + Type
, File
, Format
, LineNo
)
697 TokenInfo
= GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
698 if len(TokenInfo
) != 2:
699 RaiseParserError(Item
, 'Pcds' + Type
, File
, Format
, LineNo
)
701 TokenGuid
= TokenInfo
[0]
702 TokenName
= TokenInfo
[1]
704 return (TokenGuid
, TokenName
, Value
, DatumType
, Token
, Type
)
706 ## Parse DEFINE statement
710 # @param LineValue: A DEFINE line value
711 # @param StartLine: A DEFINE start line
712 # @param Table: A table
713 # @param FileID: File ID
714 # @param Filename: File name
715 # @param SectionName: DEFINE section name
716 # @param SectionModel: DEFINE section model
717 # @param Arch: DEFINE arch
719 def ParseDefine(LineValue
, StartLine
, Table
, FileID
, SectionName
, \
721 Logger
.Debug(Logger
.DEBUG_2
, ST
.MSG_DEFINE_STATEMENT_FOUND
% (LineValue
, \
724 GetSplitValueList(CleanString\
725 (LineValue
[LineValue
.upper().\
726 find(DataType
.TAB_DEFINE
.upper() + ' ') + \
727 len(DataType
.TAB_DEFINE
+ ' ') : ]), \
728 DataType
.TAB_EQUAL_SPLIT
, 1)
729 Table
.Insert(DataType
.MODEL_META_DATA_DEFINE
, Define
[0], Define
[1], '', \
730 '', '', Arch
, SectionModel
, FileID
, StartLine
, -1, \
733 ## InsertSectionItems
735 # Insert item data of a section to a dict
737 # @param Model: A model
738 # @param CurrentSection: Current section
739 # @param SectionItemList: Section item list
740 # @param ArchList: Arch list
741 # @param ThirdList: Third list
742 # @param RecordSet: Record set
744 def InsertSectionItems(Model
, SectionItemList
, ArchList
, \
745 ThirdList
, RecordSet
):
747 # Insert each item data of a section
749 for Index
in range(0, len(ArchList
)):
750 Arch
= ArchList
[Index
]
751 Third
= ThirdList
[Index
]
753 Arch
= DataType
.TAB_ARCH_COMMON
755 Records
= RecordSet
[Model
]
756 for SectionItem
in SectionItemList
:
757 LineValue
, StartLine
, Comment
= SectionItem
[0], \
758 SectionItem
[1], SectionItem
[2]
760 Logger
.Debug(4, ST
.MSG_PARSING
% LineValue
)
762 # And then parse DEFINE statement
764 if LineValue
.upper().find(DataType
.TAB_DEFINE
.upper() + ' ') > -1:
767 # At last parse other sections
770 Records
.append([LineValue
, Arch
, StartLine
, IdNum
, Third
, Comment
])
773 RecordSet
[Model
] = Records
775 ## GenMetaDatSectionItem
778 # @param Value: A value
779 # @param List: A list
781 def GenMetaDatSectionItem(Key
, Value
, List
):
785 List
[Key
].append(Value
)
789 # get package name, guid, version info from dec files
791 # @param Path: File path
793 def GetPkgInfoFromDec(Path
):
798 Path
= Path
.replace('\\', '/')
800 if not os
.path
.exists(Path
):
801 Logger
.Error("\nUPT", FILE_NOT_FOUND
, File
=Path
)
803 if Path
in gPKG_INFO_DICT
:
804 return gPKG_INFO_DICT
[Path
]
808 if Path
not in GlobalData
.gPackageDict
:
809 DecParser
= Dec(Path
)
810 GlobalData
.gPackageDict
[Path
] = DecParser
812 DecParser
= GlobalData
.gPackageDict
[Path
]
814 PkgName
= DecParser
.GetPackageName()
815 PkgGuid
= DecParser
.GetPackageGuid()
816 PkgVersion
= DecParser
.GetPackageVersion()
817 gPKG_INFO_DICT
[Path
] = (PkgName
, PkgGuid
, PkgVersion
)
818 return PkgName
, PkgGuid
, PkgVersion
820 return None, None, None
823 ## GetWorkspacePackage
825 # Get a list of workspace package information.
827 def GetWorkspacePackage():
829 WorkspaceDir
= GlobalData
.gWORKSPACE
830 PackageDir
= GlobalData
.gPACKAGE_PATH
831 for PkgRoot
in [WorkspaceDir
] + PackageDir
:
832 for Root
, Dirs
, Files
in os
.walk(PkgRoot
):
838 if Dir
.startswith('.'):
841 if FileSp
.startswith('.'):
843 Ext
= os
.path
.splitext(FileSp
)[1]
844 if Ext
.lower() in ['.dec']:
846 (os
.path
.normpath(os
.path
.join(Root
, FileSp
)))
848 # abstract package guid, version info from DecFile List
851 for DecFile
in DecFileList
:
852 (PkgName
, PkgGuid
, PkgVersion
) = GetPkgInfoFromDec(DecFile
)
853 if PkgName
and PkgGuid
and PkgVersion
:
854 PkgList
.append((PkgName
, PkgGuid
, PkgVersion
, DecFile
))
858 ## GetWorkspaceModule
860 # Get a list of workspace modules.
862 def GetWorkspaceModule():
864 WorkspaceDir
= GlobalData
.gWORKSPACE
865 for Root
, Dirs
, Files
in os
.walk(WorkspaceDir
):
873 if Dir
.startswith('.'):
876 if FileSp
.startswith('.'):
878 Ext
= os
.path
.splitext(FileSp
)[1]
879 if Ext
.lower() in ['.inf']:
881 (os
.path
.normpath(os
.path
.join(Root
, FileSp
)))
885 ## MacroParser used to parse macro definition
887 # @param Line: The content contain linestring and line number
888 # @param FileName: The meta-file file name
889 # @param SectionType: Section for the Line belong to
890 # @param FileLocalMacros: A list contain Macro defined in [Defines] section.
892 def MacroParser(Line
, FileName
, SectionType
, FileLocalMacros
):
893 MacroDefPattern
= re
.compile("^(DEFINE)[ \t]+")
894 LineContent
= Line
[0]
896 Match
= MacroDefPattern
.match(LineContent
)
899 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
903 TokenList
= GetSplitValueList(LineContent
[Match
.end(1):], \
904 DataType
.TAB_EQUAL_SPLIT
, 1)
909 Logger
.Error('Parser', FORMAT_INVALID
, ST
.ERR_MACRONAME_NOGIVEN
,
910 ExtraData
=LineContent
, File
=FileName
, Line
=LineNo
)
911 if len(TokenList
) < 2:
912 Logger
.Error('Parser', FORMAT_INVALID
, ST
.ERR_MACROVALUE_NOGIVEN
,
913 ExtraData
=LineContent
, File
=FileName
, Line
=LineNo
)
915 Name
, Value
= TokenList
918 # DEFINE defined macros
920 if SectionType
== DataType
.MODEL_META_DATA_HEADER
:
921 FileLocalMacros
[Name
] = Value
923 ReIsValidMacroName
= re
.compile(r
"^[A-Z][A-Z0-9_]*$", re
.DOTALL
)
924 if ReIsValidMacroName
.match(Name
) is None:
925 Logger
.Error('Parser',
927 ST
.ERR_MACRONAME_INVALID
% (Name
),
928 ExtraData
=LineContent
,
932 # Validate MACRO Value
934 # <MacroDefinition> ::= [<Comments>]{0,}
935 # "DEFINE" <MACRO> "=" [{<PATH>} {<VALUE>}] <EOL>
936 # <Value> ::= {<NumVal>} {<Boolean>} {<AsciiString>} {<GUID>}
937 # {<CString>} {<UnicodeString>} {<CArray>}
939 # The definition of <NumVal>, <PATH>, <Boolean>, <GUID>, <CString>,
940 # <UnicodeString>, <CArray> are subset of <AsciiString>.
942 ReIsValidMacroValue
= re
.compile(r
"^[\x20-\x7e]*$", re
.DOTALL
)
943 if ReIsValidMacroValue
.match(Value
) is None:
944 Logger
.Error('Parser',
946 ST
.ERR_MACROVALUE_INVALID
% (Value
),
947 ExtraData
=LineContent
,
955 # generate section contents
957 # @param SectionName: indicate the name of the section, details refer to
959 # @param SectionDict: section statement dict, key is SectionAttrs(arch,
960 # moduletype or platform may exist as needed) list
961 # seperated by space,
964 def GenSection(SectionName
, SectionDict
, SplitArch
=True, NeedBlankLine
=False):
966 for SectionAttrs
in SectionDict
:
967 StatementList
= SectionDict
[SectionAttrs
]
968 if SectionAttrs
and SectionName
!= 'Defines' and SectionAttrs
.strip().upper() != DataType
.TAB_ARCH_COMMON
:
970 ArchList
= GetSplitValueList(SectionAttrs
, DataType
.TAB_SPACE_SPLIT
)
972 if SectionName
!= 'UserExtensions':
973 ArchList
= GetSplitValueList(SectionAttrs
, DataType
.TAB_COMMENT_SPLIT
)
975 ArchList
= [SectionAttrs
]
976 for Index
in range(0, len(ArchList
)):
977 ArchList
[Index
] = ConvertArchForInstall(ArchList
[Index
])
978 Section
= '[' + SectionName
+ '.' + (', ' + SectionName
+ '.').join(ArchList
) + ']'
980 Section
= '[' + SectionName
+ ']'
981 Content
+= '\n' + Section
+ '\n'
982 if StatementList
is not None:
983 for Statement
in StatementList
:
984 LineList
= Statement
.split('\n')
986 for Line
in LineList
:
987 # ignore blank comment
988 if not Line
.replace("#", '').strip() and SectionName
not in ('Defines', 'Hob', 'Event', 'BootMode'):
990 # add two space before non-comments line except the comments in Defines section
991 if Line
.strip().startswith('#') and SectionName
== 'Defines':
992 NewStatement
+= "%s\n" % Line
994 NewStatement
+= " %s\n" % Line
996 Content
+= NewStatement
+ '\n'
998 Content
+= NewStatement
1001 Content
= Content
[:-1]
1002 if not Content
.replace('\\n', '').strip():
1006 ## ConvertArchForInstall
1007 # if Arch.upper() is in "IA32", "X64", "IPF", and "EBC", it must be upper case. "common" must be lower case.
1008 # Anything else, the case must be preserved
1010 # @param Arch: the arch string that need to be converted, it should be stripped before pass in
1011 # @return: the arch string that get converted
1013 def ConvertArchForInstall(Arch
):
1014 if Arch
.upper() in [DataType
.TAB_ARCH_IA32
, DataType
.TAB_ARCH_X64
,
1015 DataType
.TAB_ARCH_IPF
, DataType
.TAB_ARCH_EBC
]:
1017 elif Arch
.upper() == DataType
.TAB_ARCH_COMMON
: