]> git.proxmox.com Git - mirror_edk2.git/blobdiff - Tools/CCode/Source/StrGather/StringDB.c
Retiring the ANT/JAVA build and removing the older EDK II packages that required...
[mirror_edk2.git] / Tools / CCode / Source / StrGather / StringDB.c
diff --git a/Tools/CCode/Source/StrGather/StringDB.c b/Tools/CCode/Source/StrGather/StringDB.c
deleted file mode 100644 (file)
index 16ef052..0000000
+++ /dev/null
@@ -1,2759 +0,0 @@
-/*++\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