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