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 + -
显示快捷键?