1. Add a checkpoint to ignore commented "[]" section
[people/mcb30/basetools.git] / Source / Python / Common / DecClassObject.py
1 ## @file\r
2 # This file is used to define each component of DEC file\r
3 #\r
4 # Copyright (c) 2007, 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 os\r
18 from String import *\r
19 from DataType import *\r
20 from Identification import *\r
21 from Dictionary import *\r
22 from CommonDataClass.PackageClass import *\r
23 from BuildToolError import *\r
24 \r
25 ## DecObject\r
26 #\r
27 # This class defined basic Dec object which is used by inheriting\r
28\r
29 # @param object:       Inherited from object class\r
30 #\r
31 class DecObject(object):\r
32     def __init__(self):\r
33         object.__init__()\r
34 \r
35 ## DecDefines\r
36 #\r
37 # This class defined basic Defines used in Dec object\r
38\r
39 # @param DecObject:        Inherited from DecObject class\r
40 #\r
41 # @var DefinesDictionary:  To store value for DefinesDictionary \r
42 #\r
43 class DecDefines(DecObject):\r
44     def __init__(self):\r
45         self.DefinesDictionary = {\r
46             #\r
47             # Required Fields\r
48             #\r
49             TAB_DEC_DEFINES_DEC_SPECIFICATION           : [''],\r
50             TAB_DEC_DEFINES_PACKAGE_NAME                : [''],\r
51             TAB_DEC_DEFINES_PACKAGE_GUID                : [''],\r
52             TAB_DEC_DEFINES_PACKAGE_VERSION             : ['']\r
53         }\r
54 \r
55 ## DecContents\r
56 #\r
57 # This class defined basic Contents used in Dec object\r
58\r
59 # @param DecObject:            Inherited from DecObject class\r
60 #\r
61 # @var Includes:               To store value for Includes\r
62 # @var Guids:                  To store value for Guids\r
63 # @var Protocols:              To store value for Protocols\r
64 # @var Ppis:                   To store value for Ppis\r
65 # @var LibraryClasses:         To store value for LibraryClasses\r
66 # @var PcdsFixedAtBuild:       To store value for PcdsFixedAtBuild\r
67 # @var PcdsPatchableInModule:  To store value for PcdsPatchableInModule\r
68 # @var PcdsFeatureFlag:        To store value for PcdsFeatureFlag\r
69 # @var PcdsDynamic:            To store value for PcdsDynamic\r
70 # @var PcdsDynamicEx:          To store value for PcdsDynamicEx\r
71 #\r
72 class DecContents(DecObject):\r
73     def __init__(self):\r
74         self.Includes = []\r
75         self.Guids = []\r
76         self.Protocols = []\r
77         self.Ppis = []\r
78         self.LibraryClasses = []\r
79         self.PcdsFixedAtBuild = []\r
80         self.PcdsPatchableInModule = []\r
81         self.PcdsFeatureFlag = []\r
82         self.PcdsDynamic = []\r
83         self.PcdsDynamicEx = []\r
84 \r
85 ## Dec\r
86 #\r
87 # This class defined the structure used in Dec object\r
88\r
89 # @param DecObject:         Inherited from DecObject class\r
90 # @param Filename:          Input value for Filename of Dec file, default is None\r
91 # @param IsMergeAllArches:  Input value for IsMergeAllArches\r
92 #                           True is to merge all arches\r
93 #                           Fales is not to merge all arches\r
94 #                           default is False\r
95 # @param IsToPackage:       Input value for IsToPackage\r
96 #                           True is to transfer to PackageObject automatically\r
97 #                           False is not to transfer to PackageObject automatically\r
98 #                           default is False\r
99 # @param WorkspaceDir:      Input value for current workspace directory, default is None\r
100 #\r
101 # @var Identification:      To store value for Identification, it is a structure as Identification\r
102 # @var Defines:             To store value for Defines, it is a structure as DecDefines\r
103 # @var UserExtensions:      To store value for UserExtensions\r
104 # @var Package:             To store value for Package, it is a structure as PackageClass\r
105 # @var WorkspaceDir:        To store value for WorkspaceDir\r
106 # @var Contents:            To store value for Contents, it is a structure as DecContents\r
107 # @var KeyList:             To store value for KeyList, a list for all Keys used in Dec\r
108 #\r
109 class Dec(DecObject):\r
110     def __init__(self, Filename = None, IsMergeAllArches = False, IsToPackage = False, WorkspaceDir = None):\r
111         self.Identification = Identification()\r
112         self.Defines = DecDefines()\r
113         self.UserExtensions = ''\r
114         self.Package = PackageClass()\r
115         self.WorkspaceDir = WorkspaceDir\r
116         \r
117         self.Contents = {}\r
118         for Arch in DataType.ARCH_LIST_FULL:\r
119             self.Contents[Arch] = DecContents()\r
120         \r
121         self.KeyList = [\r
122             TAB_INCLUDES, TAB_GUIDS, TAB_PROTOCOLS, TAB_PPIS, TAB_LIBRARY_CLASSES, \\r
123             TAB_PCDS_FIXED_AT_BUILD_NULL, TAB_PCDS_PATCHABLE_IN_MODULE_NULL, TAB_PCDS_FEATURE_FLAG_NULL, \\r
124             TAB_PCDS_DYNAMIC_NULL, TAB_PCDS_DYNAMIC_EX_NULL\r
125         ]\r
126     \r
127         #\r
128         # Load Dec file if filename is not None\r
129         #\r
130         if Filename != None:\r
131             self.LoadDecFile(Filename)\r
132         \r
133         #\r
134         # Merge contents of Dec from all arches if IsMergeAllArches is True\r
135         #\r
136         if IsMergeAllArches:\r
137             self.MergeAllArches()\r
138         \r
139         #\r
140         # Transfer to Package Object if IsToPackage is True\r
141         #\r
142         if IsToPackage:\r
143             self.DecToPackage()\r
144     \r
145     ## Parse Dec file\r
146     #\r
147     # Go through input lines one by one to find the value defined in Key section.\r
148     # Save them to KeyField\r
149     #\r
150     # @param Lines:     Lines need to be parsed\r
151     # @param Key:       The key value of the section to be located\r
152     # @param KeyField:  To save the found contents\r
153     #\r
154     def ParseDec(self, Lines, Key, KeyField):\r
155         newKey = SplitModuleType(Key)\r
156         if newKey[0].upper().find(DataType.TAB_LIBRARY_CLASSES.upper()) != -1:\r
157             GetLibraryClassesWithModuleType(Lines, Key, KeyField, TAB_COMMENT_SPLIT)\r
158         else:\r
159             GetMultipleValuesOfKeyFromLines(Lines, Key, KeyField, TAB_COMMENT_SPLIT)\r
160 \r
161     ## Merge contents of Dec from all arches\r
162     #\r
163     # Find the contents defined in all arches and merge them to all\r
164     #   \r
165     def MergeAllArches(self):\r
166         for Key in self.KeyList:\r
167             for Arch in DataType.ARCH_LIST:\r
168                 Command = "self.Contents[Arch]." + Key + ".extend(" + "self.Contents['" + DataType.TAB_ARCH_COMMON + "']." + Key + ")"\r
169                 eval(Command)\r
170 \r
171     ## Load Dec file\r
172     #\r
173     # Load the file if it exists\r
174     #\r
175     # @param Filename:  Input value for filename of Dec file\r
176     #\r
177     def LoadDecFile(self, Filename):\r
178         (Filepath, Name) = os.path.split(Filename)\r
179         self.Identification.FileName = Name\r
180         self.Identification.FileFullPath = Filename\r
181         self.Identification.FileRelativePath = Filepath\r
182         \r
183         F = open(Filename, 'r').read()\r
184         F = PreCheck(Filename, F, self.KeyList)\r
185         Sects = F.split(DataType.TAB_SECTION_START)\r
186         for Sect in Sects:\r
187             TabList = GetSplitValueList(Sect.split(TAB_SECTION_END, 1)[0], DataType.TAB_COMMA_SPLIT)\r
188             for Tab in TabList:\r
189                 if Tab.upper() == TAB_INF_DEFINES.upper():\r
190                     GetSingleValueOfKeyFromLines(Sect, self.Defines.DefinesDictionary, TAB_COMMENT_SPLIT, TAB_EQUAL_SPLIT, True, TAB_VALUE_SPLIT)\r
191                     continue\r
192                 for Arch in DataType.ARCH_LIST_FULL + [DataType.TAB_ARCH_NULL]:\r
193                     for Key in self.KeyList:\r
194                         if Arch != DataType.TAB_ARCH_NULL:\r
195                             Target = (Key + DataType.TAB_SPLIT + Arch).upper()\r
196                         else:\r
197                             Target = Key.upper()\r
198                         if Tab.upper() == Target:\r
199                             if Arch != DataType.TAB_ARCH_NULL:\r
200                                 Command = 'self.ParseDec(Sect, Tab, self.Contents[Arch].' + Key + ')'\r
201                                 eval(Command)\r
202                                 continue\r
203                             else:\r
204                                 Command = "self.ParseDec(Sect, Tab, self.Contents['" + DataType.TAB_ARCH_COMMON + "']." + Key + ')'\r
205                                 eval(Command)\r
206                                 continue\r
207         #EndFor\r
208 \r
209     ## Transfer to Package Object\r
210     # \r
211     # Transfer all contents of a Dec file to a standard Package Object\r
212     #\r
213     def DecToPackage(self):\r
214         #\r
215         # Get value for Header\r
216         #\r
217         self.Package.Header.Name = self.Defines.DefinesDictionary[TAB_DEC_DEFINES_PACKAGE_NAME][0]\r
218         self.Package.Header.Guid = self.Defines.DefinesDictionary[TAB_DEC_DEFINES_PACKAGE_GUID][0]\r
219         self.Package.Header.Version = self.Defines.DefinesDictionary[TAB_DEC_DEFINES_PACKAGE_VERSION][0]\r
220         self.Package.Header.FileName = self.Identification.FileName\r
221         self.Package.Header.FullPath = self.Identification.FileFullPath\r
222         self.Package.Header.DecSpecification = self.Defines.DefinesDictionary[TAB_DEC_DEFINES_DEC_SPECIFICATION][0]\r
223         File = self.Package.Header.FullPath\r
224         \r
225         #\r
226         # Includes\r
227         # <IncludeDirectory>\r
228         #\r
229         Includes = {}\r
230         for Arch in DataType.ARCH_LIST:\r
231             for Item in self.Contents[Arch].Includes:\r
232                 MergeArches(Includes, Item, Arch)\r
233         for Key in Includes.keys():\r
234             Include = IncludeClass()\r
235             Include.FilePath = Key\r
236             Include.SupArchList = Includes[Key]\r
237             self.Package.Includes.append(Include)\r
238             \r
239         #\r
240         # Guids\r
241         # <CName>=<GuidValue>\r
242         #\r
243         Guids = {}\r
244         for Arch in DataType.ARCH_LIST:\r
245             for Item in self.Contents[Arch].Guids:\r
246                 List = GetSplitValueList(Item, DataType.TAB_EQUAL_SPLIT)\r
247                 if len(List) != 2:\r
248                     RaiseParserError(Item, 'Guids', File, '<CName>=<GuidValue>')\r
249                 else:\r
250                     MergeArches(Guids, (List[0], List[1]), Arch)\r
251         for Key in Guids.keys():\r
252             Guid = GuidClass()\r
253             Guid.CName = Key[0]\r
254             Guid.Guid = Key[1]\r
255             Guid.SupArchList = Guids[Key]\r
256             self.Package.GuidDeclarations.append(Guid)\r
257 \r
258         # \r
259         # Protocols\r
260         # <CName>=<GuidValue>\r
261         #\r
262         Protocols = {}\r
263         for Arch in DataType.ARCH_LIST:\r
264             for Item in self.Contents[Arch].Protocols:\r
265                 List = GetSplitValueList(Item, DataType.TAB_EQUAL_SPLIT)\r
266                 if len(List) != 2:\r
267                     RaiseParserError(Item, 'Protocols', File, '<CName>=<GuidValue>')\r
268                 else:\r
269                     MergeArches(Protocols, (List[0], List[1]), Arch)\r
270         for Key in Protocols.keys():\r
271             Protocol = ProtocolClass()\r
272             Protocol.CName = Key[0]\r
273             Protocol.Guid = Key[1]\r
274             Protocol.SupArchList = Protocols[Key]\r
275             self.Package.ProtocolDeclarations.append(Protocol)\r
276         \r
277         #\r
278         # Ppis\r
279         # <CName>=<GuidValue>\r
280         #\r
281         Ppis = {}\r
282         for Arch in DataType.ARCH_LIST:\r
283             for Item in self.Contents[Arch].Ppis:\r
284                 List = GetSplitValueList(Item, DataType.TAB_EQUAL_SPLIT)\r
285                 if len(List) != 2:\r
286                     RaiseParserError(Item, 'Ppis', File, '<CName>=<GuidValue>')\r
287                 else:\r
288                     MergeArches(Ppis, (List[0], List[1]), Arch)\r
289         for Key in Ppis.keys():\r
290             Ppi = PpiClass()\r
291             Ppi.CName = Key[0]\r
292             Ppi.Guid = Key[1]\r
293             Ppi.SupArchList = Ppis[Key]\r
294             self.Package.PpiDeclarations.append(Ppi)\r
295             \r
296         #\r
297         # LibraryClasses\r
298         # <LibraryClassName>|<LibraryClassInstance>\r
299         #\r
300         LibraryClasses = {}\r
301         for Arch in DataType.ARCH_LIST:\r
302             for Item in self.Contents[Arch].LibraryClasses:\r
303                 List = GetSplitValueList(Item[0], DataType.TAB_VALUE_SPLIT)\r
304                 if len(List) != 2:\r
305                     RaiseParserError(Item[0], 'LibraryClasses', File, '<LibraryClassName>|<LibraryClassInstanceFilename>')\r
306                 else:\r
307                     CheckFileExist(self.WorkspaceDir, os.path.join(self.Identification.FileRelativePath, List[1]), File, 'LibraryClasses', Item[0])\r
308                     if Item[1] == ['']:\r
309                             Item[1] = DataType.SUP_MODULE_LIST\r
310                     MergeArches(LibraryClasses, (List[0], List[1]) + tuple(Item[1]), Arch)\r
311         for Key in LibraryClasses.keys():\r
312             LibraryClass = LibraryClassClass()\r
313             LibraryClass.LibraryClass = Key[0]\r
314             LibraryClass.RecommendedInstance = Key[1]\r
315             LibraryClass.SupModuleList = list(Key[2:])\r
316             LibraryClass.SupArchList = LibraryClasses[Key]\r
317             self.Package.LibraryClassDeclarations.append(LibraryClass)\r
318         \r
319         #\r
320         # Pcds\r
321         # <TokenSpcCName>.<TokenCName>|<Value>|<DatumType>|<Token>\r
322         #\r
323         Pcds = {}\r
324         for Arch in DataType.ARCH_LIST:\r
325             for Item in self.Contents[Arch].PcdsFixedAtBuild:\r
326                 MergeArches(Pcds, self.GetPcdOfDec(Item, TAB_PCDS_FIXED_AT_BUILD, File), Arch)\r
327             \r
328             for Item in self.Contents[Arch].PcdsPatchableInModule:\r
329                 MergeArches(Pcds, self.GetPcdOfDec(Item, TAB_PCDS_PATCHABLE_IN_MODULE, File), Arch)\r
330             \r
331             for Item in self.Contents[Arch].PcdsFeatureFlag:\r
332                 MergeArches(Pcds, self.GetPcdOfDec(Item, TAB_PCDS_FEATURE_FLAG, File), Arch)\r
333             \r
334             for Item in self.Contents[Arch].PcdsDynamicEx:\r
335                 MergeArches(Pcds, self.GetPcdOfDec(Item, TAB_PCDS_DYNAMIC_EX, File), Arch)\r
336             \r
337             for Item in self.Contents[Arch].PcdsDynamic:\r
338                 MergeArches(Pcds, self.GetPcdOfDec(Item, TAB_PCDS_DYNAMIC, File), Arch)\r
339 \r
340         for Key in Pcds.keys():\r
341             Pcd = PcdClass()\r
342             Pcd.CName = Key[1]\r
343             Pcd.Token = Key[4]\r
344             Pcd.TokenSpaceGuidCName = Key[0]\r
345             Pcd.DatumType = Key[3]\r
346             Pcd.DefaultValue = Key[2]\r
347             Pcd.ItemType = Key[5]\r
348             Pcd.SupArchList = Pcds[Key]\r
349             self.Package.PcdDeclarations.append(Pcd)\r
350     \r
351     ## Get Pcd Values of Dec\r
352     #\r
353     # Get Pcd of Dec as <TokenSpcCName>.<TokenCName>|<Value>|<DatumType>|<Token>\r
354     # @retval (TokenSpcCName, TokenCName, Value, DatumType, Token, ItemType) Formatted Pcd Item\r
355     #\r
356     def GetPcdOfDec(self, Item, Type, File):\r
357         Format = '<TokenSpaceGuidCName>.<PcdCName>|<Value>|<DatumType>|<Token>'\r
358         List = GetSplitValueList(Item)\r
359         if len(List) != 4:\r
360             RaiseParserError(Item, 'Pcds' + Type, File, Format)\r
361         TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT)\r
362         if len(TokenInfo) != 2:\r
363             RaiseParserError(Item, 'Pcds' + Type, File, Format)\r
364         \r
365         return (TokenInfo[0], TokenInfo[1], List[1], List[2], List[3], Type)\r
366     \r
367     ## Show detailed information of Dec\r
368     #\r
369     # Print all members and their values of Dec class\r
370     #\r
371     def ShowDec(self):\r
372         print TAB_SECTION_START + TAB_INF_DEFINES + TAB_SECTION_END\r
373         printDict(self.Defines.DefinesDictionary)\r
374 \r
375         for key in self.KeyList:\r
376             for arch in DataType.ARCH_LIST_FULL:\r
377                 Command = "printList(TAB_SECTION_START + '" + \\r
378                                     key + DataType.TAB_SPLIT + arch + \\r
379                                     "' + TAB_SECTION_END, self.Contents[arch]." + key + ')'\r
380                 eval(Command)\r
381     \r
382     ## Show detailed information of Package\r
383     #\r
384     # Print all members and their values of Package class\r
385     #\r
386     def ShowPackage(self):\r
387         M = self.Package\r
388         print 'Filename =', M.Header.FileName\r
389         print 'FullPath =', M.Header.FullPath\r
390         print 'BaseName =', M.Header.Name\r
391         print 'Guid =', M.Header.Guid\r
392         print 'Version =', M.Header.Version\r
393         print 'DecSpecification =', M.Header.DecSpecification\r
394         print '\nIncludes =', M.Includes\r
395         for Item in M.Includes:\r
396             print Item.FilePath, Item.SupArchList\r
397         print '\nGuids =', M.GuidDeclarations\r
398         for Item in M.GuidDeclarations:\r
399             print Item.CName, Item.Guid, Item.SupArchList\r
400         print '\nProtocols =', M.ProtocolDeclarations\r
401         for Item in M.ProtocolDeclarations:\r
402             print Item.CName, Item.Guid, Item.SupArchList\r
403         print '\nPpis =', M.PpiDeclarations\r
404         for Item in M.PpiDeclarations:\r
405             print Item.CName, Item.Guid, Item.SupArchList\r
406         print '\nLibraryClasses =', M.LibraryClassDeclarations\r
407         for Item in M.LibraryClassDeclarations:\r
408             print Item.LibraryClass, Item.RecommendedInstance, Item.SupModuleList, Item.SupArchList\r
409         print '\nPcds =', M.PcdDeclarations\r
410         for Item in M.PcdDeclarations:\r
411             print 'CName=', Item.CName, 'TokenSpaceGuidCName=', Item.TokenSpaceGuidCName, 'DefaultValue=', Item.DefaultValue, 'ItemType=', Item.ItemType, 'Token=', Item.Token, 'DatumType=', Item.DatumType, Item.SupArchList\r
412 \r
413 ##\r
414 #\r
415 # This acts like the main() function for the script, unless it is 'import'ed into another\r
416 # script.\r
417 #\r
418 if __name__ == '__main__':\r
419     W = os.getenv('WORKSPACE')\r
420     F = os.path.join(W, 'Nt32Pkg/Nt32Pkg.dec')\r
421     P = Dec(os.path.normpath(F), True, True, W)\r
422     P.ShowPackage()\r