]>
Commit | Line | Data |
---|---|---|
97fa0ee9 | 1 | ## @file\r |
f7496d71 | 2 | # This file is used to parse a strings file and create or add to a string database\r |
97fa0ee9 YL |
3 | # file.\r |
4 | #\r | |
afb04ba1 | 5 | # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r |
40d841f6 | 6 | # This program and the accompanying materials\r |
30fdf114 LG |
7 | # are licensed and made available under the terms and conditions of the BSD License\r |
8 | # which accompanies this distribution. The full text of the license may be found at\r | |
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 | |
30fdf114 LG |
14 | ##\r |
15 | # Import Modules\r | |
16 | #\r | |
1ccc4d89 | 17 | from __future__ import absolute_import\r |
30fdf114 LG |
18 | import re\r |
19 | import Common.EdkLogger as EdkLogger\r | |
20 | from Common.BuildToolError import *\r | |
0ff3b52e | 21 | from .UniClassObject import *\r |
86379ac4 | 22 | from io import BytesIO\r |
333ba578 | 23 | from struct import pack, unpack\r |
1be2ed90 | 24 | from Common.LongFilePathSupport import OpenLongFilePath as open\r |
30fdf114 LG |
25 | \r |
26 | ##\r | |
27 | # Static definitions\r | |
28 | #\r | |
29 | EFI_HII_SIBT_END = '0x00'\r | |
30 | EFI_HII_SIBT_STRING_SCSU = '0x10'\r | |
31 | EFI_HII_SIBT_STRING_SCSU_FONT = '0x11'\r | |
32 | EFI_HII_SIBT_STRINGS_SCSU = '0x12'\r | |
33 | EFI_HII_SIBT_STRINGS_SCSU_FONT = '0x13'\r | |
34 | EFI_HII_SIBT_STRING_UCS2 = '0x14'\r | |
35 | EFI_HII_SIBT_STRING_UCS2_FONT = '0x15'\r | |
36 | EFI_HII_SIBT_STRINGS_UCS2 = '0x16'\r | |
37 | EFI_HII_SIBT_STRINGS_UCS2_FONT = '0x17'\r | |
38 | EFI_HII_SIBT_DUPLICATE = '0x20'\r | |
39 | EFI_HII_SIBT_SKIP2 = '0x21'\r | |
40 | EFI_HII_SIBT_SKIP1 = '0x22'\r | |
41 | EFI_HII_SIBT_EXT1 = '0x30'\r | |
42 | EFI_HII_SIBT_EXT2 = '0x31'\r | |
43 | EFI_HII_SIBT_EXT4 = '0x32'\r | |
44 | EFI_HII_SIBT_FONT = '0x40'\r | |
45 | \r | |
46 | EFI_HII_PACKAGE_STRINGS = '0x04'\r | |
47 | EFI_HII_PACKAGE_FORM = '0x02'\r | |
48 | \r | |
49 | StringPackageType = EFI_HII_PACKAGE_STRINGS\r | |
50 | StringPackageForm = EFI_HII_PACKAGE_FORM\r | |
51 | StringBlockType = EFI_HII_SIBT_STRING_UCS2\r | |
52 | StringSkipType = EFI_HII_SIBT_SKIP2\r | |
53 | \r | |
54 | HexHeader = '0x'\r | |
55 | \r | |
56 | COMMENT = '// '\r | |
57 | DEFINE_STR = '#define'\r | |
58 | COMMENT_DEFINE_STR = COMMENT + DEFINE_STR\r | |
59 | NOT_REFERENCED = 'not referenced'\r | |
60 | COMMENT_NOT_REFERENCED = ' ' + COMMENT + NOT_REFERENCED\r | |
61 | CHAR_ARRAY_DEFIN = 'unsigned char'\r | |
62 | COMMON_FILE_NAME = 'Strings'\r | |
30fdf114 LG |
63 | STRING_TOKEN = re.compile('STRING_TOKEN *\(([A-Z0-9_]+) *\)', re.MULTILINE | re.UNICODE)\r |
64 | \r | |
65 | EFI_HII_ARRAY_SIZE_LENGTH = 4\r | |
66 | EFI_HII_PACKAGE_HEADER_LENGTH = 4\r | |
67 | EFI_HII_HDR_SIZE_LENGTH = 4\r | |
68 | EFI_HII_STRING_OFFSET_LENGTH = 4\r | |
69 | EFI_STRING_ID = 1\r | |
70 | EFI_STRING_ID_LENGTH = 2\r | |
71 | EFI_HII_LANGUAGE_WINDOW = 0\r | |
72 | EFI_HII_LANGUAGE_WINDOW_LENGTH = 2\r | |
73 | EFI_HII_LANGUAGE_WINDOW_NUMBER = 16\r | |
74 | 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 | |
75 | \r | |
76 | H_C_FILE_HEADER = ['//', \\r | |
77 | '// DO NOT EDIT -- auto-generated file', \\r | |
78 | '//', \\r | |
79 | '// This file is generated by the StrGather utility', \\r | |
80 | '//']\r | |
81 | LANGUAGE_NAME_STRING_NAME = '$LANGUAGE_NAME'\r | |
82 | PRINTABLE_LANGUAGE_NAME_STRING_NAME = '$PRINTABLE_LANGUAGE_NAME'\r | |
83 | \r | |
84 | ## Convert a dec number to a hex string\r | |
85 | #\r | |
86 | # Convert a dec number to a formatted hex string in length digit\r | |
87 | # The digit is set to default 8\r | |
88 | # The hex string starts with "0x"\r | |
89 | # DecToHexStr(1000) is '0x000003E8'\r | |
90 | # DecToHexStr(1000, 6) is '0x0003E8'\r | |
91 | #\r | |
92 | # @param Dec: The number in dec format\r | |
93 | # @param Digit: The needed digit of hex string\r | |
94 | #\r | |
95 | # @retval: The formatted hex string\r | |
96 | #\r | |
97 | def DecToHexStr(Dec, Digit = 8):\r | |
ccaa7754 | 98 | return '0x{0:0{1}X}'.format(Dec, Digit)\r |
30fdf114 LG |
99 | \r |
100 | ## Convert a dec number to a hex list\r | |
101 | #\r | |
102 | # Convert a dec number to a formatted hex list in size digit\r | |
103 | # The digit is set to default 8\r | |
104 | # DecToHexList(1000) is ['0xE8', '0x03', '0x00', '0x00']\r | |
105 | # DecToHexList(1000, 6) is ['0xE8', '0x03', '0x00']\r | |
106 | #\r | |
107 | # @param Dec: The number in dec format\r | |
108 | # @param Digit: The needed digit of hex list\r | |
109 | #\r | |
110 | # @retval: A list for formatted hex string\r | |
111 | #\r | |
112 | def DecToHexList(Dec, Digit = 8):\r | |
ccaa7754 | 113 | Hex = '{0:0{1}X}'.format(Dec, Digit)\r |
549c59b3 | 114 | return ["0x" + Hex[Bit:Bit + 2] for Bit in range(Digit - 2, -1, -2)]\r |
30fdf114 LG |
115 | \r |
116 | ## Convert a acsii string to a hex list\r | |
117 | #\r | |
118 | # Convert a acsii string to a formatted hex list\r | |
119 | # AscToHexList('en-US') is ['0x65', '0x6E', '0x2D', '0x55', '0x53']\r | |
120 | #\r | |
121 | # @param Ascii: The acsii string\r | |
122 | #\r | |
123 | # @retval: A list for formatted hex string\r | |
124 | #\r | |
125 | def AscToHexList(Ascii):\r | |
d943b0c3 FB |
126 | try:\r |
127 | return ['0x{0:02X}'.format(Item) for Item in Ascii]\r | |
128 | except:\r | |
129 | return ['0x{0:02X}'.format(ord(Item)) for Item in Ascii]\r | |
30fdf114 | 130 | \r |
30fdf114 LG |
131 | ## Create content of .h file\r |
132 | #\r | |
133 | # Create content of .h file\r | |
134 | #\r | |
b303ea72 LG |
135 | # @param BaseName: The basename of strings\r |
136 | # @param UniObjectClass A UniObjectClass instance\r | |
137 | # @param IsCompatibleMode Compatible mode\r | |
138 | # @param UniGenCFlag UniString is generated into AutoGen C file when it is set to True\r | |
30fdf114 LG |
139 | #\r |
140 | # @retval Str: A string of .h file content\r | |
141 | #\r | |
b303ea72 | 142 | def CreateHFileContent(BaseName, UniObjectClass, IsCompatibleMode, UniGenCFlag):\r |
4e375707 | 143 | Str = []\r |
30fdf114 LG |
144 | ValueStartPtr = 60\r |
145 | Line = COMMENT_DEFINE_STR + ' ' + LANGUAGE_NAME_STRING_NAME + ' ' * (ValueStartPtr - len(DEFINE_STR + LANGUAGE_NAME_STRING_NAME)) + DecToHexStr(0, 4) + COMMENT_NOT_REFERENCED\r | |
146 | Str = WriteLine(Str, Line)\r | |
147 | 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 | |
148 | Str = WriteLine(Str, Line)\r | |
79b74a03 | 149 | UnusedStr = ''\r |
756ad8f8 | 150 | \r |
f7496d71 | 151 | #Group the referred/Unused STRING token together.\r |
30fdf114 LG |
152 | for Index in range(2, len(UniObjectClass.OrderedStringList[UniObjectClass.LanguageDef[0][0]])):\r |
153 | StringItem = UniObjectClass.OrderedStringList[UniObjectClass.LanguageDef[0][0]][Index]\r | |
154 | Name = StringItem.StringName\r | |
155 | Token = StringItem.Token\r | |
156 | Referenced = StringItem.Referenced\r | |
4231a819 | 157 | if Name is not None:\r |
30fdf114 LG |
158 | Line = ''\r |
159 | if Referenced == True:\r | |
fd171542 | 160 | if (ValueStartPtr - len(DEFINE_STR + Name)) <= 0:\r |
161 | Line = DEFINE_STR + ' ' + Name + ' ' + DecToHexStr(Token, 4)\r | |
162 | else:\r | |
163 | Line = DEFINE_STR + ' ' + Name + ' ' * (ValueStartPtr - len(DEFINE_STR + Name)) + DecToHexStr(Token, 4)\r | |
756ad8f8 | 164 | Str = WriteLine(Str, Line)\r |
79b74a03 | 165 | else:\r |
fd171542 | 166 | if (ValueStartPtr - len(DEFINE_STR + Name)) <= 0:\r |
167 | Line = COMMENT_DEFINE_STR + ' ' + Name + ' ' + DecToHexStr(Token, 4) + COMMENT_NOT_REFERENCED\r | |
168 | else:\r | |
169 | Line = COMMENT_DEFINE_STR + ' ' + Name + ' ' * (ValueStartPtr - len(DEFINE_STR + Name)) + DecToHexStr(Token, 4) + COMMENT_NOT_REFERENCED\r | |
79b74a03 LG |
170 | UnusedStr = WriteLine(UnusedStr, Line)\r |
171 | \r | |
4e375707 | 172 | Str.extend( UnusedStr)\r |
30fdf114 | 173 | \r |
b303ea72 LG |
174 | Str = WriteLine(Str, '')\r |
175 | if IsCompatibleMode or UniGenCFlag:\r | |
176 | Str = WriteLine(Str, 'extern unsigned char ' + BaseName + 'Strings[];')\r | |
4e375707 | 177 | return "".join(Str)\r |
30fdf114 LG |
178 | \r |
179 | ## Create a complete .h file\r | |
180 | #\r | |
181 | # Create a complet .h file with file header and file content\r | |
182 | #\r | |
b303ea72 LG |
183 | # @param BaseName: The basename of strings\r |
184 | # @param UniObjectClass A UniObjectClass instance\r | |
185 | # @param IsCompatibleMode Compatible mode\r | |
186 | # @param UniGenCFlag UniString is generated into AutoGen C file when it is set to True\r | |
30fdf114 LG |
187 | #\r |
188 | # @retval Str: A string of complete .h file\r | |
189 | #\r | |
b303ea72 LG |
190 | def CreateHFile(BaseName, UniObjectClass, IsCompatibleMode, UniGenCFlag):\r |
191 | HFile = WriteLine('', CreateHFileContent(BaseName, UniObjectClass, IsCompatibleMode, UniGenCFlag))\r | |
30fdf114 | 192 | \r |
4e375707 | 193 | return "".join(HFile)\r |
30fdf114 | 194 | \r |
b303ea72 LG |
195 | ## Create a buffer to store all items in an array\r |
196 | #\r | |
197 | # @param BinBuffer Buffer to contain Binary data.\r | |
198 | # @param Array: The array need to be formatted\r | |
199 | #\r | |
200 | def CreateBinBuffer(BinBuffer, Array):\r | |
201 | for Item in Array:\r | |
47fea6af | 202 | BinBuffer.write(pack("B", int(Item, 16)))\r |
b303ea72 | 203 | \r |
30fdf114 LG |
204 | ## Create a formatted string all items in an array\r |
205 | #\r | |
206 | # Use ',' to join each item in an array, and break an new line when reaching the width (default is 16)\r | |
207 | #\r | |
208 | # @param Array: The array need to be formatted\r | |
209 | # @param Width: The line length, the default value is set to 16\r | |
210 | #\r | |
211 | # @retval ArrayItem: A string for all formatted array items\r | |
212 | #\r | |
213 | def CreateArrayItem(Array, Width = 16):\r | |
214 | MaxLength = Width\r | |
215 | Index = 0\r | |
216 | Line = ' '\r | |
4e375707 | 217 | ArrayItem = []\r |
30fdf114 LG |
218 | \r |
219 | for Item in Array:\r | |
220 | if Index < MaxLength:\r | |
221 | Line = Line + Item + ', '\r | |
222 | Index = Index + 1\r | |
223 | else:\r | |
224 | ArrayItem = WriteLine(ArrayItem, Line)\r | |
47fea6af | 225 | Line = ' ' + Item + ', '\r |
30fdf114 LG |
226 | Index = 1\r |
227 | ArrayItem = Write(ArrayItem, Line.rstrip())\r | |
228 | \r | |
4e375707 | 229 | return "".join(ArrayItem)\r |
30fdf114 LG |
230 | \r |
231 | ## CreateCFileStringValue\r | |
232 | #\r | |
233 | # Create a line with string value\r | |
234 | #\r | |
235 | # @param Value: Value of the string\r | |
236 | #\r | |
237 | # @retval Str: A formatted string with string value\r | |
238 | #\r | |
239 | \r | |
240 | def CreateCFileStringValue(Value):\r | |
241 | Value = [StringBlockType] + Value\r | |
242 | Str = WriteLine('', CreateArrayItem(Value))\r | |
243 | \r | |
4e375707 | 244 | return "".join(Str)\r |
30fdf114 | 245 | \r |
6780eef1 LG |
246 | ## GetFilteredLanguage\r |
247 | #\r | |
248 | # apply get best language rules to the UNI language code list\r | |
249 | #\r | |
250 | # @param UniLanguageList: language code definition list in *.UNI file\r | |
251 | # @param LanguageFilterList: language code filter list of RFC4646 format in DSC file\r | |
252 | #\r | |
253 | # @retval UniLanguageListFiltered: the filtered language code\r | |
254 | #\r | |
255 | def GetFilteredLanguage(UniLanguageList, LanguageFilterList):\r | |
256 | UniLanguageListFiltered = []\r | |
257 | # if filter list is empty, then consider there is no filter\r | |
258 | if LanguageFilterList == []:\r | |
259 | UniLanguageListFiltered = UniLanguageList\r | |
260 | return UniLanguageListFiltered\r | |
261 | for Language in LanguageFilterList:\r | |
262 | # first check for exact match\r | |
263 | if Language in UniLanguageList:\r | |
264 | if Language not in UniLanguageListFiltered:\r | |
caf74495 | 265 | UniLanguageListFiltered.append(Language)\r |
6780eef1 LG |
266 | # find the first one with the same/equivalent primary tag\r |
267 | else:\r | |
268 | if Language.find('-') != -1:\r | |
269 | PrimaryTag = Language[0:Language.find('-')].lower()\r | |
270 | else:\r | |
271 | PrimaryTag = Language\r | |
f7496d71 | 272 | \r |
6780eef1 LG |
273 | if len(PrimaryTag) == 3:\r |
274 | PrimaryTag = LangConvTable.get(PrimaryTag)\r | |
f7496d71 | 275 | \r |
6780eef1 LG |
276 | for UniLanguage in UniLanguageList:\r |
277 | if UniLanguage.find('-') != -1:\r | |
278 | UniLanguagePrimaryTag = UniLanguage[0:UniLanguage.find('-')].lower()\r | |
279 | else:\r | |
280 | UniLanguagePrimaryTag = UniLanguage\r | |
f7496d71 | 281 | \r |
6780eef1 LG |
282 | if len(UniLanguagePrimaryTag) == 3:\r |
283 | UniLanguagePrimaryTag = LangConvTable.get(UniLanguagePrimaryTag)\r | |
284 | \r | |
285 | if PrimaryTag == UniLanguagePrimaryTag:\r | |
286 | if UniLanguage not in UniLanguageListFiltered:\r | |
caf74495 | 287 | UniLanguageListFiltered.append(UniLanguage)\r |
6780eef1 LG |
288 | break\r |
289 | else:\r | |
290 | # Here is rule 3 for "get best language"\r | |
291 | # If tag is not listed in the Unicode file, the default ("en") tag should be used for that language\r | |
292 | # for better processing, find the one that best suit for it.\r | |
293 | DefaultTag = 'en'\r | |
294 | if DefaultTag not in UniLanguageListFiltered:\r | |
295 | # check whether language code with primary code equivalent with DefaultTag already in the list, if so, use that\r | |
296 | for UniLanguage in UniLanguageList:\r | |
297 | if UniLanguage.startswith('en-') or UniLanguage.startswith('eng-'):\r | |
298 | if UniLanguage not in UniLanguageListFiltered:\r | |
caf74495 | 299 | UniLanguageListFiltered.append(UniLanguage)\r |
6780eef1 LG |
300 | break\r |
301 | else:\r | |
caf74495 | 302 | UniLanguageListFiltered.append(DefaultTag)\r |
6780eef1 LG |
303 | return UniLanguageListFiltered\r |
304 | \r | |
30fdf114 LG |
305 | \r |
306 | ## Create content of .c file\r | |
307 | #\r | |
308 | # Create content of .c file\r | |
309 | #\r | |
b303ea72 LG |
310 | # @param BaseName: The basename of strings\r |
311 | # @param UniObjectClass A UniObjectClass instance\r | |
312 | # @param IsCompatibleMode Compatible mode\r | |
313 | # @param UniBinBuffer UniBinBuffer to contain UniBinary data.\r | |
f7496d71 | 314 | # @param FilterInfo Platform language filter information\r |
30fdf114 LG |
315 | #\r |
316 | # @retval Str: A string of .c file content\r | |
317 | #\r | |
6780eef1 | 318 | def CreateCFileContent(BaseName, UniObjectClass, IsCompatibleMode, UniBinBuffer, FilterInfo):\r |
30fdf114 LG |
319 | #\r |
320 | # Init array length\r | |
321 | #\r | |
322 | TotalLength = EFI_HII_ARRAY_SIZE_LENGTH\r | |
323 | Str = ''\r | |
324 | Offset = 0\r | |
325 | \r | |
6780eef1 LG |
326 | EDK2Module = FilterInfo[0]\r |
327 | if EDK2Module:\r | |
328 | LanguageFilterList = FilterInfo[1]\r | |
329 | else:\r | |
330 | # EDK module is using ISO639-2 format filter, convert to the RFC4646 format\r | |
331 | LanguageFilterList = [LangConvTable.get(F.lower()) for F in FilterInfo[1]]\r | |
f7496d71 | 332 | \r |
6780eef1 LG |
333 | UniLanguageList = []\r |
334 | for IndexI in range(len(UniObjectClass.LanguageDef)):\r | |
47fea6af | 335 | UniLanguageList += [UniObjectClass.LanguageDef[IndexI][0]]\r |
6780eef1 LG |
336 | \r |
337 | UniLanguageListFiltered = GetFilteredLanguage(UniLanguageList, LanguageFilterList)\r | |
f7496d71 LG |
338 | \r |
339 | \r | |
30fdf114 LG |
340 | #\r |
341 | # Create lines for each language's strings\r | |
342 | #\r | |
343 | for IndexI in range(len(UniObjectClass.LanguageDef)):\r | |
344 | Language = UniObjectClass.LanguageDef[IndexI][0]\r | |
6780eef1 LG |
345 | if Language not in UniLanguageListFiltered:\r |
346 | continue\r | |
f7496d71 | 347 | \r |
86379ac4 | 348 | StringBuffer = BytesIO()\r |
30fdf114 LG |
349 | StrStringValue = ''\r |
350 | ArrayLength = 0\r | |
b303ea72 | 351 | NumberOfUseOtherLangDef = 0\r |
30fdf114 LG |
352 | Index = 0\r |
353 | for IndexJ in range(1, len(UniObjectClass.OrderedStringList[UniObjectClass.LanguageDef[IndexI][0]])):\r | |
79b74a03 LG |
354 | Item = UniObjectClass.OrderedStringListByToken[Language][IndexJ]\r |
355 | \r | |
30fdf114 LG |
356 | Name = Item.StringName\r |
357 | Value = Item.StringValueByteList\r | |
358 | Referenced = Item.Referenced\r | |
359 | Token = Item.Token\r | |
30fdf114 LG |
360 | UseOtherLangDef = Item.UseOtherLangDef\r |
361 | \r | |
362 | if UseOtherLangDef != '' and Referenced:\r | |
b303ea72 | 363 | NumberOfUseOtherLangDef = NumberOfUseOtherLangDef + 1\r |
30fdf114 LG |
364 | Index = Index + 1\r |
365 | else:\r | |
b303ea72 LG |
366 | if NumberOfUseOtherLangDef > 0:\r |
367 | StrStringValue = WriteLine(StrStringValue, CreateArrayItem([StringSkipType] + DecToHexList(NumberOfUseOtherLangDef, 4)))\r | |
368 | CreateBinBuffer (StringBuffer, ([StringSkipType] + DecToHexList(NumberOfUseOtherLangDef, 4)))\r | |
369 | NumberOfUseOtherLangDef = 0\r | |
30fdf114 LG |
370 | ArrayLength = ArrayLength + 3\r |
371 | if Referenced and Item.Token > 0:\r | |
372 | Index = Index + 1\r | |
373 | StrStringValue = WriteLine(StrStringValue, "// %s: %s:%s" % (DecToHexStr(Index, 4), Name, DecToHexStr(Token, 4)))\r | |
374 | StrStringValue = Write(StrStringValue, CreateCFileStringValue(Value))\r | |
b303ea72 | 375 | CreateBinBuffer (StringBuffer, [StringBlockType] + Value)\r |
30fdf114 LG |
376 | ArrayLength = ArrayLength + Item.Length + 1 # 1 is for the length of string type\r |
377 | \r | |
378 | #\r | |
379 | # EFI_HII_PACKAGE_HEADER\r | |
380 | #\r | |
381 | Offset = EFI_HII_STRING_PACKAGE_HDR_LENGTH + len(Language) + 1\r | |
382 | ArrayLength = Offset + ArrayLength + 1\r | |
383 | \r | |
384 | #\r | |
385 | # Create PACKAGE HEADER\r | |
386 | #\r | |
387 | Str = WriteLine(Str, '// PACKAGE HEADER\n')\r | |
388 | TotalLength = TotalLength + ArrayLength\r | |
389 | \r | |
390 | List = DecToHexList(ArrayLength, 6) + \\r | |
391 | [StringPackageType] + \\r | |
392 | DecToHexList(Offset) + \\r | |
393 | DecToHexList(Offset) + \\r | |
394 | DecToHexList(EFI_HII_LANGUAGE_WINDOW, EFI_HII_LANGUAGE_WINDOW_LENGTH * 2) * EFI_HII_LANGUAGE_WINDOW_NUMBER + \\r | |
395 | DecToHexList(EFI_STRING_ID, 4) + \\r | |
396 | AscToHexList(Language) + \\r | |
397 | DecToHexList(0, 2)\r | |
398 | Str = WriteLine(Str, CreateArrayItem(List, 16) + '\n')\r | |
399 | \r | |
400 | #\r | |
401 | # Create PACKAGE DATA\r | |
402 | #\r | |
403 | Str = WriteLine(Str, '// PACKAGE DATA\n')\r | |
404 | Str = Write(Str, StrStringValue)\r | |
405 | \r | |
406 | #\r | |
407 | # Add an EFI_HII_SIBT_END at last\r | |
408 | #\r | |
409 | Str = WriteLine(Str, ' ' + EFI_HII_SIBT_END + ",")\r | |
f7496d71 | 410 | \r |
b303ea72 LG |
411 | #\r |
412 | # Create binary UNI string\r | |
413 | #\r | |
414 | if UniBinBuffer:\r | |
415 | CreateBinBuffer (UniBinBuffer, List)\r | |
416 | UniBinBuffer.write (StringBuffer.getvalue())\r | |
47fea6af | 417 | UniBinBuffer.write (pack("B", int(EFI_HII_SIBT_END, 16)))\r |
b303ea72 | 418 | StringBuffer.close()\r |
30fdf114 LG |
419 | \r |
420 | #\r | |
421 | # Create line for string variable name\r | |
422 | # "unsigned char $(BaseName)Strings[] = {"\r | |
423 | #\r | |
47fea6af | 424 | AllStr = WriteLine('', CHAR_ARRAY_DEFIN + ' ' + BaseName + COMMON_FILE_NAME + '[] = {\n')\r |
30fdf114 | 425 | \r |
30fdf114 | 426 | if IsCompatibleMode:\r |
b303ea72 LG |
427 | #\r |
428 | # Create FRAMEWORK_EFI_HII_PACK_HEADER in compatible mode\r | |
429 | #\r | |
30fdf114 LG |
430 | AllStr = WriteLine(AllStr, '// FRAMEWORK PACKAGE HEADER Length')\r |
431 | AllStr = WriteLine(AllStr, CreateArrayItem(DecToHexList(TotalLength + 2)) + '\n')\r | |
432 | AllStr = WriteLine(AllStr, '// FRAMEWORK PACKAGE HEADER Type')\r | |
433 | AllStr = WriteLine(AllStr, CreateArrayItem(DecToHexList(2, 4)) + '\n')\r | |
b303ea72 LG |
434 | else:\r |
435 | #\r | |
436 | # Create whole array length in UEFI mode\r | |
437 | #\r | |
30fdf114 LG |
438 | AllStr = WriteLine(AllStr, '// STRGATHER_OUTPUT_HEADER')\r |
439 | AllStr = WriteLine(AllStr, CreateArrayItem(DecToHexList(TotalLength)) + '\n')\r | |
440 | \r | |
441 | #\r | |
442 | # Join package data\r | |
443 | #\r | |
444 | AllStr = Write(AllStr, Str)\r | |
445 | \r | |
4e375707 | 446 | return "".join(AllStr)\r |
30fdf114 LG |
447 | \r |
448 | ## Create end of .c file\r | |
449 | #\r | |
450 | # Create end of .c file\r | |
451 | #\r | |
452 | # @retval Str: A string of .h file end\r | |
453 | #\r | |
454 | def CreateCFileEnd():\r | |
455 | Str = Write('', '};')\r | |
456 | return Str\r | |
457 | \r | |
458 | ## Create a .c file\r | |
459 | #\r | |
460 | # Create a complete .c file\r | |
461 | #\r | |
b303ea72 LG |
462 | # @param BaseName: The basename of strings\r |
463 | # @param UniObjectClass A UniObjectClass instance\r | |
464 | # @param IsCompatibleMode Compatible Mode\r | |
f7496d71 | 465 | # @param FilterInfo Platform language filter information\r |
30fdf114 | 466 | #\r |
6780eef1 | 467 | # @retval CFile: A string of complete .c file\r |
30fdf114 | 468 | #\r |
6780eef1 | 469 | def CreateCFile(BaseName, UniObjectClass, IsCompatibleMode, FilterInfo):\r |
30fdf114 | 470 | CFile = ''\r |
6780eef1 | 471 | CFile = WriteLine(CFile, CreateCFileContent(BaseName, UniObjectClass, IsCompatibleMode, None, FilterInfo))\r |
30fdf114 | 472 | CFile = WriteLine(CFile, CreateCFileEnd())\r |
4e375707 | 473 | return "".join(CFile)\r |
30fdf114 LG |
474 | \r |
475 | ## GetFileList\r | |
476 | #\r | |
477 | # Get a list for all files\r | |
478 | #\r | |
479 | # @param IncludeList: A list of all path to be searched\r | |
480 | # @param SkipList: A list of all types of file could be skipped\r | |
481 | #\r | |
482 | # @retval FileList: A list of all files found\r | |
483 | #\r | |
484 | def GetFileList(SourceFileList, IncludeList, SkipList):\r | |
4231a819 | 485 | if IncludeList is None:\r |
30fdf114 LG |
486 | EdkLogger.error("UnicodeStringGather", AUTOGEN_ERROR, "Include path for unicode file is not defined")\r |
487 | \r | |
488 | FileList = []\r | |
4231a819 | 489 | if SkipList is None:\r |
30fdf114 LG |
490 | SkipList = []\r |
491 | \r | |
492 | for File in SourceFileList:\r | |
493 | for Dir in IncludeList:\r | |
494 | if not os.path.exists(Dir):\r | |
495 | continue\r | |
496 | File = os.path.join(Dir, File.Path)\r | |
497 | #\r | |
498 | # Ignore Dir\r | |
499 | #\r | |
500 | if os.path.isfile(File) != True:\r | |
501 | continue\r | |
502 | #\r | |
503 | # Ignore file listed in skip list\r | |
504 | #\r | |
505 | IsSkip = False\r | |
506 | for Skip in SkipList:\r | |
507 | if os.path.splitext(File)[1].upper() == Skip.upper():\r | |
508 | EdkLogger.verbose("Skipped %s for string token uses search" % File)\r | |
509 | IsSkip = True\r | |
510 | break\r | |
511 | \r | |
512 | if not IsSkip:\r | |
513 | FileList.append(File)\r | |
514 | \r | |
515 | break\r | |
516 | \r | |
517 | return FileList\r | |
518 | \r | |
519 | ## SearchString\r | |
520 | #\r | |
521 | # Search whether all string defined in UniObjectClass are referenced\r | |
522 | # All string used should be set to Referenced\r | |
523 | #\r | |
524 | # @param UniObjectClass: Input UniObjectClass\r | |
525 | # @param FileList: Search path list\r | |
b303ea72 | 526 | # @param IsCompatibleMode Compatible Mode\r |
30fdf114 LG |
527 | #\r |
528 | # @retval UniObjectClass: UniObjectClass after searched\r | |
529 | #\r | |
b303ea72 | 530 | def SearchString(UniObjectClass, FileList, IsCompatibleMode):\r |
30fdf114 LG |
531 | if FileList == []:\r |
532 | return UniObjectClass\r | |
533 | \r | |
534 | for File in FileList:\r | |
535 | if os.path.isfile(File):\r | |
536 | Lines = open(File, 'r')\r | |
537 | for Line in Lines:\r | |
afb04ba1 | 538 | for StrName in STRING_TOKEN.findall(Line):\r |
30fdf114 LG |
539 | EdkLogger.debug(EdkLogger.DEBUG_5, "Found string identifier: " + StrName)\r |
540 | UniObjectClass.SetStringReferenced(StrName)\r | |
541 | \r | |
542 | UniObjectClass.ReToken()\r | |
543 | \r | |
544 | return UniObjectClass\r | |
545 | \r | |
546 | ## GetStringFiles\r | |
547 | #\r | |
548 | # This function is used for UEFI2.1 spec\r | |
549 | #\r | |
550 | #\r | |
f7496d71 | 551 | def GetStringFiles(UniFilList, SourceFileList, IncludeList, IncludePathList, SkipList, BaseName, IsCompatibleMode = False, ShellMode = False, UniGenCFlag = True, UniGenBinBuffer = None, FilterInfo = [True, []]):\r |
30fdf114 LG |
552 | if len(UniFilList) > 0:\r |
553 | if ShellMode:\r | |
554 | #\r | |
555 | # support ISO 639-2 codes in .UNI files of EDK Shell\r | |
556 | #\r | |
f8d11e5a | 557 | Uni = UniFileClassObject(sorted(UniFilList, key=lambda x: x.File), True, IncludePathList)\r |
30fdf114 | 558 | else:\r |
f8d11e5a | 559 | Uni = UniFileClassObject(sorted(UniFilList, key=lambda x: x.File), IsCompatibleMode, IncludePathList)\r |
30fdf114 LG |
560 | else:\r |
561 | EdkLogger.error("UnicodeStringGather", AUTOGEN_ERROR, 'No unicode files given')\r | |
562 | \r | |
563 | FileList = GetFileList(SourceFileList, IncludeList, SkipList)\r | |
564 | \r | |
756ad8f8 | 565 | Uni = SearchString(Uni, sorted (FileList), IsCompatibleMode)\r |
30fdf114 | 566 | \r |
b303ea72 LG |
567 | HFile = CreateHFile(BaseName, Uni, IsCompatibleMode, UniGenCFlag)\r |
568 | CFile = None\r | |
569 | if IsCompatibleMode or UniGenCFlag:\r | |
6780eef1 | 570 | CFile = CreateCFile(BaseName, Uni, IsCompatibleMode, FilterInfo)\r |
b303ea72 | 571 | if UniGenBinBuffer:\r |
6780eef1 | 572 | CreateCFileContent(BaseName, Uni, IsCompatibleMode, UniGenBinBuffer, FilterInfo)\r |
30fdf114 LG |
573 | \r |
574 | return HFile, CFile\r | |
575 | \r | |
576 | #\r | |
577 | # Write an item\r | |
578 | #\r | |
579 | def Write(Target, Item):\r | |
4e375707 B |
580 | if isinstance(Target,str):\r |
581 | Target = [Target]\r | |
582 | if not Target:\r | |
583 | Target = []\r | |
584 | if isinstance(Item,list):\r | |
585 | Target.extend(Item)\r | |
586 | else:\r | |
587 | Target.append(Item)\r | |
588 | return Target\r | |
30fdf114 LG |
589 | \r |
590 | #\r | |
591 | # Write an item with a break line\r | |
592 | #\r | |
593 | def WriteLine(Target, Item):\r | |
4e375707 B |
594 | if isinstance(Target,str):\r |
595 | Target = [Target]\r | |
596 | if not Target:\r | |
597 | Target = []\r | |
598 | if isinstance(Item, list):\r | |
599 | Target.extend(Item)\r | |
600 | else:\r | |
601 | Target.append(Item)\r | |
602 | Target.append('\n')\r | |
603 | return Target\r | |
30fdf114 LG |
604 | \r |
605 | # This acts like the main() function for the script, unless it is 'import'ed into another\r | |
606 | # script.\r | |
607 | if __name__ == '__main__':\r | |
608 | EdkLogger.info('start')\r | |
609 | \r | |
610 | UniFileList = [\r | |
611 | r'C:\\Edk\\Strings2.uni',\r | |
612 | r'C:\\Edk\\Strings.uni'\r | |
613 | ]\r | |
614 | \r | |
615 | SrcFileList = []\r | |
616 | for Root, Dirs, Files in os.walk('C:\\Edk'):\r | |
617 | for File in Files:\r | |
618 | SrcFileList.append(File)\r | |
619 | \r | |
620 | IncludeList = [\r | |
621 | r'C:\\Edk'\r | |
622 | ]\r | |
623 | \r | |
624 | SkipList = ['.inf', '.uni']\r | |
625 | BaseName = 'DriverSample'\r | |
626 | (h, c) = GetStringFiles(UniFileList, SrcFileList, IncludeList, SkipList, BaseName, True)\r | |
627 | hfile = open('unistring.h', 'w')\r | |
628 | cfile = open('unistring.c', 'w')\r | |
629 | hfile.write(h)\r | |
630 | cfile.write(c)\r | |
631 | \r | |
632 | EdkLogger.info('end')\r |