2fe4c55075dbc1d1839b4ace4e8ea5207b59f172
[people/mcb30/basetools.git] / Source / Python / Workspace / MetaFileParser.py
1 ## @file\r
2 # This file is used to create a database used by ECC tool\r
3 #\r
4 # Copyright (c) 2007 ~ 2008, Intel Corporation\r
5 # All rights reserved. This program and the accompanying materials\r
6 # are licensed and made available under the terms and conditions of the BSD License\r
7 # which accompanies this distribution.  The full text of the license may be found at\r
8 # http://opensource.org/licenses/bsd-license.php\r
9 #\r
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12 #\r
13 \r
14 ##\r
15 # Import Modules\r
16 #\r
17 import sqlite3\r
18 import os\r
19 import time\r
20 \r
21 import Common.EdkLogger as EdkLogger\r
22 from CommonDataClass.DataClass import *\r
23 from Common.DataType import *\r
24 from Common.String import *\r
25 from Common.Misc import Blist\r
26 \r
27 class MetaFileParser(object):\r
28     DataType = {}\r
29     def __init__(self, FilePath, FileType, Table, Macros={}, Owner=-1, From=-1):\r
30         self._Table = Table\r
31         self._FileType = FileType\r
32         self._FilePath = FilePath\r
33         self._FileDir = os.path.dirname(self._FilePath)\r
34         self._Macros = Macros\r
35         # for recursive parsing \r
36         self._Owner = Owner\r
37         self._From = From\r
38 \r
39         # for parsing\r
40         self._Content = None\r
41         self._ValueList = ['', '', '', '', '']\r
42         self._Scope = []\r
43         self._LineIndex = 0\r
44         self._CurrentLine = ''\r
45         self._SectionType = MODEL_UNKNOWN\r
46         self._SectionName = ''\r
47         self._InSubsection = False\r
48         self._SubsectionType = MODEL_UNKNOWN\r
49         self._SubsectionName = ''\r
50         self._LastItem = -1\r
51         self._Enabled = 0\r
52         self._Finished = False\r
53 \r
54     def _Store(self, *Args):\r
55         return self._Table.Insert(*Args)\r
56 \r
57     def Start(self):\r
58         raise NotImplementedError \r
59 \r
60     def _Done(self):\r
61         self._Finished = True\r
62         self._Table.SetEndFlag()\r
63 \r
64     def _GetTable(self):\r
65         if not self._Finished:\r
66             self.Start()\r
67         return self._Table\r
68 \r
69     def _GetFinished(self):\r
70         return self._Finished\r
71 \r
72     def _SetFinished(self, Value):\r
73         self._Finished = Value\r
74 \r
75     # DataType = [section_header_name, scope1(arch), scope2(platform,moduletype)]\r
76     def __getitem__(self, DataInfo):\r
77         if type(DataInfo) != type(()):\r
78             DataInfo = (DataInfo,)\r
79         return self.Table.Query(*DataInfo)\r
80 \r
81     def _CommonParser(self):\r
82         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
83         self._ValueList[0:len(TokenList)] = TokenList\r
84 \r
85     def _PathParser(self):\r
86         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)\r
87         self._ValueList[0:len(TokenList)] = TokenList\r
88         if len(self._Macros) > 0:\r
89             for Index in range(0, len(self._ValueList)):\r
90                 Value = self._ValueList[Index]\r
91                 if Value == None or Value == '':\r
92                     continue\r
93                 self._ValueList[Index] = NormPath(Value, self._Macros)\r
94 \r
95     def _Skip(self):\r
96         self._ValueList[0:1] = [self._CurrentLine]\r
97 \r
98     def _SectionHeaderParser(self):\r
99         self._Scope = []\r
100         self._SectionName = ''\r
101         ArchList = set()\r
102         for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):\r
103             ItemList = GetSplitValueList(Item, TAB_SPLIT)\r
104             if self._SectionName != '' and self._SectionName != ItemList[0].upper():\r
105                 EdkLogger.error('Parser', FORMAT_INVALID, "Different section names in the same section",\r
106                                 File=self._FilePath, Line=self._LineIndex+1, ExtraData=self._CurrentLine)\r
107             self._SectionName = ItemList[0].upper()\r
108             if self._SectionName in self.DataType:\r
109                 self._SectionType = self.DataType[self._SectionName]\r
110             else:\r
111                 self._SectionType = MODEL_UNKNOWN\r
112             # S1 is always Arch\r
113             if len(ItemList) > 1:\r
114                 S1 = ItemList[1].upper()\r
115             else:\r
116                 S1 = 'COMMON'\r
117             ArchList.add(S1)\r
118             # S2 may be Platform or ModuleType\r
119             if len(ItemList) > 2:\r
120                 S2 = ItemList[2].upper()\r
121             else:\r
122                 S2 = 'COMMON'\r
123             self._Scope.append([S1, S2])\r
124 \r
125         # 'COMMON' must not be used with specific ARCHs at the same section\r
126         if 'COMMON' in ArchList and len(ArchList) > 1:\r
127             EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",\r
128                             File=self._FilePath, Line=self._LineIndex+1, ExtraData=self._CurrentLine)\r
129 \r
130     def _DefineParser(self):\r
131         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
132         self._ValueList[0:len(TokenList)] = TokenList\r
133         if self._ValueList[1] == '':\r
134             EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",\r
135                             ExtraData=self._CurrentLine, File=self._FilePath, Line=self._LineIndex+1)\r
136 \r
137     def _MacroParser(self):\r
138         TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)\r
139         if len(TokenList) < 2 or TokenList[1] == '':\r
140             EdkLogger.error('Parser', FORMAT_INVALID, "No macro name/value given",\r
141                             ExtraData=self._CurrentLine, File=self._FilePath, Line=self._LineIndex+1)\r
142         TokenList = GetSplitValueList(TokenList[1], TAB_EQUAL_SPLIT, 1)\r
143         if len(TokenList) < 1:\r
144             return\r
145         if self._Macros == None:\r
146             self._Macros = {}\r
147         self._Macros[TokenList[0]] = TokenList[1]\r
148 \r
149     _SectionParser  = {}\r
150     Table           = property(_GetTable)\r
151     Finished        = property(_GetFinished, _SetFinished)\r
152 \r
153 \r
154 class InfParser(MetaFileParser):\r
155     DataType = {\r
156         TAB_UNKNOWN.upper() : MODEL_UNKNOWN,\r
157         TAB_INF_DEFINES.upper() : MODEL_META_DATA_HEADER,\r
158         TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,\r
159         TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,\r
160         TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,\r
161         TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,\r
162         TAB_PACKAGES.upper() : MODEL_META_DATA_PACKAGE,\r
163         TAB_NMAKE.upper() : MODEL_META_DATA_NMAKE,\r
164         TAB_INF_FIXED_PCD.upper() : MODEL_PCD_FIXED_AT_BUILD,\r
165         TAB_INF_PATCH_PCD.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,\r
166         TAB_INF_FEATURE_PCD.upper() : MODEL_PCD_FEATURE_FLAG,\r
167         TAB_INF_PCD_EX.upper() : MODEL_PCD_DYNAMIC_EX,\r
168         TAB_INF_PCD.upper() : MODEL_PCD_DYNAMIC,\r
169         TAB_SOURCES.upper() : MODEL_EFI_SOURCE_FILE,\r
170         TAB_GUIDS.upper() : MODEL_EFI_GUID,\r
171         TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,\r
172         TAB_PPIS.upper() : MODEL_EFI_PPI,\r
173         TAB_DEPEX.upper() : MODEL_EFI_DEPEX,\r
174         TAB_BINARIES.upper() : MODEL_EFI_BINARY_FILE,\r
175         TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION\r
176     }\r
177 \r
178     def __init__(self, FilePath, FileId, FileType, Table, Macros={}):\r
179         MetaFileParser.__init__(self, FilePath, FileType, Table, Macros)\r
180 \r
181     def Start(self):\r
182         try:\r
183             self._Content = open(self._FilePath, 'r').readlines()\r
184         except:\r
185             EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self._FilePath)\r
186 \r
187         for Index in range(0, len(self._Content)):\r
188             Line = CleanString(self._Content[Index])\r
189             if Line == '':\r
190                 continue\r
191             self._CurrentLine = Line\r
192             self._LineIndex = Index\r
193 \r
194             # section header\r
195             if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:\r
196                 self._SectionHeaderParser()\r
197                 continue\r
198             elif Line.upper().startswith('DEFINE '):\r
199                 self._MacroParser()\r
200                 continue\r
201 \r
202             # section content\r
203             self._ValueList = ['','','']\r
204             self._SectionParser[self._SectionType](self)\r
205             if self._ValueList == None:\r
206                 continue\r
207             # \r
208             # Model, Value1, Value2, Value3, Value4, Value5, Arch, Platform, BelongsToFile=-1, \r
209             # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, BelongsToItem=-1, FeatureFlag='', \r
210             # Enabled=-1\r
211             # \r
212             for Arch, Platform in self._Scope:\r
213                 self._Store(self._SectionType,\r
214                             self._ValueList[0],\r
215                             self._ValueList[1],\r
216                             self._ValueList[2],\r
217                             Arch,\r
218                             Platform,\r
219                             self._Owner,\r
220                             self._LineIndex+1,\r
221                             -1,\r
222                             self._LineIndex+1,\r
223                             -1,\r
224                             0\r
225                             )\r
226         self._Done()\r
227             \r
228     def _BuildOptionParser(self):\r
229         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
230         TokenList2 = GetSplitValueList(TokenList[0], ':', 1)\r
231         if len(TokenList2) == 2:\r
232             self._ValueList[0] = TokenList2[0]\r
233             self._ValueList[1] = TokenList2[1]\r
234         else:\r
235             self._ValueList[1] = TokenList[0]\r
236         self._ValueList[2] = ReplaceMacro(TokenList[1], self._Macros)\r
237 \r
238     def _NmakeParser(self):\r
239         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
240         self._ValueList[0:len(TokenList)] = TokenList\r
241         # remove self-reference in macro setting\r
242         self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})\r
243 \r
244     def _PcdParser(self):\r
245         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
246         self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
247         if len(TokenList) > 1:\r
248             self._ValueList[2] = TokenList[1]\r
249         if self._ValueList[0] == '' or self._ValueList[1] == '':\r
250             EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
251                             ExtraData=self._CurrentLine, File=self._FilePath, Line=self._LineIndex+1)\r
252 \r
253     def _DepexParser(self):\r
254         self._ValueList[0:1] = [self._CurrentLine]\r
255 \r
256     _SectionParser = {\r
257         MODEL_UNKNOWN                   :   MetaFileParser._Skip,\r
258         MODEL_META_DATA_HEADER          :   MetaFileParser._DefineParser,\r
259         MODEL_META_DATA_BUILD_OPTION    :   _BuildOptionParser,\r
260         MODEL_EFI_INCLUDE               :   MetaFileParser._PathParser,     # for R8.x modules\r
261         MODEL_EFI_LIBRARY_INSTANCE      :   MetaFileParser._CommonParser,   # for R8.x modules\r
262         MODEL_EFI_LIBRARY_CLASS         :   MetaFileParser._PathParser,\r
263         MODEL_META_DATA_PACKAGE         :   MetaFileParser._PathParser,\r
264         MODEL_META_DATA_NMAKE           :   _NmakeParser,                   # for R8.x modules\r
265         MODEL_PCD_FIXED_AT_BUILD        :   _PcdParser,\r
266         MODEL_PCD_PATCHABLE_IN_MODULE   :   _PcdParser,\r
267         MODEL_PCD_FEATURE_FLAG          :   _PcdParser,\r
268         MODEL_PCD_DYNAMIC_EX            :   _PcdParser,\r
269         MODEL_PCD_DYNAMIC               :   _PcdParser,\r
270         MODEL_EFI_SOURCE_FILE           :   MetaFileParser._PathParser,\r
271         MODEL_EFI_GUID                  :   MetaFileParser._CommonParser,\r
272         MODEL_EFI_PROTOCOL              :   MetaFileParser._CommonParser,\r
273         MODEL_EFI_PPI                   :   MetaFileParser._CommonParser,\r
274         MODEL_EFI_DEPEX                 :   _DepexParser,\r
275         MODEL_EFI_BINARY_FILE           :   MetaFileParser._PathParser,\r
276         MODEL_META_DATA_USER_EXTENSION  :   MetaFileParser._Skip,\r
277     }\r
278 \r
279 class DscParser(MetaFileParser):\r
280     DataType = {\r
281         TAB_SKUIDS.upper()                          :   MODEL_EFI_SKU_ID,\r
282         TAB_LIBRARIES.upper()                       :   MODEL_EFI_LIBRARY_INSTANCE,\r
283         TAB_LIBRARY_CLASSES.upper()                 :   MODEL_EFI_LIBRARY_CLASS,\r
284         TAB_BUILD_OPTIONS.upper()                   :   MODEL_META_DATA_BUILD_OPTION,\r
285         TAB_PCDS_FIXED_AT_BUILD_NULL.upper()        :   MODEL_PCD_FIXED_AT_BUILD,\r
286         TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper()   :   MODEL_PCD_PATCHABLE_IN_MODULE,\r
287         TAB_PCDS_FEATURE_FLAG_NULL.upper()          :   MODEL_PCD_FEATURE_FLAG,\r
288         TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper()       :   MODEL_PCD_DYNAMIC_DEFAULT,\r
289         TAB_PCDS_DYNAMIC_HII_NULL.upper()           :   MODEL_PCD_DYNAMIC_HII,\r
290         TAB_PCDS_DYNAMIC_VPD_NULL.upper()           :   MODEL_PCD_DYNAMIC_VPD,\r
291         TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper()    :   MODEL_PCD_DYNAMIC_EX_DEFAULT,\r
292         TAB_PCDS_DYNAMIC_EX_HII_NULL.upper()        :   MODEL_PCD_DYNAMIC_EX_HII,\r
293         TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper()        :   MODEL_PCD_DYNAMIC_EX_VPD,\r
294         TAB_COMPONENTS.upper()                      :   MODEL_META_DATA_COMPONENT,\r
295         TAB_DSC_DEFINES.upper()                     :   MODEL_META_DATA_HEADER,\r
296         TAB_INCLUDE.upper()                         :   MODEL_META_DATA_INCLUDE,\r
297         TAB_IF.upper()                              :   MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,\r
298         TAB_IF_DEF.upper()                          :   MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,\r
299         TAB_IF_N_DEF.upper()                        :   MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF,\r
300         TAB_ELSE_IF.upper()                         :   MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF,\r
301         TAB_ELSE.upper()                            :   MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,\r
302         TAB_END_IF.upper()                          :   MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF,\r
303     }\r
304 \r
305     _IncludeAllowedSection = [\r
306         TAB_LIBRARIES.upper(), \r
307         TAB_LIBRARY_CLASSES.upper(), \r
308         TAB_SKUIDS.upper(),\r
309         TAB_COMPONENTS.upper(),\r
310         TAB_BUILD_OPTIONS.upper(),\r
311         TAB_PCDS_FIXED_AT_BUILD_NULL.upper(),\r
312         TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper(),\r
313         TAB_PCDS_FEATURE_FLAG_NULL.upper(),\r
314         TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper(),\r
315         TAB_PCDS_DYNAMIC_HII_NULL.upper(),\r
316         TAB_PCDS_DYNAMIC_VPD_NULL.upper(),\r
317         TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper(),\r
318         TAB_PCDS_DYNAMIC_EX_HII_NULL.upper(),\r
319         TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper(),\r
320         ]\r
321 \r
322     _OP_ = {\r
323         "!"     :   lambda a:   not a,\r
324         "!="    :   lambda a,b: a!=b,\r
325         "=="    :   lambda a,b: a==b,\r
326         ">"     :   lambda a,b: a>b,\r
327         "<"     :   lambda a,b: a<b,\r
328         "=>"    :   lambda a,b: a>=b,\r
329         ">="    :   lambda a,b: a>=b,\r
330         "<="    :   lambda a,b: a<=b,\r
331         "=<"    :   lambda a,b: a<=b,\r
332     }\r
333 \r
334     def __init__(self, FilePath, FileId, FileType, Table, Macros={}, Owner=-1, From=-1):\r
335         MetaFileParser.__init__(self, FilePath, FileType, Table, Macros, Owner, From)\r
336         # to store conditional directive evaluation result\r
337         self._Eval = Blist()\r
338 \r
339     def Start(self):\r
340         try:\r
341             if self._Content == None:\r
342                 self._Content = open(self._FilePath, 'r').readlines()\r
343         except:\r
344             EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self._FilePath)\r
345 \r
346         for Index in range(0, len(self._Content)):\r
347             Line = CleanString(self._Content[Index])\r
348             # skip empty line\r
349             if Line == '':\r
350                 self._LineIndex += 1\r
351                 continue\r
352             self._CurrentLine = Line\r
353             self._LineIndex = Index\r
354 \r
355             # section header\r
356             if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:\r
357                 self._SectionHeaderParser()\r
358                 continue\r
359             elif Line[0] == '}':\r
360                 self._InSubsection = False\r
361                 self._Owner = -1\r
362                 continue\r
363             elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:\r
364                 self._SubsectionHeaderParser()\r
365                 continue\r
366             # directive line\r
367             elif Line[0] == '!':\r
368                 self._DirectiveParser()\r
369                 continue\r
370             elif Line.upper().startswith('DEFINE '):\r
371                 self._MacroParser()\r
372                 continue\r
373 \r
374             # section content\r
375             if self._InSubsection:\r
376                 SectionType = self._SubsectionType\r
377                 SectionName = self._SubsectionName\r
378                 if self._Owner == -1:\r
379                     self._Owner = self._LastItem\r
380             else:\r
381                 SectionType = self._SectionType\r
382                 SectionName = self._SectionName\r
383             self._ValueList = ['', '', '']\r
384             self._SectionParser[SectionType](self)\r
385             if self._ValueList == None:\r
386                 continue\r
387 \r
388             # \r
389             # Model, Value1, Value2, Value3, Arch, Platform, BelongsToFile=-1, \r
390             # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, BelongsToItem=-1, \r
391             # Enabled=-1\r
392             # \r
393             for Arch, ModuleType in self._Scope:\r
394                 self._LastItem = self._Store(\r
395                     SectionType,\r
396                     self._ValueList[0],\r
397                     self._ValueList[1],\r
398                     self._ValueList[2],\r
399                     Arch,\r
400                     ModuleType,\r
401                     self._Owner,\r
402                     self._From,\r
403                     self._LineIndex+1,\r
404                     -1,\r
405                     self._LineIndex+1,\r
406                     -1,\r
407                     self._Enabled\r
408                     )\r
409         self._Done()\r
410 \r
411     def _DefineParser(self):\r
412         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
413         if len(TokenList) < 2:\r
414             EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",\r
415                             ExtraData=self._CurrentLine, File=self._FilePath, Line=self._LineIndex+1)\r
416         if TokenList[0] in ['FLASH_DEFINITION', 'OUTPUT_DIRECTORY']:\r
417             TokenList[1] = NormPath(TokenList[1], self._Macros)\r
418         self._ValueList[0:len(TokenList)] = TokenList    \r
419             \r
420     def _SubsectionHeaderParser(self):\r
421         self._SubsectionName = self._CurrentLine[1:-1].upper()\r
422         if self._SubsectionName in self.DataType:\r
423             self._SubsectionType = self.DataType[self._SubsectionName]\r
424         else:\r
425             self._SubsectionType = MODEL_UNKNOWN\r
426 \r
427     def _DirectiveParser(self):\r
428         self._ValueList = ['','','']\r
429         TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)\r
430         self._ValueList[0:len(TokenList)] = TokenList\r
431         if self._ValueList[1] == '':\r
432             EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression", \r
433                             File=self._FilePath, Line=self._LineIndex+1,\r
434                             ExtraData=self._CurrentLine)\r
435         DirectiveName = self._ValueList[0].upper()\r
436         self._LastItem = self._Store(\r
437             self.DataType[DirectiveName],\r
438             self._ValueList[0],\r
439             self._ValueList[1],\r
440             self._ValueList[2],\r
441             'COMMON',\r
442             'COMMON',\r
443             self._Owner,\r
444             self._LineIndex + 1,\r
445             -1,\r
446             self._LineIndex + 1,\r
447             -1,\r
448             0\r
449             )\r
450         # process the directive\r
451         if DirectiveName == "!INCLUDE":\r
452             if not self._SectionName in self._IncludeAllowedSection:\r
453                 EdkLogger.error("Parser", FORMAT_INVALID, File=self._FilePath, Line=self._LineIndex+1,\r
454                                 ExtraData="'!include' is not allowed under section [%s]" % self._SectionName)\r
455             # the included file must be relative to the parsing file\r
456             IncludedFile = os.path.join(self._FileDir, self._ValueList[1])\r
457             Parser = DscParser(IncludedFile, self._FileType, self._Table, self._Macros, From=self._LastItem)\r
458             Parser._SectionName = self._SectionName\r
459             Parser._SectionType = self._SectionType\r
460             Parser._Scope = self._Scope\r
461             Parser._Enabled = self._Enabled\r
462             try:\r
463                 Parser.Start()\r
464             except:\r
465                 EdkLogger.error("Parser", PARSER_ERROR, File=self._FilePath, Line=self._LineIndex+1,\r
466                                 ExtraData="Failed to parse content in file %s" % IncludedFile)\r
467             self._SectionName = Parser._SectionName\r
468             self._SectionType = Parser._SectionType\r
469             self._Scope       = Parser._Scope\r
470             self._Enabled     = Parser._Enabled\r
471         else:\r
472             if DirectiveName in ["!IF", "!IFDEF", "!IFNDEF"]:\r
473                 # evaluate the expression\r
474                 Result = self._Evaluate(self._ValueList[1])\r
475                 if DirectiveName == "!IFNDEF":\r
476                     Result = not Result\r
477                 self._Eval.append(Result)\r
478             elif DirectiveName in ["!ELSEIF"]:\r
479                 # evaluate the expression\r
480                 self._Eval[-1] = (not self._Eval[-1]) & self._Evaluate(self._ValueList[1])\r
481             elif DirectiveName in ["!ELSE"]:\r
482                 self._Eval[-1] = not self._Eval[-1]\r
483             elif DirectiveName in ["!ENDIF"]:\r
484                 if len(self._Eval) > 0:\r
485                     self._Eval.pop()\r
486                 else:\r
487                     EdkLogger.error("Parser", FORMAT_INVALID, "!IF..[!ELSE]..!ENDIF doesn't match",\r
488                                     File=self._FilePath, Line=self._LineIndex+1)\r
489             if self._Eval.Result == False:\r
490                 self._Enabled = 0 - len(self._Eval)\r
491             else:\r
492                 self._Enabled = len(self._Eval)\r
493 \r
494     def _Evaluate(self, Expression):\r
495         TokenList = Expression.split()\r
496         TokenNumber = len(TokenList)\r
497         if TokenNumber == 1:\r
498             return TokenList[0] in self._Macros\r
499         elif TokenNumber == 2:\r
500             Op = TokenList[0]\r
501             if Op not in self._OP_:\r
502                 EdkLogger.error('Parser', FORMAT_INVALID, "Unsupported operator", File=self._FilePath,\r
503                                 Line=self._LineIndex+1, ExtraData=Expression)\r
504             if TokenList[1].upper() == 'TRUE':\r
505                 Value = True\r
506             else:\r
507                 Value = False\r
508             return self._OP_[Op](Value)\r
509         elif TokenNumber == 3:\r
510             Name = TokenList[0]\r
511             if Name not in self._Macros:\r
512                 return False\r
513             Value = TokenList[2]\r
514             if Value[0] in ["'", '"']:\r
515                 Value = Value[1:-1]\r
516             Op = TokenList[1]\r
517             return self._OP_[Op](self._Macros[Macro], Value)\r
518         else:\r
519             EdkLogger.error('Parser', FORMAT_INVALID, File=self._FilePath, Line=self._LineIndex+1,\r
520                             ExtraData=Expression)\r
521 \r
522     def _BuildOptionParser(self):\r
523         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
524         TokenList2 = GetSplitValueList(TokenList[0], ':', 1)\r
525         if len(TokenList2) == 2:\r
526             self._ValueList[0] = TokenList2[0]\r
527             self._ValueList[1] = TokenList2[1]\r
528         else:\r
529             self._ValueList[1] = TokenList[0]\r
530         self._ValueList[2] = ReplaceMacro(TokenList[1], self._Macros)\r
531 \r
532     def _PcdParser(self):\r
533         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
534         self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
535         self._ValueList[2] = TokenList[1]\r
536         if self._ValueList[0] == '' or self._ValueList[1] == '':\r
537             EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
538                             ExtraData=self._CurrentLine, File=self._FilePath, Line=self._LineIndex+1)\r
539         if self._ValueList[2] == '':\r
540             EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",\r
541                             ExtraData=self._CurrentLine, File=self._FilePath, Line=self._LineIndex+1)\r
542 \r
543     def _ComponentParser(self):        \r
544         if self._CurrentLine[-1] == '{':\r
545             self._InSubsection = True\r
546             self._ValueList[0] = self._CurrentLine[0:-1].strip()\r
547         else:\r
548             self._ValueList[0] = self._CurrentLine\r
549         if len(self._Macros) > 0:\r
550             self._ValueList[0] = NormPath(self._ValueList[0], self._Macros)\r
551 \r
552     _SectionParser = {\r
553         MODEL_META_DATA_HEADER          :   MetaFileParser._DefineParser,\r
554         MODEL_EFI_SKU_ID                :   MetaFileParser._CommonParser,\r
555         MODEL_EFI_LIBRARY_INSTANCE      :   MetaFileParser._PathParser,\r
556         MODEL_EFI_LIBRARY_CLASS         :   MetaFileParser._PathParser,\r
557         MODEL_PCD_FIXED_AT_BUILD        :   _PcdParser,\r
558         MODEL_PCD_PATCHABLE_IN_MODULE   :   _PcdParser,\r
559         MODEL_PCD_FEATURE_FLAG          :   _PcdParser,\r
560         MODEL_PCD_DYNAMIC_DEFAULT       :   _PcdParser,\r
561         MODEL_PCD_DYNAMIC_HII           :   _PcdParser,\r
562         MODEL_PCD_DYNAMIC_VPD           :   _PcdParser,\r
563         MODEL_PCD_DYNAMIC_EX_DEFAULT    :   _PcdParser,\r
564         MODEL_PCD_DYNAMIC_EX_HII        :   _PcdParser,\r
565         MODEL_PCD_DYNAMIC_EX_VPD        :   _PcdParser,\r
566         MODEL_META_DATA_COMPONENT       :   _ComponentParser,\r
567         MODEL_META_DATA_BUILD_OPTION    :   _BuildOptionParser,\r
568         MODEL_UNKNOWN                   :   MetaFileParser._Skip,\r
569         MODEL_META_DATA_USER_EXTENSION  :   MetaFileParser._Skip,\r
570     }\r
571 \r
572 class DecParser(MetaFileParser):\r
573     DataType = {\r
574         TAB_DEC_DEFINES.upper()                     :   MODEL_META_DATA_HEADER,\r
575         TAB_INCLUDES.upper()                        :   MODEL_EFI_INCLUDE,\r
576         TAB_LIBRARY_CLASSES.upper()                 :   MODEL_EFI_LIBRARY_CLASS,\r
577         TAB_GUIDS.upper()                           :   MODEL_EFI_GUID,\r
578         TAB_PPIS.upper()                            :   MODEL_EFI_PPI,\r
579         TAB_PROTOCOLS.upper()                       :   MODEL_EFI_PROTOCOL,\r
580         TAB_PCDS_FIXED_AT_BUILD_NULL.upper()        :   MODEL_PCD_FIXED_AT_BUILD,\r
581         TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper()   :   MODEL_PCD_PATCHABLE_IN_MODULE,\r
582         TAB_PCDS_FEATURE_FLAG_NULL.upper()          :   MODEL_PCD_FEATURE_FLAG,\r
583         TAB_PCDS_DYNAMIC_NULL.upper()               :   MODEL_PCD_DYNAMIC,\r
584         TAB_PCDS_DYNAMIC_EX_NULL.upper()            :   MODEL_PCD_DYNAMIC_EX,\r
585     }\r
586 \r
587     def __init__(self, FilePath, FileId, FileType, Table, Macro={}):\r
588         MetaFileParser.__init__(self, FilePath, FileType, Table, Macro, -1)\r
589 \r
590     def Start(self):\r
591         try:\r
592             if self._Content == None:\r
593                 self._Content = open(self._FilePath, 'r').readlines()\r
594         except:\r
595             EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self._FilePath)\r
596 \r
597         for Index in range(0, len(self._Content)):\r
598             Line = CleanString(self._Content[Index])\r
599             # skip empty line\r
600             if Line == '':\r
601                 continue\r
602             self._CurrentLine = Line\r
603             self._LineIndex = Index\r
604 \r
605             # section header\r
606             if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:\r
607                 self._SectionHeaderParser()\r
608                 continue\r
609             elif Line.startswith('DEFINE '):\r
610                 self._MacroParser()\r
611                 continue\r
612 \r
613             # section content\r
614             self._ValueList = ['','','']\r
615             self._SectionParser[self._SectionType](self)\r
616             if self._ValueList == None:\r
617                 continue\r
618 \r
619             # \r
620             # Model, Value1, Value2, Value3, Value4, Value5, Arch, Platform, BelongsToFile=-1, \r
621             # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, BelongsToItem=-1, FeatureFlag='', \r
622             # Enabled=-1\r
623             # \r
624             for Arch, ModuleType in self._Scope:\r
625                 self._LastItem = self._Store(\r
626                     self._SectionType,\r
627                     self._ValueList[0],\r
628                     self._ValueList[1],\r
629                     self._ValueList[2],\r
630                     Arch,\r
631                     ModuleType,\r
632                     self._Owner,\r
633                     self._LineIndex+1,\r
634                     -1,\r
635                     self._LineIndex+1,\r
636                     -1,\r
637                     0\r
638                     )\r
639         self._Done()\r
640             \r
641     def _GuidParser(self):\r
642         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)\r
643         if len(TokenList) < 2:\r
644             EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",\r
645                             ExtraData=self._CurrentLine, File=self._FilePath, Line=self._LineIndex+1)\r
646         self._ValueList[0] = TokenList[0]\r
647         self._ValueList[1] = TokenList[1]\r
648 \r
649     def _PcdParser(self):\r
650         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)\r
651         self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)\r
652         self._ValueList[2] = TokenList[1]\r
653         if self._ValueList[0] == '' or self._ValueList[1] == '':\r
654             EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",\r
655                             ExtraData=self._CurrentLine, File=self._FilePath, Line=self._LineIndex+1)\r
656         if self._ValueList[2] == '':\r
657             EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",\r
658                             ExtraData=self._CurrentLine, File=self._FilePath, Line=self._LineIndex+1)\r
659 \r
660     _SectionParser = {\r
661         MODEL_META_DATA_HEADER          :   MetaFileParser._DefineParser,\r
662         MODEL_EFI_INCLUDE               :   MetaFileParser._PathParser,\r
663         MODEL_EFI_LIBRARY_CLASS         :   MetaFileParser._PathParser,\r
664         MODEL_EFI_GUID                  :   _GuidParser,\r
665         MODEL_EFI_PPI                   :   _GuidParser,\r
666         MODEL_EFI_PROTOCOL              :   _GuidParser,\r
667         MODEL_PCD_FIXED_AT_BUILD        :   _PcdParser,\r
668         MODEL_PCD_PATCHABLE_IN_MODULE   :   _PcdParser,\r
669         MODEL_PCD_FEATURE_FLAG          :   _PcdParser,\r
670         MODEL_PCD_DYNAMIC               :   _PcdParser,\r
671         MODEL_PCD_DYNAMIC_EX            :   _PcdParser,\r
672         MODEL_UNKNOWN                   :   MetaFileParser._Skip,\r
673         MODEL_META_DATA_USER_EXTENSION  :   MetaFileParser._Skip,\r
674     }\r
675 \r
676 ##\r
677 #\r
678 # This acts like the main() function for the script, unless it is 'import'ed into another\r
679 # script.\r
680 #\r
681 if __name__ == '__main__':\r
682     pass\r
683 \r