1 # Copyright (c) 2007, Intel Corporation
\r
2 # All rights reserved. This program and the accompanying materials
\r
3 # are licensed and made available under the terms and conditions of the BSD License
\r
4 # which accompanies this distribution. The full text of the license may be found at
\r
5 # http://opensource.org/licenses/bsd-license.php
\r
7 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
\r
8 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
\r
11 #This file is used to parse a strings file and create or add to a string database file.
\r
18 import Common.EdkLogger as EdkLogger
\r
19 from Common.BuildToolError import *
\r
20 from UniClassObject import *
\r
23 # Static definitions
\r
25 EFI_HII_SIBT_END = '0x00'
\r
26 EFI_HII_SIBT_STRING_SCSU = '0x10'
\r
27 EFI_HII_SIBT_STRING_SCSU_FONT = '0x11'
\r
28 EFI_HII_SIBT_STRINGS_SCSU = '0x12'
\r
29 EFI_HII_SIBT_STRINGS_SCSU_FONT = '0x13'
\r
30 EFI_HII_SIBT_STRING_UCS2 = '0x14'
\r
31 EFI_HII_SIBT_STRING_UCS2_FONT = '0x15'
\r
32 EFI_HII_SIBT_STRINGS_UCS2 = '0x16'
\r
33 EFI_HII_SIBT_STRINGS_UCS2_FONT = '0x17'
\r
34 EFI_HII_SIBT_DUPLICATE = '0x20'
\r
35 EFI_HII_SIBT_SKIP2 = '0x21'
\r
36 EFI_HII_SIBT_SKIP1 = '0x22'
\r
37 EFI_HII_SIBT_EXT1 = '0x30'
\r
38 EFI_HII_SIBT_EXT2 = '0x31'
\r
39 EFI_HII_SIBT_EXT4 = '0x32'
\r
40 EFI_HII_SIBT_FONT = '0x40'
\r
42 EFI_HII_PACKAGE_STRINGS = '0x04'
\r
44 StringPackageType = EFI_HII_PACKAGE_STRINGS
\r
45 StringBlockType = EFI_HII_SIBT_STRING_UCS2
\r
46 StringSkipType = EFI_HII_SIBT_SKIP2
\r
51 DEFINE_STR = '#define'
\r
52 COMMENT_DEFINE_STR = COMMENT + DEFINE_STR
\r
53 NOT_REFERENCED = 'not referenced'
\r
54 COMMENT_NOT_REFERENCED = ' ' + COMMENT + NOT_REFERENCED
\r
55 CHAR_ARRAY_DEFIN = 'unsigned char'
\r
56 COMMON_FILE_NAME = 'Strings'
\r
60 STRING_TOKEN = re.compile('STRING_TOKEN *\(([A-Z0-9_]+) *\)', re.MULTILINE | re.UNICODE)
\r
62 EFI_HII_ARRAY_SIZE_LENGTH = 4
\r
63 EFI_HII_PACKAGE_HEADER_LENGTH = 4
\r
64 EFI_HII_HDR_SIZE_LENGTH = 4
\r
65 EFI_HII_STRING_OFFSET_LENGTH = 4
\r
67 EFI_STRING_ID_LENGTH = 2
\r
68 EFI_HII_LANGUAGE_WINDOW = 0
\r
69 EFI_HII_LANGUAGE_WINDOW_LENGTH = 2
\r
70 EFI_HII_LANGUAGE_WINDOW_NUMBER = 16
\r
71 EFI_HII_STRING_PACKAGE_HDR_LENGTH = EFI_HII_PACKAGE_HEADER_LENGTH + EFI_HII_HDR_SIZE_LENGTH + EFI_HII_STRING_OFFSET_LENGTH + EFI_HII_LANGUAGE_WINDOW_LENGTH * EFI_HII_LANGUAGE_WINDOW_NUMBER + EFI_STRING_ID_LENGTH
\r
73 H_C_FILE_HEADER = ['//', \
\r
74 '// DO NOT EDIT -- auto-generated file', \
\r
76 '// This file is generated by the StrGather utility', \
\r
78 LANGUAGE_NAME_STRING_NAME = '$LANGUAGE_NAME'
\r
79 PRINTABLE_LANGUAGE_NAME_STRING_NAME = '$PRINTABLE_LANGUAGE_NAME'
\r
81 ## Convert a dec number to a hex string
\r
83 # Convert a dec number to a formatted hex string in length digit
\r
84 # The digit is set to default 8
\r
85 # The hex string starts with "0x"
\r
86 # DecToHexStr(1000) is '0x000003E8'
\r
87 # DecToHexStr(1000, 6) is '0x0003E8'
\r
89 # @param Dec: The number in dec format
\r
90 # @param Digit: The needed digit of hex string
\r
92 # @retval: The formatted hex string
\r
94 def DecToHexStr(Dec, Digit = 8):
\r
95 return eval("'0x%0" + str(Digit) + "X' % int(Dec)")
\r
97 ## Convert a dec number to a hex list
\r
99 # Convert a dec number to a formatted hex list in size digit
\r
100 # The digit is set to default 8
\r
101 # DecToHexList(1000) is ['0xE8', '0x03', '0x00', '0x00']
\r
102 # DecToHexList(1000, 6) is ['0xE8', '0x03', '0x00']
\r
104 # @param Dec: The number in dec format
\r
105 # @param Digit: The needed digit of hex list
\r
107 # @retval: A list for formatted hex string
\r
109 def DecToHexList(Dec, Digit = 8):
\r
110 Hex = eval("'%0" + str(Digit) + "X' % int(Dec)" )
\r
112 for Bit in range(Digit - 2, -1, -2):
\r
113 List.append(HexHeader + Hex[Bit:Bit + 2])
\r
116 ## Convert a acsii string to a hex list
\r
118 # Convert a acsii string to a formatted hex list
\r
119 # AscToHexList('en-US') is ['0x65', '0x6E', '0x2D', '0x55', '0x53']
\r
121 # @param Ascii: The acsii string
\r
123 # @retval: A list for formatted hex string
\r
125 def AscToHexList(Ascii):
\r
128 List.append('0x%2X' % ord(Item))
\r
132 ## Create header of .h file
\r
134 # Create a header of .h file
\r
136 # @param BaseName: The basename of strings
\r
138 # @retval Str: A string for .h file header
\r
140 def CreateHFileHeader(BaseName):
\r
142 for Item in H_C_FILE_HEADER:
\r
143 Str = WriteLine(Str, Item)
\r
144 Str = WriteLine(Str, '#ifndef _' + BaseName.upper() + '_STRINGS_DEFINE_H_')
\r
145 Str = WriteLine(Str, '#define _' + BaseName.upper() + '_STRINGS_DEFINE_H_')
\r
148 ## Create content of .h file
\r
150 # Create content of .h file
\r
152 # @param BaseName: The basename of strings
\r
153 # @param UniObjectClass: A UniObjectClass instance
\r
155 # @retval Str: A string of .h file content
\r
157 def CreateHFileContent(BaseName, UniObjectClass):
\r
160 Line = COMMENT_DEFINE_STR + ' ' + LANGUAGE_NAME_STRING_NAME + ' ' * (ValueStartPtr - len(DEFINE_STR + LANGUAGE_NAME_STRING_NAME)) + DecToHexStr(0, 4) + COMMENT_NOT_REFERENCED
\r
161 Str = WriteLine(Str, Line)
\r
162 Line = COMMENT_DEFINE_STR + ' ' + PRINTABLE_LANGUAGE_NAME_STRING_NAME + ' ' * (ValueStartPtr - len(DEFINE_STR + PRINTABLE_LANGUAGE_NAME_STRING_NAME)) + DecToHexStr(1, 4) + COMMENT_NOT_REFERENCED
\r
163 Str = WriteLine(Str, Line)
\r
164 for Index in range(2, len(UniObjectClass.OrderedStringList[UniObjectClass.LanguageDef[0][0]])):
\r
165 StringItem = UniObjectClass.OrderedStringList[UniObjectClass.LanguageDef[0][0]][Index]
\r
166 Name = StringItem.StringName
\r
167 Token = StringItem.Token
\r
168 Referenced = StringItem.Referenced
\r
171 if Referenced == True:
\r
172 Line = DEFINE_STR + ' ' + Name + ' ' * (ValueStartPtr - len(DEFINE_STR + Name)) + DecToHexStr(Token, 4)
\r
174 Line = COMMENT_DEFINE_STR + ' ' + Name + ' ' * (ValueStartPtr - len(DEFINE_STR + Name)) + DecToHexStr(Token, 4) + COMMENT_NOT_REFERENCED
\r
175 Str = WriteLine(Str, Line)
\r
177 Str = WriteLine(Str, '')
\r
178 Str = WriteLine(Str, 'extern unsigned char ' + BaseName + 'Strings[];')
\r
181 ## Create a complete .h file
\r
183 # Create a complet .h file with file header and file content
\r
185 # @param BaseName: The basename of strings
\r
186 # @param UniObjectClass: A UniObjectClass instance
\r
188 # @retval Str: A string of complete .h file
\r
190 def CreateHFile(BaseName, UniObjectClass):
\r
191 HFile = WriteLine('', CreateHFileContent(BaseName, UniObjectClass))
\r
195 ## Create header of .c file
\r
197 # Create a header of .c file
\r
199 # @retval Str: A string for .c file header
\r
201 def CreateCFileHeader():
\r
203 for Item in H_C_FILE_HEADER:
\r
204 Str = WriteLine(Str, Item)
\r
208 ## Create a formatted string all items in an array
\r
210 # Use ',' to join each item in an array, and break an new line when reaching the width (default is 16)
\r
212 # @param Array: The array need to be formatted
\r
213 # @param Width: The line length, the default value is set to 16
\r
215 # @retval ArrayItem: A string for all formatted array items
\r
217 def CreateArrayItem(Array, Width = 16):
\r
224 if Index < MaxLength:
\r
225 Line = Line + Item + ', '
\r
228 ArrayItem = WriteLine(ArrayItem, Line)
\r
229 Line = ' ' + Item + ', '
\r
231 ArrayItem = Write(ArrayItem, Line.rstrip())
\r
235 ## CreateCFileStringValue
\r
237 # Create a line with string value
\r
239 # @param Value: Value of the string
\r
241 # @retval Str: A formatted string with string value
\r
244 def CreateCFileStringValue(Value):
\r
245 Value = [StringBlockType] + Value
\r
246 Str = WriteLine('', CreateArrayItem(Value))
\r
251 ## Create content of .c file
\r
253 # Create content of .c file
\r
255 # @param BaseName: The basename of strings
\r
256 # @param UniObjectClass: A UniObjectClass instance
\r
258 # @retval Str: A string of .c file content
\r
260 def CreateCFileContent(BaseName, UniObjectClass):
\r
262 # Init array length
\r
264 TotalLength = EFI_HII_ARRAY_SIZE_LENGTH
\r
269 # Create lines for each language's strings
\r
271 for IndexI in range(len(UniObjectClass.LanguageDef)):
\r
272 Language = UniObjectClass.LanguageDef[IndexI][0]
\r
273 LangPrintName = UniObjectClass.LanguageDef[IndexI][1]
\r
275 StrStringValue = ''
\r
277 NumberOfUseOhterLangDef = 0
\r
279 for IndexJ in range(1, len(UniObjectClass.OrderedStringList[UniObjectClass.LanguageDef[IndexI][0]])):
\r
280 Item = UniObjectClass.FindByToken(IndexJ, Language)
\r
281 #Item = UniObjectClass.OrderedStringList[UniObjectClass.LanguageDef[IndexI][0]][IndexJ]
\r
282 #for Item in UniObjectClass.OrderedStringList[Language]:
\r
283 Name = Item.StringName
\r
284 Value = Item.StringValueByteList
\r
285 Referenced = Item.Referenced
\r
287 Length = Item.Length
\r
288 UseOtherLangDef = Item.UseOtherLangDef
\r
290 if UseOtherLangDef != '' and Referenced:
\r
291 NumberOfUseOhterLangDef = NumberOfUseOhterLangDef + 1
\r
294 if NumberOfUseOhterLangDef > 0:
\r
295 StrStringValue = WriteLine(StrStringValue, CreateArrayItem([StringSkipType, DecToHexStr(NumberOfUseOhterLangDef, 2), EFI_HII_SIBT_END]))
\r
296 NumberOfUseOhterLangDef = 0
\r
297 ArrayLength = ArrayLength + 3
\r
298 if Referenced and Item.Token > 0:
\r
300 StrStringValue = WriteLine(StrStringValue, "// %s: %s:%s" % (DecToHexStr(Index, 4), Name, DecToHexStr(Token, 4)))
\r
301 StrStringValue = Write(StrStringValue, CreateCFileStringValue(Value))
\r
302 Offset = Offset + Length
\r
303 ArrayLength = ArrayLength + Item.Length + 1 # 1 is for the length of string type
\r
306 # EFI_HII_PACKAGE_HEADER
\r
308 Str = WriteLine(Str, '// PACKAGE HEADER\n')
\r
309 Offset = EFI_HII_STRING_PACKAGE_HDR_LENGTH + len(Language) + 1
\r
310 ArrayLength = Offset + ArrayLength + 1
\r
311 TotalLength = TotalLength + ArrayLength
\r
313 List = DecToHexList(ArrayLength, 6) + \
\r
314 [StringPackageType] + \
\r
315 DecToHexList(Offset) + \
\r
316 DecToHexList(Offset) + \
\r
317 DecToHexList(EFI_HII_LANGUAGE_WINDOW, EFI_HII_LANGUAGE_WINDOW_LENGTH * 2) * EFI_HII_LANGUAGE_WINDOW_NUMBER + \
\r
318 DecToHexList(EFI_STRING_ID, 4) + \
\r
319 AscToHexList(Language) + \
\r
321 Str = WriteLine(Str, CreateArrayItem(List, 16) + '\n')
\r
326 Str = WriteLine(Str, '// PACKAGE DATA\n')
\r
327 Str = Write(Str, StrStringValue)
\r
330 # Add an EFI_HII_SIBT_END at last
\r
332 Str = WriteLine(Str, ' ' + EFI_HII_SIBT_END + ",")
\r
335 # Create line for string variable name
\r
336 # "unsigned char $(BaseName)Strings[] = {"
\r
338 AllStr = WriteLine('', CHAR_ARRAY_DEFIN + ' ' + BaseName + COMMON_FILE_NAME + '[] = {\n' )
\r
341 # Create whole array length
\r
343 AllStr = WriteLine(AllStr, '// STRING ARRAY LENGTH\n')
\r
344 AllStr = WriteLine(AllStr, CreateArrayItem(DecToHexList(TotalLength)))
\r
347 # Join package data
\r
349 AllStr = Write(AllStr, Str)
\r
353 ## Create end of .c file
\r
355 # Create end of .c file
\r
357 # @retval Str: A string of .h file end
\r
359 def CreateCFileEnd():
\r
360 Str = Write('', '};')
\r
363 ## Create a .c file
\r
365 # Create a complete .c file
\r
367 # @param BaseName: The basename of strings
\r
368 # @param UniObjectClass: A UniObjectClass instance
\r
370 # @retval CFile: A string of complete .c file
\r
372 def CreateCFile(BaseName, UniObjectClass):
\r
374 #CFile = WriteLine(CFile, CreateCFileHeader())
\r
375 CFile = WriteLine(CFile, CreateCFileContent(BaseName, UniObjectClass))
\r
376 CFile = WriteLine(CFile, CreateCFileEnd())
\r
381 # Get a list for all files
\r
383 # @param IncludeList: A list of all path to be searched
\r
384 # @param SkipList: A list of all types of file could be skipped
\r
386 # @retval FileList: A list of all files found
\r
388 def GetFileList(SourceFileList, IncludeList, SkipList):
\r
389 if IncludeList == None:
\r
390 EdkLogger.error("UnicodeStringGather", AUTOGEN_ERROR, "Include path for unicode file is not defined")
\r
393 if SkipList == None:
\r
396 for File in SourceFileList:
\r
397 for Dir in IncludeList:
\r
398 if not os.path.exists(Dir):
\r
400 File = os.path.join(Dir, os.path.normcase(File))
\r
404 if os.path.isfile(File) != True:
\r
407 # Ignore file listed in skip list
\r
410 for Skip in SkipList:
\r
411 if os.path.splitext(File)[1].upper() == Skip.upper():
\r
412 EdkLogger.verbose("Skipped %s for string token uses search" % File)
\r
417 FileList.append(File)
\r
424 # Search whether all string defined in UniObjectClass are referenced
\r
425 # All string used should be set to Referenced
\r
427 # @param UniObjectClass: Input UniObjectClass
\r
428 # @param FileList: Search path list
\r
430 # @retval UniObjectClass: UniObjectClass after searched
\r
432 def SearchString(UniObjectClass, FileList):
\r
434 return UniObjectClass
\r
436 for File in FileList:
\r
437 if os.path.isfile(File):
\r
438 Lines = open(File, 'r')
\r
440 StringTokenList = STRING_TOKEN.findall(Line)
\r
441 for StrName in StringTokenList:
\r
442 EdkLogger.debug(EdkLogger.DEBUG_5, "Found string identifier: " + StrName)
\r
443 UniObjectClass.SetStringReferenced(StrName)
\r
445 UniObjectClass.ReToken()
\r
447 return UniObjectClass
\r
451 # This function is used for UEFI2.1 spec
\r
454 def GetStringFiles(UniFilList, SourceFileList, IncludeList, SkipList, BaseName):
\r
458 if len(UniFilList) > 0:
\r
459 Uni = UniFileClassObject(UniFilList)
\r
461 EdkLogger.error("UnicodeStringGather", AUTOGEN_ERROR, 'No unicode files given')
\r
463 FileList = GetFileList(SourceFileList, IncludeList, SkipList)
\r
465 Uni = SearchString(Uni, FileList)
\r
467 HFile = CreateHFile(BaseName, Uni)
\r
468 CFile = CreateCFile(BaseName, Uni)
\r
470 return HFile, CFile
\r
475 def Write(Target, Item):
\r
476 return Target + Item
\r
479 # Write an item with a break line
\r
481 def WriteLine(Target, Item):
\r
482 return Target + Item + '\n'
\r
484 # This acts like the main() function for the script, unless it is 'import'ed into another
\r
486 if __name__ == '__main__':
\r
487 EdkLogger.info('start')
\r
490 r'C:\\Edk\\Strings2.uni',
\r
491 r'C:\\Edk\\Strings.uni'
\r
498 SkipList = ['.inf', '.uni']
\r
499 BaseName = 'DriverSample'
\r
500 (h, c) = GetStringFiles(UniFileList, IncludeList, SkipList, BaseName)
\r
501 hfile = open('unistring.h', 'w')
\r
502 cfile = open('unistring.c', 'w')
\r
506 EdkLogger.info('end')
\r