2006-05-15 19:25:39 +02:00
/*++
2007-01-09 23:29:27 +01:00
Copyright ( c ) 2004 - 20077 , Intel Corporation
2006-05-15 19:25:39 +02:00
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>
2006-06-16 13:42:42 +02:00
# include <Common/UefiBaseTypes.h>
2006-05-15 19:25:39 +02:00
# include "EfiUtilityMsgs.h"
2006-06-16 13:42:42 +02:00
# include "CommonLib.h"
2006-05-15 19:25:39 +02:00
//
// Structure to maintain a linked list of strings
//
typedef struct _STRING_LIST {
struct _STRING_LIST * Next ;
char * Str ;
} STRING_LIST ;
2007-01-09 23:29:27 +01:00
# define UTILITY_NAME "MakeDeps"
# define UTILITY_MAJOR_VERSION 1
# define UTILITY_MINOR_VERSION 0
2006-05-15 19:25:39 +02:00
# 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
//
2006-07-24 10:02:37 +02:00
# define PROTOCOL_DIR_PATH "Protocol / "
# define GUID_DIR_PATH "Guid / "
# define ARCH_PROTOCOL_DIR_PATH "ArchProtocol / "
# define PPI_PROTOCOL_DIR_PATH "Ppi / "
2006-05-15 19:25:39 +02:00
//
// 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 [ ]
) ;
2007-01-09 23:29:27 +01:00
static
void
Version (
VOID
) ;
2006-05-15 19:25:39 +02:00
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 ;
2006-07-24 10:02:37 +02:00
( * Cptr ! = ' \\ ' & & * Cptr ! = ' / ' ) & & ( Cptr > TargetFileName ) & & ( * Cptr ! = ' . ' ) ;
2006-05-15 19:25:39 +02:00
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 ) ) {
2006-09-13 04:15:32 +02:00
fprintf ( mGlobals . OutFptr , " \t \n " ) ; // file ending flag
2006-05-15 19:25:39 +02:00
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 ;
2006-07-24 10:02:37 +02:00
( * Cptr ! = ' \\ ' & & * Cptr ! = ' / ' ) & & ( Cptr > SumDepsFile ) & & ( * Cptr ! = ' . ' ) ;
2006-05-15 19:25:39 +02:00
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 ) {
//
// Try to find it among the paths.
//
Fptr = FindFile ( FileNameCopy , sizeof ( FileNameCopy ) ) ;
if ( Fptr = = NULL ) {
//
// If this is not the top-level file, and the command-line argument
// said to ignore missing files, then return ok
//
if ( NestDepth ! = START_NEST_DEPTH ) {
if ( mGlobals . IgnoreNotFound ) {
if ( ! mGlobals . QuietMode ) {
DebugMsg ( NULL , 0 , 0 , FileNameCopy , " could not find file " ) ;
}
return STATUS_SUCCESS ;
} else {
Error ( NULL , 0 , 0 , FileNameCopy , " could not find file " ) ;
return STATUS_ERROR ;
}
} else {
//
// Top-level (first) file. Emit an error.
//
Error ( NULL , 0 , 0 , FileNameCopy , " could not find file " ) ;
return STATUS_ERROR ;
}
}
}
//
// Print the dependency, with string substitution
//
PrintDependency ( TargetFileName , FileNameCopy ) ;
//
// Now read in lines and find all #include lines. Allow them to indent, and
// to put spaces between the # and include.
//
LineNum = 0 ;
while ( ( fgets ( Line , sizeof ( Line ) , Fptr ) ! = NULL ) & & ( Status = = STATUS_SUCCESS ) ) {
LineNum + + ;
Cptr = Line ;
//
// Skip preceeding spaces on the line
//
while ( * Cptr & & ( isspace ( * Cptr ) ) ) {
Cptr + + ;
}
//
// Check for # character
//
if ( * Cptr = = ' # ' ) {
Cptr + + ;
//
// Check for "include"
//
while ( * Cptr & & ( isspace ( * Cptr ) ) ) {
Cptr + + ;
}
if ( strncmp ( Cptr , " include " , 7 ) = = 0 ) {
//
// Skip over "include" and move on to filename as "file" or <file>
//
Cptr + = 7 ;
while ( * Cptr & & ( isspace ( * Cptr ) ) ) {
Cptr + + ;
}
if ( * Cptr = = ' < ' ) {
EndChar = ' > ' ;
} else if ( * Cptr = = ' " ' ) {
EndChar = ' " ' ;
} else {
//
// Handle special #include MACRO_NAME(file)
// Set EndChar to null so we fall through on processing below.
//
EndChar = 0 ;
//
// Look for all the special include macros and convert accordingly.
//
for ( Index = 0 ; mMacroConversion [ Index ] . IncludeMacroName ! = NULL ; Index + + ) {
//
// Save the start of the string in case some macros are substrings
// of others.
//
SaveCptr = Cptr ;
if ( strncmp (
Cptr ,
mMacroConversion [ Index ] . IncludeMacroName ,
strlen ( mMacroConversion [ Index ] . IncludeMacroName )
) = = 0 ) {
//
// Skip over the macro name
//
Cptr + = strlen ( mMacroConversion [ Index ] . IncludeMacroName ) ;
//
// Skip over open parenthesis, blank spaces, then find closing
// parenthesis or blank space
//
while ( * Cptr & & ( isspace ( * Cptr ) ) ) {
Cptr + + ;
}
if ( * Cptr = = ' ( ' ) {
Cptr + + ;
while ( * Cptr & & ( isspace ( * Cptr ) ) ) {
Cptr + + ;
}
EndPtr = Cptr ;
while ( * EndPtr & & ! isspace ( * EndPtr ) & & ( * EndPtr ! = ' ) ' ) ) {
EndPtr + + ;
}
* EndPtr = 0 ;
//
// Create the path
//
strcpy ( MacroIncludeFileName , mMacroConversion [ Index ] . PathName ) ;
strcat ( MacroIncludeFileName , Cptr ) ;
2006-07-24 10:02:37 +02:00
strcat ( MacroIncludeFileName , " / " ) ;
2006-05-15 19:25:39 +02:00
strcat ( MacroIncludeFileName , Cptr ) ;
strcat ( MacroIncludeFileName , " .h " ) ;
//
// Process immediately, then break out of the outside FOR loop.
//
Status = ProcessFile ( TargetFileName , MacroIncludeFileName , NestDepth + 1 , ProcessedFiles ) ;
break ;
}
}
//
// Restore the start
//
Cptr = SaveCptr ;
}
//
// Don't recognize the include line? Ignore it. We assume that the
// file compiles anyway.
//
if ( mMacroConversion [ Index ] . IncludeMacroName = = NULL ) {
//
// Warning (FileNameCopy, LineNum, 0, "could not parse line", NULL);
// Status = STATUS_WARNING;
//
}
}
//
// Process "normal" includes. If the endchar is 0, then the
// file has already been processed. Otherwise look for the
// endchar > or ", and process the include file.
//
if ( EndChar ! = 0 ) {
Cptr + + ;
EndPtr = Cptr ;
while ( * EndPtr & & ( * EndPtr ! = EndChar ) ) {
EndPtr + + ;
}
if ( * EndPtr = = EndChar ) {
//
// If we're processing it, do it
//
if ( ( EndChar ! = ' > ' ) | | ( ! mGlobals . NoSystem ) ) {
//
// Null terminate the filename and try to process it.
//
* EndPtr = 0 ;
Status = ProcessFile ( TargetFileName , Cptr , NestDepth + 1 , ProcessedFiles ) ;
}
} else {
Warning ( FileNameCopy , LineNum , 0 , " malformed include " , " missing closing %c " , EndChar ) ;
Status = STATUS_WARNING ;
goto Finish ;
}
}
}
}
}
Finish :
//
// Close open files and return status
//
if ( Fptr ! = NULL ) {
fclose ( Fptr ) ;
}
return Status ;
}
static
void
PrintDependency (
INT8 * TargetFileName ,
INT8 * DependentFile
)
/*++
Routine Description :
Given a target ( . obj ) file name , and a dependent file name , do any string
substitutions ( per the command line options ) on the file names , then
print the dependency line of form :
TargetFileName : DependentFile
Arguments :
TargetFileName - build target file name
DependentFile - file on which TargetFileName depends
Returns :
None
- - */
{
INT8 Str [ MAX_PATH ] ;
//
// Go through the symbols and do replacements
//
strcpy ( Str , DependentFile ) ;
ReplaceSymbols ( Str , sizeof ( Str ) ) ;
fprintf ( mGlobals . OutFptr , " %s \n " , Str ) ;
}
static
void
ReplaceSymbols (
INT8 * Str ,
UINT32 StrSize
)
{
SYMBOL * Sym ;
INT8 StrCopy [ MAX_LINE_LEN ] ;
INT8 * From ;
INT8 * To ;
BOOLEAN Replaced ;
//
// Go through the entire string to look for replacement strings at
// every position.
//
From = Str ;
To = StrCopy ;
while ( * From ) {
//
// Copy the character
//
* To = * From ;
Replaced = FALSE ;
//
// Go through each symbol and try to find a string substitution
//
Sym = mGlobals . SymbolTable ;
while ( Sym ! = NULL ) {
if ( strnicmp ( From , Sym - > Value , strlen ( Sym - > Value ) ) = = 0 ) {
//
// Replace the string, then advance the pointers past the
// replaced strings
//
strcpy ( To , Sym - > Name ) ;
To + = strlen ( Sym - > Name ) ;
From + = strlen ( Sym - > Value ) ;
Replaced = TRUE ;
//
// Break from the while()
//
break ;
} else {
Sym = Sym - > Next ;
}
}
if ( ! Replaced ) {
From + + ;
To + + ;
}
}
//
// Null terminate, and return it
//
* To = 0 ;
if ( strlen ( StrCopy ) < StrSize ) {
strcpy ( Str , StrCopy ) ;
}
}
//
// Given a filename, try to find it along the include paths.
//
static
FILE *
FindFile (
INT8 * FileName ,
UINT32 FileNameLen
)
{
FILE * Fptr ;
STRING_LIST * List ;
STRING_LIST * SubDir ;
INT8 FullFileName [ MAX_PATH * 2 ] ;
//
// Traverse the list of paths and try to find the file
//
List = mGlobals . IncludePaths ;
while ( List ! = NULL ) {
//
// Put the path and filename together
//
if ( strlen ( List - > Str ) + strlen ( FileName ) + 1 > sizeof ( FullFileName ) ) {
Error (
__FILE__ ,
__LINE__ ,
0 ,
" application error " ,
" cannot concatenate '%s' + '%s' " ,
List - > Str ,
FileName
) ;
return NULL ;
}
//
// Append the filename to this include path and try to open the file.
//
strcpy ( FullFileName , List - > Str ) ;
strcat ( FullFileName , FileName ) ;
if ( ( Fptr = fopen ( FullFileName , " r " ) ) ! = NULL ) {
//
// Return the file name
//
if ( FileNameLen < = strlen ( FullFileName ) ) {
Error ( __FILE__ , __LINE__ , 0 , " application error " , " internal path name of insufficient length " ) ;
//
// fprintf (stdout, "File length > %d: %s\n", FileNameLen, FullFileName);
//
return NULL ;
}
strcpy ( FileName , FullFileName ) ;
return Fptr ;
}
//
// Didn't find it there. Now try this directory with every subdirectory
// the user specified on the command line
//
for ( SubDir = mGlobals . SubDirs ; SubDir ! = NULL ; SubDir = SubDir - > Next ) {
strcpy ( FullFileName , List - > Str ) ;
strcat ( FullFileName , SubDir - > Str ) ;
strcat ( FullFileName , FileName ) ;
if ( ( Fptr = fopen ( FullFileName , " r " ) ) ! = NULL ) {
//
// Return the file name
//
if ( FileNameLen < = strlen ( FullFileName ) ) {
Error ( __FILE__ , __LINE__ , 0 , " application error " , " internal path name of insufficient length " ) ;
return NULL ;
}
strcpy ( FileName , FullFileName ) ;
return Fptr ;
}
}
List = List - > Next ;
}
//
// Not found
//
return NULL ;
}
//
// Process the command-line arguments
//
static
STATUS
ProcessArgs (
int Argc ,
char * Argv [ ]
)
{
STRING_LIST * NewList ;
STRING_LIST * LastIncludePath ;
STRING_LIST * LastSourceFile ;
SYMBOL * Symbol ;
int Index ;
//
// Clear our globals
//
memset ( ( char * ) & mGlobals , 0 , sizeof ( mGlobals ) ) ;
mGlobals . NoDupes = TRUE ;
//
// Skip program name
//
Argc - - ;
Argv + + ;
2007-01-09 23:29:27 +01:00
if ( Argc = = 0 ) {
Usage ( ) ;
return STATUS_ERROR ;
}
if ( ( strcmp ( Argv [ 0 ] , " -h " ) = = 0 ) | | ( strcmp ( Argv [ 0 ] , " --help " ) = = 0 ) | |
( strcmp ( Argv [ 0 ] , " -? " ) = = 0 ) | | ( strcmp ( Argv [ 0 ] , " /? " ) = = 0 ) ) {
Usage ( ) ;
return STATUS_ERROR ;
}
if ( ( strcmp ( Argv [ 0 ] , " -V " ) = = 0 ) | | ( strcmp ( Argv [ 0 ] , " --version " ) = = 0 ) ) {
Version ( ) ;
return STATUS_ERROR ;
}
2006-05-15 19:25:39 +02:00
//
// Initialize locals
//
LastIncludePath = NULL ;
LastSourceFile = NULL ;
//
// Process until no more args
//
while ( Argc ) {
//
// -i path add include search path
//
if ( stricmp ( Argv [ 0 ] , " -i " ) = = 0 ) {
//
// check for one more arg
//
if ( Argc > 1 ) {
//
// Allocate memory for a new list element, fill it in, and
// add it to our list of include paths. Always make sure it
// has a "\" on the end of it.
//
NewList = malloc ( sizeof ( STRING_LIST ) ) ;
if ( NewList = = NULL ) {
Error ( __FILE__ , __LINE__ , 0 , " memory allocation failure " , NULL ) ;
return STATUS_ERROR ;
}
NewList - > Next = NULL ;
NewList - > Str = malloc ( strlen ( Argv [ 1 ] ) + 2 ) ;
if ( NewList - > Str = = NULL ) {
free ( NewList ) ;
Error ( __FILE__ , __LINE__ , 0 , " memory allocation failure " , NULL ) ;
return STATUS_ERROR ;
}
strcpy ( NewList - > Str , Argv [ 1 ] ) ;
2006-07-24 10:02:37 +02:00
if ( NewList - > Str [ strlen ( NewList - > Str ) - 1 ] ! = ' \\ ' & & NewList - > Str [ strlen ( NewList - > Str ) - 1 ] ! = ' / ' ) {
strcat ( NewList - > Str , " / " ) ;
2006-05-15 19:25:39 +02:00
}
//
// Add it to the end of the our list of include paths
//
if ( mGlobals . IncludePaths = = NULL ) {
mGlobals . IncludePaths = NewList ;
} else {
LastIncludePath - > Next = NewList ;
}
LastIncludePath = NewList ;
//
// fprintf (stdout, "Added path: %s\n", NewList->Str);
//
} else {
Error ( NULL , 0 , 0 , Argv [ 0 ] , " option requires an include path " ) ;
Usage ( ) ;
return STATUS_ERROR ;
}
Argc - - ;
Argv + + ;
} else if ( stricmp ( Argv [ 0 ] , " -f " ) = = 0 ) {
//
// Check for one more arg
//
if ( Argc > 1 ) {
//
// Allocate memory for a new list element, fill it in, and
// add it to our list of source files.
//
NewList = malloc ( sizeof ( STRING_LIST ) ) ;
if ( NewList = = NULL ) {
Error ( __FILE__ , __LINE__ , 0 , " memory allocation failure " , NULL ) ;
return STATUS_ERROR ;
}
NewList - > Next = NULL ;
//
// Allocate space to replace ".c" with ".obj", plus null termination
//
NewList - > Str = malloc ( strlen ( Argv [ 1 ] ) + 5 ) ;
if ( NewList - > Str = = NULL ) {
free ( NewList ) ;
Error ( __FILE__ , __LINE__ , 0 , " memory allocation failure " , NULL ) ;
return STATUS_ERROR ;
}
strcpy ( NewList - > Str , Argv [ 1 ] ) ;
if ( mGlobals . SourceFiles = = NULL ) {
mGlobals . SourceFiles = NewList ;
} else {
LastSourceFile - > Next = NewList ;
}
LastSourceFile = NewList ;
} else {
Error ( NULL , 0 , 0 , Argv [ 0 ] , " option requires a file name " ) ;
Usage ( ) ;
return STATUS_ERROR ;
}
//
// The C compiler first looks for #include files in the directory where
// the source file came from. Add the file's source directory to the
// list of include paths.
//
NewList = malloc ( sizeof ( STRING_LIST ) ) ;
if ( NewList = = NULL ) {
Error ( __FILE__ , __LINE__ , 0 , " memory allocation failure " , NULL ) ;
return STATUS_ERROR ;
}
NewList - > Next = NULL ;
NewList - > Str = malloc ( strlen ( Argv [ 1 ] ) + 3 ) ;
if ( NewList - > Str = = NULL ) {
free ( NewList ) ;
Error ( __FILE__ , __LINE__ , 0 , " memory allocation failure " , NULL ) ;
return STATUS_ERROR ;
}
strcpy ( NewList - > Str , Argv [ 1 ] ) ;
//
// Back up in the source file name to the last backslash and terminate after it.
//
2006-07-24 10:02:37 +02:00
for ( Index = strlen ( NewList - > Str ) - 1 ; ( Index > 0 ) & & ( NewList - > Str [ Index ] ! = ' \\ ' & & NewList - > Str [ Index ] ! = ' / ' ) ; Index - - )
2006-05-15 19:25:39 +02:00
;
if ( Index < 0 ) {
2006-07-24 10:02:37 +02:00
strcpy ( NewList - > Str , " ./ " ) ;
2006-05-15 19:25:39 +02:00
} else {
NewList - > Str [ Index + 1 ] = 0 ;
}
//
// Add it to the end of the our list of include paths
//
if ( mGlobals . IncludePaths = = NULL ) {
mGlobals . IncludePaths = NewList ;
} else {
LastIncludePath - > Next = NewList ;
}
if ( mGlobals . Verbose ) {
fprintf ( stdout , " Adding include path: %s \n " , NewList - > Str ) ;
}
LastIncludePath = NewList ;
Argc - - ;
Argv + + ;
} else if ( stricmp ( Argv [ 0 ] , " -s " ) = = 0 ) {
//
// -s subdir add subdirectory subdir to list of subdirecties to scan.
// Check for one more arg first.
//
if ( Argc > 1 ) {
//
// Allocate memory for a new list element, fill it in, and
// add it to our list of subdirectory include paths. Always
// make sure it has a "\" on the end of it.
//
NewList = malloc ( sizeof ( STRING_LIST ) ) ;
if ( NewList = = NULL ) {
Error ( __FILE__ , __LINE__ , 0 , " memory allocation failure " , NULL ) ;
return STATUS_ERROR ;
}
NewList - > Str = malloc ( strlen ( Argv [ 1 ] ) + 2 ) ;
if ( NewList - > Str = = NULL ) {
free ( NewList ) ;
Error ( __FILE__ , __LINE__ , 0 , " memory allocation failure " , NULL ) ;
return STATUS_ERROR ;
}
strcpy ( NewList - > Str , Argv [ 1 ] ) ;
2006-07-24 10:02:37 +02:00
if ( NewList - > Str [ strlen ( NewList - > Str ) - 1 ] ! = ' \\ ' & & NewList - > Str [ strlen ( NewList - > Str ) - 1 ] ! = ' / ' ) {
strcat ( NewList - > Str , " / " ) ;
2006-05-15 19:25:39 +02:00
}
NewList - > Next = mGlobals . SubDirs ;
mGlobals . SubDirs = NewList ;
} else {
Error ( NULL , 0 , 0 , Argv [ 0 ] , " option requires a subdirectory name " ) ;
Usage ( ) ;
return STATUS_ERROR ;
}
Argc - - ;
Argv + + ;
} else if ( stricmp ( Argv [ 0 ] , " -sub " ) = = 0 ) {
//
// -sub symname symvalue to do string substitution in the output
//
if ( Argc > 2 ) {
//
// Allocate memory for the symbol object
//
Symbol = malloc ( sizeof ( SYMBOL ) ) ;
if ( Symbol = = NULL ) {
Error ( __FILE__ , __LINE__ , 0 , " memory allocation failure " , NULL ) ;
return STATUS_ERROR ;
}
//
// Allocate memory for the symbol name and value, then save copies
//
Symbol - > Name = malloc ( strlen ( Argv [ 1 ] ) + 1 ) ;
if ( Symbol - > Name = = NULL ) {
free ( Symbol ) ;
Error ( __FILE__ , __LINE__ , 0 , " memory allocation failure " , NULL ) ;
return STATUS_ERROR ;
}
strcpy ( Symbol - > Name , Argv [ 1 ] ) ;
Symbol - > Value = malloc ( strlen ( Argv [ 2 ] ) + 1 ) ;
if ( Symbol - > Value = = NULL ) {
free ( Symbol - > Name ) ;
free ( Symbol ) ;
Error ( __FILE__ , __LINE__ , 0 , " memory allocation failure " , NULL ) ;
return STATUS_ERROR ;
}
strcpy ( Symbol - > Value , Argv [ 2 ] ) ;
//
// Add it to the list
//
Symbol - > Next = mGlobals . SymbolTable ;
mGlobals . SymbolTable = Symbol ;
} else {
Error ( NULL , 0 , 0 , Argv [ 0 ] , " option requires a symbol name and value " ) ;
Usage ( ) ;
return STATUS_ERROR ;
}
//
// Skip over args
//
Argc - = 2 ;
Argv + = 2 ;
} else if ( stricmp ( Argv [ 0 ] , " -nosystem " ) = = 0 ) {
mGlobals . NoSystem = TRUE ;
} else if ( stricmp ( Argv [ 0 ] , " -nodupes " ) = = 0 ) {
mGlobals . NoDupes = TRUE ;
} else if ( stricmp ( Argv [ 0 ] , " -nodups " ) = = 0 ) {
mGlobals . NoDupes = TRUE ;
} else if ( stricmp ( Argv [ 0 ] , " -target " ) = = 0 ) {
//
// -target TargetFileName - Target object file (only one allowed right
// now) is TargetFileName rather than SourceFile.obj
//
if ( Argc > 1 ) {
strcpy ( mGlobals . TargetFileName , Argv [ 1 ] ) ;
} else {
Error ( NULL , 0 , 0 , Argv [ 0 ] , " option requires a target file name " ) ;
Usage ( ) ;
return STATUS_ERROR ;
}
Argc - - ;
Argv + + ;
} else if ( stricmp ( Argv [ 0 ] , " -usesumdeps " ) = = 0 ) {
//
// -usesumdeps Path - if we find an included file xxx.h, and file
// Path/xxx.dep exists, list Path/xxx.dep as a dependency rather than
// xxx.h and don't parse xxx.h. This allows you to create a dependency
// file for a commonly included file, and have its dependency file updated
// only if its included files are updated. Then anyone else including this
// common include file can simply have a dependency on that file's .dep file
// rather than on all the files included by it. Confusing enough?
//
mGlobals . UseSumDeps = 1 ;
if ( Argc > 1 ) {
strcpy ( mGlobals . SumDepsPath , Argv [ 1 ] ) ;
//
// Add slash on end if not there
//
2006-07-24 10:02:37 +02:00
if ( mGlobals . SumDepsPath [ strlen ( mGlobals . SumDepsPath ) - 1 ] ! = ' \\ ' & & mGlobals . SumDepsPath [ strlen ( mGlobals . SumDepsPath ) - 1 ] ! = ' / ' ) {
strcat ( mGlobals . SumDepsPath , " / " ) ;
2006-05-15 19:25:39 +02:00
}
} else {
Error ( NULL , 0 , 0 , Argv [ 0 ] , " option requires path to summary dependency files " ) ;
Usage ( ) ;
return STATUS_ERROR ;
}
Argc - - ;
Argv + + ;
} else if ( stricmp ( Argv [ 0 ] , " -o " ) = = 0 ) {
//
// -o OutputFileName - specify an output filename for dependency list
// check for one more arg
//
if ( Argc > 1 ) {
//
// Try to open the file
//
if ( ( mGlobals . OutFptr = fopen ( Argv [ 1 ] , " w " ) ) = = NULL ) {
Error ( NULL , 0 , 0 , Argv [ 1 ] , " could not open file for writing " ) ;
return STATUS_ERROR ;
}
mGlobals . OutFileName = Argv [ 1 ] ;
} else {
Error ( NULL , 0 , 0 , Argv [ 0 ] , " option requires output file name " ) ;
Usage ( ) ;
return STATUS_ERROR ;
}
Argc - - ;
Argv + + ;
} else if ( stricmp ( Argv [ 0 ] , " -v " ) = = 0 ) {
mGlobals . Verbose = TRUE ;
} else if ( stricmp ( Argv [ 0 ] , " -neverfail " ) = = 0 ) {
mGlobals . NeverFail = TRUE ;
} else if ( stricmp ( Argv [ 0 ] , " -q " ) = = 0 ) {
mGlobals . QuietMode = TRUE ;
} else if ( stricmp ( Argv [ 0 ] , " -ignorenotfound " ) = = 0 ) {
mGlobals . IgnoreNotFound = TRUE ;
} else if ( ( stricmp ( Argv [ 0 ] , " -h " ) = = 0 ) | | ( strcmp ( Argv [ 0 ] , " -? " ) = = 0 ) ) {
Usage ( ) ;
return STATUS_ERROR ;
} else {
Error ( NULL , 0 , 0 , Argv [ 0 ] , " unrecognized option " ) ;
Usage ( ) ;
return STATUS_ERROR ;
}
Argc - - ;
Argv + + ;
}
//
// Had to specify at least one source file
//
if ( mGlobals . SourceFiles = = NULL ) {
Error ( NULL , 0 , 0 , " must specify one source file name " , NULL ) ;
Usage ( ) ;
return STATUS_ERROR ;
}
//
// Assume output to stdout if not specified
//
if ( mGlobals . OutFptr = = NULL ) {
mGlobals . OutFptr = stdout ;
}
return STATUS_SUCCESS ;
}
//
// Free the global string lists we allocated memory for
//
static
void
FreeLists (
VOID
)
{
STRING_LIST * Temp ;
SYMBOL * NextSym ;
//
// printf ("Free lists.....");
//
// Traverse the include paths, freeing each
// printf ("freeing include paths\n");
//
while ( mGlobals . IncludePaths ! = NULL ) {
Temp = mGlobals . IncludePaths - > Next ;
//
// printf ("Freeing include path string '%s' at 0x%X\n",
// mGlobals.IncludePaths->Str, (int)(mGlobals.IncludePaths->Str));
//
free ( mGlobals . IncludePaths - > Str ) ;
//
// printf ("Freeing include path object at 0x%X\n", (int)(mGlobals.IncludePaths));
//
free ( mGlobals . IncludePaths ) ;
mGlobals . IncludePaths = Temp ;
}
//
// Traverse the source files, freeing each
//
while ( mGlobals . SourceFiles ! = NULL ) {
Temp = mGlobals . SourceFiles - > Next ;
free ( mGlobals . SourceFiles - > Str ) ;
free ( mGlobals . SourceFiles ) ;
mGlobals . SourceFiles = Temp ;
}
//
// Traverse the subdirectory list, freeing each
//
while ( mGlobals . SubDirs ! = NULL ) {
Temp = mGlobals . SubDirs - > Next ;
free ( mGlobals . SubDirs - > Str ) ;
free ( mGlobals . SubDirs ) ;
mGlobals . SubDirs = Temp ;
}
//
// Free the symbol table
//
while ( mGlobals . SymbolTable ! = NULL ) {
NextSym = mGlobals . SymbolTable - > Next ;
free ( mGlobals . SymbolTable - > Name ) ;
free ( mGlobals . SymbolTable - > Value ) ;
mGlobals . SymbolTable = NextSym ;
}
//
// printf ("done\n");
//
}
2007-01-09 23:29:27 +01:00
static
void
Version (
void
)
/*++
Routine Description :
Displays the standard utility information to SDTOUT
Arguments :
None
Returns :
None
- - */
{
printf ( " %s v%d.%d -Utility for generating file dependency lists for files in a given directory. \n " , UTILITY_NAME , UTILITY_MAJOR_VERSION , UTILITY_MINOR_VERSION ) ;
printf ( " Copyright (c) 1999-2007 Intel Corporation. All rights reserved. \n " ) ;
}
2006-05-15 19:25:39 +02:00
static
void
Usage (
VOID
)
/*++
Routine Description :
Print usage information for this utility .
Arguments :
None .
Returns :
Nothing .
- - */
{
int Index ;
static const char * Str [ ] = {
UTILITY_NAME " -- make dependencies " ,
" Usage: MakeDeps [options] " ,
" Options include: " ,
2007-01-09 23:29:27 +01:00
" -h,--help,-?,/? display help messages " ,
" -V,--version display version information " ,
2006-05-15 19:25:39 +02:00
" -f SourceFile add SourceFile to list of files to scan " ,
" -i IncludePath add IncludePath to list of search paths " ,
" -o OutputFile write output dependencies to OutputFile " ,
" -s SubDir for each IncludePath, also search IncludePath \\ SubDir " ,
" -v for verbose output " ,
" -ignorenotfound don't warn for files not found " ,
" -target Target for single SourceFile, target is Target, not SourceFile.obj " ,
" -q quiet mode to not report files not found if ignored " ,
" -sub sym str replace all occurrances of 'str' with 'sym' in the output " ,
" -nosystem not process system <include> files " ,
" -neverfail always return a success return code " ,
//
// " -nodupes keep track of include files, don't rescan duplicates",
//
" -usesumdeps path use summary dependency files in 'path' directory. " ,
" " ,
NULL
} ;
2007-01-09 23:29:27 +01:00
Version ( ) ;
2006-05-15 19:25:39 +02:00
for ( Index = 0 ; Str [ Index ] ! = NULL ; Index + + ) {
fprintf ( stdout , " %s \n " , Str [ Index ] ) ;
}
}