Set svn:eol-style=native
[reactos.git] / reactos / tools / rbuild / automaticdependency.cpp
index 4e33bec..b4efa2c 100644 (file)
-#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;
+                       }
+               }
+       }
+}