]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/UPT/Library/Parsing.py
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / BaseTools / Source / Python / UPT / Library / Parsing.py
1 ## @file
2 # This file is used to define common parsing related functions used in parsing
3 # INF/DEC/DSC process
4 #
5 # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
6 #
7 # SPDX-License-Identifier: BSD-2-Clause-Patent
8 #
9
10 '''
11 Parsing
12 '''
13 from __future__ import absolute_import
14
15 ##
16 # Import Modules
17 #
18 import os.path
19 import re
20
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
27
28 from Logger.ToolError import FILE_NOT_FOUND
29 from Logger.ToolError import FatalError
30 from Logger.ToolError import FORMAT_INVALID
31
32 from Library import DataType
33
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
38
39 from Parser.DecParser import Dec
40 from . import GlobalData
41
42 gPKG_INFO_DICT = {}
43
44 ## GetBuildOption
45 #
46 # Parse a string with format "[<Family>:]<ToolFlag>=Flag"
47 # Return (Family, ToolFlag, Flag)
48 #
49 # @param String: String with BuildOption statement
50 # @param File: The file which defines build option, used in error report
51 #
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)
57 else:
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()
62 else:
63 ToolChain = List[0].strip()
64 Flag = List[1].strip()
65 return (Family, ToolChain, Flag)
66
67 ## Get Library Class
68 #
69 # Get Library of Dsc as <LibraryClassKeyWord>|<LibraryInstance>
70 #
71 # @param Item: String as <LibraryClassKeyWord>|<LibraryInstance>
72 # @param ContainerFile: The file which describes the library class, used for
73 # error report
74 #
75 def GetLibraryClass(Item, ContainerFile, WorkspaceDir, LineNo= -1):
76 List = GetSplitValueList(Item[0])
77 SupMod = DataType.SUP_MODULE_LIST_STRING
78 if len(List) != 2:
79 RaiseParserError(Item[0], 'LibraryClasses', ContainerFile, \
80 '<LibraryClassKeyWord>|<LibraryInstance>')
81 else:
82 CheckFileType(List[1], '.Inf', ContainerFile, \
83 'library class instance', Item[0], LineNo)
84 CheckFileExist(WorkspaceDir, List[1], ContainerFile, \
85 'LibraryClasses', Item[0], LineNo)
86 if Item[1] != '':
87 SupMod = Item[1]
88
89 return (List[0], List[1], SupMod)
90
91 ## Get Library Class
92 #
93 # Get Library of Dsc as <LibraryClassKeyWord>[|<LibraryInstance>]
94 # [|<TokenSpaceGuidCName>.<PcdCName>]
95 #
96 # @param Item: String as <LibraryClassKeyWord>|<LibraryInstance>
97 # @param ContainerFile: The file which describes the library class, used for
98 # error report
99 #
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
103
104 if len(ItemList) > 5:
105 RaiseParserError\
106 (Item[0], 'LibraryClasses', ContainerFile, \
107 '<LibraryClassKeyWord>[|<LibraryInstance>]\
108 [|<TokenSpaceGuidCName>.<PcdCName>]')
109 else:
110 CheckFileType(ItemList[1], '.Inf', ContainerFile, 'LibraryClasses', \
111 Item[0], LineNo)
112 CheckFileExist(WorkspaceDir, ItemList[1], ContainerFile, \
113 'LibraryClasses', Item[0], LineNo)
114 if ItemList[2] != '':
115 CheckPcdTokenInfo(ItemList[2], 'LibraryClasses', \
116 ContainerFile, LineNo)
117 if Item[1] != '':
118 SupMod = Item[1]
119
120 return (ItemList[0], ItemList[1], ItemList[2], SupMod)
121
122 ## CheckPcdTokenInfo
123 #
124 # Check if PcdTokenInfo is following <TokenSpaceGuidCName>.<PcdCName>
125 #
126 # @param TokenInfoString: String to be checked
127 # @param Section: Used for error report
128 # @param File: Used for error report
129 #
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:
135 return True
136
137 RaiseParserError(TokenInfoString, Section, File, Format, LineNo)
138
139 ## Get Pcd
140 #
141 # Get Pcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<Value>
142 # [|<Type>|<MaximumDatumSize>]
143 #
144 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|
145 # <Value>[|<Type>|<MaximumDatumSize>]
146 # @param ContainerFile: The file which describes the pcd, used for error
147 # report
148
149 #
150 def GetPcd(Item, Type, ContainerFile, LineNo= -1):
151 TokenGuid, TokenName, Value, MaximumDatumSize, Token = '', '', '', '', ''
152 List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2)
153
154 if len(List) < 4 or len(List) > 6:
155 RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \
156 '<PcdTokenSpaceGuidCName>.<TokenCName>|<Value>\
157 [|<Type>|<MaximumDatumSize>]', LineNo)
158 else:
159 Value = List[1]
160 MaximumDatumSize = List[2]
161 Token = List[3]
162
163 if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
164 (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)
165
166 return (TokenName, TokenGuid, Value, MaximumDatumSize, Token, Type)
167
168 ## Get FeatureFlagPcd
169 #
170 # Get FeatureFlagPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE
171 #
172 # @param Item: String as <PcdTokenSpaceGuidCName>
173 # .<TokenCName>|TRUE/FALSE
174 # @param ContainerFile: The file which describes the pcd, used for error
175 # report
176 #
177 def GetFeatureFlagPcd(Item, Type, ContainerFile, LineNo= -1):
178 TokenGuid, TokenName, Value = '', '', ''
179 List = GetSplitValueList(Item)
180 if len(List) != 2:
181 RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \
182 '<PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE', \
183 LineNo)
184 else:
185 Value = List[1]
186 if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
187 (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)
188
189 return (TokenName, TokenGuid, Value, Type)
190
191 ## Get DynamicDefaultPcd
192 #
193 # Get DynamicDefaultPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>
194 # |<Value>[|<DatumTyp>[|<MaxDatumSize>]]
195 #
196 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|
197 # TRUE/FALSE
198 # @param ContainerFile: The file which describes the pcd, used for error
199 # report
200 #
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)
208 else:
209 Value = List[1]
210 DatumTyp = List[2]
211 MaxDatumSize = List[3]
212 if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
213 (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)
214
215 return (TokenName, TokenGuid, Value, DatumTyp, MaxDatumSize, Type)
216
217 ## Get DynamicHiiPcd
218 #
219 # Get DynamicHiiPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<String>|
220 # <VariableGuidCName>|<VariableOffset>[|<DefaultValue>[|<MaximumDatumSize>]]
221 #
222 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|
223 # TRUE/FALSE
224 # @param ContainerFile: The file which describes the pcd, used for error
225 # report
226 #
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)
236 else:
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)
241
242 return (TokenName, TokenGuid, List1, List2, List3, List4, List5, Type)
243
244 ## Get DynamicVpdPcd
245 #
246 # Get DynamicVpdPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|
247 # <VpdOffset>[|<MaximumDatumSize>]
248 #
249 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>
250 # |TRUE/FALSE
251 # @param ContainerFile: The file which describes the pcd, used for error
252 # report
253 #
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)
261 else:
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)
265
266 return (TokenName, TokenGuid, List1, List2, Type)
267
268 ## GetComponent
269 #
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]], ...]
273 #
274 # @param Lines: The content to be parsed
275 # @param KeyValues: To store data after parsing
276 #
277 def GetComponent(Lines, KeyValues):
278 (FindBlock, FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
279 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, FindPcdsDynamic, \
280 FindPcdsDynamicEx) = (False, False, False, False, False, False, False, \
281 False)
282 ListItem = None
283 LibraryClassItem = []
284 BuildOption = []
285 Pcd = []
286
287 for Line in Lines:
288 Line = Line[0]
289 #
290 # Ignore !include statement
291 #
292 if Line.upper().find(DataType.TAB_INCLUDE.upper() + ' ') > -1 or \
293 Line.upper().find(DataType.TAB_DEFINE + ' ') > -1:
294 continue
295
296 if FindBlock == False:
297 ListItem = Line
298 #
299 # find '{' at line tail
300 #
301 if Line.endswith('{'):
302 FindBlock = True
303 ListItem = CleanString(Line.rsplit('{', 1)[0], \
304 DataType.TAB_COMMENT_SPLIT)
305
306 #
307 # Parse a block content
308 #
309 if FindBlock:
310 if Line.find('<LibraryClasses>') != -1:
311 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
312 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
313 FindPcdsDynamic, FindPcdsDynamicEx) = \
314 (True, False, False, False, False, False, False)
315 continue
316 if Line.find('<BuildOptions>') != -1:
317 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
318 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
319 FindPcdsDynamic, FindPcdsDynamicEx) = \
320 (False, True, False, False, False, False, False)
321 continue
322 if Line.find('<PcdsFeatureFlag>') != -1:
323 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
324 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
325 FindPcdsDynamic, FindPcdsDynamicEx) = \
326 (False, False, True, False, False, False, False)
327 continue
328 if Line.find('<PcdsPatchableInModule>') != -1:
329 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
330 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
331 FindPcdsDynamic, FindPcdsDynamicEx) = \
332 (False, False, False, True, False, False, False)
333 continue
334 if Line.find('<PcdsFixedAtBuild>') != -1:
335 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
336 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
337 FindPcdsDynamic, FindPcdsDynamicEx) = \
338 (False, False, False, False, True, False, False)
339 continue
340 if Line.find('<PcdsDynamic>') != -1:
341 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
342 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
343 FindPcdsDynamic, FindPcdsDynamicEx) = \
344 (False, False, False, False, False, True, False)
345 continue
346 if Line.find('<PcdsDynamicEx>') != -1:
347 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
348 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
349 FindPcdsDynamic, FindPcdsDynamicEx) = \
350 (False, False, False, False, False, False, True)
351 continue
352 if Line.endswith('}'):
353 #
354 # find '}' at line tail
355 #
356 KeyValues.append([ListItem, LibraryClassItem, \
357 BuildOption, Pcd])
358 (FindBlock, FindLibraryClass, FindBuildOption, \
359 FindPcdsFeatureFlag, FindPcdsPatchableInModule, \
360 FindPcdsFixedAtBuild, FindPcdsDynamic, FindPcdsDynamicEx) = \
361 (False, False, False, False, False, False, False, False)
362 LibraryClassItem, BuildOption, Pcd = [], [], []
363 continue
364
365 if FindBlock:
366 if FindLibraryClass:
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))
380 else:
381 KeyValues.append([ListItem, [], [], []])
382
383 return True
384
385 ## GetExec
386 #
387 # Parse a string with format "InfFilename [EXEC = ExecFilename]"
388 # Return (InfFilename, ExecFilename)
389 #
390 # @param String: String with EXEC statement
391 #
392 def GetExec(String):
393 InfFilename = ''
394 ExecFilename = ''
395 if String.find('EXEC') > -1:
396 InfFilename = String[ : String.find('EXEC')].strip()
397 ExecFilename = String[String.find('EXEC') + len('EXEC') : ].strip()
398 else:
399 InfFilename = String.strip()
400
401 return (InfFilename, ExecFilename)
402
403 ## GetComponents
404 #
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]], ...]
408 #
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
413 #
414 # @retval True Get component successfully
415 #
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)
423 ListItem = None
424 LibraryClassItem = []
425 BuildOption = []
426 Pcd = []
427
428 LineList = Lines.split('\n')
429 for Line in LineList:
430 Line = CleanString(Line, CommentCharacter)
431 if Line is None or Line == '':
432 continue
433
434 if FindBlock == False:
435 ListItem = Line
436 #
437 # find '{' at line tail
438 #
439 if Line.endswith('{'):
440 FindBlock = True
441 ListItem = CleanString(Line.rsplit('{', 1)[0], CommentCharacter)
442
443 #
444 # Parse a block content
445 #
446 if FindBlock:
447 if Line.find('<LibraryClasses>') != -1:
448 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
449 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
450 FindPcdsDynamic, FindPcdsDynamicEx) = \
451 (True, False, False, False, False, False, False)
452 continue
453 if Line.find('<BuildOptions>') != -1:
454 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
455 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
456 FindPcdsDynamic, FindPcdsDynamicEx) = \
457 (False, True, False, False, False, False, False)
458 continue
459 if Line.find('<PcdsFeatureFlag>') != -1:
460 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
461 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
462 FindPcdsDynamic, FindPcdsDynamicEx) = \
463 (False, False, True, False, False, False, False)
464 continue
465 if Line.find('<PcdsPatchableInModule>') != -1:
466 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
467 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
468 FindPcdsDynamic, FindPcdsDynamicEx) = \
469 (False, False, False, True, False, False, False)
470 continue
471 if Line.find('<PcdsFixedAtBuild>') != -1:
472 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
473 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
474 FindPcdsDynamic, FindPcdsDynamicEx) = \
475 (False, False, False, False, True, False, False)
476 continue
477 if Line.find('<PcdsDynamic>') != -1:
478 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
479 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
480 FindPcdsDynamic, FindPcdsDynamicEx) = \
481 (False, False, False, False, False, True, False)
482 continue
483 if Line.find('<PcdsDynamicEx>') != -1:
484 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
485 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
486 FindPcdsDynamic, FindPcdsDynamicEx) = \
487 (False, False, False, False, False, False, True)
488 continue
489 if Line.endswith('}'):
490 #
491 # find '}' at line tail
492 #
493 KeyValues.append([ListItem, LibraryClassItem, BuildOption, \
494 Pcd])
495 (FindBlock, FindLibraryClass, FindBuildOption, \
496 FindPcdsFeatureFlag, FindPcdsPatchableInModule, \
497 FindPcdsFixedAtBuild, FindPcdsDynamic, FindPcdsDynamicEx) = \
498 (False, False, False, False, False, False, False, False)
499 LibraryClassItem, BuildOption, Pcd = [], [], []
500 continue
501
502 if FindBlock:
503 if FindLibraryClass:
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))
517 else:
518 KeyValues.append([ListItem, [], [], []])
519
520 return True
521
522 ## Get Source
523 #
524 # Get Source of Inf as <Filename>[|<Family>[|<TagName>[|<ToolCode>
525 # [|<PcdFeatureFlag>]]]]
526 #
527 # @param Item: String as <Filename>[|<Family>[|<TagName>[|<ToolCode>
528 # [|<PcdFeatureFlag>]]]]
529 # @param ContainerFile: The file which describes the library class, used
530 # for error report
531 #
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', \
541 Item, LineNo)
542 if List[4] != '':
543 CheckPcdTokenInfo(List[4], 'Sources', ContainerFile, LineNo)
544
545 return (List[0], List[1], List[2], List[3], List[4])
546
547 ## Get Binary
548 #
549 # Get Binary of Inf as <Filename>[|<Family>[|<TagName>[|<ToolCode>
550 # [|<PcdFeatureFlag>]]]]
551 #
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
556 #
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)
564
565 if len(List) >= 4:
566 if List[3] != '':
567 CheckPcdTokenInfo(List[3], 'Binaries', ContainerFile, LineNo)
568 return (List[0], List[1], List[2], List[3])
569 elif len(List) == 3:
570 return (List[0], List[1], List[2], '')
571
572 ## Get Guids/Protocols/Ppis
573 #
574 # Get Guids/Protocols/Ppis of Inf as <GuidCName>[|<PcdFeatureFlag>]
575 #
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
580 #
581 def GetGuidsProtocolsPpisOfInf(Item):
582 ItemNew = Item + DataType.TAB_VALUE_SPLIT
583 List = GetSplitValueList(ItemNew)
584 return (List[0], List[1])
585
586 ## Get Guids/Protocols/Ppis
587 #
588 # Get Guids/Protocols/Ppis of Dec as <GuidCName>=<GuidValue>
589 #
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
594 #
595 def GetGuidsProtocolsPpisOfDec(Item, Type, ContainerFile, LineNo= -1):
596 List = GetSplitValueList(Item, DataType.TAB_EQUAL_SPLIT)
597 if len(List) != 2:
598 RaiseParserError(Item, Type, ContainerFile, '<CName>=<GuidValue>', \
599 LineNo)
600 #
601 #convert C-Format Guid to Register Format
602 #
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)
608 else:
609 if CheckGuidRegFormat(List[1]):
610 RegisterFormatGuid = List[1]
611 else:
612 RaiseParserError(Item, Type, ContainerFile, \
613 'CFormat or RegisterFormat', LineNo)
614
615 return (List[0], RegisterFormatGuid)
616
617 ## GetPackage
618 #
619 # Get Package of Inf as <PackagePath>[|<PcdFeatureFlag>]
620 #
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
625 #
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', \
631 List[0], LineNo)
632 if List[1] != '':
633 CheckPcdTokenInfo(List[1], 'Packages', ContainerFile, LineNo)
634
635 return (List[0], List[1])
636
637 ## Get Pcd Values of Inf
638 #
639 # Get Pcd of Inf as <TokenSpaceGuidCName>.<PcdCName>[|<Value>]
640 #
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
644 #
645 def GetPcdOfInf(Item, Type, File, LineNo):
646 Format = '<TokenSpaceGuidCName>.<PcdCName>[|<Value>]'
647 TokenGuid, TokenName, Value, InfType = '', '', '', ''
648
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)
663 else:
664 TokenGuid = TokenInfo[0]
665 TokenName = TokenInfo[1]
666
667 if len(List) > 1:
668 Value = List[1]
669 else:
670 Value = None
671 return (TokenGuid, TokenName, Value, InfType)
672
673
674 ## Get Pcd Values of Dec
675 #
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
681 #
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)
686 if len(List) != 4:
687 RaiseParserError(Item, 'Pcds' + Type, File, Format, LineNo)
688 else:
689 Value = List[1]
690 DatumType = List[2]
691 Token = List[3]
692 TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT)
693 if len(TokenInfo) != 2:
694 RaiseParserError(Item, 'Pcds' + Type, File, Format, LineNo)
695 else:
696 TokenGuid = TokenInfo[0]
697 TokenName = TokenInfo[1]
698
699 return (TokenGuid, TokenName, Value, DatumType, Token, Type)
700
701 ## Parse DEFINE statement
702 #
703 # Get DEFINE macros
704 #
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
713 #
714 def ParseDefine(LineValue, StartLine, Table, FileID, SectionName, \
715 SectionModel, Arch):
716 Logger.Debug(Logger.DEBUG_2, ST.MSG_DEFINE_STATEMENT_FOUND % (LineValue, \
717 SectionName))
718 Define = \
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, \
726 StartLine, -1, 0)
727
728 ## InsertSectionItems
729 #
730 # Insert item data of a section to a dict
731 #
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
738 #
739 def InsertSectionItems(Model, SectionItemList, ArchList, \
740 ThirdList, RecordSet):
741 #
742 # Insert each item data of a section
743 #
744 for Index in range(0, len(ArchList)):
745 Arch = ArchList[Index]
746 Third = ThirdList[Index]
747 if Arch == '':
748 Arch = DataType.TAB_ARCH_COMMON
749
750 Records = RecordSet[Model]
751 for SectionItem in SectionItemList:
752 LineValue, StartLine, Comment = SectionItem[0], \
753 SectionItem[1], SectionItem[2]
754
755 Logger.Debug(4, ST.MSG_PARSING % LineValue)
756 #
757 # And then parse DEFINE statement
758 #
759 if LineValue.upper().find(DataType.TAB_DEFINE.upper() + ' ') > -1:
760 continue
761 #
762 # At last parse other sections
763 #
764 IdNum = -1
765 Records.append([LineValue, Arch, StartLine, IdNum, Third, Comment])
766
767 if RecordSet != {}:
768 RecordSet[Model] = Records
769
770 ## GenMetaDatSectionItem
771 #
772 # @param Key: A key
773 # @param Value: A value
774 # @param List: A list
775 #
776 def GenMetaDatSectionItem(Key, Value, List):
777 if Key not in List:
778 List[Key] = [Value]
779 else:
780 List[Key].append(Value)
781
782 ## GetPkgInfoFromDec
783 #
784 # get package name, guid, version info from dec files
785 #
786 # @param Path: File path
787 #
788 def GetPkgInfoFromDec(Path):
789 PkgName = None
790 PkgGuid = None
791 PkgVersion = None
792
793 Path = Path.replace('\\', '/')
794
795 if not os.path.exists(Path):
796 Logger.Error("\nUPT", FILE_NOT_FOUND, File=Path)
797
798 if Path in gPKG_INFO_DICT:
799 return gPKG_INFO_DICT[Path]
800
801 try:
802 DecParser = None
803 if Path not in GlobalData.gPackageDict:
804 DecParser = Dec(Path)
805 GlobalData.gPackageDict[Path] = DecParser
806 else:
807 DecParser = GlobalData.gPackageDict[Path]
808
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
814 except FatalError:
815 return None, None, None
816
817
818 ## GetWorkspacePackage
819 #
820 # Get a list of workspace package information.
821 #
822 def GetWorkspacePackage():
823 DecFileList = []
824 WorkspaceDir = GlobalData.gWORKSPACE
825 PackageDir = GlobalData.gPACKAGE_PATH
826 for PkgRoot in [WorkspaceDir] + PackageDir:
827 for Root, Dirs, Files in os.walk(PkgRoot):
828 if 'CVS' in Dirs:
829 Dirs.remove('CVS')
830 if '.svn' in Dirs:
831 Dirs.remove('.svn')
832 for Dir in Dirs:
833 if Dir.startswith('.'):
834 Dirs.remove(Dir)
835 for FileSp in Files:
836 if FileSp.startswith('.'):
837 continue
838 Ext = os.path.splitext(FileSp)[1]
839 if Ext.lower() in ['.dec']:
840 DecFileList.append\
841 (os.path.normpath(os.path.join(Root, FileSp)))
842 #
843 # abstract package guid, version info from DecFile List
844 #
845 PkgList = []
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))
850
851 return PkgList
852
853 ## GetWorkspaceModule
854 #
855 # Get a list of workspace modules.
856 #
857 def GetWorkspaceModule():
858 InfFileList = []
859 WorkspaceDir = GlobalData.gWORKSPACE
860 for Root, Dirs, Files in os.walk(WorkspaceDir):
861 if 'CVS' in Dirs:
862 Dirs.remove('CVS')
863 if '.svn' in Dirs:
864 Dirs.remove('.svn')
865 if 'Build' in Dirs:
866 Dirs.remove('Build')
867 for Dir in Dirs:
868 if Dir.startswith('.'):
869 Dirs.remove(Dir)
870 for FileSp in Files:
871 if FileSp.startswith('.'):
872 continue
873 Ext = os.path.splitext(FileSp)[1]
874 if Ext.lower() in ['.inf']:
875 InfFileList.append\
876 (os.path.normpath(os.path.join(Root, FileSp)))
877
878 return InfFileList
879
880 ## MacroParser used to parse macro definition
881 #
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.
886 #
887 def MacroParser(Line, FileName, SectionType, FileLocalMacros):
888 MacroDefPattern = re.compile("^(DEFINE)[ \t]+")
889 LineContent = Line[0]
890 LineNo = Line[1]
891 Match = MacroDefPattern.match(LineContent)
892 if not Match:
893 #
894 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
895 #
896 return None, None
897
898 TokenList = GetSplitValueList(LineContent[Match.end(1):], \
899 DataType.TAB_EQUAL_SPLIT, 1)
900 #
901 # Syntax check
902 #
903 if not TokenList[0]:
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)
909
910 Name, Value = TokenList
911
912 #
913 # DEFINE defined macros
914 #
915 if SectionType == DataType.MODEL_META_DATA_HEADER:
916 FileLocalMacros[Name] = Value
917
918 ReIsValidMacroName = re.compile(r"^[A-Z][A-Z0-9_]*$", re.DOTALL)
919 if ReIsValidMacroName.match(Name) is None:
920 Logger.Error('Parser',
921 FORMAT_INVALID,
922 ST.ERR_MACRONAME_INVALID % (Name),
923 ExtraData=LineContent,
924 File=FileName,
925 Line=LineNo)
926
927 # Validate MACRO Value
928 #
929 # <MacroDefinition> ::= [<Comments>]{0,}
930 # "DEFINE" <MACRO> "=" [{<PATH>} {<VALUE>}] <EOL>
931 # <Value> ::= {<NumVal>} {<Boolean>} {<AsciiString>} {<GUID>}
932 # {<CString>} {<UnicodeString>} {<CArray>}
933 #
934 # The definition of <NumVal>, <PATH>, <Boolean>, <GUID>, <CString>,
935 # <UnicodeString>, <CArray> are subset of <AsciiString>.
936 #
937 ReIsValidMacroValue = re.compile(r"^[\x20-\x7e]*$", re.DOTALL)
938 if ReIsValidMacroValue.match(Value) is None:
939 Logger.Error('Parser',
940 FORMAT_INVALID,
941 ST.ERR_MACROVALUE_INVALID % (Value),
942 ExtraData=LineContent,
943 File=FileName,
944 Line=LineNo)
945
946 return Name, Value
947
948 ## GenSection
949 #
950 # generate section contents
951 #
952 # @param SectionName: indicate the name of the section, details refer to
953 # INF, DEC specs
954 # @param SectionDict: section statement dict, key is SectionAttrs(arch,
955 # moduletype or platform may exist as needed) list
956 # separated by space,
957 # value is statement
958 #
959 def GenSection(SectionName, SectionDict, SplitArch=True, NeedBlankLine=False):
960 Content = ''
961 for SectionAttrs in SectionDict:
962 StatementList = SectionDict[SectionAttrs]
963 if SectionAttrs and SectionName != 'Defines' and SectionAttrs.strip().upper() != DataType.TAB_ARCH_COMMON:
964 if SplitArch:
965 ArchList = GetSplitValueList(SectionAttrs, DataType.TAB_SPACE_SPLIT)
966 else:
967 if SectionName != 'UserExtensions':
968 ArchList = GetSplitValueList(SectionAttrs, DataType.TAB_COMMENT_SPLIT)
969 else:
970 ArchList = [SectionAttrs]
971 for Index in range(0, len(ArchList)):
972 ArchList[Index] = ConvertArchForInstall(ArchList[Index])
973 Section = '[' + SectionName + '.' + (', ' + SectionName + '.').join(ArchList) + ']'
974 else:
975 Section = '[' + SectionName + ']'
976 Content += '\n' + Section + '\n'
977 if StatementList is not None:
978 for Statement in StatementList:
979 LineList = Statement.split('\n')
980 NewStatement = ""
981 for Line in LineList:
982 # ignore blank comment
983 if not Line.replace("#", '').strip() and SectionName not in ('Defines', 'Hob', 'Event', 'BootMode'):
984 continue
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
988 continue
989 NewStatement += " %s\n" % Line
990 if NeedBlankLine:
991 Content += NewStatement + '\n'
992 else:
993 Content += NewStatement
994
995 if NeedBlankLine:
996 Content = Content[:-1]
997 if not Content.replace('\\n', '').strip():
998 return ''
999 return Content
1000
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
1004 #
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
1007 #
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]:
1011 Arch = Arch.upper()
1012 elif Arch.upper() == DataType.TAB_ARCH_COMMON:
1013 Arch = Arch.lower()
1014
1015 return Arch