BaseTools: Use absolute import in UPT
[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 # 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
11 #
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.
14 #
15
16 '''
17 Parsing
18 '''
19 from __future__ import absolute_import
20
21 ##
22 # Import Modules
23 #
24 import os.path
25 import re
26
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
33
34 from Logger.ToolError import FILE_NOT_FOUND
35 from Logger.ToolError import FatalError
36 from Logger.ToolError import FORMAT_INVALID
37
38 from Library import DataType
39
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
44
45 from Parser.DecParser import Dec
46 from . import GlobalData
47
48 gPKG_INFO_DICT = {}
49
50 ## GetBuildOption
51 #
52 # Parse a string with format "[<Family>:]<ToolFlag>=Flag"
53 # Return (Family, ToolFlag, Flag)
54 #
55 # @param String: String with BuildOption statement
56 # @param File: The file which defines build option, used in error report
57 #
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)
63 else:
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()
68 else:
69 ToolChain = List[0].strip()
70 Flag = List[1].strip()
71 return (Family, ToolChain, Flag)
72
73 ## Get Library Class
74 #
75 # Get Library of Dsc as <LibraryClassKeyWord>|<LibraryInstance>
76 #
77 # @param Item: String as <LibraryClassKeyWord>|<LibraryInstance>
78 # @param ContainerFile: The file which describes the library class, used for
79 # error report
80 #
81 def GetLibraryClass(Item, ContainerFile, WorkspaceDir, LineNo= -1):
82 List = GetSplitValueList(Item[0])
83 SupMod = DataType.SUP_MODULE_LIST_STRING
84 if len(List) != 2:
85 RaiseParserError(Item[0], 'LibraryClasses', ContainerFile, \
86 '<LibraryClassKeyWord>|<LibraryInstance>')
87 else:
88 CheckFileType(List[1], '.Inf', ContainerFile, \
89 'library class instance', Item[0], LineNo)
90 CheckFileExist(WorkspaceDir, List[1], ContainerFile, \
91 'LibraryClasses', Item[0], LineNo)
92 if Item[1] != '':
93 SupMod = Item[1]
94
95 return (List[0], List[1], SupMod)
96
97 ## Get Library Class
98 #
99 # Get Library of Dsc as <LibraryClassKeyWord>[|<LibraryInstance>]
100 # [|<TokenSpaceGuidCName>.<PcdCName>]
101 #
102 # @param Item: String as <LibraryClassKeyWord>|<LibraryInstance>
103 # @param ContainerFile: The file which describes the library class, used for
104 # error report
105 #
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
109
110 if len(ItemList) > 5:
111 RaiseParserError\
112 (Item[0], 'LibraryClasses', ContainerFile, \
113 '<LibraryClassKeyWord>[|<LibraryInstance>]\
114 [|<TokenSpaceGuidCName>.<PcdCName>]')
115 else:
116 CheckFileType(ItemList[1], '.Inf', ContainerFile, 'LibraryClasses', \
117 Item[0], LineNo)
118 CheckFileExist(WorkspaceDir, ItemList[1], ContainerFile, \
119 'LibraryClasses', Item[0], LineNo)
120 if ItemList[2] != '':
121 CheckPcdTokenInfo(ItemList[2], 'LibraryClasses', \
122 ContainerFile, LineNo)
123 if Item[1] != '':
124 SupMod = Item[1]
125
126 return (ItemList[0], ItemList[1], ItemList[2], SupMod)
127
128 ## CheckPcdTokenInfo
129 #
130 # Check if PcdTokenInfo is following <TokenSpaceGuidCName>.<PcdCName>
131 #
132 # @param TokenInfoString: String to be checked
133 # @param Section: Used for error report
134 # @param File: Used for error report
135 #
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:
141 return True
142
143 RaiseParserError(TokenInfoString, Section, File, Format, LineNo)
144
145 ## Get Pcd
146 #
147 # Get Pcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<Value>
148 # [|<Type>|<MaximumDatumSize>]
149 #
150 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|
151 # <Value>[|<Type>|<MaximumDatumSize>]
152 # @param ContainerFile: The file which describes the pcd, used for error
153 # report
154
155 #
156 def GetPcd(Item, Type, ContainerFile, LineNo= -1):
157 TokenGuid, TokenName, Value, MaximumDatumSize, Token = '', '', '', '', ''
158 List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2)
159
160 if len(List) < 4 or len(List) > 6:
161 RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \
162 '<PcdTokenSpaceGuidCName>.<TokenCName>|<Value>\
163 [|<Type>|<MaximumDatumSize>]', LineNo)
164 else:
165 Value = List[1]
166 MaximumDatumSize = List[2]
167 Token = List[3]
168
169 if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
170 (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)
171
172 return (TokenName, TokenGuid, Value, MaximumDatumSize, Token, Type)
173
174 ## Get FeatureFlagPcd
175 #
176 # Get FeatureFlagPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE
177 #
178 # @param Item: String as <PcdTokenSpaceGuidCName>
179 # .<TokenCName>|TRUE/FALSE
180 # @param ContainerFile: The file which describes the pcd, used for error
181 # report
182 #
183 def GetFeatureFlagPcd(Item, Type, ContainerFile, LineNo= -1):
184 TokenGuid, TokenName, Value = '', '', ''
185 List = GetSplitValueList(Item)
186 if len(List) != 2:
187 RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \
188 '<PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE', \
189 LineNo)
190 else:
191 Value = List[1]
192 if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
193 (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)
194
195 return (TokenName, TokenGuid, Value, Type)
196
197 ## Get DynamicDefaultPcd
198 #
199 # Get DynamicDefaultPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>
200 # |<Value>[|<DatumTyp>[|<MaxDatumSize>]]
201 #
202 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|
203 # TRUE/FALSE
204 # @param ContainerFile: The file which describes the pcd, used for error
205 # report
206 #
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)
214 else:
215 Value = List[1]
216 DatumTyp = List[2]
217 MaxDatumSize = List[3]
218 if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
219 (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)
220
221 return (TokenName, TokenGuid, Value, DatumTyp, MaxDatumSize, Type)
222
223 ## Get DynamicHiiPcd
224 #
225 # Get DynamicHiiPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<String>|
226 # <VariableGuidCName>|<VariableOffset>[|<DefaultValue>[|<MaximumDatumSize>]]
227 #
228 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|
229 # TRUE/FALSE
230 # @param ContainerFile: The file which describes the pcd, used for error
231 # report
232 #
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)
242 else:
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)
247
248 return (TokenName, TokenGuid, List1, List2, List3, List4, List5, Type)
249
250 ## Get DynamicVpdPcd
251 #
252 # Get DynamicVpdPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|
253 # <VpdOffset>[|<MaximumDatumSize>]
254 #
255 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>
256 # |TRUE/FALSE
257 # @param ContainerFile: The file which describes the pcd, used for error
258 # report
259 #
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)
267 else:
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)
271
272 return (TokenName, TokenGuid, List1, List2, Type)
273
274 ## GetComponent
275 #
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]], ...]
279 #
280 # @param Lines: The content to be parsed
281 # @param KeyValues: To store data after parsing
282 #
283 def GetComponent(Lines, KeyValues):
284 (FindBlock, FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
285 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, FindPcdsDynamic, \
286 FindPcdsDynamicEx) = (False, False, False, False, False, False, False, \
287 False)
288 ListItem = None
289 LibraryClassItem = []
290 BuildOption = []
291 Pcd = []
292
293 for Line in Lines:
294 Line = Line[0]
295 #
296 # Ignore !include statement
297 #
298 if Line.upper().find(DataType.TAB_INCLUDE.upper() + ' ') > -1 or \
299 Line.upper().find(DataType.TAB_DEFINE + ' ') > -1:
300 continue
301
302 if FindBlock == False:
303 ListItem = Line
304 #
305 # find '{' at line tail
306 #
307 if Line.endswith('{'):
308 FindBlock = True
309 ListItem = CleanString(Line.rsplit('{', 1)[0], \
310 DataType.TAB_COMMENT_SPLIT)
311
312 #
313 # Parse a block content
314 #
315 if FindBlock:
316 if Line.find('<LibraryClasses>') != -1:
317 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
318 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
319 FindPcdsDynamic, FindPcdsDynamicEx) = \
320 (True, False, False, False, False, False, False)
321 continue
322 if Line.find('<BuildOptions>') != -1:
323 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
324 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
325 FindPcdsDynamic, FindPcdsDynamicEx) = \
326 (False, True, False, False, False, False, False)
327 continue
328 if Line.find('<PcdsFeatureFlag>') != -1:
329 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
330 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
331 FindPcdsDynamic, FindPcdsDynamicEx) = \
332 (False, False, True, False, False, False, False)
333 continue
334 if Line.find('<PcdsPatchableInModule>') != -1:
335 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
336 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
337 FindPcdsDynamic, FindPcdsDynamicEx) = \
338 (False, False, False, True, False, False, False)
339 continue
340 if Line.find('<PcdsFixedAtBuild>') != -1:
341 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
342 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
343 FindPcdsDynamic, FindPcdsDynamicEx) = \
344 (False, False, False, False, True, False, False)
345 continue
346 if Line.find('<PcdsDynamic>') != -1:
347 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
348 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
349 FindPcdsDynamic, FindPcdsDynamicEx) = \
350 (False, False, False, False, False, True, False)
351 continue
352 if Line.find('<PcdsDynamicEx>') != -1:
353 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
354 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
355 FindPcdsDynamic, FindPcdsDynamicEx) = \
356 (False, False, False, False, False, False, True)
357 continue
358 if Line.endswith('}'):
359 #
360 # find '}' at line tail
361 #
362 KeyValues.append([ListItem, LibraryClassItem, \
363 BuildOption, Pcd])
364 (FindBlock, FindLibraryClass, FindBuildOption, \
365 FindPcdsFeatureFlag, FindPcdsPatchableInModule, \
366 FindPcdsFixedAtBuild, FindPcdsDynamic, FindPcdsDynamicEx) = \
367 (False, False, False, False, False, False, False, False)
368 LibraryClassItem, BuildOption, Pcd = [], [], []
369 continue
370
371 if FindBlock:
372 if FindLibraryClass:
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))
386 else:
387 KeyValues.append([ListItem, [], [], []])
388
389 return True
390
391 ## GetExec
392 #
393 # Parse a string with format "InfFilename [EXEC = ExecFilename]"
394 # Return (InfFilename, ExecFilename)
395 #
396 # @param String: String with EXEC statement
397 #
398 def GetExec(String):
399 InfFilename = ''
400 ExecFilename = ''
401 if String.find('EXEC') > -1:
402 InfFilename = String[ : String.find('EXEC')].strip()
403 ExecFilename = String[String.find('EXEC') + len('EXEC') : ].strip()
404 else:
405 InfFilename = String.strip()
406
407 return (InfFilename, ExecFilename)
408
409 ## GetComponents
410 #
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]], ...]
414 #
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
419 #
420 # @retval True Get component successfully
421 #
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)
429 ListItem = None
430 LibraryClassItem = []
431 BuildOption = []
432 Pcd = []
433
434 LineList = Lines.split('\n')
435 for Line in LineList:
436 Line = CleanString(Line, CommentCharacter)
437 if Line is None or Line == '':
438 continue
439
440 if FindBlock == False:
441 ListItem = Line
442 #
443 # find '{' at line tail
444 #
445 if Line.endswith('{'):
446 FindBlock = True
447 ListItem = CleanString(Line.rsplit('{', 1)[0], CommentCharacter)
448
449 #
450 # Parse a block content
451 #
452 if FindBlock:
453 if Line.find('<LibraryClasses>') != -1:
454 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
455 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
456 FindPcdsDynamic, FindPcdsDynamicEx) = \
457 (True, False, False, False, False, False, False)
458 continue
459 if Line.find('<BuildOptions>') != -1:
460 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
461 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
462 FindPcdsDynamic, FindPcdsDynamicEx) = \
463 (False, True, False, False, False, False, False)
464 continue
465 if Line.find('<PcdsFeatureFlag>') != -1:
466 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
467 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
468 FindPcdsDynamic, FindPcdsDynamicEx) = \
469 (False, False, True, False, False, False, False)
470 continue
471 if Line.find('<PcdsPatchableInModule>') != -1:
472 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
473 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
474 FindPcdsDynamic, FindPcdsDynamicEx) = \
475 (False, False, False, True, False, False, False)
476 continue
477 if Line.find('<PcdsFixedAtBuild>') != -1:
478 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
479 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
480 FindPcdsDynamic, FindPcdsDynamicEx) = \
481 (False, False, False, False, True, False, False)
482 continue
483 if Line.find('<PcdsDynamic>') != -1:
484 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
485 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
486 FindPcdsDynamic, FindPcdsDynamicEx) = \
487 (False, False, False, False, False, True, False)
488 continue
489 if Line.find('<PcdsDynamicEx>') != -1:
490 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
491 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
492 FindPcdsDynamic, FindPcdsDynamicEx) = \
493 (False, False, False, False, False, False, True)
494 continue
495 if Line.endswith('}'):
496 #
497 # find '}' at line tail
498 #
499 KeyValues.append([ListItem, LibraryClassItem, BuildOption, \
500 Pcd])
501 (FindBlock, FindLibraryClass, FindBuildOption, \
502 FindPcdsFeatureFlag, FindPcdsPatchableInModule, \
503 FindPcdsFixedAtBuild, FindPcdsDynamic, FindPcdsDynamicEx) = \
504 (False, False, False, False, False, False, False, False)
505 LibraryClassItem, BuildOption, Pcd = [], [], []
506 continue
507
508 if FindBlock:
509 if FindLibraryClass:
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))
523 else:
524 KeyValues.append([ListItem, [], [], []])
525
526 return True
527
528 ## Get Source
529 #
530 # Get Source of Inf as <Filename>[|<Family>[|<TagName>[|<ToolCode>
531 # [|<PcdFeatureFlag>]]]]
532 #
533 # @param Item: String as <Filename>[|<Family>[|<TagName>[|<ToolCode>
534 # [|<PcdFeatureFlag>]]]]
535 # @param ContainerFile: The file which describes the library class, used
536 # for error report
537 #
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', \
547 Item, LineNo)
548 if List[4] != '':
549 CheckPcdTokenInfo(List[4], 'Sources', ContainerFile, LineNo)
550
551 return (List[0], List[1], List[2], List[3], List[4])
552
553 ## Get Binary
554 #
555 # Get Binary of Inf as <Filename>[|<Family>[|<TagName>[|<ToolCode>
556 # [|<PcdFeatureFlag>]]]]
557 #
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
562 #
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)
570
571 if len(List) >= 4:
572 if List[3] != '':
573 CheckPcdTokenInfo(List[3], 'Binaries', ContainerFile, LineNo)
574 return (List[0], List[1], List[2], List[3])
575 elif len(List) == 3:
576 return (List[0], List[1], List[2], '')
577
578 ## Get Guids/Protocols/Ppis
579 #
580 # Get Guids/Protocols/Ppis of Inf as <GuidCName>[|<PcdFeatureFlag>]
581 #
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
586 #
587 def GetGuidsProtocolsPpisOfInf(Item):
588 ItemNew = Item + DataType.TAB_VALUE_SPLIT
589 List = GetSplitValueList(ItemNew)
590 return (List[0], List[1])
591
592 ## Get Guids/Protocols/Ppis
593 #
594 # Get Guids/Protocols/Ppis of Dec as <GuidCName>=<GuidValue>
595 #
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
600 #
601 def GetGuidsProtocolsPpisOfDec(Item, Type, ContainerFile, LineNo= -1):
602 List = GetSplitValueList(Item, DataType.TAB_EQUAL_SPLIT)
603 if len(List) != 2:
604 RaiseParserError(Item, Type, ContainerFile, '<CName>=<GuidValue>', \
605 LineNo)
606 #
607 #convert C-Format Guid to Register Format
608 #
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)
614 else:
615 if CheckGuidRegFormat(List[1]):
616 RegisterFormatGuid = List[1]
617 else:
618 RaiseParserError(Item, Type, ContainerFile, \
619 'CFormat or RegisterFormat', LineNo)
620
621 return (List[0], RegisterFormatGuid)
622
623 ## GetPackage
624 #
625 # Get Package of Inf as <PackagePath>[|<PcdFeatureFlag>]
626 #
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
631 #
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', \
637 List[0], LineNo)
638 if List[1] != '':
639 CheckPcdTokenInfo(List[1], 'Packages', ContainerFile, LineNo)
640
641 return (List[0], List[1])
642
643 ## Get Pcd Values of Inf
644 #
645 # Get Pcd of Inf as <TokenSpaceGuidCName>.<PcdCName>[|<Value>]
646 #
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
650 #
651 def GetPcdOfInf(Item, Type, File, LineNo):
652 Format = '<TokenSpaceGuidCName>.<PcdCName>[|<Value>]'
653 TokenGuid, TokenName, Value, InfType = '', '', '', ''
654
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)
669 else:
670 TokenGuid = TokenInfo[0]
671 TokenName = TokenInfo[1]
672
673 if len(List) > 1:
674 Value = List[1]
675 else:
676 Value = None
677 return (TokenGuid, TokenName, Value, InfType)
678
679
680 ## Get Pcd Values of Dec
681 #
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
687 #
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)
692 if len(List) != 4:
693 RaiseParserError(Item, 'Pcds' + Type, File, Format, LineNo)
694 else:
695 Value = List[1]
696 DatumType = List[2]
697 Token = List[3]
698 TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT)
699 if len(TokenInfo) != 2:
700 RaiseParserError(Item, 'Pcds' + Type, File, Format, LineNo)
701 else:
702 TokenGuid = TokenInfo[0]
703 TokenName = TokenInfo[1]
704
705 return (TokenGuid, TokenName, Value, DatumType, Token, Type)
706
707 ## Parse DEFINE statement
708 #
709 # Get DEFINE macros
710 #
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
719 #
720 def ParseDefine(LineValue, StartLine, Table, FileID, SectionName, \
721 SectionModel, Arch):
722 Logger.Debug(Logger.DEBUG_2, ST.MSG_DEFINE_STATEMENT_FOUND % (LineValue, \
723 SectionName))
724 Define = \
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, \
732 StartLine, -1, 0)
733
734 ## InsertSectionItems
735 #
736 # Insert item data of a section to a dict
737 #
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
744 #
745 def InsertSectionItems(Model, SectionItemList, ArchList, \
746 ThirdList, RecordSet):
747 #
748 # Insert each item data of a section
749 #
750 for Index in range(0, len(ArchList)):
751 Arch = ArchList[Index]
752 Third = ThirdList[Index]
753 if Arch == '':
754 Arch = DataType.TAB_ARCH_COMMON
755
756 Records = RecordSet[Model]
757 for SectionItem in SectionItemList:
758 LineValue, StartLine, Comment = SectionItem[0], \
759 SectionItem[1], SectionItem[2]
760
761 Logger.Debug(4, ST.MSG_PARSING % LineValue)
762 #
763 # And then parse DEFINE statement
764 #
765 if LineValue.upper().find(DataType.TAB_DEFINE.upper() + ' ') > -1:
766 continue
767 #
768 # At last parse other sections
769 #
770 IdNum = -1
771 Records.append([LineValue, Arch, StartLine, IdNum, Third, Comment])
772
773 if RecordSet != {}:
774 RecordSet[Model] = Records
775
776 ## GenMetaDatSectionItem
777 #
778 # @param Key: A key
779 # @param Value: A value
780 # @param List: A list
781 #
782 def GenMetaDatSectionItem(Key, Value, List):
783 if Key not in List:
784 List[Key] = [Value]
785 else:
786 List[Key].append(Value)
787
788 ## GetPkgInfoFromDec
789 #
790 # get package name, guid, version info from dec files
791 #
792 # @param Path: File path
793 #
794 def GetPkgInfoFromDec(Path):
795 PkgName = None
796 PkgGuid = None
797 PkgVersion = None
798
799 Path = Path.replace('\\', '/')
800
801 if not os.path.exists(Path):
802 Logger.Error("\nUPT", FILE_NOT_FOUND, File=Path)
803
804 if Path in gPKG_INFO_DICT:
805 return gPKG_INFO_DICT[Path]
806
807 try:
808 DecParser = None
809 if Path not in GlobalData.gPackageDict:
810 DecParser = Dec(Path)
811 GlobalData.gPackageDict[Path] = DecParser
812 else:
813 DecParser = GlobalData.gPackageDict[Path]
814
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
820 except FatalError:
821 return None, None, None
822
823
824 ## GetWorkspacePackage
825 #
826 # Get a list of workspace package information.
827 #
828 def GetWorkspacePackage():
829 DecFileList = []
830 WorkspaceDir = GlobalData.gWORKSPACE
831 PackageDir = GlobalData.gPACKAGE_PATH
832 for PkgRoot in [WorkspaceDir] + PackageDir:
833 for Root, Dirs, Files in os.walk(PkgRoot):
834 if 'CVS' in Dirs:
835 Dirs.remove('CVS')
836 if '.svn' in Dirs:
837 Dirs.remove('.svn')
838 for Dir in Dirs:
839 if Dir.startswith('.'):
840 Dirs.remove(Dir)
841 for FileSp in Files:
842 if FileSp.startswith('.'):
843 continue
844 Ext = os.path.splitext(FileSp)[1]
845 if Ext.lower() in ['.dec']:
846 DecFileList.append\
847 (os.path.normpath(os.path.join(Root, FileSp)))
848 #
849 # abstract package guid, version info from DecFile List
850 #
851 PkgList = []
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))
856
857 return PkgList
858
859 ## GetWorkspaceModule
860 #
861 # Get a list of workspace modules.
862 #
863 def GetWorkspaceModule():
864 InfFileList = []
865 WorkspaceDir = GlobalData.gWORKSPACE
866 for Root, Dirs, Files in os.walk(WorkspaceDir):
867 if 'CVS' in Dirs:
868 Dirs.remove('CVS')
869 if '.svn' in Dirs:
870 Dirs.remove('.svn')
871 if 'Build' in Dirs:
872 Dirs.remove('Build')
873 for Dir in Dirs:
874 if Dir.startswith('.'):
875 Dirs.remove(Dir)
876 for FileSp in Files:
877 if FileSp.startswith('.'):
878 continue
879 Ext = os.path.splitext(FileSp)[1]
880 if Ext.lower() in ['.inf']:
881 InfFileList.append\
882 (os.path.normpath(os.path.join(Root, FileSp)))
883
884 return InfFileList
885
886 ## MacroParser used to parse macro definition
887 #
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.
892 #
893 def MacroParser(Line, FileName, SectionType, FileLocalMacros):
894 MacroDefPattern = re.compile("^(DEFINE)[ \t]+")
895 LineContent = Line[0]
896 LineNo = Line[1]
897 Match = MacroDefPattern.match(LineContent)
898 if not Match:
899 #
900 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
901 #
902 return None, None
903
904 TokenList = GetSplitValueList(LineContent[Match.end(1):], \
905 DataType.TAB_EQUAL_SPLIT, 1)
906 #
907 # Syntax check
908 #
909 if not TokenList[0]:
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)
915
916 Name, Value = TokenList
917
918 #
919 # DEFINE defined macros
920 #
921 if SectionType == DataType.MODEL_META_DATA_HEADER:
922 FileLocalMacros[Name] = Value
923
924 ReIsValidMacroName = re.compile(r"^[A-Z][A-Z0-9_]*$", re.DOTALL)
925 if ReIsValidMacroName.match(Name) is None:
926 Logger.Error('Parser',
927 FORMAT_INVALID,
928 ST.ERR_MACRONAME_INVALID % (Name),
929 ExtraData=LineContent,
930 File=FileName,
931 Line=LineNo)
932
933 # Validate MACRO Value
934 #
935 # <MacroDefinition> ::= [<Comments>]{0,}
936 # "DEFINE" <MACRO> "=" [{<PATH>} {<VALUE>}] <EOL>
937 # <Value> ::= {<NumVal>} {<Boolean>} {<AsciiString>} {<GUID>}
938 # {<CString>} {<UnicodeString>} {<CArray>}
939 #
940 # The definition of <NumVal>, <PATH>, <Boolean>, <GUID>, <CString>,
941 # <UnicodeString>, <CArray> are subset of <AsciiString>.
942 #
943 ReIsValidMacroValue = re.compile(r"^[\x20-\x7e]*$", re.DOTALL)
944 if ReIsValidMacroValue.match(Value) is None:
945 Logger.Error('Parser',
946 FORMAT_INVALID,
947 ST.ERR_MACROVALUE_INVALID % (Value),
948 ExtraData=LineContent,
949 File=FileName,
950 Line=LineNo)
951
952 return Name, Value
953
954 ## GenSection
955 #
956 # generate section contents
957 #
958 # @param SectionName: indicate the name of the section, details refer to
959 # INF, DEC specs
960 # @param SectionDict: section statement dict, key is SectionAttrs(arch,
961 # moduletype or platform may exist as needed) list
962 # seperated by space,
963 # value is statement
964 #
965 def GenSection(SectionName, SectionDict, SplitArch=True, NeedBlankLine=False):
966 Content = ''
967 for SectionAttrs in SectionDict:
968 StatementList = SectionDict[SectionAttrs]
969 if SectionAttrs and SectionName != 'Defines' and SectionAttrs.strip().upper() != DataType.TAB_ARCH_COMMON:
970 if SplitArch:
971 ArchList = GetSplitValueList(SectionAttrs, DataType.TAB_SPACE_SPLIT)
972 else:
973 if SectionName != 'UserExtensions':
974 ArchList = GetSplitValueList(SectionAttrs, DataType.TAB_COMMENT_SPLIT)
975 else:
976 ArchList = [SectionAttrs]
977 for Index in xrange(0, len(ArchList)):
978 ArchList[Index] = ConvertArchForInstall(ArchList[Index])
979 Section = '[' + SectionName + '.' + (', ' + SectionName + '.').join(ArchList) + ']'
980 else:
981 Section = '[' + SectionName + ']'
982 Content += '\n' + Section + '\n'
983 if StatementList is not None:
984 for Statement in StatementList:
985 LineList = Statement.split('\n')
986 NewStatement = ""
987 for Line in LineList:
988 # ignore blank comment
989 if not Line.replace("#", '').strip() and SectionName not in ('Defines', 'Hob', 'Event', 'BootMode'):
990 continue
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
994 continue
995 NewStatement += " %s\n" % Line
996 if NeedBlankLine:
997 Content += NewStatement + '\n'
998 else:
999 Content += NewStatement
1000
1001 if NeedBlankLine:
1002 Content = Content[:-1]
1003 if not Content.replace('\\n', '').strip():
1004 return ''
1005 return Content
1006
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
1010 #
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
1013 #
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]:
1017 Arch = Arch.upper()
1018 elif Arch.upper() == DataType.TAB_ARCH_COMMON:
1019 Arch = Arch.lower()
1020
1021 return Arch