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