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