makedeps.c

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

C
1,285
字号
/*++

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:

  MakeDeps.c  

Abstract:

  Recursively scan source files to find include files and emit them to 
  create dependency lists.

--*/

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

#include "Tiano.h"
#include "EfiUtilityMsgs.h"

//
// Structure to maintain a linked list of strings
//
typedef struct _STRING_LIST {
  struct _STRING_LIST *Next;
  char                *Str;
} STRING_LIST;

#define UTILITY_NAME      "MakeDeps"

#define MAX_LINE_LEN      2048
#define MAX_PATH          2048
#define START_NEST_DEPTH  1
#define MAX_NEST_DEPTH    1000  // just in case we get in an endless loop.
//
// Define the relative paths used by the special #include macros
//
#define PROTOCOL_DIR_PATH       "Protocol\\"
#define GUID_DIR_PATH           "Guid\\"
#define ARCH_PROTOCOL_DIR_PATH  "ArchProtocol\\"
#define PPI_PROTOCOL_DIR_PATH   "Ppi\\"

//
// Use this structure to keep track of all the special #include forms
//
typedef struct {
  INT8  *IncludeMacroName;
  INT8  *PathName;
} INCLUDE_MACRO_CONVERSION;

//
// This data is used to convert #include macros like:
//    #include EFI_PROTOCOL_DEFINITION(xxx)
// into
//    #include Protocol/xxx/xxx.h
//
static const INCLUDE_MACRO_CONVERSION mMacroConversion[] = {
  "EFI_PROTOCOL_DEFINITION",
  PROTOCOL_DIR_PATH,
  "EFI_GUID_DEFINITION",
  GUID_DIR_PATH,
  "EFI_ARCH_PROTOCOL_DEFINITION",
  ARCH_PROTOCOL_DIR_PATH,
  "EFI_PROTOCOL_PRODUCER",
  PROTOCOL_DIR_PATH,
  "EFI_PROTOCOL_CONSUMER",
  PROTOCOL_DIR_PATH,
  "EFI_PROTOCOL_DEPENDENCY",
  PROTOCOL_DIR_PATH,
  "EFI_ARCH_PROTOCOL_PRODUCER",
  ARCH_PROTOCOL_DIR_PATH,
  "EFI_ARCH_PROTOCOL_CONSUMER",
  ARCH_PROTOCOL_DIR_PATH,
  "EFI_ARCH_PROTOCOL_DEPENDENCY",
  ARCH_PROTOCOL_DIR_PATH,
  "EFI_PPI_DEFINITION",
  PPI_PROTOCOL_DIR_PATH,
  "EFI_PPI_PRODUCER",
  PPI_PROTOCOL_DIR_PATH,
  "EFI_PPI_CONSUMER",
  PPI_PROTOCOL_DIR_PATH,
  "EFI_PPI_DEPENDENCY",
  PPI_PROTOCOL_DIR_PATH,
  NULL,
  NULL
};

typedef struct _SYMBOL {
  struct _SYMBOL  *Next;
  INT8            *Name;
  INT8            *Value;
} SYMBOL;

//
// 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 flags to keep track of command-line options.
//
static struct {
  STRING_LIST *IncludePaths;            // all include paths to search
  STRING_LIST *SourceFiles;             // all source files to parse
  STRING_LIST *SubDirs;                 // appended to each include path when searching
  SYMBOL      *SymbolTable;             // for replacement strings
  FILE        *OutFptr;                 // output dependencies to this file
  BOOLEAN     Verbose;                  // for more detailed output
  BOOLEAN     IgnoreNotFound;           // no warnings if files not found
  BOOLEAN     QuietMode;                // -q - don't print missing file warnings
  BOOLEAN     NoSystem;                 // don't process #include <system> files
  BOOLEAN     NeverFail;                // always return success
  BOOLEAN     NoDupes;                  // to not list duplicate dependency files (for timing purposes)
  BOOLEAN     UseSumDeps;               // use summary dependency files if found
  INT8        TargetFileName[MAX_PATH]; // target object filename
  INT8        SumDepsPath[MAX_PATH];    // path to summary files
  INT8        *OutFileName;             // -o option
} mGlobals;

static
STATUS
ProcessFile (
  INT8            *TargetFileName,
  INT8            *FileName,
  UINT32          NestDepth,
  STRING_LIST     *ProcessedFiles
  );

static
FILE  *
FindFile (
  INT8    *FileName,
  UINT32  FileNameLen
  );

static
void
PrintDependency (
  INT8    *Target,
  INT8    *DependentFile
  );

static
void
ReplaceSymbols (
  INT8    *Str,
  UINT32  StrSize
  );

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

static
void
Usage (
  VOID
  );

static
void
FreeLists (
  VOID
  );

int
main (
  int   Argc,
  char  *Argv[]
  )
/*++

Routine Description:

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

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

Returns:

  0       if successful
  nonzero otherwise
  
--*/
{
  STRING_LIST *File;
  STRING_LIST ProcessedFiles;
  STRING_LIST *TempList;
  STATUS      Status;
  INT8        *Cptr;
  INT8        TargetFileName[MAX_PATH];

  SetUtilityName (UTILITY_NAME);
  //
  // Process the command-line arguments
  //
  Status = ProcessArgs (Argc, Argv);
  if (Status != STATUS_SUCCESS) {
    return STATUS_ERROR;
  }
  //
  // Go through the list of source files and process each.
  //
  memset (&ProcessedFiles, 0, sizeof (STRING_LIST));
  File = mGlobals.SourceFiles;
  while (File != NULL) {
    //
    // Clear out our list of processed files
    //
    TempList = ProcessedFiles.Next;
    while (ProcessedFiles.Next != NULL) {
      TempList = ProcessedFiles.Next->Next;
      free (ProcessedFiles.Next->Str);
      free (ProcessedFiles.Next);
      ProcessedFiles.Next = TempList;
    }
    //
    // Replace filename extension with ".obj" if they did not
    // specifically specify the target file
    //
    if (mGlobals.TargetFileName[0] == 0) {
      strcpy (TargetFileName, File->Str);
      //
      // Find the .extension
      //
      for (Cptr = TargetFileName + strlen (TargetFileName) - 1;
           (*Cptr != '\\') && (Cptr > TargetFileName) && (*Cptr != '.');
           Cptr--
          )
        ;
      if (Cptr == TargetFileName) {
        Error (NULL, 0, 0, File->Str, "could not locate extension in filename");
        goto Finish;
      }
      //
      // Tack on the ".obj"
      //
      strcpy (Cptr, ".obj");
    } else {
      //
      // Copy the target filename they specified
      //
      strcpy (TargetFileName, mGlobals.TargetFileName);
    }

    Status = ProcessFile (TargetFileName, File->Str, START_NEST_DEPTH, &ProcessedFiles);
    if (Status != STATUS_SUCCESS) {
      goto Finish;
    }

    File = File->Next;
  }

Finish:
  //
  // Free up memory
  //
  FreeLists ();
  //
  // Free up our processed files list
  //
  TempList = ProcessedFiles.Next;
  while (ProcessedFiles.Next != NULL) {
    TempList = ProcessedFiles.Next->Next;
    free (ProcessedFiles.Next->Str);
    free (ProcessedFiles.Next);
    ProcessedFiles.Next = TempList;
  }
  //
  // Close our output file
  //
  if ((mGlobals.OutFptr != stdout) && (mGlobals.OutFptr != NULL)) {
    fclose (mGlobals.OutFptr);
  }

  if (mGlobals.NeverFail) {
    return STATUS_SUCCESS;
  }
  //
  // If any errors, then delete our output so that it will get created
  // again on a rebuild.
  //
  if ((GetUtilityStatus () == STATUS_ERROR) && (mGlobals.OutFileName != NULL)) {
    remove (mGlobals.OutFileName);
  }

  return GetUtilityStatus ();
}

static
STATUS
ProcessFile (
  INT8            *TargetFileName,
  INT8            *FileName,
  UINT32          NestDepth,
  STRING_LIST     *ProcessedFiles
  )
/*++

Routine Description:

  Given a source file name, open the file and parse all #include lines.
  
Arguments:

  TargetFileName - name of the usually .obj target
  FileName       - name of the file to process
  NestDepth      - how deep we're nested in includes
  ProcessedFiles - list of processed files.

Returns:

  standard status.
  
--*/
{
  FILE        *Fptr;
  INT8        Line[MAX_LINE_LEN];
  INT8        *Cptr;
  INT8        *EndPtr;
  INT8        *SaveCptr;
  INT8        EndChar;
  INT8        FileNameCopy[MAX_PATH];
  INT8        MacroIncludeFileName[MAX_LINE_LEN];
  INT8        SumDepsFile[MAX_PATH];
  STATUS      Status;
  UINT32      Index;
  UINT32      LineNum;
  STRING_LIST *ListPtr;

  Status  = STATUS_SUCCESS;
  Fptr    = NULL;
  //
  // 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, ' ', FileName);
  }
  //
  // If we're using summary dependency files, and a matching .dep file is
  // found for this file, then just emit the summary dependency file as
  // a dependency and return.
  //
  if (mGlobals.UseSumDeps) {
    strcpy (SumDepsFile, mGlobals.SumDepsPath);
    strcat (SumDepsFile, FileName);
    for (Cptr = SumDepsFile + strlen (SumDepsFile) - 1;
         (*Cptr != '\\') && (Cptr > SumDepsFile) && (*Cptr != '.');
         Cptr--
        )
      ;
    if (*Cptr == '.') {
      strcpy (Cptr, ".dep");
    } else {
      strcat (SumDepsFile, ".dep");
    }
    //
    // See if the summary dep file exists. Could use _stat() function, but
    // it's less portable.
    //
    if ((Fptr = fopen (SumDepsFile, "r")) != NULL) {
      PrintDependency (TargetFileName, SumDepsFile);
      return STATUS_SUCCESS;
    }
  }
  //
  // If we're not doing duplicates, and we've already seen this filename,
  // then return
  //
  if (mGlobals.NoDupes) {
    for (ListPtr = ProcessedFiles->Next; ListPtr != NULL; ListPtr = ListPtr->Next) {
      if (_stricmp (FileName, ListPtr->Str) == 0) {
        break;
      }
    }
    //
    // If we found a match, we're done. If we didn't, create a new element
    // and add it to the list.
    //
    if (ListPtr != NULL) {
      //
      // Print a message if verbose mode
      //
      if (mGlobals.Verbose) {
        DebugMsg (NULL, 0, 0, FileName, "duplicate include -- not processed again");
      }

      return STATUS_SUCCESS;
    }

    ListPtr       = malloc (sizeof (STRING_LIST));
    ListPtr->Str  = malloc (strlen (FileName) + 1);
    strcpy (ListPtr->Str, FileName);
    ListPtr->Next         = ProcessedFiles->Next;
    ProcessedFiles->Next  = ListPtr;
  }

  //
  // Make sure we didn't exceed our maximum nesting depth
  //
  if (NestDepth > MAX_NEST_DEPTH) {
    Error (NULL, 0, 0, FileName, "max nesting depth exceeded on file");
    goto Finish;
  }
  //
  // Make a local copy of the filename. Then we can manipulate it
  // if we have to.
  //
  strcpy (FileNameCopy, FileName);
  //
  // Try to open the file locally
  //
  if ((Fptr = fopen (FileNameCopy, "r")) == NULL) {
    //

⌨️ 快捷键说明

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