Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r79429 - trunk/tools/build/v2/engine
From: jurko.gospodnetic_at_[hidden]
Date: 2012-07-11 17:42:52


Author: jurko
Date: 2012-07-11 17:42:51 EDT (Wed, 11 Jul 2012)
New Revision: 79429
URL: http://svn.boost.org/trac/boost/changeset/79429

Log:
Booat Jam code cleanup - synchronized filent.c & fileunix.c OS specific implementation modules. Extracted shared functionality to filesys.c. Updated related descriptive function & module comments. Added missing copyright comment for the filesys.c module.
Text files modified:
   trunk/tools/build/v2/engine/filent.c | 318 ++++++++++++++++-----------------------
   trunk/tools/build/v2/engine/filesys.c | 255 +++++++++++++++++++++++++++++--
   trunk/tools/build/v2/engine/filesys.h | 37 +--
   trunk/tools/build/v2/engine/fileunix.c | 173 +++++++--------------
   4 files changed, 442 insertions(+), 341 deletions(-)

Modified: trunk/tools/build/v2/engine/filent.c
==============================================================================
--- trunk/tools/build/v2/engine/filent.c (original)
+++ trunk/tools/build/v2/engine/filent.c 2012-07-11 17:42:51 EDT (Wed, 11 Jul 2012)
@@ -15,21 +15,17 @@
  * filent.c - scan directories and archives on NT
  *
  * External routines:
- * file_dirscan() - scan a directory for files
- * file_time() - get timestamp of file, if not done by file_dirscan()
  * file_archscan() - scan an archive for files
+ * file_mkdir() - create a directory
  *
- * File_dirscan() and file_archscan() call back a caller provided function for
- * each file found. A flag to this callback function lets file_dirscan() and
- * file_archscan() indicate whether a timestamp is being provided with the file.
- * If file_dirscan() or file_archscan() do not provide the file's timestamp,
- * interested parties may later call file_time() for it.
+ * External routines called only via routines in filesys.c:
+ * file_collect_dir_content_() - collects directory content information
+ * file_dirscan_() - OS specific file_dirscan() implementation
+ * file_query_() - query information about a path from the OS
  */
 
 #include "jam.h"
-
 #ifdef OS_NT
-
 #include "filesys.h"
 
 #include "object.h"
@@ -45,144 +41,138 @@
 # define _finddata_t ffblk
 #endif
 
+#include <assert.h>
 #include <ctype.h>
 #include <direct.h>
 #include <io.h>
-#include <sys/stat.h>
 
 #include <windows.h>
 
 
 /*
- * file_dirscan() - scan a directory for files
+ * file_collect_dir_content_() - collects directory content information
  */
 
-void file_dirscan( OBJECT * dir, scanback func, void * closure )
+int file_collect_dir_content_( file_info_t * const d )
 {
- PROFILE_ENTER( FILE_DIRSCAN );
-
- /* First enter the directory itself. */
+ PATHNAME f;
+ string filespec[ 1 ];
+ string filename[ 1 ];
+ struct _finddata_t finfo[ 1 ];
+ LIST * files = L0;
+ int d_length;
+
+ assert( d );
+ assert( d->is_dir );
+ assert( list_empty( d->files ) );
+
+ d_length = strlen( object_str( d->name ) );
+
+ memset( (char *)&f, '\0', sizeof( f ) );
+ f.f_dir.ptr = object_str( d->name );
+ f.f_dir.len = d_length;
+
+ /* Prepare file search specification for the findfirst() API. */
+ if ( !d_length )
+ string_copy( filespec, ".\\*" );
+ else
+ {
+ /* We can not simply assume the given folder name will never include its
+ * trailing path separator or otherwise we would not support the Windows
+ * root folder specified without its drive letter, i.e. '\'.
+ */
+ char const trailingChar = object_str( d->name )[ d_length - 1 ] ;
+ string_copy( filespec, object_str( d->name ) );
+ if ( ( trailingChar != '\\' ) && ( trailingChar != '/' ) )
+ string_append( filespec, "\\" );
+ string_append( filespec, "*" );
+ }
 
- file_info_t * const d = file_query( dir );
- if ( !d || !d->is_dir )
+ #if defined(__BORLANDC__) && __BORLANDC__ < 0x550
+ if ( findfirst( filespec->value, finfo, FA_NORMAL | FA_DIREC ) )
     {
- PROFILE_EXIT( FILE_DIRSCAN );
- return;
+ string_free( filespec );
+ return -1;
     }
 
- /* If we do not have the directory's contents information - collect it. */
- if ( list_empty( d->files ) )
+ string_new( filename );
+ do
     {
- PATHNAME f;
- string filespec[ 1 ];
- string filename[ 1 ];
- struct _finddata_t finfo[ 1 ];
- LIST * files = L0;
- OBJECT * const long_dir = short_path_to_long_path( dir );
- int const d_length = strlen( object_str( long_dir ) );
-
- memset( (char *)&f, '\0', sizeof( f ) );
- f.f_dir.ptr = object_str( long_dir );
- f.f_dir.len = d_length;
-
- /* Prepare file search specification for the findfirst() API. */
- if ( !d_length )
- string_copy( filespec, ".\\*" );
- else
+ f.f_base.ptr = finfo->ff_name;
+ f.f_base.len = strlen( finfo->ff_name );
+ string_truncate( filename, 0 );
+ path_build( &f, filename );
+
+ files = list_push_back( files, object_new( filename->value ) );
         {
- /* We can not simply assume the given folder name will never include
- * its trailing path separator or otherwise we would not support the
- * Windows root folder specified without its drive letter, i.e. '\'.
- */
- char const trailingChar = object_str( long_dir )[ d_length - 1 ] ;
- string_copy( filespec, object_str( long_dir ) );
- if ( ( trailingChar != '\\' ) && ( trailingChar != '/' ) )
- string_append( filespec, "\\" );
- string_append( filespec, "*" );
+ file_info_t * const ff = file_info( filename->value );
+ ff->is_file = finfo->ff_attrib & FA_DIREC ? 0 : 1;
+ ff->is_dir = !ff->is_file;
+ ff->size = finfo->ff_fsize;
+ ff->time = ( finfo->ff_ftime << 16 ) | finfo->ff_ftime;
         }
-
- if ( DEBUG_BINDSCAN )
- printf( "scan directory %s\n", long_dir );
-
- #if defined(__BORLANDC__) && __BORLANDC__ < 0x550
- if ( findfirst( filespec->value, finfo, FA_NORMAL | FA_DIREC ) )
+ }
+ while ( !findnext( finfo ) );
+ #else
+ {
+ long const handle = _findfirst( filespec->value, finfo );
+ if ( handle < 0L )
         {
             string_free( filespec );
- object_free( long_dir );
- PROFILE_EXIT( FILE_DIRSCAN );
- return;
+ return -1;
         }
 
         string_new( filename );
         do
         {
- f.f_base.ptr = finfo->ff_name;
- f.f_base.len = strlen( finfo->ff_name );
+ OBJECT * filename_obj;
+
+ f.f_base.ptr = finfo->name;
+ f.f_base.len = strlen( finfo->name );
             string_truncate( filename, 0 );
- path_build( &f, filename );
+ path_build( &f, filename, 0 );
 
- files = list_push_back( files, object_new( filename->value ) );
+ filename_obj = object_new( filename->value );
+ path_key__register_long_path( filename_obj );
+ files = list_push_back( files, filename_obj );
             {
- file_info_t * const ff = file_info( filename->value );
- ff->is_file = finfo->ff_attrib & FA_DIREC ? 0 : 1;
+ file_info_t * const ff = file_info( filename_obj );
+ ff->is_file = finfo->attrib & _A_SUBDIR ? 0 : 1;
                 ff->is_dir = !ff->is_file;
- ff->size = finfo->ff_fsize;
- ff->time = ( finfo->ff_ftime << 16 ) | finfo->ff_ftime;
+ ff->size = finfo->size;
+ ff->time = finfo->time_write;
             }
         }
- while ( !findnext( finfo ) );
- #else
- {
- long const handle = _findfirst( filespec->value, finfo );
- if ( handle < 0L )
- {
- string_free( filespec );
- object_free( long_dir );
- PROFILE_EXIT( FILE_DIRSCAN );
- return;
- }
+ while ( !_findnext( handle, finfo ) );
 
- string_new( filename );
- do
- {
- OBJECT * filename_obj;
+ _findclose( handle );
+ }
+ #endif
+ string_free( filename );
+ string_free( filespec );
 
- f.f_base.ptr = finfo->name;
- f.f_base.len = strlen( finfo->name );
- string_truncate( filename, 0 );
- path_build( &f, filename, 0 );
-
- filename_obj = object_new( filename->value );
- path_key__register_long_path( filename_obj );
- files = list_push_back( files, filename_obj );
- {
- file_info_t * const ff = file_info( filename_obj );
- ff->is_file = finfo->attrib & _A_SUBDIR ? 0 : 1;
- ff->is_dir = !ff->is_file;
- ff->size = finfo->size;
- ff->time = finfo->time_write;
- }
- }
- while ( !_findnext( handle, finfo ) );
+ d->files = files;
+ return 0;
+}
 
- _findclose( handle );
- }
- #endif
- string_free( filename );
- string_free( filespec );
- object_free( long_dir );
 
- d->files = files;
- }
+/*
+ * file_dirscan_() - OS specific file_dirscan() implementation
+ */
+
+void file_dirscan_( file_info_t * const d, scanback func, void * closure )
+{
+ assert( d );
+ assert( d->is_dir );
 
     /* Special case \ or d:\ : enter it */
     {
- unsigned long const len = strlen( object_str( d->name ) );
- if ( len == 1 && object_str( d->name )[ 0 ] == '\\' )
+ char const * const name = object_str( d->name );
+ if ( name[ 0 ] == '\\' && !name[ 1 ] )
         {
             (*func)( closure, d->name, 1 /* stat()'ed */, d->time );
         }
- else if ( len == 3 && object_str( d->name )[ 1 ] == ':' )
+ else if ( name[ 0 ] && name[ 1 ] == ':' && name[ 2 ] && !name[ 3 ] )
         {
             /* We have just entered a 3-letter drive name spelling (with a
              * trailing slash), into the hash table. Now enter its two-letter
@@ -196,90 +186,44 @@
              * There will be no trailing slash in $(p), but there will be one in
              * $(p2). But, that seems rather fragile.
              */
- char const * const str = object_str( d->name );
- OBJECT * const dir_no_slash = object_new_range( str, 2 );
+ OBJECT * const dir_no_slash = object_new_range( name, 2 );
             (*func)( closure, d->name, 1 /* stat()'ed */, d->time );
             (*func)( closure, dir_no_slash, 1 /* stat()'ed */, d->time );
             object_free( dir_no_slash );
         }
     }
-
- /* Now enter the directory contents. */
- {
- LISTITER iter = list_begin( d->files );
- LISTITER const end = list_end( d->files );
- for ( ; iter != end; iter = list_next( iter ) )
- {
- file_info_t const * const ff = file_info( list_item( iter ) );
- (*func)( closure, ff->name, 1 /* stat()'ed */, ff->time );
- }
- }
-
- PROFILE_EXIT( FILE_DIRSCAN );
-}
-
-
-file_info_t * file_query( OBJECT * filename )
-{
- file_info_t * const ff = file_info( filename );
- if ( !ff->time )
- {
- char const * const name = *object_str( filename )
- ? object_str( filename )
- : ".";
-
- /* POSIX stat() function on Windows suffers from several issues:
- * * Does not support file timestamps with resolution finer than 1
- * second. This means it can not be used to detect file timestamp
- * changes of less than one second. One possible consequence is that
- * some fast-pased touch commands (such as those done by Boost
- * Build's internal testing system if it does not do extra waiting
- * before those touch operations) will not be detected correctly by
- * the build system.
- * * Returns file modification times automatically adjusted for
- * daylight savings time even though daylight savings time should
- * have nothing to do with internal time representation.
- */
- struct stat statbuf;
-
- if ( stat( name, &statbuf ) < 0 )
- return 0;
-
- ff->is_file = statbuf.st_mode & S_IFREG ? 1 : 0;
- ff->is_dir = statbuf.st_mode & S_IFDIR ? 1 : 0;
- ff->size = statbuf.st_size;
- /* Set the file's timestamp to 1 in case it is 0 or undetected to avoid
- * confusion with non-existing files.
- */
- ff->time = statbuf.st_mtime ? statbuf.st_mtime : 1;
- }
- return ff;
 }
 
 
 /*
- * file_time() - get timestamp of file, if not done by file_dirscan()
+ * file_mkdir() - create a directory
  */
 
-int file_time( OBJECT * filename, time_t * time )
+int file_mkdir( char const * const path )
 {
- file_info_t const * const ff = file_query( filename );
- if ( !ff ) return -1;
- *time = ff->time;
- return 0;
+ return _mkdir( path );
 }
 
 
-int file_is_file( OBJECT * filename )
-{
- file_info_t const * const ff = file_query( filename );
- return ff ? ff->is_file : -1;
-}
-
+/*
+ * file_query_() - query information about a path from the OS
+ */
 
-int file_mkdir( char const * pathname )
+int file_query_( file_info_t * const info )
 {
- return _mkdir( pathname );
+ /* Note that the POSIX stat() function implementation on Windows suffers
+ * from several issues:
+ * * Does not support file timestamps with resolution finer than 1 second.
+ * This means it can not be used to detect file timestamp changes of
+ * less than one second. One possible consequence is that some
+ * fast-paced touch commands (such as those done by Boost Build's
+ * internal testing system if it does not do extra waiting before those
+ * touch operations) will not be detected correctly by the build system.
+ * * Returns file modification times automatically adjusted for daylight
+ * savings time even though daylight savings time should have nothing to
+ * do with internal time representation.
+ */
+ return file_query_posix_( info );
 }
 
 
@@ -289,7 +233,7 @@
 
 /* Straight from SunOS */
 
-#define ARMAG "!<arch>\n"
+#define ARMAG "!<arch>\n"
 #define SARMAG 8
 
 #define ARFMAG "`\n"
@@ -304,8 +248,8 @@
     char ar_fmag[ 2 ];
 };
 
-#define SARFMAG 2
-#define SARHDR sizeof( struct ar_hdr )
+#define SARFMAG 2
+#define SARHDR sizeof( struct ar_hdr )
 
 void file_archscan( char const * archive, scanback func, void * closure )
 {
@@ -336,8 +280,6 @@
         long lar_size;
         char * name = 0;
         char * endname;
- char * c;
- OBJECT * member;
 
         sscanf( ar_hdr.ar_date, "%ld", &lar_date );
         sscanf( ar_hdr.ar_size, "%ld", &lar_size );
@@ -382,16 +324,20 @@
         *++endname = 0;
 
         /* strip leading directory names, an NT specialty */
-
- if ( c = strrchr( name, '/' ) )
- name = c + 1;
- if ( c = strrchr( name, '\\' ) )
- name = c + 1;
+ {
+ char * c;
+ if ( c = strrchr( name, '/' ) )
+ name = c + 1;
+ if ( c = strrchr( name, '\\' ) )
+ name = c + 1;
+ }
 
         sprintf( buf, "%s(%.*s)", archive, endname - name, name );
- member = object_new( buf );
- (*func)( closure, member, 1 /* time valid */, (time_t)lar_date );
- object_free( member );
+ {
+ OBJECT * const member = object_new( buf );
+ (*func)( closure, member, 1 /* time valid */, (time_t)lar_date );
+ object_free( member );
+ }
 
         offset += SARHDR + lar_size;
         lseek( fd, offset, 0 );

Modified: trunk/tools/build/v2/engine/filesys.c
==============================================================================
--- trunk/tools/build/v2/engine/filesys.c (original)
+++ trunk/tools/build/v2/engine/filesys.c 2012-07-11 17:42:51 EDT (Wed, 11 Jul 2012)
@@ -1,3 +1,32 @@
+/*
+ * Copyright 2001-2004 David Abrahams.
+ * Copyright 2005 Rene Rivera.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/*
+ * filesys.c - OS independant file system manipulation support
+ *
+ * External routines:
+ * file_build1() - construct a path string based on PATHNAME information
+ * file_dirscan() - scan a directory for files
+ * file_done() - module cleanup called on shutdown
+ * file_info() - return cached information about a path
+ * file_is_file() - return whether a name identifies an existing file
+ * file_query() - get cached information about a path, query the OS if
+ * needed
+ * file_remove_atexit() - schedule a path to be removed on program exit
+ * file_time() - get a file timestamp
+ *
+ * External routines - utilites for OS specific module implementations:
+ * file_query_posix_() - query information about a path using POSIX stat()
+ *
+ * Internal routines:
+ * file_dirscan_impl() - no-profiling worker for file_dirscan()
+ */
+
+
 #include "jam.h"
 #include "filesys.h"
 
@@ -6,6 +35,29 @@
 #include "pathsys.h"
 #include "strings.h"
 
+#include <assert.h>
+#include <sys/stat.h>
+
+
+/* Internal OS specific implementation details - have names ending with an
+ * underscore and are expected to be implemented in an OS specific fileXXX.c
+ * module.
+ */
+void file_dirscan_( file_info_t * const dir, scanback func, void * closure );
+int file_collect_dir_content_( file_info_t * const dir );
+int file_query_( file_info_t * const info );
+
+static void file_dirscan_impl( OBJECT * dir, scanback func, void * closure );
+static void free_file_info( void * xfile, void * data );
+static void remove_files_atexit( void );
+
+
+static struct hash * filecache_hash;
+
+
+/*
+ * file_build1() - construct a path string based on PATHNAME information
+ */
 
 void file_build1( PATHNAME * f, string * file )
 {
@@ -36,7 +88,40 @@
 }
 
 
-static struct hash * filecache_hash = 0;
+/*
+ * file_dirscan() - scan a directory for files
+ */
+
+void file_dirscan( OBJECT * dir, scanback func, void * closure )
+{
+ PROFILE_ENTER( FILE_DIRSCAN );
+ file_dirscan_impl( dir, func, closure );
+ PROFILE_EXIT( FILE_DIRSCAN );
+}
+
+
+/*
+ * file_done() - module cleanup called on shutdown
+ */
+
+void file_done()
+{
+ remove_files_atexit();
+ if ( filecache_hash )
+ {
+ hashenumerate( filecache_hash, free_file_info, (void *)0 );
+ hashdone( filecache_hash );
+ }
+}
+
+
+/*
+ * file_info() - return cached information about a path
+ *
+ * Returns a default initialized structure containing only the path's normalized
+ * name in case this is the first time this file system entity has been
+ * referenced.
+ */
 
 file_info_t * file_info( OBJECT * filename )
 {
@@ -64,39 +149,173 @@
 }
 
 
-static LIST * files_to_remove = L0;
+/*
+ * file_is_file() - return whether a name identifies an existing file
+ */
 
-static void remove_files_atexit( void )
+int file_is_file( OBJECT * filename )
 {
- LISTITER iter = list_begin( files_to_remove );
- LISTITER const end = list_end( files_to_remove );
- for ( ; iter != end; iter = list_next( iter ) )
- remove( object_str( list_item( iter ) ) );
- list_free( files_to_remove );
- files_to_remove = L0;
+ file_info_t const * const ff = file_query( filename );
+ return ff ? ff->is_file : -1;
 }
 
 
-static void free_file_info( void * xfile, void * data )
+/*
+ * file_time() - get a file timestamp
+ */
+
+int file_time( OBJECT * filename, time_t * time )
 {
- file_info_t * const file = (file_info_t *)xfile;
- object_free( file->name );
- list_free( file->files );
+ file_info_t const * const ff = file_query( filename );
+ if ( !ff ) return -1;
+ *time = ff->time;
+ return 0;
 }
 
 
-void file_done()
+/*
+ * file_query() - get cached information about a path, query the OS if needed
+ *
+ * Returns 0 in case querying the OS about the given path fails, e.g. because
+ * the path does not reference an existing file system object.
+ */
+
+file_info_t * file_query( OBJECT * path )
 {
- remove_files_atexit();
- if ( filecache_hash )
+ /* FIXME: Add tracking for disappearing files (i.e. those that can not be
+ * detected by stat() even though they had been detected successfully
+ * before) and see how they should be handled in the rest of Boost Jam code.
+ * Possibly allow Jamfiles to specify some files as 'volatile' which would
+ * make Boost Jam avoid caching information about those files and instead
+ * ask the OS about them every time.
+ *
+ * FIXME: Consider returning a clear file_info() result here if
+ * file_query_() fails. Should simplify the caller side error checking and
+ * the caller still can and needs to detect whether the file has not been
+ * successfully detected by the OS, i.e. whether the file_query() call
+ * failed.
+ */
+ file_info_t * const ff = file_info( path );
+ if ( !ff->time )
     {
- hashenumerate( filecache_hash, free_file_info, (void *)0 );
- hashdone( filecache_hash );
+ if ( file_query_( ff ) < 0 )
+ return 0;
+
+ /* Set the path's timestamp to 1 in case it is 0 or undetected to avoid
+ * confusion with non-existing paths.
+ */
+ if ( !ff->time ) ff->time = 1;
     }
+ return ff;
 }
 
 
+/*
+ * file_query_posix_() - query information about a path using POSIX stat()
+ *
+ * Fallback file_query_() implementation for OS specific modules.
+ */
+
+int file_query_posix_( file_info_t * const info )
+{
+ struct stat statbuf;
+ char const * const pathstr = object_str( info->name );
+ char const * const pathspec = *pathstr ? pathstr : ".";
+
+ assert( !info->time );
+
+ if ( stat( pathspec, &statbuf ) < 0 )
+ return -1;
+
+ info->is_file = statbuf.st_mode & S_IFREG ? 1 : 0;
+ info->is_dir = statbuf.st_mode & S_IFDIR ? 1 : 0;
+ info->size = statbuf.st_size;
+ info->time = statbuf.st_mtime;
+ return 0;
+}
+
+
+/*
+ * file_remove_atexit() - schedule a path to be removed on program exit
+ */
+
+static LIST * files_to_remove = L0;
+
 void file_remove_atexit( OBJECT * const path )
 {
     files_to_remove = list_push_back( files_to_remove, object_copy( path ) );
 }
+
+
+/*
+ * file_dirscan_impl() - no-profiling worker for file_dirscan()
+ */
+
+static void file_dirscan_impl( OBJECT * dir, scanback func, void * closure )
+{
+ file_info_t * const d = file_query( dir );
+ if ( !d || !d->is_dir )
+ return;
+
+ /* Lazy collect the directory content information. */
+ if ( list_empty( d->files ) )
+ {
+ if ( DEBUG_BINDSCAN )
+ printf( "scan directory %s\n", object_str( d->name ) );
+ if ( file_collect_dir_content_( d ) < 0 )
+ return;
+ }
+
+ /* OS specific part of the file_dirscan operation. */
+ file_dirscan_( d, func, closure );
+
+ /* Report the collected directory content. */
+ {
+ LISTITER iter = list_begin( d->files );
+ LISTITER const end = list_end( d->files );
+ for ( ; iter != end; iter = list_next( iter ) )
+ {
+ OBJECT * const filename = list_item( iter );
+ file_info_t const * const ffq = file_query( filename );
+ /* The only way a file_query() call can fail is if its internal OS
+ * file information gathering API (e.g. stat()) failed. If that
+ * happens we should treat the file as if it no longer exists. We
+ * then request the raw cached file_info_t structure for that file
+ * and use the file name from there.
+ */
+ file_info_t const * const ff = ffq ? ffq : file_info( filename );
+ /* Using a file name read from a file_info_t structure allows OS
+ * specific implementations to store some kind of a normalized file
+ * name there. Using such a normalized file name then allows us to
+ * correctly recognize different file paths actually identifying the
+ * same file. For instance, an implementation may:
+ * - convert all file names internally to lower case on a case
+ * insensitive file system
+ * - convert the NTFS paths to their long path variants as that
+ * file system each file system entity may have a long and a
+ * short path variant thus allowing for many different path
+ * strings identifying the same file.
+ */
+ (*func)( closure, ff->name, 1 /* stat()'ed */, ff->time );
+ }
+ }
+}
+
+
+static void free_file_info( void * xfile, void * data )
+{
+ file_info_t * const file = (file_info_t *)xfile;
+ object_free( file->name );
+ list_free( file->files );
+}
+
+
+static void remove_files_atexit( void )
+{
+ LISTITER iter = list_begin( files_to_remove );
+ LISTITER const end = list_end( files_to_remove );
+ for ( ; iter != end; iter = list_next( iter ) )
+ remove( object_str( list_item( iter ) ) );
+ list_free( files_to_remove );
+ files_to_remove = L0;
+}

Modified: trunk/tools/build/v2/engine/filesys.h
==============================================================================
--- trunk/tools/build/v2/engine/filesys.h (original)
+++ trunk/tools/build/v2/engine/filesys.h 2012-07-11 17:42:51 EDT (Wed, 11 Jul 2012)
@@ -23,17 +23,6 @@
 #include "pathsys.h"
 
 
-typedef void (*scanback)( void *closure, OBJECT * file, int found, time_t t );
-
-void file_dirscan( OBJECT * dir, scanback func, void * closure );
-void file_archscan( char const * arch, scanback func, void * closure );
-
-int file_time( OBJECT * filename, time_t * time );
-
-void file_build1( PATHNAME * f, string * file ) ;
-int file_is_file( OBJECT * filename );
-int file_mkdir( char const * pathname );
-
 typedef struct file_info_t
 {
     OBJECT * name;
@@ -44,20 +33,22 @@
     LIST * files;
 } file_info_t;
 
+typedef void (*scanback)( void * closure, OBJECT * path, int found, time_t t );
 
-/* Returns a pointer to information about file 'filename', creating it as
- * necessary. If created, the structure will be default initialized.
- */
-file_info_t * file_info( OBJECT * filename );
-
-/* Returns information about a file, queries the OS if needed. Will return 0 if
- * the file does not exist.
- */
-file_info_t * file_query( OBJECT * filename );
 
-void file_done();
-
-/* Marks a path/file to be removed when JAM exits. */
+void file_archscan( char const * arch, scanback func, void * closure );
+void file_build1( PATHNAME * f, string * file ) ;
+void file_dirscan( OBJECT * dir, scanback func, void * closure );
+file_info_t * file_info( OBJECT * path );
+int file_is_file( OBJECT * path );
+int file_mkdir( char const * const path );
+file_info_t * file_query( OBJECT * path );
 void file_remove_atexit( OBJECT * const path );
+int file_time( OBJECT * path, time_t * time );
+
+/* Internal utility worker functions. */
+int file_query_posix_( file_info_t * const info );
+
+void file_done();
 
 #endif

Modified: trunk/tools/build/v2/engine/fileunix.c
==============================================================================
--- trunk/tools/build/v2/engine/fileunix.c (original)
+++ trunk/tools/build/v2/engine/fileunix.c 2012-07-11 17:42:51 EDT (Wed, 11 Jul 2012)
@@ -15,15 +15,13 @@
  * fileunix.c - manipulate file names and scan directories on UNIX/AmigaOS
  *
  * External routines:
- * file_dirscan() - scan a directory for files
- * file_time() - get timestamp of file, if not done by file_dirscan()
  * file_archscan() - scan an archive for files
+ * file_mkdir() - create a directory
  *
- * File_dirscan() and file_archscan() call back a caller provided function for
- * each file found. A flag to this callback function lets file_dirscan() and
- * file_archscan() indicate whether a timestamp is being provided with the file.
- * If file_dirscan() or file_archscan() do not provide the file's timestamp,
- * interested parties may later call file_time() for it.
+ * External routines called only via routines in filesys.c:
+ * file_collect_dir_content_() - collects directory content information
+ * file_dirscan_() - OS specific file_dirscan() implementation
+ * file_query_() - query information about a path from the OS
  */
 
 #include "jam.h"
@@ -34,8 +32,8 @@
 #include "pathsys.h"
 #include "strings.h"
 
+#include <assert.h>
 #include <stdio.h>
-#include <sys/stat.h>
 
 #if defined( sun ) || defined( __sun ) || defined( linux )
 # include <unistd.h> /* needed for read and close prototype */
@@ -48,11 +46,6 @@
 # define PORTAR 1
 #endif
 
-#ifdef __EMX__
-# include <sys/types.h>
-# include <sys/stat.h>
-#endif
-
 #if defined( OS_RHAPSODY ) || defined( OS_MACOSX ) || defined( OS_NEXT )
 # include <sys/dir.h>
 # include <unistd.h> /* need unistd for rhapsody's proper lseek */
@@ -103,136 +96,88 @@
 
 
 /*
- * file_dirscan() - scan a directory for files.
+ * file_collect_dir_content_() - collects directory content information
  */
 
-void file_dirscan( OBJECT * dir, scanback func, void * closure )
+int file_collect_dir_content_( file_info_t * const d )
 {
- PROFILE_ENTER( FILE_DIRSCAN );
-
- file_info_t * const d = file_query( dir );
- if ( !d || !d->is_dir )
- {
- PROFILE_EXIT( FILE_DIRSCAN );
- return;
- }
+ LIST * files = L0;
+ PATHNAME f;
+ DIR * dd;
+ STRUCT_DIRENT * dirent;
+ string filename[ 1 ];
+ char const * dirstr;
 
- /* If we do not have the directory's contents information - collect it. */
- if ( list_empty( d->files ) )
- {
- LIST * files = L0;
- PATHNAME f;
- DIR * dd;
- STRUCT_DIRENT * dirent;
- string filename[ 1 ];
- char const * dirstr = object_str( dir );
-
- /* First enter the directory itself. */
- memset( (char *)&f, '\0', sizeof( f ) );
- f.f_dir.ptr = dirstr;
- f.f_dir.len = strlen( dirstr );
+ assert( d );
+ assert( d->is_dir );
+ assert( list_empty( d->files ) );
 
- if ( !*dirstr ) dirstr = ".";
+ dirstr = object_str( d->name );
 
- if ( !( dd = opendir( dirstr ) ) )
- {
- PROFILE_EXIT( FILE_DIRSCAN );
- return;
- }
+ memset( (char *)&f, '\0', sizeof( f ) );
+ f.f_dir.ptr = dirstr;
+ f.f_dir.len = strlen( dirstr );
 
- if ( DEBUG_BINDSCAN )
- printf( "scan directory %s\n", dirstr );
+ if ( !*dirstr ) dirstr = ".";
 
- string_new( filename );
- while ( ( dirent = readdir( dd ) ) )
- {
- OBJECT * filename_obj;
- f.f_base.ptr = dirent->d_name
- #ifdef old_sinix
- - 2 /* Broken structure definition on sinix. */
- #endif
- ;
- f.f_base.len = strlen( f.f_base.ptr );
-
- string_truncate( filename, 0 );
- path_build( &f, filename, 0 );
-
- filename_obj = object_new( filename->value );
- files = list_push_back( files, filename_obj );
- file_query( filename_obj );
- }
- string_free( filename );
+ if ( !( dd = opendir( dirstr ) ) )
+ return -1;
 
- closedir( dd );
+ string_new( filename );
+ while ( ( dirent = readdir( dd ) ) )
+ {
+ f.f_base.ptr = dirent->d_name
+ #ifdef old_sinix
+ - 2 /* Broken structure definition on sinix. */
+ #endif
+ ;
+ f.f_base.len = strlen( f.f_base.ptr );
 
- d->files = files;
+ string_truncate( filename, 0 );
+ path_build( &f, filename, 0 );
+ files = list_push_back( files, object_new( filename->value ) );
     }
+ string_free( filename );
 
- /* Special case / : enter it */
- if ( !strcmp( object_str( d->name ), "/" ) )
- (*func)( closure, d->name, 1 /* stat()'ed */, d->time );
+ closedir( dd );
 
- /* Now enter the directory contents. */
- {
- LISTITER iter = list_begin( d->files );
- LISTITER const end = list_end( d->files );
- for ( ; iter != end; iter = list_next( iter ) )
- {
- file_info_t const * const ff = file_info( list_item( iter ) );
- (*func)( closure, ff->name, 1 /* stat()'ed */, ff->time );
- }
- }
-
- PROFILE_EXIT( FILE_DIRSCAN );
+ d->files = files;
+ return 0;
 }
 
 
-file_info_t * file_query( OBJECT * filename )
+/*
+ * file_dirscan_() - OS specific file_dirscan() implementation
+ */
+
+void file_dirscan_( file_info_t * const d, scanback func, void * closure )
 {
- file_info_t * const ff = file_info( filename );
- if ( !ff->time )
- {
- struct stat statbuf;
+ assert( d );
+ assert( d->is_dir );
 
- if ( stat( *object_str( filename ) ? object_str( filename ) : ".",
- &statbuf ) < 0 )
- return 0;
-
- ff->is_file = statbuf.st_mode & S_IFREG ? 1 : 0;
- ff->is_dir = statbuf.st_mode & S_IFDIR ? 1 : 0;
- ff->size = statbuf.st_size;
- /* Set the file's timestamp to 1 in case it is 0 or undetected to avoid
- * confusion with non-existing files.
- */
- ff->time = statbuf.st_mtime ? statbuf.st_mtime : 1;
- }
- return ff;
+ /* Special case / : enter it */
+ if ( !strcmp( object_str( d->name ), "/" ) )
+ (*func)( closure, d->name, 1 /* stat()'ed */, d->time );
 }
 
 
 /*
- * file_time() - get timestamp of file, if not done by file_dirscan()
+ * file_mkdir() - create a directory
  */
 
-int file_time( OBJECT * filename, time_t * time )
+int file_mkdir( char const * const pathname )
 {
- file_info_t const * const ff = file_query( filename );
- if ( !ff ) return -1;
- *time = ff->time;
- return 0;
+ return mkdir( pathname, 0766 );
 }
 
 
-int file_is_file( OBJECT * filename )
-{
- file_info_t const * const ff = file_query( filename );
- return ff ? ff->is_file : -1;
-}
-
+/*
+ * file_query_() - query information about a path from the OS
+ */
 
-int file_mkdir( char const * pathname )
+int file_query_( file_info_t * const info )
 {
- return mkdir( pathname, 0766 );
+ return file_query_posix_( info );
 }
 
 
@@ -446,7 +391,7 @@
     int fd;
     char fl_magic[ SAIAMAG ];
 
- if ( ( fd = open( archive, O_RDONLY, 0)) < 0 )
+ if ( ( fd = open( archive, O_RDONLY, 0 ) ) < 0 )
         return;
 
     if ( read( fd, fl_magic, SAIAMAG ) != SAIAMAG ||


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk