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.
19 from __future__
import absolute_import
27 from Library
.StringUtils
import RaiseParserError
28 from Library
.StringUtils
import GetSplitValueList
29 from Library
.StringUtils
import CheckFileType
30 from Library
.StringUtils
import CheckFileExist
31 from Library
.StringUtils
import CleanString
32 from Library
.StringUtils
import NormPath
34 from Logger
.ToolError
import FILE_NOT_FOUND
35 from Logger
.ToolError
import FatalError
36 from Logger
.ToolError
import FORMAT_INVALID
38 from Library
import DataType
40 from Library
.Misc
import GuidStructureStringToGuidString
41 from Library
.Misc
import CheckGuidRegFormat
42 from Logger
import StringTable
as ST
43 import Logger
.Log
as Logger
45 from Parser
.DecParser
import Dec
46 from . import GlobalData
52 # Parse a string with format "[<Family>:]<ToolFlag>=Flag"
53 # Return (Family, ToolFlag, Flag)
55 # @param String: String with BuildOption statement
56 # @param File: The file which defines build option, used in error report
58 def GetBuildOption(String
, File
, LineNo
= -1):
59 (Family
, ToolChain
, Flag
) = ('', '', '')
60 if String
.find(DataType
.TAB_EQUAL_SPLIT
) < 0:
61 RaiseParserError(String
, 'BuildOptions', File
, \
62 '[<Family>:]<ToolFlag>=Flag', LineNo
)
64 List
= GetSplitValueList(String
, DataType
.TAB_EQUAL_SPLIT
, MaxSplit
=1)
65 if List
[0].find(':') > -1:
66 Family
= List
[0][ : List
[0].find(':')].strip()
67 ToolChain
= List
[0][List
[0].find(':') + 1 : ].strip()
69 ToolChain
= List
[0].strip()
70 Flag
= List
[1].strip()
71 return (Family
, ToolChain
, Flag
)
75 # Get Library of Dsc as <LibraryClassKeyWord>|<LibraryInstance>
77 # @param Item: String as <LibraryClassKeyWord>|<LibraryInstance>
78 # @param ContainerFile: The file which describes the library class, used for
81 def GetLibraryClass(Item
, ContainerFile
, WorkspaceDir
, LineNo
= -1):
82 List
= GetSplitValueList(Item
[0])
83 SupMod
= DataType
.SUP_MODULE_LIST_STRING
85 RaiseParserError(Item
[0], 'LibraryClasses', ContainerFile
, \
86 '<LibraryClassKeyWord>|<LibraryInstance>')
88 CheckFileType(List
[1], '.Inf', ContainerFile
, \
89 'library class instance', Item
[0], LineNo
)
90 CheckFileExist(WorkspaceDir
, List
[1], ContainerFile
, \
91 'LibraryClasses', Item
[0], LineNo
)
95 return (List
[0], List
[1], SupMod
)
99 # Get Library of Dsc as <LibraryClassKeyWord>[|<LibraryInstance>]
100 # [|<TokenSpaceGuidCName>.<PcdCName>]
102 # @param Item: String as <LibraryClassKeyWord>|<LibraryInstance>
103 # @param ContainerFile: The file which describes the library class, used for
106 def GetLibraryClassOfInf(Item
, ContainerFile
, WorkspaceDir
, LineNo
= -1):
107 ItemList
= GetSplitValueList((Item
[0] + DataType
.TAB_VALUE_SPLIT
* 2))
108 SupMod
= DataType
.SUP_MODULE_LIST_STRING
110 if len(ItemList
) > 5:
112 (Item
[0], 'LibraryClasses', ContainerFile
, \
113 '<LibraryClassKeyWord>[|<LibraryInstance>]\
114 [|<TokenSpaceGuidCName>.<PcdCName>]')
116 CheckFileType(ItemList
[1], '.Inf', ContainerFile
, 'LibraryClasses', \
118 CheckFileExist(WorkspaceDir
, ItemList
[1], ContainerFile
, \
119 'LibraryClasses', Item
[0], LineNo
)
120 if ItemList
[2] != '':
121 CheckPcdTokenInfo(ItemList
[2], 'LibraryClasses', \
122 ContainerFile
, LineNo
)
126 return (ItemList
[0], ItemList
[1], ItemList
[2], SupMod
)
130 # Check if PcdTokenInfo is following <TokenSpaceGuidCName>.<PcdCName>
132 # @param TokenInfoString: String to be checked
133 # @param Section: Used for error report
134 # @param File: Used for error report
136 def CheckPcdTokenInfo(TokenInfoString
, Section
, File
, LineNo
= -1):
137 Format
= '<TokenSpaceGuidCName>.<PcdCName>'
138 if TokenInfoString
!= '' and TokenInfoString
is not None:
139 TokenInfoList
= GetSplitValueList(TokenInfoString
, DataType
.TAB_SPLIT
)
140 if len(TokenInfoList
) == 2:
143 RaiseParserError(TokenInfoString
, Section
, File
, Format
, LineNo
)
147 # Get Pcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<Value>
148 # [|<Type>|<MaximumDatumSize>]
150 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|
151 # <Value>[|<Type>|<MaximumDatumSize>]
152 # @param ContainerFile: The file which describes the pcd, used for error
156 def GetPcd(Item
, Type
, ContainerFile
, LineNo
= -1):
157 TokenGuid
, TokenName
, Value
, MaximumDatumSize
, Token
= '', '', '', '', ''
158 List
= GetSplitValueList(Item
+ DataType
.TAB_VALUE_SPLIT
* 2)
160 if len(List
) < 4 or len(List
) > 6:
161 RaiseParserError(Item
, 'Pcds' + Type
, ContainerFile
, \
162 '<PcdTokenSpaceGuidCName>.<TokenCName>|<Value>\
163 [|<Type>|<MaximumDatumSize>]', LineNo
)
166 MaximumDatumSize
= List
[2]
169 if CheckPcdTokenInfo(List
[0], 'Pcds' + Type
, ContainerFile
, LineNo
):
170 (TokenGuid
, TokenName
) = GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
172 return (TokenName
, TokenGuid
, Value
, MaximumDatumSize
, Token
, Type
)
174 ## Get FeatureFlagPcd
176 # Get FeatureFlagPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE
178 # @param Item: String as <PcdTokenSpaceGuidCName>
179 # .<TokenCName>|TRUE/FALSE
180 # @param ContainerFile: The file which describes the pcd, used for error
183 def GetFeatureFlagPcd(Item
, Type
, ContainerFile
, LineNo
= -1):
184 TokenGuid
, TokenName
, Value
= '', '', ''
185 List
= GetSplitValueList(Item
)
187 RaiseParserError(Item
, 'Pcds' + Type
, ContainerFile
, \
188 '<PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE', \
192 if CheckPcdTokenInfo(List
[0], 'Pcds' + Type
, ContainerFile
, LineNo
):
193 (TokenGuid
, TokenName
) = GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
195 return (TokenName
, TokenGuid
, Value
, Type
)
197 ## Get DynamicDefaultPcd
199 # Get DynamicDefaultPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>
200 # |<Value>[|<DatumTyp>[|<MaxDatumSize>]]
202 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|
204 # @param ContainerFile: The file which describes the pcd, used for error
207 def GetDynamicDefaultPcd(Item
, Type
, ContainerFile
, LineNo
= -1):
208 TokenGuid
, TokenName
, Value
, DatumTyp
, MaxDatumSize
= '', '', '', '', ''
209 List
= GetSplitValueList(Item
+ DataType
.TAB_VALUE_SPLIT
* 2)
210 if len(List
) < 4 or len(List
) > 8:
211 RaiseParserError(Item
, 'Pcds' + Type
, ContainerFile
, \
212 '<PcdTokenSpaceGuidCName>.<TokenCName>|<Value>\
213 [|<DatumTyp>[|<MaxDatumSize>]]', LineNo
)
217 MaxDatumSize
= List
[3]
218 if CheckPcdTokenInfo(List
[0], 'Pcds' + Type
, ContainerFile
, LineNo
):
219 (TokenGuid
, TokenName
) = GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
221 return (TokenName
, TokenGuid
, Value
, DatumTyp
, MaxDatumSize
, Type
)
225 # Get DynamicHiiPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<String>|
226 # <VariableGuidCName>|<VariableOffset>[|<DefaultValue>[|<MaximumDatumSize>]]
228 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|
230 # @param ContainerFile: The file which describes the pcd, used for error
233 def GetDynamicHiiPcd(Item
, Type
, ContainerFile
, LineNo
= -1):
234 TokenGuid
, TokenName
, List1
, List2
, List3
, List4
, List5
= \
235 '', '', '', '', '', '', ''
236 List
= GetSplitValueList(Item
+ DataType
.TAB_VALUE_SPLIT
* 2)
237 if len(List
) < 6 or len(List
) > 8:
238 RaiseParserError(Item
, 'Pcds' + Type
, ContainerFile
, \
239 '<PcdTokenSpaceGuidCName>.<TokenCName>|<String>|\
240 <VariableGuidCName>|<VariableOffset>[|<DefaultValue>\
241 [|<MaximumDatumSize>]]', LineNo
)
243 List1
, List2
, List3
, List4
, List5
= \
244 List
[1], List
[2], List
[3], List
[4], List
[5]
245 if CheckPcdTokenInfo(List
[0], 'Pcds' + Type
, ContainerFile
, LineNo
):
246 (TokenGuid
, TokenName
) = GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
248 return (TokenName
, TokenGuid
, List1
, List2
, List3
, List4
, List5
, Type
)
252 # Get DynamicVpdPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|
253 # <VpdOffset>[|<MaximumDatumSize>]
255 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>
257 # @param ContainerFile: The file which describes the pcd, used for error
260 def GetDynamicVpdPcd(Item
, Type
, ContainerFile
, LineNo
= -1):
261 TokenGuid
, TokenName
, List1
, List2
= '', '', '', ''
262 List
= GetSplitValueList(Item
+ DataType
.TAB_VALUE_SPLIT
)
263 if len(List
) < 3 or len(List
) > 4:
264 RaiseParserError(Item
, 'Pcds' + Type
, ContainerFile
, \
265 '<PcdTokenSpaceGuidCName>.<TokenCName>|<VpdOffset>\
266 [|<MaximumDatumSize>]', LineNo
)
268 List1
, List2
= List
[1], List
[2]
269 if CheckPcdTokenInfo(List
[0], 'Pcds' + Type
, ContainerFile
, LineNo
):
270 (TokenGuid
, TokenName
) = GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
272 return (TokenName
, TokenGuid
, List1
, List2
, Type
)
276 # Parse block of the components defined in dsc file
277 # Set KeyValues as [ ['component name', [lib1, lib2, lib3],
278 # [bo1, bo2, bo3], [pcd1, pcd2, pcd3]], ...]
280 # @param Lines: The content to be parsed
281 # @param KeyValues: To store data after parsing
283 def GetComponent(Lines
, KeyValues
):
284 (FindBlock
, FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
285 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, FindPcdsDynamic
, \
286 FindPcdsDynamicEx
) = (False, False, False, False, False, False, False, \
289 LibraryClassItem
= []
296 # Ignore !include statement
298 if Line
.upper().find(DataType
.TAB_INCLUDE
.upper() + ' ') > -1 or \
299 Line
.upper().find(DataType
.TAB_DEFINE
+ ' ') > -1:
302 if FindBlock
== False:
305 # find '{' at line tail
307 if Line
.endswith('{'):
309 ListItem
= CleanString(Line
.rsplit('{', 1)[0], \
310 DataType
.TAB_COMMENT_SPLIT
)
313 # Parse a block content
316 if Line
.find('<LibraryClasses>') != -1:
317 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
318 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
319 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
320 (True, False, False, False, False, False, False)
322 if Line
.find('<BuildOptions>') != -1:
323 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
324 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
325 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
326 (False, True, False, False, False, False, False)
328 if Line
.find('<PcdsFeatureFlag>') != -1:
329 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
330 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
331 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
332 (False, False, True, False, False, False, False)
334 if Line
.find('<PcdsPatchableInModule>') != -1:
335 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
336 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
337 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
338 (False, False, False, True, False, False, False)
340 if Line
.find('<PcdsFixedAtBuild>') != -1:
341 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
342 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
343 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
344 (False, False, False, False, True, False, False)
346 if Line
.find('<PcdsDynamic>') != -1:
347 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
348 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
349 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
350 (False, False, False, False, False, True, False)
352 if Line
.find('<PcdsDynamicEx>') != -1:
353 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
354 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
355 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
356 (False, False, False, False, False, False, True)
358 if Line
.endswith('}'):
360 # find '}' at line tail
362 KeyValues
.append([ListItem
, LibraryClassItem
, \
364 (FindBlock
, FindLibraryClass
, FindBuildOption
, \
365 FindPcdsFeatureFlag
, FindPcdsPatchableInModule
, \
366 FindPcdsFixedAtBuild
, FindPcdsDynamic
, FindPcdsDynamicEx
) = \
367 (False, False, False, False, False, False, False, False)
368 LibraryClassItem
, BuildOption
, Pcd
= [], [], []
373 LibraryClassItem
.append(Line
)
374 elif FindBuildOption
:
375 BuildOption
.append(Line
)
376 elif FindPcdsFeatureFlag
:
377 Pcd
.append((DataType
.TAB_PCDS_FEATURE_FLAG_NULL
, Line
))
378 elif FindPcdsPatchableInModule
:
379 Pcd
.append((DataType
.TAB_PCDS_PATCHABLE_IN_MODULE_NULL
, Line
))
380 elif FindPcdsFixedAtBuild
:
381 Pcd
.append((DataType
.TAB_PCDS_FIXED_AT_BUILD_NULL
, Line
))
382 elif FindPcdsDynamic
:
383 Pcd
.append((DataType
.TAB_PCDS_DYNAMIC_DEFAULT_NULL
, Line
))
384 elif FindPcdsDynamicEx
:
385 Pcd
.append((DataType
.TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
, Line
))
387 KeyValues
.append([ListItem
, [], [], []])
393 # Parse a string with format "InfFilename [EXEC = ExecFilename]"
394 # Return (InfFilename, ExecFilename)
396 # @param String: String with EXEC statement
401 if String
.find('EXEC') > -1:
402 InfFilename
= String
[ : String
.find('EXEC')].strip()
403 ExecFilename
= String
[String
.find('EXEC') + len('EXEC') : ].strip()
405 InfFilename
= String
.strip()
407 return (InfFilename
, ExecFilename
)
411 # Parse block of the components defined in dsc file
412 # Set KeyValues as [ ['component name', [lib1, lib2, lib3], [bo1, bo2, bo3],
413 # [pcd1, pcd2, pcd3]], ...]
415 # @param Lines: The content to be parsed
416 # @param Key: Reserved
417 # @param KeyValues: To store data after parsing
418 # @param CommentCharacter: Comment char, used to ignore comment content
420 # @retval True Get component successfully
422 def GetComponents(Lines
, KeyValues
, CommentCharacter
):
423 if Lines
.find(DataType
.TAB_SECTION_END
) > -1:
424 Lines
= Lines
.split(DataType
.TAB_SECTION_END
, 1)[1]
425 (FindBlock
, FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
426 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, FindPcdsDynamic
, \
427 FindPcdsDynamicEx
) = \
428 (False, False, False, False, False, False, False, False)
430 LibraryClassItem
= []
434 LineList
= Lines
.split('\n')
435 for Line
in LineList
:
436 Line
= CleanString(Line
, CommentCharacter
)
437 if Line
is None or Line
== '':
440 if FindBlock
== False:
443 # find '{' at line tail
445 if Line
.endswith('{'):
447 ListItem
= CleanString(Line
.rsplit('{', 1)[0], CommentCharacter
)
450 # Parse a block content
453 if Line
.find('<LibraryClasses>') != -1:
454 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
455 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
456 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
457 (True, False, False, False, False, False, False)
459 if Line
.find('<BuildOptions>') != -1:
460 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
461 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
462 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
463 (False, True, False, False, False, False, False)
465 if Line
.find('<PcdsFeatureFlag>') != -1:
466 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
467 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
468 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
469 (False, False, True, False, False, False, False)
471 if Line
.find('<PcdsPatchableInModule>') != -1:
472 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
473 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
474 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
475 (False, False, False, True, False, False, False)
477 if Line
.find('<PcdsFixedAtBuild>') != -1:
478 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
479 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
480 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
481 (False, False, False, False, True, False, False)
483 if Line
.find('<PcdsDynamic>') != -1:
484 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
485 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
486 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
487 (False, False, False, False, False, True, False)
489 if Line
.find('<PcdsDynamicEx>') != -1:
490 (FindLibraryClass
, FindBuildOption
, FindPcdsFeatureFlag
, \
491 FindPcdsPatchableInModule
, FindPcdsFixedAtBuild
, \
492 FindPcdsDynamic
, FindPcdsDynamicEx
) = \
493 (False, False, False, False, False, False, True)
495 if Line
.endswith('}'):
497 # find '}' at line tail
499 KeyValues
.append([ListItem
, LibraryClassItem
, BuildOption
, \
501 (FindBlock
, FindLibraryClass
, FindBuildOption
, \
502 FindPcdsFeatureFlag
, FindPcdsPatchableInModule
, \
503 FindPcdsFixedAtBuild
, FindPcdsDynamic
, FindPcdsDynamicEx
) = \
504 (False, False, False, False, False, False, False, False)
505 LibraryClassItem
, BuildOption
, Pcd
= [], [], []
510 LibraryClassItem
.append(Line
)
511 elif FindBuildOption
:
512 BuildOption
.append(Line
)
513 elif FindPcdsFeatureFlag
:
514 Pcd
.append((DataType
.TAB_PCDS_FEATURE_FLAG
, Line
))
515 elif FindPcdsPatchableInModule
:
516 Pcd
.append((DataType
.TAB_PCDS_PATCHABLE_IN_MODULE
, Line
))
517 elif FindPcdsFixedAtBuild
:
518 Pcd
.append((DataType
.TAB_PCDS_FIXED_AT_BUILD
, Line
))
519 elif FindPcdsDynamic
:
520 Pcd
.append((DataType
.TAB_PCDS_DYNAMIC
, Line
))
521 elif FindPcdsDynamicEx
:
522 Pcd
.append((DataType
.TAB_PCDS_DYNAMIC_EX
, Line
))
524 KeyValues
.append([ListItem
, [], [], []])
530 # Get Source of Inf as <Filename>[|<Family>[|<TagName>[|<ToolCode>
531 # [|<PcdFeatureFlag>]]]]
533 # @param Item: String as <Filename>[|<Family>[|<TagName>[|<ToolCode>
534 # [|<PcdFeatureFlag>]]]]
535 # @param ContainerFile: The file which describes the library class, used
538 def GetSource(Item
, ContainerFile
, FileRelativePath
, LineNo
= -1):
539 ItemNew
= Item
+ DataType
.TAB_VALUE_SPLIT
* 4
540 List
= GetSplitValueList(ItemNew
)
541 if len(List
) < 5 or len(List
) > 9:
542 RaiseParserError(Item
, 'Sources', ContainerFile
, \
543 '<Filename>[|<Family>[|<TagName>[|<ToolCode>\
544 [|<PcdFeatureFlag>]]]]', LineNo
)
545 List
[0] = NormPath(List
[0])
546 CheckFileExist(FileRelativePath
, List
[0], ContainerFile
, 'Sources', \
549 CheckPcdTokenInfo(List
[4], 'Sources', ContainerFile
, LineNo
)
551 return (List
[0], List
[1], List
[2], List
[3], List
[4])
555 # Get Binary of Inf as <Filename>[|<Family>[|<TagName>[|<ToolCode>
556 # [|<PcdFeatureFlag>]]]]
558 # @param Item: String as <Filename>[|<Family>[|<TagName>
559 # [|<ToolCode>[|<PcdFeatureFlag>]]]]
560 # @param ContainerFile: The file which describes the library class,
561 # used for error report
563 def GetBinary(Item
, ContainerFile
, LineNo
= -1):
564 ItemNew
= Item
+ DataType
.TAB_VALUE_SPLIT
565 List
= GetSplitValueList(ItemNew
)
566 if len(List
) < 3 or len(List
) > 5:
567 RaiseParserError(Item
, 'Binaries', ContainerFile
, \
568 "<FileType>|<Filename>[|<Target>\
569 [|<TokenSpaceGuidCName>.<PcdCName>]]", LineNo
)
573 CheckPcdTokenInfo(List
[3], 'Binaries', ContainerFile
, LineNo
)
574 return (List
[0], List
[1], List
[2], List
[3])
576 return (List
[0], List
[1], List
[2], '')
578 ## Get Guids/Protocols/Ppis
580 # Get Guids/Protocols/Ppis of Inf as <GuidCName>[|<PcdFeatureFlag>]
582 # @param Item: String as <GuidCName>[|<PcdFeatureFlag>]
583 # @param Type: Type of parsing string
584 # @param ContainerFile: The file which describes the library class,
585 # used for error report
587 def GetGuidsProtocolsPpisOfInf(Item
):
588 ItemNew
= Item
+ DataType
.TAB_VALUE_SPLIT
589 List
= GetSplitValueList(ItemNew
)
590 return (List
[0], List
[1])
592 ## Get Guids/Protocols/Ppis
594 # Get Guids/Protocols/Ppis of Dec as <GuidCName>=<GuidValue>
596 # @param Item: String as <GuidCName>=<GuidValue>
597 # @param Type: Type of parsing string
598 # @param ContainerFile: The file which describes the library class,
599 # used for error report
601 def GetGuidsProtocolsPpisOfDec(Item
, Type
, ContainerFile
, LineNo
= -1):
602 List
= GetSplitValueList(Item
, DataType
.TAB_EQUAL_SPLIT
)
604 RaiseParserError(Item
, Type
, ContainerFile
, '<CName>=<GuidValue>', \
607 #convert C-Format Guid to Register Format
609 if List
[1][0] == '{' and List
[1][-1] == '}':
610 RegisterFormatGuid
= GuidStructureStringToGuidString(List
[1])
611 if RegisterFormatGuid
== '':
612 RaiseParserError(Item
, Type
, ContainerFile
, \
613 'CFormat or RegisterFormat', LineNo
)
615 if CheckGuidRegFormat(List
[1]):
616 RegisterFormatGuid
= List
[1]
618 RaiseParserError(Item
, Type
, ContainerFile
, \
619 'CFormat or RegisterFormat', LineNo
)
621 return (List
[0], RegisterFormatGuid
)
625 # Get Package of Inf as <PackagePath>[|<PcdFeatureFlag>]
627 # @param Item: String as <PackagePath>[|<PcdFeatureFlag>]
628 # @param Type: Type of parsing string
629 # @param ContainerFile: The file which describes the library class,
630 # used for error report
632 def GetPackage(Item
, ContainerFile
, FileRelativePath
, LineNo
= -1):
633 ItemNew
= Item
+ DataType
.TAB_VALUE_SPLIT
634 List
= GetSplitValueList(ItemNew
)
635 CheckFileType(List
[0], '.Dec', ContainerFile
, 'package', List
[0], LineNo
)
636 CheckFileExist(FileRelativePath
, List
[0], ContainerFile
, 'Packages', \
639 CheckPcdTokenInfo(List
[1], 'Packages', ContainerFile
, LineNo
)
641 return (List
[0], List
[1])
643 ## Get Pcd Values of Inf
645 # Get Pcd of Inf as <TokenSpaceGuidCName>.<PcdCName>[|<Value>]
647 # @param Item: The string describes pcd
648 # @param Type: The type of Pcd
649 # @param File: The file which describes the pcd, used for error report
651 def GetPcdOfInf(Item
, Type
, File
, LineNo
):
652 Format
= '<TokenSpaceGuidCName>.<PcdCName>[|<Value>]'
653 TokenGuid
, TokenName
, Value
, InfType
= '', '', '', ''
655 if Type
== DataType
.TAB_PCDS_FIXED_AT_BUILD
:
656 InfType
= DataType
.TAB_INF_FIXED_PCD
657 elif Type
== DataType
.TAB_PCDS_PATCHABLE_IN_MODULE
:
658 InfType
= DataType
.TAB_INF_PATCH_PCD
659 elif Type
== DataType
.TAB_PCDS_FEATURE_FLAG
:
660 InfType
= DataType
.TAB_INF_FEATURE_PCD
661 elif Type
== DataType
.TAB_PCDS_DYNAMIC_EX
:
662 InfType
= DataType
.TAB_INF_PCD_EX
663 elif Type
== DataType
.TAB_PCDS_DYNAMIC
:
664 InfType
= DataType
.TAB_INF_PCD
665 List
= GetSplitValueList(Item
, DataType
.TAB_VALUE_SPLIT
, 1)
666 TokenInfo
= GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
667 if len(TokenInfo
) != 2:
668 RaiseParserError(Item
, InfType
, File
, Format
, LineNo
)
670 TokenGuid
= TokenInfo
[0]
671 TokenName
= TokenInfo
[1]
677 return (TokenGuid
, TokenName
, Value
, InfType
)
680 ## Get Pcd Values of Dec
682 # Get Pcd of Dec as <TokenSpcCName>.<TokenCName>|<Value>|<DatumType>|<Token>
683 # @param Item: Pcd item
684 # @param Type: Pcd type
685 # @param File: Dec file
686 # @param LineNo: Line number
688 def GetPcdOfDec(Item
, Type
, File
, LineNo
= -1):
689 Format
= '<TokenSpaceGuidCName>.<PcdCName>|<Value>|<DatumType>|<Token>'
690 TokenGuid
, TokenName
, Value
, DatumType
, Token
= '', '', '', '', ''
691 List
= GetSplitValueList(Item
)
693 RaiseParserError(Item
, 'Pcds' + Type
, File
, Format
, LineNo
)
698 TokenInfo
= GetSplitValueList(List
[0], DataType
.TAB_SPLIT
)
699 if len(TokenInfo
) != 2:
700 RaiseParserError(Item
, 'Pcds' + Type
, File
, Format
, LineNo
)
702 TokenGuid
= TokenInfo
[0]
703 TokenName
= TokenInfo
[1]
705 return (TokenGuid
, TokenName
, Value
, DatumType
, Token
, Type
)
707 ## Parse DEFINE statement
711 # @param LineValue: A DEFINE line value
712 # @param StartLine: A DEFINE start line
713 # @param Table: A table
714 # @param FileID: File ID
715 # @param Filename: File name
716 # @param SectionName: DEFINE section name
717 # @param SectionModel: DEFINE section model
718 # @param Arch: DEFINE arch
720 def ParseDefine(LineValue
, StartLine
, Table
, FileID
, SectionName
, \
722 Logger
.Debug(Logger
.DEBUG_2
, ST
.MSG_DEFINE_STATEMENT_FOUND
% (LineValue
, \
725 GetSplitValueList(CleanString\
726 (LineValue
[LineValue
.upper().\
727 find(DataType
.TAB_DEFINE
.upper() + ' ') + \
728 len(DataType
.TAB_DEFINE
+ ' ') : ]), \
729 DataType
.TAB_EQUAL_SPLIT
, 1)
730 Table
.Insert(DataType
.MODEL_META_DATA_DEFINE
, Define
[0], Define
[1], '', \
731 '', '', Arch
, SectionModel
, FileID
, StartLine
, -1, \
734 ## InsertSectionItems
736 # Insert item data of a section to a dict
738 # @param Model: A model
739 # @param CurrentSection: Current section
740 # @param SectionItemList: Section item list
741 # @param ArchList: Arch list
742 # @param ThirdList: Third list
743 # @param RecordSet: Record set
745 def InsertSectionItems(Model
, SectionItemList
, ArchList
, \
746 ThirdList
, RecordSet
):
748 # Insert each item data of a section
750 for Index
in range(0, len(ArchList
)):
751 Arch
= ArchList
[Index
]
752 Third
= ThirdList
[Index
]
754 Arch
= DataType
.TAB_ARCH_COMMON
756 Records
= RecordSet
[Model
]
757 for SectionItem
in SectionItemList
:
758 LineValue
, StartLine
, Comment
= SectionItem
[0], \
759 SectionItem
[1], SectionItem
[2]
761 Logger
.Debug(4, ST
.MSG_PARSING
% LineValue
)
763 # And then parse DEFINE statement
765 if LineValue
.upper().find(DataType
.TAB_DEFINE
.upper() + ' ') > -1:
768 # At last parse other sections
771 Records
.append([LineValue
, Arch
, StartLine
, IdNum
, Third
, Comment
])
774 RecordSet
[Model
] = Records
776 ## GenMetaDatSectionItem
779 # @param Value: A value
780 # @param List: A list
782 def GenMetaDatSectionItem(Key
, Value
, List
):
786 List
[Key
].append(Value
)
790 # get package name, guid, version info from dec files
792 # @param Path: File path
794 def GetPkgInfoFromDec(Path
):
799 Path
= Path
.replace('\\', '/')
801 if not os
.path
.exists(Path
):
802 Logger
.Error("\nUPT", FILE_NOT_FOUND
, File
=Path
)
804 if Path
in gPKG_INFO_DICT
:
805 return gPKG_INFO_DICT
[Path
]
809 if Path
not in GlobalData
.gPackageDict
:
810 DecParser
= Dec(Path
)
811 GlobalData
.gPackageDict
[Path
] = DecParser
813 DecParser
= GlobalData
.gPackageDict
[Path
]
815 PkgName
= DecParser
.GetPackageName()
816 PkgGuid
= DecParser
.GetPackageGuid()
817 PkgVersion
= DecParser
.GetPackageVersion()
818 gPKG_INFO_DICT
[Path
] = (PkgName
, PkgGuid
, PkgVersion
)
819 return PkgName
, PkgGuid
, PkgVersion
821 return None, None, None
824 ## GetWorkspacePackage
826 # Get a list of workspace package information.
828 def GetWorkspacePackage():
830 WorkspaceDir
= GlobalData
.gWORKSPACE
831 PackageDir
= GlobalData
.gPACKAGE_PATH
832 for PkgRoot
in [WorkspaceDir
] + PackageDir
:
833 for Root
, Dirs
, Files
in os
.walk(PkgRoot
):
839 if Dir
.startswith('.'):
842 if FileSp
.startswith('.'):
844 Ext
= os
.path
.splitext(FileSp
)[1]
845 if Ext
.lower() in ['.dec']:
847 (os
.path
.normpath(os
.path
.join(Root
, FileSp
)))
849 # abstract package guid, version info from DecFile List
852 for DecFile
in DecFileList
:
853 (PkgName
, PkgGuid
, PkgVersion
) = GetPkgInfoFromDec(DecFile
)
854 if PkgName
and PkgGuid
and PkgVersion
:
855 PkgList
.append((PkgName
, PkgGuid
, PkgVersion
, DecFile
))
859 ## GetWorkspaceModule
861 # Get a list of workspace modules.
863 def GetWorkspaceModule():
865 WorkspaceDir
= GlobalData
.gWORKSPACE
866 for Root
, Dirs
, Files
in os
.walk(WorkspaceDir
):
874 if Dir
.startswith('.'):
877 if FileSp
.startswith('.'):
879 Ext
= os
.path
.splitext(FileSp
)[1]
880 if Ext
.lower() in ['.inf']:
882 (os
.path
.normpath(os
.path
.join(Root
, FileSp
)))
886 ## MacroParser used to parse macro definition
888 # @param Line: The content contain linestring and line number
889 # @param FileName: The meta-file file name
890 # @param SectionType: Section for the Line belong to
891 # @param FileLocalMacros: A list contain Macro defined in [Defines] section.
893 def MacroParser(Line
, FileName
, SectionType
, FileLocalMacros
):
894 MacroDefPattern
= re
.compile("^(DEFINE)[ \t]+")
895 LineContent
= Line
[0]
897 Match
= MacroDefPattern
.match(LineContent
)
900 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
904 TokenList
= GetSplitValueList(LineContent
[Match
.end(1):], \
905 DataType
.TAB_EQUAL_SPLIT
, 1)
910 Logger
.Error('Parser', FORMAT_INVALID
, ST
.ERR_MACRONAME_NOGIVEN
,
911 ExtraData
=LineContent
, File
=FileName
, Line
=LineNo
)
912 if len(TokenList
) < 2:
913 Logger
.Error('Parser', FORMAT_INVALID
, ST
.ERR_MACROVALUE_NOGIVEN
,
914 ExtraData
=LineContent
, File
=FileName
, Line
=LineNo
)
916 Name
, Value
= TokenList
919 # DEFINE defined macros
921 if SectionType
== DataType
.MODEL_META_DATA_HEADER
:
922 FileLocalMacros
[Name
] = Value
924 ReIsValidMacroName
= re
.compile(r
"^[A-Z][A-Z0-9_]*$", re
.DOTALL
)
925 if ReIsValidMacroName
.match(Name
) is None:
926 Logger
.Error('Parser',
928 ST
.ERR_MACRONAME_INVALID
% (Name
),
929 ExtraData
=LineContent
,
933 # Validate MACRO Value
935 # <MacroDefinition> ::= [<Comments>]{0,}
936 # "DEFINE" <MACRO> "=" [{<PATH>} {<VALUE>}] <EOL>
937 # <Value> ::= {<NumVal>} {<Boolean>} {<AsciiString>} {<GUID>}
938 # {<CString>} {<UnicodeString>} {<CArray>}
940 # The definition of <NumVal>, <PATH>, <Boolean>, <GUID>, <CString>,
941 # <UnicodeString>, <CArray> are subset of <AsciiString>.
943 ReIsValidMacroValue
= re
.compile(r
"^[\x20-\x7e]*$", re
.DOTALL
)
944 if ReIsValidMacroValue
.match(Value
) is None:
945 Logger
.Error('Parser',
947 ST
.ERR_MACROVALUE_INVALID
% (Value
),
948 ExtraData
=LineContent
,
956 # generate section contents
958 # @param SectionName: indicate the name of the section, details refer to
960 # @param SectionDict: section statement dict, key is SectionAttrs(arch,
961 # moduletype or platform may exist as needed) list
962 # seperated by space,
965 def GenSection(SectionName
, SectionDict
, SplitArch
=True, NeedBlankLine
=False):
967 for SectionAttrs
in SectionDict
:
968 StatementList
= SectionDict
[SectionAttrs
]
969 if SectionAttrs
and SectionName
!= 'Defines' and SectionAttrs
.strip().upper() != DataType
.TAB_ARCH_COMMON
:
971 ArchList
= GetSplitValueList(SectionAttrs
, DataType
.TAB_SPACE_SPLIT
)
973 if SectionName
!= 'UserExtensions':
974 ArchList
= GetSplitValueList(SectionAttrs
, DataType
.TAB_COMMENT_SPLIT
)
976 ArchList
= [SectionAttrs
]
977 for Index
in xrange(0, len(ArchList
)):
978 ArchList
[Index
] = ConvertArchForInstall(ArchList
[Index
])
979 Section
= '[' + SectionName
+ '.' + (', ' + SectionName
+ '.').join(ArchList
) + ']'
981 Section
= '[' + SectionName
+ ']'
982 Content
+= '\n' + Section
+ '\n'
983 if StatementList
is not None:
984 for Statement
in StatementList
:
985 LineList
= Statement
.split('\n')
987 for Line
in LineList
:
988 # ignore blank comment
989 if not Line
.replace("#", '').strip() and SectionName
not in ('Defines', 'Hob', 'Event', 'BootMode'):
991 # add two space before non-comments line except the comments in Defines section
992 if Line
.strip().startswith('#') and SectionName
== 'Defines':
993 NewStatement
+= "%s\n" % Line
995 NewStatement
+= " %s\n" % Line
997 Content
+= NewStatement
+ '\n'
999 Content
+= NewStatement
1002 Content
= Content
[:-1]
1003 if not Content
.replace('\\n', '').strip():
1007 ## ConvertArchForInstall
1008 # if Arch.upper() is in "IA32", "X64", "IPF", and "EBC", it must be upper case. "common" must be lower case.
1009 # Anything else, the case must be preserved
1011 # @param Arch: the arch string that need to be converted, it should be stripped before pass in
1012 # @return: the arch string that get converted
1014 def ConvertArchForInstall(Arch
):
1015 if Arch
.upper() in [DataType
.TAB_ARCH_IA32
, DataType
.TAB_ARCH_X64
,
1016 DataType
.TAB_ARCH_IPF
, DataType
.TAB_ARCH_EBC
]:
1018 elif Arch
.upper() == DataType
.TAB_ARCH_COMMON
: