]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/UPT/Parser/DecParser.py
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / BaseTools / Source / Python / UPT / Parser / DecParser.py
CommitLineData
4234283c
LG
1## @file\r
2# This file is used to parse DEC file. It will consumed by DecParser\r
3#\r
64285f15 4# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
4234283c 5#\r
2e351cbe 6# SPDX-License-Identifier: BSD-2-Clause-Patent\r
4234283c
LG
7'''\r
8DecParser\r
9'''\r
10## Import modules\r
11#\r
12import Logger.Log as Logger\r
13from Logger.ToolError import FILE_PARSE_FAILURE\r
14from Logger.ToolError import FILE_OPEN_FAILURE\r
15from Logger import StringTable as ST\r
2bc3256c 16from Logger.ToolError import FORMAT_INVALID\r
4234283c
LG
17\r
18import Library.DataType as DT\r
19from Library.ParserValidate import IsValidToken\r
20from Library.ParserValidate import IsValidPath\r
21from Library.ParserValidate import IsValidCFormatGuid\r
22from Library.ParserValidate import IsValidIdString\r
23from Library.ParserValidate import IsValidUserId\r
24from Library.ParserValidate import IsValidArch\r
25from Library.ParserValidate import IsValidWord\r
48b77f5e 26from Library.ParserValidate import IsValidDecVersionVal\r
4234283c
LG
27from Parser.DecParserMisc import TOOL_NAME\r
28from Parser.DecParserMisc import CleanString\r
29from Parser.DecParserMisc import IsValidPcdDatum\r
30from Parser.DecParserMisc import ParserHelper\r
31from Parser.DecParserMisc import StripRoot\r
32from Parser.DecParserMisc import VERSION_PATTERN\r
33from Parser.DecParserMisc import CVAR_PATTERN\r
34from Parser.DecParserMisc import PCD_TOKEN_PATTERN\r
35from Parser.DecParserMisc import MACRO_PATTERN\r
36from Parser.DecParserMisc import FileContent\r
37from Object.Parser.DecObject import _DecComments\r
38from Object.Parser.DecObject import DecDefineObject\r
39from Object.Parser.DecObject import DecDefineItemObject\r
40from Object.Parser.DecObject import DecIncludeObject\r
41from Object.Parser.DecObject import DecIncludeItemObject\r
42from Object.Parser.DecObject import DecLibraryclassObject\r
43from Object.Parser.DecObject import DecLibraryclassItemObject\r
44from Object.Parser.DecObject import DecGuidObject\r
45from Object.Parser.DecObject import DecPpiObject\r
46from Object.Parser.DecObject import DecProtocolObject\r
47from Object.Parser.DecObject import DecGuidItemObject\r
48from Object.Parser.DecObject import DecUserExtensionObject\r
49from Object.Parser.DecObject import DecUserExtensionItemObject\r
50from Object.Parser.DecObject import DecPcdObject\r
51from Object.Parser.DecObject import DecPcdItemObject\r
52from Library.Misc import GuidStructureStringToGuidString\r
53from Library.Misc import CheckGuidRegFormat\r
64285f15
YZ
54from Library.StringUtils import ReplaceMacro\r
55from Library.StringUtils import GetSplitValueList\r
56from Library.StringUtils import gMACRO_PATTERN\r
57from Library.StringUtils import ConvertSpecialChar\r
421ccda3 58from Library.CommentParsing import ParsePcdErrorCode\r
4234283c
LG
59\r
60##\r
61# _DecBase class for parsing\r
62#\r
63class _DecBase:\r
64 def __init__(self, RawData):\r
65 self._RawData = RawData\r
66 self._ItemDict = {}\r
67 self._LocalMacro = {}\r
68 #\r
69 # Data parsed by 'self' are saved to this object\r
70 #\r
71 self.ItemObject = None\r
f7496d71 72\r
4234283c
LG
73 def GetDataObject(self):\r
74 return self.ItemObject\r
f7496d71 75\r
421ccda3
HC
76 def GetLocalMacro(self):\r
77 return self._LocalMacro\r
f7496d71 78\r
4234283c
LG
79 ## BlockStart\r
80 #\r
81 # Called if a new section starts\r
82 #\r
83 def BlockStart(self):\r
84 self._LocalMacro = {}\r
f7496d71 85\r
4234283c
LG
86 ## _CheckReDefine\r
87 #\r
88 # @param Key: to be checked if multi-defined\r
f7496d71 89 # @param Scope: Format: [[SectionName, Arch], ...].\r
4234283c
LG
90 # If scope is none, use global scope\r
91 #\r
92 def _CheckReDefine(self, Key, Scope = None):\r
93 if not Scope:\r
94 Scope = self._RawData.CurrentScope\r
95 return\r
f7496d71 96\r
4234283c
LG
97 SecArch = []\r
98 #\r
99 # Copy scope to SecArch, avoid Scope be changed outside\r
100 #\r
101 SecArch[0:1] = Scope[:]\r
102 if Key not in self._ItemDict:\r
103 self._ItemDict[Key] = [[SecArch, self._RawData.LineIndex]]\r
104 return\r
f7496d71 105\r
4234283c
LG
106 for Value in self._ItemDict[Key]:\r
107 for SubValue in Scope:\r
108 #\r
109 # If current is common section\r
110 #\r
111 if SubValue[-1] == 'COMMON':\r
112 for Other in Value[0]:\r
113 # Key in common cannot be redefined in other arches\r
114 # [:-1] means stripping arch info\r
115 if Other[:-1] == SubValue[:-1]:\r
116 self._LoggerError(ST.ERR_DECPARSE_REDEFINE % (Key, Value[1]))\r
117 return\r
118 continue\r
119 CommonScope = []\r
120 CommonScope[0:1] = SubValue\r
121 CommonScope[-1] = 'COMMON'\r
122 #\r
123 # Cannot be redefined if this key already defined in COMMON Or defined in same arch\r
124 #\r
125 if SubValue in Value[0] or CommonScope in Value[0]:\r
126 self._LoggerError(ST.ERR_DECPARSE_REDEFINE % (Key, Value[1]))\r
127 return\r
128 self._ItemDict[Key].append([SecArch, self._RawData.LineIndex])\r
f7496d71 129\r
4234283c
LG
130 ## CheckRequiredFields\r
131 # Some sections need to check if some fields exist, define section for example\r
132 # Derived class can re-implement, top parser will call this function after all parsing done\r
f7496d71 133 #\r
4234283c
LG
134 def CheckRequiredFields(self):\r
135 if self._RawData:\r
136 pass\r
137 return True\r
f7496d71 138\r
4234283c 139 ## IsItemRequired\r
f7496d71 140 # In DEC spec, sections must have at least one statement except user\r
4234283c
LG
141 # extension.\r
142 # For example: "[guids" [<attribs>] "]" <EOL> <statements>+\r
143 # sub class can override this method to indicate if statement is a must.\r
144 #\r
145 def _IsStatementRequired(self):\r
146 if self._RawData:\r
147 pass\r
148 return False\r
f7496d71 149\r
4234283c 150 def _LoggerError(self, ErrorString):\r
f7496d71 151 Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename,\r
4234283c
LG
152 Line = self._RawData.LineIndex,\r
153 ExtraData=ErrorString + ST.ERR_DECPARSE_LINE % self._RawData.CurrentLine)\r
f7496d71 154\r
4234283c
LG
155 def _ReplaceMacro(self, String):\r
156 if gMACRO_PATTERN.findall(String):\r
157 String = ReplaceMacro(String, self._LocalMacro, False,\r
158 FileName = self._RawData.Filename,\r
159 Line = ['', self._RawData.LineIndex])\r
160 String = ReplaceMacro(String, self._RawData.Macros, False,\r
161 FileName = self._RawData.Filename,\r
162 Line = ['', self._RawData.LineIndex])\r
163 MacroUsed = gMACRO_PATTERN.findall(String)\r
164 if MacroUsed:\r
165 Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE,\r
f7496d71 166 File=self._RawData.Filename,\r
4234283c
LG
167 Line = self._RawData.LineIndex,\r
168 ExtraData = ST.ERR_DECPARSE_MACRO_RESOLVE % (str(MacroUsed), String))\r
169 return String\r
f7496d71 170\r
4234283c
LG
171 def _MacroParser(self, String):\r
172 TokenList = GetSplitValueList(String, ' ', 1)\r
173 if len(TokenList) < 2 or TokenList[1] == '':\r
174 self._LoggerError(ST.ERR_DECPARSE_MACRO_PAIR)\r
175\r
176 TokenList = GetSplitValueList(TokenList[1], DT.TAB_EQUAL_SPLIT, 1)\r
177 if TokenList[0] == '':\r
178 self._LoggerError(ST.ERR_DECPARSE_MACRO_NAME)\r
179 elif not IsValidToken(MACRO_PATTERN, TokenList[0]):\r
180 self._LoggerError(ST.ERR_DECPARSE_MACRO_NAME_UPPER % TokenList[0])\r
f7496d71 181\r
4234283c
LG
182 if len(TokenList) == 1:\r
183 self._LocalMacro[TokenList[0]] = ''\r
184 else:\r
185 self._LocalMacro[TokenList[0]] = self._ReplaceMacro(TokenList[1])\r
421ccda3 186\r
4234283c
LG
187 ## _ParseItem\r
188 #\r
189 # Parse specified item, this function must be derived by subclass\r
190 #\r
191 def _ParseItem(self):\r
192 if self._RawData:\r
193 pass\r
194 #\r
195 # Should never be called\r
196 #\r
197 return None\r
198\r
f7496d71 199\r
4234283c
LG
200 ## _TailCommentStrategy\r
201 #\r
202 # This function can be derived to parse tail comment\r
203 # default is it will not consume any lines\r
204 #\r
205 # @param Comment: Comment of current line\r
206 #\r
207 def _TailCommentStrategy(self, Comment):\r
208 if Comment:\r
209 pass\r
210 if self._RawData:\r
211 pass\r
212 return False\r
f7496d71 213\r
4234283c
LG
214 ## _StopCurrentParsing\r
215 #\r
216 # Called in Parse if current parsing should be stopped when encounter some\r
217 # keyword\r
218 # Default is section start and end\r
219 #\r
220 # @param Line: Current line\r
221 #\r
222 def _StopCurrentParsing(self, Line):\r
223 if self._RawData:\r
224 pass\r
225 return Line[0] == DT.TAB_SECTION_START and Line[-1] == DT.TAB_SECTION_END\r
f7496d71 226\r
4234283c
LG
227 ## _TryBackSlash\r
228 #\r
229 # Split comment and DEC content, concatenate lines if end of char is '\'\r
230 #\r
231 # @param ProcessedLine: ProcessedLine line\r
232 # @param ProcessedComments: ProcessedComments line\r
233 #\r
234 def _TryBackSlash(self, ProcessedLine, ProcessedComments):\r
235 CatLine = ''\r
236 Comment = ''\r
237 Line = ProcessedLine\r
238 CommentList = ProcessedComments\r
239 while not self._RawData.IsEndOfFile():\r
240 if Line == '':\r
241 self._LoggerError(ST.ERR_DECPARSE_BACKSLASH_EMPTY)\r
242 break\r
f7496d71 243\r
4234283c
LG
244 if Comment:\r
245 CommentList.append((Comment, self._RawData.LineIndex))\r
246 if Line[-1] != DT.TAB_SLASH:\r
247 CatLine += Line\r
248 break\r
249 elif len(Line) < 2 or Line[-2] != ' ':\r
250 self._LoggerError(ST.ERR_DECPARSE_BACKSLASH)\r
251 else:\r
252 CatLine += Line[:-1]\r
253 Line, Comment = CleanString(self._RawData.GetNextLine())\r
254 #\r
255 # Reach end of content\r
256 #\r
257 if self._RawData.IsEndOfFile():\r
258 if not CatLine:\r
259 if ProcessedLine[-1] == DT.TAB_SLASH:\r
260 self._LoggerError(ST.ERR_DECPARSE_BACKSLASH_EMPTY)\r
261 CatLine = ProcessedLine\r
262 else:\r
263 if not Line or Line[-1] == DT.TAB_SLASH:\r
264 self._LoggerError(ST.ERR_DECPARSE_BACKSLASH_EMPTY)\r
265 CatLine += Line\r
f7496d71 266\r
0e025dea
HC
267 #\r
268 # All MACRO values defined by the DEFINE statements in any section\r
269 # (except [Userextensions] sections for Intel) of the INF or DEC file\r
270 # must be expanded before processing of the file.\r
271 #\r
272 __IsReplaceMacro = True\r
273 Header = self._RawData.CurrentScope[0] if self._RawData.CurrentScope else None\r
274 if Header and len(Header) > 2:\r
275 if Header[0].upper() == 'USEREXTENSIONS' and not (Header[1] == 'TianoCore' and Header[2] == '"ExtraFiles"'):\r
276 __IsReplaceMacro = False\r
277 if __IsReplaceMacro:\r
278 self._RawData.CurrentLine = self._ReplaceMacro(CatLine)\r
279 else:\r
280 self._RawData.CurrentLine = CatLine\r
281\r
4234283c 282 return CatLine, CommentList\r
f7496d71 283\r
4234283c 284 ## Parse\r
f7496d71
LG
285 # This is a template method in which other member functions which might\r
286 # override by sub class are called. It is responsible for reading file\r
4234283c
LG
287 # line by line, and call other member functions to parse. This function\r
288 # should not be re-implement by sub class.\r
289 #\r
290 def Parse(self):\r
291 HeadComments = []\r
292 TailComments = []\r
f7496d71 293\r
4234283c
LG
294 #======================================================================\r
295 # CurComments may pointer to HeadComments or TailComments\r
296 #======================================================================\r
297 CurComments = HeadComments\r
298 CurObj = None\r
299 ItemNum = 0\r
300 FromBuf = False\r
f7496d71 301\r
4234283c
LG
302 #======================================================================\r
303 # Used to report error information if empty section found\r
304 #======================================================================\r
305 Index = self._RawData.LineIndex\r
306 LineStr = self._RawData.CurrentLine\r
307 while not self._RawData.IsEndOfFile() or self._RawData.NextLine:\r
308 if self._RawData.NextLine:\r
309 #==============================================================\r
310 # Have processed line in buffer\r
311 #==============================================================\r
312 Line = self._RawData.NextLine\r
313 HeadComments.extend(self._RawData.HeadComment)\r
314 TailComments.extend(self._RawData.TailComment)\r
315 self._RawData.ResetNext()\r
316 Comment = ''\r
317 FromBuf = True\r
318 else:\r
319 #==============================================================\r
320 # No line in buffer, read next line\r
321 #==============================================================\r
322 Line, Comment = CleanString(self._RawData.GetNextLine())\r
323 FromBuf = False\r
324 if Line:\r
325 if not FromBuf and CurObj and TailComments:\r
326 #==========================================================\r
327 # Set tail comments to previous statement if not empty.\r
328 #==========================================================\r
329 CurObj.SetTailComment(CurObj.GetTailComment()+TailComments)\r
f7496d71 330\r
4234283c
LG
331 if not FromBuf:\r
332 del TailComments[:]\r
333 CurComments = TailComments\r
334 Comments = []\r
335 if Comment:\r
336 Comments = [(Comment, self._RawData.LineIndex)]\r
f7496d71 337\r
4234283c
LG
338 #==============================================================\r
339 # Try if last char of line has backslash\r
340 #==============================================================\r
341 Line, Comments = self._TryBackSlash(Line, Comments)\r
342 CurComments.extend(Comments)\r
f7496d71 343\r
4234283c
LG
344 #==============================================================\r
345 # Macro found\r
346 #==============================================================\r
347 if Line.startswith('DEFINE '):\r
348 self._MacroParser(Line)\r
349 del HeadComments[:]\r
350 del TailComments[:]\r
351 CurComments = HeadComments\r
352 continue\r
f7496d71 353\r
4234283c
LG
354 if self._StopCurrentParsing(Line):\r
355 #==========================================================\r
356 # This line does not belong to this parse,\r
357 # Save it, can be used by next parse\r
358 #==========================================================\r
359 self._RawData.SetNext(Line, HeadComments, TailComments)\r
360 break\r
f7496d71 361\r
4234283c
LG
362 Obj = self._ParseItem()\r
363 ItemNum += 1\r
364 if Obj:\r
365 Obj.SetHeadComment(Obj.GetHeadComment()+HeadComments)\r
366 Obj.SetTailComment(Obj.GetTailComment()+TailComments)\r
367 del HeadComments[:]\r
368 del TailComments[:]\r
369 CurObj = Obj\r
370 else:\r
371 CurObj = None\r
372 else:\r
373 if id(CurComments) == id(TailComments):\r
374 #==========================================================\r
375 # Check if this comment belongs to tail comment\r
376 #==========================================================\r
377 if not self._TailCommentStrategy(Comment):\r
378 CurComments = HeadComments\r
379\r
380 if Comment:\r
381 CurComments.append(((Comment, self._RawData.LineIndex)))\r
382 else:\r
383 del CurComments[:]\r
f7496d71 384\r
4234283c
LG
385 if self._IsStatementRequired() and ItemNum == 0:\r
386 Logger.Error(\r
387 TOOL_NAME, FILE_PARSE_FAILURE,\r
388 File=self._RawData.Filename,\r
389 Line=Index,\r
390 ExtraData=ST.ERR_DECPARSE_STATEMENT_EMPTY % LineStr\r
391 )\r
392\r
393## _DecDefine\r
394# Parse define section\r
395#\r
396class _DecDefine(_DecBase):\r
397 def __init__(self, RawData):\r
398 _DecBase.__init__(self, RawData)\r
399 self.ItemObject = DecDefineObject(RawData.Filename)\r
400 self._LocalMacro = self._RawData.Macros\r
401 self._DefSecNum = 0\r
f7496d71 402\r
4234283c
LG
403 #\r
404 # Each field has a function to validate\r
405 #\r
406 self.DefineValidation = {\r
407 DT.TAB_DEC_DEFINES_DEC_SPECIFICATION : self._SetDecSpecification,\r
408 DT.TAB_DEC_DEFINES_PACKAGE_NAME : self._SetPackageName,\r
409 DT.TAB_DEC_DEFINES_PACKAGE_GUID : self._SetPackageGuid,\r
410 DT.TAB_DEC_DEFINES_PACKAGE_VERSION : self._SetPackageVersion,\r
421ccda3 411 DT.TAB_DEC_DEFINES_PKG_UNI_FILE : self._SetPackageUni,\r
4234283c 412 }\r
f7496d71 413\r
4234283c
LG
414 def BlockStart(self):\r
415 self._DefSecNum += 1\r
416 if self._DefSecNum > 1:\r
417 self._LoggerError(ST.ERR_DECPARSE_DEFINE_MULTISEC)\r
f7496d71 418\r
4234283c
LG
419 ## CheckRequiredFields\r
420 #\r
421 # Check required fields: DEC_SPECIFICATION, PACKAGE_NAME\r
422 # PACKAGE_GUID, PACKAGE_VERSION\r
423 #\r
424 def CheckRequiredFields(self):\r
425 Ret = False\r
426 if self.ItemObject.GetPackageSpecification() == '':\r
f7496d71 427 Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename,\r
4234283c
LG
428 ExtraData=ST.ERR_DECPARSE_DEFINE_REQUIRED % DT.TAB_DEC_DEFINES_DEC_SPECIFICATION)\r
429 elif self.ItemObject.GetPackageName() == '':\r
f7496d71 430 Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename,\r
4234283c
LG
431 ExtraData=ST.ERR_DECPARSE_DEFINE_REQUIRED % DT.TAB_DEC_DEFINES_PACKAGE_NAME)\r
432 elif self.ItemObject.GetPackageGuid() == '':\r
f7496d71 433 Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename,\r
4234283c
LG
434 ExtraData=ST.ERR_DECPARSE_DEFINE_REQUIRED % DT.TAB_DEC_DEFINES_PACKAGE_GUID)\r
435 elif self.ItemObject.GetPackageVersion() == '':\r
f7496d71 436 Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename,\r
4234283c
LG
437 ExtraData=ST.ERR_DECPARSE_DEFINE_REQUIRED % DT.TAB_DEC_DEFINES_PACKAGE_VERSION)\r
438 else:\r
439 Ret = True\r
440 return Ret\r
f7496d71 441\r
4234283c
LG
442 def _ParseItem(self):\r
443 Line = self._RawData.CurrentLine\r
444 TokenList = GetSplitValueList(Line, DT.TAB_EQUAL_SPLIT, 1)\r
445 if TokenList[0] == DT.TAB_DEC_DEFINES_PKG_UNI_FILE:\r
421ccda3 446 self.DefineValidation[TokenList[0]](TokenList[1])\r
4234283c
LG
447 elif len(TokenList) < 2:\r
448 self._LoggerError(ST.ERR_DECPARSE_DEFINE_FORMAT)\r
449 elif TokenList[0] not in self.DefineValidation:\r
450 self._LoggerError(ST.ERR_DECPARSE_DEFINE_UNKNOWKEY % TokenList[0])\r
451 else:\r
452 self.DefineValidation[TokenList[0]](TokenList[1])\r
f7496d71 453\r
4234283c 454 DefineItem = DecDefineItemObject()\r
421ccda3
HC
455 DefineItem.Key = TokenList[0]\r
456 DefineItem.Value = TokenList[1]\r
457 self.ItemObject.AddItem(DefineItem, self._RawData.CurrentScope)\r
4234283c 458 return DefineItem\r
f7496d71 459\r
4234283c
LG
460 def _SetDecSpecification(self, Token):\r
461 if self.ItemObject.GetPackageSpecification():\r
462 self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_DEC_SPECIFICATION)\r
463 if not IsValidToken('0[xX][0-9a-fA-F]{8}', Token):\r
48b77f5e
HC
464 if not IsValidDecVersionVal(Token):\r
465 self._LoggerError(ST.ERR_DECPARSE_DEFINE_SPEC)\r
4234283c 466 self.ItemObject.SetPackageSpecification(Token)\r
f7496d71 467\r
4234283c
LG
468 def _SetPackageName(self, Token):\r
469 if self.ItemObject.GetPackageName():\r
470 self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_PACKAGE_NAME)\r
471 if not IsValidWord(Token):\r
472 self._LoggerError(ST.ERR_DECPARSE_DEFINE_PKGNAME)\r
473 self.ItemObject.SetPackageName(Token)\r
f7496d71 474\r
4234283c
LG
475 def _SetPackageGuid(self, Token):\r
476 if self.ItemObject.GetPackageGuid():\r
477 self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_PACKAGE_GUID)\r
478 if not CheckGuidRegFormat(Token):\r
479 self._LoggerError(ST.ERR_DECPARSE_DEFINE_PKGGUID)\r
480 self.ItemObject.SetPackageGuid(Token)\r
f7496d71 481\r
4234283c
LG
482 def _SetPackageVersion(self, Token):\r
483 if self.ItemObject.GetPackageVersion():\r
484 self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_PACKAGE_VERSION)\r
485 if not IsValidToken(VERSION_PATTERN, Token):\r
486 self._LoggerError(ST.ERR_DECPARSE_DEFINE_PKGVERSION)\r
487 else:\r
488 if not DT.TAB_SPLIT in Token:\r
489 Token = Token + '.0'\r
421ccda3 490 self.ItemObject.SetPackageVersion(Token)\r
f7496d71 491\r
421ccda3
HC
492 def _SetPackageUni(self, Token):\r
493 if self.ItemObject.GetPackageUniFile():\r
494 self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_PKG_UNI_FILE)\r
495 self.ItemObject.SetPackageUniFile(Token)\r
4234283c
LG
496\r
497## _DecInclude\r
498#\r
499# Parse include section\r
500#\r
501class _DecInclude(_DecBase):\r
502 def __init__(self, RawData):\r
503 _DecBase.__init__(self, RawData)\r
504 self.ItemObject = DecIncludeObject(RawData.Filename)\r
f7496d71 505\r
4234283c
LG
506 def _ParseItem(self):\r
507 Line = self._RawData.CurrentLine\r
f7496d71 508\r
4234283c 509 if not IsValidPath(Line, self._RawData.PackagePath):\r
f7496d71
LG
510 self._LoggerError(ST.ERR_DECPARSE_INCLUDE % Line)\r
511\r
4234283c
LG
512 Item = DecIncludeItemObject(StripRoot(self._RawData.PackagePath, Line), self._RawData.PackagePath)\r
513 self.ItemObject.AddItem(Item, self._RawData.CurrentScope)\r
514 return Item\r
515\r
516## _DecLibraryclass\r
517#\r
518# Parse library class section\r
519#\r
520class _DecLibraryclass(_DecBase):\r
521 def __init__(self, RawData):\r
522 _DecBase.__init__(self, RawData)\r
523 self.ItemObject = DecLibraryclassObject(RawData.Filename)\r
f7496d71 524\r
4234283c
LG
525 def _ParseItem(self):\r
526 Line = self._RawData.CurrentLine\r
527 TokenList = GetSplitValueList(Line, DT.TAB_VALUE_SPLIT)\r
528 if len(TokenList) != 2:\r
f7496d71 529 self._LoggerError(ST.ERR_DECPARSE_LIBCLASS_SPLIT)\r
4234283c
LG
530 if TokenList[0] == '' or TokenList[1] == '':\r
531 self._LoggerError(ST.ERR_DECPARSE_LIBCLASS_EMPTY)\r
532 if not IsValidToken('[A-Z][0-9A-Za-z]*', TokenList[0]):\r
533 self._LoggerError(ST.ERR_DECPARSE_LIBCLASS_LIB)\r
f7496d71 534\r
4234283c 535 self._CheckReDefine(TokenList[0])\r
f7496d71 536\r
4234283c
LG
537 Value = TokenList[1]\r
538 #\r
539 # Must end with .h\r
540 #\r
541 if not Value.endswith('.h'):\r
542 self._LoggerError(ST.ERR_DECPARSE_LIBCLASS_PATH_EXT)\r
f7496d71 543\r
4234283c
LG
544 #\r
545 # Path must be existed\r
546 #\r
547 if not IsValidPath(Value, self._RawData.PackagePath):\r
548 self._LoggerError(ST.ERR_DECPARSE_INCLUDE % Value)\r
f7496d71 549\r
4234283c
LG
550 Item = DecLibraryclassItemObject(TokenList[0], StripRoot(self._RawData.PackagePath, Value),\r
551 self._RawData.PackagePath)\r
552 self.ItemObject.AddItem(Item, self._RawData.CurrentScope)\r
553 return Item\r
554\r
555## _DecPcd\r
556#\r
557# Parse PCD section\r
558#\r
559class _DecPcd(_DecBase):\r
560 def __init__(self, RawData):\r
561 _DecBase.__init__(self, RawData)\r
562 self.ItemObject = DecPcdObject(RawData.Filename)\r
563 #\r
564 # Used to check duplicate token\r
565 # Key is token space and token number (integer), value is C name\r
566 #\r
567 self.TokenMap = {}\r
f7496d71 568\r
4234283c
LG
569 def _ParseItem(self):\r
570 Line = self._RawData.CurrentLine\r
571 TokenList = Line.split(DT.TAB_VALUE_SPLIT)\r
572 if len(TokenList) < 4:\r
573 self._LoggerError(ST.ERR_DECPARSE_PCD_SPLIT)\r
f7496d71 574\r
4234283c
LG
575 #\r
576 # Token space guid C name\r
577 #\r
578 PcdName = GetSplitValueList(TokenList[0], DT.TAB_SPLIT)\r
579 if len(PcdName) != 2 or PcdName[0] == '' or PcdName[1] == '':\r
580 self._LoggerError(ST.ERR_DECPARSE_PCD_NAME)\r
f7496d71 581\r
4234283c
LG
582 Guid = PcdName[0]\r
583 if not IsValidToken(CVAR_PATTERN, Guid):\r
584 self._LoggerError(ST.ERR_DECPARSE_PCD_CVAR_GUID)\r
f7496d71 585\r
4234283c
LG
586 #\r
587 # PCD C name\r
588 #\r
589 CName = PcdName[1]\r
590 if not IsValidToken(CVAR_PATTERN, CName):\r
591 self._LoggerError(ST.ERR_DECPARSE_PCD_CVAR_PCDCNAME)\r
f7496d71 592\r
4234283c 593 self._CheckReDefine(Guid + DT.TAB_SPLIT + CName)\r
f7496d71 594\r
4234283c
LG
595 #\r
596 # Default value, may be C array, string or number\r
597 #\r
598 Data = DT.TAB_VALUE_SPLIT.join(TokenList[1:-2]).strip()\r
f7496d71 599\r
4234283c
LG
600 #\r
601 # PCD data type\r
602 #\r
603 DataType = TokenList[-2].strip()\r
604 Valid, Cause = IsValidPcdDatum(DataType, Data)\r
605 if not Valid:\r
606 self._LoggerError(Cause)\r
607 PcdType = self._RawData.CurrentScope[0][0]\r
608 if PcdType == DT.TAB_PCDS_FEATURE_FLAG_NULL.upper() and DataType != 'BOOLEAN':\r
609 self._LoggerError(ST.ERR_DECPARSE_PCD_FEATUREFLAG)\r
610 #\r
611 # Token value is the last element in list.\r
612 #\r
613 Token = TokenList[-1].strip()\r
614 if not IsValidToken(PCD_TOKEN_PATTERN, Token):\r
615 self._LoggerError(ST.ERR_DECPARSE_PCD_TOKEN % Token)\r
616 elif not Token.startswith('0x') and not Token.startswith('0X'):\r
af881abc 617 if int(Token) > 4294967295:\r
4234283c 618 self._LoggerError(ST.ERR_DECPARSE_PCD_TOKEN_INT % Token)\r
174a9d3c 619 Token = '0x%x' % int(Token)\r
f7496d71 620\r
af881abc 621 IntToken = int(Token, 0)\r
4234283c
LG
622 if (Guid, IntToken) in self.TokenMap:\r
623 if self.TokenMap[Guid, IntToken] != CName:\r
624 self._LoggerError(ST.ERR_DECPARSE_PCD_TOKEN_UNIQUE%(Token))\r
625 else:\r
626 self.TokenMap[Guid, IntToken] = CName\r
f7496d71 627\r
4234283c
LG
628 Item = DecPcdItemObject(Guid, CName, Data, DataType, Token)\r
629 self.ItemObject.AddItem(Item, self._RawData.CurrentScope)\r
630 return Item\r
f7496d71 631\r
4234283c
LG
632## _DecGuid\r
633#\r
634# Parse GUID, PPI, Protocol section\r
635#\r
636class _DecGuid(_DecBase):\r
637 def __init__(self, RawData):\r
638 _DecBase.__init__(self, RawData)\r
639 self.GuidObj = DecGuidObject(RawData.Filename)\r
640 self.PpiObj = DecPpiObject(RawData.Filename)\r
641 self.ProtocolObj = DecProtocolObject(RawData.Filename)\r
642 self.ObjectDict = \\r
643 {\r
644 DT.TAB_GUIDS.upper() : self.GuidObj,\r
645 DT.TAB_PPIS.upper() : self.PpiObj,\r
646 DT.TAB_PROTOCOLS.upper() : self.ProtocolObj\r
647 }\r
f7496d71 648\r
4234283c
LG
649 def GetDataObject(self):\r
650 if self._RawData.CurrentScope:\r
651 return self.ObjectDict[self._RawData.CurrentScope[0][0]]\r
652 return None\r
f7496d71 653\r
4234283c
LG
654 def GetGuidObject(self):\r
655 return self.GuidObj\r
f7496d71 656\r
4234283c
LG
657 def GetPpiObject(self):\r
658 return self.PpiObj\r
f7496d71 659\r
4234283c
LG
660 def GetProtocolObject(self):\r
661 return self.ProtocolObj\r
f7496d71 662\r
4234283c
LG
663 def _ParseItem(self):\r
664 Line = self._RawData.CurrentLine\r
665 TokenList = GetSplitValueList(Line, DT.TAB_EQUAL_SPLIT, 1)\r
666 if len(TokenList) < 2:\r
667 self._LoggerError(ST.ERR_DECPARSE_CGUID)\r
668 if TokenList[0] == '':\r
669 self._LoggerError(ST.ERR_DECPARSE_CGUID_NAME)\r
670 if TokenList[1] == '':\r
671 self._LoggerError(ST.ERR_DECPARSE_CGUID_GUID)\r
672 if not IsValidToken(CVAR_PATTERN, TokenList[0]):\r
673 self._LoggerError(ST.ERR_DECPARSE_PCD_CVAR_GUID)\r
f7496d71 674\r
4234283c 675 self._CheckReDefine(TokenList[0])\r
f7496d71 676\r
4234283c
LG
677 if TokenList[1][0] != '{':\r
678 if not CheckGuidRegFormat(TokenList[1]):\r
679 self._LoggerError(ST.ERR_DECPARSE_DEFINE_PKGGUID)\r
680 GuidString = TokenList[1]\r
681 else:\r
682 #\r
683 # Convert C format GUID to GUID string and Simple error check\r
684 #\r
685 GuidString = GuidStructureStringToGuidString(TokenList[1])\r
686 if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidString == '':\r
687 self._LoggerError(ST.ERR_DECPARSE_CGUID_GUIDFORMAT)\r
f7496d71 688\r
4234283c
LG
689 #\r
690 # Check C format GUID\r
691 #\r
692 if not IsValidCFormatGuid(TokenList[1]):\r
693 self._LoggerError(ST.ERR_DECPARSE_CGUID_GUIDFORMAT)\r
694\r
695 Item = DecGuidItemObject(TokenList[0], TokenList[1], GuidString)\r
696 ItemObject = self.ObjectDict[self._RawData.CurrentScope[0][0]]\r
697 ItemObject.AddItem(Item, self._RawData.CurrentScope)\r
698 return Item\r
699\r
700## _DecUserExtension\r
701#\r
fb0b35e0 702# Parse user extension section\r
4234283c
LG
703#\r
704class _DecUserExtension(_DecBase):\r
705 def __init__(self, RawData):\r
706 _DecBase.__init__(self, RawData)\r
707 self.ItemObject = DecUserExtensionObject(RawData.Filename)\r
708 self._Headers = []\r
709 self._CurItems = []\r
f7496d71 710\r
4234283c
LG
711 def BlockStart(self):\r
712 self._CurItems = []\r
713 for Header in self._RawData.CurrentScope:\r
714 if Header in self._Headers:\r
715 self._LoggerError(ST.ERR_DECPARSE_UE_DUPLICATE)\r
716 else:\r
717 self._Headers.append(Header)\r
f7496d71 718\r
4234283c
LG
719 for Item in self._CurItems:\r
720 if Item.UserId == Header[1] and Item.IdString == Header[2]:\r
721 Item.ArchAndModuleType.append(Header[3])\r
722 break\r
723 else:\r
724 Item = DecUserExtensionItemObject()\r
725 Item.UserId = Header[1]\r
726 Item.IdString = Header[2]\r
727 Item.ArchAndModuleType.append(Header[3])\r
728 self._CurItems.append(Item)\r
729 self.ItemObject.AddItem(Item, None)\r
730 self._LocalMacro = {}\r
f7496d71 731\r
4234283c
LG
732 def _ParseItem(self):\r
733 Line = self._RawData.CurrentLine\r
734 Item = None\r
735 for Item in self._CurItems:\r
736 if Item.UserString:\r
737 Item.UserString = '\n'.join([Item.UserString, Line])\r
738 else:\r
739 Item.UserString = Line\r
740 return Item\r
741\r
742## Dec\r
743#\r
744# Top dec parser\r
745#\r
f7496d71
LG
746class Dec(_DecBase, _DecComments):\r
747 def __init__(self, DecFile, Parse = True):\r
4234283c 748 try:\r
174a9d3c 749 Content = ConvertSpecialChar(open(DecFile, 'r').readlines())\r
4234283c
LG
750 except BaseException:\r
751 Logger.Error(TOOL_NAME, FILE_OPEN_FAILURE, File=DecFile,\r
752 ExtraData=ST.ERR_DECPARSE_FILEOPEN % DecFile)\r
645a5128
HC
753\r
754 #\r
755 # Pre-parser for Private section\r
756 #\r
757 self._Private = ''\r
758 __IsFoundPrivate = False\r
759 NewContent = []\r
760 for Line in Content:\r
761 Line = Line.strip()\r
762 if Line.startswith(DT.TAB_SECTION_START) and Line.endswith(DT.TAB_PRIVATE + DT.TAB_SECTION_END):\r
763 __IsFoundPrivate = True\r
764 if Line.startswith(DT.TAB_SECTION_START) and Line.endswith(DT.TAB_SECTION_END)\\r
765 and not Line.endswith(DT.TAB_PRIVATE + DT.TAB_SECTION_END):\r
766 __IsFoundPrivate = False\r
767 if __IsFoundPrivate:\r
768 self._Private += Line + '\r'\r
769 if not __IsFoundPrivate:\r
770 NewContent.append(Line + '\r')\r
771\r
772 RawData = FileContent(DecFile, NewContent)\r
f7496d71 773\r
4234283c
LG
774 _DecComments.__init__(self)\r
775 _DecBase.__init__(self, RawData)\r
f7496d71 776\r
421ccda3
HC
777 self.BinaryHeadComment = []\r
778 self.PcdErrorCommentDict = {}\r
f7496d71 779\r
4234283c
LG
780 self._Define = _DecDefine(RawData)\r
781 self._Include = _DecInclude(RawData)\r
782 self._Guid = _DecGuid(RawData)\r
783 self._LibClass = _DecLibraryclass(RawData)\r
784 self._Pcd = _DecPcd(RawData)\r
785 self._UserEx = _DecUserExtension(RawData)\r
f7496d71 786\r
4234283c
LG
787 #\r
788 # DEC file supported data types (one type per section)\r
789 #\r
790 self._SectionParser = {\r
791 DT.TAB_DEC_DEFINES.upper() : self._Define,\r
792 DT.TAB_INCLUDES.upper() : self._Include,\r
793 DT.TAB_LIBRARY_CLASSES.upper() : self._LibClass,\r
794 DT.TAB_GUIDS.upper() : self._Guid,\r
795 DT.TAB_PPIS.upper() : self._Guid,\r
796 DT.TAB_PROTOCOLS.upper() : self._Guid,\r
797 DT.TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : self._Pcd,\r
798 DT.TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : self._Pcd,\r
799 DT.TAB_PCDS_FEATURE_FLAG_NULL.upper() : self._Pcd,\r
800 DT.TAB_PCDS_DYNAMIC_NULL.upper() : self._Pcd,\r
801 DT.TAB_PCDS_DYNAMIC_EX_NULL.upper() : self._Pcd,\r
802 DT.TAB_USER_EXTENSIONS.upper() : self._UserEx\r
803 }\r
804\r
805 if Parse:\r
806 self.ParseDecComment()\r
807 self.Parse()\r
808 #\r
809 # Parsing done, check required fields\r
810 #\r
811 self.CheckRequiredFields()\r
f7496d71 812\r
4234283c
LG
813 def CheckRequiredFields(self):\r
814 for SectionParser in self._SectionParser.values():\r
815 if not SectionParser.CheckRequiredFields():\r
816 return False\r
817 return True\r
421ccda3 818\r
4234283c
LG
819 ##\r
820 # Parse DEC file\r
821 #\r
822 def ParseDecComment(self):\r
2bc3256c
LG
823 IsFileHeader = False\r
824 IsBinaryHeader = False\r
825 FileHeaderLineIndex = -1\r
826 BinaryHeaderLineIndex = -1\r
421ccda3 827 TokenSpaceGuidCName = ''\r
f7496d71 828\r
421ccda3
HC
829 #\r
830 # Parse PCD error comment section\r
831 #\r
4234283c 832 while not self._RawData.IsEndOfFile():\r
421ccda3
HC
833 self._RawData.CurrentLine = self._RawData.GetNextLine()\r
834 if self._RawData.CurrentLine.startswith(DT.TAB_COMMENT_SPLIT) and \\r
835 DT.TAB_SECTION_START in self._RawData.CurrentLine and \\r
836 DT.TAB_SECTION_END in self._RawData.CurrentLine:\r
837 self._RawData.CurrentLine = self._RawData.CurrentLine.replace(DT.TAB_COMMENT_SPLIT, '').strip()\r
2bc3256c 838\r
421ccda3
HC
839 if self._RawData.CurrentLine[0] == DT.TAB_SECTION_START and \\r
840 self._RawData.CurrentLine[-1] == DT.TAB_SECTION_END:\r
841 RawSection = self._RawData.CurrentLine[1:-1].strip()\r
842 if RawSection.upper().startswith(DT.TAB_PCD_ERROR.upper()+'.'):\r
843 TokenSpaceGuidCName = RawSection.split(DT.TAB_PCD_ERROR+'.')[1].strip()\r
844 continue\r
845\r
846 if TokenSpaceGuidCName and self._RawData.CurrentLine.startswith(DT.TAB_COMMENT_SPLIT):\r
847 self._RawData.CurrentLine = self._RawData.CurrentLine.replace(DT.TAB_COMMENT_SPLIT, '').strip()\r
848 if self._RawData.CurrentLine != '':\r
849 if DT.TAB_VALUE_SPLIT not in self._RawData.CurrentLine:\r
f7496d71
LG
850 self._LoggerError(ST.ERR_DECPARSE_PCDERRORMSG_MISS_VALUE_SPLIT)\r
851\r
421ccda3
HC
852 PcdErrorNumber, PcdErrorMsg = GetSplitValueList(self._RawData.CurrentLine, DT.TAB_VALUE_SPLIT, 1)\r
853 PcdErrorNumber = ParsePcdErrorCode(PcdErrorNumber, self._RawData.Filename, self._RawData.LineIndex)\r
854 if not PcdErrorMsg.strip():\r
855 self._LoggerError(ST.ERR_DECPARSE_PCD_MISS_ERRORMSG)\r
f7496d71 856\r
421ccda3
HC
857 self.PcdErrorCommentDict[(TokenSpaceGuidCName, PcdErrorNumber)] = PcdErrorMsg.strip()\r
858 else:\r
859 TokenSpaceGuidCName = ''\r
860\r
861 self._RawData.LineIndex = 0\r
862 self._RawData.CurrentLine = ''\r
863 self._RawData.NextLine = ''\r
864\r
865 while not self._RawData.IsEndOfFile():\r
866 Line, Comment = CleanString(self._RawData.GetNextLine())\r
f7496d71 867\r
4234283c
LG
868 #\r
869 # Header must be pure comment\r
870 #\r
871 if Line != '':\r
872 self._RawData.UndoNextLine()\r
873 break\r
f7496d71 874\r
2bc3256c
LG
875 if Comment and Comment.startswith(DT.TAB_SPECIAL_COMMENT) and Comment.find(DT.TAB_HEADER_COMMENT) > 0 \\r
876 and not Comment[2:Comment.find(DT.TAB_HEADER_COMMENT)].strip():\r
877 IsFileHeader = True\r
878 IsBinaryHeader = False\r
879 FileHeaderLineIndex = self._RawData.LineIndex\r
f7496d71
LG
880\r
881 #\r
882 # Get license information before '@file'\r
2bc3256c 883 #\r
2bc3256c
LG
884 if not IsFileHeader and not IsBinaryHeader and Comment and Comment.startswith(DT.TAB_COMMENT_SPLIT) and \\r
885 DT.TAB_BINARY_HEADER_COMMENT not in Comment:\r
4234283c 886 self._HeadComment.append((Comment, self._RawData.LineIndex))\r
f7496d71 887\r
2bc3256c
LG
888 if Comment and IsFileHeader and \\r
889 not(Comment.startswith(DT.TAB_SPECIAL_COMMENT) \\r
890 and Comment.find(DT.TAB_BINARY_HEADER_COMMENT) > 0):\r
891 self._HeadComment.append((Comment, self._RawData.LineIndex))\r
892 #\r
893 # Double '#' indicates end of header comments\r
894 #\r
895 if (not Comment or Comment == DT.TAB_SPECIAL_COMMENT) and IsFileHeader:\r
f7496d71 896 IsFileHeader = False\r
2bc3256c 897 continue\r
f7496d71 898\r
2bc3256c
LG
899 if Comment and Comment.startswith(DT.TAB_SPECIAL_COMMENT) \\r
900 and Comment.find(DT.TAB_BINARY_HEADER_COMMENT) > 0:\r
901 IsBinaryHeader = True\r
902 IsFileHeader = False\r
903 BinaryHeaderLineIndex = self._RawData.LineIndex\r
f7496d71 904\r
2bc3256c
LG
905 if Comment and IsBinaryHeader:\r
906 self.BinaryHeadComment.append((Comment, self._RawData.LineIndex))\r
4234283c
LG
907 #\r
908 # Double '#' indicates end of header comments\r
909 #\r
2bc3256c
LG
910 if (not Comment or Comment == DT.TAB_SPECIAL_COMMENT) and IsBinaryHeader:\r
911 IsBinaryHeader = False\r
4234283c 912 break\r
f7496d71 913\r
2bc3256c
LG
914 if FileHeaderLineIndex > -1 and not IsFileHeader and not IsBinaryHeader:\r
915 break\r
916\r
917 if FileHeaderLineIndex > BinaryHeaderLineIndex and FileHeaderLineIndex > -1 and BinaryHeaderLineIndex > -1:\r
918 self._LoggerError(ST.ERR_BINARY_HEADER_ORDER)\r
f7496d71 919\r
2bc3256c 920 if FileHeaderLineIndex == -1:\r
421ccda3 921# self._LoggerError(ST.ERR_NO_SOURCE_HEADER)\r
f7496d71 922 Logger.Error(TOOL_NAME, FORMAT_INVALID,\r
2bc3256c 923 ST.ERR_NO_SOURCE_HEADER,\r
421ccda3 924 File=self._RawData.Filename)\r
4234283c 925 return\r
f7496d71 926\r
4234283c
LG
927 def _StopCurrentParsing(self, Line):\r
928 return False\r
f7496d71 929\r
4234283c
LG
930 def _ParseItem(self):\r
931 self._SectionHeaderParser()\r
932 if len(self._RawData.CurrentScope) == 0:\r
933 self._LoggerError(ST.ERR_DECPARSE_SECTION_EMPTY)\r
4234283c 934 SectionObj = self._SectionParser[self._RawData.CurrentScope[0][0]]\r
4234283c
LG
935 SectionObj.BlockStart()\r
936 SectionObj.Parse()\r
4234283c
LG
937 return SectionObj.GetDataObject()\r
938\r
939 def _UserExtentionSectionParser(self):\r
940 self._RawData.CurrentScope = []\r
941 ArchList = set()\r
942 Section = self._RawData.CurrentLine[1:-1]\r
4234283c
LG
943 Par = ParserHelper(Section, self._RawData.Filename)\r
944 while not Par.End():\r
945 #\r
946 # User extention\r
947 #\r
948 Token = Par.GetToken()\r
949 if Token.upper() != DT.TAB_USER_EXTENSIONS.upper():\r
950 self._LoggerError(ST.ERR_DECPARSE_SECTION_UE)\r
951 UserExtension = Token.upper()\r
f7496d71
LG
952 Par.AssertChar(DT.TAB_SPLIT, ST.ERR_DECPARSE_SECTION_UE, self._RawData.LineIndex)\r
953\r
4234283c
LG
954 #\r
955 # UserID\r
956 #\r
957 Token = Par.GetToken()\r
958 if not IsValidUserId(Token):\r
959 self._LoggerError(ST.ERR_DECPARSE_SECTION_UE_USERID)\r
960 UserId = Token\r
4234283c
LG
961 Par.AssertChar(DT.TAB_SPLIT, ST.ERR_DECPARSE_SECTION_UE, self._RawData.LineIndex)\r
962 #\r
963 # IdString\r
964 #\r
965 Token = Par.GetToken()\r
966 if not IsValidIdString(Token):\r
967 self._LoggerError(ST.ERR_DECPARSE_SECTION_UE_IDSTRING)\r
968 IdString = Token\r
4234283c
LG
969 Arch = 'COMMON'\r
970 if Par.Expect(DT.TAB_SPLIT):\r
971 Token = Par.GetToken()\r
972 Arch = Token.upper()\r
973 if not IsValidArch(Arch):\r
974 self._LoggerError(ST.ERR_DECPARSE_ARCH)\r
975 ArchList.add(Arch)\r
4234283c
LG
976 if [UserExtension, UserId, IdString, Arch] not in \\r
977 self._RawData.CurrentScope:\r
978 self._RawData.CurrentScope.append(\r
979 [UserExtension, UserId, IdString, Arch]\r
980 )\r
4234283c
LG
981 if not Par.Expect(DT.TAB_COMMA_SPLIT):\r
982 break\r
983 elif Par.End():\r
984 self._LoggerError(ST.ERR_DECPARSE_SECTION_COMMA)\r
4234283c 985 Par.AssertEnd(ST.ERR_DECPARSE_SECTION_UE, self._RawData.LineIndex)\r
4234283c
LG
986 if 'COMMON' in ArchList and len(ArchList) > 1:\r
987 self._LoggerError(ST.ERR_DECPARSE_SECTION_COMMON)\r
f7496d71 988\r
4234283c
LG
989 ## Section header parser\r
990 #\r
991 # The section header is always in following format:\r
992 #\r
993 # [section_name.arch<.platform|module_type>]\r
994 #\r
995 def _SectionHeaderParser(self):\r
996 if self._RawData.CurrentLine[0] != DT.TAB_SECTION_START or self._RawData.CurrentLine[-1] != DT.TAB_SECTION_END:\r
997 self._LoggerError(ST.ERR_DECPARSE_SECTION_IDENTIFY)\r
f7496d71 998\r
4234283c 999 RawSection = self._RawData.CurrentLine[1:-1].strip().upper()\r
4234283c
LG
1000 #\r
1001 # Check defines section which is only allowed to occur once and\r
1002 # no arch can be followed\r
1003 #\r
1004 if RawSection.startswith(DT.TAB_DEC_DEFINES.upper()):\r
1005 if RawSection != DT.TAB_DEC_DEFINES.upper():\r
1006 self._LoggerError(ST.ERR_DECPARSE_DEFINE_SECNAME)\r
4234283c
LG
1007 #\r
1008 # Check user extension section\r
1009 #\r
1010 if RawSection.startswith(DT.TAB_USER_EXTENSIONS.upper()):\r
1011 return self._UserExtentionSectionParser()\r
4234283c
LG
1012 self._RawData.CurrentScope = []\r
1013 SectionNames = []\r
1014 ArchList = set()\r
1015 for Item in GetSplitValueList(RawSection, DT.TAB_COMMA_SPLIT):\r
1016 if Item == '':\r
1017 self._LoggerError(ST.ERR_DECPARSE_SECTION_SUBEMPTY % self._RawData.CurrentLine)\r
1018\r
1019 ItemList = GetSplitValueList(Item, DT.TAB_SPLIT)\r
4234283c
LG
1020 #\r
1021 # different types of PCD are permissible in one section\r
1022 #\r
1023 SectionName = ItemList[0]\r
1024 if SectionName not in self._SectionParser:\r
1025 self._LoggerError(ST.ERR_DECPARSE_SECTION_UNKNOW % SectionName)\r
4234283c
LG
1026 if SectionName not in SectionNames:\r
1027 SectionNames.append(SectionName)\r
4234283c
LG
1028 #\r
1029 # In DEC specification, all section headers have at most two part:\r
fb0b35e0 1030 # SectionName.Arch except UserExtension\r
4234283c
LG
1031 #\r
1032 if len(ItemList) > 2:\r
1033 self._LoggerError(ST.ERR_DECPARSE_SECTION_SUBTOOMANY % Item)\r
1034\r
1035 if DT.TAB_PCDS_FEATURE_FLAG_NULL.upper() in SectionNames and len(SectionNames) > 1:\r
f7496d71 1036 self._LoggerError(ST.ERR_DECPARSE_SECTION_FEATUREFLAG % DT.TAB_PCDS_FEATURE_FLAG_NULL)\r
4234283c
LG
1037 #\r
1038 # S1 is always Arch\r
1039 #\r
1040 if len(ItemList) > 1:\r
1041 Str1 = ItemList[1]\r
1042 if not IsValidArch(Str1):\r
1043 self._LoggerError(ST.ERR_DECPARSE_ARCH)\r
1044 else:\r
1045 Str1 = 'COMMON'\r
1046 ArchList.add(Str1)\r
1047\r
1048 if [SectionName, Str1] not in self._RawData.CurrentScope:\r
1049 self._RawData.CurrentScope.append([SectionName, Str1])\r
1050 #\r
1051 # 'COMMON' must not be used with specific ARCHs at the same section\r
1052 #\r
1053 if 'COMMON' in ArchList and len(ArchList) > 1:\r
1054 self._LoggerError(ST.ERR_DECPARSE_SECTION_COMMON)\r
4234283c
LG
1055 if len(SectionNames) == 0:\r
1056 self._LoggerError(ST.ERR_DECPARSE_SECTION_SUBEMPTY % self._RawData.CurrentLine)\r
1057 if len(SectionNames) != 1:\r
1058 for Sec in SectionNames:\r
1059 if not Sec.startswith(DT.TAB_PCDS.upper()):\r
1060 self._LoggerError(ST.ERR_DECPARSE_SECTION_NAME % str(SectionNames))\r
f7496d71 1061\r
421ccda3
HC
1062 def GetDefineSectionMacro(self):\r
1063 return self._Define.GetLocalMacro()\r
4234283c
LG
1064 def GetDefineSectionObject(self):\r
1065 return self._Define.GetDataObject()\r
4234283c
LG
1066 def GetIncludeSectionObject(self):\r
1067 return self._Include.GetDataObject()\r
4234283c
LG
1068 def GetGuidSectionObject(self):\r
1069 return self._Guid.GetGuidObject()\r
4234283c
LG
1070 def GetProtocolSectionObject(self):\r
1071 return self._Guid.GetProtocolObject()\r
4234283c
LG
1072 def GetPpiSectionObject(self):\r
1073 return self._Guid.GetPpiObject()\r
4234283c
LG
1074 def GetLibraryClassSectionObject(self):\r
1075 return self._LibClass.GetDataObject()\r
4234283c
LG
1076 def GetPcdSectionObject(self):\r
1077 return self._Pcd.GetDataObject()\r
4234283c
LG
1078 def GetUserExtensionSectionObject(self):\r
1079 return self._UserEx.GetDataObject()\r
4234283c 1080 def GetPackageSpecification(self):\r
f7496d71 1081 return self._Define.GetDataObject().GetPackageSpecification()\r
4234283c 1082 def GetPackageName(self):\r
f7496d71 1083 return self._Define.GetDataObject().GetPackageName()\r
4234283c 1084 def GetPackageGuid(self):\r
f7496d71 1085 return self._Define.GetDataObject().GetPackageGuid()\r
4234283c
LG
1086 def GetPackageVersion(self):\r
1087 return self._Define.GetDataObject().GetPackageVersion()\r
4234283c
LG
1088 def GetPackageUniFile(self):\r
1089 return self._Define.GetDataObject().GetPackageUniFile()\r
645a5128
HC
1090 def GetPrivateSections(self):\r
1091 return self._Private\r