]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/UPT/Library/Parsing.py
BaseTools/Upt: Fix several bugs
[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 - 2014, 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.String import RaiseParserError
27 from Library.String import GetSplitValueList
28 from Library.String import CheckFileType
29 from Library.String import CheckFileExist
30 from Library.String import CleanString
31 from Library.String 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 != 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 == 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 for Root, Dirs, Files in os.walk(WorkspaceDir):
831 if 'CVS' in Dirs:
832 Dirs.remove('CVS')
833 if '.svn' in Dirs:
834 Dirs.remove('.svn')
835 for Dir in Dirs:
836 if Dir.startswith('.'):
837 Dirs.remove(Dir)
838 for FileSp in Files:
839 if FileSp.startswith('.'):
840 continue
841 Ext = os.path.splitext(FileSp)[1]
842 if Ext.lower() in ['.dec']:
843 DecFileList.append\
844 (os.path.normpath(os.path.join(Root, FileSp)))
845 #
846 # abstract package guid, version info from DecFile List
847 #
848 PkgList = []
849 for DecFile in DecFileList:
850 (PkgName, PkgGuid, PkgVersion) = GetPkgInfoFromDec(DecFile)
851 if PkgName and PkgGuid and PkgVersion:
852 PkgList.append((PkgName, PkgGuid, PkgVersion, DecFile))
853
854 return PkgList
855
856 ## GetWorkspaceModule
857 #
858 # Get a list of workspace modules.
859 #
860 def GetWorkspaceModule():
861 InfFileList = []
862 WorkspaceDir = GlobalData.gWORKSPACE
863 for Root, Dirs, Files in os.walk(WorkspaceDir):
864 if 'CVS' in Dirs:
865 Dirs.remove('CVS')
866 if '.svn' in Dirs:
867 Dirs.remove('.svn')
868 if 'Build' in Dirs:
869 Dirs.remove('Build')
870 for Dir in Dirs:
871 if Dir.startswith('.'):
872 Dirs.remove(Dir)
873 for FileSp in Files:
874 if FileSp.startswith('.'):
875 continue
876 Ext = os.path.splitext(FileSp)[1]
877 if Ext.lower() in ['.inf']:
878 InfFileList.append\
879 (os.path.normpath(os.path.join(Root, FileSp)))
880
881 return InfFileList
882
883 ## MacroParser used to parse macro definition
884 #
885 # @param Line: The content contain linestring and line number
886 # @param FileName: The meta-file file name
887 # @param SectionType: Section for the Line belong to
888 # @param FileLocalMacros: A list contain Macro defined in [Defines] section.
889 #
890 def MacroParser(Line, FileName, SectionType, FileLocalMacros):
891 MacroDefPattern = re.compile("^(DEFINE)[ \t]+")
892 LineContent = Line[0]
893 LineNo = Line[1]
894 Match = MacroDefPattern.match(LineContent)
895 if not Match:
896 #
897 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
898 #
899 return None, None
900
901 TokenList = GetSplitValueList(LineContent[Match.end(1):], \
902 DataType.TAB_EQUAL_SPLIT, 1)
903 #
904 # Syntax check
905 #
906 if not TokenList[0]:
907 Logger.Error('Parser', FORMAT_INVALID, ST.ERR_MACRONAME_NOGIVEN,
908 ExtraData=LineContent, File=FileName, Line=LineNo)
909 if len(TokenList) < 2:
910 Logger.Error('Parser', FORMAT_INVALID, ST.ERR_MACROVALUE_NOGIVEN,
911 ExtraData=LineContent, File=FileName, Line=LineNo)
912
913 Name, Value = TokenList
914
915 #
916 # DEFINE defined macros
917 #
918 if SectionType == DataType.MODEL_META_DATA_HEADER:
919 FileLocalMacros[Name] = Value
920
921 ReIsValidMacroName = re.compile(r"^[A-Z][A-Z0-9_]*$", re.DOTALL)
922 if ReIsValidMacroName.match(Name) == None:
923 Logger.Error('Parser',
924 FORMAT_INVALID,
925 ST.ERR_MACRONAME_INVALID % (Name),
926 ExtraData=LineContent,
927 File=FileName,
928 Line=LineNo)
929
930 # Validate MACRO Value
931 #
932 # <MacroDefinition> ::= [<Comments>]{0,}
933 # "DEFINE" <MACRO> "=" [{<PATH>} {<VALUE>}] <EOL>
934 # <Value> ::= {<NumVal>} {<Boolean>} {<AsciiString>} {<GUID>}
935 # {<CString>} {<UnicodeString>} {<CArray>}
936 #
937 # The definition of <NumVal>, <PATH>, <Boolean>, <GUID>, <CString>,
938 # <UnicodeString>, <CArray> are subset of <AsciiString>.
939 #
940 ReIsValidMacroValue = re.compile(r"^[\x20-\x7e]*$", re.DOTALL)
941 if ReIsValidMacroValue.match(Value) == None:
942 Logger.Error('Parser',
943 FORMAT_INVALID,
944 ST.ERR_MACROVALUE_INVALID % (Value),
945 ExtraData=LineContent,
946 File=FileName,
947 Line=LineNo)
948
949 return Name, Value
950
951 ## GenSection
952 #
953 # generate section contents
954 #
955 # @param SectionName: indicate the name of the section, details refer to
956 # INF, DEC specs
957 # @param SectionDict: section statement dict, key is SectionAttrs(arch,
958 # moduletype or platform may exist as needed) list
959 # seperated by space,
960 # value is statement
961 #
962 def GenSection(SectionName, SectionDict, SplitArch=True, NeedBlankLine=False):
963 Content = ''
964 for SectionAttrs in SectionDict:
965 StatementList = SectionDict[SectionAttrs]
966 if SectionAttrs and SectionName != 'Defines' and SectionAttrs.strip().upper() != DataType.TAB_ARCH_COMMON:
967 if SplitArch:
968 ArchList = GetSplitValueList(SectionAttrs, DataType.TAB_SPACE_SPLIT)
969 else:
970 if SectionName != 'UserExtensions':
971 ArchList = GetSplitValueList(SectionAttrs, DataType.TAB_COMMENT_SPLIT)
972 else:
973 ArchList = [SectionAttrs]
974 for Index in xrange(0, len(ArchList)):
975 ArchList[Index] = ConvertArchForInstall(ArchList[Index])
976 Section = '[' + SectionName + '.' + (', ' + SectionName + '.').join(ArchList) + ']'
977 else:
978 Section = '[' + SectionName + ']'
979 Content += '\n' + Section + '\n'
980 if StatementList != None:
981 for Statement in StatementList:
982 LineList = Statement.split('\n')
983 NewStatement = ""
984 for Line in LineList:
985 # ignore blank comment
986 if not Line.replace("#", '').strip() and SectionName not in ('Defines', 'Hob', 'Event', 'BootMode'):
987 continue
988 # add two space before non-comments line except the comments in Defines section
989 if Line.strip().startswith('#') and SectionName == 'Defines':
990 NewStatement += "%s\n" % Line
991 continue
992 NewStatement += " %s\n" % Line
993 if NeedBlankLine:
994 Content += NewStatement + '\n'
995 else:
996 Content += NewStatement
997
998 if NeedBlankLine:
999 Content = Content[:-1]
1000 if not Content.replace('\\n', '').strip():
1001 return ''
1002 return Content
1003
1004 ## ConvertArchForInstall
1005 # if Arch.upper() is in "IA32", "X64", "IPF", and "EBC", it must be upper case. "common" must be lower case.
1006 # Anything else, the case must be preserved
1007 #
1008 # @param Arch: the arch string that need to be converted, it should be stripped before pass in
1009 # @return: the arch string that get converted
1010 #
1011 def ConvertArchForInstall(Arch):
1012 if Arch.upper() in [DataType.TAB_ARCH_IA32, DataType.TAB_ARCH_X64,
1013 DataType.TAB_ARCH_IPF, DataType.TAB_ARCH_EBC]:
1014 Arch = Arch.upper()
1015 elif Arch.upper() == DataType.TAB_ARCH_COMMON:
1016 Arch = Arch.lower()
1017
1018 return Arch