]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Sample/Tools/Source/UefiStrGather/StringDB.c
Update the copyright notice format
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / UefiStrGather / StringDB.c
CommitLineData
95d675b5 1/*++\r
2\r
4b1e1121
HT
3Copyright (c) 2004 - 2007, Intel Corporation. All rights reserved.<BR>\r
4This program and the accompanying materials \r
95d675b5 5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 StringDB.c\r
15\r
16Abstract:\r
17\r
18 String database implementation\r
19 \r
20--*/\r
21\r
22#include <stdio.h>\r
23#include <stdlib.h>\r
24#include <string.h>\r
25#include <ctype.h>\r
26#include <Tiano.h>\r
27#include <EfiUtilityMsgs.h>\r
28#include <EfiHii.h>\r
29#include "StrGather.h"\r
30#include "StringDb.h"\r
31\r
32static STRING_DB_DATA mDBData;\r
33\r
34static const char *mSourceFileHeader[] = {\r
35 "//",\r
36 "// DO NOT EDIT -- auto-generated file",\r
37 "//",\r
38 "// This file is generated by the string gather utility",\r
39 "//",\r
40 NULL\r
41};\r
42\r
43static\r
44STRING_LIST *\r
45StringDBFindString (\r
46 WCHAR *LanguageName,\r
47 WCHAR *StringName,\r
48 WCHAR *Scope,\r
49 WCHAR_STRING_LIST *LanguagesOfInterest,\r
50 WCHAR_MATCHING_STRING_LIST *IndirectionList\r
51 );\r
52\r
53static\r
54STRING_IDENTIFIER *\r
55StringDBFindStringIdentifierByName (\r
56 WCHAR *Name\r
57 );\r
58\r
59static\r
60STRING_IDENTIFIER *\r
61StringDBFindStringIdentifierByIndex (\r
62 UINT32 Index\r
63 );\r
64\r
65static\r
66void\r
67StringDBWriteStandardFileHeader (\r
68 FILE *OutFptr\r
69 );\r
70\r
71static\r
72WCHAR *\r
73AsciiToWchar (\r
74 INT8 *Str\r
75 );\r
76\r
77static\r
78CHAR8 *\r
79WcharToAscii (\r
80 WCHAR *Str\r
81 );\r
82\r
83static\r
84WCHAR *\r
85DuplicateString (\r
86 WCHAR *Str\r
87 );\r
88\r
89static\r
90WCHAR *\r
91WstrCatenate (\r
92 WCHAR *Dst,\r
93 WCHAR *Src\r
94 );\r
95\r
96static\r
97STATUS\r
98StringDBWriteStringIdentifier (\r
99 FILE *DBFptr,\r
100 UINT16 StringId,\r
101 UINT16 Flags,\r
102 WCHAR *IdentifierName\r
103 );\r
104\r
105static\r
106STATUS\r
107StringDBReadStringIdentifier (\r
108 FILE *DBFptr\r
109 );\r
110\r
111static\r
112STATUS\r
113StringDBWriteLanguageDefinition (\r
114 FILE *DBFptr,\r
115 WCHAR *LanguageName,\r
116 WCHAR *PrintableLanguageName,\r
117 WCHAR *SecondaryLanguageList\r
118 );\r
119\r
120static\r
121STATUS\r
122StringDBReadLanguageDefinition (\r
123 FILE *DBFptr\r
124 );\r
125\r
126static\r
127STATUS\r
128StringDBWriteString (\r
129 FILE *DBFptr,\r
130 UINT16 Flags,\r
131 WCHAR *Language,\r
132 WCHAR *StringName,\r
133 WCHAR *Scope,\r
134 WCHAR *Str\r
135 );\r
136\r
137static\r
138STATUS\r
139StringDBReadString (\r
140 FILE *DBFptr\r
141 );\r
142\r
143static\r
144STATUS\r
145StringDBReadGenericString (\r
146 FILE *DBFptr,\r
147 UINT16 *Size,\r
148 WCHAR **Str\r
149 );\r
150\r
151static\r
152STATUS\r
153StringDBWriteGenericString (\r
154 FILE *DBFptr,\r
155 WCHAR *Str\r
156 );\r
157\r
158static\r
159void\r
160StringDBAssignStringIndexes (\r
161 VOID\r
162 );\r
163\r
164/*****************************************************************************/\r
165\r
166/*++\r
167\r
168Routine Description:\r
169 Constructor function for the string database handler.\r
170\r
171Arguments:\r
172 None.\r
173\r
174Returns:\r
175 None.\r
176\r
177--*/\r
178void\r
179StringDBConstructor (\r
180 VOID\r
181 )\r
182{\r
183 memset ((char *) &mDBData, 0, sizeof (STRING_DB_DATA));\r
184 mDBData.CurrentScope = DuplicateString (L"NULL");\r
185}\r
186\r
187/*****************************************************************************/\r
188\r
189/*++\r
190\r
191Routine Description:\r
192 Destructor function for the string database handler.\r
193\r
194Arguments:\r
195 None.\r
196\r
197Returns:\r
198 None.\r
199\r
200--*/\r
201void\r
202StringDBDestructor (\r
203 VOID\r
204 )\r
205{\r
206 LANGUAGE_LIST *NextLang;\r
207 STRING_LIST *NextStr;\r
208 STRING_IDENTIFIER *NextIdentifier;\r
209 //\r
210 // Close the database file if it's open\r
211 //\r
212 if (mDBData.StringDBFptr != NULL) {\r
213 fclose (mDBData.StringDBFptr);\r
214 mDBData.StringDBFptr = NULL;\r
215 }\r
216 //\r
217 // If we've allocated any strings/languages, free them up\r
218 //\r
219 while (mDBData.LanguageList != NULL) {\r
220 NextLang = mDBData.LanguageList->Next;\r
221 //\r
222 // Free up all strings for this language\r
223 //\r
224 while (mDBData.LanguageList->String != NULL) {\r
225 NextStr = mDBData.LanguageList->String->Next;\r
226 FREE (mDBData.LanguageList->String->Str);\r
227 FREE (mDBData.LanguageList->String);\r
228 mDBData.LanguageList->String = NextStr;\r
229 }\r
230\r
231 FREE (mDBData.LanguageList->SecondaryLanguageList);\r
232 FREE (mDBData.LanguageList->PrintableLanguageName);\r
233 FREE (mDBData.LanguageList);\r
234 mDBData.LanguageList = NextLang;\r
235 }\r
236 //\r
237 // Free up string identifiers\r
238 //\r
239 while (mDBData.StringIdentifier != NULL) {\r
240 NextIdentifier = mDBData.StringIdentifier->Next;\r
241 FREE (mDBData.StringIdentifier->StringName);\r
242 FREE (mDBData.StringIdentifier);\r
243 mDBData.StringIdentifier = NextIdentifier;\r
244 }\r
245 //\r
246 // Free the filename\r
247 //\r
248 if (mDBData.StringDBFileName != NULL) {\r
249 FREE (mDBData.StringDBFileName);\r
250 mDBData.StringDBFileName = NULL;\r
251 }\r
252 //\r
253 // We save a copy of the scope, so free it up if we\r
254 // have one.\r
255 //\r
256 if (mDBData.CurrentScope != NULL) {\r
257 FREE (mDBData.CurrentScope);\r
258 mDBData.CurrentScope = NULL;\r
259 }\r
260}\r
261\r
262/*****************************************************************************/\r
263STATUS\r
264StringDBDumpStringDefines (\r
265 INT8 *FileName,\r
266 INT8 *BaseName\r
267 )\r
268{\r
269 FILE *Fptr;\r
270 STRING_IDENTIFIER *Identifier;\r
271 INT8 CopyBaseName[100];\r
272 UINT32 Index;\r
273 const INT8 *StrDefHeader[] = {\r
274 "#ifndef _%s_STRINGS_DEFINE_H_\n",\r
275 "#define _%s_STRINGS_DEFINE_H_\n\n",\r
276 NULL\r
277 };\r
278\r
279 if ((Fptr = fopen (FileName, "w")) == NULL) {\r
280 Error (NULL, 0, 0, FileName, "failed to open output string defines file");\r
281 return STATUS_ERROR;\r
282 }\r
283 //\r
284 // Get the base source filename and convert to uppercase.\r
285 //\r
286 if (sizeof (CopyBaseName) <= strlen (BaseName) + 1) {\r
287 Error (NULL, 0, 0, "application error", "StringDBDumpStringDefines() string length insufficient");\r
288 return STATUS_ERROR;\r
289 }\r
290\r
291 strcpy (CopyBaseName, BaseName);\r
292 for (Index = 0; CopyBaseName[Index] != 0; Index++) {\r
293 if (islower (CopyBaseName[Index])) {\r
294 CopyBaseName[Index] = (INT8) toupper (CopyBaseName[Index]);\r
295 }\r
296 }\r
297 //\r
298 // Assign index values to the string identifiers\r
299 //\r
300 StringDBAssignStringIndexes ();\r
301 //\r
302 // Write the standard header to the output file, and then the\r
303 // protective #ifndef.\r
304 //\r
305 StringDBWriteStandardFileHeader (Fptr);\r
306 for (Index = 0; StrDefHeader[Index] != NULL; Index++) {\r
307 fprintf (Fptr, StrDefHeader[Index], CopyBaseName);\r
308 }\r
309 //\r
310 // Print all the #defines for the string identifiers. Print identifiers\r
311 // whose names start with '$' as comments. Add comments for string\r
312 // identifiers not used as well.\r
313 //\r
314 Identifier = mDBData.StringIdentifier;\r
315 while (Identifier != NULL) {\r
316 if (Identifier->StringName[0] == L'$') {\r
317 fprintf (Fptr, "// ");\r
318 }\r
319\r
320 if (Identifier->Flags & STRING_FLAGS_REFERENCED) {\r
321 fprintf (Fptr, "#define %-40S 0x%04X\n", Identifier->StringName, Identifier->Index);\r
322 } else {\r
323 fprintf (Fptr, "//#define %-40S 0x%04X // not referenced\n", Identifier->StringName, Identifier->Index);\r
324 }\r
325\r
326 Identifier = Identifier->Next;\r
327 }\r
328\r
329 fprintf (Fptr, "\n#endif\n");\r
330 fclose (Fptr);\r
331 return STATUS_SUCCESS;\r
332}\r
333\r
334/*****************************************************************************/\r
335\r
336/*++\r
337\r
338Routine Description:\r
339\r
340 Add a string identifier to the database.\r
341\r
342Arguments:\r
343\r
344 StringName - name of the string identifier. For example "STR_MY_STRING"\r
345 NewId - if an ID has been assigned\r
346 Flags - characteristics for the identifier\r
347\r
348Returns:\r
349\r
350 STATUS\r
351\r
352--*/\r
353STATUS\r
354StringDBAddStringIdentifier (\r
355 WCHAR *StringName,\r
356 UINT16 *NewId,\r
357 UINT16 Flags\r
358 )\r
359{\r
360 STRING_IDENTIFIER *StringIdentifier;\r
361 STATUS Status;\r
362 //\r
363 // If it was already used for some other language, then we don't\r
364 // need to add it. But set it to the current string identifier.\r
365 // The referenced bit is sticky.\r
366 //\r
367 Status = STATUS_SUCCESS;\r
368 StringIdentifier = StringDBFindStringIdentifierByName (StringName);\r
369 if (StringIdentifier != NULL) {\r
370 if (Flags & STRING_FLAGS_REFERENCED) {\r
371 StringIdentifier->Flags |= STRING_FLAGS_REFERENCED;\r
372 }\r
373\r
374 mDBData.CurrentStringIdentifier = StringIdentifier;\r
375 *NewId = (UINT16) StringIdentifier->Index;\r
376 return Status;\r
377 }\r
378\r
379 StringIdentifier = (STRING_IDENTIFIER *) MALLOC (sizeof (STRING_IDENTIFIER));\r
380 if (StringIdentifier == NULL) {\r
381 Error (NULL, 0, 0, NULL, "memory allocation error");\r
382 return STATUS_ERROR;\r
383 }\r
384\r
385 memset ((char *) StringIdentifier, 0, sizeof (STRING_IDENTIFIER));\r
386 StringIdentifier->StringName = (WCHAR *) malloc ((wcslen (StringName) + 1) * sizeof (WCHAR));\r
387 if (StringIdentifier->StringName == NULL) {\r
388 Error (NULL, 0, 0, NULL, "memory allocation error");\r
389 return STATUS_ERROR;\r
390 }\r
391\r
392 wcscpy (StringIdentifier->StringName, StringName);\r
393 if (*NewId != STRING_ID_INVALID) {\r
394 StringIdentifier->Index = *NewId;\r
395 StringIdentifier->Flags |= STRING_FLAGS_INDEX_ASSIGNED;\r
396 if (mDBData.NumStringIdentifiers <= StringIdentifier->Index) {\r
397 mDBData.NumStringIdentifiers = StringIdentifier->Index + 1;\r
398 }\r
399 } else {\r
400 StringIdentifier->Index = mDBData.NumStringIdentifiers++;\r
401 }\r
402\r
403 StringIdentifier->Flags |= Flags;\r
404 //\r
405 // Add it to our list of string identifiers\r
406 //\r
407 if (mDBData.StringIdentifier == NULL) {\r
408 mDBData.StringIdentifier = StringIdentifier;\r
409 } else {\r
410 mDBData.LastStringIdentifier->Next = StringIdentifier;\r
411 }\r
412\r
413 mDBData.LastStringIdentifier = StringIdentifier;\r
414 mDBData.CurrentStringIdentifier = StringIdentifier;\r
415 *NewId = (UINT16) StringIdentifier->Index;\r
416 return Status;\r
417}\r
418\r
419/*****************************************************************************/\r
420\r
421/*++\r
422\r
423Routine Description:\r
424\r
425 Add a new string to the database.\r
426\r
427Arguments:\r
428\r
429 LanguageName - "eng" or "spa" language name\r
430 StringName - "STR_MY_TEXT" string name\r
431 Scope - from the #scope statements in the string file\r
432 Format - if we should format the string\r
433 Flags - characteristic flags for the string\r
434\r
435Returns:\r
436\r
437 STATUS\r
438\r
439Notes:\r
440\r
441 Several of the fields can be "inherited" from the previous calls to\r
442 our database functions. For example, if scope is NULL here, then\r
443 we'll use the previous setting.\r
444\r
445--*/\r
446STATUS\r
447StringDBAddString (\r
448 WCHAR *LanguageName,\r
449 WCHAR *StringName,\r
450 WCHAR *Scope,\r
451 WCHAR *String,\r
452 BOOLEAN Format,\r
453 UINT16 Flags\r
454 )\r
455{\r
456 LANGUAGE_LIST *Lang;\r
457 UINT32 Size;\r
458 STRING_LIST *Str;\r
459 UINT16 StringIndex;\r
460 STRING_IDENTIFIER *StringIdentifier;\r
461\r
462 //\r
463 // If they specified a language, make sure they've defined it already\r
464 // via a #langdef statement. Otherwise use the current default language.\r
465 //\r
466 if (LanguageName != NULL) {\r
467 Lang = StringDBFindLanguageList (LanguageName);\r
468 if (Lang == NULL) {\r
469 ParserError (0, "language not defined", "%S", LanguageName);\r
470 return STATUS_ERROR;\r
471 } else {\r
472 StringDBSetCurrentLanguage (LanguageName);\r
473 }\r
474 } else {\r
475 Lang = mDBData.CurrentLanguage;\r
476 if (Lang == NULL) {\r
477 //\r
478 // Have to call SetLanguage() first\r
479 //\r
480 ParserError (0, "no language defined", "%S", StringName);\r
481 return STATUS_ERROR;\r
482 }\r
483 }\r
484 //\r
485 // If they didn't define a string identifier, use the last string identifier\r
486 // added.\r
487 //\r
488 if (StringName == NULL) {\r
489 StringName = mDBData.CurrentStringIdentifier->StringName;\r
490 if (StringName == NULL) {\r
491 ParserError (0, "no string identifier previously specified", NULL);\r
492 return STATUS_ERROR;\r
493 }\r
494 }\r
495 //\r
496 // If scope was not specified, use the default setting\r
497 //\r
498 if (Scope != NULL) {\r
499 Scope = DuplicateString (Scope);\r
500 } else {\r
501 Scope = DuplicateString (mDBData.CurrentScope);\r
502 }\r
503 //\r
504 // printf ("Adding string: %S.%S.%S\n", Lang->LanguageName, StringName, Scope);\r
505 //\r
506 // Check for duplicates for this Language.StringName.Scope. Allow multiple\r
507 // definitions of the language name and printable language name, since the\r
508 // user does not specifically define them.\r
509 //\r
510 if (StringDBFindString (Lang->LanguageName, StringName, Scope, NULL, NULL) != NULL) {\r
511 if ((wcscmp (StringName, LANGUAGE_NAME_STRING_NAME) == 0) &&\r
512 (wcscmp (StringName, PRINTABLE_LANGUAGE_NAME_STRING_NAME) == 0)\r
513 ) {\r
514 ParserError (\r
515 0,\r
516 "string multiply defined",\r
517 "Language.Name.Scope = %S.%S.%S",\r
518 Lang->LanguageName,\r
519 StringName,\r
520 Scope\r
521 );\r
522 return STATUS_ERROR;\r
523 }\r
524 }\r
525\r
526 StringIndex = STRING_ID_INVALID;\r
527 if (StringDBAddStringIdentifier (StringName, &StringIndex, Flags) != STATUS_SUCCESS) {\r
528 return STATUS_ERROR;\r
529 }\r
530\r
531 StringIdentifier = StringDBFindStringIdentifierByName (StringName);\r
532 //\r
533 // Add this string to the end of the strings for this language.\r
534 //\r
535 Str = (STRING_LIST *) malloc (sizeof (STRING_LIST));\r
536 if (Str == NULL) {\r
537 Error (NULL, 0, 0, NULL, "memory allocation error");\r
538 return STATUS_ERROR;\r
539 }\r
540\r
541 memset ((char *) Str, 0, sizeof (STRING_LIST));\r
542 Size = (wcslen (String) + 1) * sizeof (WCHAR);\r
543 Str->Flags = Flags;\r
544 Str->Scope = Scope;\r
545 Str->StringName = StringIdentifier->StringName;\r
546 Str->LanguageName = DuplicateString (LanguageName);\r
547 Str->Str = (WCHAR *) MALLOC (Size);\r
548 if (Str->Str == NULL) {\r
549 Error (NULL, 0, 0, NULL, "memory allocation error");\r
550 return STATUS_ERROR;\r
551 }\r
552 //\r
553 // If not formatting, just copy the string.\r
554 //\r
555 wcscpy (Str->Str, String);\r
556 if (Format) {\r
557 StringDBFormatString (Str->Str);\r
558 }\r
559 //\r
560 // Size may change after formatting. We set the size to\r
561 // the actual size of the string, including the null for\r
562 // easier processing later.\r
563 //\r
564 Str->Size = (wcslen (Str->Str) + 1) * sizeof (WCHAR);\r
565 if (Lang->String == NULL) {\r
566 Lang->String = Str;\r
567 } else {\r
568 Lang->LastString->Next = Str;\r
569 }\r
570\r
571 Lang->LastString = Str;\r
572 return STATUS_SUCCESS;\r
573}\r
574\r
575/*****************************************************************************/\r
576\r
577/*++\r
578\r
579Routine Description:\r
580\r
581 Given a language name, see if a language list for it has been defined\r
582\r
583Arguments:\r
584\r
585 LanguageName - like "eng"\r
586\r
587Returns:\r
588\r
589 A pointer to the language list\r
590\r
591--*/\r
592LANGUAGE_LIST *\r
593StringDBFindLanguageList (\r
594 WCHAR *LanguageName\r
595 )\r
596{\r
597 LANGUAGE_LIST *Lang;\r
598\r
599 Lang = mDBData.LanguageList;\r
600 while (Lang != NULL) {\r
601 if (wcscmp (LanguageName, Lang->LanguageName) == 0) {\r
602 break;\r
603 }\r
604\r
605 Lang = Lang->Next;\r
606 }\r
607\r
608 return Lang;\r
609}\r
610\r
611/*****************************************************************************/\r
612STATUS\r
613StringDBSetCurrentLanguage (\r
614 WCHAR *LanguageName\r
615 )\r
616{\r
617 LANGUAGE_LIST *Lang;\r
618\r
619 Lang = StringDBFindLanguageList (LanguageName);\r
620 if (Lang == NULL) {\r
621 ParserError (0, "language not previously defined", "%S", LanguageName);\r
622 return STATUS_ERROR;\r
623 }\r
624\r
625 mDBData.CurrentLanguage = Lang;\r
626 return STATUS_SUCCESS;\r
627}\r
628\r
629/*****************************************************************************/\r
630STATUS\r
631StringDBAddLanguage (\r
632 WCHAR *LanguageName,\r
633 WCHAR *PrintableLanguageName,\r
634 WCHAR *SecondaryLanguageList\r
635 )\r
636{\r
637 LANGUAGE_LIST *Lang;\r
638 //\r
639 // Check for redefinitions\r
640 //\r
641 Lang = StringDBFindLanguageList (LanguageName);\r
642 if (Lang != NULL) {\r
643 //\r
644 // Better be the same printable name\r
645 //\r
646 if (wcscmp (PrintableLanguageName, Lang->PrintableLanguageName) != 0) {\r
647 ParserError (\r
648 0,\r
649 "language redefinition",\r
650 "%S:%S != %S:%S",\r
651 Lang->LanguageName,\r
652 Lang->PrintableLanguageName,\r
653 LanguageName,\r
654 PrintableLanguageName\r
655 );\r
656 return STATUS_ERROR;\r
657 //\r
658 // } else {\r
659 // ParserWarning (0, "benign language redefinition", "%S", PrintableLanguageName);\r
660 // return STATUS_WARNING;\r
661 //\r
662 }\r
663 } else {\r
664 //\r
665 // Allocate memory to keep track of this new language\r
666 //\r
667 Lang = (LANGUAGE_LIST *) malloc (sizeof (LANGUAGE_LIST));\r
668 if (Lang == NULL) {\r
669 Error (NULL, 0, 0, NULL, "memory allocation error");\r
670 return STATUS_ERROR;\r
671 }\r
672\r
673 memset ((char *) Lang, 0, sizeof (LANGUAGE_LIST));\r
674 //\r
675 // Save the language name, then allocate memory to save the\r
676 // printable language name\r
677 //\r
678 Lang->LanguageName = (WCHAR *) malloc ((wcslen (LanguageName) + 1) * 2);\r
679 if (Lang->LanguageName == NULL) {\r
680 Error (NULL, 0, 0, NULL, "memory allocation error");\r
681 return STATUS_ERROR;\r
682 }\r
683 wcscpy (Lang->LanguageName, LanguageName);\r
684 Lang->PrintableLanguageName = (WCHAR *) malloc ((wcslen (PrintableLanguageName) + 1) * sizeof (WCHAR));\r
685 if (Lang->PrintableLanguageName == NULL) {\r
686 Error (NULL, 0, 0, NULL, "memory allocation error");\r
687 FREE (Lang->LanguageName);\r
688 return STATUS_ERROR;\r
689 }\r
690 wcscpy (Lang->PrintableLanguageName, PrintableLanguageName);\r
691\r
692 if (SecondaryLanguageList != NULL) {\r
693 Lang->SecondaryLanguageList = (WCHAR *) malloc ((wcslen (SecondaryLanguageList) + 1) * sizeof (WCHAR));\r
694 if (Lang->SecondaryLanguageList == NULL) {\r
695 Error (NULL, 0, 0, NULL, "memory allocation error");\r
696 FREE (Lang->PrintableLanguageName);\r
697 FREE (Lang->LanguageName);\r
698 return STATUS_ERROR;\r
699 }\r
700 wcscpy (Lang->SecondaryLanguageList, SecondaryLanguageList);\r
701 } else {\r
702 Lang->SecondaryLanguageList = NULL;\r
703 }\r
704\r
705 if (mDBData.LanguageList == NULL) {\r
706 mDBData.LanguageList = Lang;\r
707 } else {\r
708 mDBData.LastLanguageList->Next = Lang;\r
709 }\r
710\r
711 mDBData.LastLanguageList = Lang;\r
712 }\r
713 //\r
714 // Default is to make our active language this new one\r
715 //\r
716 StringDBSetCurrentLanguage (LanguageName);\r
717 //\r
718 // The first two strings for any language are the language name,\r
719 // followed by the printable language name. Add them and set them\r
720 // to referenced so they never get stripped out.\r
721 //\r
722 StringDBAddString (\r
723 LanguageName,\r
724 LANGUAGE_NAME_STRING_NAME,\r
725 NULL,\r
726 LanguageName,\r
727 FALSE,\r
728 STRING_FLAGS_REFERENCED\r
729 );\r
730 StringDBAddString (\r
731 LanguageName,\r
732 PRINTABLE_LANGUAGE_NAME_STRING_NAME,\r
733 NULL,\r
734 PrintableLanguageName,\r
735 FALSE,\r
736 STRING_FLAGS_REFERENCED\r
737 );\r
738 return STATUS_SUCCESS;\r
739}\r
740\r
741STATUS\r
742StringDBAddSecondaryLanguage (\r
743 WCHAR *LanguageName,\r
744 WCHAR *SecondaryLanguageList\r
745 )\r
746{\r
747 LANGUAGE_LIST *Lang;\r
748\r
749 Lang = StringDBFindLanguageList (LanguageName);\r
750 if (Lang == NULL) {\r
751 return STATUS_ERROR;\r
752 } else {\r
753 Lang->SecondaryLanguageList = WstrCatenate(Lang->SecondaryLanguageList, SecondaryLanguageList);\r
754 return STATUS_SUCCESS;\r
755 }\r
756}\r
757\r
758/*****************************************************************************/\r
759static\r
760STRING_IDENTIFIER *\r
761StringDBFindStringIdentifierByName (\r
762 WCHAR *StringName\r
763 )\r
764{\r
765 STRING_IDENTIFIER *Identifier;\r
766\r
767 Identifier = mDBData.StringIdentifier;\r
768 while (Identifier != NULL) {\r
769 if (wcscmp (StringName, Identifier->StringName) == 0) {\r
770 return Identifier;\r
771 }\r
772\r
773 Identifier = Identifier->Next;\r
774 }\r
775\r
776 return NULL;\r
777}\r
778\r
779static\r
780STRING_IDENTIFIER *\r
781StringDBFindStringIdentifierByIndex (\r
782 UINT32 StringIndex\r
783 )\r
784{\r
785 STRING_IDENTIFIER *Identifier;\r
786\r
787 Identifier = mDBData.StringIdentifier;\r
788 while (Identifier != NULL) {\r
789 if (Identifier->Index == StringIndex) {\r
790 return Identifier;\r
791 }\r
792\r
793 Identifier = Identifier->Next;\r
794 }\r
795\r
796 return NULL;\r
797}\r
798\r
799/*****************************************************************************/\r
800static\r
801void\r
802StringDBWriteStandardFileHeader (\r
803 FILE *OutFptr\r
804 )\r
805{\r
806 UINT32 TempIndex;\r
807 for (TempIndex = 0; mSourceFileHeader[TempIndex] != NULL; TempIndex++) {\r
808 fprintf (OutFptr, "%s\n", mSourceFileHeader[TempIndex]);\r
809 }\r
810}\r
811\r
812/*****************************************************************************/\r
813\r
814/*++\r
815\r
816Routine Description:\r
817 \r
818 Given a Unicode string from an input file, reformat the string to replace\r
819 backslash control sequences with the appropriate encoding.\r
820\r
821Arguments:\r
822\r
823 String - pointer to string to reformat\r
824\r
825Returns:\r
826\r
827 Nothing\r
828\r
829--*/\r
830void\r
831StringDBFormatString (\r
832 WCHAR *String\r
833 )\r
834{\r
835 WCHAR *From;\r
836 WCHAR *To;\r
837 int HexNibbles;\r
838 WCHAR HexValue;\r
839 //\r
840 // Go through the string and process any formatting characters\r
841 //\r
842 From = String;\r
843 To = String;\r
844 while (*From) {\r
845 if (*From == UNICODE_BACKSLASH) {\r
846 //\r
847 // First look for \wide and replace with the appropriate control character. Note that\r
848 // when you have "define STR L"ABC"", then sizeof(ABC) is 8 because the null char is\r
849 // counted. Make adjustments for this. We advance From below, so subtract 2 each time.\r
850 //\r
851 if (wcsncmp (From, UNICODE_WIDE_STRING, sizeof (UNICODE_WIDE_STRING) / sizeof (WCHAR) - 1) == 0) {\r
852 *To = WIDE_CHAR;\r
853 From += sizeof (UNICODE_WIDE_STRING) / sizeof (WCHAR) - 2;\r
854 } else if (wcsncmp (From, UNICODE_NARROW_STRING, sizeof (UNICODE_NARROW_STRING) / sizeof (WCHAR) - 1) == 0) {\r
855 //\r
856 // Found: \narrow\r
857 //\r
858 *To = NARROW_CHAR;\r
859 From += sizeof (UNICODE_NARROW_STRING) / sizeof (WCHAR) - 2;\r
860 } else if (wcsncmp (From, UNICODE_NBR_STRING, sizeof (UNICODE_NBR_STRING) / sizeof (WCHAR) - 1) == 0) {\r
861 //\r
862 // Found: \nbr\r
863 //\r
864 *To = NON_BREAKING_CHAR;\r
865 From += sizeof (UNICODE_NBR_STRING) / sizeof (WCHAR) - 2;\r
866 } else if (wcsncmp (From, UNICODE_BR_STRING, sizeof (UNICODE_BR_STRING) / sizeof (WCHAR) - 1) == 0) {\r
867 //\r
868 // Found: \br -- pass through untouched\r
869 //\r
870 *To = *From;\r
871 } else {\r
872 //\r
873 // Standard one-character control sequences such as \n, \r, \\, or \x\r
874 //\r
875 From++;\r
876 switch (*From) {\r
877 case ASCII_TO_UNICODE ('n'):\r
878 *To = UNICODE_CR;\r
879 To++;\r
880 *To = UNICODE_LF;\r
881 break;\r
882\r
883 //\r
884 // carriage return\r
885 //\r
886 case ASCII_TO_UNICODE ('r'):\r
887 *To = UNICODE_CR;\r
888 break;\r
889\r
890 //\r
891 // backslash\r
892 //\r
893 case UNICODE_BACKSLASH:\r
894 *To = UNICODE_BACKSLASH;\r
895 break;\r
896\r
897 //\r
898 // Tab\r
899 //\r
900 case ASCII_TO_UNICODE ('t'):\r
901 *To = UNICODE_TAB;\r
902 break;\r
903\r
904 //\r
905 // embedded double-quote\r
906 //\r
907 case UNICODE_DOUBLE_QUOTE:\r
908 *To = UNICODE_DOUBLE_QUOTE;\r
909 break;\r
910\r
911 //\r
912 // Hex Unicode character \x1234. We'll process up to 4 hex characters\r
913 //\r
914 case ASCII_TO_UNICODE ('x'):\r
915 HexValue = 0;\r
916 for (HexNibbles = 0; HexNibbles < 4; HexNibbles++) {\r
917 if ((From[1] >= UNICODE_0) && (From[1] <= UNICODE_9)) {\r
918 HexValue = (HexValue << 4) | (From[1] - UNICODE_0);\r
919 } else if ((From[1] >= UNICODE_a) && (From[1] <= UNICODE_f)) {\r
920 HexValue = (HexValue << 4) | (10 + From[1] - UNICODE_a);\r
921 } else if ((From[1] >= UNICODE_A) && (From[1] <= UNICODE_F)) {\r
922 HexValue = (HexValue << 4) | (10 + From[1] - UNICODE_A);\r
923 } else {\r
924 break;\r
925 }\r
926\r
927 From++;\r
928 }\r
929\r
930 if (HexNibbles == 0) {\r
931 ParserWarning (\r
932 0,\r
933 "expected at least one valid hex digit with \\x escaped character in string",\r
934 "\\%C",\r
935 *From\r
936 );\r
937 } else {\r
938 *To = HexValue;\r
939 }\r
940 break;\r
941\r
942 default:\r
943 *To = UNICODE_SPACE;\r
944 ParserWarning (0, "invalid escaped character in string", "\\%C", *From);\r
945 break;\r
946 }\r
947 }\r
948 } else {\r
949 *To = *From;\r
950 }\r
951\r
952 From++;\r
953 To++;\r
954 }\r
955\r
956 *To = 0;\r
957}\r
958\r
959/*****************************************************************************/\r
960STATUS\r
961StringDBReadDatabase (\r
962 INT8 *DBFileName,\r
963 BOOLEAN IgnoreIfNotExist,\r
964 BOOLEAN Verbose\r
965 )\r
966{\r
967 STRING_DB_HEADER DbHeader;\r
968 STATUS Status;\r
969 FILE *DBFptr;\r
970 DB_DATA_ITEM_HEADER DataItemHeader;\r
971\r
972 Status = STATUS_SUCCESS;\r
973 DBFptr = NULL;\r
974 //\r
975 // if (Verbose) {\r
976 // fprintf (stdout, "Reading database file %s\n", DBFileName);\r
977 // }\r
978 //\r
979 // Try to open the input file\r
980 //\r
981 if ((DBFptr = fopen (DBFileName, "rb")) == NULL) {\r
982 if (IgnoreIfNotExist) {\r
983 return STATUS_SUCCESS;\r
984 }\r
985\r
986 Error (NULL, 0, 0, DBFileName, "failed to open input database file for reading");\r
987 return STATUS_ERROR;\r
988 }\r
989 //\r
990 // Read and verify the database header\r
991 //\r
992 if (fread ((void *) &DbHeader, sizeof (STRING_DB_HEADER), 1, DBFptr) != 1) {\r
993 Error (NULL, 0, 0, DBFileName, "failed to read header from database file");\r
994 Status = STATUS_ERROR;\r
995 goto Finish;\r
996 }\r
997\r
998 if (DbHeader.Key != STRING_DB_KEY) {\r
999 Error (NULL, 0, 0, DBFileName, "invalid header in database file");\r
1000 Status = STATUS_ERROR;\r
1001 goto Finish;\r
1002 }\r
1003\r
1004 if ((DbHeader.Version & STRING_DB_MAJOR_VERSION_MASK) != (STRING_DB_VERSION & STRING_DB_MAJOR_VERSION_MASK)) {\r
1005 Error (NULL, 0, 0, DBFileName, "incompatible database file version -- rebuild clean");\r
1006 Status = STATUS_ERROR;\r
1007 goto Finish;\r
1008 }\r
1009 //\r
1010 // Read remaining items\r
1011 //\r
1012 while (fread (&DataItemHeader, sizeof (DataItemHeader), 1, DBFptr) == 1) {\r
1013 switch (DataItemHeader.DataType) {\r
1014 case DB_DATA_TYPE_STRING_IDENTIFIER:\r
1015 StringDBReadStringIdentifier (DBFptr);\r
1016 break;\r
1017\r
1018 case DB_DATA_TYPE_LANGUAGE_DEFINITION:\r
1019 StringDBReadLanguageDefinition (DBFptr);\r
1020 break;\r
1021\r
1022 case DB_DATA_TYPE_STRING_DEFINITION:\r
1023 StringDBReadString (DBFptr);\r
1024 break;\r
1025\r
1026 default:\r
1027 Error (\r
1028 NULL,\r
1029 0,\r
1030 0,\r
1031 "database corrupted",\r
1032 "invalid data item type 0x%X at offset 0x%X",\r
1033 (UINT32) DataItemHeader.DataType,\r
1034 ftell (DBFptr) - sizeof (DataItemHeader)\r
1035 );\r
1036 Status = STATUS_ERROR;\r
1037 goto Finish;\r
1038 }\r
1039 }\r
1040\r
1041Finish:\r
1042 if (DBFptr != NULL) {\r
1043 fclose (DBFptr);\r
1044 }\r
1045\r
1046 return Status;\r
1047}\r
1048\r
1049/*****************************************************************************/\r
1050\r
1051/*++\r
1052\r
1053Routine Description:\r
1054 \r
1055 Write everything we know to the output database file. Write:\r
1056\r
1057 Database header\r
1058 String identifiers[]\r
1059 StringPacks[]\r
1060\r
1061Arguments:\r
1062\r
1063 DBFileName - name of the file to write to\r
1064 Verbose - for debug purposes, print info messages along the way.\r
1065\r
1066Returns:\r
1067\r
1068 STATUS\r
1069\r
1070--*/\r
1071STATUS\r
1072StringDBWriteDatabase (\r
1073 INT8 *DBFileName,\r
1074 BOOLEAN Verbose\r
1075 )\r
1076{\r
1077 STRING_DB_HEADER DbHeader;\r
1078 UINT32 Counter;\r
1079 UINT32 StrLen;\r
1080 LANGUAGE_LIST *Lang;\r
1081 STRING_IDENTIFIER *StringIdentifier;\r
1082 STRING_LIST *StrList;\r
1083 FILE *DBFptr;\r
1084\r
1085 if (Verbose) {\r
1086 fprintf (stdout, "Writing database %s\n", DBFileName);\r
1087 }\r
1088\r
1089 if ((DBFptr = fopen (DBFileName, "wb")) == NULL) {\r
1090 Error (NULL, 0, 0, DBFileName, "failed to open output database file for writing");\r
1091 return STATUS_ERROR;\r
1092 }\r
1093 //\r
1094 // Fill in and write the database header\r
1095 //\r
1096 memset (&DbHeader, 0, sizeof (STRING_DB_HEADER));\r
1097 DbHeader.HeaderSize = sizeof (STRING_DB_HEADER);\r
1098 DbHeader.Key = STRING_DB_KEY;\r
1099 DbHeader.Version = STRING_DB_VERSION;\r
1100 //\r
1101 // Count the number of languages we have\r
1102 //\r
1103 for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) {\r
1104 DbHeader.NumLanguages++;\r
1105 }\r
1106 //\r
1107 // Count up how many string identifiers we have, and total up the\r
1108 // size of the names plus the size of the flags field we will\r
1109 // write out too.\r
1110 //\r
1111 DbHeader.NumStringIdenfiers = mDBData.NumStringIdentifiers;\r
1112 StringIdentifier = mDBData.StringIdentifier;\r
1113 for (Counter = 0; Counter < mDBData.NumStringIdentifiers; Counter++) {\r
1114 StrLen = wcslen (StringIdentifier->StringName) + 1;\r
1115 DbHeader.StringIdentifiersSize += StrLen * sizeof (WCHAR) + sizeof (StringIdentifier->Flags);\r
1116 StringIdentifier = StringIdentifier->Next;\r
1117 }\r
1118\r
1119 //\r
1120 // Write the header\r
1121 //\r
1122 fwrite (&DbHeader, sizeof (STRING_DB_HEADER), 1, DBFptr);\r
1123 if (Verbose) {\r
1124 fprintf (stdout, " Number of string identifiers 0x%04X\n", DbHeader.NumStringIdenfiers);\r
1125 fprintf (stdout, " Number of languages %d\n", DbHeader.NumLanguages);\r
1126 }\r
1127 //\r
1128 // Write the string identifiers\r
1129 //\r
1130 for (StringIdentifier = mDBData.StringIdentifier; StringIdentifier != NULL; StringIdentifier = StringIdentifier->Next) {\r
1131 StringDBWriteStringIdentifier (\r
1132 DBFptr,\r
1133 (UINT16) StringIdentifier->Index,\r
1134 StringIdentifier->Flags,\r
1135 StringIdentifier->StringName\r
1136 );\r
1137 }\r
1138 //\r
1139 // Now write all the strings for each language\r
1140 //\r
1141 for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) {\r
1142 StringDBWriteLanguageDefinition (DBFptr, Lang->LanguageName, Lang->PrintableLanguageName, Lang->SecondaryLanguageList);\r
1143 for (StrList = Lang->String; StrList != NULL; StrList = StrList->Next) {\r
1144 StringDBWriteString (\r
1145 DBFptr,\r
1146 StrList->Flags,\r
1147 Lang->LanguageName,\r
1148 StrList->StringName,\r
1149 StrList->Scope,\r
1150 StrList->Str\r
1151 );\r
1152 }\r
1153 }\r
1154\r
1155 fclose (DBFptr);\r
1156 return STATUS_SUCCESS;\r
1157}\r
1158\r
1159STATUS\r
1160StringDBSetStringReferenced (\r
1161 INT8 *StringIdentifierName,\r
1162 BOOLEAN IgnoreNotFound\r
1163 )\r
1164{\r
1165 STRING_IDENTIFIER *Id;\r
1166 WCHAR *WName;\r
1167 STATUS Status;\r
1168 //\r
1169 // See if it's already been defined.\r
1170 //\r
1171 Status = STATUS_SUCCESS;\r
1172 WName = (WCHAR *) malloc ((strlen (StringIdentifierName) + 1) * sizeof (WCHAR));\r
1173#ifdef USE_VC8\r
1174 swprintf (WName, (strlen (StringIdentifierName) + 1) * sizeof (WCHAR), L"%S", StringIdentifierName);\r
1175#else\r
1176 swprintf (WName, L"%S", StringIdentifierName);\r
1177#endif\r
1178 Id = StringDBFindStringIdentifierByName (WName);\r
1179 if (Id != NULL) {\r
1180 Id->Flags |= STRING_FLAGS_REFERENCED;\r
1181 } else {\r
1182 if (IgnoreNotFound == 0) {\r
1183 ParserWarning (0, StringIdentifierName, "string identifier not found in database");\r
1184 Status = STATUS_WARNING;\r
1185 }\r
1186 }\r
1187\r
1188 free (WName);\r
1189 return Status;\r
1190}\r
1191\r
1192/*****************************************************************************/\r
1193\r
1194/*++\r
1195\r
1196Routine Description:\r
1197\r
1198 Dump the contents of a database to an output unicode file.\r
1199\r
1200Arguments:\r
1201\r
1202 DBFileName - name of the pre-existing database file to read\r
1203 OutputFileName - name of the file to dump the database contents to\r
1204 Verbose - for printing of additional info useful for debugging\r
1205\r
1206Returns:\r
1207\r
1208 STATUS\r
1209\r
1210Notes:\r
1211\r
1212 There's some issue with the unicode printing routines. Therefore to \r
1213 write to the output file properly, open it as binary and use fwrite.\r
1214 Ideally we could open it with just L"w" and use fwprintf().\r
1215\r
1216--*/\r
1217STATUS\r
1218StringDBDumpDatabase (\r
1219 INT8 *DBFileName,\r
1220 INT8 *OutputFileName,\r
1221 BOOLEAN Verbose\r
1222 )\r
1223{\r
1224 LANGUAGE_LIST *Lang;\r
1225 STRING_IDENTIFIER *StringIdentifier;\r
1226 STRING_LIST *StrList;\r
1227 FILE *OutFptr;\r
1228 WCHAR WChar;\r
1229 WCHAR *WOutputFileName;\r
1230 WCHAR CrLf[2];\r
1231 WCHAR Line[200];\r
1232 WCHAR *Scope;\r
1233 //\r
1234 // This function assumes the database has already been read, and\r
1235 // we're just dumping our internal data structures to a unicode file.\r
1236 //\r
1237 if (Verbose) {\r
1238 fprintf (stdout, "Dumping database file %s\n", DBFileName);\r
1239 }\r
1240\r
1241 WOutputFileName = AsciiToWchar (OutputFileName);\r
1242 OutFptr = _wfopen (WOutputFileName, L"wb");\r
1243 free (WOutputFileName);\r
1244 if (OutFptr == NULL) {\r
1245 Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");\r
1246 return STATUS_ERROR;\r
1247 }\r
1248\r
1249 WChar = UNICODE_FILE_START;\r
1250 fwrite (&WChar, sizeof (WCHAR), 1, OutFptr);\r
1251 CrLf[1] = UNICODE_LF;\r
1252 CrLf[0] = UNICODE_CR;\r
1253 //\r
1254 // The default control character is '/'. Make it '#' by writing\r
1255 // "/=#" to the output file.\r
1256 //\r
1257#ifdef USE_VC8\r
1258 swprintf (Line, wcslen(Line) * sizeof (WCHAR), L"/=#");\r
1259#else\r
1260 swprintf (Line, L"/=#");\r
1261#endif\r
1262 fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr);\r
1263 fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);\r
1264 fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);\r
1265 //\r
1266 // Dump all the string identifiers and their values\r
1267 //\r
1268 StringDBAssignStringIndexes ();\r
1269 for (StringIdentifier = mDBData.StringIdentifier; StringIdentifier != NULL; StringIdentifier = StringIdentifier->Next) {\r
1270 //\r
1271 // Write the "#define " string\r
1272 //\r
1273 if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) {\r
1274#ifdef USE_VC8\r
1275 swprintf (\r
1276 Line,\r
1277 wcslen(Line) * sizeof (WCHAR),\r
1278 L"%s %-60.60s 0x%04X",\r
1279 DEFINE_STR,\r
1280 StringIdentifier->StringName,\r
1281 StringIdentifier->Index\r
1282 );\r
1283#else\r
1284 swprintf (\r
1285 Line,\r
1286 L"%s %-60.60s 0x%04X",\r
1287 DEFINE_STR,\r
1288 StringIdentifier->StringName,\r
1289 StringIdentifier->Index\r
1290 );\r
1291#endif\r
1292 } else {\r
1293#ifdef USE_VC8\r
1294 swprintf (\r
1295 Line,\r
1296 wcslen(Line) * sizeof (WCHAR), \r
1297 L"%s %-60.60s 0x%04X // NOT REFERENCED",\r
1298 DEFINE_STR,\r
1299 StringIdentifier->StringName,\r
1300 StringIdentifier->Index\r
1301 );\r
1302#else\r
1303 swprintf (\r
1304 Line,\r
1305 L"%s %-60.60s 0x%04X // NOT REFERENCED",\r
1306 DEFINE_STR,\r
1307 StringIdentifier->StringName,\r
1308 StringIdentifier->Index\r
1309 );\r
1310#endif\r
1311 }\r
1312\r
1313 fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr);\r
1314 fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);\r
1315 }\r
1316\r
1317 fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);\r
1318 //\r
1319 // Now write all the strings for each language.\r
1320 //\r
1321 WChar = UNICODE_DOUBLE_QUOTE;\r
1322 Scope = NULL;\r
1323 for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) {\r
1324 fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);\r
1325#ifdef USE_VC8\r
1326 swprintf (Line, wcslen(Line) * sizeof (WCHAR), L"#langdef %s \"%s\"", Lang->LanguageName, Lang->PrintableLanguageName);\r
1327#else\r
1328 swprintf (Line, L"#langdef %s \"%s\"", Lang->LanguageName, Lang->PrintableLanguageName);\r
1329#endif\r
1330 fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr);\r
1331 fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);\r
1332 fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);\r
1333 //\r
1334 // Now the strings (in double-quotes) for this language. Write\r
1335 // #string STR_NAME #language eng "string"\r
1336 //\r
1337 for (StrList = Lang->String; StrList != NULL; StrList = StrList->Next) {\r
1338 //\r
1339 // Print the internal flags for debug\r
1340 //\r
1341#ifdef USE_VC8\r
1342 swprintf (Line, wcslen(Line) * sizeof (WCHAR), L"// flags=0x%02X", (UINT32) StrList->Flags);\r
1343#else\r
1344 swprintf (Line, L"// flags=0x%02X", (UINT32) StrList->Flags);\r
1345#endif\r
1346 fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr);\r
1347 fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);\r
1348 //\r
1349 // Print the scope if changed\r
1350 //\r
1351 if ((Scope == NULL) || (wcscmp (Scope, StrList->Scope) != 0)) {\r
1352#ifdef USE_VC8\r
1353 swprintf (Line, wcslen(Line) * sizeof (WCHAR), L"#scope %s", StrList->Scope);\r
1354#else\r
1355 swprintf (Line, L"#scope %s", StrList->Scope);\r
1356#endif\r
1357 fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr);\r
1358 fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);\r
1359 Scope = StrList->Scope;\r
1360 }\r
1361\r
1362#ifdef USE_VC8\r
1363 swprintf (\r
1364 Line,\r
1365 wcslen(Line) * sizeof (WCHAR), \r
1366 L"#string %-50.50s #language %s \"",\r
1367 StrList->StringName,\r
1368 Lang->LanguageName\r
1369 );\r
1370#else\r
1371 swprintf (\r
1372 Line,\r
1373 L"#string %-50.50s #language %s \"",\r
1374 StrList->StringName,\r
1375 Lang->LanguageName\r
1376 );\r
1377#endif\r
1378 fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr);\r
1379 fwrite (StrList->Str, StrList->Size - sizeof (WCHAR), 1, OutFptr);\r
1380#ifdef USE_VC8\r
1381 swprintf (Line, wcslen(Line) * sizeof (WCHAR), L"\"");\r
1382#else\r
1383 swprintf (Line, L"\"");\r
1384#endif\r
1385 fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr);\r
1386 fwrite (&CrLf, sizeof (CrLf), 1, OutFptr);\r
1387 }\r
1388 }\r
1389\r
1390 fclose (OutFptr);\r
1391 return STATUS_SUCCESS;\r
1392}\r
1393\r
1394/*****************************************************************************/\r
1395\r
1396/*++\r
1397\r
1398Routine Description:\r
1399\r
1400 Given a primary language, a string identifier number, and a list of\r
1401 languages, find a secondary string.\r
1402\r
1403Arguments:\r
1404\r
1405 LanguageName - primary language, like "spa"\r
1406 StringId - string index value\r
1407 LanguageList - linked list of "eng", "spa+cat",...\r
1408\r
1409Returns:\r
1410\r
1411 Pointer to a secondary string if found. NULL otherwise.\r
1412\r
1413Notes:\r
1414 \r
1415 Given: LanguageName "spa" and LanguageList "spa+cat", match the\r
1416 "spa" and extract the "cat" and see if there is a string defined\r
1417 for "cat".StringId.\r
1418\r
1419--*/\r
1420static\r
1421STATUS\r
1422StringDBWriteStringIdentifier (\r
1423 FILE *DBFptr,\r
1424 UINT16 StringId,\r
1425 UINT16 Flags,\r
1426 WCHAR *IdentifierName\r
1427 )\r
1428{\r
1429 DB_DATA_ITEM_HEADER Hdr;\r
1430 memset (&Hdr, 0, sizeof (DB_DATA_ITEM_HEADER));\r
1431 Hdr.DataType = DB_DATA_TYPE_STRING_IDENTIFIER;\r
1432 if (fwrite (&Hdr, sizeof (DB_DATA_ITEM_HEADER), 1, DBFptr) != 1) {\r
1433 Error (NULL, 0, 0, "failed to write string to output database file", NULL);\r
1434 return STATUS_ERROR;\r
1435 }\r
1436\r
1437 if (fwrite (&StringId, sizeof (StringId), 1, DBFptr) != 1) {\r
1438 Error (NULL, 0, 0, "failed to write StringId to output database", NULL);\r
1439 return STATUS_ERROR;\r
1440 }\r
1441\r
1442 if (fwrite (&Flags, sizeof (Flags), 1, DBFptr) != 1) {\r
1443 Error (NULL, 0, 0, "failed to write StringId flags to output database", NULL);\r
1444 return STATUS_ERROR;\r
1445 }\r
1446\r
1447 if (StringDBWriteGenericString (DBFptr, IdentifierName) != STATUS_SUCCESS) {\r
1448 return STATUS_ERROR;\r
1449 }\r
1450\r
1451 return STATUS_SUCCESS;\r
1452}\r
1453\r
1454static\r
1455STATUS\r
1456StringDBReadStringIdentifier (\r
1457 FILE *DBFptr\r
1458 )\r
1459{\r
1460 WCHAR *IdentifierName;\r
1461 UINT16 Flags;\r
1462 UINT16 StringId;\r
1463 UINT16 Size;\r
1464\r
1465 if (fread (&StringId, sizeof (StringId), 1, DBFptr) != 1) {\r
1466 Error (NULL, 0, 0, "failed to read StringId from database", NULL);\r
1467 return STATUS_ERROR;\r
1468 }\r
1469\r
1470 if (fread (&Flags, sizeof (Flags), 1, DBFptr) != 1) {\r
1471 Error (NULL, 0, 0, "failed to read StringId flags from database", NULL);\r
1472 return STATUS_ERROR;\r
1473 }\r
1474\r
1475 if (StringDBReadGenericString (DBFptr, &Size, &IdentifierName) != STATUS_SUCCESS) {\r
1476 return STATUS_ERROR;\r
1477 }\r
1478\r
1479 StringDBAddStringIdentifier (IdentifierName, &StringId, Flags);\r
1480 //\r
1481 // printf ("STRID: 0x%04X %S\n", (UINT32)StringId, IdentifierName);\r
1482 //\r
1483 FREE (IdentifierName);\r
1484 return STATUS_SUCCESS;\r
1485}\r
1486\r
1487static\r
1488STATUS\r
1489StringDBWriteString (\r
1490 FILE *DBFptr,\r
1491 UINT16 Flags,\r
1492 WCHAR *Language,\r
1493 WCHAR *StringName,\r
1494 WCHAR *Scope,\r
1495 WCHAR *Str\r
1496 )\r
1497{\r
1498 DB_DATA_ITEM_HEADER Hdr;\r
1499 memset (&Hdr, 0, sizeof (DB_DATA_ITEM_HEADER));\r
1500 Hdr.DataType = DB_DATA_TYPE_STRING_DEFINITION;\r
1501 if (fwrite (&Hdr, sizeof (DB_DATA_ITEM_HEADER), 1, DBFptr) != 1) {\r
1502 Error (NULL, 0, 0, "failed to write string header to output database file", NULL);\r
1503 return STATUS_ERROR;\r
1504 }\r
1505\r
1506 if (fwrite (&Flags, sizeof (Flags), 1, DBFptr) != 1) {\r
1507 Error (NULL, 0, 0, "failed to write string flags to output database", NULL);\r
1508 return STATUS_ERROR;\r
1509 }\r
1510\r
1511 if (StringDBWriteGenericString (DBFptr, Language) != STATUS_SUCCESS) {\r
1512 return STATUS_ERROR;\r
1513 }\r
1514\r
1515 if (StringDBWriteGenericString (DBFptr, StringName) != STATUS_SUCCESS) {\r
1516 return STATUS_ERROR;\r
1517 }\r
1518\r
1519 if (StringDBWriteGenericString (DBFptr, Scope) != STATUS_SUCCESS) {\r
1520 return STATUS_ERROR;\r
1521 }\r
1522\r
1523 if (StringDBWriteGenericString (DBFptr, Str) != STATUS_SUCCESS) {\r
1524 return STATUS_ERROR;\r
1525 }\r
1526 //\r
1527 // printf ("DBWriteString: %S.%S.%S\n", Language, StringName, Scope);\r
1528 //\r
1529 return STATUS_SUCCESS;\r
1530}\r
1531\r
1532static\r
1533STATUS\r
1534StringDBReadString (\r
1535 FILE *DBFptr\r
1536 )\r
1537{\r
1538 UINT16 Flags;\r
1539 UINT16 Size;\r
1540 WCHAR *Language;\r
1541 WCHAR *StringName;\r
1542 WCHAR *Scope;\r
1543 WCHAR *Str;\r
1544\r
1545 if (fread (&Flags, sizeof (Flags), 1, DBFptr) != 1) {\r
1546 Error (NULL, 0, 0, "failed to read string flags from database", NULL);\r
1547 return STATUS_ERROR;\r
1548 }\r
1549\r
1550 if (StringDBReadGenericString (DBFptr, &Size, &Language) != STATUS_SUCCESS) {\r
1551 return STATUS_ERROR;\r
1552 }\r
1553\r
1554 if (StringDBReadGenericString (DBFptr, &Size, &StringName) != STATUS_SUCCESS) {\r
1555 return STATUS_ERROR;\r
1556 }\r
1557\r
1558 if (StringDBReadGenericString (DBFptr, &Size, &Scope) != STATUS_SUCCESS) {\r
1559 return STATUS_ERROR;\r
1560 }\r
1561\r
1562 if (StringDBReadGenericString (DBFptr, &Size, &Str) != STATUS_SUCCESS) {\r
1563 return STATUS_ERROR;\r
1564 }\r
1565 //\r
1566 // If the first or second string (language name and printable language name),\r
1567 // then skip them. They're added via language definitions data items in\r
1568 // the database.\r
1569 //\r
1570 if (StringName[0] != L'$') {\r
1571 StringDBAddString (Language, StringName, Scope, Str, FALSE, Flags);\r
1572 }\r
1573 //\r
1574 // printf ("DBReadString: %S.%S.%S\n", Language, StringName, Scope);\r
1575 //\r
1576 FREE (Language);\r
1577 FREE (StringName);\r
1578 if (Str != NULL) {\r
1579 FREE (Str);\r
1580 }\r
1581\r
1582 if (Scope != NULL) {\r
1583 FREE (Scope);\r
1584 }\r
1585\r
1586 return STATUS_SUCCESS;\r
1587}\r
1588\r
1589static\r
1590STATUS\r
1591StringDBWriteLanguageDefinition (\r
1592 FILE *DBFptr,\r
1593 WCHAR *LanguageName,\r
1594 WCHAR *PrintableLanguageName,\r
1595 WCHAR *SecondaryLanguageList\r
1596 )\r
1597{\r
1598 DB_DATA_ITEM_HEADER Hdr;\r
1599 memset (&Hdr, 0, sizeof (DB_DATA_ITEM_HEADER));\r
1600 Hdr.DataType = DB_DATA_TYPE_LANGUAGE_DEFINITION;\r
1601 if (fwrite (&Hdr, sizeof (DB_DATA_ITEM_HEADER), 1, DBFptr) != 1) {\r
1602 Error (NULL, 0, 0, "failed to write string to output database file", NULL);\r
1603 return STATUS_ERROR;\r
1604 }\r
1605\r
1606 if (StringDBWriteGenericString (DBFptr, LanguageName) != STATUS_SUCCESS) {\r
1607 return STATUS_ERROR;\r
1608 }\r
1609\r
1610 if (StringDBWriteGenericString (DBFptr, PrintableLanguageName) != STATUS_SUCCESS) {\r
1611 return STATUS_ERROR;\r
1612 }\r
1613\r
1614 if (StringDBWriteGenericString (DBFptr, SecondaryLanguageList) != STATUS_SUCCESS) {\r
1615 return STATUS_ERROR;\r
1616 }\r
1617\r
1618 return STATUS_SUCCESS;\r
1619}\r
1620\r
1621static\r
1622STATUS\r
1623StringDBReadLanguageDefinition (\r
1624 FILE *DBFptr\r
1625 )\r
1626{\r
1627 WCHAR *LanguageName = NULL;\r
1628 WCHAR *PrintableLanguageName = NULL;\r
1629 WCHAR *SecondaryLanguageList = NULL;\r
1630 UINT16 Size;\r
1631 STATUS Status;\r
1632\r
1633 if (StringDBReadGenericString (DBFptr, &Size, &LanguageName) != STATUS_SUCCESS) {\r
1634 return STATUS_ERROR;\r
1635 }\r
1636\r
1637 if (StringDBReadGenericString (DBFptr, &Size, &PrintableLanguageName) != STATUS_SUCCESS) {\r
1638 return STATUS_ERROR;\r
1639 }\r
1640\r
1641 if (StringDBReadGenericString (DBFptr, &Size, &SecondaryLanguageList) != STATUS_SUCCESS) {\r
1642 return STATUS_ERROR;\r
1643 }\r
1644\r
1645 //\r
1646 // printf("LANG: %S %S\n", LanguageName, PrintableLanguageName);\r
1647 //\r
1648 Status = StringDBAddLanguage (LanguageName, PrintableLanguageName, SecondaryLanguageList);\r
1649 FREE (LanguageName);\r
1650 FREE (PrintableLanguageName);\r
1651 FREE (SecondaryLanguageList);\r
1652 return Status;\r
1653}\r
1654//\r
1655// All unicode strings in the database consist of a UINT16 length\r
1656// field, followed by the string itself. This routine reads one\r
1657// of those and returns the info.\r
1658//\r
1659static\r
1660STATUS\r
1661StringDBReadGenericString (\r
1662 FILE *DBFptr,\r
1663 UINT16 *Size,\r
1664 WCHAR **Str\r
1665 )\r
1666{\r
1667 UINT16 LSize;\r
1668 UINT16 Flags;\r
1669 WCHAR *LStr;\r
1670\r
1671 if (fread (&LSize, sizeof (UINT16), 1, DBFptr) != 1) {\r
1672 Error (NULL, 0, 0, "failed to read a string length field from the database", NULL);\r
1673 return STATUS_ERROR;\r
1674 }\r
1675\r
1676 if (fread (&Flags, sizeof (UINT16), 1, DBFptr) != 1) {\r
1677 Error (NULL, 0, 0, "failed to read a string flags field from the database", NULL);\r
1678 return STATUS_ERROR;\r
1679 }\r
1680\r
1681 LStr = MALLOC (LSize);\r
1682 if (LStr == NULL) {\r
1683 Error (__FILE__, __LINE__, 0, "memory allocation failed reading the database", NULL);\r
1684 return STATUS_ERROR;\r
1685 }\r
1686\r
1687 if (fread (LStr, sizeof (WCHAR), (UINT32) LSize / sizeof (WCHAR), DBFptr) != (UINT32) LSize / sizeof (WCHAR)) {\r
1688 Error (NULL, 0, 0, "failed to read string from database", NULL);\r
1689 Error (NULL, 0, 0, "database read failure", "offset 0x%X", ftell (DBFptr));\r
1690 free (LStr);\r
1691 return STATUS_ERROR;\r
1692 }\r
1693 //\r
1694 // printf ("DBR: %S\n", LStr);\r
1695 //\r
1696 // If the flags field indicated we were asked to write a NULL string, then\r
1697 // return them a NULL pointer.\r
1698 //\r
1699 if (Flags & STRING_FLAGS_UNDEFINED) {\r
1700 *Size = 0;\r
1701 *Str = NULL;\r
1702 } else {\r
1703 *Size = LSize;\r
1704 *Str = LStr;\r
1705 }\r
1706\r
1707 return STATUS_SUCCESS;\r
1708}\r
1709\r
1710static\r
1711STATUS\r
1712StringDBWriteGenericString (\r
1713 FILE *DBFptr,\r
1714 WCHAR *Str\r
1715 )\r
1716{\r
1717 UINT16 Size;\r
1718 UINT16 Flags;\r
1719 WCHAR ZeroString[1];\r
1720 //\r
1721 // Strings in the database consist of a size UINT16 followed\r
1722 // by the string itself.\r
1723 //\r
1724 if (Str == NULL) {\r
1725 ZeroString[0] = 0;\r
1726 Str = ZeroString;\r
1727 Size = sizeof (ZeroString);\r
1728 Flags = STRING_FLAGS_UNDEFINED;\r
1729 } else {\r
1730 Flags = 0;\r
1731 Size = (UINT16) ((wcslen (Str) + 1) * sizeof (WCHAR));\r
1732 }\r
1733\r
1734 if (fwrite (&Size, sizeof (UINT16), 1, DBFptr) != 1) {\r
1735 Error (NULL, 0, 0, "failed to write string size to database", NULL);\r
1736 return STATUS_ERROR;\r
1737 }\r
1738\r
1739 if (fwrite (&Flags, sizeof (UINT16), 1, DBFptr) != 1) {\r
1740 Error (NULL, 0, 0, "failed to write string flags to database", NULL);\r
1741 return STATUS_ERROR;\r
1742 }\r
1743\r
1744 if (fwrite (Str, sizeof (WCHAR), Size / sizeof (WCHAR), DBFptr) != Size / sizeof (WCHAR)) {\r
1745 Error (NULL, 0, 0, "failed to write string to database", NULL);\r
1746 return STATUS_ERROR;\r
1747 }\r
1748\r
1749 return STATUS_SUCCESS;\r
1750}\r
1751\r
1752static\r
1753STRING_LIST *\r
1754StringDBFindString (\r
1755 WCHAR *LanguageName,\r
1756 WCHAR *StringName,\r
1757 WCHAR *Scope,\r
1758 WCHAR_STRING_LIST *LanguagesOfInterest,\r
1759 WCHAR_MATCHING_STRING_LIST *IndirectionList\r
1760 )\r
1761{\r
1762 LANGUAGE_LIST *Lang;\r
1763 STRING_LIST *CurrString;\r
1764 WCHAR_MATCHING_STRING_LIST *IndListPtr;\r
1765 WCHAR TempLangName[LANGUAGE_IDENTIFIER_NAME_LEN + 1];\r
1766 WCHAR *WCharPtr;\r
1767\r
1768 //\r
1769 // If we were given an indirection list, then see if one was specified for this\r
1770 // string identifier. That is to say, if the indirection says "STR_ID_MY_FAVORITE MyScope",\r
1771 // then if this string name matches one in the list, then do a lookup with the\r
1772 // specified scope and return that value.\r
1773 //\r
1774 if (IndirectionList != NULL) {\r
1775 for (IndListPtr = IndirectionList; IndListPtr != NULL; IndListPtr = IndListPtr->Next) {\r
1776 if (wcscmp (StringName, IndListPtr->Str1) == 0) {\r
1777 CurrString = StringDBFindString (LanguageName, StringName, IndListPtr->Str2, LanguagesOfInterest, NULL);\r
1778 if (CurrString != NULL) {\r
1779 return CurrString;\r
1780 }\r
1781 }\r
1782 }\r
1783 }\r
1784 //\r
1785 // First look for exact match language.stringname\r
1786 //\r
1787 for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) {\r
1788 if (wcscmp (LanguageName, Lang->LanguageName) == 0) {\r
1789 //\r
1790 // Found language match. Try to find string name match\r
1791 //\r
1792 for (CurrString = Lang->String; CurrString != NULL; CurrString = CurrString->Next) {\r
1793 if (wcscmp (StringName, CurrString->StringName) == 0) {\r
1794 //\r
1795 // Found a string name match. See if we're supposed to find\r
1796 // a scope match.\r
1797 //\r
1798 if (Scope != NULL) {\r
1799 if (wcscmp (CurrString->Scope, Scope) == 0) {\r
1800 return CurrString;\r
1801 }\r
1802 } else {\r
1803 return CurrString;\r
1804 }\r
1805 }\r
1806 }\r
1807 }\r
1808 }\r
1809 //\r
1810 // If we got here, then we didn't find a match. Look for secondary string\r
1811 // matches. That is to say, if we're processing "spa", and they requested\r
1812 // "spa+cat", then recursively call with "cat"\r
1813 //\r
1814 while (LanguagesOfInterest != NULL) {\r
1815 //\r
1816 // If this is the language we're looking for, then process the\r
1817 // languages of interest list for it.\r
1818 //\r
1819 if (wcsncmp (LanguageName, LanguagesOfInterest->Str, LANGUAGE_IDENTIFIER_NAME_LEN) == 0) {\r
1820 WCharPtr = LanguagesOfInterest->Str + LANGUAGE_IDENTIFIER_NAME_LEN;\r
1821 while (*WCharPtr) {\r
1822 //\r
1823 // Double-check the length, though it should have been checked on the\r
1824 // command line.\r
1825 //\r
1826 if (wcslen (WCharPtr) < LANGUAGE_IDENTIFIER_NAME_LEN) {\r
1827 Error (NULL, 0, 0, "malformed alternate language list", "%S", LanguagesOfInterest->Str);\r
1828 return NULL;\r
1829 }\r
1830\r
1831 wcsncpy (TempLangName, WCharPtr, LANGUAGE_IDENTIFIER_NAME_LEN);\r
1832 TempLangName[LANGUAGE_IDENTIFIER_NAME_LEN] = 0;\r
1833 CurrString = StringDBFindString (TempLangName, StringName, NULL, NULL, IndirectionList);\r
1834 if (CurrString != NULL) {\r
1835 return CurrString;\r
1836 }\r
1837\r
1838 WCharPtr += LANGUAGE_IDENTIFIER_NAME_LEN;\r
1839 }\r
1840 }\r
1841\r
1842 LanguagesOfInterest = LanguagesOfInterest->Next;\r
1843 }\r
1844\r
1845 return NULL;\r
1846}\r
1847\r
1848STATUS\r
1849StringDBSetScope (\r
1850 WCHAR *Scope\r
1851 )\r
1852{\r
1853 //\r
1854 // Free up existing scope memory.\r
1855 //\r
1856 if (mDBData.CurrentScope != NULL) {\r
1857 FREE (mDBData.CurrentScope);\r
1858 }\r
1859\r
1860 mDBData.CurrentScope = DuplicateString (Scope);\r
1861 return STATUS_SUCCESS;\r
1862}\r
1863//\r
1864// We typically don't assign index values to string identifiers\r
1865// until we're ready to write out files. To reduce the size of\r
1866// the output file, re-order the string identifiers to move any\r
1867// unreferenced ones to the end. Then we'll walk the list\r
1868// again to assign string indexes, keeping track of the last\r
1869// one referenced.\r
1870//\r
1871static\r
1872void\r
1873StringDBAssignStringIndexes (\r
1874 VOID\r
1875 )\r
1876{\r
1877 STRING_IDENTIFIER *StrId;\r
1878 STRING_IDENTIFIER *FirstUsed;\r
1879 STRING_IDENTIFIER *LastUsed;\r
1880 STRING_IDENTIFIER *FirstUnused;\r
1881 STRING_IDENTIFIER *LastUnused;\r
1882 UINT32 Index;\r
1883 UINT32 MaxReferenced;\r
1884\r
1885 //\r
1886 // Create two lists -- used and unused. Then put them together with\r
1887 // the unused ones on the end.\r
1888 //\r
1889 FirstUsed = NULL;\r
1890 LastUsed = NULL;\r
1891 FirstUnused = NULL;\r
1892 LastUnused = NULL;\r
1893 StrId = mDBData.StringIdentifier;\r
1894 while (StrId != NULL) {\r
1895 if ((StrId->Flags & STRING_FLAGS_REFERENCED) == 0) {\r
1896 //\r
1897 // Put it on the unused list\r
1898 //\r
1899 if (FirstUnused == NULL) {\r
1900 FirstUnused = StrId;\r
1901 } else {\r
1902 LastUnused->Next = StrId;\r
1903 }\r
1904\r
1905 LastUnused = StrId;\r
1906 StrId = StrId->Next;\r
1907 LastUnused->Next = NULL;\r
1908 } else {\r
1909 //\r
1910 // Put it on the used list\r
1911 //\r
1912 if (FirstUsed == NULL) {\r
1913 FirstUsed = StrId;\r
1914 } else {\r
1915 LastUsed->Next = StrId;\r
1916 }\r
1917\r
1918 LastUsed = StrId;\r
1919 StrId = StrId->Next;\r
1920 LastUsed->Next = NULL;\r
1921 }\r
1922 }\r
1923 //\r
1924 // Join the lists\r
1925 //\r
1926 if (FirstUsed != NULL) {\r
1927 mDBData.StringIdentifier = FirstUsed;\r
1928 LastUsed->Next = FirstUnused;\r
1929 } else {\r
1930 mDBData.StringIdentifier = FirstUnused;\r
1931 }\r
1932\r
1933 MaxReferenced = 0;\r
1934 Index = 0;\r
1935 for (StrId = mDBData.StringIdentifier; StrId != NULL; StrId = StrId->Next) {\r
1936 StrId->Index = Index;\r
1937 Index++;\r
1938 if (StrId->Flags & STRING_FLAGS_REFERENCED) {\r
1939 mDBData.NumStringIdentifiersReferenced = Index;\r
1940 }\r
1941 }\r
1942\r
1943 mDBData.NumStringIdentifiers = Index;\r
1944}\r
1945\r
1946static\r
1947WCHAR *\r
1948DuplicateString (\r
1949 WCHAR *Str\r
1950 )\r
1951{\r
1952 WCHAR *NewStr;\r
1953 if (Str == NULL) {\r
1954 return NULL;\r
1955 }\r
1956\r
1957 NewStr = MALLOC ((wcslen (Str) + 1) * sizeof (WCHAR));\r
1958 if (NewStr == NULL) {\r
1959 Error (NULL, 0, 0, "memory allocation failure", NULL);\r
1960 return NULL;\r
1961 }\r
1962\r
1963 wcscpy (NewStr, Str);\r
1964 return NewStr;\r
1965}\r
1966\r
1967static\r
1968WCHAR *\r
1969WstrCatenate (\r
1970 WCHAR *Dst,\r
1971 WCHAR *Src\r
1972 )\r
1973{\r
1974 UINT32 Len = 0;\r
1975 WCHAR *Bak = Dst;\r
1976\r
1977 if (Src == NULL) {\r
1978 return Dst;\r
1979 }\r
1980\r
1981 if (Dst != NULL) {\r
1982 Len = wcslen (Dst);\r
1983 }\r
1984 Len += wcslen (Src);\r
1985 Dst = (WCHAR *) malloc ((Len + 1) * 2);\r
1986 if (Dst == NULL) {\r
1987 return NULL;\r
1988 }\r
1989\r
1990 Dst[0] = L'\0';\r
1991 if (Bak != NULL) {\r
1992 wcscpy (Dst, Bak);\r
1993 FREE (Bak);\r
1994 }\r
1995 wcscat (Dst, Src);\r
1996 return Dst;\r
1997}\r
1998\r
1999static\r
2000WCHAR *\r
2001AsciiToWchar (\r
2002 INT8 *Str\r
2003 )\r
2004{\r
2005 UINT32 Len;\r
2006 WCHAR *NewStr;\r
2007 WCHAR *Ptr;\r
2008\r
2009 Len = strlen (Str) + 1;\r
2010 NewStr = (WCHAR *) malloc (Len * sizeof (WCHAR));\r
2011 for (Ptr = NewStr; *Str != 0; Str++, Ptr++) {\r
2012 *Ptr = (UINT16) (UINT8) *Str;\r
2013 }\r
2014\r
2015 *Ptr = 0;\r
2016 return NewStr;\r
2017}\r
2018\r
2019static\r
2020CHAR8 *\r
2021WcharToAscii (\r
2022 WCHAR *Str\r
2023 )\r
2024{\r
2025 UINT32 Len;\r
2026 CHAR8 *NewStr;\r
2027 CHAR8 *Ptr;\r
2028\r
2029 Len = wcslen (Str) + 1;\r
2030 NewStr = (CHAR8 *) malloc (Len * sizeof (CHAR8));\r
2031 for (Ptr = NewStr; *Str != L'\0'; Str++, Ptr++) {\r
2032 *Ptr = (CHAR8) *Str;\r
2033 }\r
2034\r
2035 *Ptr = '\0';\r
2036 return NewStr;\r
2037}\r
2038\r
2039/*****************************************************************************/\r
2040CHAR8 *\r
2041unicode2ascii (\r
2042 WCHAR *UnicodeStr\r
2043 )\r
2044{\r
2045 CHAR8 *RetStr = (CHAR8 *)UnicodeStr;\r
2046 CHAR8 *AsciiStr = (CHAR8 *)UnicodeStr;\r
2047\r
2048 while (*UnicodeStr != '\0') {\r
2049 *AsciiStr = (CHAR8) *(UnicodeStr++);\r
2050 AsciiStr++;\r
2051 }\r
2052 *AsciiStr = '\0';\r
2053\r
2054 return RetStr;\r
2055}\r
2056\r
2057STATUS\r
2058BuildStringPkgHdr (\r
2059 IN WCHAR *PrimaryLangName,\r
2060 IN WCHAR *SecondaryLangList,\r
2061 IN UINT32 Type,\r
2062 IN UINT32 PkgBlkSize,\r
2063 OUT EFI_HII_STRING_PACKAGE_HDR **StrPkgHdr\r
2064 )\r
2065{\r
2066 UINT32 LangNameLen;\r
2067\r
2068 LangNameLen = wcslen (PrimaryLangName);\r
2069 if (SecondaryLangList != NULL) {\r
2070 LangNameLen += wcslen (SecondaryLangList) + 1;\r
2071 }\r
2072\r
2073 *StrPkgHdr = (EFI_HII_STRING_PACKAGE_HDR *) malloc(sizeof (EFI_HII_STRING_PACKAGE_HDR) + LangNameLen);\r
2074 if (*StrPkgHdr == NULL) {\r
2075 return STATUS_ERROR;\r
2076 }\r
2077 memset (*StrPkgHdr, 0, sizeof (EFI_HII_STRING_PACKAGE_HDR) + LangNameLen);\r
2078\r
2079 (*StrPkgHdr)->Header.Type = Type;\r
2080 (*StrPkgHdr)->Header.Length = PkgBlkSize + sizeof (EFI_HII_STRING_PACKAGE_HDR) + LangNameLen;\r
2081 (*StrPkgHdr)->HdrSize = sizeof (EFI_HII_STRING_PACKAGE_HDR) + LangNameLen;\r
2082 (*StrPkgHdr)->StringInfoOffset = sizeof (EFI_HII_STRING_PACKAGE_HDR) + LangNameLen;\r
2083 (*StrPkgHdr)->LanguageWindow[0] = L'\0';\r
2084 (*StrPkgHdr)->LanguageName = (EFI_STRING_ID)1;\r
2085\r
2086 strcpy ((*StrPkgHdr)->Language, unicode2ascii(PrimaryLangName));\r
2087 if (SecondaryLangList != NULL) {\r
2088 strcat ((*StrPkgHdr)->Language, ";");\r
2089 strcat ((*StrPkgHdr)->Language, unicode2ascii(SecondaryLangList));\r
2090 }\r
2091\r
2092#ifdef DEBUG_STRGATHER\r
2093 printf ("STR HDR\t %s\n", (*StrPkgHdr)->Language);\r
2094#endif\r
2095 return STATUS_SUCCESS;\r
2096}\r
2097\r
2098STATUS\r
2099BuildStringPkgUCS2Blk (\r
2100 IN EFI_STRING_ID StringId,\r
2101 IN WCHAR *LangName,\r
2102 IN WCHAR *StrName,\r
2103 OUT EFI_HII_SIBT_STRING_UCS2_BLOCK **StrBlk,\r
2104 OUT UINT32 *BlkSize\r
2105 )\r
2106{\r
2107 UINT32 StrLen = 0;\r
2108 STRING_LIST *CurrString = NULL;\r
2109\r
2110 if ((LangName == NULL) || (StrName == NULL) || (StrBlk == NULL)) {\r
2111 return STATUS_ERROR;\r
2112 }\r
2113\r
2114 *StrBlk = NULL;\r
2115 *BlkSize = 0;\r
2116\r
2117 CurrString = StringDBFindString (LangName, StrName, NULL, NULL, NULL);\r
2118 if (CurrString == NULL) {\r
2119 return STATUS_WARNING;\r
2120 }\r
2121\r
2122 StrLen = wcslen (CurrString->Str);\r
2123 *BlkSize = sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) + StrLen * 2;\r
2124 *StrBlk = (EFI_HII_SIBT_STRING_UCS2_BLOCK *) malloc (*BlkSize);\r
2125 if (*StrBlk == NULL) {\r
2126 *StrBlk = NULL;\r
2127 *BlkSize = 0;\r
2128 return STATUS_ERROR;\r
2129 }\r
2130 (*StrBlk)->Header.BlockType = EFI_HII_SIBT_STRING_UCS2;\r
2131 wcscpy((*StrBlk)->StringText, CurrString->Str);\r
2132\r
2133 return STATUS_SUCCESS;\r
2134}\r
2135\r
2136STATUS\r
2137BuildStringPkgSKIP2Blk (\r
2138 IN EFI_STRING_ID SkipIdCount,\r
2139 OUT EFI_HII_SIBT_SKIP2_BLOCK **StrBlk\r
2140 )\r
2141{\r
2142 if (StrBlk == NULL) {\r
2143 return STATUS_ERROR;\r
2144 }\r
2145\r
2146 *StrBlk = NULL;\r
2147\r
2148 *StrBlk = (EFI_HII_SIBT_SKIP2_BLOCK *) malloc (sizeof (EFI_HII_SIBT_SKIP2_BLOCK));\r
2149 if (*StrBlk == NULL) {\r
2150 *StrBlk = NULL;\r
2151 return STATUS_ERROR;\r
2152 }\r
2153 (*StrBlk)->Header.BlockType = EFI_HII_SIBT_SKIP2;\r
2154 (*StrBlk)->SkipCount = SkipIdCount;\r
2155\r
2156 return STATUS_SUCCESS;\r
2157}\r
2158\r
2159STATUS\r
2160BuildStringPkgEndBlk (\r
2161 OUT EFI_HII_SIBT_END_BLOCK **End\r
2162 )\r
2163{\r
2164 *End = (EFI_HII_SIBT_END_BLOCK *) malloc (sizeof (EFI_HII_SIBT_END_BLOCK));\r
2165 if (*End == NULL) {\r
2166 return STATUS_ERROR;\r
2167 }\r
2168\r
2169 (*End)->Header.BlockType = EFI_HII_SIBT_END;\r
2170 return STATUS_SUCCESS;\r
2171}\r
2172\r
2173/*++\r
2174\r
2175Routine Description:\r
2176\r
2177 Create an HII export string pack for the strings in our database.\r
2178\r
2179Arguments:\r
2180\r
2181 FileName - name of the output file to write \r
2182\r
2183Returns:\r
2184\r
2185 STATUS\r
2186\r
2187\r
2188--*/\r
2189STATUS\r
2190StrPkgBlkBufferListAddTail (\r
2191 IN EFI_STRING_ID StringId,\r
2192 IN WCHAR *StrName,\r
2193 IN SPkgBlkBuffer **PkgBufferListHead,\r
2194 IN SPkgBlkBuffer **PkgBufferListTail,\r
2195 IN VOID *Buffer,\r
2196 IN UINT32 Size \r
2197 )\r
2198{\r
2199 SPkgBlkBuffer *pNew = NULL;\r
2200#ifdef DEBUG_STRGATHER\r
2201 EFI_HII_STRING_BLOCK *SBlk = (EFI_HII_STRING_BLOCK *)Buffer;\r
2202#endif\r
2203\r
2204 if ((PkgBufferListHead == NULL) || (PkgBufferListTail == NULL)) {\r
2205 return STATUS_ERROR;\r
2206 }\r
2207\r
2208 pNew = (SPkgBlkBuffer *) malloc (sizeof (SPkgBlkBuffer));\r
2209 if (pNew == NULL) {\r
2210 return STATUS_ERROR;\r
2211 }\r
2212\r
2213 pNew->mBlkBuffer = Buffer;\r
2214 pNew->mBlkSize = Size;\r
2215 if ((*PkgBufferListTail) == NULL) {\r
2216 (*PkgBufferListHead) = (*PkgBufferListTail) = pNew;\r
2217 } else {\r
2218 (*PkgBufferListTail)->mNext = pNew;\r
2219 (*PkgBufferListTail) = pNew;\r
2220 pNew->mNext = NULL;\r
2221 }\r
2222\r
2223#ifdef DEBUG_STRGATHER\r
2224 switch (SBlk->BlockType) {\r
2225 case EFI_HII_SIBT_STRING_UCS2 :\r
2226 printf ("\tID: [%x] TYPE: [UCS2]\t NAME: %S \t STR: %S\n", StringId, StrName, ((EFI_HII_SIBT_STRING_UCS2_BLOCK *)SBlk)->StringText);\r
2227 break;\r
2228 case EFI_HII_SIBT_SKIP2 :\r
2229 printf ("\tID: [NULL] TYPE: [SKIP2] SKIPCOUNT: [%x]\n", ((EFI_HII_SIBT_SKIP2_BLOCK *)SBlk)->SkipCount);\r
2230 break;\r
2231 case EFI_HII_SIBT_END :\r
2232 printf ("\tID: [%x] TYPE: [END]\n", StringId);\r
2233 break;\r
2234 default :\r
2235 printf ("!!!!UNKNOWN STRING TYPE!!!\n");\r
2236 }\r
2237#endif\r
2238\r
2239 return STATUS_SUCCESS;\r
2240}\r
2241\r
2242VOID\r
2243StrPkgHdrFree (\r
2244 IN EFI_HII_STRING_PACKAGE_HDR *StrPkgHdr\r
2245 )\r
2246{\r
2247 if (StrPkgHdr != NULL) {\r
2248 free (StrPkgHdr);\r
2249 }\r
2250}\r
2251\r
2252VOID\r
2253StrPkgBlkBufferListFree (\r
2254 IN SPkgBlkBuffer *PkgBlkList\r
2255 )\r
2256{\r
2257 SPkgBlkBuffer *Buffer;\r
2258\r
2259 while (PkgBlkList != NULL) {\r
2260 Buffer = PkgBlkList;\r
2261 PkgBlkList = PkgBlkList->mNext;\r
2262\r
2263 if (Buffer->mBlkBuffer != NULL) {\r
2264 free (Buffer->mBlkBuffer);\r
2265 }\r
2266 free (Buffer);\r
2267 }\r
2268}\r
2269\r
2270VOID\r
2271WriteBlockLine (\r
2272 IN FILE *pFile,\r
2273 IN UINT32 LineBytes,\r
2274 IN INT8 *LineHeader,\r
2275 IN INT8 *BlkBuf,\r
2276 IN UINT32 BlkSize\r
2277 )\r
2278{\r
2279 UINT32 Index;\r
2280\r
2281 if ((pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) {\r
2282 return;\r
2283 }\r
2284\r
2285 for (Index = 0; Index < BlkSize; Index++) {\r
2286 if ((Index % LineBytes) == 0) {\r
2287 fprintf (pFile, "\n%s", LineHeader);\r
2288 }\r
2289 fprintf (pFile, "0x%02X, ", (UINT8)BlkBuf[Index]);\r
2290 }\r
2291}\r
2292\r
2293VOID\r
2294WriteBlockEnd (\r
2295 IN FILE *pFile,\r
2296 IN UINT32 LineBytes,\r
2297 IN INT8 *LineHeader,\r
2298 IN INT8 *BlkBuf,\r
2299 IN UINT32 BlkSize\r
2300 )\r
2301{\r
2302 UINT32 Index;\r
2303\r
2304 if ((BlkSize == 0) || (pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) {\r
2305 return;\r
2306 }\r
2307\r
2308 for (Index = 0; Index < BlkSize - 1; Index++) {\r
2309 if ((Index % LineBytes) == 0) {\r
2310 fprintf (pFile, "\n%s", LineHeader);\r
2311 }\r
2312 fprintf (pFile, "0x%02X, ", (UINT8)BlkBuf[Index]);\r
2313 }\r
2314\r
2315 if ((Index % LineBytes) == 0) {\r
2316 fprintf (pFile, "\n%s", LineHeader);\r
2317 }\r
2318 fprintf (pFile, "0x%02X\n", (UINT8)BlkBuf[Index]);\r
2319}\r
2320\r
2321#define BYTES_PRE_LINE 0x10\r
2322\r
2323VOID\r
2324StrPkgWriteHdrCFile (\r
2325 IN FILE *File,\r
2326 IN EFI_HII_STRING_PACKAGE_HDR *StrPkgHdr\r
2327 )\r
2328{\r
2329 if (StrPkgHdr != NULL) {\r
2330 fprintf (File, "\n // PACKAGE HEADER\n");\r
2331 WriteBlockLine(File, BYTES_PRE_LINE, " ", (INT8 *)StrPkgHdr, StrPkgHdr->HdrSize);\r
2332 }\r
2333}\r
2334\r
2335VOID\r
2336StrPkgWirteArrayLength (\r
2337 IN FILE *File,\r
2338 IN UINT32 PkgNumber,\r
2339 IN EFI_HII_STRING_PACKAGE_HDR **PkgHdr\r
2340 )\r
2341{\r
2342 UINT32 Index;\r
2343 UINT32 ArrayLen;\r
2344\r
2345 ArrayLen = sizeof (UINT32);\r
2346 for (Index = 0; Index < PkgNumber; Index++) {\r
2347 if (PkgHdr[Index] != NULL) {\r
2348 ArrayLen += PkgHdr[Index]->Header.Length;\r
2349 }\r
2350 }\r
2351\r
2352 fprintf (File, "\n // STRING ARRAY LENGTH\n");\r
2353 WriteBlockLine(File, BYTES_PRE_LINE, " ", (UINT8 *)&ArrayLen, sizeof (UINT32));\r
2354}\r
2355\r
2356VOID\r
2357StrPkgWriteBlkListCFile (\r
2358 IN FILE *File,\r
2359 IN SPkgBlkBuffer *BlkList,\r
2360 IN BOOLEAN WriteEnd\r
2361 )\r
2362{\r
2363 SPkgBlkBuffer *Buffer;\r
2364\r
2365 fprintf (File, "\n\n // PACKAGE DATA\n");\r
2366\r
2367 while (BlkList != NULL) {\r
2368 Buffer = BlkList;\r
2369 BlkList = BlkList->mNext;\r
2370\r
2371 if ((Buffer->mNext == NULL) && (WriteEnd == TRUE)) {\r
2372 if (Buffer->mBlkBuffer != NULL) {\r
2373 WriteBlockEnd (File, BYTES_PRE_LINE, " ", Buffer->mBlkBuffer, Buffer->mBlkSize);\r
2374 }\r
2375 } else {\r
2376 if (Buffer->mBlkBuffer != NULL) {\r
2377 WriteBlockLine(File, BYTES_PRE_LINE, " ", Buffer->mBlkBuffer, Buffer->mBlkSize);\r
2378 }\r
2379 }\r
2380 }\r
2381}\r
2382\r
2383VOID\r
2384StrPkgWriteHdrBinary (\r
2385 IN FILE *File,\r
2386 IN EFI_HII_STRING_PACKAGE_HDR *StrPkgHdr\r
2387 )\r
2388{\r
2389 fwrite (StrPkgHdr, StrPkgHdr->HdrSize, 1, File);\r
2390}\r
2391\r
2392VOID\r
2393StrPkgWriteBlkListBinary (\r
2394 IN FILE *File,\r
2395 IN SPkgBlkBuffer *BlkList\r
2396 )\r
2397{\r
2398 SPkgBlkBuffer *Buffer;\r
2399\r
2400 while (BlkList != NULL) {\r
2401 Buffer = BlkList;\r
2402 BlkList = BlkList->mNext;\r
2403\r
2404 if (Buffer->mBlkBuffer != NULL) {\r
2405 fwrite (Buffer->mBlkBuffer, Buffer->mBlkSize, 1, File);\r
2406 }\r
2407 }\r
2408}\r
2409\r
2410STATUS\r
2411StringDBGenStrPkgHdrAndBlkList (\r
2412 IN LANGUAGE_LIST *Lang,\r
2413 OUT EFI_HII_STRING_PACKAGE_HDR **StrPkgHdr,\r
2414 OUT SPkgBlkBuffer **BlkList\r
2415 )\r
2416{\r
2417 STATUS Status;\r
2418 UINT32 StringIndex;\r
2419 EFI_STRING_ID StringIdCurrent;\r
2420 EFI_STRING_ID SkipIdCount;\r
2421 UINT32 BlkSize = 0;\r
2422 EFI_HII_SIBT_STRING_UCS2_BLOCK *StrUCS2Blk = NULL;\r
2423 EFI_HII_SIBT_SKIP2_BLOCK *StrSKIP2Blk = NULL;\r
2424 STRING_IDENTIFIER *StringIdentifier = NULL;\r
2425 EFI_HII_SIBT_END_BLOCK *EndBlk = NULL;\r
2426 UINT32 PkgBlkSize = 0;\r
2427 SPkgBlkBuffer *PkgBufferListHead = NULL;\r
2428 SPkgBlkBuffer *PkgBufferListTail = NULL;\r
2429\r
2430 if ((Lang == NULL) || (StrPkgHdr == NULL) || (BlkList == NULL)) {\r
2431 return STATUS_ERROR;\r
2432 }\r
2433\r
2434 //\r
2435 // Assign index values to the string identifiers\r
2436 //\r
2437 StringDBAssignStringIndexes ();\r
2438 StringIdCurrent = EFI_STRING_ID_BEGIN;\r
2439 SkipIdCount = 0;\r
2440\r
2441 for (StringIndex = STRING_ID_PRINTABLE_LANGUAGE_NAME; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) {\r
2442 if ((StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex)) == NULL) {\r
2443 Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex);\r
2444 goto ExportPackOut;\r
2445 }\r
2446\r
2447 if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) {\r
2448 Status = BuildStringPkgUCS2Blk (StringIdCurrent, Lang->LanguageName, StringIdentifier->StringName, &StrUCS2Blk, &BlkSize);\r
2449 switch (Status) {\r
2450 case STATUS_ERROR: \r
2451 goto ExportPackOut; \r
2452 break;\r
2453 case STATUS_WARNING :\r
2454 SkipIdCount++;\r
2455 break;\r
2456 case STATUS_SUCCESS :\r
2457 if (SkipIdCount == 0) {\r
2458 if (StrPkgBlkBufferListAddTail (\r
2459 StringIdCurrent, \r
2460 StringIdentifier->StringName, \r
2461 &PkgBufferListHead, \r
2462 &PkgBufferListTail, \r
2463 StrUCS2Blk, \r
2464 BlkSize\r
2465 ) != STATUS_SUCCESS) {\r
2466 goto ExportPackOut;\r
2467 }\r
2468 PkgBlkSize += BlkSize;\r
2469 } else {\r
2470 if (BuildStringPkgSKIP2Blk (SkipIdCount, &StrSKIP2Blk) != STATUS_SUCCESS) {\r
2471 goto ExportPackOut;\r
2472 } else {\r
2473 if (StrPkgBlkBufferListAddTail (\r
2474 StringIdCurrent, \r
2475 NULL, \r
2476 &PkgBufferListHead, \r
2477 &PkgBufferListTail, \r
2478 StrSKIP2Blk, \r
2479 sizeof (EFI_HII_SIBT_SKIP2_BLOCK)\r
2480 ) != STATUS_SUCCESS) {\r
2481 goto ExportPackOut;\r
2482 }\r
2483 PkgBlkSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);\r
2484 SkipIdCount = 0;\r
2485 }\r
2486\r
2487 if (StrPkgBlkBufferListAddTail (\r
2488 StringIdCurrent, \r
2489 StringIdentifier->StringName, \r
2490 &PkgBufferListHead, \r
2491 &PkgBufferListTail, \r
2492 StrUCS2Blk, \r
2493 BlkSize\r
2494 ) != STATUS_SUCCESS) {\r
2495 goto ExportPackOut;\r
2496 }\r
2497 PkgBlkSize += BlkSize;\r
2498 }\r
2499 }\r
2500 }\r
2501\r
2502 StringIdCurrent++;\r
2503 }\r
2504\r
2505 if (SkipIdCount != 0) {\r
2506 if (BuildStringPkgSKIP2Blk (SkipIdCount, &StrSKIP2Blk) != STATUS_SUCCESS) {\r
2507 goto ExportPackOut;\r
2508 } else {\r
2509 if (StrPkgBlkBufferListAddTail (\r
2510 StringIdCurrent, \r
2511 NULL, \r
2512 &PkgBufferListHead, \r
2513 &PkgBufferListTail, \r
2514 StrSKIP2Blk, \r
2515 sizeof (EFI_HII_SIBT_SKIP2_BLOCK)\r
2516 ) != STATUS_SUCCESS) {\r
2517 goto ExportPackOut;\r
2518 }\r
2519 PkgBlkSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);\r
2520 SkipIdCount = 0;\r
2521 }\r
2522 }\r
2523\r
2524 if (BuildStringPkgEndBlk (&EndBlk) != STATUS_SUCCESS) {\r
2525 goto ExportPackOut;\r
2526 } else if (StrPkgBlkBufferListAddTail (\r
2527 StringIdCurrent, \r
2528 NULL, \r
2529 &PkgBufferListHead, \r
2530 &PkgBufferListTail, \r
2531 EndBlk, \r
2532 sizeof (EFI_HII_SIBT_END_BLOCK)\r
2533 ) != STATUS_SUCCESS) {\r
2534 goto ExportPackOut;\r
2535 }\r
2536 StringIdCurrent++;\r
2537 PkgBlkSize += sizeof (EFI_HII_SIBT_END_BLOCK);\r
2538\r
2539 if (BuildStringPkgHdr(\r
2540 Lang->LanguageName, \r
2541 Lang->SecondaryLanguageList,\r
2542 EFI_HII_PACKAGE_STRINGS, \r
2543 PkgBlkSize, \r
2544 StrPkgHdr\r
2545 ) != STATUS_SUCCESS) {\r
2546 goto ExportPackOut;\r
2547 }\r
2548\r
2549 *BlkList = PkgBufferListHead;\r
2550\r
2551 return STATUS_SUCCESS;\r
2552\r
2553ExportPackOut:\r
2554 StrPkgBlkBufferListFree(PkgBufferListHead);\r
2555 *BlkList = NULL;\r
2556 *StrPkgHdr = NULL;\r
2557 return STATUS_ERROR;\r
2558}\r
2559\r
2560STATUS\r
2561StringDBCreateHiiExportPack (\r
2562 INT8 *FileName\r
2563 )\r
2564{\r
2565 FILE *File = NULL;\r
2566 LANGUAGE_LIST *Lang = NULL;\r
2567 EFI_HII_STRING_PACKAGE_HDR *StrPkgHdr = NULL;\r
2568 SPkgBlkBuffer *BlkList = NULL;\r
2569\r
2570 if (FileName == NULL) {\r
2571 return STATUS_ERROR;\r
2572 }\r
2573\r
2574 if ((File = fopen (FileName, "wb")) == NULL) {\r
2575 Error (NULL, 0, 0, FileName, "failed to open output HII export file");\r
2576 return STATUS_ERROR;\r
2577 }\r
2578\r
2579 for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) {\r
2580 if (StringDBGenStrPkgHdrAndBlkList(Lang, &StrPkgHdr, &BlkList) != STATUS_SUCCESS) {\r
2581 fclose (File);\r
2582 return STATUS_SUCCESS;\r
2583 }\r
2584\r
2585 StrPkgWriteHdrBinary (File, StrPkgHdr);\r
2586 StrPkgWriteBlkListBinary (File, BlkList);\r
2587\r
2588 StrPkgHdrFree (StrPkgHdr);\r
2589 StrPkgBlkBufferListFree (BlkList);\r
2590 }\r
2591\r
2592 fclose (File);\r
2593 return STATUS_SUCCESS;\r
2594}\r
2595\r
2596static const char *gSourceFileHeader[] = {\r
2597 "//",\r
2598 "// DO NOT EDIT -- auto-generated file",\r
2599 "//",\r
2600 "// This file is generated by the StrGather utility",\r
2601 "//",\r
2602 NULL\r
2603};\r
2604\r
2605STATUS\r
2606StringDBDumpCStrings (\r
2607 INT8 *BaseName,\r
2608 INT8 *FileName\r
2609 )\r
2610{\r
2611 EFI_STATUS Status;\r
2612 FILE *File = NULL;\r
2613 LANGUAGE_LIST *Lang = NULL;\r
2614 EFI_HII_STRING_PACKAGE_HDR **StrPkgHdr = NULL;\r
2615 SPkgBlkBuffer **BlkList = NULL;\r
2616 UINT32 Index;\r
2617 UINT32 LangNumber = 0;\r
2618\r
2619 if ((BaseName == NULL) || (FileName == NULL)) {\r
2620 return STATUS_ERROR;\r
2621 }\r
2622\r
2623 if (mDBData.LanguageList == NULL) {\r
2624 return STATUS_SUCCESS;\r
2625 }\r
2626\r
2627 for (LangNumber = 0, Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next, LangNumber++)\r
2628 ;\r
2629\r
2630 StrPkgHdr = (EFI_HII_STRING_PACKAGE_HDR **) malloc (sizeof (EFI_HII_STRING_PACKAGE_HDR *) * LangNumber);\r
2631 BlkList = (SPkgBlkBuffer **) malloc (sizeof (SPkgBlkBuffer *) * LangNumber);\r
2632 for (Index = 0; Index < LangNumber; Index++) {\r
2633 StrPkgHdr[Index] = NULL;\r
2634 BlkList[Index] = NULL;\r
2635 }\r
2636\r
2637 for (Index = 0, Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next, Index++) {\r
2638 Status = StringDBGenStrPkgHdrAndBlkList(Lang, &StrPkgHdr[Index], &BlkList[Index]);\r
2639 if (EFI_ERROR(Status)) {\r
2640 return Status;\r
2641 }\r
2642 }\r
2643\r
2644 if ((File = fopen (FileName, "w")) == NULL) {\r
2645 Error (NULL, 0, 0, FileName, "failed to open output C file - %s", FileName);\r
2646 return STATUS_ERROR;\r
2647 }\r
2648\r
2649 for (Index = 0; gSourceFileHeader[Index] != NULL; Index++) {\r
2650 fprintf (File, "%s\n", gSourceFileHeader[Index]);\r
2651 }\r
2652\r
2653 fprintf (File, "\nunsigned char %s[] = {\n", BaseName);\r
2654\r
2655 //\r
2656 // Save the length of the string package array.\r
2657 //\r
2658 StrPkgWirteArrayLength (File, LangNumber, StrPkgHdr);\r
2659\r
2660 for (Index = 0, Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next, Index++) {\r
2661 if (StrPkgHdr[Index] != NULL) {\r
2662 StrPkgWriteHdrCFile (File, StrPkgHdr[Index]);\r
2663 StrPkgWriteBlkListCFile (File, BlkList[Index], (Lang->Next == NULL) ? TRUE : FALSE);\r
2664 }\r
2665\r
2666 StrPkgHdrFree (StrPkgHdr[Index]);\r
2667 StrPkgBlkBufferListFree (BlkList[Index]);\r
2668 }\r
2669\r
2670 fprintf (File, "\n};\n");\r
2671\r
2672 fclose (File);\r
2673 return STATUS_SUCCESS;\r
2674}\r