]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/UPT/Library/UniClassObject.py
BaseTools: Correct the error message for UPT
[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
8059cd24 4# Copyright (c) 2014 - 2019, 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
8059cd24
FB
600\r
601 #\r
602 # Check the situation that there has more than 2 '"' for the language entry\r
603 #\r
604 if Line.strip() and Line.replace(u'\\"', '').count(u'"') > 2:\r
605 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
606 ExtraData='''The line %s has more than 2 '"' for language entry in file %s'''\r
607 % (LineCount, File.Path))\r
608\r
421ccda3
HC
609 elif Line.startswith(u'#language'):\r
610 if StringEntryExistsFlag == 2:\r
645a5128 611 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
fe90f483 612 Message=ST.ERR_UNI_MISS_STRING_ENTRY % Line, ExtraData=File.Path)\r
421ccda3
HC
613 StringEntryExistsFlag = 0\r
614 else:\r
615 StringEntryExistsFlag = 0\r
616\r
617 Lines.append(Line)\r
f7496d71 618\r
421ccda3
HC
619 #\r
620 # Convert string def format as below\r
621 #\r
622 # #string MY_STRING_1\r
623 # #language eng\r
624 # "My first English string line 1"\r
625 # "My first English string line 2"\r
626 # #string MY_STRING_1\r
627 # #language spa\r
628 # "Mi segunda secuencia 1"\r
629 # "Mi segunda secuencia 2"\r
630 #\r
f7496d71 631\r
421ccda3
HC
632 if not IsIncludeFile and not Lines:\r
633 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
634 Message=ST.ERR_UNIPARSE_NO_SECTION_EXIST, \\r
f7496d71 635 ExtraData=File.Path)\r
421ccda3
HC
636\r
637 NewLines = []\r
638 StrName = u''\r
639 ExistStrNameList = []\r
640 for Line in Lines:\r
641 if StrName and not StrName.split()[1].startswith(DT.TAB_STR_TOKENCNAME + DT.TAB_UNDERLINE_SPLIT):\r
642 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
643 Message=ST.ERR_UNIPARSE_STRNAME_FORMAT_ERROR % StrName.split()[1], \\r
644 ExtraData=File.Path)\r
f7496d71 645\r
421ccda3
HC
646 if StrName and len(StrName.split()[1].split(DT.TAB_UNDERLINE_SPLIT)) == 4:\r
647 StringTokenList = StrName.split()[1].split(DT.TAB_UNDERLINE_SPLIT)\r
648 if (StringTokenList[3].upper() in [DT.TAB_STR_TOKENPROMPT, DT.TAB_STR_TOKENHELP] and \\r
649 StringTokenList[3] not in [DT.TAB_STR_TOKENPROMPT, DT.TAB_STR_TOKENHELP]) or \\r
650 (StringTokenList[2].upper() == DT.TAB_STR_TOKENERR and StringTokenList[2] != DT.TAB_STR_TOKENERR):\r
651 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
652 Message=ST.ERR_UNIPARSE_STRTOKEN_FORMAT_ERROR % StrName.split()[1], \\r
653 ExtraData=File.Path)\r
f7496d71 654\r
421ccda3
HC
655 if Line.count(u'#language') > 1:\r
656 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
657 Message=ST.ERR_UNIPARSE_SEP_LANGENTRY_LINE % Line, \\r
f7496d71
LG
658 ExtraData=File.Path)\r
659\r
421ccda3
HC
660 if Line.startswith(u'//'):\r
661 continue\r
662 elif Line.startswith(u'#langdef'):\r
663 if len(Line.split()) == 2:\r
664 NewLines.append(Line)\r
665 continue\r
f7496d71 666 elif len(Line.split()) > 2 and Line.find(u'"') > 0:\r
421ccda3
HC
667 NewLines.append(Line[:Line.find(u'"')].strip())\r
668 NewLines.append(Line[Line.find(u'"'):])\r
669 else:\r
670 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
671 elif Line.startswith(u'#string'):\r
672 if len(Line.split()) == 2:\r
673 StrName = Line\r
674 if StrName:\r
675 if StrName.split()[1] not in ExistStrNameList:\r
676 ExistStrNameList.append(StrName.split()[1].strip())\r
677 elif StrName.split()[1] in [DT.TAB_INF_ABSTRACT, DT.TAB_INF_DESCRIPTION, \\r
678 DT.TAB_INF_BINARY_ABSTRACT, DT.TAB_INF_BINARY_DESCRIPTION, \\r
679 DT.TAB_DEC_PACKAGE_ABSTRACT, DT.TAB_DEC_PACKAGE_DESCRIPTION, \\r
680 DT.TAB_DEC_BINARY_ABSTRACT, DT.TAB_DEC_BINARY_DESCRIPTION]:\r
681 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
682 Message=ST.ERR_UNIPARSE_MULTI_ENTRY_EXIST % StrName.split()[1], \\r
683 ExtraData=File.Path)\r
684 continue\r
685 elif len(Line.split()) == 4 and Line.find(u'#language') > 0:\r
686 if Line[Line.find(u'#language')-1] != ' ' or \\r
687 Line[Line.find(u'#language')+len(u'#language')] != u' ':\r
688 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
f7496d71 689\r
421ccda3
HC
690 if Line.find(u'"') > 0:\r
691 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
f7496d71 692\r
421ccda3
HC
693 StrName = Line.split()[0] + u' ' + Line.split()[1]\r
694 if StrName:\r
695 if StrName.split()[1] not in ExistStrNameList:\r
696 ExistStrNameList.append(StrName.split()[1].strip())\r
697 elif StrName.split()[1] in [DT.TAB_INF_ABSTRACT, DT.TAB_INF_DESCRIPTION, \\r
698 DT.TAB_INF_BINARY_ABSTRACT, DT.TAB_INF_BINARY_DESCRIPTION, \\r
699 DT.TAB_DEC_PACKAGE_ABSTRACT, DT.TAB_DEC_PACKAGE_DESCRIPTION, \\r
700 DT.TAB_DEC_BINARY_ABSTRACT, DT.TAB_DEC_BINARY_DESCRIPTION]:\r
701 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
702 Message=ST.ERR_UNIPARSE_MULTI_ENTRY_EXIST % StrName.split()[1], \\r
703 ExtraData=File.Path)\r
704 if IsIncludeFile:\r
705 if StrName not in NewLines:\r
706 NewLines.append((Line[:Line.find(u'#language')]).strip())\r
707 else:\r
708 NewLines.append((Line[:Line.find(u'#language')]).strip())\r
709 NewLines.append((Line[Line.find(u'#language'):]).strip())\r
710 elif len(Line.split()) > 4 and Line.find(u'#language') > 0 and Line.find(u'"') > 0:\r
711 if Line[Line.find(u'#language')-1] != u' ' or \\r
712 Line[Line.find(u'#language')+len(u'#language')] != u' ':\r
713 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
f7496d71 714\r
421ccda3 715 if Line[Line.find(u'"')-1] != u' ':\r
f7496d71
LG
716 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
717\r
718 StrName = Line.split()[0] + u' ' + Line.split()[1]\r
421ccda3
HC
719 if StrName:\r
720 if StrName.split()[1] not in ExistStrNameList:\r
721 ExistStrNameList.append(StrName.split()[1].strip())\r
722 elif StrName.split()[1] in [DT.TAB_INF_ABSTRACT, DT.TAB_INF_DESCRIPTION, \\r
723 DT.TAB_INF_BINARY_ABSTRACT, DT.TAB_INF_BINARY_DESCRIPTION, \\r
724 DT.TAB_DEC_PACKAGE_ABSTRACT, DT.TAB_DEC_PACKAGE_DESCRIPTION, \\r
725 DT.TAB_DEC_BINARY_ABSTRACT, DT.TAB_DEC_BINARY_DESCRIPTION]:\r
726 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
727 Message=ST.ERR_UNIPARSE_MULTI_ENTRY_EXIST % StrName.split()[1], \\r
f7496d71 728 ExtraData=File.Path)\r
421ccda3
HC
729 if IsIncludeFile:\r
730 if StrName not in NewLines:\r
731 NewLines.append((Line[:Line.find(u'#language')]).strip())\r
f7496d71 732 else:\r
421ccda3
HC
733 NewLines.append((Line[:Line.find(u'#language')]).strip())\r
734 NewLines.append((Line[Line.find(u'#language'):Line.find(u'"')]).strip())\r
735 NewLines.append((Line[Line.find(u'"'):]).strip())\r
736 else:\r
737 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
738 elif Line.startswith(u'#language'):\r
739 if len(Line.split()) == 2:\r
740 if IsIncludeFile:\r
741 if StrName not in NewLines:\r
742 NewLines.append(StrName)\r
743 else:\r
744 NewLines.append(StrName)\r
745 NewLines.append(Line)\r
746 elif len(Line.split()) > 2 and Line.find(u'"') > 0:\r
747 if IsIncludeFile:\r
748 if StrName not in NewLines:\r
749 NewLines.append(StrName)\r
750 else:\r
751 NewLines.append(StrName)\r
752 NewLines.append((Line[:Line.find(u'"')]).strip())\r
753 NewLines.append((Line[Line.find(u'"'):]).strip())\r
754 else:\r
755 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
756 elif Line.startswith(u'"'):\r
757 if u'#string' in Line or u'#language' in Line:\r
758 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
759 NewLines.append(Line)\r
760 else:\r
72443dd2 761 print(Line)\r
421ccda3 762 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
f7496d71 763\r
421ccda3
HC
764 if StrName and not StrName.split()[1].startswith(u'STR_'):\r
765 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
766 Message=ST.ERR_UNIPARSE_STRNAME_FORMAT_ERROR % StrName.split()[1], \\r
f7496d71
LG
767 ExtraData=File.Path)\r
768\r
421ccda3
HC
769 if StrName and not NewLines:\r
770 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
771 Message=ST.ERR_UNI_MISS_LANGENTRY % StrName, \\r
772 ExtraData=File.Path)\r
f7496d71 773\r
421ccda3
HC
774 #\r
775 # Check Abstract, Description, BinaryAbstract and BinaryDescription order,\r
fb0b35e0 776 # should be Abstract, Description, BinaryAbstract, BinaryDescription\r
421ccda3
HC
777 AbstractPosition = -1\r
778 DescriptionPosition = -1\r
779 BinaryAbstractPosition = -1\r
780 BinaryDescriptionPosition = -1\r
781 for StrName in ExistStrNameList:\r
782 if DT.TAB_HEADER_ABSTRACT.upper() in StrName:\r
783 if 'BINARY' in StrName:\r
784 BinaryAbstractPosition = ExistStrNameList.index(StrName)\r
785 else:\r
786 AbstractPosition = ExistStrNameList.index(StrName)\r
787 if DT.TAB_HEADER_DESCRIPTION.upper() in StrName:\r
788 if 'BINARY' in StrName:\r
789 BinaryDescriptionPosition = ExistStrNameList.index(StrName)\r
790 else:\r
791 DescriptionPosition = ExistStrNameList.index(StrName)\r
f7496d71 792\r
421ccda3
HC
793 OrderList = sorted([AbstractPosition, DescriptionPosition])\r
794 BinaryOrderList = sorted([BinaryAbstractPosition, BinaryDescriptionPosition])\r
795 Min = OrderList[0]\r
796 Max = OrderList[1]\r
797 BinaryMin = BinaryOrderList[0]\r
798 BinaryMax = BinaryOrderList[1]\r
799 if BinaryDescriptionPosition > -1:\r
800 if not(BinaryDescriptionPosition == BinaryMax and BinaryAbstractPosition == BinaryMin and \\r
801 BinaryMax > Max):\r
802 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
803 Message=ST.ERR_UNIPARSE_ENTRY_ORDER_WRONG, \\r
f7496d71 804 ExtraData=File.Path)\r
421ccda3
HC
805 elif BinaryAbstractPosition > -1:\r
806 if not(BinaryAbstractPosition > Max):\r
807 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
808 Message=ST.ERR_UNIPARSE_ENTRY_ORDER_WRONG, \\r
f7496d71
LG
809 ExtraData=File.Path)\r
810\r
421ccda3
HC
811 if DescriptionPosition > -1:\r
812 if not(DescriptionPosition == Max and AbstractPosition == Min and \\r
813 DescriptionPosition > AbstractPosition):\r
814 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
815 Message=ST.ERR_UNIPARSE_ENTRY_ORDER_WRONG, \\r
f7496d71
LG
816 ExtraData=File.Path)\r
817\r
421ccda3 818 if not self.UniFileHeader:\r
f7496d71 819 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
421ccda3
HC
820 Message = ST.ERR_NO_SOURCE_HEADER,\r
821 ExtraData=File.Path)\r
f7496d71 822\r
421ccda3
HC
823 return NewLines\r
824\r
825 #\r
826 # Load a .uni file\r
827 #\r
828 def LoadUniFile(self, File = None):\r
4231a819 829 if File is None:\r
f7496d71
LG
830 EdkLogger.Error("Unicode File Parser",\r
831 ToolError.PARSER_ERROR,\r
832 Message='No unicode file is given',\r
421ccda3 833 ExtraData=File.Path)\r
f7496d71 834\r
421ccda3 835 self.File = File\r
f7496d71 836\r
421ccda3
HC
837 #\r
838 # Process special char in file\r
839 #\r
840 Lines = self.PreProcess(File)\r
841\r
842 #\r
843 # Get Unicode Information\r
844 #\r
845 for IndexI in range(len(Lines)):\r
846 Line = Lines[IndexI]\r
847 if (IndexI + 1) < len(Lines):\r
848 SecondLine = Lines[IndexI + 1]\r
849 if (IndexI + 2) < len(Lines):\r
850 ThirdLine = Lines[IndexI + 2]\r
851\r
852 #\r
853 # Get Language def information\r
854 #\r
855 if Line.find(u'#langdef ') >= 0:\r
856 self.GetLangDef(File, Line + u' ' + SecondLine)\r
857 continue\r
858\r
859 Name = ''\r
860 Language = ''\r
861 Value = ''\r
862 CombineToken = False\r
863 #\r
864 # Get string def information format as below\r
865 #\r
866 # #string MY_STRING_1\r
867 # #language eng\r
868 # "My first English string line 1"\r
869 # "My first English string line 2"\r
870 # #string MY_STRING_1\r
871 # #language spa\r
872 # "Mi segunda secuencia 1"\r
873 # "Mi segunda secuencia 2"\r
874 #\r
875 if Line.find(u'#string ') >= 0 and Line.find(u'#language ') < 0 and \\r
876 SecondLine.find(u'#string ') < 0 and SecondLine.find(u'#language ') >= 0 and \\r
877 ThirdLine.find(u'#string ') < 0 and ThirdLine.find(u'#language ') < 0:\r
878 if Line.find('"') > 0 or SecondLine.find('"') > 0:\r
f7496d71 879 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
421ccda3
HC
880 Message=ST.ERR_UNIPARSE_DBLQUOTE_UNMATCHED,\r
881 ExtraData=File.Path)\r
f7496d71 882\r
421ccda3
HC
883 Name = Line[Line.find(u'#string ') + len(u'#string ') : ].strip(' ')\r
884 Language = SecondLine[SecondLine.find(u'#language ') + len(u'#language ') : ].strip(' ')\r
885 for IndexJ in range(IndexI + 2, len(Lines)):\r
886 if Lines[IndexJ].find(u'#string ') < 0 and Lines[IndexJ].find(u'#language ') < 0 and \\r
887 Lines[IndexJ].strip().startswith(u'"') and Lines[IndexJ].strip().endswith(u'"'):\r
888 if Lines[IndexJ][-2] == ' ':\r
889 CombineToken = True\r
890 if CombineToken:\r
891 if Lines[IndexJ].strip()[1:-1].strip():\r
892 Value = Value + Lines[IndexJ].strip()[1:-1].rstrip() + ' '\r
893 else:\r
894 Value = Value + Lines[IndexJ].strip()[1:-1]\r
895 CombineToken = False\r
896 else:\r
1ccc4d89 897 Value = Value + Lines[IndexJ].strip()[1:-1] + '\r\n'\r
421ccda3
HC
898 else:\r
899 IndexI = IndexJ\r
900 break\r
1ccc4d89
LG
901 if Value.endswith('\r\n'):\r
902 Value = Value[: Value.rfind('\r\n')]\r
421ccda3
HC
903 Language = GetLanguageCode(Language, self.IsCompatibleMode, self.File)\r
904 self.AddStringToList(Name, Language, Value)\r
905 continue\r
906\r
907 #\r
908 # Load multiple .uni files\r
909 #\r
910 def LoadUniFiles(self, FileList):\r
911 if len(FileList) > 0:\r
912 for File in FileList:\r
913 FilePath = File.Path.strip()\r
914 if FilePath.endswith('.uni') or FilePath.endswith('.UNI') or FilePath.endswith('.Uni'):\r
915 self.LoadUniFile(File)\r
916\r
917 #\r
918 # Add a string to list\r
919 #\r
920 def AddStringToList(self, Name, Language, Value, Token = 0, Referenced = False, UseOtherLangDef = '', Index = -1):\r
921 for LangNameItem in self.LanguageDef:\r
922 if Language == LangNameItem[0]:\r
923 break\r
f7496d71 924\r
421ccda3
HC
925 if Language not in self.OrderedStringList:\r
926 self.OrderedStringList[Language] = []\r
927 self.OrderedStringDict[Language] = {}\r
f7496d71 928\r
421ccda3
HC
929 IsAdded = True\r
930 if Name in self.OrderedStringDict[Language]:\r
931 IsAdded = False\r
4231a819 932 if Value is not None:\r
421ccda3
HC
933 ItemIndexInList = self.OrderedStringDict[Language][Name]\r
934 Item = self.OrderedStringList[Language][ItemIndexInList]\r
935 Item.UpdateValue(Value)\r
f7496d71 936 Item.UseOtherLangDef = ''\r
421ccda3
HC
937\r
938 if IsAdded:\r
939 Token = len(self.OrderedStringList[Language])\r
940 if Index == -1:\r
f7496d71
LG
941 self.OrderedStringList[Language].append(StringDefClassObject(Name,\r
942 Value,\r
943 Referenced,\r
944 Token,\r
421ccda3
HC
945 UseOtherLangDef))\r
946 self.OrderedStringDict[Language][Name] = Token\r
947 for LangName in self.LanguageDef:\r
948 #\r
949 # New STRING token will be added into all language string lists.\r
f7496d71 950 # so that the unique STRING identifier is reserved for all languages in the package list.\r
421ccda3
HC
951 #\r
952 if LangName[0] != Language:\r
953 if UseOtherLangDef != '':\r
954 OtherLangDef = UseOtherLangDef\r
955 else:\r
956 OtherLangDef = Language\r
f7496d71
LG
957 self.OrderedStringList[LangName[0]].append(StringDefClassObject(Name,\r
958 '',\r
959 Referenced,\r
960 Token,\r
421ccda3
HC
961 OtherLangDef))\r
962 self.OrderedStringDict[LangName[0]][Name] = len(self.OrderedStringList[LangName[0]]) - 1\r
963 else:\r
f7496d71
LG
964 self.OrderedStringList[Language].insert(Index, StringDefClassObject(Name,\r
965 Value,\r
966 Referenced,\r
967 Token,\r
421ccda3
HC
968 UseOtherLangDef))\r
969 self.OrderedStringDict[Language][Name] = Index\r
970\r
971 #\r
972 # Set the string as referenced\r
973 #\r
974 def SetStringReferenced(self, Name):\r
975 #\r
976 # String stoken are added in the same order in all language string lists.\r
977 # So, only update the status of string stoken in first language string list.\r
978 #\r
979 Lang = self.LanguageDef[0][0]\r
980 if Name in self.OrderedStringDict[Lang]:\r
981 ItemIndexInList = self.OrderedStringDict[Lang][Name]\r
982 Item = self.OrderedStringList[Lang][ItemIndexInList]\r
983 Item.Referenced = True\r
984\r
985 #\r
986 # Search the string in language definition by Name\r
987 #\r
988 def FindStringValue(self, Name, Lang):\r
989 if Name in self.OrderedStringDict[Lang]:\r
990 ItemIndexInList = self.OrderedStringDict[Lang][Name]\r
991 return self.OrderedStringList[Lang][ItemIndexInList]\r
992\r
993 return None\r
994\r
995 #\r
996 # Search the string in language definition by Token\r
997 #\r
998 def FindByToken(self, Token, Lang):\r
999 for Item in self.OrderedStringList[Lang]:\r
1000 if Item.Token == Token:\r
1001 return Item\r
1002\r
1003 return None\r
1004\r
1005 #\r
1006 # Re-order strings and re-generate tokens\r
1007 #\r
1008 def ReToken(self):\r
1009 if len(self.LanguageDef) == 0:\r
1010 return None\r
1011 #\r
1012 # Retoken all language strings according to the status of string stoken in the first language string.\r
1013 #\r
1014 FirstLangName = self.LanguageDef[0][0]\r
1015\r
1016 # Convert the OrderedStringList to be OrderedStringListByToken in order to faciliate future search by token\r
1017 for LangNameItem in self.LanguageDef:\r
1018 self.OrderedStringListByToken[LangNameItem[0]] = {}\r
1019\r
1020 #\r
1021 # Use small token for all referred string stoken.\r
1022 #\r
1023 RefToken = 0\r
1024 for Index in range (0, len (self.OrderedStringList[FirstLangName])):\r
1025 FirstLangItem = self.OrderedStringList[FirstLangName][Index]\r
1026 if FirstLangItem.Referenced == True:\r
1027 for LangNameItem in self.LanguageDef:\r
1028 LangName = LangNameItem[0]\r
1029 OtherLangItem = self.OrderedStringList[LangName][Index]\r
1030 OtherLangItem.Referenced = True\r
1031 OtherLangItem.Token = RefToken\r
1032 self.OrderedStringListByToken[LangName][OtherLangItem.Token] = OtherLangItem\r
1033 RefToken = RefToken + 1\r
1034\r
1035 #\r
1036 # Use big token for all unreferred string stoken.\r
1037 #\r
1038 UnRefToken = 0\r
1039 for Index in range (0, len (self.OrderedStringList[FirstLangName])):\r
1040 FirstLangItem = self.OrderedStringList[FirstLangName][Index]\r
1041 if FirstLangItem.Referenced == False:\r
1042 for LangNameItem in self.LanguageDef:\r
1043 LangName = LangNameItem[0]\r
1044 OtherLangItem = self.OrderedStringList[LangName][Index]\r
1045 OtherLangItem.Token = RefToken + UnRefToken\r
1046 self.OrderedStringListByToken[LangName][OtherLangItem.Token] = OtherLangItem\r
1047 UnRefToken = UnRefToken + 1\r
1048\r
1049 #\r
1050 # Show the instance itself\r
1051 #\r
1052 def ShowMe(self):\r
72443dd2 1053 print(self.LanguageDef)\r
421ccda3
HC
1054 #print self.OrderedStringList\r
1055 for Item in self.OrderedStringList:\r
72443dd2 1056 print(Item)\r
421ccda3 1057 for Member in self.OrderedStringList[Item]:\r
72443dd2 1058 print(str(Member))\r
f7496d71 1059\r
421ccda3 1060 #\r
f7496d71 1061 # Read content from '!include' UNI file\r
421ccda3
HC
1062 #\r
1063 def ReadIncludeUNIfile(self, FilaPath):\r
1064 if self.File:\r
1065 pass\r
f7496d71 1066\r
421ccda3 1067 if not os.path.exists(FilaPath) or not os.path.isfile(FilaPath):\r
f7496d71 1068 EdkLogger.Error("Unicode File Parser",\r
421ccda3
HC
1069 ToolError.FILE_NOT_FOUND,\r
1070 ExtraData=FilaPath)\r
1071 try:\r
645a5128 1072 FileIn = codecs.open(FilaPath, mode='rb', encoding='utf_8').readlines()\r
5b0671c1 1073 except UnicodeError as Xstr:\r
421ccda3
HC
1074 FileIn = codecs.open(FilaPath, mode='rb', encoding='utf_16').readlines()\r
1075 except UnicodeError:\r
1076 FileIn = codecs.open(FilaPath, mode='rb', encoding='utf_16_le').readlines()\r
1077 except:\r
1078 EdkLogger.Error("Unicode File Parser", ToolError.FILE_OPEN_FAILURE, ExtraData=FilaPath)\r
1079 return FileIn\r
1080\r