-#include "pch.h"\r
-#include <assert.h>\r
-\r
-#include "rbuild.h"\r
-\r
-/* Read at most this amount of bytes from each file and assume that all #includes are located within this block */\r
-#define MAX_BYTES_TO_READ 4096\r
-\r
-using std::string;\r
-using std::vector;\r
-using std::map;\r
-\r
-SourceFile::SourceFile ( AutomaticDependency* automaticDependency,\r
- Module& module,\r
- const string& filename,\r
- SourceFile* parent,\r
- bool isNonAutomaticDependency )\r
- : automaticDependency ( automaticDependency ),\r
- module ( module ),\r
- filename ( filename ),\r
- isNonAutomaticDependency ( isNonAutomaticDependency ),\r
- youngestLastWriteTime ( 0 )\r
-{\r
- if ( parent != NULL )\r
- parents.push_back ( parent );\r
- GetDirectoryAndFilenameParts ();\r
-}\r
-\r
-void\r
-SourceFile::GetDirectoryAndFilenameParts ()\r
-{\r
- size_t index = filename.find_last_of ( CSEP );\r
- if ( index != string::npos )\r
- {\r
- directoryPart = filename.substr ( 0, index );\r
- filenamePart = filename.substr ( index + 1, filename.length () - index );\r
- }\r
- else\r
- {\r
- directoryPart = "";\r
- filenamePart = filename;\r
- }\r
-}\r
-\r
-void\r
-SourceFile::Close ()\r
-{\r
- buf.resize ( 0 );\r
- p = end = NULL;\r
-}\r
-\r
-void\r
-SourceFile::Open ()\r
-{\r
- struct stat statbuf;\r
-\r
- Close ();\r
- FILE* f = fopen ( filename.c_str (), "rb" );\r
- if ( !f )\r
- throw FileNotFoundException ( filename );\r
-\r
- if ( fstat ( fileno ( f ), &statbuf ) != 0 )\r
- {\r
- fclose ( f );\r
- throw AccessDeniedException ( filename );\r
- }\r
- lastWriteTime = statbuf.st_mtime;\r
-\r
- unsigned long len = (unsigned long) filelen ( f );\r
- if ( len > MAX_BYTES_TO_READ )\r
- len = MAX_BYTES_TO_READ;\r
- buf.resize ( len );\r
- fread ( &buf[0], 1, len, f );\r
- fclose ( f );\r
- p = buf.c_str ();\r
- end = p + len;\r
-}\r
-\r
-void\r
-SourceFile::SkipWhitespace ()\r
-{\r
- while ( p < end && isspace ( *p ))\r
- p++;\r
-}\r
-\r
-bool\r
-SourceFile::ReadInclude ( string& filename,\r
- bool& includeNext)\r
-{\r
- while ( p < end )\r
- {\r
- if ( ( *p == '#') && ( end - p > 13 ) )\r
- {\r
- bool include = false;\r
- p++;\r
- SkipWhitespace ();\r
- if ( strncmp ( p, "include ", 8 ) == 0 )\r
- {\r
- p += 8;\r
- includeNext = false;\r
- include = true;\r
- }\r
- if ( strncmp ( p, "include_next ", 13 ) == 0 )\r
- {\r
- p += 13;\r
- includeNext = true;\r
- include = true;\r
- }\r
- \r
- if ( include )\r
- {\r
- SkipWhitespace ();\r
- if ( p < end && *p == '<' || *p == '"' )\r
- {\r
- p++;\r
- filename.resize ( MAX_PATH );\r
- int i = 0;\r
- while ( p < end && *p != '>' && *p != '"' && *p != '\n' )\r
- filename[i++] = *p++;\r
- filename.resize ( i );\r
- return true;\r
- }\r
- }\r
- }\r
- p++;\r
- }\r
- filename = "";\r
- includeNext = false;\r
- return false;\r
-}\r
-\r
-bool\r
-SourceFile::IsParentOf ( const SourceFile* parent,\r
- const SourceFile* child )\r
-{\r
- size_t i;\r
- for ( i = 0; i < child->parents.size (); i++ )\r
- {\r
- if ( child->parents[i] != NULL )\r
- {\r
- if ( child->parents[i] == parent )\r
- return true;\r
- }\r
- }\r
- for ( i = 0; i < child->parents.size (); i++ )\r
- {\r
- if ( child->parents[i] != NULL )\r
- {\r
- if ( IsParentOf ( parent,\r
- child->parents[i] ) )\r
- return true;\r
- }\r
- }\r
- return false;\r
-}\r
-\r
-bool\r
-SourceFile::IsIncludedFrom ( const string& normalizedFilename )\r
-{\r
- if ( normalizedFilename == filename )\r
- return true;\r
- \r
- SourceFile* sourceFile = automaticDependency->RetrieveFromCache ( normalizedFilename );\r
- if ( sourceFile == NULL )\r
- return false;\r
-\r
- return IsParentOf ( sourceFile,\r
- this );\r
-}\r
-\r
-SourceFile*\r
-SourceFile::GetParentSourceFile ()\r
-{\r
- if ( isNonAutomaticDependency )\r
- return NULL;\r
- return this;\r
-}\r
-\r
-bool\r
-SourceFile::CanProcessFile ( const string& extension )\r
-{\r
- if ( extension == ".h" || extension == ".H" )\r
- return true;\r
- if ( extension == ".c" || extension == ".C" )\r
- return true;\r
- if ( extension == ".cpp" || extension == ".CPP" )\r
- return true;\r
- if ( extension == ".rc" || extension == ".RC" )\r
- return true;\r
- if ( extension == ".s" || extension == ".S" )\r
- return true;\r
- return false;\r
-}\r
-\r
-SourceFile*\r
-SourceFile::ParseFile ( const string& normalizedFilename )\r
-{\r
- string extension = GetExtension ( normalizedFilename );\r
- if ( CanProcessFile ( extension ) )\r
- {\r
- if ( IsIncludedFrom ( normalizedFilename ) )\r
- return NULL;\r
- \r
- SourceFile* sourceFile = automaticDependency->RetrieveFromCacheOrParse ( module,\r
- normalizedFilename,\r
- GetParentSourceFile () );\r
- return sourceFile;\r
- }\r
- return NULL;\r
-}\r
-\r
-void\r
-SourceFile::Parse ()\r
-{\r
- Open ();\r
- while ( p < end )\r
- {\r
- string includedFilename ( "" );\r
- \r
- bool includeNext;\r
- while ( ReadInclude ( includedFilename,\r
- includeNext ) )\r
- {\r
- string resolvedFilename ( "" );\r
- bool locatedFile = automaticDependency->LocateIncludedFile ( this,\r
- module,\r
- includedFilename,\r
- includeNext,\r
- resolvedFilename );\r
- if ( locatedFile )\r
- {\r
- SourceFile* sourceFile = ParseFile ( resolvedFilename );\r
- if ( sourceFile != NULL )\r
- files.push_back ( sourceFile );\r
- }\r
- }\r
- p++;\r
- }\r
- Close ();\r
-}\r
-\r
-string\r
-SourceFile::Location () const\r
-{\r
- int line = 1;\r
- const char* end_of_line = strchr ( buf.c_str (), '\n' );\r
- while ( end_of_line && end_of_line < p )\r
- {\r
- ++line;\r
- end_of_line = strchr ( end_of_line + 1, '\n' );\r
- }\r
- return ssprintf ( "%s(%i)",\r
- filename.c_str (),\r
- line );\r
-}\r
-\r
-\r
-AutomaticDependency::AutomaticDependency ( const Project& project )\r
- : project ( project )\r
-{\r
-}\r
-\r
-AutomaticDependency::~AutomaticDependency ()\r
-{\r
- std::map<std::string, SourceFile*>::iterator theIterator;\r
- for ( theIterator = sourcefile_map.begin (); theIterator != sourcefile_map.end (); theIterator++ )\r
- delete theIterator->second;\r
-}\r
-\r
-void\r
-AutomaticDependency::Process ()\r
-{\r
- for ( size_t i = 0; i < project.modules.size (); i++ )\r
- ProcessModule ( *project.modules[i] );\r
-}\r
-\r
-void\r
-AutomaticDependency::ProcessModule ( Module& module )\r
-{\r
- const vector<File*>& files = module.non_if_data.files;\r
- for ( size_t i = 0; i < files.size (); i++ )\r
- ProcessFile ( module, *files[i] );\r
-}\r
-\r
-void\r
-AutomaticDependency::ProcessFile ( Module& module,\r
- const File& file )\r
-{\r
- string normalizedFilename = NormalizeFilename ( file.name );\r
- RetrieveFromCacheOrParse ( module,\r
- normalizedFilename,\r
- NULL );\r
-}\r
-\r
-bool\r
-AutomaticDependency::LocateIncludedFile ( const string& directory,\r
- const string& includedFilename,\r
- string& resolvedFilename )\r
-{\r
- string normalizedFilename = NormalizeFilename ( directory + SSEP + includedFilename );\r
- FILE* f = fopen ( normalizedFilename.c_str (), "rb" );\r
- if ( f != NULL )\r
- {\r
- fclose ( f );\r
- resolvedFilename = normalizedFilename;\r
- return true;\r
- }\r
- resolvedFilename = "";\r
- return false;\r
-}\r
-\r
-string\r
-AutomaticDependency::GetFilename ( const string& filename )\r
-{\r
- size_t index = filename.find_last_of ( CSEP );\r
- if (index == string::npos)\r
- return filename;\r
- else\r
- return filename.substr ( index + 1,\r
- filename.length () - index - 1);\r
-}\r
-\r
-bool\r
-AutomaticDependency::LocateIncludedFile ( SourceFile* sourceFile,\r
- Module& module,\r
- const string& includedFilename,\r
- bool includeNext,\r
- string& resolvedFilename )\r
-{\r
- size_t i, j;\r
- const vector<Include*>* pincludes;\r
- for ( i = 0; i < 2; i++ )\r
- {\r
- if ( !i )\r
- pincludes = &module.non_if_data.includes;\r
- else\r
- pincludes = &module.project.non_if_data.includes;\r
- const vector<Include*>& includes = *pincludes;\r
- for ( j = 0; j < includes.size (); j++ )\r
- {\r
- Include& include = *includes[j];\r
- if ( LocateIncludedFile ( include.directory,\r
- includedFilename,\r
- resolvedFilename ) )\r
- {\r
- if ( includeNext && stricmp ( resolvedFilename.c_str (),\r
- sourceFile->filename.c_str () ) == 0 )\r
- continue;\r
- return true;\r
- }\r
- }\r
- }\r
-\r
- resolvedFilename = "";\r
- return false;\r
-}\r
-\r
-SourceFile*\r
-AutomaticDependency::RetrieveFromCacheOrParse ( Module& module,\r
- const string& filename,\r
- SourceFile* parentSourceFile )\r
-{\r
- SourceFile* sourceFile = sourcefile_map[filename];\r
- if ( sourceFile == NULL )\r
- {\r
- sourceFile = new SourceFile ( this,\r
- module,\r
- filename,\r
- parentSourceFile,\r
- false );\r
- sourcefile_map[filename] = sourceFile;\r
- sourceFile->Parse ();\r
- }\r
- else if ( parentSourceFile != NULL )\r
- sourceFile->parents.push_back ( parentSourceFile );\r
- return sourceFile;\r
-}\r
-\r
-SourceFile*\r
-AutomaticDependency::RetrieveFromCache ( const string& filename )\r
-{\r
- return sourcefile_map[filename];\r
-}\r
-\r
-void\r
-AutomaticDependency::CheckAutomaticDependencies ( bool verbose )\r
-{\r
- struct utimbuf timebuf;\r
- for ( size_t mi = 0; mi < project.modules.size (); mi++ )\r
- {\r
- const vector<File*>& files = project.modules[mi]->non_if_data.files;\r
- for ( size_t fi = 0; fi < files.size (); fi++ )\r
- {\r
- File& file = *files[fi];\r
- string normalizedFilename = NormalizeFilename ( file.name );\r
-\r
- SourceFile* sourceFile = RetrieveFromCache ( normalizedFilename );\r
- if ( sourceFile != NULL )\r
- {\r
- CheckAutomaticDependenciesForFile ( sourceFile );\r
- assert ( sourceFile->youngestLastWriteTime != 0 );\r
- if ( sourceFile->youngestLastWriteTime > sourceFile->lastWriteTime )\r
- {\r
- if ( verbose )\r
- {\r
- printf ( "Marking %s for rebuild due to younger file %s\n",\r
- sourceFile->filename.c_str (),\r
- sourceFile->youngestFile->filename.c_str () );\r
- }\r
- timebuf.actime = sourceFile->youngestLastWriteTime;\r
- timebuf.modtime = sourceFile->youngestLastWriteTime;\r
- utime ( sourceFile->filename.c_str (),\r
- &timebuf );\r
- }\r
- }\r
- }\r
- }\r
-}\r
-\r
-void\r
-AutomaticDependency::CheckAutomaticDependenciesForFile ( SourceFile* sourceFile )\r
-{\r
- if ( sourceFile->youngestLastWriteTime > 0 )\r
- return;\r
-\r
- if ( sourceFile->files.size () == 0 )\r
- {\r
- sourceFile->youngestLastWriteTime = sourceFile->lastWriteTime;\r
- sourceFile->youngestFile = sourceFile;\r
- return;\r
- }\r
-\r
- for ( size_t i = 0; i < sourceFile->files.size (); i++ )\r
- {\r
- SourceFile* childSourceFile = sourceFile->files[i];\r
- \r
- CheckAutomaticDependenciesForFile ( childSourceFile );\r
- if ( ( childSourceFile->youngestLastWriteTime > sourceFile->youngestLastWriteTime ) ||\r
- ( childSourceFile->lastWriteTime > sourceFile->youngestLastWriteTime ) )\r
- {\r
- if ( childSourceFile->youngestLastWriteTime > childSourceFile->lastWriteTime )\r
- {\r
- sourceFile->youngestLastWriteTime = childSourceFile->youngestLastWriteTime;\r
- sourceFile->youngestFile = childSourceFile->youngestFile;\r
- }\r
- else\r
- {\r
- sourceFile->youngestLastWriteTime = childSourceFile->lastWriteTime;\r
- sourceFile->youngestFile = childSourceFile;\r
- }\r
- }\r
- }\r
-}\r
+#include "pch.h"
+#include <assert.h>
+
+#include "rbuild.h"
+
+/* Read at most this amount of bytes from each file and assume that all #includes are located within this block */
+#define MAX_BYTES_TO_READ 4096
+
+using std::string;
+using std::vector;
+using std::map;
+
+SourceFile::SourceFile ( AutomaticDependency* automaticDependency,
+ Module& module,
+ const string& filename,
+ SourceFile* parent,
+ bool isNonAutomaticDependency )
+ : automaticDependency ( automaticDependency ),
+ module ( module ),
+ filename ( filename ),
+ isNonAutomaticDependency ( isNonAutomaticDependency ),
+ youngestLastWriteTime ( 0 )
+{
+ if ( parent != NULL )
+ parents.push_back ( parent );
+ GetDirectoryAndFilenameParts ();
+}
+
+void
+SourceFile::GetDirectoryAndFilenameParts ()
+{
+ size_t index = filename.find_last_of ( CSEP );
+ if ( index != string::npos )
+ {
+ directoryPart = filename.substr ( 0, index );
+ filenamePart = filename.substr ( index + 1, filename.length () - index );
+ }
+ else
+ {
+ directoryPart = "";
+ filenamePart = filename;
+ }
+}
+
+void
+SourceFile::Close ()
+{
+ buf.resize ( 0 );
+ p = end = NULL;
+}
+
+void
+SourceFile::Open ()
+{
+ struct stat statbuf;
+
+ Close ();
+ FILE* f = fopen ( filename.c_str (), "rb" );
+ if ( !f )
+ throw FileNotFoundException ( filename );
+
+ if ( fstat ( fileno ( f ), &statbuf ) != 0 )
+ {
+ fclose ( f );
+ throw AccessDeniedException ( filename );
+ }
+ lastWriteTime = statbuf.st_mtime;
+
+ unsigned long len = (unsigned long) filelen ( f );
+ if ( len > MAX_BYTES_TO_READ )
+ len = MAX_BYTES_TO_READ;
+ buf.resize ( len );
+ fread ( &buf[0], 1, len, f );
+ fclose ( f );
+ p = buf.c_str ();
+ end = p + len;
+}
+
+void
+SourceFile::SkipWhitespace ()
+{
+ while ( p < end && isspace ( *p ))
+ p++;
+}
+
+bool
+SourceFile::ReadInclude ( string& filename,
+ bool& includeNext)
+{
+ while ( p < end )
+ {
+ if ( ( *p == '#') && ( end - p > 13 ) )
+ {
+ bool include = false;
+ p++;
+ SkipWhitespace ();
+ if ( strncmp ( p, "include ", 8 ) == 0 )
+ {
+ p += 8;
+ includeNext = false;
+ include = true;
+ }
+ if ( strncmp ( p, "include_next ", 13 ) == 0 )
+ {
+ p += 13;
+ includeNext = true;
+ include = true;
+ }
+
+ if ( include )
+ {
+ SkipWhitespace ();
+ if ( p < end && *p == '<' || *p == '"' )
+ {
+ p++;
+ filename.resize ( MAX_PATH );
+ int i = 0;
+ while ( p < end && *p != '>' && *p != '"' && *p != '\n' )
+ filename[i++] = *p++;
+ filename.resize ( i );
+ return true;
+ }
+ }
+ }
+ p++;
+ }
+ filename = "";
+ includeNext = false;
+ return false;
+}
+
+bool
+SourceFile::IsParentOf ( const SourceFile* parent,
+ const SourceFile* child )
+{
+ size_t i;
+ for ( i = 0; i < child->parents.size (); i++ )
+ {
+ if ( child->parents[i] != NULL )
+ {
+ if ( child->parents[i] == parent )
+ return true;
+ }
+ }
+ for ( i = 0; i < child->parents.size (); i++ )
+ {
+ if ( child->parents[i] != NULL )
+ {
+ if ( IsParentOf ( parent,
+ child->parents[i] ) )
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+SourceFile::IsIncludedFrom ( const string& normalizedFilename )
+{
+ if ( normalizedFilename == filename )
+ return true;
+
+ SourceFile* sourceFile = automaticDependency->RetrieveFromCache ( normalizedFilename );
+ if ( sourceFile == NULL )
+ return false;
+
+ return IsParentOf ( sourceFile,
+ this );
+}
+
+SourceFile*
+SourceFile::GetParentSourceFile ()
+{
+ if ( isNonAutomaticDependency )
+ return NULL;
+ return this;
+}
+
+bool
+SourceFile::CanProcessFile ( const string& extension )
+{
+ if ( extension == ".h" || extension == ".H" )
+ return true;
+ if ( extension == ".c" || extension == ".C" )
+ return true;
+ if ( extension == ".cpp" || extension == ".CPP" )
+ return true;
+ if ( extension == ".rc" || extension == ".RC" )
+ return true;
+ if ( extension == ".s" || extension == ".S" )
+ return true;
+ return false;
+}
+
+SourceFile*
+SourceFile::ParseFile ( const string& normalizedFilename )
+{
+ string extension = GetExtension ( normalizedFilename );
+ if ( CanProcessFile ( extension ) )
+ {
+ if ( IsIncludedFrom ( normalizedFilename ) )
+ return NULL;
+
+ SourceFile* sourceFile = automaticDependency->RetrieveFromCacheOrParse ( module,
+ normalizedFilename,
+ GetParentSourceFile () );
+ return sourceFile;
+ }
+ return NULL;
+}
+
+void
+SourceFile::Parse ()
+{
+ Open ();
+ while ( p < end )
+ {
+ string includedFilename ( "" );
+
+ bool includeNext;
+ while ( ReadInclude ( includedFilename,
+ includeNext ) )
+ {
+ string resolvedFilename ( "" );
+ bool locatedFile = automaticDependency->LocateIncludedFile ( this,
+ module,
+ includedFilename,
+ includeNext,
+ resolvedFilename );
+ if ( locatedFile )
+ {
+ SourceFile* sourceFile = ParseFile ( resolvedFilename );
+ if ( sourceFile != NULL )
+ files.push_back ( sourceFile );
+ }
+ }
+ p++;
+ }
+ Close ();
+}
+
+string
+SourceFile::Location () const
+{
+ int line = 1;
+ const char* end_of_line = strchr ( buf.c_str (), '\n' );
+ while ( end_of_line && end_of_line < p )
+ {
+ ++line;
+ end_of_line = strchr ( end_of_line + 1, '\n' );
+ }
+ return ssprintf ( "%s(%i)",
+ filename.c_str (),
+ line );
+}
+
+
+AutomaticDependency::AutomaticDependency ( const Project& project )
+ : project ( project )
+{
+}
+
+AutomaticDependency::~AutomaticDependency ()
+{
+ std::map<std::string, SourceFile*>::iterator theIterator;
+ for ( theIterator = sourcefile_map.begin (); theIterator != sourcefile_map.end (); theIterator++ )
+ delete theIterator->second;
+}
+
+void
+AutomaticDependency::Process ()
+{
+ for ( size_t i = 0; i < project.modules.size (); i++ )
+ ProcessModule ( *project.modules[i] );
+}
+
+void
+AutomaticDependency::ProcessModule ( Module& module )
+{
+ const vector<File*>& files = module.non_if_data.files;
+ for ( size_t i = 0; i < files.size (); i++ )
+ ProcessFile ( module, *files[i] );
+}
+
+void
+AutomaticDependency::ProcessFile ( Module& module,
+ const File& file )
+{
+ string normalizedFilename = NormalizeFilename ( file.name );
+ RetrieveFromCacheOrParse ( module,
+ normalizedFilename,
+ NULL );
+}
+
+bool
+AutomaticDependency::LocateIncludedFile ( const string& directory,
+ const string& includedFilename,
+ string& resolvedFilename )
+{
+ string normalizedFilename = NormalizeFilename ( directory + SSEP + includedFilename );
+ FILE* f = fopen ( normalizedFilename.c_str (), "rb" );
+ if ( f != NULL )
+ {
+ fclose ( f );
+ resolvedFilename = normalizedFilename;
+ return true;
+ }
+ resolvedFilename = "";
+ return false;
+}
+
+string
+AutomaticDependency::GetFilename ( const string& filename )
+{
+ size_t index = filename.find_last_of ( CSEP );
+ if (index == string::npos)
+ return filename;
+ else
+ return filename.substr ( index + 1,
+ filename.length () - index - 1);
+}
+
+bool
+AutomaticDependency::LocateIncludedFile ( SourceFile* sourceFile,
+ Module& module,
+ const string& includedFilename,
+ bool includeNext,
+ string& resolvedFilename )
+{
+ size_t i, j;
+ const vector<Include*>* pincludes;
+ for ( i = 0; i < 2; i++ )
+ {
+ if ( !i )
+ pincludes = &module.non_if_data.includes;
+ else
+ pincludes = &module.project.non_if_data.includes;
+ const vector<Include*>& includes = *pincludes;
+ for ( j = 0; j < includes.size (); j++ )
+ {
+ Include& include = *includes[j];
+ if ( LocateIncludedFile ( include.directory,
+ includedFilename,
+ resolvedFilename ) )
+ {
+ if ( includeNext && stricmp ( resolvedFilename.c_str (),
+ sourceFile->filename.c_str () ) == 0 )
+ continue;
+ return true;
+ }
+ }
+ }
+
+ resolvedFilename = "";
+ return false;
+}
+
+SourceFile*
+AutomaticDependency::RetrieveFromCacheOrParse ( Module& module,
+ const string& filename,
+ SourceFile* parentSourceFile )
+{
+ SourceFile* sourceFile = sourcefile_map[filename];
+ if ( sourceFile == NULL )
+ {
+ sourceFile = new SourceFile ( this,
+ module,
+ filename,
+ parentSourceFile,
+ false );
+ sourcefile_map[filename] = sourceFile;
+ sourceFile->Parse ();
+ }
+ else if ( parentSourceFile != NULL )
+ sourceFile->parents.push_back ( parentSourceFile );
+ return sourceFile;
+}
+
+SourceFile*
+AutomaticDependency::RetrieveFromCache ( const string& filename )
+{
+ return sourcefile_map[filename];
+}
+
+void
+AutomaticDependency::CheckAutomaticDependencies ( bool verbose )
+{
+ struct utimbuf timebuf;
+ for ( size_t mi = 0; mi < project.modules.size (); mi++ )
+ {
+ const vector<File*>& files = project.modules[mi]->non_if_data.files;
+ for ( size_t fi = 0; fi < files.size (); fi++ )
+ {
+ File& file = *files[fi];
+ string normalizedFilename = NormalizeFilename ( file.name );
+
+ SourceFile* sourceFile = RetrieveFromCache ( normalizedFilename );
+ if ( sourceFile != NULL )
+ {
+ CheckAutomaticDependenciesForFile ( sourceFile );
+ assert ( sourceFile->youngestLastWriteTime != 0 );
+ if ( sourceFile->youngestLastWriteTime > sourceFile->lastWriteTime )
+ {
+ if ( verbose )
+ {
+ printf ( "Marking %s for rebuild due to younger file %s\n",
+ sourceFile->filename.c_str (),
+ sourceFile->youngestFile->filename.c_str () );
+ }
+ timebuf.actime = sourceFile->youngestLastWriteTime;
+ timebuf.modtime = sourceFile->youngestLastWriteTime;
+ utime ( sourceFile->filename.c_str (),
+ &timebuf );
+ }
+ }
+ }
+ }
+}
+
+void
+AutomaticDependency::CheckAutomaticDependenciesForFile ( SourceFile* sourceFile )
+{
+ if ( sourceFile->youngestLastWriteTime > 0 )
+ return;
+
+ if ( sourceFile->files.size () == 0 )
+ {
+ sourceFile->youngestLastWriteTime = sourceFile->lastWriteTime;
+ sourceFile->youngestFile = sourceFile;
+ return;
+ }
+
+ for ( size_t i = 0; i < sourceFile->files.size (); i++ )
+ {
+ SourceFile* childSourceFile = sourceFile->files[i];
+
+ CheckAutomaticDependenciesForFile ( childSourceFile );
+ if ( ( childSourceFile->youngestLastWriteTime > sourceFile->youngestLastWriteTime ) ||
+ ( childSourceFile->lastWriteTime > sourceFile->youngestLastWriteTime ) )
+ {
+ if ( childSourceFile->youngestLastWriteTime > childSourceFile->lastWriteTime )
+ {
+ sourceFile->youngestLastWriteTime = childSourceFile->youngestLastWriteTime;
+ sourceFile->youngestFile = childSourceFile->youngestFile;
+ }
+ else
+ {
+ sourceFile->youngestLastWriteTime = childSourceFile->lastWriteTime;
+ sourceFile->youngestFile = childSourceFile;
+ }
+ }
+ }
+}