strgather.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,364 行 · 第 1/5 页

C
2,364
字号
/*++

Copyright (c) 2004 - 2006, Intel Corporation                                                         
All rights reserved. This program and the accompanying materials                          
are licensed and made available under the terms and conditions of the BSD License         
which accompanies this distribution.  The full text of the license may be found at        
http://opensource.org/licenses/bsd-license.php                                            
                                                                                          
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

Module Name:

  StrGather.c  

Abstract:

  Parse a strings file and create or add to a string database file.

--*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#include "Tiano.h"
#include "EfiUtilityMsgs.h"
#include "StrGather.h"
#include "StringDB.h"

#define TOOL_VERSION  "0.31"

typedef UINT16  WCHAR;

#define MAX_PATH                    1024
#define MAX_NEST_DEPTH              20  // just in case we get in an endless loop.
#define MAX_STRING_IDENTIFIER_NAME  100 // number of wchars
#define MAX_LINE_LEN                400
#define STRING_TOKEN                "STRING_TOKEN"
#define DEFAULT_BASE_NAME           "BaseName"
//
// Operational modes for this utility
//
#define MODE_UNKNOWN  0
#define MODE_PARSE    1
#define MODE_SCAN     2
#define MODE_DUMP     3

//
// We keep a linked list of these for the source files we process
//
typedef struct _SOURCE_FILE {
  FILE                *Fptr;
  WCHAR               *FileBuffer;
  WCHAR               *FileBufferPtr;
  UINT32              FileSize;
  INT8                FileName[MAX_PATH];
  UINT32              LineNum;
  BOOLEAN             EndOfFile;
  BOOLEAN             SkipToHash;
  struct _SOURCE_FILE *Previous;
  struct _SOURCE_FILE *Next;
  WCHAR               ControlCharacter;
} SOURCE_FILE;

#define DEFAULT_CONTROL_CHARACTER UNICODE_SLASH

//
// Here's all our globals. We need a linked list of include paths, a linked
// list of source files, a linked list of subdirectories (appended to each
// include path when searching), and a couple other fields.
//
static struct {
  SOURCE_FILE                 SourceFiles;
  TEXT_STRING_LIST            *IncludePaths;                    // all include paths to search
  TEXT_STRING_LIST            *LastIncludePath;
  TEXT_STRING_LIST            *ScanFileName;
  TEXT_STRING_LIST            *LastScanFileName;
  TEXT_STRING_LIST            *SkipExt;                         // if -skipext .uni
  TEXT_STRING_LIST            *LastSkipExt;
  TEXT_STRING_LIST            *IndirectionFileName;
  TEXT_STRING_LIST            *LastIndirectionFileName;
  TEXT_STRING_LIST            *DatabaseFileName;
  TEXT_STRING_LIST            *LastDatabaseFileName;
  WCHAR_STRING_LIST           *Language;
  WCHAR_STRING_LIST           *LastLanguage;
  WCHAR_MATCHING_STRING_LIST  *IndirectionList;                 // from indirection file(s)
  WCHAR_MATCHING_STRING_LIST  *LastIndirectionList;
  BOOLEAN                     Verbose;                          // for more detailed output
  BOOLEAN                     VerboseDatabaseWrite;             // for more detailed output when writing database
  BOOLEAN                     VerboseDatabaseRead;              // for more detailed output when reading database
  BOOLEAN                     NewDatabase;                      // to start from scratch
  BOOLEAN                     IgnoreNotFound;                   // when scanning
  BOOLEAN                     VerboseScan;
  BOOLEAN                     UnquotedStrings;                  // -uqs option
  INT8                        OutputDatabaseFileName[MAX_PATH];
  INT8                        OutputDependencyFileName[MAX_PATH];
  INT8                        StringHFileName[MAX_PATH];
  INT8                        StringCFileName[MAX_PATH];        // output .C filename
  INT8                        DumpUFileName[MAX_PATH];          // output unicode dump file name
  INT8                        HiiExportPackFileName[MAX_PATH];  // HII export pack file name
  INT8                        BaseName[MAX_PATH];               // base filename of the strings file
  UINT32                      Mode;
} mGlobals;

static
BOOLEAN
IsValidIdentifierChar (
  INT8      Char,
  BOOLEAN   FirstChar
  );

static
void
RewindFile (
  SOURCE_FILE *SourceFile
  );

static
BOOLEAN
SkipTo (
  SOURCE_FILE *SourceFile,
  WCHAR       WChar,
  BOOLEAN     StopAfterNewline
  );

static
UINT32
SkipWhiteSpace (
  SOURCE_FILE *SourceFile
  );

static
BOOLEAN
IsWhiteSpace (
  SOURCE_FILE *SourceFile
  );

static
BOOLEAN
EndOfFile (
  SOURCE_FILE *SourceFile
  );

static
void
PreprocessFile (
  SOURCE_FILE *SourceFile
  );

static
UINT32
GetStringIdentifierName (
  IN SOURCE_FILE  *SourceFile,
  IN OUT WCHAR    *StringIdentifierName,
  IN UINT32       StringIdentifierNameLen
  );

static
UINT32
GetLanguageIdentifierName (
  IN SOURCE_FILE  *SourceFile,
  IN OUT WCHAR    *LanguageIdentifierName,
  IN UINT32       LanguageIdentifierNameLen,
  IN BOOLEAN      Optional
  );

static
WCHAR *
GetPrintableLanguageName (
  IN SOURCE_FILE  *SourceFile
  );

static
STATUS
AddCommandLineLanguage (
  IN INT8          *Language
  );

static
WCHAR *
GetQuotedString (
  SOURCE_FILE *SourceFile,
  BOOLEAN     Optional
  );

static
STATUS
ProcessIncludeFile (
  SOURCE_FILE *SourceFile,
  SOURCE_FILE *ParentSourceFile
  );

static
STATUS
ParseFile (
  SOURCE_FILE *SourceFile
  );

static
FILE  *
FindFile (
  IN INT8     *FileName,
  OUT INT8    *FoundFileName,
  IN UINT32   FoundFileNameLen
  );

static
STATUS
ProcessArgs (
  int   Argc,
  char  *Argv[]
  );

static
STATUS
ProcessFile (
  SOURCE_FILE *SourceFile
  );

static
UINT32
wstrcmp (
  WCHAR *Buffer,
  WCHAR *Str
  );

static
void
Usage (
  VOID
  );

static
void
FreeLists (
  VOID
  );

static
void
ProcessTokenString (
  SOURCE_FILE *SourceFile
  );

static
void
ProcessTokenInclude (
  SOURCE_FILE *SourceFile
  );

static
void
ProcessTokenScope (
  SOURCE_FILE *SourceFile
  );

static
void
ProcessTokenLanguage (
  SOURCE_FILE *SourceFile
  );

static
void
ProcessTokenLangDef (
  SOURCE_FILE *SourceFile
  );

static
STATUS
ScanFiles (
  TEXT_STRING_LIST *ScanFiles
  );

static
STATUS
ParseIndirectionFiles (
  TEXT_STRING_LIST    *Files
  );

STATUS
StringDBCreateHiiExportPack (
  INT8                *OutputFileName
  );

static
void
EmptyDependency (
    void
  );
  
static
void
AddDependency (
  INT8          *FileName
  );
  
int
main (
  int   Argc,
  char  *Argv[]
  )
/*++

Routine Description:

  Call the routine to parse the command-line options, then process the file.
  
Arguments:

  Argc - Standard C main() argc and argv.
  Argv - Standard C main() argc and argv.

Returns:

  0       if successful
  nonzero otherwise
  
--*/
{
  STATUS  Status;

  SetUtilityName (PROGRAM_NAME);
  //
  // Process the command-line arguments
  //
  Status = ProcessArgs (Argc, Argv);
  if (Status != STATUS_SUCCESS) {
    return Status;
  }
  //
  // Initialize the database manager
  //
  StringDBConstructor ();
  //
  // We always try to read in an existing database file. It may not
  // exist, which is ok usually.
  //
  if (mGlobals.NewDatabase == 0) {
    //
    // Read all databases specified.
    //
    for (mGlobals.LastDatabaseFileName = mGlobals.DatabaseFileName;
         mGlobals.LastDatabaseFileName != NULL;
         mGlobals.LastDatabaseFileName = mGlobals.LastDatabaseFileName->Next
        ) {
      Status = StringDBReadDatabase (mGlobals.LastDatabaseFileName->Str, TRUE, mGlobals.VerboseDatabaseRead);
      if (Status != STATUS_SUCCESS) {
        return Status;
      }
    }
  }
  //
  // Read indirection file(s) if specified
  //
  if (ParseIndirectionFiles (mGlobals.IndirectionFileName) != STATUS_SUCCESS) {
    goto Finish;
  }
  //
  // If scanning source files, do that now
  //
  if (mGlobals.Mode == MODE_SCAN) {
    ScanFiles (mGlobals.ScanFileName);
  } else if (mGlobals.Mode == MODE_PARSE) {
    //
    // Parsing a unicode strings file
    //
    mGlobals.SourceFiles.ControlCharacter = DEFAULT_CONTROL_CHARACTER;
    EmptyDependency ();
    Status = ProcessIncludeFile (&mGlobals.SourceFiles, NULL);
    if (Status != STATUS_SUCCESS) {
      goto Finish;
    }
  }
  //
  // Create the string defines header file if there have been no errors.
  //
  ParserSetPosition (NULL, 0);
  if ((mGlobals.StringHFileName[0] != 0) && (GetUtilityStatus () < STATUS_ERROR)) {
    Status = StringDBDumpStringDefines (mGlobals.StringHFileName, mGlobals.BaseName);
    if (Status != EFI_SUCCESS) {
      goto Finish;
    }
  }
  //
  // Dump the strings to a .c file if there have still been no errors.
  //
  if ((mGlobals.StringCFileName[0] != 0) && (GetUtilityStatus () < STATUS_ERROR)) {
    Status = StringDBDumpCStrings (
              mGlobals.StringCFileName,
              mGlobals.BaseName,
              mGlobals.Language,
              mGlobals.IndirectionList
              );
    if (Status != EFI_SUCCESS) {
      goto Finish;
    }
  }
  //
  // Dump the database if requested
  //
  if ((mGlobals.DumpUFileName[0] != 0) && (GetUtilityStatus () < STATUS_ERROR)) {
    StringDBDumpDatabase (NULL, mGlobals.DumpUFileName, FALSE);
  }
  //
  // Dump the string data as HII binary string pack if requested
  //
  if ((mGlobals.HiiExportPackFileName[0] != 0) && (GetUtilityStatus () < STATUS_ERROR)) {
    StringDBCreateHiiExportPack (mGlobals.HiiExportPackFileName);
  }
  //
  // Always update the database if no errors and not in dump mode. If they specified -od
  // for an output database file name, then use that name. Otherwise use the name of
  // the first database file specified with -db
  //
  if ((mGlobals.Mode != MODE_DUMP) && (GetUtilityStatus () < STATUS_ERROR)) {
    if (mGlobals.OutputDatabaseFileName[0]) {
      Status = StringDBWriteDatabase (mGlobals.OutputDatabaseFileName, mGlobals.VerboseDatabaseWrite);
    } else {
      Status = StringDBWriteDatabase (mGlobals.DatabaseFileName->Str, mGlobals.VerboseDatabaseWrite);
    }

    if (Status != EFI_SUCCESS) {
      goto Finish;
    }
  }

Finish:
  //
  // Free up memory
  //
  FreeLists ();
  StringDBDestructor ();
  return GetUtilityStatus ();
}

static
STATUS
ProcessIncludeFile (
  SOURCE_FILE *SourceFile,
  SOURCE_FILE *ParentSourceFile
  )
/*++

Routine Description:

  Given a source file, open the file and parse it
  
Arguments:

  SourceFile        - name of file to parse
  ParentSourceFile  - for error reporting purposes, the file that #included SourceFile.

Returns:

  Standard status.
  
--*/
{
  static UINT32 NestDepth = 0;
  INT8          FoundFileName[MAX_PATH];
  STATUS        Status;

  Status = STATUS_SUCCESS;
  NestDepth++;
  //
  // Print the file being processed. Indent so you can tell the include nesting
  // depth.
  //
  if (mGlobals.Verbose) {
    fprintf (stdout, "%*cProcessing file '%s'\n", NestDepth * 2, ' ', SourceFile->FileName);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?