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