68b354b032a0a50f765fe735ed937f6cd0b04392
[people/mcb30/basetools.git] / Source / Python / AutoGen / UniClassObject.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 collect all defined strings in multiple uni files \r
12 #\r
13 \r
14 import os, codecs, re\r
15 import Common.EdkLogger\r
16 from Common.BuildToolError import *\r
17 \r
18 UNICODE_WIDE_CHAR = u'\\wide'\r
19 UNICODE_NARROW_CHAR = u'\\narrow'\r
20 UNICODE_NON_BREAKING_CHAR = u'\\nbr'\r
21 UNICODE_UNICODE_CR = '\r'\r
22 UNICODE_UNICODE_LF = '\n'\r
23 \r
24 NARROW_CHAR = u'\uFFF0'\r
25 WIDE_CHAR = u'\uFFF1'\r
26 NON_BREAKING_CHAR = u'\uFFF2'\r
27 CR = u'\u000D'\r
28 LF = u'\u000A'\r
29 NULL = u'\u0000'\r
30 TAB = u'\t'\r
31 BACK_SPLASH = u'\\'\r
32 \r
33 gIncludePattern = re.compile("^#include +[\"<]+([^\"< >]+)[>\"]+$", re.MULTILINE | re.UNICODE)\r
34 \r
35 def UniToStr(Uni):\r
36     return repr(Uni)[2:-1]\r
37 \r
38 def UniToHexList(Uni):\r
39     List = []\r
40     for Item in Uni:\r
41         Temp = '%04X' % ord(Item)\r
42         List.append('0x' + Temp[2:4])\r
43         List.append('0x' + Temp[0:2])\r
44     return List\r
45 \r
46 class StringDefClassObject(object):\r
47     def __init__(self, Name = None, Value = None, Referenced = False, Token = None, UseOtherLangDef = ''):\r
48         self.StringName = ''\r
49         self.StringNameByteList = []\r
50         self.StringValue = ''\r
51         self.StringValueByteList = ''\r
52         self.Token = 0\r
53         self.Referenced = Referenced\r
54         self.UseOtherLangDef = UseOtherLangDef\r
55         self.Length = 0\r
56         \r
57         if Name != None:\r
58             self.StringName = Name\r
59             self.StringNameByteList = UniToHexList(Name)\r
60         if Value != None:\r
61             self.StringValue = Value + u'\x00'        # Add a NULL at string tail\r
62             self.StringValueByteList = UniToHexList(self.StringValue)\r
63             self.Length = len(self.StringValueByteList)\r
64         if Token != None:\r
65             self.Token = Token\r
66 \r
67     def __str__(self):\r
68         return repr(self.StringName) + ' ' + \\r
69                repr(self.Token) + ' ' + \\r
70                repr(self.Referenced) + ' ' + \\r
71                repr(self.StringValue)\r
72 \r
73 class UniFileClassObject(object):\r
74     def __init__(self, FileList = []):\r
75         self.FileList = FileList\r
76         self.Token = 2\r
77         self.LanguageDef = []                   #[ [u'LanguageIdentifier', u'PrintableName'], ... ]\r
78         self.OrderedStringList = {}             #{ u'LanguageIdentifier' : [StringDefClassObject]  }\r
79         \r
80         if len(self.FileList) > 0:\r
81             self.LoadUniFiles(FileList)\r
82 \r
83     def GetLangDef(self, Line):\r
84         Lang = Line.split()\r
85         if len(Lang) != 3:\r
86             raise ParserError(msg="""Wrong language definition '""" + Line + """' which should be '#langdef eng "English"'""")\r
87         else:\r
88             LangName = Lang[1]\r
89             LangPrintName = Lang[2][1:-1]\r
90 \r
91         if [LangName, LangPrintName] not in self.LanguageDef:\r
92             self.LanguageDef.append([LangName, LangPrintName])\r
93         \r
94         #\r
95         # Add language string\r
96         #\r
97         self.AddStringToList(u'$LANGUAGE_NAME', LangName, LangName, 0, True)\r
98         self.AddStringToList(u'$PRINTABLE_LANGUAGE_NAME', LangName, LangPrintName, 1, True)\r
99 \r
100         return True\r
101         \r
102     def GetStringObject(self, Item):\r
103         Name = ''\r
104         Language = ''\r
105         Value = ''\r
106         \r
107         Name = Item.split()[1]\r
108         LanguageList = Item.split(u'#language ')\r
109         for IndexI in range(len(LanguageList)):\r
110             if IndexI == 0:\r
111                 continue\r
112             else:\r
113                 Language = LanguageList[IndexI].split()[0]\r
114                 Value = LanguageList[IndexI][LanguageList[IndexI].find(u'\"') + len(u'\"') : LanguageList[IndexI].rfind(u'\"')].replace(u'\r\n', u'')\r
115                 self.AddStringToList(Name, Language, Value)\r
116     \r
117     def GetIncludeFile(self, Item, Dir):\r
118         FileName = Item[Item.find(u'#include ') + len(u'#include ') :Item.find(u' ', len(u'#include '))][1:-1]\r
119         self.LoadUniFile(FileName)\r
120     \r
121     def PreProcess(self, File):\r
122         if not os.path.exists(File) or not os.path.isfile(File):\r
123             raise ParserError(msg=File + ' is not a valid file')\r
124         \r
125         Dir = os.path.dirname(File)\r
126         FileIn = codecs.open(File, mode='rb', encoding='utf-16').readlines()\r
127         Lines = []\r
128         #\r
129         # Use unique identifier\r
130         #\r
131         for Line in FileIn:\r
132             Line = Line.strip()\r
133             #\r
134             # Ignore comment line and empty line\r
135             #\r
136             if Line == u'' or Line.startswith(u'//'):\r
137                 continue\r
138             Line = Line.replace(u'/langdef', u'#langdef')\r
139             Line = Line.replace(u'/string', u'#string')\r
140             Line = Line.replace(u'/language', u'#language')\r
141             Line = Line.replace(u'/include', u'#include')\r
142                         \r
143             Line = Line.replace(UNICODE_WIDE_CHAR, WIDE_CHAR)\r
144             Line = Line.replace(UNICODE_NARROW_CHAR, NARROW_CHAR)\r
145             Line = Line.replace(UNICODE_NON_BREAKING_CHAR, NON_BREAKING_CHAR)\r
146             Line = Line.replace(u'\\r\\n', CR + LF)\r
147             Line = Line.replace(u'\\n', CR + LF)\r
148             Line = Line.replace(u'\\r', CR)\r
149             Line = Line.replace(u'\\t', u'\t')\r
150             Line = Line.replace(u'\\\\', u'\\')\r
151             Line = Line.replace(u'''\"''', u'''"''')\r
152             Line = Line.replace(u'\t', u' ')\r
153 #           if Line.find(u'\\x'):\r
154 #               hex = Line[Line.find(u'\\x') + 2 : Line.find(u'\\x') + 6]\r
155 #               hex = "u'\\u" + hex + "'"\r
156                         \r
157             IncList = gIncludePattern.findall(Line)\r
158             if len(IncList) == 1:\r
159                 Lines.extend(self.PreProcess(os.path.join(Dir, IncList[0])))\r
160                 continue\r
161 \r
162             Lines.append(Line)\r
163         \r
164         return Lines\r
165     \r
166     def LoadUniFile(self, File = None):\r
167         if File == None:\r
168             raise ParserError(ms='No unicode file is given')\r
169         #\r
170         # Process special char in file\r
171         #\r
172         Lines = self.PreProcess(File)\r
173         \r
174         #\r
175         # Get Unicode Information\r
176         #\r
177         for IndexI in range(len(Lines)):\r
178             Line = Lines[IndexI]\r
179             if (IndexI + 1) < len(Lines):\r
180                 SecondLine = Lines[IndexI + 1]\r
181             if (IndexI + 2) < len(Lines):\r
182                 ThirdLine = Lines[IndexI + 2]\r
183                                     \r
184             #\r
185             # Get Language def information\r
186             # \r
187             if Line.find(u'#langdef ') >= 0:\r
188                 self.GetLangDef(Line)\r
189                 continue\r
190             \r
191             Name = ''\r
192             Language = ''\r
193             Value = ''\r
194             #\r
195             # Get string def information format 1 as below\r
196             #\r
197             #     #string MY_STRING_1\r
198             #     #language eng\r
199             #     My first English string line 1\r
200             #     My first English string line 2\r
201             #     #string MY_STRING_1\r
202             #     #language spa\r
203             #     Mi segunda secuencia 1\r
204             #     Mi segunda secuencia 2\r
205             #\r
206             if Line.find(u'#string ') >= 0 and Line.find(u'#language ') < 0 and \\r
207                 SecondLine.find(u'#string ') < 0 and SecondLine.find(u'#language ') >= 0 and \\r
208                 ThirdLine.find(u'#string ') < 0 and ThirdLine.find(u'#language ') < 0:\r
209                 Name = Line[Line.find(u'#string ') + len(u'#string ') : ].strip()\r
210                 Language = SecondLine[SecondLine.find(u'#language ') + len(u'#language ') : ].strip()\r
211                 for IndexJ in range(IndexI + 2, len(Lines)):\r
212                     if Lines[IndexJ].find(u'#string ') < 0 and Lines[IndexJ].find(u'#language ') < 0:\r
213                         Value = Value + Lines[IndexJ]\r
214                     else:\r
215                         IndexI = IndexJ\r
216                         break\r
217                 Value = Value.replace(u'\r\n', u'')\r
218                 self.AddStringToList(Name, Language, Value)\r
219                 continue\r
220             \r
221             #\r
222             # Get string def information format 2 as below\r
223             #\r
224             #     #string MY_STRING_1     #language eng     "My first English string line 1"\r
225             #                                               "My first English string line 2"\r
226             #                             #language spa     "Mi segunda secuencia 1"\r
227             #                                               "Mi segunda secuencia 2"\r
228             #     #string MY_STRING_2     #language eng     "My first English string line 1"\r
229             #                                               "My first English string line 2"\r
230             #     #string MY_STRING_2     #language spa     "Mi segunda secuencia 1"\r
231             #                                               "Mi segunda secuencia 2"\r
232             #\r
233             if Line.find(u'#string ') >= 0 and Line.find(u'#language ') >= 0:\r
234                 StringItem = Line\r
235                 for IndexJ in range(IndexI + 1, len(Lines)):\r
236                     if Lines[IndexJ].find(u'#string ') >= 0 and Lines[IndexJ].find(u'#language ') >= 0:\r
237                         IndexI = IndexJ\r
238                         break\r
239                     elif Lines[IndexJ].find(u'#string ') < 0 and Lines[IndexJ].find(u'#language ') >= 0:\r
240                         StringItem = StringItem + Lines[IndexJ]\r
241                     elif Lines[IndexJ].find(u'\"') >= 2:\r
242                         StringItem = StringItem[ : StringItem.rfind(u'\"')] + Lines[IndexJ][Lines[IndexJ].find(u'\"') + len(u'\"') : ]\r
243                 self.GetStringObject(StringItem)              \r
244     \r
245     def LoadUniFiles(self, FileList = []):\r
246         if len(FileList) > 0:\r
247             for File in FileList:\r
248                 self.LoadUniFile(File)\r
249                 \r
250     def AddStringToList(self, Name, Language, Value, Token = None, Referenced = False, UseOtherLangDef = '', Index = -1):\r
251         if Language not in self.OrderedStringList:\r
252             self.OrderedStringList[Language] = []\r
253         \r
254         IsAdded = False\r
255         for Item in self.OrderedStringList[Language]:\r
256             if Name == Item.StringName:\r
257                 IsAdded = True\r
258                 break\r
259         if not IsAdded:\r
260             Token = len(self.OrderedStringList[Language])\r
261             if Index == -1:\r
262                 self.OrderedStringList[Language].append(StringDefClassObject(Name, Value, Referenced, Token, UseOtherLangDef))\r
263             else:\r
264                 self.OrderedStringList[Language].insert(Index, StringDefClassObject(Name, Value, Referenced, Token, UseOtherLangDef))\r
265     \r
266     def SetStringReferenced(self, Name):\r
267         for Lang in self.OrderedStringList:\r
268             for Item in self.OrderedStringList[Lang]:\r
269                 if Name == Item.StringName:\r
270                     Item.Referenced = True\r
271                     break\r
272     \r
273     def FindStringValue(self, Name, Lang):\r
274         for Item in self.OrderedStringList[Lang]:\r
275             if Item.StringName == Name:\r
276                 return Item\r
277         \r
278         return None\r
279     \r
280     def ReToken(self):\r
281         #\r
282         # Search each string to find if it is defined for each language\r
283         # Use secondary language value to replace if missing in any one language\r
284         #           \r
285         for IndexI in range(0, len(self.LanguageDef)):\r
286             LangKey = self.LanguageDef[IndexI][0]\r
287             for Item in self.OrderedStringList[LangKey]:\r
288                 Name = Item.StringName\r
289                 Value = Item.StringValue[0:-1]\r
290                 Referenced = Item.Referenced\r
291                 Index = self.OrderedStringList[LangKey].index(Item)\r
292                 for IndexJ in range(0, len(self.LanguageDef)):\r
293                     LangFind = self.LanguageDef[IndexJ][0]\r
294                     if self.FindStringValue(Name, LangFind) == None:\r
295                         Token = len(self.OrderedStringList[LangFind])\r
296                         self.AddStringToList(Name, LangFind, Value, Token, Referenced, LangKey, Index)\r
297         \r
298         #\r
299         # Retoken\r
300         #\r
301         for Lang in self.LanguageDef:\r
302             LangName = Lang[0]\r
303             ReferencedStringList = []\r
304             NotReferencedStringList = []\r
305             Token = 0\r
306             for Item in self.OrderedStringList[LangName]:\r
307                 if Item.Referenced == True:\r
308                     Item.Token = Token\r
309                     ReferencedStringList.append(Item)\r
310                     Token = Token + 1\r
311                 else:\r
312                     NotReferencedStringList.append(Item)\r
313             self.OrderedStringList[LangName] = ReferencedStringList\r
314             for Index in range(len(NotReferencedStringList)):\r
315                 NotReferencedStringList[Index].Token = Token + Index\r
316                 self.OrderedStringList[LangName].append(NotReferencedStringList[Index])\r
317         \r
318     def ShowMe(self):\r
319         print self.LanguageDef\r
320         #print self.OrderedStringList\r
321         for Item in self.OrderedStringList:\r
322             print Item\r
323             for Member in self.OrderedStringList[Item]:\r
324                 print str(Member)\r
325             \r
326 # This acts like the main() function for the script, unless it is 'import'ed into another\r
327 # script.\r
328 if __name__ == '__main__':\r
329     a = UniFileClassObject(['C:\\Tiano\\Edk\\Sample\\Universal\\UserInterface\\SetupBrowser\\Dxe\\DriverSample\\inventorystrings.uni', 'C:\\Tiano\\Edk\\Sample\\Universal\\UserInterface\\SetupBrowser\\Dxe\\DriverSample\\VfrStrings.uni'])\r
330     a.ShowMe()\r