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