2
0
mirror of https://github.com/boostorg/build.git synced 2026-02-17 13:42:14 +00:00

Restoring Boost Build & Jam changes from revisions [79281 - 79310] (inclusive) previously temporarily reverted in revision [79321]. This is done to test whether the problem causing the original revert was introduced in revision [79311] (a bug has been found in that revision that could cause the observed Boost Jam crashes). Remaining reverted changes will be reverted if we do not detect any Boost library tester failures with this revision.

[SVN r79402]
This commit is contained in:
Jurko Gospodnetić
2012-07-10 15:27:58 +00:00
parent dc8e3d28bc
commit ed56af5717
10 changed files with 252 additions and 202 deletions

View File

@@ -627,7 +627,6 @@ static void builtin_glob_back( void * closure, OBJECT * file, int status,
PROFILE_ENTER( BUILTIN_GLOB_BACK );
struct globbing * const globbing = (struct globbing *)closure;
LIST * l;
PATHNAME f;
string buf[ 1 ];
LISTITER iter;

View File

@@ -339,9 +339,8 @@ static int read_descriptor( int i, int s )
* contains the command status at beginning of it own line instead of
* appended to end of the previous output.
*/
if ( globs.max_buf && globs.max_buf <= cmdtab[i].buf_size[s] ) {
if ( globs.max_buf && globs.max_buf <= cmdtab[i].buf_size[s] )
cmdtab[ i ].buffer[ s ][ cmdtab[ i ].buf_size[ s ] - 2 ] = '\n';
}
return feof( cmdtab[ i ].stream[ s ] );
}

View File

@@ -15,7 +15,6 @@
* 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
@@ -67,7 +66,6 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure )
file_info_t * const d = file_query( dir );
if ( !d || !d->is_dir )
{
object_free( dir );
PROFILE_EXIT( FILE_DIRSCAN );
return;
}
@@ -77,25 +75,19 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure )
PATHNAME f;
string filespec[ 1 ];
string filename[ 1 ];
long handle;
int ret;
struct _finddata_t finfo[ 1 ];
LIST * files = L0;
int d_length;
dir = short_path_to_long_path( dir );
d_length = strlen( object_str( dir ) );
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( dir );
f.f_dir.ptr = object_str( long_dir );
f.f_dir.len = d_length;
/* Now enter contents of directory */
/* Prepare file search specification for the findfirst() API. */
if ( d_length == 0 )
if ( !d_length )
string_copy( filespec, ".\\*" );
else
{
@@ -103,85 +95,83 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure )
* 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( dir )[ d_length - 1 ] ;
string_copy( filespec, object_str( dir ) );
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, "*" );
}
if ( DEBUG_BINDSCAN )
printf( "scan directory %s\n", dir );
printf( "scan directory %s\n", long_dir );
#if defined(__BORLANDC__) && __BORLANDC__ < 0x550
if ( ret = findfirst( filespec->value, finfo, FA_NORMAL | FA_DIREC ) )
if ( findfirst( filespec->value, finfo, FA_NORMAL | FA_DIREC ) )
{
string_free( filespec );
object_free( dir );
object_free( long_dir );
PROFILE_EXIT( FILE_DIRSCAN );
return;
}
string_new( filename );
while ( !ret )
do
{
file_info_t * ff;
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 ) );
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;
ret = findnext( finfo );
{
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;
}
}
while ( !findnext( finfo ) );
#else
handle = _findfirst( filespec->value, finfo );
if ( ret = ( handle < 0L ) )
{
string_free( filespec );
object_free( dir );
PROFILE_EXIT( FILE_DIRSCAN );
return;
long const handle = _findfirst( filespec->value, finfo );
if ( handle < 0L )
{
string_free( filespec );
object_free( long_dir );
PROFILE_EXIT( FILE_DIRSCAN );
return;
}
string_new( filename );
do
{
OBJECT * filename_obj;
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 ) );
_findclose( handle );
}
string_new( filename );
while ( !ret )
{
OBJECT * filename_obj;
file_info_t * ff;
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_add_key( filename_obj );
files = list_push_back( files, filename_obj );
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;
ret = _findnext( handle, finfo );
}
_findclose( handle );
#endif
string_free( filename );
string_free( filespec );
object_free( dir );
object_free( long_dir );
d->files = files;
}
@@ -191,16 +181,12 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure )
unsigned long len = strlen( object_str( d->name ) );
if ( len == 1 && object_str( d->name )[ 0 ] == '\\' )
{
OBJECT * const dir = short_path_to_long_path( d->name );
(*func)( closure, dir, 1 /* stat()'ed */, d->time );
object_free( dir );
OBJECT * const long_dir = short_path_to_long_path( d->name );
(*func)( closure, long_dir, 1 /* stat()'ed */, d->time );
object_free( long_dir );
}
else if ( len == 3 && object_str( d->name )[ 1 ] == ':' )
{
char buf[ 4 ];
OBJECT * const dir1 = short_path_to_long_path( d->name );
OBJECT * dir2;
(*func)( closure, dir1, 1 /* stat()'ed */, d->time );
/* We have just entered a 3-letter drive name spelling (with a
* trailing slash), into the hash table. Now enter its two-letter
* variant, without the trailing slash, so that if we try to check
@@ -213,9 +199,11 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure )
* There will be no trailing slash in $(p), but there will be one in
* $(p2). But, that seems rather fragile.
*/
strcpy( buf, object_str( dir1 ) );
buf[ 2 ] = 0;
dir2 = object_new( buf );
OBJECT * const dir1 = short_path_to_long_path( d->name );
char const * const dir1_raw = object_str( dir1 );
char const dir2_raw[ 3 ] = { dir1_raw[ 0 ], dir1_raw[ 1 ], 0 };
OBJECT * const dir2 = object_new( dir2_raw );
(*func)( closure, dir1, 1 /* stat()'ed */, d->time );
(*func)( closure, dir2, 1 /* stat()'ed */, d->time );
object_free( dir2 );
object_free( dir1 );

View File

@@ -37,30 +37,28 @@ void file_build1( PATHNAME * f, string * file )
static struct hash * filecache_hash = 0;
static file_info_t filecache_finfo;
file_info_t * file_info( OBJECT * filename )
{
file_info_t * finfo = &filecache_finfo;
OBJECT * const path_key = path_as_key( filename );
file_info_t * finfo;
int found;
if ( !filecache_hash )
filecache_hash = hashinit( sizeof( file_info_t ), "file_info" );
filename = path_as_key( filename );
finfo = (file_info_t *)hash_insert( filecache_hash, filename, &found );
finfo = (file_info_t *)hash_insert( filecache_hash, path_key, &found );
if ( !found )
{
finfo->name = object_copy( filename );
finfo->name = path_key;
finfo->is_file = 0;
finfo->is_dir = 0;
finfo->size = 0;
finfo->time = 0;
finfo->files = L0;
}
object_free( filename );
else
object_free( path_key );
return finfo;
}

View File

@@ -34,8 +34,7 @@ void file_build1( PATHNAME * f, string * file ) ;
int file_is_file( OBJECT * filename );
int file_mkdir( char const * pathname );
typedef struct file_info_t file_info_t ;
struct file_info_t
typedef struct file_info_t
{
OBJECT * name;
short is_file;
@@ -43,15 +42,17 @@ struct file_info_t
unsigned long size;
time_t time;
LIST * files;
};
} file_info_t;
/* Creates a pointer to information about file 'filename', creating it as
/* 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. */
/* 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();

View File

@@ -99,7 +99,7 @@ static void make1atail ( state * );
static void make1b ( state * );
static void make1c ( state * );
static void make1d ( state * );
static void make_closure( void * const closure, int const status,
static void make_closure( void * const closure, int status,
timing_info const * const, char const * const cmd_stdout,
char const * const cmd_stderr, int const cmd_exit_reason );
@@ -830,7 +830,7 @@ static void make_closure
)
{
TARGET * const t = (TARGET *)closure;
CMD * cmd = (CMD *)t->cmds;
CMD const * const cmd = (CMD *)t->cmds;
char const * rule_name = 0;
char const * target_name = 0;
@@ -882,7 +882,7 @@ static void make_closure
printf( "%s\n", cmd->buf->value );
printf( "...failed %s ", object_str( cmd->rule->name ) );
list_print( lol_get( &cmd->args, 0 ) );
list_print( lol_get( (LOL *)&cmd->args, 0 ) );
printf( "...\n" );
}

View File

@@ -9,11 +9,12 @@
* object.c - object manipulation routines
*
* External functions:
* object_new() - create an object from a string
* object_copy() - return a copy of an object
* object_free() - free an object
* object_str() - get the string value of an object
* object_done() - free string tables
* object_new() - create an object from a string
* object_new_range() - create an object from a string of given length
* object_copy() - return a copy of an object
* object_free() - free an object
* object_str() - get the string value of an object
* object_done() - free string tables
*
* This implementation builds a hash table of all strings, so that multiple
* calls of object_new() on the same string allocate memory for the string once.
@@ -128,28 +129,27 @@ static char * allocate( size_t n )
}
static unsigned int hash_keyval( char const * key )
static unsigned int hash_keyval( char const * key, int const size )
{
unsigned int const magic = 2147059363;
unsigned int hash = 0;
unsigned i;
unsigned int len = strlen( key );
for ( i = 0; i < len / sizeof( unsigned int ); ++i )
unsigned int i;
for ( i = 0; i < size / sizeof( unsigned int ); ++i )
{
unsigned int val;
memcpy( &val, key, sizeof( unsigned int ) );
hash = hash * 2147059363 + val;
hash = hash * magic + val;
key += sizeof( unsigned int );
}
{
unsigned int val = 0;
memcpy( &val, key, len % sizeof( unsigned int ) );
hash = hash * 2147059363 + val;
memcpy( &val, key, size % sizeof( unsigned int ) );
hash = hash * magic + val;
}
hash += (hash >> 17);
return hash;
return hash + ( hash >> 17 );
}
@@ -193,16 +193,16 @@ static void string_set_resize( string_set * set )
}
static char const * string_set_insert( string_set * set, char const * string )
static char const * string_set_insert( string_set * set, char const * string,
int const size )
{
unsigned hash = hash_keyval( string );
unsigned hash = hash_keyval( string, size );
unsigned pos = hash % set->num;
unsigned len;
struct hash_item * result;
for ( result = set->data[ pos ]; result; result = result->header.next )
if ( !strcmp( result->data, string ) )
if ( !strncmp( result->data, string, size ) && !result->data[ size ] )
return result->data;
if ( set->size >= set->num )
@@ -211,17 +211,18 @@ static char const * string_set_insert( string_set * set, char const * string )
pos = hash % set->num;
}
len = strlen( string ) + 1;
result = (struct hash_item *)allocate( sizeof( struct hash_header ) + len );
result = (struct hash_item *)allocate( sizeof( struct hash_header ) + size +
1 );
result->header.hash = hash;
result->header.next = set->data[ pos ];
#ifndef NDEBUG
result->header.magic = OBJECT_MAGIC;
#endif
memcpy( result->data, string, len );
assert( hash_keyval( result->data ) == result->header.hash );
memcpy( result->data, string, size );
result->data[ size ] = '\0';
assert( hash_keyval( result->data, size ) == result->header.hash );
set->data[ pos ] = result;
strtotal += len;
strtotal += size + 1;
++set->size;
return result->data;
@@ -243,32 +244,41 @@ static void object_validate( OBJECT * obj )
/*
* object_new() - create an object from a string.
* object_new_range() - create an object from a string of given length
*/
OBJECT * object_new( char const * string )
OBJECT * object_new_range( char const * const string, int const size )
{
++strcount_in;
#ifdef BJAM_NO_MEM_CACHE
{
int const len = strlen( string ) + 1;
struct hash_item * const m = (struct hash_item *)BJAM_MALLOC( sizeof(
struct hash_header ) + len );
strtotal += len;
memcpy( m->data, string, len );
struct hash_header ) + size + 1 );
strtotal += size + 1;
memcpy( m->data, string, size );
m->data[ size ] = '\0';
m->header.magic = OBJECT_MAGIC;
return (OBJECT *)m->data;
}
#else
if ( !strhash.data )
string_set_init( &strhash );
return (OBJECT *)string_set_insert( &strhash, string );
return (OBJECT *)string_set_insert( &strhash, string, size );
#endif
}
/*
* object_new() - create an object from a string
*/
OBJECT * object_new( char const * const string )
{
return object_new_range( string, strlen( string ) );
}
#ifndef object_copy
/*
@@ -337,7 +347,7 @@ unsigned int object_hash( OBJECT * obj )
{
object_validate( obj );
#ifdef BJAM_NO_MEM_CACHE
return hash_keyval( object_str( obj ) );
return hash_keyval( object_str( obj ), strlen( object_str( obj ) ) );
#else
return object_get_item( obj )->header.hash;
#endif

View File

@@ -13,8 +13,9 @@
typedef struct _object OBJECT;
OBJECT * object_new ( char const * );
void object_done( void );
OBJECT * object_new( char const * const );
OBJECT * object_new_range( char const * const, int const size );
void object_done( void );
#if defined(NDEBUG) && !defined(BJAM_NO_MEM_CACHE)

View File

@@ -72,7 +72,7 @@ OBJECT * path_as_key( OBJECT * path );
* long form. Avoids the need for some subsequent path_as_key() call to do a
* potentially expensive short-->long path conversion.
*/
void path_add_key( OBJECT * long_path );
void path_key__register_long_path( OBJECT * long_path );
#ifdef USE_PATHUNIX
/* Returns a static pointer to the system dependent path to the temporary

View File

@@ -247,68 +247,151 @@ void path_parent( PATHNAME * f )
#undef INVALID_FILE_ATTRIBUTES
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
static void path_write_key( char const * const path_, string * const out );
typedef struct path_key_entry
{
OBJECT * path;
OBJECT * key;
} path_key_entry;
static struct hash * path_key_cache;
static void ShortPathToLongPath( char const * const short_path,
/*
* may_be_a_valid_short_name() - returns whether the given file name may be a
* valid Windows short name, i.e. whether it might have a different long name.
*/
static int may_be_a_valid_short_name( char const * const n, int const n_length )
{
char const * p;
char const * const n_end = n + n_length;
char const * dot = 0;
/* Short names have at most 12 characters (8 + dot + 3). */
if ( n_length > 12 )
return 0;
for ( p = n; p != n_end; ++p )
switch ( *p )
{
case ' ':
/* Short names may not contain spaces. */
return 0;
case '.':
/* Short name may contain at most one dot. */
if ( dot )
return 0;
dot = p;
/* Short name base must have at least one character. */
if ( dot == n )
return 0;
/* Short name base may not be longer than 8 characters. */
if ( dot - n > 8 )
return 0;
/* Short name extension may not be longer than 3 characters. */
if ( n_end - dot - 1 > 3 )
return 0;
}
return 1;
}
/*
* ShortPathToLongPath() - convert a given path into its long format
*
* In the process, automatically registers long paths for all of the parent
* folders on the path, if they have not already been registered.
*
* Prerequisites:
* - Path to given in normalized form, i.e. all of its folder separators have
* already been converted into '\\'.
* - path_key_cache path/key mapping cache object has already been initialized.
*/
static void ShortPathToLongPath( char const * const path, int const path_length,
string * const out )
{
char const * new_element;
char const * last_element;
unsigned long saved_size;
char * p;
char const * p;
if ( short_path[ 0 ] == '\0' )
/* This is only called via path_key(), which initializes the cache. */
assert( path_key_cache );
if ( !path_length )
return;
if ( short_path[ 0 ] == '\\' && short_path[ 1 ] == '\0' )
if ( path_length == 1 && path[ 0 ] == '\\' )
{
string_push_back( out, '\\' );
return;
}
if ( short_path[ 1 ] == ':' &&
( short_path[ 2 ] == '\0' ||
( short_path[ 2 ] == '\\' && short_path[ 3 ] == '\0' ) ) )
if ( path[ 1 ] == ':' &&
( path_length == 2 ||
( path_length == 3 && path[ 2 ] == '\\' ) ) )
{
string_push_back( out, toupper( short_path[ 0 ] ) );
string_push_back( out, toupper( path[ 0 ] ) );
string_push_back( out, ':' );
string_push_back( out, '\\' );
return;
}
/* '/' already handled. */
if ( ( p = strrchr( short_path, '\\' ) ) )
/* Find last '\\'. */
for ( p = path + path_length - 1; p >= path && *p != '\\'; --p );
last_element = p + 1;
/* Special case '\' && 'D:\' - include trailing '\'. */
if ( p == path ||
p == path + 2 && path[ 1 ] == ':' )
++p;
if ( p >= path )
{
char saved;
new_element = p + 1;
/* special case '\' */
if ( p == short_path )
++p;
/* special case 'D:\' */
if ( p == short_path + 2 && short_path[ 1 ] == ':' )
++p;
saved = *p;
*p = '\0';
path_write_key( short_path, out );
*p = saved;
char const * const dir = path;
int const dir_length = p - path;
OBJECT * const dir_obj = object_new_range( dir, dir_length );
int found;
path_key_entry * const result = (path_key_entry *)hash_insert(
path_key_cache, dir_obj, &found );
if ( !found )
{
/* dir is already normalized. */
result->path = dir_obj;
ShortPathToLongPath( dir, dir_length, out );
result->key = object_new( out->value );
}
else
{
object_free( dir_obj );
string_append( out, object_str( result->key ) );
}
}
else
new_element = short_path;
if ( out->size && out->value[ out->size - 1 ] != '\\' )
string_push_back( out, '\\' );
saved_size = out->size;
string_append( out, new_element );
string_append_range( out, last_element, path + path_length );
/* If the file exists, replace its name with its long name variant. */
/* If we have a name that can not be a valid short name then it must be a
* valid long name and we are done. If there is a chance this is not the
* file's long name, ask the OS for the file's actual long name. We try to
* avoid this file system access as it could be unnecessarily expensive.
* Note that there is no way to detect the file's 'long name' in case it
* does not already exist, in which case in theory a file could later be
* created that has a different long name and the name given here as its
* short name.
*/
{
char const * const n = new_element;
if ( !( n[ 0 ] == '.' && n[ 1 ] == '\0' ||
n[ 0 ] == '.' && n[ 1 ] == '.' && n[ 2 ] == '\0' ) )
char const * const n = last_element;
int const n_length = path + path_length - n;
if ( !( n_length == 1 && n[ 0 ] == '.' )
&& !( n_length == 2 && n[ 0 ] == '.' && n[ 1 ] == '.' )
&& may_be_a_valid_short_name( n, n_length ) )
{
WIN32_FIND_DATA fd;
HANDLE const hf = FindFirstFile( out->value, &fd );
@@ -329,40 +412,6 @@ OBJECT * short_path_to_long_path( OBJECT * short_path )
}
typedef struct path_key_entry
{
OBJECT * path;
OBJECT * key;
} path_key_entry;
static struct hash * path_key_cache;
static void path_write_key( char const * const path_, string * const out )
{
path_key_entry * result;
OBJECT * const path = object_new( path_ );
int found;
/* This is only called via path_as_key(), which initializes the cache. */
assert( path_key_cache );
result = (path_key_entry *)hash_insert( path_key_cache, path, &found );
if ( !found )
{
/* path_ is already normalized. */
result->path = path;
ShortPathToLongPath( path_, out );
result->key = object_new( out->value );
}
else
{
object_free( path );
string_append( out, object_str( result->key ) );
}
}
static void normalize_path( string * path )
{
char * s;
@@ -387,13 +436,18 @@ static path_key_entry * path_key( OBJECT * const path,
result = (path_key_entry *)hash_insert( path_key_cache, path, &found );
if ( !found )
{
string buf[ 1 ];
OBJECT * normalized;
int normalized_size;
path_key_entry * nresult;
result->path = path;
string_copy( buf, object_str( path ) );
normalize_path( buf );
normalized = object_new( buf->value );
{
string buf[ 1 ];
string_copy( buf, object_str( path ) );
normalize_path( buf );
normalized = object_new( buf->value );
normalized_size = buf->size;
string_free( buf );
}
nresult = (path_key_entry *)hash_insert( path_key_cache, normalized,
&found );
if ( !found || nresult == result )
@@ -405,14 +459,14 @@ static path_key_entry * path_key( OBJECT * const path,
{
string long_path[ 1 ];
string_new( long_path );
ShortPathToLongPath( buf->value, long_path );
ShortPathToLongPath( object_str( normalized ), normalized_size,
long_path );
nresult->key = object_new( long_path->value );
string_free( long_path );
}
}
else
object_free( normalized );
string_free( buf );
if ( nresult != result )
{
result->path = object_copy( path );
@@ -424,7 +478,7 @@ static path_key_entry * path_key( OBJECT * const path,
}
void path_add_key( OBJECT * long_path )
void path_key__register_long_path( OBJECT * long_path )
{
path_key( long_path, 1 );
}
@@ -456,7 +510,7 @@ void path_done( void )
#else /* NT */
void path_add_key( OBJECT * path )
void path_key__register_long_path( OBJECT * path )
{
}