1. Add !include statement support in .dsc file
[people/mcb30/basetools.git] / Source / Python / Common / DecClassObject.py
1 # Copyright (c) 2007, Intel Corporation\r
2 # All rights reserved. This program and the accompanying materials\r
3 # are licensed and made available under the terms and conditions of the BSD License\r
4 # which accompanies this distribution.    The full text of the license may be found at\r
5 # http://opensource.org/licenses/bsd-license.php\r
6 #\r
7 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
8 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
9 \r
10 #\r
11 #This file is used to define each component of DEC file\r
12 #\r
13 \r
14 import os\r
15 from String import *\r
16 from DataType import *\r
17 from Identification import *\r
18 from Dictionary import *\r
19 from CommonDataClass.PackageClass import *\r
20 from BuildToolError import *\r
21 \r
22 class DecObject(object):\r
23     def __init__(self):\r
24         object.__init__()\r
25 \r
26 class DecDefines(DecObject):\r
27     def __init__(self):\r
28         self.DefinesDictionary = {\r
29             #Req\r
30             TAB_DEC_DEFINES_DEC_SPECIFICATION           : [''],\r
31             TAB_DEC_DEFINES_PACKAGE_NAME                : [''],\r
32             TAB_DEC_DEFINES_PACKAGE_GUID                : [''],\r
33             TAB_DEC_DEFINES_PACKAGE_VERSION             : ['']\r
34         }\r
35         \r
36 class DecContents(DecObject):\r
37     def __init__(self):\r
38         self.Includes = []\r
39         self.Guids = []\r
40         self.Protocols = []\r
41         self.Ppis = []\r
42         self.LibraryClasses = []\r
43         self.PcdsFixedAtBuild = []\r
44         self.PcdsPatchableInModule = []\r
45         self.PcdsFeatureFlag = []\r
46         self.PcdsDynamic = []\r
47         self.PcdsDynamicEx = []\r
48 \r
49 class Dec(DecObject):\r
50     def __init__(self, filename = None, isMergeAllArches = False, isToPackage = False, WorkspaceDir = None):\r
51         self.Identification = Identification()\r
52         self.Defines = DecDefines()\r
53         self.UserExtensions = ''\r
54         self.Package = PackageClass()\r
55         self.WorkspaceDir = WorkspaceDir\r
56         \r
57         self.Contents = {}\r
58         for key in DataType.ARCH_LIST_FULL:\r
59             self.Contents[key] = DecContents()\r
60         \r
61         self.KeyList = [\r
62             TAB_INCLUDES, TAB_GUIDS, TAB_PROTOCOLS, TAB_PPIS, TAB_LIBRARY_CLASSES, \\r
63             TAB_PCDS_FIXED_AT_BUILD_NULL, TAB_PCDS_PATCHABLE_IN_MODULE_NULL, TAB_PCDS_FEATURE_FLAG_NULL, \\r
64             TAB_PCDS_DYNAMIC_NULL, TAB_PCDS_DYNAMIC_EX_NULL\r
65         ]\r
66     \r
67         if filename != None:\r
68             self.LoadDecFile(filename)\r
69             \r
70         if isMergeAllArches:\r
71             self.MergeAllArches()\r
72         \r
73         if isToPackage:\r
74             self.DecToPackage()\r
75     \r
76     def ParseDec(self, Lines, Key, KeyField):\r
77         newKey = SplitModuleType(Key)\r
78         if newKey[0].upper().find(DataType.TAB_LIBRARY_CLASSES.upper()) != -1:\r
79             GetLibraryClassesWithModuleType(Lines, Key, KeyField, TAB_COMMENT_SPLIT)\r
80         else:\r
81             GetMultipleValuesOfKeyFromLines(Lines, Key, KeyField, TAB_COMMENT_SPLIT)\r
82             \r
83     def MergeAllArches(self):\r
84         for key in self.KeyList:\r
85             for arch in DataType.ARCH_LIST:\r
86                 Command = "self.Contents[arch]." + key + ".extend(" + "self.Contents['" + DataType.TAB_ARCH_COMMON + "']." + key + ")"\r
87                 eval(Command)\r
88 \r
89     def LoadDecFile(self, Filename):\r
90         (Filepath, Name) = os.path.split(Filename)\r
91         self.Identification.FileName = Name\r
92         self.Identification.FileFullPath = Filename\r
93         self.Identification.FileRelativePath = Filepath\r
94         \r
95         F = open(Filename, 'r').read()\r
96         PreCheck(Filename, F, self.KeyList)\r
97         Sects = F.split(DataType.TAB_SECTION_START)\r
98         for Sect in Sects:\r
99             TabList = GetSplitValueList(Sect.split(TAB_SECTION_END, 1)[0], DataType.TAB_COMMA_SPLIT)\r
100             for Tab in TabList:\r
101                 if Tab.upper() == TAB_INF_DEFINES.upper():\r
102                     GetSingleValueOfKeyFromLines(Sect, self.Defines.DefinesDictionary, TAB_COMMENT_SPLIT, TAB_EQUAL_SPLIT, True, TAB_VALUE_SPLIT)\r
103                     continue\r
104                 for Arch in DataType.ARCH_LIST_FULL + [DataType.TAB_ARCH_NULL]:\r
105                     for Key in self.KeyList:\r
106                         if Arch != DataType.TAB_ARCH_NULL:\r
107                             Target = (Key + DataType.TAB_SPLIT + Arch).upper()\r
108                         else:\r
109                             Target = Key.upper()\r
110                         if Tab.upper() == Target:\r
111                             if Arch != DataType.TAB_ARCH_NULL:\r
112                                 Command = 'self.ParseDec(Sect, Tab, self.Contents[Arch].' + Key + ')'\r
113                                 eval(Command)\r
114                                 continue\r
115                             else:\r
116                                 Command = "self.ParseDec(Sect, Tab, self.Contents['" + DataType.TAB_ARCH_COMMON + "']." + Key + ')'\r
117                                 eval(Command)\r
118                                 continue\r
119         #EndFor\r
120 \r
121     def DecToPackage(self):\r
122         #\r
123         # Get value for Header\r
124         #\r
125         self.Package.Header.Name = self.Defines.DefinesDictionary[TAB_DEC_DEFINES_PACKAGE_NAME][0]\r
126         self.Package.Header.Guid = self.Defines.DefinesDictionary[TAB_DEC_DEFINES_PACKAGE_GUID][0]\r
127         self.Package.Header.Version = self.Defines.DefinesDictionary[TAB_DEC_DEFINES_PACKAGE_VERSION][0]\r
128         self.Package.Header.FileName = self.Identification.FileName\r
129         self.Package.Header.FullPath = self.Identification.FileFullPath\r
130         self.Package.Header.DecSpecification = self.Defines.DefinesDictionary[TAB_DEC_DEFINES_DEC_SPECIFICATION][0]\r
131         \r
132         #Includes\r
133         Includes = {}\r
134         for Arch in DataType.ARCH_LIST:\r
135             for Item in self.Contents[Arch].Includes:\r
136                 MergeArches(Includes, Item, Arch)\r
137         for Key in Includes.keys():\r
138             Include = IncludeClass()\r
139             Include.FilePath = Key\r
140             Include.SupArchList = Includes[Key]\r
141             self.Package.Includes.append(Include)\r
142             \r
143         #Guids\r
144         Guids = {}\r
145         for Arch in DataType.ARCH_LIST:\r
146             for Item in self.Contents[Arch].Guids:\r
147                 List = GetSplitValueList(Item, DataType.TAB_EQUAL_SPLIT)\r
148                 if len(List) != 2:\r
149                     ErrorMsg = "Wrong statement '%s' found in section Guids in file '%s', correct format is '<CName>=<GuidValue>'" % (Item, self.Package.Header.FullPath) \r
150                     raise ParserError(PARSER_ERROR, msg = ErrorMsg)\r
151                 else:\r
152                     MergeArches(Guids, (List[0], List[1]), Arch)\r
153         for Key in Guids.keys():\r
154             Guid = GuidClass()\r
155             Guid.CName = Key[0]\r
156             Guid.Guid = Key[1]\r
157             Guid.SupArchList = Guids[Key]\r
158             self.Package.GuidDeclarations.append(Guid)\r
159 \r
160         #Protocols\r
161         Protocols = {}\r
162         for Arch in DataType.ARCH_LIST:\r
163             for Item in self.Contents[Arch].Protocols:\r
164                 List = GetSplitValueList(Item, DataType.TAB_EQUAL_SPLIT)\r
165                 if len(List) != 2:\r
166                     ErrorMsg = "Wrong statement '%s' found in section Protocols in file '%s', correct format is '<CName>=<GuidValue>'" % (Item, self.Package.Header.FullPath) \r
167                     raise ParserError(PARSER_ERROR, msg = ErrorMsg)\r
168                 else:\r
169                     MergeArches(Protocols, (List[0], List[1]), Arch)\r
170         for Key in Protocols.keys():\r
171             Protocol = ProtocolClass()\r
172             Protocol.CName = Key[0]\r
173             Protocol.Guid = Key[1]\r
174             Protocol.SupArchList = Protocols[Key]\r
175             self.Package.ProtocolDeclarations.append(Protocol)\r
176         \r
177         #Ppis\r
178         Ppis = {}\r
179         for Arch in DataType.ARCH_LIST:\r
180             for Item in self.Contents[Arch].Ppis:\r
181                 List = GetSplitValueList(Item, DataType.TAB_EQUAL_SPLIT)\r
182                 if len(List) != 2:\r
183                     ErrorMsg = "Wrong statement '%s' found in section Ppis in file '%s', correct format is '<CName>=<GuidValue>'" % (Item, self.Package.Header.FullPath) \r
184                     raise ParserError(PARSER_ERROR, msg = ErrorMsg)\r
185                 else:\r
186                     MergeArches(Ppis, (List[0], List[1]), Arch)\r
187         for Key in Ppis.keys():\r
188             Ppi = PpiClass()\r
189             Ppi.CName = Key[0]\r
190             Ppi.Guid = Key[1]\r
191             Ppi.SupArchList = Ppis[Key]\r
192             self.Package.PpiDeclarations.append(Ppi)\r
193             \r
194         #LibraryClasses\r
195         LibraryClasses = {}\r
196         for Arch in DataType.ARCH_LIST:\r
197             for Item in self.Contents[Arch].LibraryClasses:\r
198                 List = GetSplitValueList(Item[0], DataType.TAB_VALUE_SPLIT)\r
199                 if len(List) != 2:\r
200                     ErrorMsg = "Wrong statement '%s' found in section LibraryClasses in file '%s', correct format is '<CName>=<GuidValue>'" % (Item, self.Package.Header.FullPath) \r
201                     raise ParserError(PARSER_ERROR, msg = ErrorMsg)\r
202                 else:\r
203                     CheckFileExist(self.WorkspaceDir, os.path.join(self.Identification.FileRelativePath, List[1]), self.Package.Header.FullPath, 'LibraryClasses', Item[0])\r
204                     if Item[1] == ['']:\r
205                             Item[1] = DataType.SUP_MODULE_LIST\r
206                     MergeArches(LibraryClasses, (List[0], List[1]) + tuple(Item[1]), Arch)\r
207         for Key in LibraryClasses.keys():\r
208             LibraryClass = LibraryClassClass()\r
209             LibraryClass.LibraryClass = Key[0]\r
210             LibraryClass.RecommendedInstance = Key[1]\r
211             LibraryClass.SupModuleList = list(Key[2:])\r
212             LibraryClass.SupArchList = LibraryClasses[Key]\r
213             self.Package.LibraryClassDeclarations.append(LibraryClass)\r
214         \r
215         #Pcds\r
216         Pcds = {}\r
217         for Arch in DataType.ARCH_LIST:\r
218             for Item in self.Contents[Arch].PcdsFixedAtBuild:\r
219                 List = GetSplitValueList(Item)\r
220                 if len(List) != 4:\r
221                     ErrorMsg = "Wrong statement '%s' found in section PcdsFixedAtBuild in file '%s', correct format is '<TokenSpcCName>.<TokenCName>|<Token>|<Value>|<DatumType>'" % (Item, self.Package.Header.FullPath) \r
222                     raise ParserError(PARSER_ERROR, msg = ErrorMsg)\r
223                 TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT)\r
224                 if len(TokenInfo) != 2:\r
225                     ErrorMsg = "Wrong statement '%s' found in section PcdsFixedAtBuild in file '%s', correct format is '<TokenSpcCName>.<TokenCName>|<Token>|<Value>|<DatumType>'" % (Item[0], Type, self.Platform.Header.FullPath) \r
226                     raise ParserError(PARSER_ERROR, msg = ErrorMsg)\r
227                 MergeArches(Pcds, (TokenInfo[0], TokenInfo[1], List[1], List[2], List[3], TAB_PCDS_FIXED_AT_BUILD), Arch)\r
228             \r
229             for Item in self.Contents[Arch].PcdsPatchableInModule:\r
230                 List = GetSplitValueList(Item)\r
231                 if len(List) != 4:\r
232                     ErrorMsg = "Wrong statement '%s' found in section PcdsPatchableInModule in file '%s', correct format is '<TokenSpcCName>.<TokenCName>|<Token>|<Value>|<DatumType>'" % (Item, self.Package.Header.FullPath) \r
233                     raise ParserError(PARSER_ERROR, msg = ErrorMsg)\r
234                 TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT)\r
235                 if len(TokenInfo) != 2:\r
236                     ErrorMsg = "Wrong statement '%s' found in section PcdsPatchableInModule in file '%s', correct format is '<TokenSpcCName>.<TokenCName>|<Token>|<Value>|<DatumType>'" % (Item[0], Type, self.Platform.Header.FullPath) \r
237                     raise ParserError(PARSER_ERROR, msg = ErrorMsg)\r
238                 MergeArches(Pcds, (TokenInfo[0], TokenInfo[1], List[1], List[2], List[3], TAB_PCDS_PATCHABLE_IN_MODULE), Arch)\r
239             \r
240             for Item in self.Contents[Arch].PcdsFeatureFlag:\r
241                 List = GetSplitValueList(Item)\r
242                 if len(List) != 4:\r
243                     ErrorMsg = "Wrong statement '%s' found in section PcdsFeatureFlag in file '%s', correct format is '<TokenSpcCName>.<TokenCName>|<Token>|<Value>|<DatumType>'" % (Item, self.Package.Header.FullPath) \r
244                     raise ParserError(PARSER_ERROR, msg = ErrorMsg)\r
245                 TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT)\r
246                 if len(TokenInfo) != 2:\r
247                     ErrorMsg = "Wrong statement '%s' found in section PcdsFeatureFlag in file '%s', correct format is '<TokenSpcCName>.<TokenCName>|<Token>|<Value>|<DatumType>'" % (Item[0], Type, self.Platform.Header.FullPath) \r
248                     raise ParserError(PARSER_ERROR, msg = ErrorMsg)\r
249                 MergeArches(Pcds, (TokenInfo[0], TokenInfo[1], List[1], List[2], List[3], TAB_PCDS_FEATURE_FLAG), Arch)\r
250             \r
251             for Item in self.Contents[Arch].PcdsDynamicEx:\r
252                 List = GetSplitValueList(Item)\r
253                 if len(List) != 4:\r
254                     ErrorMsg = "Wrong statement '%s' found in section PcdsDynamicEx in file '%s', correct format is '<TokenSpcCName>.<TokenCName>|<Token>|<Value>|<DatumType>'" % (Item, self.Package.Header.FullPath) \r
255                     raise ParserError(PARSER_ERROR, msg = ErrorMsg)\r
256                 TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT)\r
257                 if len(TokenInfo) != 2:\r
258                     ErrorMsg = "Wrong statement '%s' found in section PcdsDynamicEx in file '%s', correct format is '<TokenSpcCName>.<TokenCName>|<Token>|<Value>|<DatumType>'" % (Item[0], Type, self.Platform.Header.FullPath) \r
259                     raise ParserError(PARSER_ERROR, msg = ErrorMsg)\r
260                 MergeArches(Pcds, (TokenInfo[0], TokenInfo[1], List[1], List[2], List[3], TAB_PCDS_DYNAMIC_EX), Arch)\r
261             \r
262             for Item in self.Contents[Arch].PcdsDynamic:\r
263                 List = GetSplitValueList(Item)\r
264                 if len(List) != 4:\r
265                     ErrorMsg = "Wrong statement '%s' found in section PcdsDynamic in file '%s', correct format is '<TokenSpcCName>.<TokenCName>|<Token>|<Value>|<DatumType>'" % (Item, self.Package.Header.FullPath) \r
266                     raise ParserError(PARSER_ERROR, msg = ErrorMsg)\r
267                 TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT)\r
268                 if len(TokenInfo) != 2:\r
269                     ErrorMsg = "Wrong statement '%s' found in section PcdsDynamic in file '%s', correct format is '<TokenSpcCName>.<TokenCName>|<Token>|<Value>|<DatumType>'" % (Item[0], Type, self.Platform.Header.FullPath) \r
270                     raise ParserError(PARSER_ERROR, msg = ErrorMsg)\r
271                 MergeArches(Pcds, (TokenInfo[0], TokenInfo[1], List[1], List[2], List[3], TAB_PCDS_DYNAMIC), Arch)\r
272         for Key in Pcds.keys():\r
273             Pcd = PcdClass()\r
274             Pcd.CName = Key[1]\r
275             Pcd.Token = Key[4]\r
276             Pcd.TokenSpaceGuidCName = Key[0]\r
277             Pcd.DatumType = Key[3]\r
278             Pcd.DefaultValue = Key[2]\r
279             Pcd.ItemType = Key[5]\r
280             Pcd.SupArchList = Pcds[Key]\r
281             self.Package.PcdDeclarations.append(Pcd)\r
282     \r
283     def ShowDec(self):\r
284         print TAB_SECTION_START + TAB_INF_DEFINES + TAB_SECTION_END\r
285         printDict(self.Defines.DefinesDictionary)\r
286 \r
287         for key in self.KeyList:\r
288             for arch in DataType.ARCH_LIST_FULL:\r
289                 Command = "printList(TAB_SECTION_START + '" + \\r
290                                     key + DataType.TAB_SPLIT + arch + \\r
291                                     "' + TAB_SECTION_END, self.Contents[arch]." + key + ')'\r
292                 eval(Command)\r
293     \r
294     def ShowPackage(self):\r
295         m = self.Package\r
296         print 'Filename =', m.Header.FileName\r
297         print 'FullPath =', m.Header.FullPath\r
298         print 'BaseName =', m.Header.Name\r
299         print 'Guid =', m.Header.Guid\r
300         print 'Version =', m.Header.Version\r
301         print 'DecSpecification =', m.Header.DecSpecification\r
302         print '\nIncludes =', m.Includes\r
303         for Item in m.Includes:\r
304             print Item.FilePath, Item.SupArchList\r
305         print '\nGuids =', m.GuidDeclarations\r
306         for Item in m.GuidDeclarations:\r
307             print Item.CName, Item.Guid, Item.SupArchList\r
308         print '\nProtocols =', m.ProtocolDeclarations\r
309         for Item in m.ProtocolDeclarations:\r
310             print Item.CName, Item.Guid, Item.SupArchList\r
311         print '\nPpis =', m.PpiDeclarations\r
312         for Item in m.PpiDeclarations:\r
313             print Item.CName, Item.Guid, Item.SupArchList\r
314         print '\nLibraryClasses =', m.LibraryClassDeclarations\r
315         for Item in m.LibraryClassDeclarations:\r
316             print Item.LibraryClass, Item.RecommendedInstance, Item.SupModuleList, Item.SupArchList\r
317         print '\nPcds =', m.PcdDeclarations\r
318         for Item in m.PcdDeclarations:\r
319             print 'CName=', Item.CName, 'TokenSpaceGuidCName=', Item.TokenSpaceGuidCName, 'DefaultValue=', Item.DefaultValue, 'ItemType=', Item.ItemType, 'Token=', Item.Token, 'DatumType=', Item.DatumType, Item.SupArchList\r
320 \r
321 if __name__ == '__main__':\r
322     w = os.getenv('WORKSPACE')\r
323     f = os.path.join(w, 'Nt32Pkg/Nt32Pkg.dec')\r
324     p = Dec(os.path.normpath(f), True, True, w)\r
325     p.ShowPackage()\r