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