]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/UPT/Library/UniClassObject.py
BaseTools/UPT: Porting UPT Tool from Python2 to Python3
[mirror_edk2.git] / BaseTools / Source / Python / UPT / Library / UniClassObject.py
CommitLineData
421ccda3
HC
1## @file\r
2# Collect all defined strings in multiple uni files.\r
3#\r
b3fa393f 4# Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>\r
421ccda3 5#\r
f7496d71
LG
6# This program and the accompanying materials are licensed and made available\r
7# under the terms and conditions of the BSD License which accompanies this\r
8# distribution. The full text of the license may be found at\r
421ccda3
HC
9# http://opensource.org/licenses/bsd-license.php\r
10#\r
11# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13#\r
14"""\r
15Collect all defined strings in multiple uni files\r
16"""\r
17\r
18##\r
19# Import Modules\r
20#\r
21import os, codecs, re\r
22import distutils.util\r
23from Logger import ToolError\r
24from Logger import Log as EdkLogger\r
25from Logger import StringTable as ST\r
64285f15 26from Library.StringUtils import GetLineNo\r
421ccda3
HC
27from Library.Misc import PathClass\r
28from Library.Misc import GetCharIndexOutStr\r
29from Library import DataType as DT\r
fe90f483 30from Library.ParserValidate import CheckUTF16FileHeader\r
421ccda3
HC
31\r
32##\r
33# Static definitions\r
34#\r
35UNICODE_WIDE_CHAR = u'\\wide'\r
36UNICODE_NARROW_CHAR = u'\\narrow'\r
37UNICODE_NON_BREAKING_CHAR = u'\\nbr'\r
38UNICODE_UNICODE_CR = '\r'\r
39UNICODE_UNICODE_LF = '\n'\r
40\r
41NARROW_CHAR = u'\uFFF0'\r
42WIDE_CHAR = u'\uFFF1'\r
43NON_BREAKING_CHAR = u'\uFFF2'\r
44CR = u'\u000D'\r
45LF = u'\u000A'\r
46NULL = u'\u0000'\r
47TAB = u'\t'\r
48BACK_SPLASH = u'\\'\r
49\r
421ccda3
HC
50gLANG_CONV_TABLE = {'eng':'en', 'fra':'fr', \\r
51 'aar':'aa', 'abk':'ab', 'ave':'ae', 'afr':'af', 'aka':'ak', 'amh':'am', \\r
52 'arg':'an', 'ara':'ar', 'asm':'as', 'ava':'av', 'aym':'ay', 'aze':'az', \\r
53 'bak':'ba', 'bel':'be', 'bul':'bg', 'bih':'bh', 'bis':'bi', 'bam':'bm', \\r
54 'ben':'bn', 'bod':'bo', 'bre':'br', 'bos':'bs', 'cat':'ca', 'che':'ce', \\r
55 'cha':'ch', 'cos':'co', 'cre':'cr', 'ces':'cs', 'chu':'cu', 'chv':'cv', \\r
56 'cym':'cy', 'dan':'da', 'deu':'de', 'div':'dv', 'dzo':'dz', 'ewe':'ee', \\r
57 'ell':'el', 'epo':'eo', 'spa':'es', 'est':'et', 'eus':'eu', 'fas':'fa', \\r
58 'ful':'ff', 'fin':'fi', 'fij':'fj', 'fao':'fo', 'fry':'fy', 'gle':'ga', \\r
59 'gla':'gd', 'glg':'gl', 'grn':'gn', 'guj':'gu', 'glv':'gv', 'hau':'ha', \\r
60 'heb':'he', 'hin':'hi', 'hmo':'ho', 'hrv':'hr', 'hat':'ht', 'hun':'hu', \\r
61 'hye':'hy', 'her':'hz', 'ina':'ia', 'ind':'id', 'ile':'ie', 'ibo':'ig', \\r
62 'iii':'ii', 'ipk':'ik', 'ido':'io', 'isl':'is', 'ita':'it', 'iku':'iu', \\r
63 'jpn':'ja', 'jav':'jv', 'kat':'ka', 'kon':'kg', 'kik':'ki', 'kua':'kj', \\r
64 'kaz':'kk', 'kal':'kl', 'khm':'km', 'kan':'kn', 'kor':'ko', 'kau':'kr', \\r
65 'kas':'ks', 'kur':'ku', 'kom':'kv', 'cor':'kw', 'kir':'ky', 'lat':'la', \\r
66 'ltz':'lb', 'lug':'lg', 'lim':'li', 'lin':'ln', 'lao':'lo', 'lit':'lt', \\r
67 'lub':'lu', 'lav':'lv', 'mlg':'mg', 'mah':'mh', 'mri':'mi', 'mkd':'mk', \\r
68 'mal':'ml', 'mon':'mn', 'mar':'mr', 'msa':'ms', 'mlt':'mt', 'mya':'my', \\r
69 'nau':'na', 'nob':'nb', 'nde':'nd', 'nep':'ne', 'ndo':'ng', 'nld':'nl', \\r
70 'nno':'nn', 'nor':'no', 'nbl':'nr', 'nav':'nv', 'nya':'ny', 'oci':'oc', \\r
71 'oji':'oj', 'orm':'om', 'ori':'or', 'oss':'os', 'pan':'pa', 'pli':'pi', \\r
72 'pol':'pl', 'pus':'ps', 'por':'pt', 'que':'qu', 'roh':'rm', 'run':'rn', \\r
73 'ron':'ro', 'rus':'ru', 'kin':'rw', 'san':'sa', 'srd':'sc', 'snd':'sd', \\r
74 'sme':'se', 'sag':'sg', 'sin':'si', 'slk':'sk', 'slv':'sl', 'smo':'sm', \\r
75 'sna':'sn', 'som':'so', 'sqi':'sq', 'srp':'sr', 'ssw':'ss', 'sot':'st', \\r
76 'sun':'su', 'swe':'sv', 'swa':'sw', 'tam':'ta', 'tel':'te', 'tgk':'tg', \\r
77 'tha':'th', 'tir':'ti', 'tuk':'tk', 'tgl':'tl', 'tsn':'tn', 'ton':'to', \\r
78 'tur':'tr', 'tso':'ts', 'tat':'tt', 'twi':'tw', 'tah':'ty', 'uig':'ug', \\r
79 'ukr':'uk', 'urd':'ur', 'uzb':'uz', 'ven':'ve', 'vie':'vi', 'vol':'vo', \\r
80 'wln':'wa', 'wol':'wo', 'xho':'xh', 'yid':'yi', 'yor':'yo', 'zha':'za', \\r
81 'zho':'zh', 'zul':'zu'}\r
82\r
83## Convert a python unicode string to a normal string\r
84#\r
85# Convert a python unicode string to a normal string\r
86# UniToStr(u'I am a string') is 'I am a string'\r
87#\r
88# @param Uni: The python unicode string\r
89#\r
90# @retval: The formatted normal string\r
91#\r
92def UniToStr(Uni):\r
93 return repr(Uni)[2:-1]\r
94\r
95## Convert a unicode string to a Hex list\r
96#\r
97# Convert a unicode string to a Hex list\r
98# UniToHexList('ABC') is ['0x41', '0x00', '0x42', '0x00', '0x43', '0x00']\r
99#\r
100# @param Uni: The python unicode string\r
101#\r
102# @retval List: The formatted hex list\r
103#\r
104def UniToHexList(Uni):\r
105 List = []\r
106 for Item in Uni:\r
107 Temp = '%04X' % ord(Item)\r
108 List.append('0x' + Temp[2:4])\r
109 List.append('0x' + Temp[0:2])\r
110 return List\r
111\r
112## Convert special unicode characters\r
113#\r
114# Convert special characters to (c), (r) and (tm).\r
115#\r
116# @param Uni: The python unicode string\r
117#\r
118# @retval NewUni: The converted unicode string\r
119#\r
120def ConvertSpecialUnicodes(Uni):\r
121 NewUni = Uni\r
122 NewUni = NewUni.replace(u'\u00A9', '(c)')\r
123 NewUni = NewUni.replace(u'\u00AE', '(r)')\r
124 NewUni = NewUni.replace(u'\u2122', '(tm)')\r
125 return NewUni\r
126\r
127## GetLanguageCode1766\r
128#\r
129# Check the language code read from .UNI file and convert RFC 4646 codes to RFC 1766 codes\r
130# RFC 1766 language codes supported in compatiblity mode\r
131# RFC 4646 language codes supported in native mode\r
132#\r
133# @param LangName: Language codes read from .UNI file\r
134#\r
135# @retval LangName: Valid lanugage code in RFC 1766 format or None\r
136#\r
137def GetLanguageCode1766(LangName, File=None):\r
fe90f483
HC
138 return LangName\r
139\r
421ccda3
HC
140 length = len(LangName)\r
141 if length == 2:\r
142 if LangName.isalpha():\r
143 for Key in gLANG_CONV_TABLE.keys():\r
144 if gLANG_CONV_TABLE.get(Key) == LangName.lower():\r
145 return Key\r
146 elif length == 3:\r
147 if LangName.isalpha() and gLANG_CONV_TABLE.get(LangName.lower()):\r
148 return LangName\r
149 else:\r
f7496d71 150 EdkLogger.Error("Unicode File Parser",\r
421ccda3 151 ToolError.FORMAT_INVALID,\r
f7496d71 152 "Invalid RFC 1766 language code : %s" % LangName,\r
421ccda3
HC
153 File)\r
154 elif length == 5:\r
155 if LangName[0:2].isalpha() and LangName[2] == '-':\r
156 for Key in gLANG_CONV_TABLE.keys():\r
157 if gLANG_CONV_TABLE.get(Key) == LangName[0:2].lower():\r
158 return Key\r
159 elif length >= 6:\r
160 if LangName[0:2].isalpha() and LangName[2] == '-':\r
161 for Key in gLANG_CONV_TABLE.keys():\r
162 if gLANG_CONV_TABLE.get(Key) == LangName[0:2].lower():\r
163 return Key\r
4231a819 164 if LangName[0:3].isalpha() and gLANG_CONV_TABLE.get(LangName.lower()) is None and LangName[3] == '-':\r
421ccda3
HC
165 for Key in gLANG_CONV_TABLE.keys():\r
166 if Key == LangName[0:3].lower():\r
167 return Key\r
168\r
f7496d71 169 EdkLogger.Error("Unicode File Parser",\r
421ccda3 170 ToolError.FORMAT_INVALID,\r
f7496d71 171 "Invalid RFC 4646 language code : %s" % LangName,\r
421ccda3 172 File)\r
f7496d71 173\r
421ccda3
HC
174## GetLanguageCode\r
175#\r
176# Check the language code read from .UNI file and convert RFC 1766 codes to RFC 4646 codes if appropriate\r
177# RFC 1766 language codes supported in compatiblity mode\r
178# RFC 4646 language codes supported in native mode\r
179#\r
180# @param LangName: Language codes read from .UNI file\r
181#\r
182# @retval LangName: Valid lanugage code in RFC 4646 format or None\r
183#\r
184def GetLanguageCode(LangName, IsCompatibleMode, File):\r
185 length = len(LangName)\r
186 if IsCompatibleMode:\r
187 if length == 3 and LangName.isalpha():\r
188 TempLangName = gLANG_CONV_TABLE.get(LangName.lower())\r
4231a819 189 if TempLangName is not None:\r
421ccda3
HC
190 return TempLangName\r
191 return LangName\r
192 else:\r
f7496d71 193 EdkLogger.Error("Unicode File Parser",\r
421ccda3 194 ToolError.FORMAT_INVALID,\r
f7496d71 195 "Invalid RFC 1766 language code : %s" % LangName,\r
421ccda3
HC
196 File)\r
197 if (LangName[0] == 'X' or LangName[0] == 'x') and LangName[1] == '-':\r
198 return LangName\r
199 if length == 2:\r
200 if LangName.isalpha():\r
201 return LangName\r
202 elif length == 3:\r
4231a819 203 if LangName.isalpha() and gLANG_CONV_TABLE.get(LangName.lower()) is None:\r
421ccda3
HC
204 return LangName\r
205 elif length == 5:\r
206 if LangName[0:2].isalpha() and LangName[2] == '-':\r
207 return LangName\r
208 elif length >= 6:\r
209 if LangName[0:2].isalpha() and LangName[2] == '-':\r
210 return LangName\r
4231a819 211 if LangName[0:3].isalpha() and gLANG_CONV_TABLE.get(LangName.lower()) is None and LangName[3] == '-':\r
421ccda3
HC
212 return LangName\r
213\r
f7496d71 214 EdkLogger.Error("Unicode File Parser",\r
421ccda3 215 ToolError.FORMAT_INVALID,\r
f7496d71 216 "Invalid RFC 4646 language code : %s" % LangName,\r
421ccda3
HC
217 File)\r
218\r
219## FormatUniEntry\r
220#\r
221# Formated the entry in Uni file.\r
222#\r
223# @param StrTokenName StrTokenName.\r
224# @param TokenValueList A list need to be processed.\r
225# @param ContainerFile ContainerFile.\r
226#\r
227# @return formated entry\r
228def FormatUniEntry(StrTokenName, TokenValueList, ContainerFile):\r
229 SubContent = ''\r
230 PreFormatLength = 40\r
231 if len(StrTokenName) > PreFormatLength:\r
232 PreFormatLength = len(StrTokenName) + 1\r
f7496d71 233 for (Lang, Value) in TokenValueList:\r
421ccda3
HC
234 if not Value or Lang == DT.TAB_LANGUAGE_EN_X:\r
235 continue\r
236 if Lang == '':\r
237 Lang = DT.TAB_LANGUAGE_EN_US\r
238 if Lang == 'eng':\r
239 Lang = DT.TAB_LANGUAGE_EN_US\r
240 elif len(Lang.split('-')[0]) == 3:\r
241 Lang = GetLanguageCode(Lang.split('-')[0], True, ContainerFile)\r
242 else:\r
243 Lang = GetLanguageCode(Lang, False, ContainerFile)\r
244 ValueList = Value.split('\n')\r
245 SubValueContent = ''\r
246 for SubValue in ValueList:\r
247 if SubValue.strip():\r
248 SubValueContent += \\r
1b2e0772 249 ' ' * (PreFormatLength + len('#language en-US ')) + '\"%s\\n\"' % SubValue.strip() + '\n'\r
cf2b2bde 250 SubValueContent = SubValueContent[(PreFormatLength + len('#language en-US ')):SubValueContent.rfind('\\n')] \\r
1b2e0772 251 + '\"' + '\n'\r
421ccda3
HC
252 SubContent += ' '*PreFormatLength + '#language %-5s ' % Lang + SubValueContent\r
253 if SubContent:\r
254 SubContent = StrTokenName + ' '*(PreFormatLength - len(StrTokenName)) + SubContent[PreFormatLength:]\r
255 return SubContent\r
256\r
257\r
258## StringDefClassObject\r
259#\r
260# A structure for language definition\r
261#\r
262class StringDefClassObject(object):\r
263 def __init__(self, Name = None, Value = None, Referenced = False, Token = None, UseOtherLangDef = ''):\r
264 self.StringName = ''\r
265 self.StringNameByteList = []\r
266 self.StringValue = ''\r
267 self.StringValueByteList = ''\r
268 self.Token = 0\r
269 self.Referenced = Referenced\r
270 self.UseOtherLangDef = UseOtherLangDef\r
271 self.Length = 0\r
272\r
4231a819 273 if Name is not None:\r
421ccda3
HC
274 self.StringName = Name\r
275 self.StringNameByteList = UniToHexList(Name)\r
4231a819 276 if Value is not None:\r
421ccda3
HC
277 self.StringValue = Value\r
278 self.StringValueByteList = UniToHexList(self.StringValue)\r
279 self.Length = len(self.StringValueByteList)\r
4231a819 280 if Token is not None:\r
421ccda3
HC
281 self.Token = Token\r
282\r
283 def __str__(self):\r
284 return repr(self.StringName) + ' ' + \\r
285 repr(self.Token) + ' ' + \\r
286 repr(self.Referenced) + ' ' + \\r
287 repr(self.StringValue) + ' ' + \\r
288 repr(self.UseOtherLangDef)\r
289\r
290 def UpdateValue(self, Value = None):\r
4231a819 291 if Value is not None:\r
421ccda3 292 if self.StringValue:\r
1b2e0772 293 self.StringValue = self.StringValue + '\n' + Value\r
421ccda3
HC
294 else:\r
295 self.StringValue = Value\r
296 self.StringValueByteList = UniToHexList(self.StringValue)\r
297 self.Length = len(self.StringValueByteList)\r
298\r
299## UniFileClassObject\r
300#\r
301# A structure for .uni file definition\r
302#\r
303class UniFileClassObject(object):\r
304 def __init__(self, FileList = None, IsCompatibleMode = False, IncludePathList = None):\r
305 self.FileList = FileList\r
306 self.File = None\r
307 self.IncFileList = FileList\r
308 self.UniFileHeader = ''\r
309 self.Token = 2\r
310 self.LanguageDef = [] #[ [u'LanguageIdentifier', u'PrintableName'], ... ]\r
311 self.OrderedStringList = {} #{ u'LanguageIdentifier' : [StringDefClassObject] }\r
312 self.OrderedStringDict = {} #{ u'LanguageIdentifier' : {StringName:(IndexInList)} }\r
313 self.OrderedStringListByToken = {} #{ u'LanguageIdentifier' : {Token: StringDefClassObject} }\r
314 self.IsCompatibleMode = IsCompatibleMode\r
315 if not IncludePathList:\r
316 self.IncludePathList = []\r
317 else:\r
318 self.IncludePathList = IncludePathList\r
319 if len(self.FileList) > 0:\r
320 self.LoadUniFiles(FileList)\r
321\r
322 #\r
323 # Get Language definition\r
324 #\r
325 def GetLangDef(self, File, Line):\r
326 Lang = distutils.util.split_quoted((Line.split(u"//")[0]))\r
327 if len(Lang) != 3:\r
328 try:\r
645a5128 329 FileIn = codecs.open(File.Path, mode='rb', encoding='utf_8').readlines()\r
5b0671c1 330 except UnicodeError as Xstr:\r
645a5128 331 FileIn = codecs.open(File.Path, mode='rb', encoding='utf_16').readlines()\r
5b0671c1 332 except UnicodeError as Xstr:\r
645a5128 333 FileIn = codecs.open(File.Path, mode='rb', encoding='utf_16_le').readlines()\r
421ccda3 334 except:\r
f7496d71
LG
335 EdkLogger.Error("Unicode File Parser",\r
336 ToolError.FILE_OPEN_FAILURE,\r
421ccda3
HC
337 "File read failure: %s" % str(Xstr),\r
338 ExtraData=File)\r
339 LineNo = GetLineNo(FileIn, Line, False)\r
f7496d71 340 EdkLogger.Error("Unicode File Parser",\r
421ccda3 341 ToolError.PARSER_ERROR,\r
f7496d71
LG
342 "Wrong language definition",\r
343 ExtraData="""%s\n\t*Correct format is like '#langdef en-US "English"'""" % Line,\r
421ccda3
HC
344 File = File, Line = LineNo)\r
345 else:\r
346 LangName = GetLanguageCode(Lang[1], self.IsCompatibleMode, self.File)\r
347 LangPrintName = Lang[2]\r
348\r
349 IsLangInDef = False\r
350 for Item in self.LanguageDef:\r
351 if Item[0] == LangName:\r
352 IsLangInDef = True\r
353 break\r
354\r
355 if not IsLangInDef:\r
356 self.LanguageDef.append([LangName, LangPrintName])\r
357\r
358 #\r
359 # Add language string\r
360 #\r
361 self.AddStringToList(u'$LANGUAGE_NAME', LangName, LangName, 0, True, Index=0)\r
362 self.AddStringToList(u'$PRINTABLE_LANGUAGE_NAME', LangName, LangPrintName, 1, True, Index=1)\r
363\r
364 if not IsLangInDef:\r
365 #\r
366 # The found STRING tokens will be added into new language string list\r
f7496d71 367 # so that the unique STRING identifier is reserved for all languages in the package list.\r
421ccda3
HC
368 #\r
369 FirstLangName = self.LanguageDef[0][0]\r
370 if LangName != FirstLangName:\r
371 for Index in range (2, len (self.OrderedStringList[FirstLangName])):\r
372 Item = self.OrderedStringList[FirstLangName][Index]\r
373 if Item.UseOtherLangDef != '':\r
374 OtherLang = Item.UseOtherLangDef\r
375 else:\r
376 OtherLang = FirstLangName\r
f7496d71
LG
377 self.OrderedStringList[LangName].append (StringDefClassObject(Item.StringName,\r
378 '',\r
379 Item.Referenced,\r
380 Item.Token,\r
421ccda3
HC
381 OtherLang))\r
382 self.OrderedStringDict[LangName][Item.StringName] = len(self.OrderedStringList[LangName]) - 1\r
383 return True\r
384\r
385 #\r
386 # Get String name and value\r
387 #\r
388 def GetStringObject(self, Item):\r
389 Language = ''\r
390 Value = ''\r
391\r
392 Name = Item.split()[1]\r
393 # Check the string name is the upper character\r
394 if Name != '':\r
395 MatchString = re.match('[A-Z0-9_]+', Name, re.UNICODE)\r
4231a819 396 if MatchString is None or MatchString.end(0) != len(Name):\r
f7496d71 397 EdkLogger.Error("Unicode File Parser",\r
421ccda3
HC
398 ToolError.FORMAT_INVALID,\r
399 'The string token name %s in UNI file %s must be upper case character.' %(Name, self.File))\r
400 LanguageList = Item.split(u'#language ')\r
401 for IndexI in range(len(LanguageList)):\r
402 if IndexI == 0:\r
403 continue\r
404 else:\r
405 Language = LanguageList[IndexI].split()[0]\r
406 #.replace(u'\r\n', u'')\r
407 Value = \\r
f7496d71 408 LanguageList[IndexI][LanguageList[IndexI].find(u'\"') + len(u'\"') : LanguageList[IndexI].rfind(u'\"')]\r
421ccda3
HC
409 Language = GetLanguageCode(Language, self.IsCompatibleMode, self.File)\r
410 self.AddStringToList(Name, Language, Value)\r
411\r
412 #\r
413 # Get include file list and load them\r
414 #\r
415 def GetIncludeFile(self, Item, Dir = None):\r
416 if Dir:\r
417 pass\r
418 FileName = Item[Item.find(u'!include ') + len(u'!include ') :Item.find(u' ', len(u'!include '))][1:-1]\r
419 self.LoadUniFile(FileName)\r
420\r
421 #\r
422 # Pre-process before parse .uni file\r
423 #\r
424 def PreProcess(self, File, IsIncludeFile=False):\r
425 if not os.path.exists(File.Path) or not os.path.isfile(File.Path):\r
f7496d71 426 EdkLogger.Error("Unicode File Parser",\r
421ccda3
HC
427 ToolError.FILE_NOT_FOUND,\r
428 ExtraData=File.Path)\r
429\r
fe90f483
HC
430 #\r
431 # Check file header of the Uni file\r
432 #\r
4a21fb3b
HC
433# if not CheckUTF16FileHeader(File.Path):\r
434# EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
435# ExtraData='The file %s is either invalid UTF-16LE or it is missing the BOM.' % File.Path)\r
fe90f483 436\r
421ccda3 437 try:\r
645a5128 438 FileIn = codecs.open(File.Path, mode='rb', encoding='utf_8').readlines()\r
5b0671c1 439 except UnicodeError as Xstr:\r
421ccda3
HC
440 FileIn = codecs.open(File.Path, mode='rb', encoding='utf_16').readlines()\r
441 except UnicodeError:\r
442 FileIn = codecs.open(File.Path, mode='rb', encoding='utf_16_le').readlines()\r
443 except:\r
444 EdkLogger.Error("Unicode File Parser", ToolError.FILE_OPEN_FAILURE, ExtraData=File.Path)\r
f7496d71
LG
445\r
446\r
421ccda3
HC
447 #\r
448 # get the file header\r
449 #\r
450 Lines = []\r
451 HeaderStart = False\r
452 HeaderEnd = False\r
453 if not self.UniFileHeader:\r
454 FirstGenHeader = True\r
455 else:\r
456 FirstGenHeader = False\r
457 for Line in FileIn:\r
458 Line = Line.strip()\r
459 if Line == u'':\r
460 continue\r
461 if Line.startswith(DT.TAB_COMMENT_EDK1_SPLIT) and (Line.find(DT.TAB_HEADER_COMMENT) > -1) \\r
462 and not HeaderEnd and not HeaderStart:\r
463 HeaderStart = True\r
464 if not Line.startswith(DT.TAB_COMMENT_EDK1_SPLIT) and HeaderStart and not HeaderEnd:\r
465 HeaderEnd = True\r
466 if Line.startswith(DT.TAB_COMMENT_EDK1_SPLIT) and HeaderStart and not HeaderEnd and FirstGenHeader:\r
1b2e0772 467 self.UniFileHeader += Line + '\n'\r
421ccda3 468 continue\r
f7496d71 469\r
421ccda3
HC
470 #\r
471 # Use unique identifier\r
472 #\r
473 FindFlag = -1\r
474 LineCount = 0\r
475 MultiLineFeedExits = False\r
476 #\r
477 # 0: initial value\r
478 # 1: signle String entry exist\r
479 # 2: line feed exist under the some signle String entry\r
480 #\r
481 StringEntryExistsFlag = 0\r
482 for Line in FileIn:\r
483 Line = FileIn[LineCount]\r
484 LineCount += 1\r
485 Line = Line.strip()\r
486 #\r
487 # Ignore comment line and empty line\r
f7496d71 488 #\r
421ccda3
HC
489 if Line == u'' or Line.startswith(u'//'):\r
490 #\r
491 # Change the single line String entry flag status\r
492 #\r
493 if StringEntryExistsFlag == 1:\r
494 StringEntryExistsFlag = 2\r
495 #\r
496 # If the '#string' line and the '#language' line are not in the same line,\r
497 # there should be only one line feed character betwwen them\r
498 #\r
499 if MultiLineFeedExits:\r
500 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
501 continue\r
502\r
503 MultiLineFeedExits = False\r
504 #\r
505 # Process comment embeded in string define lines\r
506 #\r
507 FindFlag = Line.find(u'//')\r
508 if FindFlag != -1 and Line.find(u'//') < Line.find(u'"'):\r
509 Line = Line.replace(Line[FindFlag:], u' ')\r
510 if FileIn[LineCount].strip().startswith('#language'):\r
511 Line = Line + FileIn[LineCount]\r
512 FileIn[LineCount-1] = Line\r
1b2e0772 513 FileIn[LineCount] = '\n'\r
421ccda3 514 LineCount -= 1\r
1b2e0772 515 for Index in range (LineCount + 1, len (FileIn) - 1):\r
421ccda3 516 if (Index == len(FileIn) -1):\r
1b2e0772 517 FileIn[Index] = '\n'\r
421ccda3
HC
518 else:\r
519 FileIn[Index] = FileIn[Index + 1]\r
520 continue\r
521 CommIndex = GetCharIndexOutStr(u'/', Line)\r
522 if CommIndex > -1:\r
523 if (len(Line) - 1) > CommIndex:\r
524 if Line[CommIndex+1] == u'/':\r
525 Line = Line[:CommIndex].strip()\r
526 else:\r
527 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
528 else:\r
529 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
f7496d71 530\r
421ccda3
HC
531 Line = Line.replace(UNICODE_WIDE_CHAR, WIDE_CHAR)\r
532 Line = Line.replace(UNICODE_NARROW_CHAR, NARROW_CHAR)\r
533 Line = Line.replace(UNICODE_NON_BREAKING_CHAR, NON_BREAKING_CHAR)\r
534\r
535 Line = Line.replace(u'\\\\', u'\u0006')\r
536 Line = Line.replace(u'\\r\\n', CR + LF)\r
537 Line = Line.replace(u'\\n', CR + LF)\r
538 Line = Line.replace(u'\\r', CR)\r
539 Line = Line.replace(u'\\t', u'\t')\r
540 Line = Line.replace(u'''\"''', u'''"''')\r
541 Line = Line.replace(u'\t', u' ')\r
542 Line = Line.replace(u'\u0006', u'\\')\r
543\r
85ea493f
HC
544 #\r
545 # Check if single line has correct '"'\r
546 #\r
547 if Line.startswith(u'#string') and Line.find(u'#language') > -1 and Line.find('"') > Line.find(u'#language'):\r
548 if not Line.endswith('"'):\r
549 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
550 ExtraData='''The line %s misses '"' at the end of it in file %s'''\r
551 % (LineCount, File.Path))\r
552\r
421ccda3
HC
553 #\r
554 # Between Name entry and Language entry can not contain line feed\r
555 #\r
556 if Line.startswith(u'#string') and Line.find(u'#language') == -1:\r
557 MultiLineFeedExits = True\r
f7496d71 558\r
421ccda3
HC
559 if Line.startswith(u'#string') and Line.find(u'#language') > 0 and Line.find(u'"') < 0:\r
560 MultiLineFeedExits = True\r
f7496d71 561\r
421ccda3
HC
562 #\r
563 # Between Language entry and String entry can not contain line feed\r
564 #\r
565 if Line.startswith(u'#language') and len(Line.split()) == 2:\r
566 MultiLineFeedExits = True\r
f7496d71 567\r
421ccda3
HC
568 #\r
569 # Between two String entry, can not contain line feed\r
570 #\r
571 if Line.startswith(u'"'):\r
572 if StringEntryExistsFlag == 2:\r
645a5128 573 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
421ccda3 574 Message=ST.ERR_UNIPARSE_LINEFEED_UP_EXIST % Line, ExtraData=File.Path)\r
645a5128 575\r
421ccda3
HC
576 StringEntryExistsFlag = 1\r
577 if not Line.endswith('"'):\r
fe90f483
HC
578 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
579 ExtraData='''The line %s misses '"' at the end of it in file %s'''\r
580 % (LineCount, File.Path))\r
421ccda3
HC
581 elif Line.startswith(u'#language'):\r
582 if StringEntryExistsFlag == 2:\r
645a5128 583 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
fe90f483 584 Message=ST.ERR_UNI_MISS_STRING_ENTRY % Line, ExtraData=File.Path)\r
421ccda3
HC
585 StringEntryExistsFlag = 0\r
586 else:\r
587 StringEntryExistsFlag = 0\r
588\r
589 Lines.append(Line)\r
f7496d71 590\r
421ccda3
HC
591 #\r
592 # Convert string def format as below\r
593 #\r
594 # #string MY_STRING_1\r
595 # #language eng\r
596 # "My first English string line 1"\r
597 # "My first English string line 2"\r
598 # #string MY_STRING_1\r
599 # #language spa\r
600 # "Mi segunda secuencia 1"\r
601 # "Mi segunda secuencia 2"\r
602 #\r
f7496d71 603\r
421ccda3
HC
604 if not IsIncludeFile and not Lines:\r
605 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
606 Message=ST.ERR_UNIPARSE_NO_SECTION_EXIST, \\r
f7496d71 607 ExtraData=File.Path)\r
421ccda3
HC
608\r
609 NewLines = []\r
610 StrName = u''\r
611 ExistStrNameList = []\r
612 for Line in Lines:\r
613 if StrName and not StrName.split()[1].startswith(DT.TAB_STR_TOKENCNAME + DT.TAB_UNDERLINE_SPLIT):\r
614 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
615 Message=ST.ERR_UNIPARSE_STRNAME_FORMAT_ERROR % StrName.split()[1], \\r
616 ExtraData=File.Path)\r
f7496d71 617\r
421ccda3
HC
618 if StrName and len(StrName.split()[1].split(DT.TAB_UNDERLINE_SPLIT)) == 4:\r
619 StringTokenList = StrName.split()[1].split(DT.TAB_UNDERLINE_SPLIT)\r
620 if (StringTokenList[3].upper() in [DT.TAB_STR_TOKENPROMPT, DT.TAB_STR_TOKENHELP] and \\r
621 StringTokenList[3] not in [DT.TAB_STR_TOKENPROMPT, DT.TAB_STR_TOKENHELP]) or \\r
622 (StringTokenList[2].upper() == DT.TAB_STR_TOKENERR and StringTokenList[2] != DT.TAB_STR_TOKENERR):\r
623 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
624 Message=ST.ERR_UNIPARSE_STRTOKEN_FORMAT_ERROR % StrName.split()[1], \\r
625 ExtraData=File.Path)\r
f7496d71 626\r
421ccda3
HC
627 if Line.count(u'#language') > 1:\r
628 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
629 Message=ST.ERR_UNIPARSE_SEP_LANGENTRY_LINE % Line, \\r
f7496d71
LG
630 ExtraData=File.Path)\r
631\r
421ccda3
HC
632 if Line.startswith(u'//'):\r
633 continue\r
634 elif Line.startswith(u'#langdef'):\r
635 if len(Line.split()) == 2:\r
636 NewLines.append(Line)\r
637 continue\r
f7496d71 638 elif len(Line.split()) > 2 and Line.find(u'"') > 0:\r
421ccda3
HC
639 NewLines.append(Line[:Line.find(u'"')].strip())\r
640 NewLines.append(Line[Line.find(u'"'):])\r
641 else:\r
642 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
643 elif Line.startswith(u'#string'):\r
644 if len(Line.split()) == 2:\r
645 StrName = Line\r
646 if StrName:\r
647 if StrName.split()[1] not in ExistStrNameList:\r
648 ExistStrNameList.append(StrName.split()[1].strip())\r
649 elif StrName.split()[1] in [DT.TAB_INF_ABSTRACT, DT.TAB_INF_DESCRIPTION, \\r
650 DT.TAB_INF_BINARY_ABSTRACT, DT.TAB_INF_BINARY_DESCRIPTION, \\r
651 DT.TAB_DEC_PACKAGE_ABSTRACT, DT.TAB_DEC_PACKAGE_DESCRIPTION, \\r
652 DT.TAB_DEC_BINARY_ABSTRACT, DT.TAB_DEC_BINARY_DESCRIPTION]:\r
653 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
654 Message=ST.ERR_UNIPARSE_MULTI_ENTRY_EXIST % StrName.split()[1], \\r
655 ExtraData=File.Path)\r
656 continue\r
657 elif len(Line.split()) == 4 and Line.find(u'#language') > 0:\r
658 if Line[Line.find(u'#language')-1] != ' ' or \\r
659 Line[Line.find(u'#language')+len(u'#language')] != u' ':\r
660 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
f7496d71 661\r
421ccda3
HC
662 if Line.find(u'"') > 0:\r
663 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
f7496d71 664\r
421ccda3
HC
665 StrName = Line.split()[0] + u' ' + Line.split()[1]\r
666 if StrName:\r
667 if StrName.split()[1] not in ExistStrNameList:\r
668 ExistStrNameList.append(StrName.split()[1].strip())\r
669 elif StrName.split()[1] in [DT.TAB_INF_ABSTRACT, DT.TAB_INF_DESCRIPTION, \\r
670 DT.TAB_INF_BINARY_ABSTRACT, DT.TAB_INF_BINARY_DESCRIPTION, \\r
671 DT.TAB_DEC_PACKAGE_ABSTRACT, DT.TAB_DEC_PACKAGE_DESCRIPTION, \\r
672 DT.TAB_DEC_BINARY_ABSTRACT, DT.TAB_DEC_BINARY_DESCRIPTION]:\r
673 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
674 Message=ST.ERR_UNIPARSE_MULTI_ENTRY_EXIST % StrName.split()[1], \\r
675 ExtraData=File.Path)\r
676 if IsIncludeFile:\r
677 if StrName not in NewLines:\r
678 NewLines.append((Line[:Line.find(u'#language')]).strip())\r
679 else:\r
680 NewLines.append((Line[:Line.find(u'#language')]).strip())\r
681 NewLines.append((Line[Line.find(u'#language'):]).strip())\r
682 elif len(Line.split()) > 4 and Line.find(u'#language') > 0 and Line.find(u'"') > 0:\r
683 if Line[Line.find(u'#language')-1] != u' ' or \\r
684 Line[Line.find(u'#language')+len(u'#language')] != u' ':\r
685 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
f7496d71 686\r
421ccda3 687 if Line[Line.find(u'"')-1] != u' ':\r
f7496d71
LG
688 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
689\r
690 StrName = Line.split()[0] + u' ' + Line.split()[1]\r
421ccda3
HC
691 if StrName:\r
692 if StrName.split()[1] not in ExistStrNameList:\r
693 ExistStrNameList.append(StrName.split()[1].strip())\r
694 elif StrName.split()[1] in [DT.TAB_INF_ABSTRACT, DT.TAB_INF_DESCRIPTION, \\r
695 DT.TAB_INF_BINARY_ABSTRACT, DT.TAB_INF_BINARY_DESCRIPTION, \\r
696 DT.TAB_DEC_PACKAGE_ABSTRACT, DT.TAB_DEC_PACKAGE_DESCRIPTION, \\r
697 DT.TAB_DEC_BINARY_ABSTRACT, DT.TAB_DEC_BINARY_DESCRIPTION]:\r
698 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
699 Message=ST.ERR_UNIPARSE_MULTI_ENTRY_EXIST % StrName.split()[1], \\r
f7496d71 700 ExtraData=File.Path)\r
421ccda3
HC
701 if IsIncludeFile:\r
702 if StrName not in NewLines:\r
703 NewLines.append((Line[:Line.find(u'#language')]).strip())\r
f7496d71 704 else:\r
421ccda3
HC
705 NewLines.append((Line[:Line.find(u'#language')]).strip())\r
706 NewLines.append((Line[Line.find(u'#language'):Line.find(u'"')]).strip())\r
707 NewLines.append((Line[Line.find(u'"'):]).strip())\r
708 else:\r
709 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
710 elif Line.startswith(u'#language'):\r
711 if len(Line.split()) == 2:\r
712 if IsIncludeFile:\r
713 if StrName not in NewLines:\r
714 NewLines.append(StrName)\r
715 else:\r
716 NewLines.append(StrName)\r
717 NewLines.append(Line)\r
718 elif len(Line.split()) > 2 and Line.find(u'"') > 0:\r
719 if IsIncludeFile:\r
720 if StrName not in NewLines:\r
721 NewLines.append(StrName)\r
722 else:\r
723 NewLines.append(StrName)\r
724 NewLines.append((Line[:Line.find(u'"')]).strip())\r
725 NewLines.append((Line[Line.find(u'"'):]).strip())\r
726 else:\r
727 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
728 elif Line.startswith(u'"'):\r
729 if u'#string' in Line or u'#language' in Line:\r
730 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
731 NewLines.append(Line)\r
732 else:\r
72443dd2 733 print(Line)\r
421ccda3 734 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
f7496d71 735\r
421ccda3
HC
736 if StrName and not StrName.split()[1].startswith(u'STR_'):\r
737 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
738 Message=ST.ERR_UNIPARSE_STRNAME_FORMAT_ERROR % StrName.split()[1], \\r
f7496d71
LG
739 ExtraData=File.Path)\r
740\r
421ccda3
HC
741 if StrName and not NewLines:\r
742 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
743 Message=ST.ERR_UNI_MISS_LANGENTRY % StrName, \\r
744 ExtraData=File.Path)\r
f7496d71 745\r
421ccda3
HC
746 #\r
747 # Check Abstract, Description, BinaryAbstract and BinaryDescription order,\r
748 # should be Abstract, Description, BinaryAbstract, BinaryDesctiption\r
749 AbstractPosition = -1\r
750 DescriptionPosition = -1\r
751 BinaryAbstractPosition = -1\r
752 BinaryDescriptionPosition = -1\r
753 for StrName in ExistStrNameList:\r
754 if DT.TAB_HEADER_ABSTRACT.upper() in StrName:\r
755 if 'BINARY' in StrName:\r
756 BinaryAbstractPosition = ExistStrNameList.index(StrName)\r
757 else:\r
758 AbstractPosition = ExistStrNameList.index(StrName)\r
759 if DT.TAB_HEADER_DESCRIPTION.upper() in StrName:\r
760 if 'BINARY' in StrName:\r
761 BinaryDescriptionPosition = ExistStrNameList.index(StrName)\r
762 else:\r
763 DescriptionPosition = ExistStrNameList.index(StrName)\r
f7496d71 764\r
421ccda3
HC
765 OrderList = sorted([AbstractPosition, DescriptionPosition])\r
766 BinaryOrderList = sorted([BinaryAbstractPosition, BinaryDescriptionPosition])\r
767 Min = OrderList[0]\r
768 Max = OrderList[1]\r
769 BinaryMin = BinaryOrderList[0]\r
770 BinaryMax = BinaryOrderList[1]\r
771 if BinaryDescriptionPosition > -1:\r
772 if not(BinaryDescriptionPosition == BinaryMax and BinaryAbstractPosition == BinaryMin and \\r
773 BinaryMax > Max):\r
774 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
775 Message=ST.ERR_UNIPARSE_ENTRY_ORDER_WRONG, \\r
f7496d71 776 ExtraData=File.Path)\r
421ccda3
HC
777 elif BinaryAbstractPosition > -1:\r
778 if not(BinaryAbstractPosition > Max):\r
779 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
780 Message=ST.ERR_UNIPARSE_ENTRY_ORDER_WRONG, \\r
f7496d71
LG
781 ExtraData=File.Path)\r
782\r
421ccda3
HC
783 if DescriptionPosition > -1:\r
784 if not(DescriptionPosition == Max and AbstractPosition == Min and \\r
785 DescriptionPosition > AbstractPosition):\r
786 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
787 Message=ST.ERR_UNIPARSE_ENTRY_ORDER_WRONG, \\r
f7496d71
LG
788 ExtraData=File.Path)\r
789\r
421ccda3 790 if not self.UniFileHeader:\r
f7496d71 791 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
421ccda3
HC
792 Message = ST.ERR_NO_SOURCE_HEADER,\r
793 ExtraData=File.Path)\r
f7496d71 794\r
421ccda3
HC
795 return NewLines\r
796\r
797 #\r
798 # Load a .uni file\r
799 #\r
800 def LoadUniFile(self, File = None):\r
4231a819 801 if File is None:\r
f7496d71
LG
802 EdkLogger.Error("Unicode File Parser",\r
803 ToolError.PARSER_ERROR,\r
804 Message='No unicode file is given',\r
421ccda3 805 ExtraData=File.Path)\r
f7496d71 806\r
421ccda3 807 self.File = File\r
f7496d71 808\r
421ccda3
HC
809 #\r
810 # Process special char in file\r
811 #\r
812 Lines = self.PreProcess(File)\r
813\r
814 #\r
815 # Get Unicode Information\r
816 #\r
817 for IndexI in range(len(Lines)):\r
818 Line = Lines[IndexI]\r
819 if (IndexI + 1) < len(Lines):\r
820 SecondLine = Lines[IndexI + 1]\r
821 if (IndexI + 2) < len(Lines):\r
822 ThirdLine = Lines[IndexI + 2]\r
823\r
824 #\r
825 # Get Language def information\r
826 #\r
827 if Line.find(u'#langdef ') >= 0:\r
828 self.GetLangDef(File, Line + u' ' + SecondLine)\r
829 continue\r
830\r
831 Name = ''\r
832 Language = ''\r
833 Value = ''\r
834 CombineToken = False\r
835 #\r
836 # Get string def information format as below\r
837 #\r
838 # #string MY_STRING_1\r
839 # #language eng\r
840 # "My first English string line 1"\r
841 # "My first English string line 2"\r
842 # #string MY_STRING_1\r
843 # #language spa\r
844 # "Mi segunda secuencia 1"\r
845 # "Mi segunda secuencia 2"\r
846 #\r
847 if Line.find(u'#string ') >= 0 and Line.find(u'#language ') < 0 and \\r
848 SecondLine.find(u'#string ') < 0 and SecondLine.find(u'#language ') >= 0 and \\r
849 ThirdLine.find(u'#string ') < 0 and ThirdLine.find(u'#language ') < 0:\r
850 if Line.find('"') > 0 or SecondLine.find('"') > 0:\r
f7496d71 851 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
421ccda3
HC
852 Message=ST.ERR_UNIPARSE_DBLQUOTE_UNMATCHED,\r
853 ExtraData=File.Path)\r
f7496d71 854\r
421ccda3
HC
855 Name = Line[Line.find(u'#string ') + len(u'#string ') : ].strip(' ')\r
856 Language = SecondLine[SecondLine.find(u'#language ') + len(u'#language ') : ].strip(' ')\r
857 for IndexJ in range(IndexI + 2, len(Lines)):\r
858 if Lines[IndexJ].find(u'#string ') < 0 and Lines[IndexJ].find(u'#language ') < 0 and \\r
859 Lines[IndexJ].strip().startswith(u'"') and Lines[IndexJ].strip().endswith(u'"'):\r
860 if Lines[IndexJ][-2] == ' ':\r
861 CombineToken = True\r
862 if CombineToken:\r
863 if Lines[IndexJ].strip()[1:-1].strip():\r
864 Value = Value + Lines[IndexJ].strip()[1:-1].rstrip() + ' '\r
865 else:\r
866 Value = Value + Lines[IndexJ].strip()[1:-1]\r
867 CombineToken = False\r
868 else:\r
1b2e0772 869 Value = Value + Lines[IndexJ].strip()[1:-1] + '\n'\r
421ccda3
HC
870 else:\r
871 IndexI = IndexJ\r
872 break\r
1b2e0772
YZ
873 if Value.endswith('\n'):\r
874 Value = Value[: Value.rfind('\n')]\r
421ccda3
HC
875 Language = GetLanguageCode(Language, self.IsCompatibleMode, self.File)\r
876 self.AddStringToList(Name, Language, Value)\r
877 continue\r
878\r
879 #\r
880 # Load multiple .uni files\r
881 #\r
882 def LoadUniFiles(self, FileList):\r
883 if len(FileList) > 0:\r
884 for File in FileList:\r
885 FilePath = File.Path.strip()\r
886 if FilePath.endswith('.uni') or FilePath.endswith('.UNI') or FilePath.endswith('.Uni'):\r
887 self.LoadUniFile(File)\r
888\r
889 #\r
890 # Add a string to list\r
891 #\r
892 def AddStringToList(self, Name, Language, Value, Token = 0, Referenced = False, UseOtherLangDef = '', Index = -1):\r
893 for LangNameItem in self.LanguageDef:\r
894 if Language == LangNameItem[0]:\r
895 break\r
f7496d71 896\r
421ccda3
HC
897 if Language not in self.OrderedStringList:\r
898 self.OrderedStringList[Language] = []\r
899 self.OrderedStringDict[Language] = {}\r
f7496d71 900\r
421ccda3
HC
901 IsAdded = True\r
902 if Name in self.OrderedStringDict[Language]:\r
903 IsAdded = False\r
4231a819 904 if Value is not None:\r
421ccda3
HC
905 ItemIndexInList = self.OrderedStringDict[Language][Name]\r
906 Item = self.OrderedStringList[Language][ItemIndexInList]\r
907 Item.UpdateValue(Value)\r
f7496d71 908 Item.UseOtherLangDef = ''\r
421ccda3
HC
909\r
910 if IsAdded:\r
911 Token = len(self.OrderedStringList[Language])\r
912 if Index == -1:\r
f7496d71
LG
913 self.OrderedStringList[Language].append(StringDefClassObject(Name,\r
914 Value,\r
915 Referenced,\r
916 Token,\r
421ccda3
HC
917 UseOtherLangDef))\r
918 self.OrderedStringDict[Language][Name] = Token\r
919 for LangName in self.LanguageDef:\r
920 #\r
921 # New STRING token will be added into all language string lists.\r
f7496d71 922 # so that the unique STRING identifier is reserved for all languages in the package list.\r
421ccda3
HC
923 #\r
924 if LangName[0] != Language:\r
925 if UseOtherLangDef != '':\r
926 OtherLangDef = UseOtherLangDef\r
927 else:\r
928 OtherLangDef = Language\r
f7496d71
LG
929 self.OrderedStringList[LangName[0]].append(StringDefClassObject(Name,\r
930 '',\r
931 Referenced,\r
932 Token,\r
421ccda3
HC
933 OtherLangDef))\r
934 self.OrderedStringDict[LangName[0]][Name] = len(self.OrderedStringList[LangName[0]]) - 1\r
935 else:\r
f7496d71
LG
936 self.OrderedStringList[Language].insert(Index, StringDefClassObject(Name,\r
937 Value,\r
938 Referenced,\r
939 Token,\r
421ccda3
HC
940 UseOtherLangDef))\r
941 self.OrderedStringDict[Language][Name] = Index\r
942\r
943 #\r
944 # Set the string as referenced\r
945 #\r
946 def SetStringReferenced(self, Name):\r
947 #\r
948 # String stoken are added in the same order in all language string lists.\r
949 # So, only update the status of string stoken in first language string list.\r
950 #\r
951 Lang = self.LanguageDef[0][0]\r
952 if Name in self.OrderedStringDict[Lang]:\r
953 ItemIndexInList = self.OrderedStringDict[Lang][Name]\r
954 Item = self.OrderedStringList[Lang][ItemIndexInList]\r
955 Item.Referenced = True\r
956\r
957 #\r
958 # Search the string in language definition by Name\r
959 #\r
960 def FindStringValue(self, Name, Lang):\r
961 if Name in self.OrderedStringDict[Lang]:\r
962 ItemIndexInList = self.OrderedStringDict[Lang][Name]\r
963 return self.OrderedStringList[Lang][ItemIndexInList]\r
964\r
965 return None\r
966\r
967 #\r
968 # Search the string in language definition by Token\r
969 #\r
970 def FindByToken(self, Token, Lang):\r
971 for Item in self.OrderedStringList[Lang]:\r
972 if Item.Token == Token:\r
973 return Item\r
974\r
975 return None\r
976\r
977 #\r
978 # Re-order strings and re-generate tokens\r
979 #\r
980 def ReToken(self):\r
981 if len(self.LanguageDef) == 0:\r
982 return None\r
983 #\r
984 # Retoken all language strings according to the status of string stoken in the first language string.\r
985 #\r
986 FirstLangName = self.LanguageDef[0][0]\r
987\r
988 # Convert the OrderedStringList to be OrderedStringListByToken in order to faciliate future search by token\r
989 for LangNameItem in self.LanguageDef:\r
990 self.OrderedStringListByToken[LangNameItem[0]] = {}\r
991\r
992 #\r
993 # Use small token for all referred string stoken.\r
994 #\r
995 RefToken = 0\r
996 for Index in range (0, len (self.OrderedStringList[FirstLangName])):\r
997 FirstLangItem = self.OrderedStringList[FirstLangName][Index]\r
998 if FirstLangItem.Referenced == True:\r
999 for LangNameItem in self.LanguageDef:\r
1000 LangName = LangNameItem[0]\r
1001 OtherLangItem = self.OrderedStringList[LangName][Index]\r
1002 OtherLangItem.Referenced = True\r
1003 OtherLangItem.Token = RefToken\r
1004 self.OrderedStringListByToken[LangName][OtherLangItem.Token] = OtherLangItem\r
1005 RefToken = RefToken + 1\r
1006\r
1007 #\r
1008 # Use big token for all unreferred string stoken.\r
1009 #\r
1010 UnRefToken = 0\r
1011 for Index in range (0, len (self.OrderedStringList[FirstLangName])):\r
1012 FirstLangItem = self.OrderedStringList[FirstLangName][Index]\r
1013 if FirstLangItem.Referenced == False:\r
1014 for LangNameItem in self.LanguageDef:\r
1015 LangName = LangNameItem[0]\r
1016 OtherLangItem = self.OrderedStringList[LangName][Index]\r
1017 OtherLangItem.Token = RefToken + UnRefToken\r
1018 self.OrderedStringListByToken[LangName][OtherLangItem.Token] = OtherLangItem\r
1019 UnRefToken = UnRefToken + 1\r
1020\r
1021 #\r
1022 # Show the instance itself\r
1023 #\r
1024 def ShowMe(self):\r
72443dd2 1025 print(self.LanguageDef)\r
421ccda3
HC
1026 #print self.OrderedStringList\r
1027 for Item in self.OrderedStringList:\r
72443dd2 1028 print(Item)\r
421ccda3 1029 for Member in self.OrderedStringList[Item]:\r
72443dd2 1030 print(str(Member))\r
f7496d71 1031\r
421ccda3 1032 #\r
f7496d71 1033 # Read content from '!include' UNI file\r
421ccda3
HC
1034 #\r
1035 def ReadIncludeUNIfile(self, FilaPath):\r
1036 if self.File:\r
1037 pass\r
f7496d71 1038\r
421ccda3 1039 if not os.path.exists(FilaPath) or not os.path.isfile(FilaPath):\r
f7496d71 1040 EdkLogger.Error("Unicode File Parser",\r
421ccda3
HC
1041 ToolError.FILE_NOT_FOUND,\r
1042 ExtraData=FilaPath)\r
1043 try:\r
645a5128 1044 FileIn = codecs.open(FilaPath, mode='rb', encoding='utf_8').readlines()\r
5b0671c1 1045 except UnicodeError as Xstr:\r
421ccda3
HC
1046 FileIn = codecs.open(FilaPath, mode='rb', encoding='utf_16').readlines()\r
1047 except UnicodeError:\r
1048 FileIn = codecs.open(FilaPath, mode='rb', encoding='utf_16_le').readlines()\r
1049 except:\r
1050 EdkLogger.Error("Unicode File Parser", ToolError.FILE_OPEN_FAILURE, ExtraData=FilaPath)\r
1051 return FileIn\r
1052\r