1## @file 2# This file is used to collect all defined strings in multiple uni files 3# 4# 5# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.<BR> 6# 7# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR> 8# This program and the accompanying materials 9# are licensed and made available under the terms and conditions of the BSD License 10# which accompanies this distribution. The full text of the license may be found at 11# http://opensource.org/licenses/bsd-license.php 12# 13# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 14# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 15 16## 17# Import Modules 18# 19import Common.LongFilePathOs as os, codecs, re 20import distutils.util 21import Common.EdkLogger as EdkLogger 22from Common.BuildToolError import * 23from Common.String import GetLineNo 24from Common.Misc import PathClass 25from Common.LongFilePathSupport import LongFilePath 26## 27# Static definitions 28# 29UNICODE_WIDE_CHAR = u'\\wide' 30UNICODE_NARROW_CHAR = u'\\narrow' 31UNICODE_NON_BREAKING_CHAR = u'\\nbr' 32UNICODE_UNICODE_CR = '\r' 33UNICODE_UNICODE_LF = '\n' 34 35NARROW_CHAR = u'\uFFF0' 36WIDE_CHAR = u'\uFFF1' 37NON_BREAKING_CHAR = u'\uFFF2' 38CR = u'\u000D' 39LF = u'\u000A' 40NULL = u'\u0000' 41TAB = u'\t' 42BACK_SLASH_PLACEHOLDER = u'\u0006' 43 44gIncludePattern = re.compile("^#include +[\"<]+([^\"< >]+)[>\"]+$", re.MULTILINE | re.UNICODE) 45 46## Convert a python unicode string to a normal string 47# 48# Convert a python unicode string to a normal string 49# UniToStr(u'I am a string') is 'I am a string' 50# 51# @param Uni: The python unicode string 52# 53# @retval: The formatted normal string 54# 55def UniToStr(Uni): 56 return repr(Uni)[2:-1] 57 58## Convert a unicode string to a Hex list 59# 60# Convert a unicode string to a Hex list 61# UniToHexList('ABC') is ['0x41', '0x00', '0x42', '0x00', '0x43', '0x00'] 62# 63# @param Uni: The python unicode string 64# 65# @retval List: The formatted hex list 66# 67def UniToHexList(Uni): 68 List = [] 69 for Item in Uni: 70 Temp = '%04X' % ord(Item) 71 List.append('0x' + Temp[2:4]) 72 List.append('0x' + Temp[0:2]) 73 return List 74 75LangConvTable = {'eng':'en', 'fra':'fr', \ 76 'aar':'aa', 'abk':'ab', 'ave':'ae', 'afr':'af', 'aka':'ak', 'amh':'am', \ 77 'arg':'an', 'ara':'ar', 'asm':'as', 'ava':'av', 'aym':'ay', 'aze':'az', \ 78 'bak':'ba', 'bel':'be', 'bul':'bg', 'bih':'bh', 'bis':'bi', 'bam':'bm', \ 79 'ben':'bn', 'bod':'bo', 'bre':'br', 'bos':'bs', 'cat':'ca', 'che':'ce', \ 80 'cha':'ch', 'cos':'co', 'cre':'cr', 'ces':'cs', 'chu':'cu', 'chv':'cv', \ 81 'cym':'cy', 'dan':'da', 'deu':'de', 'div':'dv', 'dzo':'dz', 'ewe':'ee', \ 82 'ell':'el', 'epo':'eo', 'spa':'es', 'est':'et', 'eus':'eu', 'fas':'fa', \ 83 'ful':'ff', 'fin':'fi', 'fij':'fj', 'fao':'fo', 'fry':'fy', 'gle':'ga', \ 84 'gla':'gd', 'glg':'gl', 'grn':'gn', 'guj':'gu', 'glv':'gv', 'hau':'ha', \ 85 'heb':'he', 'hin':'hi', 'hmo':'ho', 'hrv':'hr', 'hat':'ht', 'hun':'hu', \ 86 'hye':'hy', 'her':'hz', 'ina':'ia', 'ind':'id', 'ile':'ie', 'ibo':'ig', \ 87 'iii':'ii', 'ipk':'ik', 'ido':'io', 'isl':'is', 'ita':'it', 'iku':'iu', \ 88 'jpn':'ja', 'jav':'jv', 'kat':'ka', 'kon':'kg', 'kik':'ki', 'kua':'kj', \ 89 'kaz':'kk', 'kal':'kl', 'khm':'km', 'kan':'kn', 'kor':'ko', 'kau':'kr', \ 90 'kas':'ks', 'kur':'ku', 'kom':'kv', 'cor':'kw', 'kir':'ky', 'lat':'la', \ 91 'ltz':'lb', 'lug':'lg', 'lim':'li', 'lin':'ln', 'lao':'lo', 'lit':'lt', \ 92 'lub':'lu', 'lav':'lv', 'mlg':'mg', 'mah':'mh', 'mri':'mi', 'mkd':'mk', \ 93 'mal':'ml', 'mon':'mn', 'mar':'mr', 'msa':'ms', 'mlt':'mt', 'mya':'my', \ 94 'nau':'na', 'nob':'nb', 'nde':'nd', 'nep':'ne', 'ndo':'ng', 'nld':'nl', \ 95 'nno':'nn', 'nor':'no', 'nbl':'nr', 'nav':'nv', 'nya':'ny', 'oci':'oc', \ 96 'oji':'oj', 'orm':'om', 'ori':'or', 'oss':'os', 'pan':'pa', 'pli':'pi', \ 97 'pol':'pl', 'pus':'ps', 'por':'pt', 'que':'qu', 'roh':'rm', 'run':'rn', \ 98 'ron':'ro', 'rus':'ru', 'kin':'rw', 'san':'sa', 'srd':'sc', 'snd':'sd', \ 99 'sme':'se', 'sag':'sg', 'sin':'si', 'slk':'sk', 'slv':'sl', 'smo':'sm', \ 100 'sna':'sn', 'som':'so', 'sqi':'sq', 'srp':'sr', 'ssw':'ss', 'sot':'st', \ 101 'sun':'su', 'swe':'sv', 'swa':'sw', 'tam':'ta', 'tel':'te', 'tgk':'tg', \ 102 'tha':'th', 'tir':'ti', 'tuk':'tk', 'tgl':'tl', 'tsn':'tn', 'ton':'to', \ 103 'tur':'tr', 'tso':'ts', 'tat':'tt', 'twi':'tw', 'tah':'ty', 'uig':'ug', \ 104 'ukr':'uk', 'urd':'ur', 'uzb':'uz', 'ven':'ve', 'vie':'vi', 'vol':'vo', \ 105 'wln':'wa', 'wol':'wo', 'xho':'xh', 'yid':'yi', 'yor':'yo', 'zha':'za', \ 106 'zho':'zh', 'zul':'zu'} 107 108## GetLanguageCode 109# 110# Check the language code read from .UNI file and convert ISO 639-2 codes to RFC 4646 codes if appropriate 111# ISO 639-2 language codes supported in compatiblity mode 112# RFC 4646 language codes supported in native mode 113# 114# @param LangName: Language codes read from .UNI file 115# 116# @retval LangName: Valid lanugage code in RFC 4646 format or None 117# 118def GetLanguageCode(LangName, IsCompatibleMode, File): 119 global LangConvTable 120 121 length = len(LangName) 122 if IsCompatibleMode: 123 if length == 3 and LangName.isalpha(): 124 TempLangName = LangConvTable.get(LangName.lower()) 125 if TempLangName != None: 126 return TempLangName 127 return LangName 128 else: 129 EdkLogger.error("Unicode File Parser", FORMAT_INVALID, "Invalid ISO 639-2 language code : %s" % LangName, File) 130 131 if (LangName[0] == 'X' or LangName[0] == 'x') and LangName[1] == '-': 132 return LangName 133 if length == 2: 134 if LangName.isalpha(): 135 return LangName 136 elif length == 3: 137 if LangName.isalpha() and LangConvTable.get(LangName.lower()) == None: 138 return LangName 139 elif length == 5: 140 if LangName[0:2].isalpha() and LangName[2] == '-': 141 return LangName 142 elif length >= 6: 143 if LangName[0:2].isalpha() and LangName[2] == '-': 144 return LangName 145 if LangName[0:3].isalpha() and LangConvTable.get(LangName.lower()) == None and LangName[3] == '-': 146 return LangName 147 148 EdkLogger.error("Unicode File Parser", FORMAT_INVALID, "Invalid RFC 4646 language code : %s" % LangName, File) 149 150## StringDefClassObject 151# 152# A structure for language definition 153# 154class StringDefClassObject(object): 155 def __init__(self, Name = None, Value = None, Referenced = False, Token = None, UseOtherLangDef = ''): 156 self.StringName = '' 157 self.StringNameByteList = [] 158 self.StringValue = '' 159 self.StringValueByteList = '' 160 self.Token = 0 161 self.Referenced = Referenced 162 self.UseOtherLangDef = UseOtherLangDef 163 self.Length = 0 164 165 if Name != None: 166 self.StringName = Name 167 self.StringNameByteList = UniToHexList(Name) 168 if Value != None: 169 self.StringValue = Value + u'\x00' # Add a NULL at string tail 170 self.StringValueByteList = UniToHexList(self.StringValue) 171 self.Length = len(self.StringValueByteList) 172 if Token != None: 173 self.Token = Token 174 175 def __str__(self): 176 return repr(self.StringName) + ' ' + \ 177 repr(self.Token) + ' ' + \ 178 repr(self.Referenced) + ' ' + \ 179 repr(self.StringValue) + ' ' + \ 180 repr(self.UseOtherLangDef) 181 182 def UpdateValue(self, Value = None): 183 if Value != None: 184 self.StringValue = Value + u'\x00' # Add a NULL at string tail 185 self.StringValueByteList = UniToHexList(self.StringValue) 186 self.Length = len(self.StringValueByteList) 187 188## UniFileClassObject 189# 190# A structure for .uni file definition 191# 192class UniFileClassObject(object): 193 def __init__(self, FileList = [], IsCompatibleMode = False, IncludePathList = []): 194 self.FileList = FileList 195 self.Token = 2 196 self.LanguageDef = [] #[ [u'LanguageIdentifier', u'PrintableName'], ... ] 197 self.OrderedStringList = {} #{ u'LanguageIdentifier' : [StringDefClassObject] } 198 self.OrderedStringDict = {} #{ u'LanguageIdentifier' : {StringName:(IndexInList)} } 199 self.OrderedStringListByToken = {} #{ u'LanguageIdentifier' : {Token: StringDefClassObject} } 200 self.IsCompatibleMode = IsCompatibleMode 201 self.IncludePathList = IncludePathList 202 if len(self.FileList) > 0: 203 self.LoadUniFiles(FileList) 204 205 # 206 # Get Language definition 207 # 208 def GetLangDef(self, File, Line): 209 Lang = distutils.util.split_quoted((Line.split(u"//")[0])) 210 if len(Lang) != 3: 211 try: 212 FileIn = codecs.open(LongFilePath(File.Path), mode='rb', encoding='utf-16').read() 213 except UnicodeError, X: 214 EdkLogger.error("build", FILE_READ_FAILURE, "File read failure: %s" % str(X), ExtraData=File); 215 except: 216 EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=File); 217 LineNo = GetLineNo(FileIn, Line, False) 218 EdkLogger.error("Unicode File Parser", PARSER_ERROR, "Wrong language definition", 219 ExtraData="""%s\n\t*Correct format is like '#langdef en-US "English"'""" % Line, File = File, Line = LineNo) 220 else: 221 LangName = GetLanguageCode(Lang[1], self.IsCompatibleMode, self.File) 222 LangPrintName = Lang[2] 223 224 IsLangInDef = False 225 for Item in self.LanguageDef: 226 if Item[0] == LangName: 227 IsLangInDef = True 228 break; 229 230 if not IsLangInDef: 231 self.LanguageDef.append([LangName, LangPrintName]) 232 233 # 234 # Add language string 235 # 236 self.AddStringToList(u'$LANGUAGE_NAME', LangName, LangName, 0, True, Index=0) 237 self.AddStringToList(u'$PRINTABLE_LANGUAGE_NAME', LangName, LangPrintName, 1, True, Index=1) 238 239 if not IsLangInDef: 240 # 241 # The found STRING tokens will be added into new language string list 242 # so that the unique STRING identifier is reserved for all languages in the package list. 243 # 244 FirstLangName = self.LanguageDef[0][0] 245 if LangName != FirstLangName: 246 for Index in range (2, len (self.OrderedStringList[FirstLangName])): 247 Item = self.OrderedStringList[FirstLangName][Index] 248 if Item.UseOtherLangDef != '': 249 OtherLang = Item.UseOtherLangDef 250 else: 251 OtherLang = FirstLangName 252 self.OrderedStringList[LangName].append (StringDefClassObject(Item.StringName, '', Item.Referenced, Item.Token, OtherLang)) 253 self.OrderedStringDict[LangName][Item.StringName] = len(self.OrderedStringList[LangName]) - 1 254 return True 255 256 # 257 # Get String name and value 258 # 259 def GetStringObject(self, Item): 260 Language = '' 261 Value = '' 262 263 Name = Item.split()[1] 264 # Check the string name is the upper character 265 if Name != '': 266 MatchString = re.match('[A-Z0-9_]+', Name, re.UNICODE) 267 if MatchString == None or MatchString.end(0) != len(Name): 268 EdkLogger.error('Unicode File Parser', FORMAT_INVALID, 'The string token name %s defined in UNI file %s contains the invalid lower case character.' %(Name, self.File)) 269 LanguageList = Item.split(u'#language ') 270 for IndexI in range(len(LanguageList)): 271 if IndexI == 0: 272 continue 273 else: 274 Language = LanguageList[IndexI].split()[0] 275 Value = LanguageList[IndexI][LanguageList[IndexI].find(u'\"') + len(u'\"') : LanguageList[IndexI].rfind(u'\"')] #.replace(u'\r\n', u'') 276 Language = GetLanguageCode(Language, self.IsCompatibleMode, self.File) 277 self.AddStringToList(Name, Language, Value) 278 279 # 280 # Get include file list and load them 281 # 282 def GetIncludeFile(self, Item, Dir): 283 FileName = Item[Item.find(u'#include ') + len(u'#include ') :Item.find(u' ', len(u'#include '))][1:-1] 284 self.LoadUniFile(FileName) 285 286 def StripComments(self, Line): 287 Comment = u'//' 288 CommentPos = Line.find(Comment) 289 while CommentPos >= 0: 290 # if there are non matched quotes before the comment header 291 # then we are in the middle of a string 292 # but we need to ignore the escaped quotes and backslashes. 293 if ((Line.count(u'"', 0, CommentPos) - Line.count(u'\\"', 0, CommentPos)) & 1) == 1: 294 CommentPos = Line.find (Comment, CommentPos + 1) 295 else: 296 return Line[:CommentPos] 297 return Line 298 299 300 # 301 # Pre-process before parse .uni file 302 # 303 def PreProcess(self, File): 304 if not os.path.exists(File.Path) or not os.path.isfile(File.Path): 305 EdkLogger.error("Unicode File Parser", FILE_NOT_FOUND, ExtraData=File.Path) 306 307 try: 308 FileIn = codecs.open(LongFilePath(File.Path), mode='rb', encoding='utf-16') 309 except UnicodeError, X: 310 EdkLogger.error("build", FILE_READ_FAILURE, "File read failure: %s" % str(X), ExtraData=File.Path); 311 except: 312 EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=File.Path); 313 314 Lines = [] 315 # 316 # Use unique identifier 317 # 318 for Line in FileIn: 319 Line = Line.strip() 320 Line = Line.replace(u'\\\\', BACK_SLASH_PLACEHOLDER) 321 Line = self.StripComments(Line) 322 323 # 324 # Ignore empty line 325 # 326 if len(Line) == 0: 327 continue 328 329 330 Line = Line.replace(u'/langdef', u'#langdef') 331 Line = Line.replace(u'/string', u'#string') 332 Line = Line.replace(u'/language', u'#language') 333 Line = Line.replace(u'/include', u'#include') 334 335 Line = Line.replace(UNICODE_WIDE_CHAR, WIDE_CHAR) 336 Line = Line.replace(UNICODE_NARROW_CHAR, NARROW_CHAR) 337 Line = Line.replace(UNICODE_NON_BREAKING_CHAR, NON_BREAKING_CHAR) 338 339 Line = Line.replace(u'\\r\\n', CR + LF) 340 Line = Line.replace(u'\\n', CR + LF) 341 Line = Line.replace(u'\\r', CR) 342 Line = Line.replace(u'\\t', u' ') 343 Line = Line.replace(u'\t', u' ') 344 Line = Line.replace(u'\\"', u'"') 345 Line = Line.replace(u"\\'", u"'") 346 Line = Line.replace(BACK_SLASH_PLACEHOLDER, u'\\') 347 348# if Line.find(u'\\x'): 349# hex = Line[Line.find(u'\\x') + 2 : Line.find(u'\\x') + 6] 350# hex = "u'\\u" + hex + "'" 351 352 IncList = gIncludePattern.findall(Line) 353 if len(IncList) == 1: 354 for Dir in [File.Dir] + self.IncludePathList: 355 IncFile = PathClass(str(IncList[0]), Dir) 356 if os.path.isfile(IncFile.Path): 357 Lines.extend(self.PreProcess(IncFile)) 358 break 359 else: 360 EdkLogger.error("Unicode File Parser", FILE_NOT_FOUND, Message="Cannot find include file", ExtraData=str(IncList[0])) 361 continue 362 363 Lines.append(Line) 364 365 return Lines 366 367 # 368 # Load a .uni file 369 # 370 def LoadUniFile(self, File = None): 371 if File == None: 372 EdkLogger.error("Unicode File Parser", PARSER_ERROR, 'No unicode file is given') 373 self.File = File 374 # 375 # Process special char in file 376 # 377 Lines = self.PreProcess(File) 378 379 # 380 # Get Unicode Information 381 # 382 for IndexI in range(len(Lines)): 383 Line = Lines[IndexI] 384 if (IndexI + 1) < len(Lines): 385 SecondLine = Lines[IndexI + 1] 386 if (IndexI + 2) < len(Lines): 387 ThirdLine = Lines[IndexI + 2] 388 389 # 390 # Get Language def information 391 # 392 if Line.find(u'#langdef ') >= 0: 393 self.GetLangDef(File, Line) 394 continue 395 396 Name = '' 397 Language = '' 398 Value = '' 399 # 400 # Get string def information format 1 as below 401 # 402 # #string MY_STRING_1 403 # #language eng 404 # My first English string line 1 405 # My first English string line 2 406 # #string MY_STRING_1 407 # #language spa 408 # Mi segunda secuencia 1 409 # Mi segunda secuencia 2 410 # 411 if Line.find(u'#string ') >= 0 and Line.find(u'#language ') < 0 and \ 412 SecondLine.find(u'#string ') < 0 and SecondLine.find(u'#language ') >= 0 and \ 413 ThirdLine.find(u'#string ') < 0 and ThirdLine.find(u'#language ') < 0: 414 Name = Line[Line.find(u'#string ') + len(u'#string ') : ].strip(' ') 415 Language = SecondLine[SecondLine.find(u'#language ') + len(u'#language ') : ].strip(' ') 416 for IndexJ in range(IndexI + 2, len(Lines)): 417 if Lines[IndexJ].find(u'#string ') < 0 and Lines[IndexJ].find(u'#language ') < 0: 418 Value = Value + Lines[IndexJ] 419 else: 420 IndexI = IndexJ 421 break 422 # Value = Value.replace(u'\r\n', u'') 423 Language = GetLanguageCode(Language, self.IsCompatibleMode, self.File) 424 # Check the string name is the upper character 425 if not self.IsCompatibleMode and Name != '': 426 MatchString = re.match('[A-Z0-9_]+', Name, re.UNICODE) 427 if MatchString == None or MatchString.end(0) != len(Name): 428 EdkLogger.error('Unicode File Parser', FORMAT_INVALID, 'The string token name %s defined in UNI file %s contains the invalid lower case character.' %(Name, self.File)) 429 self.AddStringToList(Name, Language, Value) 430 continue 431 432 # 433 # Get string def information format 2 as below 434 # 435 # #string MY_STRING_1 #language eng "My first English string line 1" 436 # "My first English string line 2" 437 # #language spa "Mi segunda secuencia 1" 438 # "Mi segunda secuencia 2" 439 # #string MY_STRING_2 #language eng "My first English string line 1" 440 # "My first English string line 2" 441 # #string MY_STRING_2 #language spa "Mi segunda secuencia 1" 442 # "Mi segunda secuencia 2" 443 # 444 if Line.find(u'#string ') >= 0 and Line.find(u'#language ') >= 0: 445 StringItem = Line 446 for IndexJ in range(IndexI + 1, len(Lines)): 447 if Lines[IndexJ].find(u'#string ') >= 0 and Lines[IndexJ].find(u'#language ') >= 0: 448 IndexI = IndexJ 449 break 450 elif Lines[IndexJ].find(u'#string ') < 0 and Lines[IndexJ].find(u'#language ') >= 0: 451 StringItem = StringItem + Lines[IndexJ] 452 elif Lines[IndexJ].count(u'\"') >= 2: 453 StringItem = StringItem[ : StringItem.rfind(u'\"')] + Lines[IndexJ][Lines[IndexJ].find(u'\"') + len(u'\"') : ] 454 self.GetStringObject(StringItem) 455 continue 456 457 # 458 # Load multiple .uni files 459 # 460 def LoadUniFiles(self, FileList): 461 if len(FileList) > 0: 462 for File in FileList: 463 self.LoadUniFile(File) 464 465 # 466 # Add a string to list 467 # 468 def AddStringToList(self, Name, Language, Value, Token = None, Referenced = False, UseOtherLangDef = '', Index = -1): 469 for LangNameItem in self.LanguageDef: 470 if Language == LangNameItem[0]: 471 break 472 else: 473 EdkLogger.error('Unicode File Parser', FORMAT_NOT_SUPPORTED, "The language '%s' for %s is not defined in Unicode file %s." \ 474 % (Language, Name, self.File)) 475 476 if Language not in self.OrderedStringList: 477 self.OrderedStringList[Language] = [] 478 self.OrderedStringDict[Language] = {} 479 480 IsAdded = True 481 if Name in self.OrderedStringDict[Language]: 482 IsAdded = False 483 if Value != None: 484 ItemIndexInList = self.OrderedStringDict[Language][Name] 485 Item = self.OrderedStringList[Language][ItemIndexInList] 486 Item.UpdateValue(Value) 487 Item.UseOtherLangDef = '' 488 489 if IsAdded: 490 Token = len(self.OrderedStringList[Language]) 491 if Index == -1: 492 self.OrderedStringList[Language].append(StringDefClassObject(Name, Value, Referenced, Token, UseOtherLangDef)) 493 self.OrderedStringDict[Language][Name] = Token 494 for LangName in self.LanguageDef: 495 # 496 # New STRING token will be added into all language string lists. 497 # so that the unique STRING identifier is reserved for all languages in the package list. 498 # 499 if LangName[0] != Language: 500 if UseOtherLangDef != '': 501 OtherLangDef = UseOtherLangDef 502 else: 503 OtherLangDef = Language 504 self.OrderedStringList[LangName[0]].append(StringDefClassObject(Name, '', Referenced, Token, OtherLangDef)) 505 self.OrderedStringDict[LangName[0]][Name] = len(self.OrderedStringList[LangName[0]]) - 1 506 else: 507 self.OrderedStringList[Language].insert(Index, StringDefClassObject(Name, Value, Referenced, Token, UseOtherLangDef)) 508 self.OrderedStringDict[Language][Name] = Index 509 510 # 511 # Set the string as referenced 512 # 513 def SetStringReferenced(self, Name): 514 # 515 # String stoken are added in the same order in all language string lists. 516 # So, only update the status of string stoken in first language string list. 517 # 518 Lang = self.LanguageDef[0][0] 519 if Name in self.OrderedStringDict[Lang]: 520 ItemIndexInList = self.OrderedStringDict[Lang][Name] 521 Item = self.OrderedStringList[Lang][ItemIndexInList] 522 Item.Referenced = True 523 524 # 525 # Search the string in language definition by Name 526 # 527 def FindStringValue(self, Name, Lang): 528 if Name in self.OrderedStringDict[Lang]: 529 ItemIndexInList = self.OrderedStringDict[Lang][Name] 530 return self.OrderedStringList[Lang][ItemIndexInList] 531 532 return None 533 534 # 535 # Search the string in language definition by Token 536 # 537 def FindByToken(self, Token, Lang): 538 for Item in self.OrderedStringList[Lang]: 539 if Item.Token == Token: 540 return Item 541 542 return None 543 544 # 545 # Re-order strings and re-generate tokens 546 # 547 def ReToken(self): 548 # 549 # Retoken all language strings according to the status of string stoken in the first language string. 550 # 551 FirstLangName = self.LanguageDef[0][0] 552 553 # Convert the OrderedStringList to be OrderedStringListByToken in order to faciliate future search by token 554 for LangNameItem in self.LanguageDef: 555 self.OrderedStringListByToken[LangNameItem[0]] = {} 556 557 # 558 # Use small token for all referred string stoken. 559 # 560 RefToken = 0 561 for Index in range (0, len (self.OrderedStringList[FirstLangName])): 562 FirstLangItem = self.OrderedStringList[FirstLangName][Index] 563 if FirstLangItem.Referenced == True: 564 for LangNameItem in self.LanguageDef: 565 LangName = LangNameItem[0] 566 OtherLangItem = self.OrderedStringList[LangName][Index] 567 OtherLangItem.Referenced = True 568 OtherLangItem.Token = RefToken 569 self.OrderedStringListByToken[LangName][OtherLangItem.Token] = OtherLangItem 570 RefToken = RefToken + 1 571 572 # 573 # Use big token for all unreferred string stoken. 574 # 575 UnRefToken = 0 576 for Index in range (0, len (self.OrderedStringList[FirstLangName])): 577 FirstLangItem = self.OrderedStringList[FirstLangName][Index] 578 if FirstLangItem.Referenced == False: 579 for LangNameItem in self.LanguageDef: 580 LangName = LangNameItem[0] 581 OtherLangItem = self.OrderedStringList[LangName][Index] 582 OtherLangItem.Token = RefToken + UnRefToken 583 self.OrderedStringListByToken[LangName][OtherLangItem.Token] = OtherLangItem 584 UnRefToken = UnRefToken + 1 585 586 # 587 # Show the instance itself 588 # 589 def ShowMe(self): 590 print self.LanguageDef 591 #print self.OrderedStringList 592 for Item in self.OrderedStringList: 593 print Item 594 for Member in self.OrderedStringList[Item]: 595 print str(Member) 596 597# This acts like the main() function for the script, unless it is 'import'ed into another 598# script. 599if __name__ == '__main__': 600 EdkLogger.Initialize() 601 EdkLogger.SetLevel(EdkLogger.DEBUG_0) 602 a = UniFileClassObject([PathClass("C:\\Edk\\Strings.uni"), PathClass("C:\\Edk\\Strings2.uni")]) 603 a.ReToken() 604 a.ShowMe() 605