]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/UPT/Library/UniClassObject.py
BaseTools/UPT: Fix an issue of UNI string checking.
[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
122 NewUni = Uni\r
123 NewUni = NewUni.replace(u'\u00A9', '(c)')\r
124 NewUni = NewUni.replace(u'\u00AE', '(r)')\r
125 NewUni = NewUni.replace(u'\u2122', '(tm)')\r
126 return NewUni\r
127\r
128## GetLanguageCode1766\r
129#\r
130# Check the language code read from .UNI file and convert RFC 4646 codes to RFC 1766 codes\r
131# RFC 1766 language codes supported in compatiblity mode\r
132# RFC 4646 language codes supported in native mode\r
133#\r
134# @param LangName: Language codes read from .UNI file\r
135#\r
136# @retval LangName: Valid lanugage code in RFC 1766 format or None\r
137#\r
138def GetLanguageCode1766(LangName, File=None):\r
fe90f483
HC
139 return LangName\r
140\r
421ccda3
HC
141 length = len(LangName)\r
142 if length == 2:\r
143 if LangName.isalpha():\r
144 for Key in gLANG_CONV_TABLE.keys():\r
145 if gLANG_CONV_TABLE.get(Key) == LangName.lower():\r
146 return Key\r
147 elif length == 3:\r
148 if LangName.isalpha() and gLANG_CONV_TABLE.get(LangName.lower()):\r
149 return LangName\r
150 else:\r
f7496d71 151 EdkLogger.Error("Unicode File Parser",\r
421ccda3 152 ToolError.FORMAT_INVALID,\r
f7496d71 153 "Invalid RFC 1766 language code : %s" % LangName,\r
421ccda3
HC
154 File)\r
155 elif length == 5:\r
156 if LangName[0:2].isalpha() and LangName[2] == '-':\r
157 for Key in gLANG_CONV_TABLE.keys():\r
158 if gLANG_CONV_TABLE.get(Key) == LangName[0:2].lower():\r
159 return Key\r
160 elif length >= 6:\r
161 if LangName[0:2].isalpha() and LangName[2] == '-':\r
162 for Key in gLANG_CONV_TABLE.keys():\r
163 if gLANG_CONV_TABLE.get(Key) == LangName[0:2].lower():\r
164 return Key\r
4231a819 165 if LangName[0:3].isalpha() and gLANG_CONV_TABLE.get(LangName.lower()) is None and LangName[3] == '-':\r
421ccda3
HC
166 for Key in gLANG_CONV_TABLE.keys():\r
167 if Key == LangName[0:3].lower():\r
168 return Key\r
169\r
f7496d71 170 EdkLogger.Error("Unicode File Parser",\r
421ccda3 171 ToolError.FORMAT_INVALID,\r
f7496d71 172 "Invalid RFC 4646 language code : %s" % LangName,\r
421ccda3 173 File)\r
f7496d71 174\r
421ccda3
HC
175## GetLanguageCode\r
176#\r
177# Check the language code read from .UNI file and convert RFC 1766 codes to RFC 4646 codes if appropriate\r
178# RFC 1766 language codes supported in compatiblity mode\r
179# RFC 4646 language codes supported in native mode\r
180#\r
181# @param LangName: Language codes read from .UNI file\r
182#\r
183# @retval LangName: Valid lanugage code in RFC 4646 format or None\r
184#\r
185def GetLanguageCode(LangName, IsCompatibleMode, File):\r
186 length = len(LangName)\r
187 if IsCompatibleMode:\r
188 if length == 3 and LangName.isalpha():\r
189 TempLangName = gLANG_CONV_TABLE.get(LangName.lower())\r
4231a819 190 if TempLangName is not None:\r
421ccda3
HC
191 return TempLangName\r
192 return LangName\r
193 else:\r
f7496d71 194 EdkLogger.Error("Unicode File Parser",\r
421ccda3 195 ToolError.FORMAT_INVALID,\r
f7496d71 196 "Invalid RFC 1766 language code : %s" % LangName,\r
421ccda3
HC
197 File)\r
198 if (LangName[0] == 'X' or LangName[0] == 'x') and LangName[1] == '-':\r
199 return LangName\r
200 if length == 2:\r
201 if LangName.isalpha():\r
202 return LangName\r
203 elif length == 3:\r
4231a819 204 if LangName.isalpha() and gLANG_CONV_TABLE.get(LangName.lower()) is None:\r
421ccda3
HC
205 return LangName\r
206 elif length == 5:\r
207 if LangName[0:2].isalpha() and LangName[2] == '-':\r
208 return LangName\r
209 elif length >= 6:\r
210 if LangName[0:2].isalpha() and LangName[2] == '-':\r
211 return LangName\r
4231a819 212 if LangName[0:3].isalpha() and gLANG_CONV_TABLE.get(LangName.lower()) is None and LangName[3] == '-':\r
421ccda3
HC
213 return LangName\r
214\r
f7496d71 215 EdkLogger.Error("Unicode File Parser",\r
421ccda3 216 ToolError.FORMAT_INVALID,\r
f7496d71 217 "Invalid RFC 4646 language code : %s" % LangName,\r
421ccda3
HC
218 File)\r
219\r
220## FormatUniEntry\r
221#\r
222# Formated the entry in Uni file.\r
223#\r
224# @param StrTokenName StrTokenName.\r
225# @param TokenValueList A list need to be processed.\r
226# @param ContainerFile ContainerFile.\r
227#\r
228# @return formated entry\r
229def FormatUniEntry(StrTokenName, TokenValueList, ContainerFile):\r
230 SubContent = ''\r
231 PreFormatLength = 40\r
232 if len(StrTokenName) > PreFormatLength:\r
233 PreFormatLength = len(StrTokenName) + 1\r
f7496d71 234 for (Lang, Value) in TokenValueList:\r
421ccda3
HC
235 if not Value or Lang == DT.TAB_LANGUAGE_EN_X:\r
236 continue\r
237 if Lang == '':\r
238 Lang = DT.TAB_LANGUAGE_EN_US\r
239 if Lang == 'eng':\r
240 Lang = DT.TAB_LANGUAGE_EN_US\r
241 elif len(Lang.split('-')[0]) == 3:\r
242 Lang = GetLanguageCode(Lang.split('-')[0], True, ContainerFile)\r
243 else:\r
244 Lang = GetLanguageCode(Lang, False, ContainerFile)\r
245 ValueList = Value.split('\n')\r
246 SubValueContent = ''\r
247 for SubValue in ValueList:\r
248 if SubValue.strip():\r
249 SubValueContent += \\r
1ccc4d89 250 ' ' * (PreFormatLength + len('#language en-US ')) + '\"%s\\n\"' % SubValue.strip() + '\r\n'\r
cf2b2bde 251 SubValueContent = SubValueContent[(PreFormatLength + len('#language en-US ')):SubValueContent.rfind('\\n')] \\r
1ccc4d89 252 + '\"' + '\r\n'\r
421ccda3
HC
253 SubContent += ' '*PreFormatLength + '#language %-5s ' % Lang + SubValueContent\r
254 if SubContent:\r
255 SubContent = StrTokenName + ' '*(PreFormatLength - len(StrTokenName)) + SubContent[PreFormatLength:]\r
256 return SubContent\r
257\r
258\r
259## StringDefClassObject\r
260#\r
261# A structure for language definition\r
262#\r
263class StringDefClassObject(object):\r
264 def __init__(self, Name = None, Value = None, Referenced = False, Token = None, UseOtherLangDef = ''):\r
265 self.StringName = ''\r
266 self.StringNameByteList = []\r
267 self.StringValue = ''\r
268 self.StringValueByteList = ''\r
269 self.Token = 0\r
270 self.Referenced = Referenced\r
271 self.UseOtherLangDef = UseOtherLangDef\r
272 self.Length = 0\r
273\r
4231a819 274 if Name is not None:\r
421ccda3
HC
275 self.StringName = Name\r
276 self.StringNameByteList = UniToHexList(Name)\r
4231a819 277 if Value is not None:\r
421ccda3
HC
278 self.StringValue = Value\r
279 self.StringValueByteList = UniToHexList(self.StringValue)\r
280 self.Length = len(self.StringValueByteList)\r
4231a819 281 if Token is not None:\r
421ccda3
HC
282 self.Token = Token\r
283\r
284 def __str__(self):\r
285 return repr(self.StringName) + ' ' + \\r
286 repr(self.Token) + ' ' + \\r
287 repr(self.Referenced) + ' ' + \\r
288 repr(self.StringValue) + ' ' + \\r
289 repr(self.UseOtherLangDef)\r
290\r
291 def UpdateValue(self, Value = None):\r
4231a819 292 if Value is not None:\r
421ccda3 293 if self.StringValue:\r
1ccc4d89 294 self.StringValue = self.StringValue + '\r\n' + Value\r
421ccda3
HC
295 else:\r
296 self.StringValue = Value\r
297 self.StringValueByteList = UniToHexList(self.StringValue)\r
298 self.Length = len(self.StringValueByteList)\r
299\r
300## UniFileClassObject\r
301#\r
302# A structure for .uni file definition\r
303#\r
304class UniFileClassObject(object):\r
305 def __init__(self, FileList = None, IsCompatibleMode = False, IncludePathList = None):\r
306 self.FileList = FileList\r
307 self.File = None\r
308 self.IncFileList = FileList\r
309 self.UniFileHeader = ''\r
310 self.Token = 2\r
311 self.LanguageDef = [] #[ [u'LanguageIdentifier', u'PrintableName'], ... ]\r
312 self.OrderedStringList = {} #{ u'LanguageIdentifier' : [StringDefClassObject] }\r
313 self.OrderedStringDict = {} #{ u'LanguageIdentifier' : {StringName:(IndexInList)} }\r
314 self.OrderedStringListByToken = {} #{ u'LanguageIdentifier' : {Token: StringDefClassObject} }\r
315 self.IsCompatibleMode = IsCompatibleMode\r
316 if not IncludePathList:\r
317 self.IncludePathList = []\r
318 else:\r
319 self.IncludePathList = IncludePathList\r
320 if len(self.FileList) > 0:\r
321 self.LoadUniFiles(FileList)\r
322\r
323 #\r
324 # Get Language definition\r
325 #\r
326 def GetLangDef(self, File, Line):\r
327 Lang = distutils.util.split_quoted((Line.split(u"//")[0]))\r
328 if len(Lang) != 3:\r
329 try:\r
645a5128 330 FileIn = codecs.open(File.Path, mode='rb', encoding='utf_8').readlines()\r
5b0671c1 331 except UnicodeError as Xstr:\r
645a5128 332 FileIn = codecs.open(File.Path, mode='rb', encoding='utf_16').readlines()\r
5b0671c1 333 except UnicodeError as Xstr:\r
645a5128 334 FileIn = codecs.open(File.Path, mode='rb', encoding='utf_16_le').readlines()\r
421ccda3 335 except:\r
f7496d71
LG
336 EdkLogger.Error("Unicode File Parser",\r
337 ToolError.FILE_OPEN_FAILURE,\r
421ccda3
HC
338 "File read failure: %s" % str(Xstr),\r
339 ExtraData=File)\r
340 LineNo = GetLineNo(FileIn, Line, False)\r
f7496d71 341 EdkLogger.Error("Unicode File Parser",\r
421ccda3 342 ToolError.PARSER_ERROR,\r
f7496d71
LG
343 "Wrong language definition",\r
344 ExtraData="""%s\n\t*Correct format is like '#langdef en-US "English"'""" % Line,\r
421ccda3
HC
345 File = File, Line = LineNo)\r
346 else:\r
347 LangName = GetLanguageCode(Lang[1], self.IsCompatibleMode, self.File)\r
348 LangPrintName = Lang[2]\r
349\r
350 IsLangInDef = False\r
351 for Item in self.LanguageDef:\r
352 if Item[0] == LangName:\r
353 IsLangInDef = True\r
354 break\r
355\r
356 if not IsLangInDef:\r
357 self.LanguageDef.append([LangName, LangPrintName])\r
358\r
359 #\r
360 # Add language string\r
361 #\r
362 self.AddStringToList(u'$LANGUAGE_NAME', LangName, LangName, 0, True, Index=0)\r
363 self.AddStringToList(u'$PRINTABLE_LANGUAGE_NAME', LangName, LangPrintName, 1, True, Index=1)\r
364\r
365 if not IsLangInDef:\r
366 #\r
367 # The found STRING tokens will be added into new language string list\r
f7496d71 368 # so that the unique STRING identifier is reserved for all languages in the package list.\r
421ccda3
HC
369 #\r
370 FirstLangName = self.LanguageDef[0][0]\r
371 if LangName != FirstLangName:\r
372 for Index in range (2, len (self.OrderedStringList[FirstLangName])):\r
373 Item = self.OrderedStringList[FirstLangName][Index]\r
374 if Item.UseOtherLangDef != '':\r
375 OtherLang = Item.UseOtherLangDef\r
376 else:\r
377 OtherLang = FirstLangName\r
f7496d71
LG
378 self.OrderedStringList[LangName].append (StringDefClassObject(Item.StringName,\r
379 '',\r
380 Item.Referenced,\r
381 Item.Token,\r
421ccda3
HC
382 OtherLang))\r
383 self.OrderedStringDict[LangName][Item.StringName] = len(self.OrderedStringList[LangName]) - 1\r
384 return True\r
385\r
386 #\r
387 # Get String name and value\r
388 #\r
389 def GetStringObject(self, Item):\r
390 Language = ''\r
391 Value = ''\r
392\r
393 Name = Item.split()[1]\r
394 # Check the string name is the upper character\r
395 if Name != '':\r
396 MatchString = re.match('[A-Z0-9_]+', Name, re.UNICODE)\r
4231a819 397 if MatchString is None or MatchString.end(0) != len(Name):\r
f7496d71 398 EdkLogger.Error("Unicode File Parser",\r
421ccda3
HC
399 ToolError.FORMAT_INVALID,\r
400 'The string token name %s in UNI file %s must be upper case character.' %(Name, self.File))\r
401 LanguageList = Item.split(u'#language ')\r
402 for IndexI in range(len(LanguageList)):\r
403 if IndexI == 0:\r
404 continue\r
405 else:\r
406 Language = LanguageList[IndexI].split()[0]\r
407 #.replace(u'\r\n', u'')\r
408 Value = \\r
f7496d71 409 LanguageList[IndexI][LanguageList[IndexI].find(u'\"') + len(u'\"') : LanguageList[IndexI].rfind(u'\"')]\r
421ccda3
HC
410 Language = GetLanguageCode(Language, self.IsCompatibleMode, self.File)\r
411 self.AddStringToList(Name, Language, Value)\r
412\r
413 #\r
414 # Get include file list and load them\r
415 #\r
416 def GetIncludeFile(self, Item, Dir = None):\r
417 if Dir:\r
418 pass\r
419 FileName = Item[Item.find(u'!include ') + len(u'!include ') :Item.find(u' ', len(u'!include '))][1:-1]\r
420 self.LoadUniFile(FileName)\r
421\r
422 #\r
423 # Pre-process before parse .uni file\r
424 #\r
425 def PreProcess(self, File, IsIncludeFile=False):\r
426 if not os.path.exists(File.Path) or not os.path.isfile(File.Path):\r
f7496d71 427 EdkLogger.Error("Unicode File Parser",\r
421ccda3
HC
428 ToolError.FILE_NOT_FOUND,\r
429 ExtraData=File.Path)\r
430\r
fe90f483
HC
431 #\r
432 # Check file header of the Uni file\r
433 #\r
4a21fb3b
HC
434# if not CheckUTF16FileHeader(File.Path):\r
435# EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
436# ExtraData='The file %s is either invalid UTF-16LE or it is missing the BOM.' % File.Path)\r
fe90f483 437\r
421ccda3 438 try:\r
645a5128 439 FileIn = codecs.open(File.Path, mode='rb', encoding='utf_8').readlines()\r
5b0671c1 440 except UnicodeError as Xstr:\r
421ccda3
HC
441 FileIn = codecs.open(File.Path, mode='rb', encoding='utf_16').readlines()\r
442 except UnicodeError:\r
443 FileIn = codecs.open(File.Path, mode='rb', encoding='utf_16_le').readlines()\r
444 except:\r
445 EdkLogger.Error("Unicode File Parser", ToolError.FILE_OPEN_FAILURE, ExtraData=File.Path)\r
f7496d71
LG
446\r
447\r
421ccda3
HC
448 #\r
449 # get the file header\r
450 #\r
451 Lines = []\r
452 HeaderStart = False\r
453 HeaderEnd = False\r
454 if not self.UniFileHeader:\r
455 FirstGenHeader = True\r
456 else:\r
457 FirstGenHeader = False\r
458 for Line in FileIn:\r
459 Line = Line.strip()\r
460 if Line == u'':\r
461 continue\r
462 if Line.startswith(DT.TAB_COMMENT_EDK1_SPLIT) and (Line.find(DT.TAB_HEADER_COMMENT) > -1) \\r
463 and not HeaderEnd and not HeaderStart:\r
464 HeaderStart = True\r
465 if not Line.startswith(DT.TAB_COMMENT_EDK1_SPLIT) and HeaderStart and not HeaderEnd:\r
466 HeaderEnd = True\r
467 if Line.startswith(DT.TAB_COMMENT_EDK1_SPLIT) and HeaderStart and not HeaderEnd and FirstGenHeader:\r
1ccc4d89 468 self.UniFileHeader += Line + '\r\n'\r
421ccda3 469 continue\r
f7496d71 470\r
421ccda3
HC
471 #\r
472 # Use unique identifier\r
473 #\r
474 FindFlag = -1\r
475 LineCount = 0\r
476 MultiLineFeedExits = False\r
477 #\r
478 # 0: initial value\r
479 # 1: signle String entry exist\r
480 # 2: line feed exist under the some signle String entry\r
481 #\r
482 StringEntryExistsFlag = 0\r
483 for Line in FileIn:\r
484 Line = FileIn[LineCount]\r
485 LineCount += 1\r
486 Line = Line.strip()\r
487 #\r
488 # Ignore comment line and empty line\r
f7496d71 489 #\r
421ccda3
HC
490 if Line == u'' or Line.startswith(u'//'):\r
491 #\r
492 # Change the single line String entry flag status\r
493 #\r
494 if StringEntryExistsFlag == 1:\r
495 StringEntryExistsFlag = 2\r
496 #\r
497 # If the '#string' line and the '#language' line are not in the same line,\r
498 # there should be only one line feed character betwwen them\r
499 #\r
500 if MultiLineFeedExits:\r
501 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
502 continue\r
503\r
504 MultiLineFeedExits = False\r
505 #\r
506 # Process comment embeded in string define lines\r
507 #\r
508 FindFlag = Line.find(u'//')\r
509 if FindFlag != -1 and Line.find(u'//') < Line.find(u'"'):\r
510 Line = Line.replace(Line[FindFlag:], u' ')\r
511 if FileIn[LineCount].strip().startswith('#language'):\r
512 Line = Line + FileIn[LineCount]\r
513 FileIn[LineCount-1] = Line\r
1ccc4d89 514 FileIn[LineCount] = '\r\n'\r
421ccda3 515 LineCount -= 1\r
1ccc4d89 516 for Index in xrange (LineCount + 1, len (FileIn) - 1):\r
421ccda3 517 if (Index == len(FileIn) -1):\r
1ccc4d89 518 FileIn[Index] = '\r\n'\r
421ccda3
HC
519 else:\r
520 FileIn[Index] = FileIn[Index + 1]\r
521 continue\r
522 CommIndex = GetCharIndexOutStr(u'/', Line)\r
523 if CommIndex > -1:\r
524 if (len(Line) - 1) > CommIndex:\r
525 if Line[CommIndex+1] == u'/':\r
526 Line = Line[:CommIndex].strip()\r
527 else:\r
528 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
529 else:\r
530 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
f7496d71 531\r
421ccda3
HC
532 Line = Line.replace(UNICODE_WIDE_CHAR, WIDE_CHAR)\r
533 Line = Line.replace(UNICODE_NARROW_CHAR, NARROW_CHAR)\r
534 Line = Line.replace(UNICODE_NON_BREAKING_CHAR, NON_BREAKING_CHAR)\r
535\r
536 Line = Line.replace(u'\\\\', u'\u0006')\r
537 Line = Line.replace(u'\\r\\n', CR + LF)\r
538 Line = Line.replace(u'\\n', CR + LF)\r
539 Line = Line.replace(u'\\r', CR)\r
540 Line = Line.replace(u'\\t', u'\t')\r
541 Line = Line.replace(u'''\"''', u'''"''')\r
542 Line = Line.replace(u'\t', u' ')\r
543 Line = Line.replace(u'\u0006', u'\\')\r
544\r
85ea493f
HC
545 #\r
546 # Check if single line has correct '"'\r
547 #\r
548 if Line.startswith(u'#string') and Line.find(u'#language') > -1 and Line.find('"') > Line.find(u'#language'):\r
549 if not Line.endswith('"'):\r
550 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
551 ExtraData='''The line %s misses '"' at the end of it in file %s'''\r
552 % (LineCount, File.Path))\r
553\r
421ccda3
HC
554 #\r
555 # Between Name entry and Language entry can not contain line feed\r
556 #\r
557 if Line.startswith(u'#string') and Line.find(u'#language') == -1:\r
558 MultiLineFeedExits = True\r
f7496d71 559\r
421ccda3
HC
560 if Line.startswith(u'#string') and Line.find(u'#language') > 0 and Line.find(u'"') < 0:\r
561 MultiLineFeedExits = True\r
f7496d71 562\r
421ccda3
HC
563 #\r
564 # Between Language entry and String entry can not contain line feed\r
565 #\r
566 if Line.startswith(u'#language') and len(Line.split()) == 2:\r
567 MultiLineFeedExits = True\r
f7496d71 568\r
90c64aad
HC
569 #\r
570 # Check the situation that there only has one '"' for the language entry\r
571 #\r
572 if Line.startswith(u'#string') and Line.find(u'#language') > 0 and Line.count(u'"') == 1:\r
573 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
574 ExtraData='''The line %s misses '"' at the end of it in file %s'''\r
575 % (LineCount, File.Path))\r
576\r
577 #\r
578 # Check the situation that there has more than 2 '"' for the language entry\r
579 #\r
580 if Line.startswith(u'#string') and Line.find(u'#language') > 0 and Line.replace(u'\\"', '').count(u'"') > 2:\r
581 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
582 ExtraData='''The line %s has more than 2 '"' for language entry in file %s'''\r
583 % (LineCount, File.Path))\r
584\r
421ccda3
HC
585 #\r
586 # Between two String entry, can not contain line feed\r
587 #\r
588 if Line.startswith(u'"'):\r
589 if StringEntryExistsFlag == 2:\r
645a5128 590 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
421ccda3 591 Message=ST.ERR_UNIPARSE_LINEFEED_UP_EXIST % Line, ExtraData=File.Path)\r
645a5128 592\r
421ccda3
HC
593 StringEntryExistsFlag = 1\r
594 if not Line.endswith('"'):\r
fe90f483
HC
595 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
596 ExtraData='''The line %s misses '"' at the end of it in file %s'''\r
597 % (LineCount, File.Path))\r
421ccda3
HC
598 elif Line.startswith(u'#language'):\r
599 if StringEntryExistsFlag == 2:\r
645a5128 600 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
fe90f483 601 Message=ST.ERR_UNI_MISS_STRING_ENTRY % Line, ExtraData=File.Path)\r
421ccda3
HC
602 StringEntryExistsFlag = 0\r
603 else:\r
604 StringEntryExistsFlag = 0\r
605\r
606 Lines.append(Line)\r
f7496d71 607\r
421ccda3
HC
608 #\r
609 # Convert string def format as below\r
610 #\r
611 # #string MY_STRING_1\r
612 # #language eng\r
613 # "My first English string line 1"\r
614 # "My first English string line 2"\r
615 # #string MY_STRING_1\r
616 # #language spa\r
617 # "Mi segunda secuencia 1"\r
618 # "Mi segunda secuencia 2"\r
619 #\r
f7496d71 620\r
421ccda3
HC
621 if not IsIncludeFile and not Lines:\r
622 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
623 Message=ST.ERR_UNIPARSE_NO_SECTION_EXIST, \\r
f7496d71 624 ExtraData=File.Path)\r
421ccda3
HC
625\r
626 NewLines = []\r
627 StrName = u''\r
628 ExistStrNameList = []\r
629 for Line in Lines:\r
630 if StrName and not StrName.split()[1].startswith(DT.TAB_STR_TOKENCNAME + DT.TAB_UNDERLINE_SPLIT):\r
631 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
632 Message=ST.ERR_UNIPARSE_STRNAME_FORMAT_ERROR % StrName.split()[1], \\r
633 ExtraData=File.Path)\r
f7496d71 634\r
421ccda3
HC
635 if StrName and len(StrName.split()[1].split(DT.TAB_UNDERLINE_SPLIT)) == 4:\r
636 StringTokenList = StrName.split()[1].split(DT.TAB_UNDERLINE_SPLIT)\r
637 if (StringTokenList[3].upper() in [DT.TAB_STR_TOKENPROMPT, DT.TAB_STR_TOKENHELP] and \\r
638 StringTokenList[3] not in [DT.TAB_STR_TOKENPROMPT, DT.TAB_STR_TOKENHELP]) or \\r
639 (StringTokenList[2].upper() == DT.TAB_STR_TOKENERR and StringTokenList[2] != DT.TAB_STR_TOKENERR):\r
640 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
641 Message=ST.ERR_UNIPARSE_STRTOKEN_FORMAT_ERROR % StrName.split()[1], \\r
642 ExtraData=File.Path)\r
f7496d71 643\r
421ccda3
HC
644 if Line.count(u'#language') > 1:\r
645 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
646 Message=ST.ERR_UNIPARSE_SEP_LANGENTRY_LINE % Line, \\r
f7496d71
LG
647 ExtraData=File.Path)\r
648\r
421ccda3
HC
649 if Line.startswith(u'//'):\r
650 continue\r
651 elif Line.startswith(u'#langdef'):\r
652 if len(Line.split()) == 2:\r
653 NewLines.append(Line)\r
654 continue\r
f7496d71 655 elif len(Line.split()) > 2 and Line.find(u'"') > 0:\r
421ccda3
HC
656 NewLines.append(Line[:Line.find(u'"')].strip())\r
657 NewLines.append(Line[Line.find(u'"'):])\r
658 else:\r
659 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
660 elif Line.startswith(u'#string'):\r
661 if len(Line.split()) == 2:\r
662 StrName = Line\r
663 if StrName:\r
664 if StrName.split()[1] not in ExistStrNameList:\r
665 ExistStrNameList.append(StrName.split()[1].strip())\r
666 elif StrName.split()[1] in [DT.TAB_INF_ABSTRACT, DT.TAB_INF_DESCRIPTION, \\r
667 DT.TAB_INF_BINARY_ABSTRACT, DT.TAB_INF_BINARY_DESCRIPTION, \\r
668 DT.TAB_DEC_PACKAGE_ABSTRACT, DT.TAB_DEC_PACKAGE_DESCRIPTION, \\r
669 DT.TAB_DEC_BINARY_ABSTRACT, DT.TAB_DEC_BINARY_DESCRIPTION]:\r
670 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
671 Message=ST.ERR_UNIPARSE_MULTI_ENTRY_EXIST % StrName.split()[1], \\r
672 ExtraData=File.Path)\r
673 continue\r
674 elif len(Line.split()) == 4 and Line.find(u'#language') > 0:\r
675 if Line[Line.find(u'#language')-1] != ' ' or \\r
676 Line[Line.find(u'#language')+len(u'#language')] != u' ':\r
677 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
f7496d71 678\r
421ccda3
HC
679 if Line.find(u'"') > 0:\r
680 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
f7496d71 681\r
421ccda3
HC
682 StrName = Line.split()[0] + u' ' + Line.split()[1]\r
683 if StrName:\r
684 if StrName.split()[1] not in ExistStrNameList:\r
685 ExistStrNameList.append(StrName.split()[1].strip())\r
686 elif StrName.split()[1] in [DT.TAB_INF_ABSTRACT, DT.TAB_INF_DESCRIPTION, \\r
687 DT.TAB_INF_BINARY_ABSTRACT, DT.TAB_INF_BINARY_DESCRIPTION, \\r
688 DT.TAB_DEC_PACKAGE_ABSTRACT, DT.TAB_DEC_PACKAGE_DESCRIPTION, \\r
689 DT.TAB_DEC_BINARY_ABSTRACT, DT.TAB_DEC_BINARY_DESCRIPTION]:\r
690 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
691 Message=ST.ERR_UNIPARSE_MULTI_ENTRY_EXIST % StrName.split()[1], \\r
692 ExtraData=File.Path)\r
693 if IsIncludeFile:\r
694 if StrName not in NewLines:\r
695 NewLines.append((Line[:Line.find(u'#language')]).strip())\r
696 else:\r
697 NewLines.append((Line[:Line.find(u'#language')]).strip())\r
698 NewLines.append((Line[Line.find(u'#language'):]).strip())\r
699 elif len(Line.split()) > 4 and Line.find(u'#language') > 0 and Line.find(u'"') > 0:\r
700 if Line[Line.find(u'#language')-1] != u' ' or \\r
701 Line[Line.find(u'#language')+len(u'#language')] != u' ':\r
702 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
f7496d71 703\r
421ccda3 704 if Line[Line.find(u'"')-1] != u' ':\r
f7496d71
LG
705 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
706\r
707 StrName = Line.split()[0] + u' ' + Line.split()[1]\r
421ccda3
HC
708 if StrName:\r
709 if StrName.split()[1] not in ExistStrNameList:\r
710 ExistStrNameList.append(StrName.split()[1].strip())\r
711 elif StrName.split()[1] in [DT.TAB_INF_ABSTRACT, DT.TAB_INF_DESCRIPTION, \\r
712 DT.TAB_INF_BINARY_ABSTRACT, DT.TAB_INF_BINARY_DESCRIPTION, \\r
713 DT.TAB_DEC_PACKAGE_ABSTRACT, DT.TAB_DEC_PACKAGE_DESCRIPTION, \\r
714 DT.TAB_DEC_BINARY_ABSTRACT, DT.TAB_DEC_BINARY_DESCRIPTION]:\r
715 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
716 Message=ST.ERR_UNIPARSE_MULTI_ENTRY_EXIST % StrName.split()[1], \\r
f7496d71 717 ExtraData=File.Path)\r
421ccda3
HC
718 if IsIncludeFile:\r
719 if StrName not in NewLines:\r
720 NewLines.append((Line[:Line.find(u'#language')]).strip())\r
f7496d71 721 else:\r
421ccda3
HC
722 NewLines.append((Line[:Line.find(u'#language')]).strip())\r
723 NewLines.append((Line[Line.find(u'#language'):Line.find(u'"')]).strip())\r
724 NewLines.append((Line[Line.find(u'"'):]).strip())\r
725 else:\r
726 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
727 elif Line.startswith(u'#language'):\r
728 if len(Line.split()) == 2:\r
729 if IsIncludeFile:\r
730 if StrName not in NewLines:\r
731 NewLines.append(StrName)\r
732 else:\r
733 NewLines.append(StrName)\r
734 NewLines.append(Line)\r
735 elif len(Line.split()) > 2 and Line.find(u'"') > 0:\r
736 if IsIncludeFile:\r
737 if StrName not in NewLines:\r
738 NewLines.append(StrName)\r
739 else:\r
740 NewLines.append(StrName)\r
741 NewLines.append((Line[:Line.find(u'"')]).strip())\r
742 NewLines.append((Line[Line.find(u'"'):]).strip())\r
743 else:\r
744 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
745 elif Line.startswith(u'"'):\r
90c64aad
HC
746 #\r
747 # Check the situation that there has more than 2 '"' for the language entry\r
748 #\r
749 if Line.replace(u'\\"', '').count(u'"') > 2:\r
750 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
751 ExtraData='''The line %s has more than 2 '"' for language entry in file %s'''\r
752 % (LineCount, File.Path))\r
421ccda3
HC
753 if u'#string' in Line or u'#language' in Line:\r
754 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
755 NewLines.append(Line)\r
756 else:\r
72443dd2 757 print(Line)\r
421ccda3 758 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path)\r
f7496d71 759\r
421ccda3
HC
760 if StrName and not StrName.split()[1].startswith(u'STR_'):\r
761 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
762 Message=ST.ERR_UNIPARSE_STRNAME_FORMAT_ERROR % StrName.split()[1], \\r
f7496d71
LG
763 ExtraData=File.Path)\r
764\r
421ccda3
HC
765 if StrName and not NewLines:\r
766 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
767 Message=ST.ERR_UNI_MISS_LANGENTRY % StrName, \\r
768 ExtraData=File.Path)\r
f7496d71 769\r
421ccda3
HC
770 #\r
771 # Check Abstract, Description, BinaryAbstract and BinaryDescription order,\r
772 # should be Abstract, Description, BinaryAbstract, BinaryDesctiption\r
773 AbstractPosition = -1\r
774 DescriptionPosition = -1\r
775 BinaryAbstractPosition = -1\r
776 BinaryDescriptionPosition = -1\r
777 for StrName in ExistStrNameList:\r
778 if DT.TAB_HEADER_ABSTRACT.upper() in StrName:\r
779 if 'BINARY' in StrName:\r
780 BinaryAbstractPosition = ExistStrNameList.index(StrName)\r
781 else:\r
782 AbstractPosition = ExistStrNameList.index(StrName)\r
783 if DT.TAB_HEADER_DESCRIPTION.upper() in StrName:\r
784 if 'BINARY' in StrName:\r
785 BinaryDescriptionPosition = ExistStrNameList.index(StrName)\r
786 else:\r
787 DescriptionPosition = ExistStrNameList.index(StrName)\r
f7496d71 788\r
421ccda3
HC
789 OrderList = sorted([AbstractPosition, DescriptionPosition])\r
790 BinaryOrderList = sorted([BinaryAbstractPosition, BinaryDescriptionPosition])\r
791 Min = OrderList[0]\r
792 Max = OrderList[1]\r
793 BinaryMin = BinaryOrderList[0]\r
794 BinaryMax = BinaryOrderList[1]\r
795 if BinaryDescriptionPosition > -1:\r
796 if not(BinaryDescriptionPosition == BinaryMax and BinaryAbstractPosition == BinaryMin and \\r
797 BinaryMax > Max):\r
798 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
799 Message=ST.ERR_UNIPARSE_ENTRY_ORDER_WRONG, \\r
f7496d71 800 ExtraData=File.Path)\r
421ccda3
HC
801 elif BinaryAbstractPosition > -1:\r
802 if not(BinaryAbstractPosition > Max):\r
803 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
804 Message=ST.ERR_UNIPARSE_ENTRY_ORDER_WRONG, \\r
f7496d71
LG
805 ExtraData=File.Path)\r
806\r
421ccda3
HC
807 if DescriptionPosition > -1:\r
808 if not(DescriptionPosition == Max and AbstractPosition == Min and \\r
809 DescriptionPosition > AbstractPosition):\r
810 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \\r
811 Message=ST.ERR_UNIPARSE_ENTRY_ORDER_WRONG, \\r
f7496d71
LG
812 ExtraData=File.Path)\r
813\r
421ccda3 814 if not self.UniFileHeader:\r
f7496d71 815 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
421ccda3
HC
816 Message = ST.ERR_NO_SOURCE_HEADER,\r
817 ExtraData=File.Path)\r
f7496d71 818\r
421ccda3
HC
819 return NewLines\r
820\r
821 #\r
822 # Load a .uni file\r
823 #\r
824 def LoadUniFile(self, File = None):\r
4231a819 825 if File is None:\r
f7496d71
LG
826 EdkLogger.Error("Unicode File Parser",\r
827 ToolError.PARSER_ERROR,\r
828 Message='No unicode file is given',\r
421ccda3 829 ExtraData=File.Path)\r
f7496d71 830\r
421ccda3 831 self.File = File\r
f7496d71 832\r
421ccda3
HC
833 #\r
834 # Process special char in file\r
835 #\r
836 Lines = self.PreProcess(File)\r
837\r
838 #\r
839 # Get Unicode Information\r
840 #\r
841 for IndexI in range(len(Lines)):\r
842 Line = Lines[IndexI]\r
843 if (IndexI + 1) < len(Lines):\r
844 SecondLine = Lines[IndexI + 1]\r
845 if (IndexI + 2) < len(Lines):\r
846 ThirdLine = Lines[IndexI + 2]\r
847\r
848 #\r
849 # Get Language def information\r
850 #\r
851 if Line.find(u'#langdef ') >= 0:\r
852 self.GetLangDef(File, Line + u' ' + SecondLine)\r
853 continue\r
854\r
855 Name = ''\r
856 Language = ''\r
857 Value = ''\r
858 CombineToken = False\r
859 #\r
860 # Get string def information format as below\r
861 #\r
862 # #string MY_STRING_1\r
863 # #language eng\r
864 # "My first English string line 1"\r
865 # "My first English string line 2"\r
866 # #string MY_STRING_1\r
867 # #language spa\r
868 # "Mi segunda secuencia 1"\r
869 # "Mi segunda secuencia 2"\r
870 #\r
871 if Line.find(u'#string ') >= 0 and Line.find(u'#language ') < 0 and \\r
872 SecondLine.find(u'#string ') < 0 and SecondLine.find(u'#language ') >= 0 and \\r
873 ThirdLine.find(u'#string ') < 0 and ThirdLine.find(u'#language ') < 0:\r
874 if Line.find('"') > 0 or SecondLine.find('"') > 0:\r
f7496d71 875 EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID,\r
421ccda3
HC
876 Message=ST.ERR_UNIPARSE_DBLQUOTE_UNMATCHED,\r
877 ExtraData=File.Path)\r
f7496d71 878\r
421ccda3
HC
879 Name = Line[Line.find(u'#string ') + len(u'#string ') : ].strip(' ')\r
880 Language = SecondLine[SecondLine.find(u'#language ') + len(u'#language ') : ].strip(' ')\r
881 for IndexJ in range(IndexI + 2, len(Lines)):\r
882 if Lines[IndexJ].find(u'#string ') < 0 and Lines[IndexJ].find(u'#language ') < 0 and \\r
883 Lines[IndexJ].strip().startswith(u'"') and Lines[IndexJ].strip().endswith(u'"'):\r
884 if Lines[IndexJ][-2] == ' ':\r
885 CombineToken = True\r
886 if CombineToken:\r
887 if Lines[IndexJ].strip()[1:-1].strip():\r
888 Value = Value + Lines[IndexJ].strip()[1:-1].rstrip() + ' '\r
889 else:\r
890 Value = Value + Lines[IndexJ].strip()[1:-1]\r
891 CombineToken = False\r
892 else:\r
1ccc4d89 893 Value = Value + Lines[IndexJ].strip()[1:-1] + '\r\n'\r
421ccda3
HC
894 else:\r
895 IndexI = IndexJ\r
896 break\r
1ccc4d89
LG
897 if Value.endswith('\r\n'):\r
898 Value = Value[: Value.rfind('\r\n')]\r
421ccda3
HC
899 Language = GetLanguageCode(Language, self.IsCompatibleMode, self.File)\r
900 self.AddStringToList(Name, Language, Value)\r
901 continue\r
902\r
903 #\r
904 # Load multiple .uni files\r
905 #\r
906 def LoadUniFiles(self, FileList):\r
907 if len(FileList) > 0:\r
908 for File in FileList:\r
909 FilePath = File.Path.strip()\r
910 if FilePath.endswith('.uni') or FilePath.endswith('.UNI') or FilePath.endswith('.Uni'):\r
911 self.LoadUniFile(File)\r
912\r
913 #\r
914 # Add a string to list\r
915 #\r
916 def AddStringToList(self, Name, Language, Value, Token = 0, Referenced = False, UseOtherLangDef = '', Index = -1):\r
917 for LangNameItem in self.LanguageDef:\r
918 if Language == LangNameItem[0]:\r
919 break\r
f7496d71 920\r
421ccda3
HC
921 if Language not in self.OrderedStringList:\r
922 self.OrderedStringList[Language] = []\r
923 self.OrderedStringDict[Language] = {}\r
f7496d71 924\r
421ccda3
HC
925 IsAdded = True\r
926 if Name in self.OrderedStringDict[Language]:\r
927 IsAdded = False\r
4231a819 928 if Value is not None:\r
421ccda3
HC
929 ItemIndexInList = self.OrderedStringDict[Language][Name]\r
930 Item = self.OrderedStringList[Language][ItemIndexInList]\r
931 Item.UpdateValue(Value)\r
f7496d71 932 Item.UseOtherLangDef = ''\r
421ccda3
HC
933\r
934 if IsAdded:\r
935 Token = len(self.OrderedStringList[Language])\r
936 if Index == -1:\r
f7496d71
LG
937 self.OrderedStringList[Language].append(StringDefClassObject(Name,\r
938 Value,\r
939 Referenced,\r
940 Token,\r
421ccda3
HC
941 UseOtherLangDef))\r
942 self.OrderedStringDict[Language][Name] = Token\r
943 for LangName in self.LanguageDef:\r
944 #\r
945 # New STRING token will be added into all language string lists.\r
f7496d71 946 # so that the unique STRING identifier is reserved for all languages in the package list.\r
421ccda3
HC
947 #\r
948 if LangName[0] != Language:\r
949 if UseOtherLangDef != '':\r
950 OtherLangDef = UseOtherLangDef\r
951 else:\r
952 OtherLangDef = Language\r
f7496d71
LG
953 self.OrderedStringList[LangName[0]].append(StringDefClassObject(Name,\r
954 '',\r
955 Referenced,\r
956 Token,\r
421ccda3
HC
957 OtherLangDef))\r
958 self.OrderedStringDict[LangName[0]][Name] = len(self.OrderedStringList[LangName[0]]) - 1\r
959 else:\r
f7496d71
LG
960 self.OrderedStringList[Language].insert(Index, StringDefClassObject(Name,\r
961 Value,\r
962 Referenced,\r
963 Token,\r
421ccda3
HC
964 UseOtherLangDef))\r
965 self.OrderedStringDict[Language][Name] = Index\r
966\r
967 #\r
968 # Set the string as referenced\r
969 #\r
970 def SetStringReferenced(self, Name):\r
971 #\r
972 # String stoken are added in the same order in all language string lists.\r
973 # So, only update the status of string stoken in first language string list.\r
974 #\r
975 Lang = self.LanguageDef[0][0]\r
976 if Name in self.OrderedStringDict[Lang]:\r
977 ItemIndexInList = self.OrderedStringDict[Lang][Name]\r
978 Item = self.OrderedStringList[Lang][ItemIndexInList]\r
979 Item.Referenced = True\r
980\r
981 #\r
982 # Search the string in language definition by Name\r
983 #\r
984 def FindStringValue(self, Name, Lang):\r
985 if Name in self.OrderedStringDict[Lang]:\r
986 ItemIndexInList = self.OrderedStringDict[Lang][Name]\r
987 return self.OrderedStringList[Lang][ItemIndexInList]\r
988\r
989 return None\r
990\r
991 #\r
992 # Search the string in language definition by Token\r
993 #\r
994 def FindByToken(self, Token, Lang):\r
995 for Item in self.OrderedStringList[Lang]:\r
996 if Item.Token == Token:\r
997 return Item\r
998\r
999 return None\r
1000\r
1001 #\r
1002 # Re-order strings and re-generate tokens\r
1003 #\r
1004 def ReToken(self):\r
1005 if len(self.LanguageDef) == 0:\r
1006 return None\r
1007 #\r
1008 # Retoken all language strings according to the status of string stoken in the first language string.\r
1009 #\r
1010 FirstLangName = self.LanguageDef[0][0]\r
1011\r
1012 # Convert the OrderedStringList to be OrderedStringListByToken in order to faciliate future search by token\r
1013 for LangNameItem in self.LanguageDef:\r
1014 self.OrderedStringListByToken[LangNameItem[0]] = {}\r
1015\r
1016 #\r
1017 # Use small token for all referred string stoken.\r
1018 #\r
1019 RefToken = 0\r
1020 for Index in range (0, len (self.OrderedStringList[FirstLangName])):\r
1021 FirstLangItem = self.OrderedStringList[FirstLangName][Index]\r
1022 if FirstLangItem.Referenced == True:\r
1023 for LangNameItem in self.LanguageDef:\r
1024 LangName = LangNameItem[0]\r
1025 OtherLangItem = self.OrderedStringList[LangName][Index]\r
1026 OtherLangItem.Referenced = True\r
1027 OtherLangItem.Token = RefToken\r
1028 self.OrderedStringListByToken[LangName][OtherLangItem.Token] = OtherLangItem\r
1029 RefToken = RefToken + 1\r
1030\r
1031 #\r
1032 # Use big token for all unreferred string stoken.\r
1033 #\r
1034 UnRefToken = 0\r
1035 for Index in range (0, len (self.OrderedStringList[FirstLangName])):\r
1036 FirstLangItem = self.OrderedStringList[FirstLangName][Index]\r
1037 if FirstLangItem.Referenced == False:\r
1038 for LangNameItem in self.LanguageDef:\r
1039 LangName = LangNameItem[0]\r
1040 OtherLangItem = self.OrderedStringList[LangName][Index]\r
1041 OtherLangItem.Token = RefToken + UnRefToken\r
1042 self.OrderedStringListByToken[LangName][OtherLangItem.Token] = OtherLangItem\r
1043 UnRefToken = UnRefToken + 1\r
1044\r
1045 #\r
1046 # Show the instance itself\r
1047 #\r
1048 def ShowMe(self):\r
72443dd2 1049 print(self.LanguageDef)\r
421ccda3
HC
1050 #print self.OrderedStringList\r
1051 for Item in self.OrderedStringList:\r
72443dd2 1052 print(Item)\r
421ccda3 1053 for Member in self.OrderedStringList[Item]:\r
72443dd2 1054 print(str(Member))\r
f7496d71 1055\r
421ccda3 1056 #\r
f7496d71 1057 # Read content from '!include' UNI file\r
421ccda3
HC
1058 #\r
1059 def ReadIncludeUNIfile(self, FilaPath):\r
1060 if self.File:\r
1061 pass\r
f7496d71 1062\r
421ccda3 1063 if not os.path.exists(FilaPath) or not os.path.isfile(FilaPath):\r
f7496d71 1064 EdkLogger.Error("Unicode File Parser",\r
421ccda3
HC
1065 ToolError.FILE_NOT_FOUND,\r
1066 ExtraData=FilaPath)\r
1067 try:\r
645a5128 1068 FileIn = codecs.open(FilaPath, mode='rb', encoding='utf_8').readlines()\r
5b0671c1 1069 except UnicodeError as Xstr:\r
421ccda3
HC
1070 FileIn = codecs.open(FilaPath, mode='rb', encoding='utf_16').readlines()\r
1071 except UnicodeError:\r
1072 FileIn = codecs.open(FilaPath, mode='rb', encoding='utf_16_le').readlines()\r
1073 except:\r
1074 EdkLogger.Error("Unicode File Parser", ToolError.FILE_OPEN_FAILURE, ExtraData=FilaPath)\r
1075 return FileIn\r
1076\r