5c4666399e29305019975ab4e88ece946304a14c
[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
20 ##
21 # Import Modules
22 #
23 import os.path
24 import re
25
26 from Library.StringUtils import RaiseParserError
27 from Library.StringUtils import GetSplitValueList
28 from Library.StringUtils import CheckFileType
29 from Library.StringUtils import CheckFileExist
30 from Library.StringUtils import CleanString
31 from Library.StringUtils import NormPath
32
33 from Logger.ToolError import FILE_NOT_FOUND
34 from Logger.ToolError import FatalError
35 from Logger.ToolError import FORMAT_INVALID
36
37 from Library import DataType
38
39 from Library.Misc import GuidStructureStringToGuidString
40 from Library.Misc import CheckGuidRegFormat
41 from Logger import StringTable as ST
42 import Logger.Log as Logger
43
44 from Parser.DecParser import Dec
45 import GlobalData
46
47 gPKG_INFO_DICT = {}
48
49 ## GetBuildOption
50 #
51 # Parse a string with format "[<Family>:]<ToolFlag>=Flag"
52 # Return (Family, ToolFlag, Flag)
53 #
54 # @param String: String with BuildOption statement
55 # @param File: The file which defines build option, used in error report
56 #
57 def GetBuildOption(String, File, LineNo= -1):
58 (Family, ToolChain, Flag) = ('', '', '')
59 if String.find(DataType.TAB_EQUAL_SPLIT) < 0:
60 RaiseParserError(String, 'BuildOptions', File, \
61 '[<Family>:]<ToolFlag>=Flag', LineNo)
62 else:
63 List = GetSplitValueList(String, DataType.TAB_EQUAL_SPLIT, MaxSplit=1)
64 if List[0].find(':') > -1:
65 Family = List[0][ : List[0].find(':')].strip()
66 ToolChain = List[0][List[0].find(':') + 1 : ].strip()
67 else:
68 ToolChain = List[0].strip()
69 Flag = List[1].strip()
70 return (Family, ToolChain, Flag)
71
72 ## Get Library Class
73 #
74 # Get Library of Dsc as <LibraryClassKeyWord>|<LibraryInstance>
75 #
76 # @param Item: String as <LibraryClassKeyWord>|<LibraryInstance>
77 # @param ContainerFile: The file which describes the library class, used for
78 # error report
79 #
80 def GetLibraryClass(Item, ContainerFile, WorkspaceDir, LineNo= -1):
81 List = GetSplitValueList(Item[0])
82 SupMod = DataType.SUP_MODULE_LIST_STRING
83 if len(List) != 2:
84 RaiseParserError(Item[0], 'LibraryClasses', ContainerFile, \
85 '<LibraryClassKeyWord>|<LibraryInstance>')
86 else:
87 CheckFileType(List[1], '.Inf', ContainerFile, \
88 'library class instance', Item[0], LineNo)
89 CheckFileExist(WorkspaceDir, List[1], ContainerFile, \
90 'LibraryClasses', Item[0], LineNo)
91 if Item[1] != '':
92 SupMod = Item[1]
93
94 return (List[0], List[1], SupMod)
95
96 ## Get Library Class
97 #
98 # Get Library of Dsc as <LibraryClassKeyWord>[|<LibraryInstance>]
99 # [|<TokenSpaceGuidCName>.<PcdCName>]
100 #
101 # @param Item: String as <LibraryClassKeyWord>|<LibraryInstance>
102 # @param ContainerFile: The file which describes the library class, used for
103 # error report
104 #
105 def GetLibraryClassOfInf(Item, ContainerFile, WorkspaceDir, LineNo= -1):
106 ItemList = GetSplitValueList((Item[0] + DataType.TAB_VALUE_SPLIT * 2))
107 SupMod = DataType.SUP_MODULE_LIST_STRING
108
109 if len(ItemList) > 5:
110 RaiseParserError\
111 (Item[0], 'LibraryClasses', ContainerFile, \
112 '<LibraryClassKeyWord>[|<LibraryInstance>]\
113 [|<TokenSpaceGuidCName>.<PcdCName>]')
114 else:
115 CheckFileType(ItemList[1], '.Inf', ContainerFile, 'LibraryClasses', \
116 Item[0], LineNo)
117 CheckFileExist(WorkspaceDir, ItemList[1], ContainerFile, \
118 'LibraryClasses', Item[0], LineNo)
119 if ItemList[2] != '':
120 CheckPcdTokenInfo(ItemList[2], 'LibraryClasses', \
121 ContainerFile, LineNo)
122 if Item[1] != '':
123 SupMod = Item[1]
124
125 return (ItemList[0], ItemList[1], ItemList[2], SupMod)
126
127 ## CheckPcdTokenInfo
128 #
129 # Check if PcdTokenInfo is following <TokenSpaceGuidCName>.<PcdCName>
130 #
131 # @param TokenInfoString: String to be checked
132 # @param Section: Used for error report
133 # @param File: Used for error report
134 #
135 def CheckPcdTokenInfo(TokenInfoString, Section, File, LineNo= -1):
136 Format = '<TokenSpaceGuidCName>.<PcdCName>'
137 if TokenInfoString != '' and TokenInfoString is not None:
138 TokenInfoList = GetSplitValueList(TokenInfoString, DataType.TAB_SPLIT)
139 if len(TokenInfoList) == 2:
140 return True
141
142 RaiseParserError(TokenInfoString, Section, File, Format, LineNo)
143
144 ## Get Pcd
145 #
146 # Get Pcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<Value>
147 # [|<Type>|<MaximumDatumSize>]
148 #
149 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|
150 # <Value>[|<Type>|<MaximumDatumSize>]
151 # @param ContainerFile: The file which describes the pcd, used for error
152 # report
153
154 #
155 def GetPcd(Item, Type, ContainerFile, LineNo= -1):
156 TokenGuid, TokenName, Value, MaximumDatumSize, Token = '', '', '', '', ''
157 List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2)
158
159 if len(List) < 4 or len(List) > 6:
160 RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \
161 '<PcdTokenSpaceGuidCName>.<TokenCName>|<Value>\
162 [|<Type>|<MaximumDatumSize>]', LineNo)
163 else:
164 Value = List[1]
165 MaximumDatumSize = List[2]
166 Token = List[3]
167
168 if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
169 (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)
170
171 return (TokenName, TokenGuid, Value, MaximumDatumSize, Token, Type)
172
173 ## Get FeatureFlagPcd
174 #
175 # Get FeatureFlagPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE
176 #
177 # @param Item: String as <PcdTokenSpaceGuidCName>
178 # .<TokenCName>|TRUE/FALSE
179 # @param ContainerFile: The file which describes the pcd, used for error
180 # report
181 #
182 def GetFeatureFlagPcd(Item, Type, ContainerFile, LineNo= -1):
183 TokenGuid, TokenName, Value = '', '', ''
184 List = GetSplitValueList(Item)
185 if len(List) != 2:
186 RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \
187 '<PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE', \
188 LineNo)
189 else:
190 Value = List[1]
191 if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
192 (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)
193
194 return (TokenName, TokenGuid, Value, Type)
195
196 ## Get DynamicDefaultPcd
197 #
198 # Get DynamicDefaultPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>
199 # |<Value>[|<DatumTyp>[|<MaxDatumSize>]]
200 #
201 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|
202 # TRUE/FALSE
203 # @param ContainerFile: The file which describes the pcd, used for error
204 # report
205 #
206 def GetDynamicDefaultPcd(Item, Type, ContainerFile, LineNo= -1):
207 TokenGuid, TokenName, Value, DatumTyp, MaxDatumSize = '', '', '', '', ''
208 List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2)
209 if len(List) < 4 or len(List) > 8:
210 RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \
211 '<PcdTokenSpaceGuidCName>.<TokenCName>|<Value>\
212 [|<DatumTyp>[|<MaxDatumSize>]]', LineNo)
213 else:
214 Value = List[1]
215 DatumTyp = List[2]
216 MaxDatumSize = List[3]
217 if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
218 (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)
219
220 return (TokenName, TokenGuid, Value, DatumTyp, MaxDatumSize, Type)
221
222 ## Get DynamicHiiPcd
223 #
224 # Get DynamicHiiPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<String>|
225 # <VariableGuidCName>|<VariableOffset>[|<DefaultValue>[|<MaximumDatumSize>]]
226 #
227 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>|
228 # TRUE/FALSE
229 # @param ContainerFile: The file which describes the pcd, used for error
230 # report
231 #
232 def GetDynamicHiiPcd(Item, Type, ContainerFile, LineNo= -1):
233 TokenGuid, TokenName, List1, List2, List3, List4, List5 = \
234 '', '', '', '', '', '', ''
235 List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2)
236 if len(List) < 6 or len(List) > 8:
237 RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \
238 '<PcdTokenSpaceGuidCName>.<TokenCName>|<String>|\
239 <VariableGuidCName>|<VariableOffset>[|<DefaultValue>\
240 [|<MaximumDatumSize>]]', LineNo)
241 else:
242 List1, List2, List3, List4, List5 = \
243 List[1], List[2], List[3], List[4], List[5]
244 if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
245 (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)
246
247 return (TokenName, TokenGuid, List1, List2, List3, List4, List5, Type)
248
249 ## Get DynamicVpdPcd
250 #
251 # Get DynamicVpdPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|
252 # <VpdOffset>[|<MaximumDatumSize>]
253 #
254 # @param Item: String as <PcdTokenSpaceGuidCName>.<TokenCName>
255 # |TRUE/FALSE
256 # @param ContainerFile: The file which describes the pcd, used for error
257 # report
258 #
259 def GetDynamicVpdPcd(Item, Type, ContainerFile, LineNo= -1):
260 TokenGuid, TokenName, List1, List2 = '', '', '', ''
261 List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT)
262 if len(List) < 3 or len(List) > 4:
263 RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \
264 '<PcdTokenSpaceGuidCName>.<TokenCName>|<VpdOffset>\
265 [|<MaximumDatumSize>]', LineNo)
266 else:
267 List1, List2 = List[1], List[2]
268 if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
269 (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)
270
271 return (TokenName, TokenGuid, List1, List2, Type)
272
273 ## GetComponent
274 #
275 # Parse block of the components defined in dsc file
276 # Set KeyValues as [ ['component name', [lib1, lib2, lib3],
277 # [bo1, bo2, bo3], [pcd1, pcd2, pcd3]], ...]
278 #
279 # @param Lines: The content to be parsed
280 # @param KeyValues: To store data after parsing
281 #
282 def GetComponent(Lines, KeyValues):
283 (FindBlock, FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
284 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, FindPcdsDynamic, \
285 FindPcdsDynamicEx) = (False, False, False, False, False, False, False, \
286 False)
287 ListItem = None
288 LibraryClassItem = []
289 BuildOption = []
290 Pcd = []
291
292 for Line in Lines:
293 Line = Line[0]
294 #
295 # Ignore !include statement
296 #
297 if Line.upper().find(DataType.TAB_INCLUDE.upper() + ' ') > -1 or \
298 Line.upper().find(DataType.TAB_DEFINE + ' ') > -1:
299 continue
300
301 if FindBlock == False:
302 ListItem = Line
303 #
304 # find '{' at line tail
305 #
306 if Line.endswith('{'):
307 FindBlock = True
308 ListItem = CleanString(Line.rsplit('{', 1)[0], \
309 DataType.TAB_COMMENT_SPLIT)
310
311 #
312 # Parse a block content
313 #
314 if FindBlock:
315 if Line.find('<LibraryClasses>') != -1:
316 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
317 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
318 FindPcdsDynamic, FindPcdsDynamicEx) = \
319 (True, False, False, False, False, False, False)
320 continue
321 if Line.find('<BuildOptions>') != -1:
322 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
323 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
324 FindPcdsDynamic, FindPcdsDynamicEx) = \
325 (False, True, False, False, False, False, False)
326 continue
327 if Line.find('<PcdsFeatureFlag>') != -1:
328 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
329 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
330 FindPcdsDynamic, FindPcdsDynamicEx) = \
331 (False, False, True, False, False, False, False)
332 continue
333 if Line.find('<PcdsPatchableInModule>') != -1:
334 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
335 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
336 FindPcdsDynamic, FindPcdsDynamicEx) = \
337 (False, False, False, True, False, False, False)
338 continue
339 if Line.find('<PcdsFixedAtBuild>') != -1:
340 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
341 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
342 FindPcdsDynamic, FindPcdsDynamicEx) = \
343 (False, False, False, False, True, False, False)
344 continue
345 if Line.find('<PcdsDynamic>') != -1:
346 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
347 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
348 FindPcdsDynamic, FindPcdsDynamicEx) = \
349 (False, False, False, False, False, True, False)
350 continue
351 if Line.find('<PcdsDynamicEx>') != -1:
352 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
353 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
354 FindPcdsDynamic, FindPcdsDynamicEx) = \
355 (False, False, False, False, False, False, True)
356 continue
357 if Line.endswith('}'):
358 #
359 # find '}' at line tail
360 #
361 KeyValues.append([ListItem, LibraryClassItem, \
362 BuildOption, Pcd])
363 (FindBlock, FindLibraryClass, FindBuildOption, \
364 FindPcdsFeatureFlag, FindPcdsPatchableInModule, \
365 FindPcdsFixedAtBuild, FindPcdsDynamic, FindPcdsDynamicEx) = \
366 (False, False, False, False, False, False, False, False)
367 LibraryClassItem, BuildOption, Pcd = [], [], []
368 continue
369
370 if FindBlock:
371 if FindLibraryClass:
372 LibraryClassItem.append(Line)
373 elif FindBuildOption:
374 BuildOption.append(Line)
375 elif FindPcdsFeatureFlag:
376 Pcd.append((DataType.TAB_PCDS_FEATURE_FLAG_NULL, Line))
377 elif FindPcdsPatchableInModule:
378 Pcd.append((DataType.TAB_PCDS_PATCHABLE_IN_MODULE_NULL, Line))
379 elif FindPcdsFixedAtBuild:
380 Pcd.append((DataType.TAB_PCDS_FIXED_AT_BUILD_NULL, Line))
381 elif FindPcdsDynamic:
382 Pcd.append((DataType.TAB_PCDS_DYNAMIC_DEFAULT_NULL, Line))
383 elif FindPcdsDynamicEx:
384 Pcd.append((DataType.TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL, Line))
385 else:
386 KeyValues.append([ListItem, [], [], []])
387
388 return True
389
390 ## GetExec
391 #
392 # Parse a string with format "InfFilename [EXEC = ExecFilename]"
393 # Return (InfFilename, ExecFilename)
394 #
395 # @param String: String with EXEC statement
396 #
397 def GetExec(String):
398 InfFilename = ''
399 ExecFilename = ''
400 if String.find('EXEC') > -1:
401 InfFilename = String[ : String.find('EXEC')].strip()
402 ExecFilename = String[String.find('EXEC') + len('EXEC') : ].strip()
403 else:
404 InfFilename = String.strip()
405
406 return (InfFilename, ExecFilename)
407
408 ## GetComponents
409 #
410 # Parse block of the components defined in dsc file
411 # Set KeyValues as [ ['component name', [lib1, lib2, lib3], [bo1, bo2, bo3],
412 # [pcd1, pcd2, pcd3]], ...]
413 #
414 # @param Lines: The content to be parsed
415 # @param Key: Reserved
416 # @param KeyValues: To store data after parsing
417 # @param CommentCharacter: Comment char, used to ignore comment content
418 #
419 # @retval True Get component successfully
420 #
421 def GetComponents(Lines, KeyValues, CommentCharacter):
422 if Lines.find(DataType.TAB_SECTION_END) > -1:
423 Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1]
424 (FindBlock, FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
425 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, FindPcdsDynamic, \
426 FindPcdsDynamicEx) = \
427 (False, False, False, False, False, False, False, False)
428 ListItem = None
429 LibraryClassItem = []
430 BuildOption = []
431 Pcd = []
432
433 LineList = Lines.split('\n')
434 for Line in LineList:
435 Line = CleanString(Line, CommentCharacter)
436 if Line is None or Line == '':
437 continue
438
439 if FindBlock == False:
440 ListItem = Line
441 #
442 # find '{' at line tail
443 #
444 if Line.endswith('{'):
445 FindBlock = True
446 ListItem = CleanString(Line.rsplit('{', 1)[0], CommentCharacter)
447
448 #
449 # Parse a block content
450 #
451 if FindBlock:
452 if Line.find('<LibraryClasses>') != -1:
453 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
454 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
455 FindPcdsDynamic, FindPcdsDynamicEx) = \
456 (True, False, False, False, False, False, False)
457 continue
458 if Line.find('<BuildOptions>') != -1:
459 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
460 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
461 FindPcdsDynamic, FindPcdsDynamicEx) = \
462 (False, True, False, False, False, False, False)
463 continue
464 if Line.find('<PcdsFeatureFlag>') != -1:
465 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
466 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
467 FindPcdsDynamic, FindPcdsDynamicEx) = \
468 (False, False, True, False, False, False, False)
469 continue
470 if Line.find('<PcdsPatchableInModule>') != -1:
471 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
472 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
473 FindPcdsDynamic, FindPcdsDynamicEx) = \
474 (False, False, False, True, False, False, False)
475 continue
476 if Line.find('<PcdsFixedAtBuild>') != -1:
477 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
478 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
479 FindPcdsDynamic, FindPcdsDynamicEx) = \
480 (False, False, False, False, True, False, False)
481 continue
482 if Line.find('<PcdsDynamic>') != -1:
483 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
484 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
485 FindPcdsDynamic, FindPcdsDynamicEx) = \
486 (False, False, False, False, False, True, False)
487 continue
488 if Line.find('<PcdsDynamicEx>') != -1:
489 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
490 FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
491 FindPcdsDynamic, FindPcdsDynamicEx) = \
492 (False, False, False, False, False, False, True)
493 continue
494 if Line.endswith('}'):
495 #
496 # find '}' at line tail
497 #
498 KeyValues.append([ListItem, LibraryClassItem, BuildOption, \
499 Pcd])
500 (FindBlock, FindLibraryClass, FindBuildOption, \
501 FindPcdsFeatureFlag, FindPcdsPatchableInModule, \
502 FindPcdsFixedAtBuild, FindPcdsDynamic, FindPcdsDynamicEx) = \
503 (False, False, False, False, False, False, False, False)
504 LibraryClassItem, BuildOption, Pcd = [], [], []
505 continue
506
507 if FindBlock:
508 if FindLibraryClass:
509 LibraryClassItem.append(Line)
510 elif FindBuildOption:
511 BuildOption.append(Line)
512 elif FindPcdsFeatureFlag:
513 Pcd.append((DataType.TAB_PCDS_FEATURE_FLAG, Line))
514 elif FindPcdsPatchableInModule:
515 Pcd.append((DataType.TAB_PCDS_PATCHABLE_IN_MODULE, Line))
516 elif FindPcdsFixedAtBuild:
517 Pcd.append((DataType.TAB_PCDS_FIXED_AT_BUILD, Line))
518 elif FindPcdsDynamic:
519 Pcd.append((DataType.TAB_PCDS_DYNAMIC, Line))
520 elif FindPcdsDynamicEx:
521 Pcd.append((DataType.TAB_PCDS_DYNAMIC_EX, Line))
522 else:
523 KeyValues.append([ListItem, [], [], []])
524
525 return True
526
527 ## Get Source
528 #
529 # Get Source of Inf as <Filename>[|<Family>[|<TagName>[|<ToolCode>
530 # [|<PcdFeatureFlag>]]]]
531 #
532 # @param Item: String as <Filename>[|<Family>[|<TagName>[|<ToolCode>
533 # [|<PcdFeatureFlag>]]]]
534 # @param ContainerFile: The file which describes the library class, used
535 # for error report
536 #
537 def GetSource(Item, ContainerFile, FileRelativePath, LineNo= -1):
538 ItemNew = Item + DataType.TAB_VALUE_SPLIT * 4
539 List = GetSplitValueList(ItemNew)
540 if len(List) < 5 or len(List) > 9:
541 RaiseParserError(Item, 'Sources', ContainerFile, \
542 '<Filename>[|<Family>[|<TagName>[|<ToolCode>\
543 [|<PcdFeatureFlag>]]]]', LineNo)
544 List[0] = NormPath(List[0])
545 CheckFileExist(FileRelativePath, List[0], ContainerFile, 'Sources', \
546 Item, LineNo)
547 if List[4] != '':
548 CheckPcdTokenInfo(List[4], 'Sources', ContainerFile, LineNo)
549
550 return (List[0], List[1], List[2], List[3], List[4])
551
552 ## Get Binary
553 #
554 # Get Binary of Inf as <Filename>[|<Family>[|<TagName>[|<ToolCode>
555 # [|<PcdFeatureFlag>]]]]
556 #
557 # @param Item: String as <Filename>[|<Family>[|<TagName>
558 # [|<ToolCode>[|<PcdFeatureFlag>]]]]
559 # @param ContainerFile: The file which describes the library class,
560 # used for error report
561 #
562 def GetBinary(Item, ContainerFile, LineNo= -1):
563 ItemNew = Item + DataType.TAB_VALUE_SPLIT
564 List = GetSplitValueList(ItemNew)
565 if len(List) < 3 or len(List) > 5:
566 RaiseParserError(Item, 'Binaries', ContainerFile, \
567 "<FileType>|<Filename>[|<Target>\
568 [|<TokenSpaceGuidCName>.<PcdCName>]]", LineNo)
569
570 if len(List) >= 4:
571 if List[3] != '':
572 CheckPcdTokenInfo(List[3], 'Binaries', ContainerFile, LineNo)
573 return (List[0], List[1], List[2], List[3])
574 elif len(List) == 3:
575 return (List[0], List[1], List[2], '')
576
577 ## Get Guids/Protocols/Ppis
578 #
579 # Get Guids/Protocols/Ppis of Inf as <GuidCName>[|<PcdFeatureFlag>]
580 #
581 # @param Item: String as <GuidCName>[|<PcdFeatureFlag>]
582 # @param Type: Type of parsing string
583 # @param ContainerFile: The file which describes the library class,
584 # used for error report
585 #
586 def GetGuidsProtocolsPpisOfInf(Item):
587 ItemNew = Item + DataType.TAB_VALUE_SPLIT
588 List = GetSplitValueList(ItemNew)
589 return (List[0], List[1])
590
591 ## Get Guids/Protocols/Ppis
592 #
593 # Get Guids/Protocols/Ppis of Dec as <GuidCName>=<GuidValue>
594 #
595 # @param Item: String as <GuidCName>=<GuidValue>
596 # @param Type: Type of parsing string
597 # @param ContainerFile: The file which describes the library class,
598 # used for error report
599 #
600 def GetGuidsProtocolsPpisOfDec(Item, Type, ContainerFile, LineNo= -1):
601 List = GetSplitValueList(Item, DataType.TAB_EQUAL_SPLIT)
602 if len(List) != 2:
603 RaiseParserError(Item, Type, ContainerFile, '<CName>=<GuidValue>', \
604 LineNo)
605 #
606 #convert C-Format Guid to Register Format
607 #
608 if List[1][0] == '{' and List[1][-1] == '}':
609 RegisterFormatGuid = GuidStructureStringToGuidString(List[1])
610 if RegisterFormatGuid == '':
611 RaiseParserError(Item, Type, ContainerFile, \
612 'CFormat or RegisterFormat', LineNo)
613 else:
614 if CheckGuidRegFormat(List[1]):
615 RegisterFormatGuid = List[1]
616 else:
617 RaiseParserError(Item, Type, ContainerFile, \
618 'CFormat or RegisterFormat', LineNo)
619
620 return (List[0], RegisterFormatGuid)
621
622 ## GetPackage
623 #
624 # Get Package of Inf as <PackagePath>[|<PcdFeatureFlag>]
625 #
626 # @param Item: String as <PackagePath>[|<PcdFeatureFlag>]
627 # @param Type: Type of parsing string
628 # @param ContainerFile: The file which describes the library class,
629 # used for error report
630 #
631 def GetPackage(Item, ContainerFile, FileRelativePath, LineNo= -1):
632 ItemNew = Item + DataType.TAB_VALUE_SPLIT
633 List = GetSplitValueList(ItemNew)
634 CheckFileType(List[0], '.Dec', ContainerFile, 'package', List[0], LineNo)
635 CheckFileExist(FileRelativePath, List[0], ContainerFile, 'Packages', \
636 List[0], LineNo)
637 if List[1] != '':
638 CheckPcdTokenInfo(List[1], 'Packages', ContainerFile, LineNo)
639
640 return (List[0], List[1])
641
642 ## Get Pcd Values of Inf
643 #
644 # Get Pcd of Inf as <TokenSpaceGuidCName>.<PcdCName>[|<Value>]
645 #
646 # @param Item: The string describes pcd
647 # @param Type: The type of Pcd
648 # @param File: The file which describes the pcd, used for error report
649 #
650 def GetPcdOfInf(Item, Type, File, LineNo):
651 Format = '<TokenSpaceGuidCName>.<PcdCName>[|<Value>]'
652 TokenGuid, TokenName, Value, InfType = '', '', '', ''
653
654 if Type == DataType.TAB_PCDS_FIXED_AT_BUILD:
655 InfType = DataType.TAB_INF_FIXED_PCD
656 elif Type == DataType.TAB_PCDS_PATCHABLE_IN_MODULE:
657 InfType = DataType.TAB_INF_PATCH_PCD
658 elif Type == DataType.TAB_PCDS_FEATURE_FLAG:
659 InfType = DataType.TAB_INF_FEATURE_PCD
660 elif Type == DataType.TAB_PCDS_DYNAMIC_EX:
661 InfType = DataType.TAB_INF_PCD_EX
662 elif Type == DataType.TAB_PCDS_DYNAMIC:
663 InfType = DataType.TAB_INF_PCD
664 List = GetSplitValueList(Item, DataType.TAB_VALUE_SPLIT, 1)
665 TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT)
666 if len(TokenInfo) != 2:
667 RaiseParserError(Item, InfType, File, Format, LineNo)
668 else:
669 TokenGuid = TokenInfo[0]
670 TokenName = TokenInfo[1]
671
672 if len(List) > 1:
673 Value = List[1]
674 else:
675 Value = None
676 return (TokenGuid, TokenName, Value, InfType)
677
678
679 ## Get Pcd Values of Dec
680 #
681 # Get Pcd of Dec as <TokenSpcCName>.<TokenCName>|<Value>|<DatumType>|<Token>
682 # @param Item: Pcd item
683 # @param Type: Pcd type
684 # @param File: Dec file
685 # @param LineNo: Line number
686 #
687 def GetPcdOfDec(Item, Type, File, LineNo= -1):
688 Format = '<TokenSpaceGuidCName>.<PcdCName>|<Value>|<DatumType>|<Token>'
689 TokenGuid, TokenName, Value, DatumType, Token = '', '', '', '', ''
690 List = GetSplitValueList(Item)
691 if len(List) != 4:
692 RaiseParserError(Item, 'Pcds' + Type, File, Format, LineNo)
693 else:
694 Value = List[1]
695 DatumType = List[2]
696 Token = List[3]
697 TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT)
698 if len(TokenInfo) != 2:
699 RaiseParserError(Item, 'Pcds' + Type, File, Format, LineNo)
700 else:
701 TokenGuid = TokenInfo[0]
702 TokenName = TokenInfo[1]
703
704 return (TokenGuid, TokenName, Value, DatumType, Token, Type)
705
706 ## Parse DEFINE statement
707 #
708 # Get DEFINE macros
709 #
710 # @param LineValue: A DEFINE line value
711 # @param StartLine: A DEFINE start line
712 # @param Table: A table
713 # @param FileID: File ID
714 # @param Filename: File name
715 # @param SectionName: DEFINE section name
716 # @param SectionModel: DEFINE section model
717 # @param Arch: DEFINE arch
718 #
719 def ParseDefine(LineValue, StartLine, Table, FileID, SectionName, \
720 SectionModel, Arch):
721 Logger.Debug(Logger.DEBUG_2, ST.MSG_DEFINE_STATEMENT_FOUND % (LineValue, \
722 SectionName))
723 Define = \
724 GetSplitValueList(CleanString\
725 (LineValue[LineValue.upper().\
726 find(DataType.TAB_DEFINE.upper() + ' ') + \
727 len(DataType.TAB_DEFINE + ' ') : ]), \
728 DataType.TAB_EQUAL_SPLIT, 1)
729 Table.Insert(DataType.MODEL_META_DATA_DEFINE, Define[0], Define[1], '', \
730 '', '', Arch, SectionModel, FileID, StartLine, -1, \
731 StartLine, -1, 0)
732
733 ## InsertSectionItems
734 #
735 # Insert item data of a section to a dict
736 #
737 # @param Model: A model
738 # @param CurrentSection: Current section
739 # @param SectionItemList: Section item list
740 # @param ArchList: Arch list
741 # @param ThirdList: Third list
742 # @param RecordSet: Record set
743 #
744 def InsertSectionItems(Model, SectionItemList, ArchList, \
745 ThirdList, RecordSet):
746 #
747 # Insert each item data of a section
748 #
749 for Index in range(0, len(ArchList)):
750 Arch = ArchList[Index]
751 Third = ThirdList[Index]
752 if Arch == '':
753 Arch = DataType.TAB_ARCH_COMMON
754
755 Records = RecordSet[Model]
756 for SectionItem in SectionItemList:
757 LineValue, StartLine, Comment = SectionItem[0], \
758 SectionItem[1], SectionItem[2]
759
760 Logger.Debug(4, ST.MSG_PARSING % LineValue)
761 #
762 # And then parse DEFINE statement
763 #
764 if LineValue.upper().find(DataType.TAB_DEFINE.upper() + ' ') > -1:
765 continue
766 #
767 # At last parse other sections
768 #
769 IdNum = -1
770 Records.append([LineValue, Arch, StartLine, IdNum, Third, Comment])
771
772 if RecordSet != {}:
773 RecordSet[Model] = Records
774
775 ## GenMetaDatSectionItem
776 #
777 # @param Key: A key
778 # @param Value: A value
779 # @param List: A list
780 #
781 def GenMetaDatSectionItem(Key, Value, List):
782 if Key not in List:
783 List[Key] = [Value]
784 else:
785 List[Key].append(Value)
786
787 ## GetPkgInfoFromDec
788 #
789 # get package name, guid, version info from dec files
790 #
791 # @param Path: File path
792 #
793 def GetPkgInfoFromDec(Path):
794 PkgName = None
795 PkgGuid = None
796 PkgVersion = None
797
798 Path = Path.replace('\\', '/')
799
800 if not os.path.exists(Path):
801 Logger.Error("\nUPT", FILE_NOT_FOUND, File=Path)
802
803 if Path in gPKG_INFO_DICT:
804 return gPKG_INFO_DICT[Path]
805
806 try:
807 DecParser = None
808 if Path not in GlobalData.gPackageDict:
809 DecParser = Dec(Path)
810 GlobalData.gPackageDict[Path] = DecParser
811 else:
812 DecParser = GlobalData.gPackageDict[Path]
813
814 PkgName = DecParser.GetPackageName()
815 PkgGuid = DecParser.GetPackageGuid()
816 PkgVersion = DecParser.GetPackageVersion()
817 gPKG_INFO_DICT[Path] = (PkgName, PkgGuid, PkgVersion)
818 return PkgName, PkgGuid, PkgVersion
819 except FatalError:
820 return None, None, None
821
822
823 ## GetWorkspacePackage
824 #
825 # Get a list of workspace package information.
826 #
827 def GetWorkspacePackage():
828 DecFileList = []
829 WorkspaceDir = GlobalData.gWORKSPACE
830 PackageDir = GlobalData.gPACKAGE_PATH
831 for PkgRoot in [WorkspaceDir] + PackageDir:
832 for Root, Dirs, Files in os.walk(PkgRoot):
833 if 'CVS' in Dirs:
834 Dirs.remove('CVS')
835 if '.svn' in Dirs:
836 Dirs.remove('.svn')
837 for Dir in Dirs:
838 if Dir.startswith('.'):
839 Dirs.remove(Dir)
840 for FileSp in Files:
841 if FileSp.startswith('.'):
842 continue
843 Ext = os.path.splitext(FileSp)[1]
844 if Ext.lower() in ['.dec']:
845 DecFileList.append\
846 (os.path.normpath(os.path.join(Root, FileSp)))
847 #
848 # abstract package guid, version info from DecFile List
849 #
850 PkgList = []
851 for DecFile in DecFileList:
852 (PkgName, PkgGuid, PkgVersion) = GetPkgInfoFromDec(DecFile)
853 if PkgName and PkgGuid and PkgVersion:
854 PkgList.append((PkgName, PkgGuid, PkgVersion, DecFile))
855
856 return PkgList
857
858 ## GetWorkspaceModule
859 #
860 # Get a list of workspace modules.
861 #
862 def GetWorkspaceModule():
863 InfFileList = []
864 WorkspaceDir = GlobalData.gWORKSPACE
865 for Root, Dirs, Files in os.walk(WorkspaceDir):
866 if 'CVS' in Dirs:
867 Dirs.remove('CVS')
868 if '.svn' in Dirs:
869 Dirs.remove('.svn')
870 if 'Build' in Dirs:
871 Dirs.remove('Build')
872 for Dir in Dirs:
873 if Dir.startswith('.'):
874 Dirs.remove(Dir)
875 for FileSp in Files:
876 if FileSp.startswith('.'):
877 continue
878 Ext = os.path.splitext(FileSp)[1]
879 if Ext.lower() in ['.inf']:
880 InfFileList.append\
881 (os.path.normpath(os.path.join(Root, FileSp)))
882
883 return InfFileList
884
885 ## MacroParser used to parse macro definition
886 #
887 # @param Line: The content contain linestring and line number
888 # @param FileName: The meta-file file name
889 # @param SectionType: Section for the Line belong to
890 # @param FileLocalMacros: A list contain Macro defined in [Defines] section.
891 #
892 def MacroParser(Line, FileName, SectionType, FileLocalMacros):
893 MacroDefPattern = re.compile("^(DEFINE)[ \t]+")
894 LineContent = Line[0]
895 LineNo = Line[1]
896 Match = MacroDefPattern.match(LineContent)
897 if not Match:
898 #
899 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
900 #
901 return None, None
902
903 TokenList = GetSplitValueList(LineContent[Match.end(1):], \
904 DataType.TAB_EQUAL_SPLIT, 1)
905 #
906 # Syntax check
907 #
908 if not TokenList[0]:
909 Logger.Error('Parser', FORMAT_INVALID, ST.ERR_MACRONAME_NOGIVEN,
910 ExtraData=LineContent, File=FileName, Line=LineNo)
911 if len(TokenList) < 2:
912 Logger.Error('Parser', FORMAT_INVALID, ST.ERR_MACROVALUE_NOGIVEN,
913 ExtraData=LineContent, File=FileName, Line=LineNo)
914
915 Name, Value = TokenList
916
917 #
918 # DEFINE defined macros
919 #
920 if SectionType == DataType.MODEL_META_DATA_HEADER:
921 FileLocalMacros[Name] = Value
922
923 ReIsValidMacroName = re.compile(r"^[A-Z][A-Z0-9_]*$", re.DOTALL)
924 if ReIsValidMacroName.match(Name) is None:
925 Logger.Error('Parser',
926 FORMAT_INVALID,
927 ST.ERR_MACRONAME_INVALID % (Name),
928 ExtraData=LineContent,
929 File=FileName,
930 Line=LineNo)
931
932 # Validate MACRO Value
933 #
934 # <MacroDefinition> ::= [<Comments>]{0,}
935 # "DEFINE" <MACRO> "=" [{<PATH>} {<VALUE>}] <EOL>
936 # <Value> ::= {<NumVal>} {<Boolean>} {<AsciiString>} {<GUID>}
937 # {<CString>} {<UnicodeString>} {<CArray>}
938 #
939 # The definition of <NumVal>, <PATH>, <Boolean>, <GUID>, <CString>,
940 # <UnicodeString>, <CArray> are subset of <AsciiString>.
941 #
942 ReIsValidMacroValue = re.compile(r"^[\x20-\x7e]*$", re.DOTALL)
943 if ReIsValidMacroValue.match(Value) is None:
944 Logger.Error('Parser',
945 FORMAT_INVALID,
946 ST.ERR_MACROVALUE_INVALID % (Value),
947 ExtraData=LineContent,
948 File=FileName,
949 Line=LineNo)
950
951 return Name, Value
952
953 ## GenSection
954 #
955 # generate section contents
956 #
957 # @param SectionName: indicate the name of the section, details refer to
958 # INF, DEC specs
959 # @param SectionDict: section statement dict, key is SectionAttrs(arch,
960 # moduletype or platform may exist as needed) list
961 # seperated by space,
962 # value is statement
963 #
964 def GenSection(SectionName, SectionDict, SplitArch=True, NeedBlankLine=False):
965 Content = ''
966 for SectionAttrs in SectionDict:
967 StatementList = SectionDict[SectionAttrs]
968 if SectionAttrs and SectionName != 'Defines' and SectionAttrs.strip().upper() != DataType.TAB_ARCH_COMMON:
969 if SplitArch:
970 ArchList = GetSplitValueList(SectionAttrs, DataType.TAB_SPACE_SPLIT)
971 else:
972 if SectionName != 'UserExtensions':
973 ArchList = GetSplitValueList(SectionAttrs, DataType.TAB_COMMENT_SPLIT)
974 else:
975 ArchList = [SectionAttrs]
976 for Index in xrange(0, len(ArchList)):
977 ArchList[Index] = ConvertArchForInstall(ArchList[Index])
978 Section = '[' + SectionName + '.' + (', ' + SectionName + '.').join(ArchList) + ']'
979 else:
980 Section = '[' + SectionName + ']'
981 Content += '\n' + Section + '\n'
982 if StatementList is not None:
983 for Statement in StatementList:
984 LineList = Statement.split('\n')
985 NewStatement = ""
986 for Line in LineList:
987 # ignore blank comment
988 if not Line.replace("#", '').strip() and SectionName not in ('Defines', 'Hob', 'Event', 'BootMode'):
989 continue
990 # add two space before non-comments line except the comments in Defines section
991 if Line.strip().startswith('#') and SectionName == 'Defines':
992 NewStatement += "%s\n" % Line
993 continue
994 NewStatement += " %s\n" % Line
995 if NeedBlankLine:
996 Content += NewStatement + '\n'
997 else:
998 Content += NewStatement
999
1000 if NeedBlankLine:
1001 Content = Content[:-1]
1002 if not Content.replace('\\n', '').strip():
1003 return ''
1004 return Content
1005
1006 ## ConvertArchForInstall
1007 # if Arch.upper() is in "IA32", "X64", "IPF", and "EBC", it must be upper case. "common" must be lower case.
1008 # Anything else, the case must be preserved
1009 #
1010 # @param Arch: the arch string that need to be converted, it should be stripped before pass in
1011 # @return: the arch string that get converted
1012 #
1013 def ConvertArchForInstall(Arch):
1014 if Arch.upper() in [DataType.TAB_ARCH_IA32, DataType.TAB_ARCH_X64,
1015 DataType.TAB_ARCH_IPF, DataType.TAB_ARCH_EBC]:
1016 Arch = Arch.upper()
1017 elif Arch.upper() == DataType.TAB_ARCH_COMMON:
1018 Arch = Arch.lower()
1019
1020 return Arch