X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=Tools%2FCCode%2FSource%2FStrGather%2FStringDB.c;fp=Tools%2FCCode%2FSource%2FStrGather%2FStringDB.c;h=0000000000000000000000000000000000000000;hp=16ef0526d756c7ee9b3a3c435ff6f6e8addc391c;hb=808def96aa4589fba9c2d0ea55837754a3b7a4f7;hpb=9216450d1143056a50a5f916984a2d7faf590488 diff --git a/Tools/CCode/Source/StrGather/StringDB.c b/Tools/CCode/Source/StrGather/StringDB.c deleted file mode 100644 index 16ef0526d7..0000000000 --- a/Tools/CCode/Source/StrGather/StringDB.c +++ /dev/null @@ -1,2759 +0,0 @@ -/*++ - -Copyright (c) 2004, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -Module Name: - - StringDB.c - -Abstract: - - String database implementation - ---*/ - -#include -#include -#include -#include // for tolower() - -#include -#include -#include -#include // for EFI_UGA_PIXEL definition -#include - -#include "EfiUtilityMsgs.h" -#include "StrGather.h" -#include "StringDB.h" - - -#define STRING_OFFSET RELOFST - -#define STRING_DB_KEY (('S' << 24) | ('D' << 16) | ('B' << 8) | 'K') -// -// Version supported by this tool -// -#define STRING_DB_VERSION 0x00010000 - -#define STRING_DB_MAJOR_VERSION_MASK 0xFFFF0000 -#define STRING_DB_MINOR_VERSION_MASK 0x0000FFFF - -#define DEFINE_STR L"// #define" - -#define LANGUAGE_CODE_WIDTH 4 -// -// This is the header that gets written to the top of the -// output binary database file. -// -typedef struct { - UINT32 Key; - UINT32 HeaderSize; - UINT32 Version; - UINT32 NumStringIdenfiers; - UINT32 StringIdentifiersSize; - UINT32 NumLanguages; -} STRING_DB_HEADER; - -// -// When we write out data to the database, we have a UINT16 identifier, which -// indicates what follows, followed by the data. Here's the structure. -// -typedef struct { - UINT16 DataType; - UINT16 Reserved; -} DB_DATA_ITEM_HEADER; - -#define DB_DATA_TYPE_INVALID 0x0000 -#define DB_DATA_TYPE_STRING_IDENTIFIER 0x0001 -#define DB_DATA_TYPE_LANGUAGE_DEFINITION 0x0002 -#define DB_DATA_TYPE_STRING_DEFINITION 0x0003 -#define DB_DATA_TYPE_LAST DB_DATA_TYPE_STRING_DEFINITION - -// -// We have to keep track of a list of languages, each of which has its own -// list of strings. Define a structure to keep track of all languages and -// their list of strings. -// -typedef struct _STRING_LIST { - struct _STRING_LIST *Next; - UINT32 Size; // number of bytes in string, including null terminator - WCHAR *LanguageName; - WCHAR *StringName; // for example STR_ID_TEXT1 - WCHAR *Scope; // - WCHAR *Str; // the actual string - UINT16 Flags; // properties of this string (used, undefined) -} STRING_LIST; - -typedef struct _LANGUAGE_LIST { - struct _LANGUAGE_LIST *Next; - WCHAR LanguageName[4]; - WCHAR *PrintableLanguageName; - STRING_LIST *String; - STRING_LIST *LastString; -} LANGUAGE_LIST; - -// -// We also keep track of all the string identifier names, which we assign unique -// values to. Create a structure to keep track of them all. -// -typedef struct _STRING_IDENTIFIER { - struct _STRING_IDENTIFIER *Next; - UINT32 Index; // only need 16 bits, but makes it easier with UINT32 - WCHAR *StringName; - UINT16 Flags; // if someone referenced it via STRING_TOKEN() -} STRING_IDENTIFIER; -// -// Keep our globals in this structure to be as modular as possible. -// -typedef struct { - FILE *StringDBFptr; - LANGUAGE_LIST *LanguageList; - LANGUAGE_LIST *LastLanguageList; - LANGUAGE_LIST *CurrentLanguage; // keep track of the last language they used - STRING_IDENTIFIER *StringIdentifier; - STRING_IDENTIFIER *LastStringIdentifier; - UINT8 *StringDBFileName; - UINT32 NumStringIdentifiers; - UINT32 NumStringIdentifiersReferenced; - STRING_IDENTIFIER *CurrentStringIdentifier; // keep track of the last string identifier they added - WCHAR *CurrentScope; -} STRING_DB_DATA; - -static STRING_DB_DATA mDBData; - -static const char *mSourceFileHeader[] = { - "//", - "// DO NOT EDIT -- auto-generated file", - "//", - "// This file is generated by the string gather utility", - "//", - NULL -}; - -static -STRING_LIST * -StringDBFindString ( - WCHAR *LanguageName, - WCHAR *StringName, - WCHAR *Scope, - WCHAR_STRING_LIST *LanguagesOfInterest, - WCHAR_MATCHING_STRING_LIST *IndirectionList - ); - -static -STRING_IDENTIFIER * -StringDBFindStringIdentifierByName ( - WCHAR *Name - ); - -static -STRING_IDENTIFIER * -StringDBFindStringIdentifierByIndex ( - UINT32 Index - ); - -static -LANGUAGE_LIST * -StringDBFindLanguageList ( - WCHAR *LanguageName - ); - -static -void -StringDBWriteStandardFileHeader ( - FILE *OutFptr - ); - -static -WCHAR * -AsciiToWchar ( - CHAR8 *Str - ); - -static -WCHAR * -DuplicateString ( - WCHAR *Str - ); - -static -STATUS -StringDBWriteStringIdentifier ( - FILE *DBFptr, - UINT16 StringId, - UINT16 Flags, - WCHAR *IdentifierName - ); - -static -STATUS -StringDBReadStringIdentifier ( - FILE *DBFptr - ); - -static -STATUS -StringDBWriteLanguageDefinition ( - FILE *DBFptr, - WCHAR *LanguageName, - WCHAR *PrintableLanguageName - ); - -static -STATUS -StringDBReadLanguageDefinition ( - FILE *DBFptr - ); - -static -STATUS -StringDBWriteString ( - FILE *DBFptr, - UINT16 Flags, - WCHAR *Language, - WCHAR *StringName, - WCHAR *Scope, - WCHAR *Str - ); - -static -STATUS -StringDBReadString ( - FILE *DBFptr - ); - -static -STATUS -StringDBReadGenericString ( - FILE *DBFptr, - UINT16 *Size, - WCHAR **Str - ); - -static -STATUS -StringDBWriteGenericString ( - FILE *DBFptr, - WCHAR *Str - ); - -static -void -StringDBAssignStringIndexes ( - VOID - ); - -/*****************************************************************************/ - -/*++ - -Routine Description: - Constructor function for the string database handler. - -Arguments: - None. - -Returns: - None. - ---*/ -void -StringDBConstructor ( - VOID - ) -{ - memset ((char *) &mDBData, 0, sizeof (STRING_DB_DATA)); - mDBData.CurrentScope = DuplicateString (L"NULL"); -} - -/*****************************************************************************/ - -/*++ - -Routine Description: - Destructor function for the string database handler. - -Arguments: - None. - -Returns: - None. - ---*/ -void -StringDBDestructor ( - VOID - ) -{ - LANGUAGE_LIST *NextLang; - STRING_LIST *NextStr; - STRING_IDENTIFIER *NextIdentifier; - // - // Close the database file if it's open - // - if (mDBData.StringDBFptr != NULL) { - fclose (mDBData.StringDBFptr); - mDBData.StringDBFptr = NULL; - } - // - // If we've allocated any strings/languages, free them up - // - while (mDBData.LanguageList != NULL) { - NextLang = mDBData.LanguageList->Next; - // - // Free up all strings for this language - // - while (mDBData.LanguageList->String != NULL) { - NextStr = mDBData.LanguageList->String->Next; - FREE (mDBData.LanguageList->String->Str); - FREE (mDBData.LanguageList->String); - mDBData.LanguageList->String = NextStr; - } - - FREE (mDBData.LanguageList->PrintableLanguageName); - FREE (mDBData.LanguageList); - mDBData.LanguageList = NextLang; - } - // - // Free up string identifiers - // - while (mDBData.StringIdentifier != NULL) { - NextIdentifier = mDBData.StringIdentifier->Next; - FREE (mDBData.StringIdentifier->StringName); - FREE (mDBData.StringIdentifier); - mDBData.StringIdentifier = NextIdentifier; - } - // - // Free the filename - // - if (mDBData.StringDBFileName != NULL) { - FREE (mDBData.StringDBFileName); - mDBData.StringDBFileName = NULL; - } - // - // We save a copy of the scope, so free it up if we - // have one. - // - if (mDBData.CurrentScope != NULL) { - FREE (mDBData.CurrentScope); - mDBData.CurrentScope = NULL; - } -} - -/*****************************************************************************/ - -/*++ - -Routine Description: - - Dump the contents of a database to an output C file. - -Arguments: - - FileName - name of the output file to write - BaseName - used for the name of the C array defined - Languages - list of languages of interest - -Returns: - - STATUS - -Notes: - - Languages is a pointer to a linked list of languages specified on - the command line. Format is "eng" and "spa+cat". For this, print - the strings for eng. Print the strings for spa too, but if one is - missing look for a cat string and print if it it exists. - ---*/ -STATUS -StringDBDumpCStrings ( - CHAR8 *FileName, - CHAR8 *BaseName, - WCHAR_STRING_LIST *LanguagesOfInterest, - WCHAR_MATCHING_STRING_LIST *IndirectionList - ) -{ - FILE *Fptr; - LANGUAGE_LIST *Lang; - STRING_LIST *CurrString; - STRING_LIST EmptyString; - UINT32 Offset; - UINT32 StringIndex; - UINT32 TempIndex; - UINT32 BytesThisLine; - EFI_HII_STRING_PACK StringPack; - UINT8 *Ptr; - UINT32 Len; - WCHAR ZeroString[1]; - WCHAR_STRING_LIST *LOIPtr; - BOOLEAN LanguageOk; - WCHAR *TempStringPtr; - WCHAR *LangName; - STRING_IDENTIFIER *StringIdentifier; - WCHAR Line[200]; - - if ((Fptr = fopen (FileName, "w")) == NULL) { - Error (NULL, 0, 0, FileName, "failed to open output C string file"); - return STATUS_ERROR; - } - // - // Assign index values to the string identifiers - // - StringDBAssignStringIndexes (); - // - // Write the standard header to the output file, then the structure - // definition header. - // - StringDBWriteStandardFileHeader (Fptr); - fprintf (Fptr, "\nunsigned char %s[] = {\n", BaseName); - // - // If a given string is not defined, then we'll use this one. - // - memset (&EmptyString, 0, sizeof (EmptyString)); - EmptyString.Size = sizeof (ZeroString); - EmptyString.Str = ZeroString; - // - // Process each language, then each string for each langage - // - ZeroString[0] = 0; - for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) { - // - // If we have a language list, then make sure this language is in that - // list. - // - LanguageOk = TRUE; - LangName = Lang->LanguageName; - if (LanguagesOfInterest != NULL) { - LanguageOk = FALSE; - for (LOIPtr = LanguagesOfInterest; LOIPtr != NULL; LOIPtr = LOIPtr->Next) { - if (StrnCmp (LOIPtr->Str, Lang->LanguageName, LANGUAGE_IDENTIFIER_NAME_LEN) == 0) { - LangName = LOIPtr->Str; - LanguageOk = TRUE; - break; - } - } - } - - if (!LanguageOk) { - continue; - } - // - // Process each string for this language. We have to make 3 passes on the strings: - // Pass1: computes sizes and fill in the string pack header - // Pass2: write the array of offsets - // Pass3: write the strings - // - // - // PASS 1: Fill in and print the HII string pack header - // - // Compute the size for this language package and write - // the header out. Each string package contains: - // Header - // Offset[] -- an array of offsets to strings, of type RELOFST each - // String[] -- the actual strings themselves - // - AsciiSPrint ( Line, sizeof(Line), - "\n//******************************************************************************" - "\n// Start of string definitions for %s/%s", - Lang->LanguageName, - Lang->PrintableLanguageName - ); - fprintf (Fptr, "%s", Line); - memset ((char *) &StringPack, 0, sizeof (EFI_HII_STRING_PACK)); - StringPack.Header.Type = EFI_HII_STRING; - StringPack.NumStringPointers = (UINT16) mDBData.NumStringIdentifiersReferenced; - // - // First string is the language name. If we're printing all languages, then - // it's just the "spa". If we were given a list of languages to print, then it's - // the "spacat" string. Compute its offset and fill in - // the info in the header. Since we know the language name string's length, - // and the printable language name follows it, use that info to fill in the - // entry for the printable language name as well. - // - StringPack.LanguageNameString = (STRING_OFFSET) (sizeof (EFI_HII_STRING_PACK) + (mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET))); - StringPack.PrintableLanguageName = (STRING_OFFSET) (StringPack.LanguageNameString + (StrLen (LangName) + 1) * sizeof (WCHAR)); - // - // Add up the size of all strings so we can fill in our header. - // - Len = 0; - for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) { - // - // For the first string (language name), we print out the "spacat" if they - // requested it. We set LangName to point to the proper language name string above. - // - if (StringIndex == STRING_ID_LANGUAGE_NAME) { - Len += (StrLen (LangName) + 1) * sizeof (WCHAR); - } else { - // - // Find a string with this language.stringname - // - StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); - if (StringIdentifier == NULL) { - Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex); - return STATUS_ERROR; - } - // - // Find a matching string if this string identifier was referenced - // - EmptyString.Flags = STRING_FLAGS_UNDEFINED; - CurrString = NULL; - if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) { - CurrString = StringDBFindString ( - Lang->LanguageName, - StringIdentifier->StringName, - NULL, - LanguagesOfInterest, - IndirectionList - ); - if (NULL == CurrString) { - // - // If string for Lang->LanguageName is not found, try to get an English version - // - CurrString = StringDBFindString ( - L"eng", - StringIdentifier->StringName, - NULL, - LanguagesOfInterest, - IndirectionList - ); - } - } - - if (CurrString == NULL) { - CurrString = &EmptyString; - EmptyString.Flags |= StringIdentifier->Flags; - } - - Len += CurrString->Size; - } - } - StringPack.Header.Length = sizeof (EFI_HII_STRING_PACK) - + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET) - + Len; - // - // Write out the header one byte at a time - // - Ptr = (UINT8 *) &StringPack; - for (TempIndex = 0; TempIndex < sizeof (EFI_HII_STRING_PACK); TempIndex++, Ptr++) { - if ((TempIndex & 0x07) == 0) { - fprintf (Fptr, "\n "); - } - - fprintf (Fptr, "0x%02X, ", (UINT32) *Ptr); - } - - fprintf (Fptr, "\n // offset 0x%X\n", sizeof (StringPack)); - // - // PASS2 : write the offsets - // - // Traverse the list of strings again and write the array of offsets. The - // offset to the first string is the size of the string pack header - // plus the size of the offsets array. The other strings follow it. - // - StringIndex = 0; - Offset = sizeof (StringPack) + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET); - for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) { - // - // Write the offset, followed by a useful comment - // - fprintf (Fptr, " "); - Ptr = (UINT8 *) &Offset; - for (TempIndex = 0; TempIndex < sizeof (STRING_OFFSET); TempIndex++) { - fprintf (Fptr, "0x%02X, ", (UINT32) Ptr[TempIndex]); - } - // - // Find the string name - // - StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); - if (StringIdentifier == NULL) { - Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex); - return STATUS_ERROR; - } - - AsciiSPrint (Line, sizeof(Line) , " // offset to string %s (0x%04X)", StringIdentifier->StringName, StringIndex); - fprintf (Fptr, "%s", Line); - // - // For the first string (language name), we print out the "spacat" if they - // requested it. We set LangName to point to the proper language name string above. - // - if (StringIndex == STRING_ID_LANGUAGE_NAME) { - Offset += (StrLen (LangName) + 1) * sizeof (WCHAR); - CurrString = StringDBFindString ( - Lang->LanguageName, - StringIdentifier->StringName, - NULL, // scope - NULL, - NULL - ); - } else { - // - // Find a matching string - // - CurrString = StringDBFindString ( - Lang->LanguageName, - StringIdentifier->StringName, - NULL, // scope - LanguagesOfInterest, - IndirectionList - ); - - if (NULL == CurrString) { - CurrString = StringDBFindString ( - L"eng", - StringIdentifier->StringName, - NULL, // scope - LanguagesOfInterest, - IndirectionList - ); - } - - EmptyString.LanguageName = Lang->LanguageName; - if (CurrString == NULL) { - CurrString = &EmptyString; - EmptyString.Flags = STRING_FLAGS_UNDEFINED; - } else if ((StringIdentifier->Flags & STRING_FLAGS_REFERENCED) == 0) { - CurrString = &EmptyString; - EmptyString.Flags = 0; - } - - Offset += CurrString->Size; - } - // - // Print useful info about this string - // - if ((StringIdentifier->Flags & STRING_FLAGS_REFERENCED) == 0) { - fprintf (Fptr, " - not referenced"); - } - - if (CurrString->Flags & STRING_FLAGS_UNDEFINED) { - fprintf (Fptr, " - not defined for this language"); - } else if (StrCmp (CurrString->LanguageName, Lang->LanguageName) != 0) { - AsciiSPrint ( - Line, sizeof(Line), - " - not defined for this language -- using secondary language %s definition", - CurrString->LanguageName - ); - fprintf ( Fptr, "%s", Line); - } - - fprintf (Fptr, "\n"); - } - // - // For unreferenced string identifiers, print a message that they are not referenced anywhere - // - while (StringIndex < mDBData.NumStringIdentifiers) { - StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); - if (StringIdentifier != NULL) { - AsciiSPrint (Line, sizeof(Line), " // %s not referenced\n", StringIdentifier->StringName); - fprintf (Fptr, "%s", Line); - } - - StringIndex++; - } - - // - // PASS 3: write the strings themselves. - // Keep track of how many bytes we write per line because some editors - // (Visual Studio for instance) can't handle too long of lines. - // - Offset = sizeof (StringPack) + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET); - for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) { - StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); - if (StringIdentifier == NULL) { - Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex); - return STATUS_ERROR; - } - - AsciiSPrint (Line, sizeof(Line), " // string %s offset 0x%08X\n ", StringIdentifier->StringName, Offset); - fprintf (Fptr, "%s", Line); - // - // For the first string (language name), we print out the "spacat" if they - // requested it. We set LangName to point to the proper language name string above. - // - if (StringIndex == STRING_ID_LANGUAGE_NAME) { - TempStringPtr = LangName; - } else { - // - // Find a matching string if this string identifier was referenced - // - CurrString = NULL; - if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) { - CurrString = StringDBFindString ( - Lang->LanguageName, - StringIdentifier->StringName, - NULL, // scope - LanguagesOfInterest, - IndirectionList - ); - if (NULL == CurrString) { - CurrString = StringDBFindString ( - L"eng", - StringIdentifier->StringName, - NULL, // scope - LanguagesOfInterest, - IndirectionList - ); - } - } - - if (CurrString == NULL) { - CurrString = &EmptyString; - } - - TempStringPtr = CurrString->Str; - } - - BytesThisLine = 0; - for (TempIndex = 0; TempStringPtr[TempIndex] != 0; TempIndex++) { - fprintf ( - Fptr, - "0x%02X, 0x%02X, ", - (UINT32) TempStringPtr[TempIndex] & 0xFF, - (UINT32) ((TempStringPtr[TempIndex] >> 8) & 0xFF) - ); - BytesThisLine += 2; - Offset += 2; - // - // Let's say we only allow 14 per line - // - if (BytesThisLine > 14) { - fprintf (Fptr, "\n "); - BytesThisLine = 0; - } - } - // - // Print NULL WCHAR at the end of this string. - // - fprintf (Fptr, "0x00, 0x00,\n"); - Offset += 2; - } - // - // Sanity check the offset. Make sure our running offset is what we put in the - // string pack header. - // - if (StringPack.Header.Length != Offset) { - Error ( - __FILE__, - __LINE__, - 0, - "application error", - "stringpack size 0x%X does not match final size 0x%X", - StringPack.Header.Length, - Offset - ); - } - } - // - // Print terminator string pack, closing brace and close the file. - // The size of 0 triggers to the consumer that this is the end. - // - memset ((char *) &StringPack, 0, sizeof (EFI_HII_STRING_PACK)); - StringPack.Header.Type = EFI_HII_STRING; - Ptr = (UINT8 *) &StringPack; - fprintf (Fptr, "\n // strings terminator pack"); - for (TempIndex = 0; TempIndex < sizeof (StringPack); TempIndex++, Ptr++) { - if ((TempIndex & 0x0F) == 0) { - fprintf (Fptr, "\n "); - } - - fprintf (Fptr, "0x%02X, ", (UINT32) *Ptr); - } - - fprintf (Fptr, "\n};\n"); - fclose (Fptr); - return STATUS_SUCCESS; -} - -/*****************************************************************************/ - -/*++ - -Routine Description: - - Dump the #define string names - -Arguments: - - FileName - name of the output file to write - BaseName - used for the protection #ifndef/#endif - -Returns: - - STATUS - ---*/ -STATUS -StringDBDumpStringDefines ( - CHAR8 *FileName, - CHAR8 *BaseName - ) -{ - FILE *Fptr; - STRING_IDENTIFIER *Identifier; - CHAR8 CopyBaseName[100]; - WCHAR Line[200]; - UINT32 Index; - const CHAR8 *StrDefHeader[] = { - "#ifndef _%s_STRINGS_DEFINE_H_\n", - "#define _%s_STRINGS_DEFINE_H_\n\n", - NULL - }; - - if ((Fptr = fopen (FileName, "w")) == NULL) { - Error (NULL, 0, 0, FileName, "failed to open output string defines file"); - return STATUS_ERROR; - } - // - // Get the base source filename and convert to uppercase. - // - if (sizeof (CopyBaseName) <= strlen (BaseName) + 1) { - Error (NULL, 0, 0, "application error", "StringDBDumpStringDefines() string length insufficient"); - return STATUS_ERROR; - } - - strcpy (CopyBaseName, BaseName); - for (Index = 0; CopyBaseName[Index] != 0; Index++) { - if (islower (CopyBaseName[Index])) { - CopyBaseName[Index] = (INT8) toupper (CopyBaseName[Index]); - } - } - // - // Assign index values to the string identifiers - // - StringDBAssignStringIndexes (); - // - // Write the standard header to the output file, and then the - // protective #ifndef. - // - StringDBWriteStandardFileHeader (Fptr); - for (Index = 0; StrDefHeader[Index] != NULL; Index++) { - fprintf (Fptr, StrDefHeader[Index], CopyBaseName); - } - // - // Print all the #defines for the string identifiers. Print identifiers - // whose names start with '$' as comments. Add comments for string - // identifiers not used as well. - // - Identifier = mDBData.StringIdentifier; - while (Identifier != NULL) { - if (Identifier->StringName[0] == L'$') { - fprintf (Fptr, "// "); - } - - if (Identifier->Flags & STRING_FLAGS_REFERENCED) { - AsciiSPrint (Line, sizeof(Line), "#define %-40s 0x%04X\n", Identifier->StringName, Identifier->Index); - fprintf (Fptr, "%s", Line); - } else { - AsciiSPrint (Line, sizeof(Line), "//#define %-40s 0x%04X // not referenced\n", Identifier->StringName, Identifier->Index); - fprintf (Fptr, "%s", Line); - } - - Identifier = Identifier->Next; - } - - fprintf (Fptr, "\n#endif\n"); - fclose (Fptr); - return STATUS_SUCCESS; -} - -/*****************************************************************************/ - -/*++ - -Routine Description: - - Add a string identifier to the database. - -Arguments: - - StringName - name of the string identifier. For example "STR_MY_STRING" - NewId - if an ID has been assigned - Flags - characteristics for the identifier - -Returns: - - STATUS - ---*/ -STATUS -StringDBAddStringIdentifier ( - WCHAR *StringName, - UINT16 *NewId, - UINT16 Flags - ) -{ - STRING_IDENTIFIER *StringIdentifier; - STATUS Status; - // - // If it was already used for some other language, then we don't - // need to add it. But set it to the current string identifier. - // The referenced bit is sticky. - // - Status = STATUS_SUCCESS; - StringIdentifier = StringDBFindStringIdentifierByName (StringName); - if (StringIdentifier != NULL) { - if (Flags & STRING_FLAGS_REFERENCED) { - StringIdentifier->Flags |= STRING_FLAGS_REFERENCED; - } - - mDBData.CurrentStringIdentifier = StringIdentifier; - *NewId = (UINT16) StringIdentifier->Index; - return Status; - } - - StringIdentifier = (STRING_IDENTIFIER *) MALLOC (sizeof (STRING_IDENTIFIER)); - if (StringIdentifier == NULL) { - Error (NULL, 0, 0, NULL, "memory allocation error"); - return STATUS_ERROR; - } - - memset ((char *) StringIdentifier, 0, sizeof (STRING_IDENTIFIER)); - StringIdentifier->StringName = (WCHAR *) malloc ((StrLen (StringName) + 1) * sizeof (WCHAR)); - if (StringIdentifier->StringName == NULL) { - Error (NULL, 0, 0, NULL, "memory allocation error"); - return STATUS_ERROR; - } - - StrCpy (StringIdentifier->StringName, StringName); - if (*NewId != STRING_ID_INVALID) { - StringIdentifier->Index = *NewId; - StringIdentifier->Flags |= STRING_FLAGS_INDEX_ASSIGNED; - if (mDBData.NumStringIdentifiers <= StringIdentifier->Index) { - mDBData.NumStringIdentifiers = StringIdentifier->Index + 1; - } - } else { - StringIdentifier->Index = mDBData.NumStringIdentifiers++; - } - - StringIdentifier->Flags |= Flags; - // - // Add it to our list of string identifiers - // - if (mDBData.StringIdentifier == NULL) { - mDBData.StringIdentifier = StringIdentifier; - } else { - mDBData.LastStringIdentifier->Next = StringIdentifier; - } - - mDBData.LastStringIdentifier = StringIdentifier; - mDBData.CurrentStringIdentifier = StringIdentifier; - *NewId = (UINT16) StringIdentifier->Index; - return Status; -} - -/*****************************************************************************/ - -/*++ - -Routine Description: - - Add a new string to the database. - -Arguments: - - LanguageName - "eng" or "spa" language name - StringName - "STR_MY_TEXT" string name - Scope - from the #scope statements in the string file - Format - if we should format the string - Flags - characteristic flags for the string - -Returns: - - STATUS - -Notes: - - Several of the fields can be "inherited" from the previous calls to - our database functions. For example, if scope is NULL here, then - we'll use the previous setting. - ---*/ -STATUS -StringDBAddString ( - WCHAR *LanguageName, - WCHAR *StringName, - WCHAR *Scope, - WCHAR *String, - BOOLEAN Format, - UINT16 Flags - ) -{ - LANGUAGE_LIST *Lang; - UINT32 Size; - STRING_LIST *Str; - UINT16 StringIndex; - WCHAR TempLangName[4]; - STRING_IDENTIFIER *StringIdentifier; - - // - // Check that language name is exactly 3 characters, or emit an error. - // Truncate at 3 if it's longer, or make it 3 if it's shorter. - // - if (LanguageName != NULL) { - Size = StrLen (LanguageName); - if (Size != 3) { - ParserError (0, "invalid length for language name", "%S", LanguageName); - if (Size > 3) { - LanguageName[3] = 0; - } else { - // - // Make a local copy of the language name string, and extend to - // 3 characters since we make assumptions elsewhere in this program - // on the length. - // - StrCpy (TempLangName, LanguageName); - for (; Size < 3; Size++) { - TempLangName[Size] = L'?'; - } - - TempLangName[4] = 0; - LanguageName = TempLangName; - } - } - } - // - // If they specified a language, make sure they've defined it already - // via a #langdef statement. Otherwise use the current default language. - // - if (LanguageName != NULL) { - Lang = StringDBFindLanguageList (LanguageName); - if (Lang == NULL) { - ParserError (0, "language not defined", "%S", LanguageName); - return STATUS_ERROR; - } else { - StringDBSetCurrentLanguage (LanguageName); - } - } else { - Lang = mDBData.CurrentLanguage; - if (Lang == NULL) { - // - // Have to call SetLanguage() first - // - ParserError (0, "no language defined", "%S", StringName); - return STATUS_ERROR; - } - } - // - // If they didn't define a string identifier, use the last string identifier - // added. - // - if (StringName == NULL) { - StringName = mDBData.CurrentStringIdentifier->StringName; - if (StringName == NULL) { - ParserError (0, "no string identifier previously specified", NULL); - return STATUS_ERROR; - } - } - // - // If scope was not specified, use the default setting - // - if (Scope != NULL) { - Scope = DuplicateString (Scope); - } else { - Scope = DuplicateString (mDBData.CurrentScope); - } - // - // printf ("Adding string: %S.%S.%S\n", Lang->LanguageName, StringName, Scope); - // - // Check for duplicates for this Language.StringName.Scope. Allow multiple - // definitions of the language name and printable language name, since the - // user does not specifically define them. - // - if (StringDBFindString (Lang->LanguageName, StringName, Scope, NULL, NULL) != NULL) { - if ((StrCmp (StringName, LANGUAGE_NAME_STRING_NAME) == 0) && - (StrCmp (StringName, PRINTABLE_LANGUAGE_NAME_STRING_NAME) == 0) - ) { - ParserError ( - 0, - "string multiply defined", - "Language.Name.Scope = %S.%S.%S", - Lang->LanguageName, - StringName, - Scope - ); - return STATUS_ERROR; - } - } - - StringIndex = STRING_ID_INVALID; - if (StringDBAddStringIdentifier (StringName, &StringIndex, Flags) != STATUS_SUCCESS) { - return STATUS_ERROR; - } - - StringIdentifier = StringDBFindStringIdentifierByName (StringName); - // - // Add this string to the end of the strings for this language. - // - Str = (STRING_LIST *) malloc (sizeof (STRING_LIST)); - if (Str == NULL) { - Error (NULL, 0, 0, NULL, "memory allocation error"); - return STATUS_ERROR; - } - - memset ((char *) Str, 0, sizeof (STRING_LIST)); - Size = (StrLen (String) + 1) * sizeof (WCHAR); - Str->Flags = Flags; - Str->Scope = Scope; - Str->StringName = StringIdentifier->StringName; - Str->LanguageName = DuplicateString (LanguageName); - Str->Str = (WCHAR *) MALLOC (Size); - if (Str->Str == NULL) { - Error (NULL, 0, 0, NULL, "memory allocation error"); - return STATUS_ERROR; - } - // - // If not formatting, just copy the string. - // - StrCpy (Str->Str, String); - if (Format) { - StringDBFormatString (Str->Str); - } - // - // Size may change after formatting. We set the size to - // the actual size of the string, including the null for - // easier processing later. - // - Str->Size = (StrLen (Str->Str) + 1) * sizeof (WCHAR); - if (Lang->String == NULL) { - Lang->String = Str; - } else { - Lang->LastString->Next = Str; - } - - Lang->LastString = Str; - return STATUS_SUCCESS; -} - -/*****************************************************************************/ - -/*++ - -Routine Description: - - Given a language name, see if a language list for it has been defined - -Arguments: - - LanguageName - like "eng" - -Returns: - - A pointer to the language list - ---*/ -static -LANGUAGE_LIST * -StringDBFindLanguageList ( - WCHAR *LanguageName - ) -{ - LANGUAGE_LIST *Lang; - - Lang = mDBData.LanguageList; - while (Lang != NULL) { - if (StrCmp (LanguageName, Lang->LanguageName) == 0) { - break; - } - - Lang = Lang->Next; - } - - return Lang; -} - -/*****************************************************************************/ -STATUS -StringDBSetCurrentLanguage ( - WCHAR *LanguageName - ) -{ - LANGUAGE_LIST *Lang; - - Lang = StringDBFindLanguageList (LanguageName); - if (Lang == NULL) { - ParserError (0, "language not previously defined", "%S", LanguageName); - return STATUS_ERROR; - } - - mDBData.CurrentLanguage = Lang; - return STATUS_SUCCESS; -} - -/*****************************************************************************/ -STATUS -StringDBAddLanguage ( - WCHAR *LanguageName, - WCHAR *PrintableLanguageName - ) -{ - LANGUAGE_LIST *Lang; - // - // Check for redefinitions - // - Lang = StringDBFindLanguageList (LanguageName); - if (Lang != NULL) { - // - // Better be the same printable name - // - if (StrCmp (PrintableLanguageName, Lang->PrintableLanguageName) != 0) { - ParserError ( - 0, - "language redefinition", - "%S:%S != %S:%S", - Lang->LanguageName, - Lang->PrintableLanguageName, - LanguageName, - PrintableLanguageName - ); - return STATUS_ERROR; - // - // } else { - // ParserWarning (0, "benign language redefinition", "%S", PrintableLanguageName); - // return STATUS_WARNING; - // - } - } else { - // - // Allocate memory to keep track of this new language - // - Lang = (LANGUAGE_LIST *) malloc (sizeof (LANGUAGE_LIST)); - if (Lang == NULL) { - Error (NULL, 0, 0, NULL, "memory allocation error"); - return STATUS_ERROR; - } - - memset ((char *) Lang, 0, sizeof (LANGUAGE_LIST)); - // - // Save the language name, then allocate memory to save the - // printable language name - // - StrCpy (Lang->LanguageName, LanguageName); - Lang->PrintableLanguageName = (WCHAR *) malloc ((StrLen (PrintableLanguageName) + 1) * sizeof (WCHAR)); - if (Lang->PrintableLanguageName == NULL) { - Error (NULL, 0, 0, NULL, "memory allocation error"); - return STATUS_ERROR; - } - - StrCpy (Lang->PrintableLanguageName, PrintableLanguageName); - - if (mDBData.LanguageList == NULL) { - mDBData.LanguageList = Lang; - } else { - mDBData.LastLanguageList->Next = Lang; - } - - mDBData.LastLanguageList = Lang; - } - // - // Default is to make our active language this new one - // - StringDBSetCurrentLanguage (LanguageName); - // - // The first two strings for any language are the language name, - // followed by the printable language name. Add them and set them - // to referenced so they never get stripped out. - // - StringDBAddString ( - LanguageName, - LANGUAGE_NAME_STRING_NAME, - NULL, - LanguageName, - FALSE, - STRING_FLAGS_REFERENCED - ); - StringDBAddString ( - LanguageName, - PRINTABLE_LANGUAGE_NAME_STRING_NAME, - NULL, - PrintableLanguageName, - FALSE, - STRING_FLAGS_REFERENCED - ); - return STATUS_SUCCESS; -} - -/*****************************************************************************/ -static -STRING_IDENTIFIER * -StringDBFindStringIdentifierByName ( - WCHAR *StringName - ) -{ - STRING_IDENTIFIER *Identifier; - - Identifier = mDBData.StringIdentifier; - while (Identifier != NULL) { - if (StrCmp (StringName, Identifier->StringName) == 0) { - return Identifier; - } - - Identifier = Identifier->Next; - } - - return NULL; -} - -static -STRING_IDENTIFIER * -StringDBFindStringIdentifierByIndex ( - UINT32 StringIndex - ) -{ - STRING_IDENTIFIER *Identifier; - - Identifier = mDBData.StringIdentifier; - while (Identifier != NULL) { - if (Identifier->Index == StringIndex) { - return Identifier; - } - - Identifier = Identifier->Next; - } - - return NULL; -} - -/*****************************************************************************/ -static -void -StringDBWriteStandardFileHeader ( - FILE *OutFptr - ) -{ - UINT32 TempIndex; - for (TempIndex = 0; mSourceFileHeader[TempIndex] != NULL; TempIndex++) { - fprintf (OutFptr, "%s\n", mSourceFileHeader[TempIndex]); - } -} - -/*****************************************************************************/ - -/*++ - -Routine Description: - - Given a Unicode string from an input file, reformat the string to replace - backslash control sequences with the appropriate encoding. - -Arguments: - - String - pointer to string to reformat - -Returns: - - Nothing - ---*/ -void -StringDBFormatString ( - WCHAR *String - ) -{ - WCHAR *From; - WCHAR *To; - int HexNibbles; - WCHAR HexValue; - // - // Go through the string and process any formatting characters - // - From = String; - To = String; - while (*From) { - if (*From == UNICODE_BACKSLASH) { - // - // First look for \wide and replace with the appropriate control character. Note that - // when you have "define STR L"ABC"", then sizeof(ABC) is 8 because the null char is - // counted. Make adjustments for this. We advance From below, so subtract 2 each time. - // - if (StrnCmp (From, UNICODE_WIDE_STRING, sizeof (UNICODE_WIDE_STRING) / sizeof (WCHAR) - 1) == 0) { - *To = WIDE_CHAR; - From += sizeof (UNICODE_WIDE_STRING) / sizeof (WCHAR) - 2; - } else if (StrnCmp (From, UNICODE_NARROW_STRING, sizeof (UNICODE_NARROW_STRING) / sizeof (WCHAR) - 1) == 0) { - // - // Found: \narrow - // - *To = NARROW_CHAR; - From += sizeof (UNICODE_NARROW_STRING) / sizeof (WCHAR) - 2; - } else if (StrnCmp (From, UNICODE_NBR_STRING, sizeof (UNICODE_NBR_STRING) / sizeof (WCHAR) - 1) == 0) { - // - // Found: \nbr - // - *To = NON_BREAKING_CHAR; - From += sizeof (UNICODE_NBR_STRING) / sizeof (WCHAR) - 2; - } else if (StrnCmp (From, UNICODE_BR_STRING, sizeof (UNICODE_BR_STRING) / sizeof (WCHAR) - 1) == 0) { - // - // Found: \br -- pass through untouched - // - *To = *From; - } else { - // - // Standard one-character control sequences such as \n, \r, \\, or \x - // - From++; - switch (*From) { - case ASCII_TO_UNICODE ('n'): - *To = UNICODE_CR; - To++; - *To = UNICODE_LF; - break; - - // - // carriage return - // - case ASCII_TO_UNICODE ('r'): - *To = UNICODE_CR; - break; - - // - // backslash - // - case UNICODE_BACKSLASH: - *To = UNICODE_BACKSLASH; - break; - - // - // Tab - // - case ASCII_TO_UNICODE ('t'): - *To = UNICODE_TAB; - break; - - // - // embedded double-quote - // - case UNICODE_DOUBLE_QUOTE: - *To = UNICODE_DOUBLE_QUOTE; - break; - - // - // Hex Unicode character \x1234. We'll process up to 4 hex characters - // - case ASCII_TO_UNICODE ('x'): - HexValue = 0; - for (HexNibbles = 0; HexNibbles < 4; HexNibbles++) { - if ((From[1] >= UNICODE_0) && (From[1] <= UNICODE_9)) { - HexValue = (HexValue << 4) | (From[1] - UNICODE_0); - } else if ((From[1] >= UNICODE_a) && (From[1] <= UNICODE_f)) { - HexValue = (HexValue << 4) | (10 + From[1] - UNICODE_a); - } else if ((From[1] >= UNICODE_A) && (From[1] <= UNICODE_F)) { - HexValue = (HexValue << 4) | (10 + From[1] - UNICODE_A); - } else { - break; - } - - From++; - } - - if (HexNibbles == 0) { - ParserWarning ( - 0, - "expected at least one valid hex digit with \\x escaped character in string", - "\\%C", - *From - ); - } else { - *To = HexValue; - } - break; - - default: - *To = UNICODE_SPACE; - ParserWarning (0, "invalid escaped character in string", "\\%C", *From); - break; - } - } - } else { - *To = *From; - } - - From++; - To++; - } - - *To = 0; -} - -/*****************************************************************************/ -STATUS -StringDBReadDatabase ( - CHAR8 *DBFileName, - BOOLEAN IgnoreIfNotExist, - BOOLEAN Verbose - ) -{ - STRING_DB_HEADER DbHeader; - STATUS Status; - FILE *DBFptr; - DB_DATA_ITEM_HEADER DataItemHeader; - - Status = STATUS_SUCCESS; - DBFptr = NULL; - // - // if (Verbose) { - // fprintf (stdout, "Reading database file %s\n", DBFileName); - // } - // - // Try to open the input file - // - if ((DBFptr = fopen (DBFileName, "rb")) == NULL) { - if (IgnoreIfNotExist) { - return STATUS_SUCCESS; - } - - Error (NULL, 0, 0, DBFileName, "failed to open input database file for reading"); - return STATUS_ERROR; - } - // - // Read and verify the database header - // - if (fread ((void *) &DbHeader, sizeof (STRING_DB_HEADER), 1, DBFptr) != 1) { - Error (NULL, 0, 0, DBFileName, "failed to read header from database file"); - Status = STATUS_ERROR; - goto Finish; - } - - if (DbHeader.Key != STRING_DB_KEY) { - Error (NULL, 0, 0, DBFileName, "invalid header in database file"); - Status = STATUS_ERROR; - goto Finish; - } - - if ((DbHeader.Version & STRING_DB_MAJOR_VERSION_MASK) != (STRING_DB_VERSION & STRING_DB_MAJOR_VERSION_MASK)) { - Error (NULL, 0, 0, DBFileName, "incompatible database file version -- rebuild clean"); - Status = STATUS_ERROR; - goto Finish; - } - // - // Read remaining items - // - while (fread (&DataItemHeader, sizeof (DataItemHeader), 1, DBFptr) == 1) { - switch (DataItemHeader.DataType) { - case DB_DATA_TYPE_STRING_IDENTIFIER: - StringDBReadStringIdentifier (DBFptr); - break; - - case DB_DATA_TYPE_LANGUAGE_DEFINITION: - StringDBReadLanguageDefinition (DBFptr); - break; - - case DB_DATA_TYPE_STRING_DEFINITION: - StringDBReadString (DBFptr); - break; - - default: - Error ( - NULL, - 0, - 0, - "database corrupted", - "invalid data item type 0x%X at offset 0x%X", - (UINT32) DataItemHeader.DataType, - ftell (DBFptr) - sizeof (DataItemHeader) - ); - Status = STATUS_ERROR; - goto Finish; - } - } - -Finish: - if (DBFptr != NULL) { - fclose (DBFptr); - } - - return Status; -} - -/*****************************************************************************/ - -/*++ - -Routine Description: - - Write everything we know to the output database file. Write: - - Database header - String identifiers[] - StringPacks[] - -Arguments: - - DBFileName - name of the file to write to - Verbose - for debug purposes, print info messages along the way. - -Returns: - - STATUS - ---*/ -STATUS -StringDBWriteDatabase ( - CHAR8 *DBFileName, - BOOLEAN Verbose - ) -{ - STRING_DB_HEADER DbHeader; - UINT32 Counter; - UINT32 StrLength; - LANGUAGE_LIST *Lang; - STRING_IDENTIFIER *StringIdentifier; - STRING_LIST *StrList; - FILE *DBFptr; - - if (Verbose) { - fprintf (stdout, "Writing database %s\n", DBFileName); - } - - if ((DBFptr = fopen (DBFileName, "wb")) == NULL) { - Error (NULL, 0, 0, DBFileName, "failed to open output database file for writing"); - return STATUS_ERROR; - } - // - // Fill in and write the database header - // - memset (&DbHeader, 0, sizeof (STRING_DB_HEADER)); - DbHeader.HeaderSize = sizeof (STRING_DB_HEADER); - DbHeader.Key = STRING_DB_KEY; - DbHeader.Version = STRING_DB_VERSION; - // - // Count the number of languages we have - // - for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) { - DbHeader.NumLanguages++; - } - // - // Count up how many string identifiers we have, and total up the - // size of the names plus the size of the flags field we will - // write out too. - // - DbHeader.NumStringIdenfiers = mDBData.NumStringIdentifiers; - StringIdentifier = mDBData.StringIdentifier; - for (Counter = 0; Counter < mDBData.NumStringIdentifiers; Counter++) { - StrLength = StrLen (StringIdentifier->StringName) + 1; - DbHeader.StringIdentifiersSize += StrLength * sizeof (WCHAR) + sizeof (StringIdentifier->Flags); - StringIdentifier = StringIdentifier->Next; - } - - // - // Write the header - // - fwrite (&DbHeader, sizeof (STRING_DB_HEADER), 1, DBFptr); - if (Verbose) { - fprintf (stdout, " Number of string identifiers 0x%04X\n", DbHeader.NumStringIdenfiers); - fprintf (stdout, " Number of languages %d\n", DbHeader.NumLanguages); - } - // - // Write the string identifiers - // - for (StringIdentifier = mDBData.StringIdentifier; StringIdentifier != NULL; StringIdentifier = StringIdentifier->Next) { - StringDBWriteStringIdentifier ( - DBFptr, - (UINT16) StringIdentifier->Index, - StringIdentifier->Flags, - StringIdentifier->StringName - ); - } - // - // Now write all the strings for each language - // - for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) { - StringDBWriteLanguageDefinition (DBFptr, Lang->LanguageName, Lang->PrintableLanguageName); - for (StrList = Lang->String; StrList != NULL; StrList = StrList->Next) { - StringDBWriteString ( - DBFptr, - StrList->Flags, - Lang->LanguageName, - StrList->StringName, - StrList->Scope, - StrList->Str - ); - } - } - - fclose (DBFptr); - return STATUS_SUCCESS; -} - -STATUS -StringDBSetStringReferenced ( - CHAR8 *StringIdentifierName, - BOOLEAN IgnoreNotFound - ) -{ - STRING_IDENTIFIER *Id; - WCHAR *WName; - STATUS Status; - // - // See if it's already been defined. - // - Status = STATUS_SUCCESS; - WName = (WCHAR *) malloc ((strlen (StringIdentifierName) + 1) * sizeof (WCHAR)); - UnicodeSPrint (WName, (strlen (StringIdentifierName) + 1) * sizeof (WCHAR), L"%a", StringIdentifierName); - Id = StringDBFindStringIdentifierByName (WName); - if (Id != NULL) { - Id->Flags |= STRING_FLAGS_REFERENCED; - } else { - if (IgnoreNotFound == 0) { - ParserWarning (0, StringIdentifierName, "string identifier not found in database"); - Status = STATUS_WARNING; - } - } - - free (WName); - return Status; -} - -/*****************************************************************************/ - -/*++ - -Routine Description: - - Dump the contents of a database to an output unicode file. - -Arguments: - - DBFileName - name of the pre-existing database file to read - OutputFileName - name of the file to dump the database contents to - Verbose - for printing of additional info useful for debugging - -Returns: - - STATUS - -Notes: - - There's some issue with the unicode printing routines. Therefore to - write to the output file properly, open it as binary and use fwrite. - Ideally we could open it with just L"w" and use fwprintf(). - ---*/ -STATUS -StringDBDumpDatabase ( - CHAR8 *DBFileName, - CHAR8 *OutputFileName, - BOOLEAN Verbose - ) -{ - LANGUAGE_LIST *Lang; - STRING_IDENTIFIER *StringIdentifier; - STRING_LIST *StrList; - FILE *OutFptr; - WCHAR WChar; - WCHAR CrLf[2]; - WCHAR Line[200]; - WCHAR *Scope; - // - // This function assumes the database has already been read, and - // we're just dumping our internal data structures to a unicode file. - // - if (Verbose) { - fprintf (stdout, "Dumping database file %s\n", DBFileName); - } - - OutFptr = fopen (OutputFileName, "wb"); - if (OutFptr == NULL) { - Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing"); - return STATUS_ERROR; - } - - WChar = UNICODE_FILE_START; - fwrite (&WChar, sizeof (WCHAR), 1, OutFptr); - CrLf[1] = UNICODE_LF; - CrLf[0] = UNICODE_CR; - // - // The default control character is '/'. Make it '#' by writing - // "/=#" to the output file. - // - UnicodeSPrint (Line, sizeof(Line), L"/=#"); - fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr); - fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); - fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); - // - // Dump all the string identifiers and their values - // - StringDBAssignStringIndexes (); - for (StringIdentifier = mDBData.StringIdentifier; StringIdentifier != NULL; StringIdentifier = StringIdentifier->Next) { - // - // Write the "#define " string - // - if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) { - UnicodeSPrint ( - Line, - sizeof(Line), L"%s %-60.60s 0x%04X", - DEFINE_STR, - StringIdentifier->StringName, - StringIdentifier->Index - ); - } else { - UnicodeSPrint ( - Line, - sizeof(Line), L"%s %-60.60s 0x%04X // NOT REFERENCED", - DEFINE_STR, - StringIdentifier->StringName, - StringIdentifier->Index - ); - } - - fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr); - fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); - } - - fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); - // - // Now write all the strings for each language. - // - WChar = UNICODE_DOUBLE_QUOTE; - Scope = NULL; - for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) { - fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); - UnicodeSPrint (Line, sizeof(Line), L"#langdef %s \"%s\"", Lang->LanguageName, Lang->PrintableLanguageName); - fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr); - fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); - fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); - // - // Now the strings (in double-quotes) for this language. Write - // #string STR_NAME #language eng "string" - // - for (StrList = Lang->String; StrList != NULL; StrList = StrList->Next) { - // - // Print the internal flags for debug - // - UnicodeSPrint (Line, sizeof(Line), L"// flags=0x%02X", (UINT32) StrList->Flags); - fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr); - fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); - // - // Print the scope if changed - // - if ((Scope == NULL) || (StrCmp (Scope, StrList->Scope) != 0)) { - UnicodeSPrint (Line, sizeof(Line), L"#scope %s", StrList->Scope); - fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr); - fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); - Scope = StrList->Scope; - } - - UnicodeSPrint ( - Line, - sizeof(Line), L"#string %-50.50s #language %s \"", - StrList->StringName, - Lang->LanguageName - ); - fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr); - fwrite (StrList->Str, StrList->Size - sizeof (WCHAR), 1, OutFptr); - UnicodeSPrint (Line, sizeof(Line), L"\""); - fwrite (Line, StrLen (Line) * sizeof (WCHAR), 1, OutFptr); - fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); - } - } - - fclose (OutFptr); - return STATUS_SUCCESS; -} - -/*****************************************************************************/ - -/*++ - -Routine Description: - - Given a primary language, a string identifier number, and a list of - languages, find a secondary string. - -Arguments: - - LanguageName - primary language, like "spa" - StringId - string index value - LanguageList - linked list of "eng", "spa+cat",... - -Returns: - - Pointer to a secondary string if found. NULL otherwise. - -Notes: - - Given: LanguageName "spa" and LanguageList "spa+cat", match the - "spa" and extract the "cat" and see if there is a string defined - for "cat".StringId. - ---*/ -static -STATUS -StringDBWriteStringIdentifier ( - FILE *DBFptr, - UINT16 StringId, - UINT16 Flags, - WCHAR *IdentifierName - ) -{ - DB_DATA_ITEM_HEADER Hdr; - memset (&Hdr, 0, sizeof (DB_DATA_ITEM_HEADER)); - Hdr.DataType = DB_DATA_TYPE_STRING_IDENTIFIER; - if (fwrite (&Hdr, sizeof (DB_DATA_ITEM_HEADER), 1, DBFptr) != 1) { - Error (NULL, 0, 0, "failed to write string to output database file", NULL); - return STATUS_ERROR; - } - - if (fwrite (&StringId, sizeof (StringId), 1, DBFptr) != 1) { - Error (NULL, 0, 0, "failed to write StringId to output database", NULL); - return STATUS_ERROR; - } - - if (fwrite (&Flags, sizeof (Flags), 1, DBFptr) != 1) { - Error (NULL, 0, 0, "failed to write StringId flags to output database", NULL); - return STATUS_ERROR; - } - - if (StringDBWriteGenericString (DBFptr, IdentifierName) != STATUS_SUCCESS) { - return STATUS_ERROR; - } - - return STATUS_SUCCESS; -} - -static -STATUS -StringDBReadStringIdentifier ( - FILE *DBFptr - ) -{ - WCHAR *IdentifierName; - UINT16 Flags; - UINT16 StringId; - UINT16 Size; - - if (fread (&StringId, sizeof (StringId), 1, DBFptr) != 1) { - Error (NULL, 0, 0, "failed to read StringId from database", NULL); - return STATUS_ERROR; - } - - if (fread (&Flags, sizeof (Flags), 1, DBFptr) != 1) { - Error (NULL, 0, 0, "failed to read StringId flags from database", NULL); - return STATUS_ERROR; - } - - if (StringDBReadGenericString (DBFptr, &Size, &IdentifierName) != STATUS_SUCCESS) { - return STATUS_ERROR; - } - - StringDBAddStringIdentifier (IdentifierName, &StringId, Flags); - // - // printf ("STRID: 0x%04X %S\n", (UINT32)StringId, IdentifierName); - // - FREE (IdentifierName); - return STATUS_SUCCESS; -} - -static -STATUS -StringDBWriteString ( - FILE *DBFptr, - UINT16 Flags, - WCHAR *Language, - WCHAR *StringName, - WCHAR *Scope, - WCHAR *Str - ) -{ - DB_DATA_ITEM_HEADER Hdr; - memset (&Hdr, 0, sizeof (DB_DATA_ITEM_HEADER)); - Hdr.DataType = DB_DATA_TYPE_STRING_DEFINITION; - if (fwrite (&Hdr, sizeof (DB_DATA_ITEM_HEADER), 1, DBFptr) != 1) { - Error (NULL, 0, 0, "failed to write string header to output database file", NULL); - return STATUS_ERROR; - } - - if (fwrite (&Flags, sizeof (Flags), 1, DBFptr) != 1) { - Error (NULL, 0, 0, "failed to write string flags to output database", NULL); - return STATUS_ERROR; - } - - if (StringDBWriteGenericString (DBFptr, Language) != STATUS_SUCCESS) { - return STATUS_ERROR; - } - - if (StringDBWriteGenericString (DBFptr, StringName) != STATUS_SUCCESS) { - return STATUS_ERROR; - } - - if (StringDBWriteGenericString (DBFptr, Scope) != STATUS_SUCCESS) { - return STATUS_ERROR; - } - - if (StringDBWriteGenericString (DBFptr, Str) != STATUS_SUCCESS) { - return STATUS_ERROR; - } - // - // printf ("DBWriteString: %S.%S.%S\n", Language, StringName, Scope); - // - return STATUS_SUCCESS; -} - -static -STATUS -StringDBReadString ( - FILE *DBFptr - ) -{ - UINT16 Flags; - UINT16 Size; - WCHAR *Language; - WCHAR *StringName; - WCHAR *Scope; - WCHAR *Str; - - if (fread (&Flags, sizeof (Flags), 1, DBFptr) != 1) { - Error (NULL, 0, 0, "failed to read string flags from database", NULL); - return STATUS_ERROR; - } - - if (StringDBReadGenericString (DBFptr, &Size, &Language) != STATUS_SUCCESS) { - return STATUS_ERROR; - } - - if (StringDBReadGenericString (DBFptr, &Size, &StringName) != STATUS_SUCCESS) { - return STATUS_ERROR; - } - - if (StringDBReadGenericString (DBFptr, &Size, &Scope) != STATUS_SUCCESS) { - return STATUS_ERROR; - } - - if (StringDBReadGenericString (DBFptr, &Size, &Str) != STATUS_SUCCESS) { - return STATUS_ERROR; - } - // - // If the first or second string (language name and printable language name), - // then skip them. They're added via language definitions data items in - // the database. - // - if (StringName[0] != L'$') { - StringDBAddString (Language, StringName, Scope, Str, FALSE, Flags); - } - // - // printf ("DBReadString: %S.%S.%S\n", Language, StringName, Scope); - // - FREE (Language); - FREE (StringName); - if (Str != NULL) { - FREE (Str); - } - - if (Scope != NULL) { - FREE (Scope); - } - - return STATUS_SUCCESS; -} - -static -STATUS -StringDBWriteLanguageDefinition ( - FILE *DBFptr, - WCHAR *LanguageName, - WCHAR *PrintableLanguageName - ) -{ - DB_DATA_ITEM_HEADER Hdr; - memset (&Hdr, 0, sizeof (DB_DATA_ITEM_HEADER)); - Hdr.DataType = DB_DATA_TYPE_LANGUAGE_DEFINITION; - if (fwrite (&Hdr, sizeof (DB_DATA_ITEM_HEADER), 1, DBFptr) != 1) { - Error (NULL, 0, 0, "failed to write string to output database file", NULL); - return STATUS_ERROR; - } - - if (StringDBWriteGenericString (DBFptr, LanguageName) != STATUS_SUCCESS) { - return STATUS_ERROR; - } - - if (StringDBWriteGenericString (DBFptr, PrintableLanguageName) != STATUS_SUCCESS) { - return STATUS_ERROR; - } - - return STATUS_SUCCESS; -} - -static -STATUS -StringDBReadLanguageDefinition ( - FILE *DBFptr - ) -{ - WCHAR *LanguageName; - WCHAR *PrintableLanguageName; - UINT16 Size; - STATUS Status; - - if (StringDBReadGenericString (DBFptr, &Size, &LanguageName) != STATUS_SUCCESS) { - return STATUS_ERROR; - } - - if (StringDBReadGenericString (DBFptr, &Size, &PrintableLanguageName) != STATUS_SUCCESS) { - return STATUS_ERROR; - } - // - // printf("LANG: %S %S\n", LanguageName, PrintableLanguageName); - // - Status = StringDBAddLanguage (LanguageName, PrintableLanguageName); - FREE (LanguageName); - FREE (PrintableLanguageName); - return Status; -} -// -// All unicode strings in the database consist of a UINT16 length -// field, followed by the string itself. This routine reads one -// of those and returns the info. -// -static -STATUS -StringDBReadGenericString ( - FILE *DBFptr, - UINT16 *Size, - WCHAR **Str - ) -{ - UINT16 LSize; - UINT16 Flags; - WCHAR *LStr; - - if (fread (&LSize, sizeof (UINT16), 1, DBFptr) != 1) { - Error (NULL, 0, 0, "failed to read a string length field from the database", NULL); - return STATUS_ERROR; - } - - if (fread (&Flags, sizeof (UINT16), 1, DBFptr) != 1) { - Error (NULL, 0, 0, "failed to read a string flags field from the database", NULL); - return STATUS_ERROR; - } - - LStr = MALLOC (LSize); - if (LStr == NULL) { - Error (__FILE__, __LINE__, 0, "memory allocation failed reading the database", NULL); - return STATUS_ERROR; - } - - if (fread (LStr, sizeof (WCHAR), (UINT32) LSize / sizeof (WCHAR), DBFptr) != (UINT32) LSize / sizeof (WCHAR)) { - Error (NULL, 0, 0, "failed to read string from database", NULL); - Error (NULL, 0, 0, "database read failure", "offset 0x%X", ftell (DBFptr)); - free (LStr); - return STATUS_ERROR; - } - // - // printf ("DBR: %S\n", LStr); - // - // If the flags field indicated we were asked to write a NULL string, then - // return them a NULL pointer. - // - if (Flags & STRING_FLAGS_UNDEFINED) { - *Size = 0; - *Str = NULL; - } else { - *Size = LSize; - *Str = LStr; - } - - return STATUS_SUCCESS; -} - -static -STATUS -StringDBWriteGenericString ( - FILE *DBFptr, - WCHAR *Str - ) -{ - UINT16 Size; - UINT16 Flags; - WCHAR ZeroString[1]; - // - // Strings in the database consist of a size UINT16 followed - // by the string itself. - // - if (Str == NULL) { - ZeroString[0] = 0; - Str = ZeroString; - Size = sizeof (ZeroString); - Flags = STRING_FLAGS_UNDEFINED; - } else { - Flags = 0; - Size = (UINT16) ((StrLen (Str) + 1) * sizeof (WCHAR)); - } - - if (fwrite (&Size, sizeof (UINT16), 1, DBFptr) != 1) { - Error (NULL, 0, 0, "failed to write string size to database", NULL); - return STATUS_ERROR; - } - - if (fwrite (&Flags, sizeof (UINT16), 1, DBFptr) != 1) { - Error (NULL, 0, 0, "failed to write string flags to database", NULL); - return STATUS_ERROR; - } - - if (fwrite (Str, sizeof (WCHAR), Size / sizeof (WCHAR), DBFptr) != Size / sizeof (WCHAR)) { - Error (NULL, 0, 0, "failed to write string to database", NULL); - return STATUS_ERROR; - } - - return STATUS_SUCCESS; -} - -static -STRING_LIST * -StringDBFindString ( - WCHAR *LanguageName, - WCHAR *StringName, - WCHAR *Scope, - WCHAR_STRING_LIST *LanguagesOfInterest, - WCHAR_MATCHING_STRING_LIST *IndirectionList - ) -{ - LANGUAGE_LIST *Lang; - STRING_LIST *CurrString; - WCHAR_MATCHING_STRING_LIST *IndListPtr; - WCHAR TempLangName[LANGUAGE_IDENTIFIER_NAME_LEN + 1]; - WCHAR *WCharPtr; - - // - // If we were given an indirection list, then see if one was specified for this - // string identifier. That is to say, if the indirection says "STR_ID_MY_FAVORITE MyScope", - // then if this string name matches one in the list, then do a lookup with the - // specified scope and return that value. - // - if (IndirectionList != NULL) { - for (IndListPtr = IndirectionList; IndListPtr != NULL; IndListPtr = IndListPtr->Next) { - if (StrCmp (StringName, IndListPtr->Str1) == 0) { - CurrString = StringDBFindString (LanguageName, StringName, IndListPtr->Str2, LanguagesOfInterest, NULL); - if (CurrString != NULL) { - return CurrString; - } - } - } - } - // - // First look for exact match language.stringname - // - for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) { - if (StrCmp (LanguageName, Lang->LanguageName) == 0) { - // - // Found language match. Try to find string name match - // - for (CurrString = Lang->String; CurrString != NULL; CurrString = CurrString->Next) { - if (StrCmp (StringName, CurrString->StringName) == 0) { - // - // Found a string name match. See if we're supposed to find - // a scope match. - // - if (Scope != NULL) { - if (StrCmp (CurrString->Scope, Scope) == 0) { - return CurrString; - } - } else { - return CurrString; - } - } - } - } - } - // - // If we got here, then we didn't find a match. Look for secondary string - // matches. That is to say, if we're processing "spa", and they requested - // "spa+cat", then recursively call with "cat" - // - while (LanguagesOfInterest != NULL) { - // - // If this is the language we're looking for, then process the - // languages of interest list for it. - // - if (StrnCmp (LanguageName, LanguagesOfInterest->Str, LANGUAGE_IDENTIFIER_NAME_LEN) == 0) { - WCharPtr = LanguagesOfInterest->Str + LANGUAGE_IDENTIFIER_NAME_LEN; - while (*WCharPtr) { - // - // Double-check the length, though it should have been checked on the - // command line. - // - if (StrLen (WCharPtr) < LANGUAGE_IDENTIFIER_NAME_LEN) { - Error (NULL, 0, 0, "malformed alternate language list", "%S", LanguagesOfInterest->Str); - return NULL; - } - - StrnCpy (TempLangName, WCharPtr, LANGUAGE_IDENTIFIER_NAME_LEN); - TempLangName[LANGUAGE_IDENTIFIER_NAME_LEN] = 0; - CurrString = StringDBFindString (TempLangName, StringName, NULL, NULL, IndirectionList); - if (CurrString != NULL) { - return CurrString; - } - - WCharPtr += LANGUAGE_IDENTIFIER_NAME_LEN; - } - } - - LanguagesOfInterest = LanguagesOfInterest->Next; - } - - return NULL; -} - -STATUS -StringDBSetScope ( - WCHAR *Scope - ) -{ - // - // Free up existing scope memory. - // - if (mDBData.CurrentScope != NULL) { - FREE (mDBData.CurrentScope); - } - - mDBData.CurrentScope = DuplicateString (Scope); - return STATUS_SUCCESS; -} -// -// We typically don't assign index values to string identifiers -// until we're ready to write out files. To reduce the size of -// the output file, re-order the string identifiers to move any -// unreferenced ones to the end. Then we'll walk the list -// again to assign string indexes, keeping track of the last -// one referenced. -// -static -void -StringDBAssignStringIndexes ( - VOID - ) -{ - STRING_IDENTIFIER *StrId; - STRING_IDENTIFIER *FirstUsed; - STRING_IDENTIFIER *LastUsed; - STRING_IDENTIFIER *FirstUnused; - STRING_IDENTIFIER *LastUnused; - UINT32 Index; - UINT32 MaxReferenced; - - // - // Create two lists -- used and unused. Then put them together with - // the unused ones on the end. - // - FirstUsed = NULL; - LastUsed = NULL; - FirstUnused = NULL; - LastUnused = NULL; - StrId = mDBData.StringIdentifier; - while (StrId != NULL) { - if ((StrId->Flags & STRING_FLAGS_REFERENCED) == 0) { - // - // Put it on the unused list - // - if (FirstUnused == NULL) { - FirstUnused = StrId; - } else { - LastUnused->Next = StrId; - } - - LastUnused = StrId; - StrId = StrId->Next; - LastUnused->Next = NULL; - } else { - // - // Put it on the used list - // - if (FirstUsed == NULL) { - FirstUsed = StrId; - } else { - LastUsed->Next = StrId; - } - - LastUsed = StrId; - StrId = StrId->Next; - LastUsed->Next = NULL; - } - } - // - // Join the lists - // - if (FirstUsed != NULL) { - mDBData.StringIdentifier = FirstUsed; - LastUsed->Next = FirstUnused; - } else { - mDBData.StringIdentifier = FirstUnused; - } - - MaxReferenced = 0; - Index = 0; - for (StrId = mDBData.StringIdentifier; StrId != NULL; StrId = StrId->Next) { - StrId->Index = Index; - Index++; - if (StrId->Flags & STRING_FLAGS_REFERENCED) { - mDBData.NumStringIdentifiersReferenced = Index; - } - } - - mDBData.NumStringIdentifiers = Index; -} - -static -WCHAR * -DuplicateString ( - WCHAR *Str - ) -{ - WCHAR *NewStr; - if (Str == NULL) { - return NULL; - } - - NewStr = MALLOC ((StrLen (Str) + 1) * sizeof (WCHAR)); - if (NewStr == NULL) { - Error (NULL, 0, 0, "memory allocation failure", NULL); - return NULL; - } - - StrCpy (NewStr, Str); - return NewStr; -} - -static -WCHAR * -AsciiToWchar ( - CHAR8 *Str - ) -{ - UINT32 Len; - WCHAR *NewStr; - WCHAR *Ptr; - - Len = strlen (Str) + 1; - NewStr = (WCHAR *) malloc (Len * sizeof (WCHAR)); - for (Ptr = NewStr; *Str != 0; Str++, Ptr++) { - *Ptr = (UINT16) (UINT8) *Str; - } - - *Ptr = 0; - return NewStr; -} - -/*****************************************************************************/ - -/*++ - -Routine Description: - - Create an HII export string pack for the strings in our database. - -Arguments: - - FileName - name of the output file to write - -Returns: - - STATUS - - ---*/ -STATUS -StringDBCreateHiiExportPack ( - CHAR8 *FileName - ) -{ - FILE *Fptr; - LANGUAGE_LIST *Lang; - STRING_LIST *CurrString; - STRING_LIST EmptyString; - UINT32 Offset; - UINT32 StringIndex; - UINT32 TempIndex; - EFI_HII_STRING_PACK StringPack; - UINT32 Len; - WCHAR ZeroString[1]; - WCHAR *TempStringPtr; - WCHAR *LangName; - STRING_IDENTIFIER *StringIdentifier; - - if ((Fptr = fopen (FileName, "wb")) == NULL) { - Error (NULL, 0, 0, FileName, "failed to open output HII export file"); - return STATUS_ERROR; - } - // - // Assign index values to the string identifiers - // - StringDBAssignStringIndexes (); - // - // If a given string is not defined, then we'll use this one. - // - memset (&EmptyString, 0, sizeof (EmptyString)); - EmptyString.Size = sizeof (ZeroString); - EmptyString.Str = ZeroString; - // - // Process each language, then each string for each langage - // - ZeroString[0] = 0; - for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) { - // - // Process each string for this language. We have to make 3 passes on the strings: - // Pass1: computes sizes and fill in the string pack header - // Pass2: write the array of offsets - // Pass3: write the strings - // - // - // PASS 1: Fill in and print the HII string pack header - // - // Compute the size for this language package and write - // the header out. Each string package contains: - // Header - // Offset[] -- an array of offsets to strings, of type RELOFST each - // String[] -- the actual strings themselves - // - memset ((char *) &StringPack, 0, sizeof (EFI_HII_STRING_PACK)); - StringPack.Header.Type = EFI_HII_STRING; - StringPack.NumStringPointers = (UINT16) mDBData.NumStringIdentifiersReferenced; - LangName = Lang->LanguageName; - // - // First string is the language name. If we're printing all languages, then - // it's just the "spa". If we were given a list of languages to print, then it's - // the "spacat" string. Compute its offset and fill in - // the info in the header. Since we know the language name string's length, - // and the printable language name follows it, use that info to fill in the - // entry for the printable language name as well. - // - StringPack.LanguageNameString = (STRING_OFFSET) (sizeof (EFI_HII_STRING_PACK) + (mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET))); - StringPack.PrintableLanguageName = (STRING_OFFSET) (StringPack.LanguageNameString + (StrLen (LangName) + 1) * sizeof (WCHAR)); - // - // Add up the size of all strings so we can fill in our header. - // - Len = 0; - for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) { - // - // For the first string (language name), we print out the "spacat" if they - // requested it. We set LangName to point to the proper language name string above. - // - if (StringIndex == STRING_ID_LANGUAGE_NAME) { - Len += (StrLen (LangName) + 1) * sizeof (WCHAR); - } else { - // - // Find a string with this language.stringname - // - StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); - if (StringIdentifier == NULL) { - Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex); - return STATUS_ERROR; - } - // - // Find a matching string if this string identifier was referenced - // - EmptyString.Flags = STRING_FLAGS_UNDEFINED; - CurrString = NULL; - if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) { - CurrString = StringDBFindString ( - Lang->LanguageName, - StringIdentifier->StringName, - NULL, - NULL, // LanguagesOfInterest, - NULL - ); - // - // IndirectionList); - // - if (NULL == CurrString) { - // - // If string for Lang->LanguageName is not found, try to get an English version - // - CurrString = StringDBFindString ( - L"eng", - StringIdentifier->StringName, - NULL, - NULL, // LanguagesOfInterest, - NULL - ); - // - // IndirectionList); - // - } - } - - if (CurrString == NULL) { - CurrString = &EmptyString; - EmptyString.Flags |= StringIdentifier->Flags; - } - - Len += CurrString->Size; - } - } - StringPack.Header.Length = sizeof (EFI_HII_STRING_PACK) - + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET) - + Len; - // - // Write out the string pack header - // - fwrite ((void *) &StringPack, sizeof (StringPack), 1, Fptr); - // - // PASS2 : write the offsets - // - // Traverse the list of strings again and write the array of offsets. The - // offset to the first string is the size of the string pack header - // plus the size of the offsets array. The other strings follow it. - // - StringIndex = 0; - Offset = sizeof (StringPack) + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET); - for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) { - // - // Write the offset - // - fwrite (&Offset, sizeof (STRING_OFFSET), 1, Fptr); - // - // Find the string name - // - StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); - if (StringIdentifier == NULL) { - Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex); - return STATUS_ERROR; - } - // - // For the first string (language name), we print out the "spacat" if they - // requested it. We set LangName to point to the proper language name string above. - // - if (StringIndex == STRING_ID_LANGUAGE_NAME) { - Offset += (StrLen (LangName) + 1) * sizeof (WCHAR); - CurrString = StringDBFindString ( - Lang->LanguageName, - StringIdentifier->StringName, - NULL, // scope - NULL, - NULL - ); - } else { - // - // Find a matching string - // - CurrString = StringDBFindString ( - Lang->LanguageName, - StringIdentifier->StringName, - NULL, // scope - NULL, // LanguagesOfInterest, - NULL - ); - // - // IndirectionList); - // - if (NULL == CurrString) { - CurrString = StringDBFindString ( - L"eng", - StringIdentifier->StringName, - NULL, // scope - NULL, // LanguagesOfInterest, - NULL - ); - // - // IndirectionList); - // - } - - EmptyString.LanguageName = Lang->LanguageName; - if (CurrString == NULL) { - CurrString = &EmptyString; - EmptyString.Flags = STRING_FLAGS_UNDEFINED; - } else if ((StringIdentifier->Flags & STRING_FLAGS_REFERENCED) == 0) { - CurrString = &EmptyString; - EmptyString.Flags = 0; - } - - Offset += CurrString->Size; - } - } - - // - // PASS 3: write the strings themselves. - // - Offset = sizeof (StringPack) + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET); - for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) { - StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); - if (StringIdentifier == NULL) { - Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex); - return STATUS_ERROR; - } - // - // For the first string (language name), we print out the "spacat" if they - // requested it. We set LangName to point to the proper language name string above. - // - if (StringIndex == STRING_ID_LANGUAGE_NAME) { - TempStringPtr = LangName; - } else { - // - // Find a matching string if this string identifier was referenced - // - CurrString = NULL; - if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) { - CurrString = StringDBFindString ( - Lang->LanguageName, - StringIdentifier->StringName, - NULL, // scope - NULL, // LanguagesOfInterest, - NULL - ); - // - // IndirectionList); - // - if (NULL == CurrString) { - CurrString = StringDBFindString ( - L"eng", - StringIdentifier->StringName, - NULL, // scope - NULL, // LanguagesOfInterest, - NULL - ); - // - // IndirectionList); - // - } - } - - if (CurrString == NULL) { - CurrString = &EmptyString; - } - - TempStringPtr = CurrString->Str; - } - - for (TempIndex = 0; TempStringPtr[TempIndex] != 0; TempIndex++) { - fwrite (&TempStringPtr[TempIndex], sizeof (CHAR16), 1, Fptr); - Offset += 2; - } - // - // Print NULL WCHAR at the end of this string. - // - TempIndex = 0; - fwrite (&TempIndex, sizeof (CHAR16), 1, Fptr); - Offset += 2; - } - // - // Sanity check the offset. Make sure our running offset is what we put in the - // string pack header. - // - if (StringPack.Header.Length != Offset) { - Error ( - __FILE__, - __LINE__, - 0, - "application error", - "stringpack size 0x%X does not match final size 0x%X", - StringPack.Header.Length, - Offset - ); - } - } - // - // Print terminator string pack, closing brace and close the file. - // The size of 0 triggers to the consumer that this is the end. - // - memset ((char *) &StringPack, 0, sizeof (EFI_HII_STRING_PACK)); - StringPack.Header.Type = EFI_HII_STRING; - fwrite ((void *) &StringPack, sizeof (StringPack), 1, Fptr); - fclose (Fptr); - return STATUS_SUCCESS; -}