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