2
0
mirror of https://github.com/boostorg/build.git synced 2026-02-15 00:52:16 +00:00

Boost Build/Jam cleanup - stylistic code changes.

[SVN r79244]
This commit is contained in:
Jurko Gospodnetić
2012-07-03 15:58:26 +00:00
parent 6c3b7dbe7f
commit 7c5dac15be
32 changed files with 1578 additions and 1627 deletions

View File

@@ -7,13 +7,12 @@
# typed targets.
import "class" : new ;
import errors ;
import feature ;
import generators : * ;
import os ;
import project ;
import property ;
import scanner ;
import os ;
# The following import would create a circular dependency:
# project -> project-root -> builtin -> type -> targets -> project
@@ -39,11 +38,14 @@ rule register ( type : suffixes * : base-type ? )
# decomposed.
switch $(type)
{
case *-* : errors.error "type name \"$(type)\" contains a hyphen" ;
case *-* :
import errors ;
errors.error "type name \"$(type)\" contains a hyphen" ;
}
if $(type) in $(.types)
{
import errors ;
errors.error "Type $(type) is already registered." ;
}
else
@@ -52,7 +54,7 @@ rule register ( type : suffixes * : base-type ? )
.base.$(type) = $(base-type) ;
.derived.$(base-type) += $(type) ;
if $(suffixes)-is-not-empty
if $(suffixes)-is-defined
{
# Specify mapping from suffixes to type.
register-suffixes $(suffixes) : $(type) ;
@@ -119,6 +121,7 @@ rule register-suffixes ( suffixes + : type )
}
else if $(.type.$(s)) != $(type)
{
import errors ;
errors.error Attempting to specify multiple types for suffix
\"$(s)\" : "Old type $(.type.$(s)), New type $(type)" ;
}
@@ -143,6 +146,7 @@ rule validate ( type )
{
if ! [ registered $(type) ]
{
import errors ;
errors.error "Unknown target type $(type)" ;
}
}
@@ -336,7 +340,7 @@ local rule generated-target-ps-real ( ps : type : properties * )
# If the prefix/suffix is explicitly set to an empty string, we consider
# prefix/suffix to be found. If we were not to compare with "", there
# would be no way to specify an empty prefix/suffix.
if $(result)-is-not-empty
if $(result)-is-defined
{
found = true ;
}
@@ -381,7 +385,7 @@ rule type ( filename )
if [ os.name ] in NT CYGWIN
{
filename = $(filename:L) ;
}
}
local type ;
while ! $(type) && $(filename:S)
{

File diff suppressed because it is too large Load Diff

View File

@@ -175,13 +175,10 @@ evaluate_rule(
{
backtrace_line( frame->prev );
if ( frame->module->name )
{
printf( "rule %s unknown in module %s\n", object_str( rule->name ), object_str( frame->module->name ) );
}
printf( "rule %s unknown in module %s\n", object_str( rule->name ),
object_str( frame->module->name ) );
else
{
printf( "rule %s unknown in module \n", object_str( rule->name ) );
}
backtrace( frame->prev );
exit( 1 );
}

View File

@@ -698,8 +698,8 @@ static time_t filetime_dt( FILETIME t_utc )
FILETIME f0_;
SYSTEMTIME s0_;
GetSystemTime( &s0_ );
t0_.tm_year = s0_.wYear-1900;
t0_.tm_mon = s0_.wMonth-1;
t0_.tm_year = s0_.wYear - 1900;
t0_.tm_mon = s0_.wMonth - 1;
t0_.tm_wday = s0_.wDayOfWeek;
t0_.tm_mday = s0_.wDay;
t0_.tm_hour = s0_.wHour;

View File

@@ -335,13 +335,12 @@ static int read_descriptor( int i, int s )
}
}
/* If buffer full, ensure last buffer char is newline
* so process jam log finds command status at beginning
* of it own line, not appended to end of buffer output.
/* If buffer full, ensure last buffer char is newline so that jam log
* contains the command status at beginning of it own line instead of
* appended to end of the previous output.
*/
if ( globs.max_buf && cmdtab[i].buf_size[s] == globs.max_buf ) {
cmdtab[i].buffer[s][cmdtab[i].buf_size[s]-2] = '\n';
}
if ( globs.max_buf && cmdtab[ i ].buf_size[ s ] == globs.max_buf )
cmdtab[ i ].buffer[ s ][ cmdtab[ i ].buf_size[ s ] - 2 ] = '\n';
return feof( cmdtab[ i ].stream[ s ] );
}

View File

@@ -11,29 +11,6 @@
* (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
*/
# include "jam.h"
# include "filesys.h"
# include "pathsys.h"
# include "strings.h"
# include "object.h"
# ifdef OS_NT
# ifdef __BORLANDC__
# if __BORLANDC__ < 0x550
# include <dir.h>
# include <dos.h>
# endif
# undef FILENAME /* cpp namespace collision */
# define _finddata_t ffblk
# endif
# include <io.h>
# include <sys/stat.h>
# include <ctype.h>
# include <direct.h>
/*
* filent.c - scan directories and archives on NT
*
@@ -43,16 +20,40 @@
* file_time() - get timestamp of file, if not done by file_dirscan()
* file_archscan() - scan an archive for files
*
* 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 that 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().
*
* 07/10/95 (taylor) Findfirst() returns the first file on NT.
* 05/03/96 (seiwald) split apart into pathnt.c
* 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.
*/
#include "jam.h"
#ifdef OS_NT
#include "filesys.h"
#include "object.h"
#include "pathsys.h"
#include "strings.h"
#ifdef __BORLANDC__
# if __BORLANDC__ < 0x550
# include <dir.h>
# include <dos.h>
# endif
# undef FILENAME /* cpp namespace collision */
# define _finddata_t ffblk
#endif
#include <ctype.h>
#include <direct.h>
#include <io.h>
#include <sys/stat.h>
#include <windows.h>
/*
* file_dirscan() - scan a directory for files
*/
@@ -61,12 +62,9 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure )
{
PROFILE_ENTER( FILE_DIRSCAN );
file_info_t * d = 0;
/* First enter directory itself */
d = file_query( dir );
/* First enter the directory itself. */
file_info_t * const d = file_query( dir );
if ( !d || !d->is_dir )
{
object_free( dir );
@@ -101,12 +99,11 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure )
string_copy( filespec, ".\\*" );
else
{
/*
* We can not simply assume the given folder name will never include
/* 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 trailingChar = object_str( dir )[ d_length - 1 ] ;
char const trailingChar = object_str( dir )[ d_length - 1 ] ;
string_copy( filespec, object_str( dir ) );
if ( ( trailingChar != '\\' ) && ( trailingChar != '/' ) )
string_append( filespec, "\\" );
@@ -125,10 +122,10 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure )
return;
}
string_new ( filename );
string_new( filename );
while ( !ret )
{
file_info_t * ff = 0;
file_info_t * ff;
f.f_base.ptr = finfo->ff_name;
f.f_base.len = strlen( finfo->ff_name );
@@ -136,16 +133,16 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure )
string_truncate( filename, 0 );
path_build( &f, filename );
files = list_push_back( files, object_new(filename->value) );
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 = finfo->ff_attrib & FA_DIREC ? 1 : 0;
ff->is_dir = !ff->is_file;
ff->size = finfo->ff_fsize;
ff->time = (finfo->ff_ftime << 16) | finfo->ff_ftime;
ff->time = ( finfo->ff_ftime << 16 ) | finfo->ff_ftime;
ret = findnext( finfo );
}
# else
#else
handle = _findfirst( filespec->value, finfo );
if ( ret = ( handle < 0L ) )
@@ -160,7 +157,7 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure )
while ( !ret )
{
OBJECT * filename_obj;
file_info_t * ff = 0;
file_info_t * ff;
f.f_base.ptr = finfo->name;
f.f_base.len = strlen( finfo->name );
@@ -173,7 +170,7 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure )
files = list_push_back( files, filename_obj );
ff = file_info( filename_obj );
ff->is_file = finfo->attrib & _A_SUBDIR ? 0 : 1;
ff->is_dir = finfo->attrib & _A_SUBDIR ? 1 : 0;
ff->is_dir = !ff->is_file;
ff->size = finfo->size;
ff->time = finfo->time_write;
@@ -181,7 +178,7 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure )
}
_findclose( handle );
# endif
#endif
string_free( filename );
string_free( filespec );
object_free( dir );
@@ -192,32 +189,32 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure )
/* Special case \ or d:\ : enter it */
{
unsigned long len = strlen( object_str( d->name ) );
if ( len == 1 && object_str( d->name )[0] == '\\' )
if ( len == 1 && object_str( d->name )[ 0 ] == '\\' )
{
OBJECT * dir = short_path_to_long_path( d->name );
OBJECT * const dir = short_path_to_long_path( d->name );
(*func)( closure, dir, 1 /* stat()'ed */, d->time );
object_free( dir );
}
else if ( len == 3 && object_str( d->name )[1] == ':' )
else if ( len == 3 && object_str( d->name )[ 1 ] == ':' )
{
char buf[4];
OBJECT * dir1 = short_path_to_long_path( d->name );
char buf[ 4 ];
OBJECT * const dir1 = short_path_to_long_path( d->name );
OBJECT * dir2;
(*func)( closure, dir1, 1 /* stat()'ed */, d->time );
/* We've just entered 3-letter drive name spelling (with trailing
slash), into the hash table. Now enter two-letter variant,
without trailing slash, so that if we try to check whether
"c:" exists, we hit it.
Jam core has workarounds for that. Given:
x = c:\whatever\foo ;
p = $(x:D) ;
p2 = $(p:D) ;
There will be no trailing slash in $(p), but there will be one
in $(p2). But, that seems rather fragile.
*/
/* 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
* whether "c:" exists, we hit it.
*
* Jam core has workarounds for that. Given:
* x = c:\whatever\foo ;
* p = $(x:D) ;
* p2 = $(p:D) ;
* 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;
buf[ 2 ] = 0;
dir2 = object_new( buf );
(*func)( closure, dir2, 1 /* stat()'ed */, d->time );
object_free( dir2 );
@@ -228,11 +225,12 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure )
/* Now enter contents of directory */
if ( !list_empty( d->files ) )
{
LIST * files = d->files;
LISTITER iter = list_begin( files ), end = list_end( files );
LIST * const files = d->files;
LISTITER iter = list_begin( files );
LISTITER const end = list_end( files );
for ( ; iter != end; iter = list_next( iter ) )
{
file_info_t * ff = file_info( list_item( iter ) );
file_info_t const * const ff = file_info( list_item( iter ) );
(*func)( closure, list_item( iter ), 1 /* stat()'ed */, ff->time );
}
}
@@ -240,51 +238,71 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure )
PROFILE_EXIT( FILE_DIRSCAN );
}
file_info_t * file_query( OBJECT * filename )
{
file_info_t * ff = file_info( filename );
if ( ! ff->time )
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( *object_str( filename ) ? object_str( filename ) : ".", &statbuf ) < 0 )
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()
*/
int
file_time(
OBJECT * filename,
time_t * time )
int file_time( OBJECT * filename, time_t * time )
{
file_info_t * ff = file_query( filename );
file_info_t const * const ff = file_query( filename );
if ( !ff ) return -1;
*time = ff->time;
return 0;
}
int file_is_file( OBJECT * filename )
{
file_info_t * ff = file_query( filename );
if ( !ff ) return -1;
return ff->is_file;
file_info_t const * const ff = file_query( filename );
return ff ? ff->is_file : -1;
}
int file_mkdir( const char * pathname )
int file_mkdir( char const * pathname )
{
return _mkdir(pathname);
return _mkdir( pathname );
}
/*
* file_archscan() - scan an archive for files
*/
@@ -297,35 +315,30 @@ int file_mkdir( const char * pathname )
#define ARFMAG "`\n"
struct ar_hdr {
char ar_name[16];
char ar_date[12];
char ar_uid[6];
char ar_gid[6];
char ar_mode[8];
char ar_size[10];
char ar_fmag[2];
char ar_name[ 16 ];
char ar_date[ 12 ];
char ar_uid[ 6 ];
char ar_gid[ 6 ];
char ar_mode[ 8 ];
char ar_size[ 10 ];
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(
const char * archive,
scanback func,
void * closure )
void file_archscan( char const * archive, scanback func, void * closure )
{
struct ar_hdr ar_hdr;
char *string_table = 0;
char * string_table = 0;
char buf[ MAXJPATH ];
long offset;
int fd;
int const fd = open( archive, O_RDONLY | O_BINARY, 0 );
if ( ( fd = open( archive, O_RDONLY | O_BINARY, 0 ) ) < 0 )
if ( fd < 0 )
return;
if ( read( fd, buf, SARMAG ) != SARMAG ||
strncmp( ARMAG, buf, SARMAG ) )
if ( read( fd, buf, SARMAG ) != SARMAG || strncmp( ARMAG, buf, SARMAG ) )
{
close( fd );
return;
@@ -337,13 +350,13 @@ file_archscan(
printf( "scan archive %s\n", archive );
while ( ( read( fd, &ar_hdr, SARHDR ) == SARHDR ) &&
!memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG ) )
!memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG ) )
{
long lar_date;
long lar_size;
char * name = 0;
char * endname;
char * c;
long lar_date;
long lar_size;
char * name = 0;
char * endname;
char * c;
OBJECT * member;
sscanf( ar_hdr.ar_date, "%ld", &lar_date );
@@ -351,29 +364,27 @@ file_archscan(
lar_size = ( lar_size + 1 ) & ~1;
if (ar_hdr.ar_name[0] == '/' && ar_hdr.ar_name[1] == '/' )
if ( ar_hdr.ar_name[ 0 ] == '/' && ar_hdr.ar_name[ 1 ] == '/' )
{
/* this is the "string table" entry of the symbol table,
** which holds strings of filenames that are longer than
** 15 characters (ie. don't fit into a ar_name
*/
string_table = BJAM_MALLOC_ATOMIC(lar_size+1);
if (read(fd, string_table, lar_size) != lar_size)
printf("error reading string table\n");
string_table[lar_size] = '\0';
offset += SARHDR + lar_size;
continue;
/* This is the "string table" entry of the symbol table, holding
* filename strings longer than 15 characters, i.e. those that do
* not fit into ar_name.
*/
string_table = BJAM_MALLOC_ATOMIC( lar_size + 1 );
if ( read( fd, string_table, lar_size ) != lar_size )
printf( "error reading string table\n" );
string_table[ lar_size ] = '\0';
offset += SARHDR + lar_size;
continue;
}
else if (ar_hdr.ar_name[0] == '/' && ar_hdr.ar_name[1] != ' ')
else if ( ar_hdr.ar_name[ 0 ] == '/' && ar_hdr.ar_name[ 1 ] != ' ' )
{
/* Long filenames are recognized by "/nnnn" where nnnn is
** the offset of the string in the string table represented
** in ASCII decimals.
*/
/* Long filenames are recognized by "/nnnn" where nnnn is the
* string's offset in the string table represented in ASCII
* decimals.
*/
name = string_table + atoi( ar_hdr.ar_name + 1 );
for ( endname = name; *endname && *endname != '\n'; ++endname) {}
for ( endname = name; *endname && *endname != '\n'; ++endname );
}
else
{
@@ -385,16 +396,17 @@ file_archscan(
/* strip trailing white-space, slashes, and backslashes */
while ( endname-- > name )
if ( !isspace(*endname) && ( *endname != '\\' ) && ( *endname != '/' ) )
if ( !isspace( *endname ) && ( *endname != '\\' ) && ( *endname !=
'/' ) )
break;
*++endname = 0;
/* strip leading directory names, an NT specialty */
if ( c = strrchr( name, '/' ) )
name = c + 1;
name = c + 1;
if ( c = strrchr( name, '\\' ) )
name = c + 1;
name = c + 1;
sprintf( buf, "%s(%.*s)", archive, endname - name, name );
member = object_new( buf );
@@ -408,4 +420,4 @@ file_archscan(
close( fd );
}
# endif /* NT */
#endif /* OS_NT */

View File

@@ -1,15 +1,17 @@
# include "jam.h"
# include "pathsys.h"
# include "strings.h"
# include "object.h"
# include "filesys.h"
# include "lists.h"
#include "jam.h"
#include "filesys.h"
#include "lists.h"
#include "object.h"
#include "pathsys.h"
#include "strings.h"
void file_build1( PATHNAME * f, string * file )
{
if ( DEBUG_SEARCH )
{
printf("build file: ");
printf( "build file: " );
if ( f->f_root.len )
printf( "root = '%.*s' ", f->f_root.len, f->f_root.ptr );
if ( f->f_dir.len )
@@ -19,26 +21,27 @@ void file_build1( PATHNAME * f, string * file )
printf( "\n" );
}
/* Start with the grist. If the current grist isn't */
/* surrounded by <>'s, add them. */
/* Start with the grist. If the current grist is not surrounded by <>'s, add
* them.
*/
if ( f->f_grist.len )
{
if ( f->f_grist.ptr[0] != '<' )
string_push_back( file, '<' );
string_append_range(
file, f->f_grist.ptr, f->f_grist.ptr + f->f_grist.len );
if ( file->value[file->size - 1] != '>' )
if ( file->value[ file->size - 1 ] != '>' )
string_push_back( 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;
file_info_t * finfo = &filecache_finfo;
int found;
if ( !filecache_hash )
@@ -49,7 +52,6 @@ file_info_t * file_info( OBJECT * filename )
finfo = (file_info_t *)hash_insert( filecache_hash, filename, &found );
if ( !found )
{
/* printf( "file_info: %s\n", filename ); */
finfo->name = object_copy( filename );
finfo->is_file = 0;
finfo->is_dir = 0;
@@ -63,26 +65,28 @@ file_info_t * file_info( OBJECT * filename )
return finfo;
}
static LIST * files_to_remove = L0;
static void remove_files_atexit(void)
static void remove_files_atexit( void )
{
LISTITER iter = list_begin( files_to_remove ), end = list_end( files_to_remove );
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;
}
static void free_file_info ( void * xfile, void * data )
static void free_file_info( void * xfile, void * data )
{
file_info_t * file = (file_info_t *)xfile;
file_info_t * const file = (file_info_t *)xfile;
object_free( file->name );
list_free( file->files );
}
void file_done()
{
remove_files_atexit();
@@ -93,7 +97,8 @@ void file_done()
}
}
void file_remove_atexit( OBJECT * path )
void file_remove_atexit( OBJECT * const path )
{
files_to_remove = list_push_back( files_to_remove, object_copy( path ) );
}

View File

@@ -15,33 +15,34 @@
*/
#ifndef FILESYS_DWA20011025_H
# define FILESYS_DWA20011025_H
#define FILESYS_DWA20011025_H
# include "pathsys.h"
#include "hash.h"
#include "lists.h"
#include "object.h"
#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( const char * arch, 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) ;
void file_build1( PATHNAME * f, string * file ) ;
int file_is_file( OBJECT * filename );
int file_mkdir( const char * pathname );
int file_mkdir( char const * pathname );
typedef struct file_info_t file_info_t ;
struct file_info_t
{
OBJECT * name;
short is_file;
short is_dir;
unsigned long size;
time_t time;
LIST * files;
OBJECT * name;
short is_file;
short is_dir;
unsigned long size;
time_t time;
LIST * files;
};
@@ -55,7 +56,7 @@ file_info_t * file_query( OBJECT * filename );
void file_done();
/* Marks a path/file to be removed when jam exits. */
void file_remove_atexit( OBJECT * path );
/* Marks a path/file to be removed when JAM exits. */
void file_remove_atexit( OBJECT * const path );
#endif

View File

@@ -107,17 +107,11 @@ struct ar_hdr /* archive file member header - printable ascii */
* file_time() - get timestamp of file, if not done by file_dirscan()
* file_archscan() - scan an archive for files
*
* 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 that 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().
*
* 04/08/94 (seiwald) - Coherent/386 support added.
* 12/19/94 (mikem) - solaris string table insanity support
* 02/14/95 (seiwald) - parse and build /xxx properly
* 05/03/96 (seiwald) - split into pathunix.c
* 11/21/96 (peterk) - BEOS does not have Unix-style archives
* 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.
*/
@@ -204,10 +198,11 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure )
if ( !list_empty( d->files ) )
{
LIST * files = d->files;
LISTITER iter = list_begin( files ), end = list_end( files );
LISTITER iter = list_begin( files );
LISTITER const end = list_end( files );
for ( ; iter != end; iter = list_next( iter ) )
{
file_info_t * ff = file_info( list_item( iter ) );
file_info_t * const ff = file_info( list_item( iter ) );
(*func)( closure, ff->name, 1 /* stat()'ed */, ff->time );
files = list_next( files );
}
@@ -219,17 +214,21 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure )
file_info_t * file_query( OBJECT * filename )
{
file_info_t * ff = file_info( filename );
if ( ! ff->time )
file_info_t * const ff = file_info( filename );
if ( !ff->time )
{
struct stat statbuf;
if ( stat( *object_str( filename ) ? object_str( filename ) : ".", &statbuf ) < 0 )
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;
@@ -239,12 +238,9 @@ file_info_t * file_query( OBJECT * filename )
* file_time() - get timestamp of file, if not done by file_dirscan()
*/
int
file_time(
OBJECT * filename,
time_t * time )
int file_time( OBJECT * filename, time_t * time )
{
file_info_t * ff = file_query( filename );
file_info_t const * const ff = file_query( filename );
if ( !ff ) return -1;
*time = ff->time;
return 0;
@@ -252,12 +248,13 @@ file_time(
int file_is_file( OBJECT * filename )
{
file_info_t * ff = file_query( filename );
file_info_t const * const ff = file_query( filename );
if ( !ff ) return -1;
return ff->is_file;
}
int file_mkdir( const char * pathname )
int file_mkdir( char const * pathname )
{
return mkdir( pathname, 0766 );
}
@@ -266,22 +263,18 @@ int file_mkdir( const char * pathname )
* file_archscan() - scan an archive for files
*/
# ifndef AIAMAG /* God-fearing UNIX */
#ifndef AIAMAG /* God-fearing UNIX */
# define SARFMAG 2
# define SARHDR sizeof( struct ar_hdr )
#define SARFMAG 2
#define SARHDR sizeof( struct ar_hdr )
void
file_archscan(
const char * archive,
scanback func,
void * closure )
void file_archscan( char const * archive, scanback func, void * closure )
{
# ifndef NO_AR
#ifndef NO_AR
struct ar_hdr ar_hdr;
char * string_table = 0;
char buf[ MAXJPATH ];
long offset;
char *string_table = 0;
int fd;
if ( ( fd = open( archive, O_RDONLY, 0 ) ) < 0 )
@@ -299,13 +292,13 @@ file_archscan(
if ( DEBUG_BINDSCAN )
printf( "scan archive %s\n", archive );
while ( ( read( fd, &ar_hdr, SARHDR ) == SARHDR )
&& !( memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG )
while ( ( read( fd, &ar_hdr, SARHDR ) == SARHDR ) &&
!( memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG )
#ifdef ARFZMAG
/* OSF also has a compressed format */
&& memcmp( ar_hdr.ar_fmag, ARFZMAG, SARFMAG )
/* OSF also has a compressed format */
&& memcmp( ar_hdr.ar_fmag, ARFZMAG, SARFMAG )
#endif
) )
) )
{
char lar_name_[257];
char * lar_name = lar_name_ + 1;
@@ -317,46 +310,45 @@ file_archscan(
char * dest;
OBJECT * member;
strncpy( lar_name, ar_hdr.ar_name, sizeof(ar_hdr.ar_name) );
strncpy( lar_name, ar_hdr.ar_name, sizeof( ar_hdr.ar_name ) );
sscanf( ar_hdr.ar_date, "%ld", &lar_date );
sscanf( ar_hdr.ar_size, "%ld", &lar_size );
if (ar_hdr.ar_name[0] == '/')
if ( ar_hdr.ar_name[ 0 ] == '/' )
{
if (ar_hdr.ar_name[1] == '/')
{
/* this is the "string table" entry of the symbol table,
** which holds strings of filenames that are longer than
** 15 characters (ie. don't fit into a ar_name
*/
string_table = (char *)BJAM_MALLOC_ATOMIC(lar_size);
lseek(fd, offset + SARHDR, 0);
if (read(fd, string_table, lar_size) != lar_size)
printf("error reading string table\n");
}
else if (string_table && ar_hdr.ar_name[1] != ' ')
{
/* Long filenames are recognized by "/nnnn" where nnnn is
** the offset of the string in the string table represented
** in ASCII decimals.
*/
dest = lar_name;
lar_offset = atoi(lar_name + 1);
src = &string_table[lar_offset];
while (*src != '/')
*dest++ = *src++;
*dest = '/';
}
if ( ar_hdr.ar_name[ 1 ] == '/' )
{
/* This is the "string table" entry of the symbol table, holding
* filename strings longer than 15 characters, i.e. those that
* do not fit into ar_name.
*/
string_table = (char *)BJAM_MALLOC_ATOMIC( lar_size );
lseek( fd, offset + SARHDR, 0 );
if ( read( fd, string_table, lar_size ) != lar_size )
printf("error reading string table\n");
}
else if ( string_table && ar_hdr.ar_name[ 1 ] != ' ' )
{
/* Long filenames are recognized by "/nnnn" where nnnn is the
* offset of the string in the string table represented in ASCII
* decimals.
*/
dest = lar_name;
lar_offset = atoi( lar_name + 1 );
src = &string_table[ lar_offset ];
while ( *src != '/' )
*dest++ = *src++;
*dest = '/';
}
}
c = lar_name - 1;
while ( ( *++c != ' ' ) && ( *c != '/' ) ) ;
while ( ( *++c != ' ' ) && ( *c != '/' ) );
*c = '\0';
if ( DEBUG_BINDSCAN )
printf( "archive name %s found\n", lar_name );
printf( "archive name %s found\n", lar_name );
sprintf( buf, "%s(%s)", archive, lar_name );
@@ -373,14 +365,14 @@ file_archscan(
close( fd );
# endif /* NO_AR */
#endif /* NO_AR */
}
# else /* AIAMAG - RS6000 AIX */
#else /* AIAMAG - RS6000 AIX */
static void file_archscan_small(
int fd, char const *archive, scanback func, void *closure)
static void file_archscan_small( int fd, char const * archive, scanback func,
void * closure )
{
struct fl_hdr fl_hdr;
@@ -400,12 +392,11 @@ static void file_archscan_small(
if ( DEBUG_BINDSCAN )
printf( "scan archive %s\n", archive );
while ( ( offset > 0 )
&& ( lseek( fd, offset, 0 ) >= 0 )
&& ( read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= (int)sizeof( ar_hdr.hdr ) ) )
while ( offset > 0 && lseek( fd, offset, 0 ) >= 0 &&
read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= (int)sizeof( ar_hdr.hdr ) )
{
long lar_date;
int lar_namlen;
int lar_namlen;
OBJECT * member;
sscanf( ar_hdr.hdr.ar_namlen, "%d" , &lar_namlen );
@@ -428,8 +419,8 @@ static void file_archscan_small(
/* Check for OS version which supports the big variant. */
#ifdef AR_HSZ_BIG
static void file_archscan_big(
int fd, char const *archive, scanback func, void *closure)
static void file_archscan_big( int fd, char const * archive, scanback func,
void * closure )
{
struct fl_hdr_big fl_hdr;
@@ -449,9 +440,8 @@ static void file_archscan_big(
if ( DEBUG_BINDSCAN )
printf( "scan archive %s\n", archive );
while ( ( offset > 0 )
&& ( lseek( fd, offset, 0 ) >= 0 )
&& ( read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= sizeof( ar_hdr.hdr ) ) )
while ( offset > 0 && lseek( fd, offset, 0 ) >= 0 &&
read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= sizeof( ar_hdr.hdr ) )
{
long lar_date;
int lar_namlen;
@@ -472,33 +462,32 @@ static void file_archscan_big(
(*func)( closure, member, 1 /* time valid */, (time_t)lar_date );
object_free( member );
}
}
#endif /* AR_HSZ_BIG */
void file_archscan( const char * archive, scanback func, void *closure)
void file_archscan( char const * archive, scanback func, void * closure )
{
int fd;
char fl_magic[SAIAMAG];
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
|| lseek(fd, 0, SEEK_SET) == -1)
if ( read( fd, fl_magic, SAIAMAG ) != SAIAMAG ||
lseek( fd, 0, SEEK_SET ) == -1 )
{
close(fd);
close( fd );
return;
}
if ( strncmp( AIAMAG, fl_magic, SAIAMAG ) == 0 )
if ( !strncmp( AIAMAG, fl_magic, SAIAMAG ) )
{
/* read small variant */
file_archscan_small( fd, archive, func, closure );
}
#ifdef AR_HSZ_BIG
else if ( strncmp( AIAMAGBIG, fl_magic, SAIAMAG ) == 0 )
else if ( !strncmp( AIAMAGBIG, fl_magic, SAIAMAG ) )
{
/* read big variant */
file_archscan_big( fd, archive, func, closure );

View File

@@ -7,23 +7,22 @@
#include "jam.h"
#include "function.h"
#include "lists.h"
#include "pathsys.h"
#include "mem.h"
#include "constants.h"
#include "frames.h"
#include "rules.h"
#include "variable.h"
#include "compile.h"
#include "search.h"
#include "class.h"
#include "pathsys.h"
#include "compile.h"
#include "constants.h"
#include "filesys.h"
#include "frames.h"
#include "lists.h"
#include "mem.h"
#include "pathsys.h"
#include "rules.h"
#include "search.h"
#include "variable.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef OS_CYGWIN
# include <cygwin/version.h>
@@ -650,7 +649,9 @@ static void var_edit_cyg2win( string * out, size_t pos, VAR_EDITS * edits )
if ( edits->to_windows )
{
#ifdef CYGWIN_VERSION_CYGWIN_CONV
/* Use new Cygwin API added with Cygwin 1.7. */
/* Use new Cygwin API added with Cygwin 1.7. Old one had no error
* handling and has been deprecated.
*/
char * dynamicBuffer = 0;
char buffer[ MAX_PATH + 1001 ];
char const * result = buffer;

View File

@@ -4,28 +4,26 @@
* This file is part of Jam - see jam.c for Copyright information.
*/
# include "jam.h"
# include "hash.h"
# include "compile.h"
# include "object.h"
# include <assert.h>
/*
* hash.c - simple in-memory hashing routines
*
* External routines:
*
* hashinit() - initialize a hash table, returning a handle
* hashitem() - find a record in the table, and optionally enter a new one
* hashdone() - free a hash table, given its handle
*
* Internal routines:
*
* hashrehash() - resize and rebuild hp->tab, the hash table
*
* 4/29/93 - ensure ITEM's are aligned
*/
#include "jam.h"
#include "hash.h"
#include "compile.h"
#include "object.h"
#include <assert.h>
/* */
#define HASH_DEBUG_PROFILE 1
/* */
@@ -51,7 +49,7 @@ struct hash
*/
struct {
int nel;
ITEM **base;
ITEM * * base;
} tab;
int bloat; /* tab.nel / items.nel */
@@ -62,66 +60,61 @@ struct hash
* essentially a microallocator
*/
struct {
int more; /* how many more ITEMs fit in lists[ list ] */
ITEM *free; /* free list of items */
char *next; /* where to put more ITEMs in lists[ list ] */
int size; /* sizeof( ITEM ) + aligned datalen */
int nel; /* total ITEMs held by all lists[] */
int list; /* index into lists[] */
int more; /* how many more ITEMs fit in lists[ list ] */
ITEM * free; /* free list of items */
char * next; /* where to put more ITEMs in lists[ list ] */
int size; /* sizeof( ITEM ) + aligned datalen */
int nel; /* total ITEMs held by all lists[] */
int list; /* index into lists[] */
struct {
int nel; /* total ITEMs held by this list */
char *base; /* base of ITEMs array */
int nel; /* total ITEMs held by this list */
char *base; /* base of ITEMs array */
} lists[ MAX_LISTS ];
} items;
const char * name; /* just for hashstats() */
char const * name; /* just for hashstats() */
};
static void hashrehash( struct hash *hp );
static void hashstat( struct hash *hp );
static void hashrehash( struct hash * );
static void hashstat( struct hash * );
static unsigned int hash_keyval( OBJECT * key )
{
return object_hash( key );
}
#define hash_bucket(hp,keyval) ((hp)->tab.base + ( (keyval) % (hp)->tab.nel ))
#define hash_bucket(hp, keyval) ((hp)->tab.base + ((keyval) % (hp)->tab.nel))
#define hash_data_key(data) (*(OBJECT * *)(data))
#define hash_item_data(item) ((HASHDATA *)((char *)item + sizeof(struct hashhdr)))
#define hash_item_key(item) (hash_data_key(hash_item_data(item)))
/* Find the hash item for the given data. Returns pointer to the
item and if given a pointer to the item before the found item.
If it's the first item in a bucket, there is no previous item,
and zero is returned for the previous item instead.
*/
static ITEM * hash_search(
struct hash *hp,
unsigned int keyval,
OBJECT * keydata,
ITEM * * previous )
{
ITEM * i = *hash_bucket(hp,keyval);
ITEM * p = 0;
/* Find the hash item for the given data. Returns a pointer to a hashed item
* with the given key. If given a 'previous' pointer, makes it point to the item
* prior to the found item in the same bucket or to 0 if our item is the first
* item in its bucket.
*/
static ITEM * hash_search( struct hash * hp, unsigned int keyval,
OBJECT * keydata, ITEM * * previous )
{
ITEM * i = *hash_bucket( hp, keyval );
ITEM * p = 0;
for ( ; i; i = i->hdr.next )
{
if ( object_equal( hash_item_key( i ), keydata ) )
{
if (previous)
{
if ( previous )
*previous = p;
}
return i;
}
p = i;
}
return 0;
}
/*
* hash_insert() - insert a record in the table or return the existing one
*/
@@ -132,7 +125,7 @@ HASHDATA * hash_insert( struct hash * hp, OBJECT * key, int * found )
unsigned int keyval = hash_keyval( key );
#ifdef HASH_DEBUG_PROFILE
profile_frame prof[1];
profile_frame prof[ 1 ];
if ( DEBUG_PROFILE )
profile_enter( 0, prof );
#endif
@@ -142,14 +135,12 @@ HASHDATA * hash_insert( struct hash * hp, OBJECT * key, int * found )
i = hash_search( hp, keyval, key, 0 );
if ( i )
{
*found = 1;
}
else
{
ITEM * * base = hash_bucket( hp, keyval );
/* try to grab one from the free list */
/* Try to grab one from the free list. */
if ( hp->items.free )
{
i = hp->items.free;
@@ -161,7 +152,7 @@ HASHDATA * hash_insert( struct hash * hp, OBJECT * key, int * found )
i = (ITEM *)hp->items.next;
hp->items.next += hp->items.size;
}
hp->items.more--;
--hp->items.more;
i->hdr.next = *base;
*base = i;
*found = 0;
@@ -175,17 +166,18 @@ HASHDATA * hash_insert( struct hash * hp, OBJECT * key, int * found )
return hash_item_data( i );
}
/*
* hash_find() - find a record in the table or NULL if none exists
*/
HASHDATA * hash_find( struct hash *hp, OBJECT *key )
HASHDATA * hash_find( struct hash * hp, OBJECT * key )
{
ITEM *i;
unsigned int keyval = hash_keyval(key);
ITEM * i;
unsigned int keyval = hash_keyval( key );
#ifdef HASH_DEBUG_PROFILE
profile_frame prof[1];
profile_frame prof[ 1 ];
if ( DEBUG_PROFILE )
profile_enter( 0, prof );
#endif
@@ -206,16 +198,10 @@ HASHDATA * hash_find( struct hash *hp, OBJECT *key )
profile_exit( prof );
#endif
if (i)
{
return hash_item_data( i );
}
else
{
return 0;
}
return i ? hash_item_data( i ) : 0;
}
/*
* hashrehash() - resize and rebuild hp->tab, the hash table
*/
@@ -227,8 +213,8 @@ static void hashrehash( register struct hash *hp )
hp->items.next = (char *)BJAM_MALLOC( hp->items.more * hp->items.size );
hp->items.free = 0;
hp->items.lists[i].nel = hp->items.more;
hp->items.lists[i].base = hp->items.next;
hp->items.lists[ i ].nel = hp->items.more;
hp->items.lists[ i ].base = hp->items.next;
hp->items.nel += hp->items.more;
if ( hp->tab.base )
@@ -241,13 +227,13 @@ static void hashrehash( register struct hash *hp )
for ( i = 0; i < hp->items.list; ++i )
{
int nel = hp->items.lists[i].nel;
char *next = hp->items.lists[i].base;
int nel = hp->items.lists[ i ].nel;
char * next = hp->items.lists[ i ].base;
for ( ; nel--; next += hp->items.size )
{
register ITEM *i = (ITEM *)next;
ITEM **ip = hp->tab.base + object_hash( hash_item_key( i ) ) % hp->tab.nel;
register ITEM * i = (ITEM *)next;
ITEM * * ip = hp->tab.base + object_hash( hash_item_key( i ) ) % hp->tab.nel;
/* code currently assumes rehashing only when there are no free items */
assert( hash_item_key( i ) != 0 );
@@ -257,6 +243,7 @@ static void hashrehash( register struct hash *hp )
}
}
void hashenumerate( struct hash * hp, void (* f)( void *, void * ), void * data )
{
int i;
@@ -270,7 +257,7 @@ void hashenumerate( struct hash * hp, void (* f)( void *, void * ), void * data
for ( ; nel--; next += hp->items.size )
{
ITEM * i = (ITEM *)next;
if ( hash_item_key( i ) != 0 ) /* DO not enumerate freed items. */
if ( hash_item_key( i ) != 0 ) /* Do not enumerate freed items. */
f( hash_item_data( i ), data );
}
}
@@ -278,33 +265,31 @@ void hashenumerate( struct hash * hp, void (* f)( void *, void * ), void * data
/* --- */
# define ALIGNED(x) ( ( x + sizeof( ITEM ) - 1 ) & ~( sizeof( ITEM ) - 1 ) )
#define ALIGNED(x) ((x + sizeof(ITEM) - 1) & ~(sizeof(ITEM) - 1))
/*
* hashinit() - initialize a hash table, returning a handle
*/
struct hash *
hashinit(
int datalen,
const char *name )
struct hash * hashinit( int datalen, char const * name )
{
struct hash *hp = (struct hash *)BJAM_MALLOC( sizeof( *hp ) );
struct hash * hp = (struct hash *)BJAM_MALLOC( sizeof( *hp ) );
hp->bloat = 3;
hp->tab.nel = 0;
hp->tab.base = (ITEM **)0;
hp->tab.base = (ITEM * *)0;
hp->items.more = 0;
hp->items.free = 0;
hp->items.size = sizeof( struct hashhdr ) + ALIGNED( datalen );
hp->items.list = -1;
hp->items.nel = 0;
hp->inel = 11 /* 47 */;
hp->inel = 11; /* 47 */
hp->name = name;
return hp;
}
void hashdone( struct hash * hp )
{
if ( !hp )
@@ -314,22 +299,20 @@ void hashdone( struct hash * hp )
hash_free( hp );
}
/*
* hash_free() - free a hash table, given its handle
*/
void
hash_free( struct hash * hp )
void hash_free( struct hash * hp )
{
int i;
if ( !hp )
return;
if ( hp->tab.base )
BJAM_FREE( (char *)hp->tab.base );
for ( i = 0; i <= hp->items.list; ++i )
BJAM_FREE( hp->items.lists[i].base );
BJAM_FREE( hp->items.lists[ i ].base );
BJAM_FREE( (char *)hp );
}
@@ -367,7 +350,7 @@ void hashstats_add( struct hashstats * stats, struct hash * hp )
{
ITEM * item;
int here = 0;
for ( item = tab[ i ]; item != 0; item = item->hdr.next )
for ( item = tab[ i ]; item; item = item->hdr.next )
++here;
count += here;
@@ -383,7 +366,7 @@ void hashstats_add( struct hashstats * stats, struct hash * hp )
}
}
void hashstats_print( struct hashstats * stats, const char * name )
void hashstats_print( struct hashstats * stats, char const * name )
{
printf( "%s table: %d+%d+%d (%dK+%luK) items+table+hash, %f density\n",
name,

View File

@@ -11,57 +11,57 @@
#ifndef BOOST_JAM_HASH_H
#define BOOST_JAM_HASH_H
#include "object.h"
/*
* An opaque struct representing an item in the
* hash table. The first element of every struct
* stored in the table must be an OBJECT * which
* is treated as the key.
* An opaque struct representing an item in the hash table. The first element of
* every struct stored in the table must be an OBJECT * which is treated as the
* key.
*/
typedef struct hashdata HASHDATA;
/*
* hashinit() - initialize a hash table, returning a handle.
* datalen is the size of the items. name is used for debugging.
*
* Parameters:
* datalen - item size
* name - used for debugging
*/
struct hash * hashinit ( int datalen, const char * name );
struct hash * hashinit( int datalen, char const * name );
/*
* hash_free() - free a hash table, given its handle
*/
void hash_free( struct hash * hp );
void hashdone( struct hash * hp );
void hash_free( struct hash * );
void hashdone( struct hash * );
/*
* hashenumerate() - call f(i, data) on each item, i in the hash
* table. The order of the items is unspecified.
* hashenumerate() - call f(i, data) on each item, i in the hash table. The
* enumeration order is unspecified.
*/
void hashenumerate( struct hash * hp, void (* f)( void *, void * ), void * data );
void hashenumerate( struct hash *, void (* f)( void *, void * ), void * data );
/*
* hash_insert() - insert a new item in a hash table, or return an
* existing one.
* hash_insert() - insert a new item in a hash table, or return an existing one.
*
* Preconditions:
* - hp must be a hash table created by hashinit
* - key must be an object created by object_new
* - hp must be a hash table created by hashinit()
* - key must be an object created by object_new()
*
* Postconditions:
* - if the key does not already exist in the hash
* table, *found == 0 and the result will be a
* pointer to an uninitialized item. The key
* of the new item must be set to a value equal to
* key before any further operations on the
* hash table except hashdone.
* - if the key is present then *found == 1 and
* the result is a pointer to the existing
* record.
* - if the key does not already exist in the hash table, *found == 0 and the
* result will be a pointer to an uninitialized item. The key of the new
* item must be set to a value equal to key before any further operations on
* the hash table except hashdone().
* - if the key is present then *found == 1 and the result is a pointer to the
* existing record.
*/
HASHDATA * hash_insert ( struct hash * hp, OBJECT * key, int * found );
HASHDATA * hash_insert( struct hash *, OBJECT * key, int * found );
/*
* hash_find() - find a record in the table or NULL if none exists
*/
HASHDATA * hash_find ( struct hash * hp, OBJECT * key );
HASHDATA * hash_find( struct hash *, OBJECT * key );
struct hashstats {
int count;
@@ -73,6 +73,6 @@ struct hashstats {
void hashstats_init( struct hashstats * stats );
void hashstats_add( struct hashstats * stats, struct hash * hp );
void hashstats_print( struct hashstats * stats, const char * name );
void hashstats_print( struct hashstats * stats, char const * name );
#endif

View File

@@ -2,21 +2,6 @@
* This file has been donated to Jam.
*/
# include "jam.h"
# include "lists.h"
# include "parse.h"
# include "rules.h"
# include "regexp.h"
# include "headers.h"
# include "object.h"
# include "hash.h"
# include "hcache.h"
# include "variable.h"
# include "search.h"
# include "modules.h"
#ifdef OPT_HEADER_CACHE_EXT
/*
* Craig W. McPheeters, Alias|Wavefront.
*
@@ -28,7 +13,7 @@
* files found in their scan. During the binding phase of jam, look in the
* header cache first for the headers contained in a file. If the cache is
* present and valid, use its contents. This results in dramatic speedups with
* large projects (eg. 3min -> 1min startup for one project.)
* large projects (e.g. 3min -> 1min startup for one project.)
*
* External routines:
* hcache_init() - read and parse the local .jamdeps file.
@@ -37,9 +22,25 @@
*
* The dependency file format is an ASCII file with 1 line per target. Each line
* has the following fields:
* @boundname@ timestamp @file@ @file@ @file@ ... \n
* @boundname@ timestamp @file@ @file@ @file@ ...
*/
#ifdef OPT_HEADER_CACHE_EXT
#include "jam.h"
#include "hcache.h"
#include "hash.h"
#include "headers.h"
#include "lists.h"
#include "modules.h"
#include "object.h"
#include "parse.h"
#include "regexp.h"
#include "rules.h"
#include "search.h"
#include "variable.h"
typedef struct hcachedata HCACHEDATA ;
struct hcachedata
@@ -48,13 +49,13 @@ struct hcachedata
time_t time;
LIST * includes;
LIST * hdrscan; /* the HDRSCAN value for this target */
int age; /* if too old, we'll remove it from cache */
int age; /* if too old, we will remove it from cache */
HCACHEDATA * next;
};
static struct hash * hcachehash = 0;
static HCACHEDATA * hcachelist = 0;
static HCACHEDATA * hcachelist = 0;
static int queries = 0;
static int hits = 0;
@@ -76,11 +77,11 @@ static const char * cache_name( void )
static OBJECT * name = 0;
if ( !name )
{
LIST * hcachevar = var_get( root_module(), constant_HCACHEFILE );
LIST * const hcachevar = var_get( root_module(), constant_HCACHEFILE );
if ( !list_empty( hcachevar ) )
{
TARGET * t = bindtarget( list_front( hcachevar ) );
TARGET * const t = bindtarget( list_front( hcachevar ) );
pushsettings( root_module(), t->settings );
/* Do not expect the cache file to be generated, so pass 0 as the
@@ -99,14 +100,14 @@ static const char * cache_name( void )
/*
* Return the maximum age a cache entry can have before it is purged ftom the
* Return the maximum age a cache entry can have before it is purged from the
* cache.
*/
static int cache_maxage( void )
{
int age = 100;
LIST * var = var_get( root_module(), constant_HCACHEMAXAGE );
LIST * const var = var_get( root_module(), constant_HCACHEMAXAGE );
if ( !list_empty( var ) )
{
age = atoi( object_str( list_front( var ) ) );
@@ -235,7 +236,8 @@ void hcache_init()
age_str = read_netstring( f );
includes_count_str = read_netstring( f );
if ( !cachedata.boundname || !time_str || !age_str || !includes_count_str )
if ( !cachedata.boundname || !time_str || !age_str ||
!includes_count_str )
{
fprintf( stderr, "invalid %s\n", hcachename );
goto cleanup;
@@ -268,7 +270,7 @@ void hcache_init()
count = atoi( object_str( hdrscan_count_str ) );
for ( l = L0, i = 0; i < count; ++i )
{
OBJECT * s = read_netstring( f );
OBJECT * const s = read_netstring( f );
if ( !s )
{
fprintf( stderr, "invalid %s\n", hcachename );
@@ -279,7 +281,8 @@ void hcache_init()
}
cachedata.hdrscan = l;
c = (HCACHEDATA *)hash_insert( hcachehash, cachedata.boundname, &found );
c = (HCACHEDATA *)hash_insert( hcachehash, cachedata.boundname, &found )
;
if ( !found )
{
c->boundname = cachedata.boundname;
@@ -290,8 +293,8 @@ void hcache_init()
}
else
{
fprintf( stderr, "can't insert header cache item, bailing on %s\n",
hcachename );
fprintf( stderr, "can not insert header cache item, bailing on %s"
"\n", hcachename );
goto cleanup;
}
@@ -299,7 +302,7 @@ void hcache_init()
hcachelist = c;
++header_count;
object_free( record_type );
object_free( time_str );
object_free( age_str );
@@ -357,11 +360,12 @@ void hcache_done()
c = hcachelist;
for ( c = hcachelist; c; c = c->next )
{
LISTITER iter, end;
char time_str[ 30 ];
char age_str[ 30 ];
char includes_count_str[ 30 ];
char hdrscan_count_str[ 30 ];
LISTITER iter;
LISTITER end;
char time_str[ 30 ];
char age_str[ 30 ];
char includes_count_str[ 30 ];
char hdrscan_count_str[ 30 ];
if ( maxage == 0 )
c->age = 0;
@@ -370,8 +374,8 @@ void hcache_done()
sprintf( includes_count_str, "%lu", (long unsigned) list_length( c->includes ) );
sprintf( hdrscan_count_str, "%lu", (long unsigned) list_length( c->hdrscan ) );
sprintf( time_str, "%lu", (long unsigned) c->time );
sprintf( age_str, "%lu", (long unsigned) c->age );
sprintf( time_str, "%lu", (long unsigned)c->time );
sprintf( age_str, "%lu", (long unsigned)c->age );
write_netstring( f, CACHE_RECORD_HEADER );
write_netstring( f, object_str( c->boundname ) );
@@ -395,7 +399,7 @@ void hcache_done()
hcachename, header_count, queries ? 100.0 * hits / queries : 0 );
fclose ( f );
cleanup:
for ( c = hcachelist; c; c = c->next )
{
@@ -423,15 +427,16 @@ LIST * hcache( TARGET * t, int rec, regexp * re[], LIST * hdrscan )
{
if ( c->time == t->time )
{
LIST *l1 = hdrscan, *l2 = c->hdrscan;
LISTITER iter1 = list_begin( l1 ), end1 = list_end( l1 ),
iter2 = list_begin( l2 ), end2 = list_end( l2 );
LIST * const l1 = hdrscan;
LIST * const l2 = c->hdrscan;
LISTITER iter1 = list_begin( l1 );
LISTITER const end1 = list_end( l1 );
LISTITER iter2 = list_begin( l2 );
LISTITER const end2 = list_end( l2 );
while ( iter1 != end1 && iter2 != end2 )
{
if ( !object_equal( list_item( iter1 ), list_item( iter2 ) ) )
{
iter1 = end1;
}
else
{
iter1 = list_next( iter1 );
@@ -440,12 +445,12 @@ LIST * hcache( TARGET * t, int rec, regexp * re[], LIST * hdrscan )
}
if ( iter1 != end1 || iter2 != end2 )
{
if (DEBUG_HEADER)
if ( DEBUG_HEADER )
printf( "HDRSCAN out of date in cache for %s\n",
object_str( t->boundname ) );
printf( "HDRSCAN out of date for %s\n",
object_str( t->boundname ) );
printf( "HDRSCAN out of date for %s\n", object_str(
t->boundname ) );
printf(" real : ");
list_print( hdrscan );
printf( "\n cached: " );
@@ -459,9 +464,9 @@ LIST * hcache( TARGET * t, int rec, regexp * re[], LIST * hdrscan )
}
else
{
if (DEBUG_HEADER)
printf( "using header cache for %s\n",
object_str( t->boundname ) );
if ( DEBUG_HEADER )
printf( "using header cache for %s\n", object_str(
t->boundname ) );
c->age = 0;
++hits;
l = list_copy( c->includes );
@@ -470,9 +475,9 @@ LIST * hcache( TARGET * t, int rec, regexp * re[], LIST * hdrscan )
}
else
{
if (DEBUG_HEADER)
printf ("header cache out of date for %s\n",
object_str( t->boundname ) );
if ( DEBUG_HEADER )
printf ("header cache out of date for %s\n", object_str(
t->boundname ) );
list_free( c->includes );
list_free( c->hdrscan );
c->includes = L0;
@@ -503,4 +508,4 @@ LIST * hcache( TARGET * t, int rec, regexp * re[], LIST * hdrscan )
return l;
}
#endif
#endif /* OPT_HEADER_CACHE_EXT */

View File

@@ -6,13 +6,14 @@
* hcache.h - handle #includes in source files
*/
#ifndef HCACHE_H
# define HCACHE_H
#define HCACHE_H
# include "regexp.h"
# include "lists.h"
#include "lists.h"
#include "regexp.h"
#include "rules.h"
void hcache_init( void );
void hcache_done( void );
LIST * hcache( TARGET *t, int rec, regexp * re[], LIST * hdrscan );
LIST * hcache( TARGET * t, int rec, regexp * re[], LIST * hdrscan );
#endif

View File

@@ -12,8 +12,11 @@
#ifndef HDRMACRO_SW20111118_H
#define HDRMACRO_SW20111118_H
void macro_headers( TARGET *t );
#include "object.h"
#include "rules.h"
OBJECT * macro_header_get( OBJECT * macro_name );
void macro_headers( TARGET * t );
OBJECT * macro_header_get( OBJECT * macro_name );
#endif

View File

@@ -440,7 +440,7 @@ extern struct globs globs;
#define DEBUG_MAKE ( globs.debug[ 1 ] ) /* show actions when executed */
#define DEBUG_MAKEQ ( globs.debug[ 2 ] ) /* show even quiet actions */
#define DEBUG_EXEC ( globs.debug[ 2 ] ) /* show text of actons */
#define DEBUG_MAKEPROG ( globs.debug[ 3 ] ) /* show progress of make0 */
#define DEBUG_MAKEPROG ( globs.debug[ 3 ] ) /* show make0 progress */
#define DEBUG_BIND ( globs.debug[ 3 ] ) /* show when files bound */
#define DEBUG_EXECCMD ( globs.debug[ 4 ] ) /* show execcmds()'s work */
@@ -449,7 +449,7 @@ extern struct globs globs;
#define DEBUG_HEADER ( globs.debug[ 6 ] ) /* show result of header scan */
#define DEBUG_BINDSCAN ( globs.debug[ 6 ] ) /* show result of dir scan */
#define DEBUG_SEARCH ( globs.debug[ 6 ] ) /* show attempts at binding */
#define DEBUG_SEARCH ( globs.debug[ 6 ] ) /* show binding attempts */
#define DEBUG_VARSET ( globs.debug[ 7 ] ) /* show variable settings */
#define DEBUG_VARGET ( globs.debug[ 8 ] ) /* show variable fetches */
@@ -462,7 +462,7 @@ extern struct globs globs;
#define DEBUG_PROFILE ( globs.debug[ 10 ] ) /* dump rule execution times */
#define DEBUG_PARSE ( globs.debug[ 11 ] ) /* debug parsing */
#define DEBUG_GRAPH ( globs.debug[ 12 ] ) /* debug dependencies */
#define DEBUG_FATE ( globs.debug[ 13 ] ) /* show changes to fate in make0() */
#define DEBUG_FATE ( globs.debug[ 13 ] ) /* show fate changes in make0() */
/* Everyone gets the memory definitions. */
#include "mem.h"

View File

@@ -27,45 +27,27 @@
* Internal routines:
* make0() - bind and scan everything to make a TARGET
* make0sort() - reorder TARGETS chain by their time (newest to oldest)
*
* 12/26/93 (seiwald) - allow NOTIME targets to be expanded via $(<), $(>).
* 01/04/94 (seiwald) - print all targets, bounded, when tracing commands.
* 04/08/94 (seiwald) - progress report now reflects only targets with actions.
* 04/11/94 (seiwald) - Combined deps & headers into deps[2] in TARGET.
* 12/20/94 (seiwald) - NOTIME renamed NOTFILE.
* 12/20/94 (seiwald) - make0() headers after determining fate of target, so
* that headers are not seen as being dependent on
* themselves.
* 01/19/95 (seiwald) - distinguish between CANTFIND/CANTMAKE targets.
* 02/02/95 (seiwald) - propagate leaf source time for new LEAVES rule.
* 02/14/95 (seiwald) - NOUPDATE rule means don't update existing target.
* 08/22/95 (seiwald) - NOUPDATE targets immune to anyhow (-a) flag.
* 09/06/00 (seiwald) - NOCARE affects targets with sources/actions.
* 03/02/01 (seiwald) - reverse NOCARE change.
* 03/14/02 (seiwald) - TEMPORARY targets no longer take on parents age.
* 03/16/02 (seiwald) - support for -g (reorder builds by source time).
*/
#include "jam.h"
#include "lists.h"
#include "parse.h"
#include "variable.h"
#include "rules.h"
#ifdef OPT_HEADER_CACHE_EXT
#include "hcache.h"
#endif
#include "search.h"
#include "object.h"
#include "make.h"
#include "headers.h"
#include "command.h"
#ifdef OPT_HEADER_CACHE_EXT
# include "hcache.h"
#endif
#include "headers.h"
#include "lists.h"
#include "make.h"
#include "object.h"
#include "parse.h"
#include "rules.h"
#include "search.h"
#include "variable.h"
#include <assert.h>
#ifndef max
#define max( a,b ) ((a)>(b)?(a):(b))
# define max(a,b) ((a)>(b)?(a):(b))
#endif
static TARGETS * make0sort( TARGETS * c );
@@ -99,7 +81,7 @@ static const char * target_bind[] =
"exists",
};
# define spaces(x) ( " " + ( x > 20 ? 0 : 20-x ) )
#define spaces(x) ( " " + ( x > 20 ? 0 : 20-x ) )
/*
@@ -109,7 +91,7 @@ static const char * target_bind[] =
int make( LIST * targets, int anyhow )
{
COUNTS counts[ 1 ];
int status = 0; /* 1 if anything fails */
int status = 0; /* 1 if anything fails */
#ifdef OPT_HEADER_CACHE_EXT
hcache_init();
@@ -165,9 +147,11 @@ int make( LIST * targets, int anyhow )
status = counts->cantfind || counts->cantmake;
{
LISTITER iter, end;
LISTITER iter;
LISTITER end;
PROFILE_ENTER( MAKE_MAKE1 );
for ( iter = list_begin( targets ), end = list_end( targets ); iter != end; iter = list_next( iter ) )
for ( iter = list_begin( targets ), end = list_end( targets ); iter !=
end; iter = list_next( iter ) )
status |= make1( bindtarget( list_item( iter ) ) );
PROFILE_EXIT( MAKE_MAKE1 );
}
@@ -310,7 +294,8 @@ void make0
SETTINGS * s;
#ifdef OPT_GRAPH_DEBUG_EXT
int savedFate, oldTimeStamp;
int savedFate;
int oldTimeStamp;
#endif
if ( DEBUG_MAKEPROG )
@@ -327,8 +312,8 @@ void make0
t->depth = depth;
/*
* Step 2: under the influence of "on target" variables,
* bind the target and search for headers.
* Step 2: under the influence of "on target" variables, bind the target and
* search for headers.
*/
/* Step 2a: set "on target" variables. */
@@ -341,10 +326,10 @@ void make0
OBJECT * another_target;
object_free( t->boundname );
t->boundname = search( t->name, &t->time, &another_target,
t->flags & T_FLAG_ISFILE );
t->flags & T_FLAG_ISFILE );
/* If it was detected that this target refers to an already existing and
* bound one, we add a dependency, so that every target
* depending on us will depend on that other target as well.
* bound target, we add a dependency so that every target depending on
* us will depend on that other target as well.
*/
if ( another_target )
located_target = bindtarget( another_target );
@@ -370,7 +355,7 @@ void make0
LIST * var = var_get( root_module(), constant_JAM_SEMAPHORE );
if ( !list_empty( var ) )
{
TARGET * semaphore = bindtarget( list_front( var ) );
TARGET * const semaphore = bindtarget( list_front( var ) );
semaphore->progress = T_MAKE_SEMAPHORE;
t->semaphore = semaphore;
}
@@ -386,27 +371,27 @@ void make0
freesettings( s );
/*
* Pause for a little progress reporting .
* Pause for a little progress reporting.
*/
if ( DEBUG_BIND )
{
if ( ! object_equal( t->name, t->boundname ) )
printf( "bind\t--\t%s%s: %s\n",
spaces( depth ), object_str( t->name ), object_str( t->boundname ) );
if ( !object_equal( t->name, t->boundname ) )
printf( "bind\t--\t%s%s: %s\n", spaces( depth ),
object_str( t->name ), object_str( t->boundname ) );
switch ( t->binding )
{
case T_BIND_UNBOUND:
case T_BIND_MISSING:
case T_BIND_PARENTS:
printf( "time\t--\t%s%s: %s\n",
spaces( depth ), object_str( t->name ), target_bind[ (int) t->binding ] );
printf( "time\t--\t%s%s: %s\n", spaces( depth ),
object_str( t->name ), target_bind[ (int)t->binding ] );
break;
case T_BIND_EXISTS:
printf( "time\t--\t%s%s: %s",
spaces( depth ), object_str( t->name ), ctime( &t->time ) );
printf( "time\t--\t%s%s: %s", spaces( depth ),
object_str( t->name ), ctime( &t->time ) );
break;
}
}
@@ -418,7 +403,7 @@ void make0
/* Step 3a: recursively make0() dependencies. */
for ( c = t->depends; c; c = c->next )
{
int internal = t->flags & T_FLAG_INTERNAL;
int const internal = t->flags & T_FLAG_INTERNAL;
/* Warn about circular deps, except for includes, which include each
* other alot.
@@ -426,17 +411,20 @@ void make0
if ( c->target->fate == T_FATE_INIT )
make0( c->target, ptime, depth + 1, counts, anyhow, rescanning );
else if ( c->target->fate == T_FATE_MAKING && !internal )
printf( "warning: %s depends on itself\n", object_str( c->target->name ) );
printf( "warning: %s depends on itself\n", object_str(
c->target->name ) );
else if ( c->target->fate != T_FATE_MAKING && rescanning )
make0rescan( c->target, rescanning );
if ( rescanning && c->target->includes && c->target->includes->fate != T_FATE_MAKING )
if ( rescanning && c->target->includes && c->target->includes->fate !=
T_FATE_MAKING )
make0rescan( target_scc( c->target->includes ), rescanning );
}
if ( located_target )
{
if ( located_target->fate == T_FATE_INIT )
make0( located_target, ptime, depth + 1, counts, anyhow, rescanning );
make0( located_target, ptime, depth + 1, counts, anyhow, rescanning
);
else if ( located_target->fate != T_FATE_MAKING && rescanning )
make0rescan( located_target, rescanning );
}
@@ -486,12 +474,12 @@ void make0
fate = T_FATE_STABLE;
for ( c = t->depends; c; c = c->next )
{
/* If we're in a different strongly connected component,
* pull timestamps from the root.
/* If we are in a different strongly connected component, pull
* timestamps from the root.
*/
if ( c->target->scc_root )
{
TARGET * scc_root = target_scc( c->target );
TARGET * const scc_root = target_scc( c->target );
if ( scc_root != t->scc_root )
{
c->target->leaf = max( c->target->leaf, scc_root->leaf );
@@ -504,13 +492,11 @@ void make0
* source nodes.
*/
leaf = max( leaf, c->target->leaf );
if ( t->flags & T_FLAG_LEAVES )
{
last = leaf;
continue;
}
last = max( last, c->target->time );
fate = max( fate, c->target->fate );
@@ -518,18 +504,18 @@ void make0
if ( DEBUG_FATE )
if ( fate < c->target->fate )
printf( "fate change %s from %s to %s by dependency %s\n",
object_str( t->name ), target_fate[(int) fate], target_fate[(int) c->target->fate],
object_str( c->target->name ) );
object_str( t->name ), target_fate[ (int)fate ],
target_fate[ (int)c->target->fate ], object_str(
c->target->name ) );
#endif
}
/* Step 4b: pick up included headers time */
/*
* If a header is newer than a temp source that includes it,
* the temp source will need building.
* If a header is newer than a temp source that includes it, the temp source
* will need building.
*/
hlast = t->includes ? t->includes->time : 0;
/* Step 4c: handle NOUPDATE oddity.
@@ -571,9 +557,8 @@ void make0
If target newer than non-notfile parent, mark target newer.
Otherwise, stable!
Note this block runs from least to most stable:
as we make it further down the list, the target's
fate is getting stabler.
Note this block runs from least to most stable: as we make it further
down the list, the target's fate gets more stable.
*/
#ifdef OPT_GRAPH_DEBUG_EXT
@@ -643,8 +628,8 @@ void make0
target_fate[ fate ], oldTimeStamp ? " (by timestamp)" : "" );
else
printf( "fate change %s from %s to %s%s\n", object_str( t->name ),
target_fate[ savedFate ], target_fate[ fate ],
oldTimeStamp ? " (by timestamp)" : "" );
target_fate[ savedFate ], target_fate[ fate ], oldTimeStamp ?
" (by timestamp)" : "" );
}
#endif
@@ -737,7 +722,7 @@ void make0
flag = "*";
if ( DEBUG_MAKEPROG )
printf( "made%s\t%s\t%s%s\n", flag, target_fate[ (int) t->fate ],
printf( "made%s\t%s\t%s%s\n", flag, target_fate[ (int)t->fate ],
spaces( depth ), object_str( t->name ) );
}
@@ -837,7 +822,7 @@ static void dependGraphOutput( TARGET * t, int depth )
for ( c = t->depends; c; c = c->next )
{
printf( " %s : Depends on %s (%s)", spaces( depth ),
target_name( c->target ), target_fate[ (int) c->target->fate ] );
target_name( c->target ), target_fate[ (int)c->target->fate ] );
if ( c->target->time == t->time )
printf( " (max time)");
printf( "\n" );
@@ -877,9 +862,7 @@ static TARGETS * make0sort( TARGETS * chain )
while ( s && ( s->target->time > c->target->time ) )
s = s->next;
/* Insert c in front of s (might be 0). Do not even think of deciphering
* this.
*/
/* Insert c in front of s (might be 0). */
c->next = s; /* good even if s = 0 */
if ( result == s ) result = c; /* new head of chain? */
if ( !s ) s = result; /* wrap to ensure a next */
@@ -898,7 +881,8 @@ static LIST * targets_to_update_ = L0;
void mark_target_for_updating( OBJECT * target )
{
targets_to_update_ = list_push_back( targets_to_update_, object_copy( target ) );
targets_to_update_ = list_push_back( targets_to_update_, object_copy(
target ) );
}

View File

@@ -1262,7 +1262,7 @@ static void make1bind( TARGET * t )
pushsettings( root_module(), t->settings );
object_free( t->boundname );
t->boundname = search( t->name, &t->time, 0, ( t->flags & T_FLAG_ISFILE ) );
t->boundname = search( t->name, &t->time, 0, t->flags & T_FLAG_ISFILE );
t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING;
popsettings( root_module(), t->settings );
}

View File

@@ -13,6 +13,7 @@ http://www.boost.org/LICENSE_1_0.txt)
/* Use Boehm GC memory allocator. */
#include <gc.h>
#define bjam_malloc_x(s) memset(GC_malloc(s),0,s)
#define bjam_malloc_atomic_x(s) memset(GC_malloc_atomic(s),0,s)
#define bjam_calloc_x(n,s) memset(GC_malloc((n)*(s)),0,(n)*(s))
@@ -27,13 +28,14 @@ http://www.boost.org/LICENSE_1_0.txt)
#define bjam_free_raw_x(p) free(p)
#ifndef BJAM_NEWSTR_NO_ALLOCATE
#define BJAM_NEWSTR_NO_ALLOCATE
# define BJAM_NEWSTR_NO_ALLOCATE
#endif
#elif defined(OPT_DUMA)
/* Use Duma memory debugging library. */
#include <stdlib.h>
#define _DUMA_CONFIG_H_
#define DUMA_NO_GLOBAL_MALLOC_FREE
#define DUMA_EXPLICIT_INIT
@@ -50,13 +52,14 @@ http://www.boost.org/LICENSE_1_0.txt)
typedef unsigned int DUMA_ADDR;
typedef unsigned int DUMA_SIZE;
#include <duma.h>
#define bjam_malloc_x(s) malloc(s)
#define bjam_calloc_x(n,s) calloc(n,s)
#define bjam_realloc_x(p,s) realloc(p,s)
#define bjam_free_x(p) free(p)
#ifndef BJAM_NEWSTR_NO_ALLOCATE
#define BJAM_NEWSTR_NO_ALLOCATE
# define BJAM_NEWSTR_NO_ALLOCATE
#endif
#else
@@ -95,7 +98,6 @@ http://www.boost.org/LICENSE_1_0.txt)
#endif
#ifdef OPT_DEBUG_PROFILE
/* Profile tracing of memory allocations. */
#define BJAM_MALLOC(s) (profile_memory(s), bjam_malloc_x(s))
#define BJAM_MALLOC_ATOMIC(s) (profile_memory(s), bjam_malloc_atomic_x(s))
@@ -106,9 +108,7 @@ http://www.boost.org/LICENSE_1_0.txt)
#define BJAM_MALLOC_RAW(s) (profile_memory(s), bjam_malloc_raw_x(s))
#define BJAM_CALLOC_RAW(n,s) (profile_memory(n*s), bjam_calloc_raw_x(n,s))
#define BJAM_REALLOC_RAW(p,s) (profile_memory(s), bjam_realloc_raw_x(p,s))
#else
/* No mem tracing. */
#define BJAM_MALLOC(s) bjam_malloc_x(s)
#define BJAM_MALLOC_ATOMIC(s) bjam_malloc_atomic_x(s)
@@ -119,13 +119,12 @@ http://www.boost.org/LICENSE_1_0.txt)
#define BJAM_MALLOC_RAW(s) bjam_malloc_raw_x(s)
#define BJAM_CALLOC_RAW(n,s) bjam_calloc_raw_x(n,s)
#define BJAM_REALLOC_RAW(p,s) bjam_realloc_raw_x(p,s)
#endif
#define BJAM_MEM_INIT() bjam_mem_init_x()
#define BJAM_MEM_CLOSE() bjam_mem_close_x()
#define BJAM_MEM_INIT() bjam_mem_init_x()
#define BJAM_MEM_CLOSE() bjam_mem_close_x()
#define BJAM_FREE(p) bjam_free_x(p)
#define BJAM_FREE_RAW(p) bjam_free_raw_x(p)
#define BJAM_FREE(p) bjam_free_x(p)
#define BJAM_FREE_RAW(p) bjam_free_raw_x(p)
#endif

View File

@@ -3,30 +3,20 @@
/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
#include "../native.h"
#include "../timestamp.h"
#include "../object.h"
#include "../timestamp.h"
LIST *path_exists( FRAME *frame, int flags )
LIST * path_exists( FRAME * frame, int flags )
{
LIST* l = lol_get( frame->args, 0 );
time_t time;
timestamp(list_front(l), &time);
if (time != 0)
{
return list_new(object_new("true"));
}
else
{
return L0;
}
timestamp( list_front( lol_get( frame->args, 0 ) ), &time );
return time ? list_new( object_new( "true" ) ) : L0;
}
void init_path()
{
{
const char* args[] = { "location", 0 };
declare_native_rule("path", "exists", args, path_exists, 1);
}
char const * args[] = { "location", 0 };
declare_native_rule( "path", "exists", args, path_exists, 1 );
}

View File

@@ -5,17 +5,10 @@
* This file is part of Jam - see jam.c for Copyright information.
*/
# include "jam.h"
# include "object.h"
# include <stddef.h>
# include <stdlib.h>
# include <assert.h>
/*
* 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
@@ -27,6 +20,14 @@
* Strings are never actually freed.
*/
#include "jam.h"
#include "object.h"
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#define OBJECT_MAGIC 0xa762e0e3u
#ifndef object_copy
@@ -45,10 +46,10 @@ struct hash_header
struct hash_item
{
struct hash_header header;
char data[1];
char data[ 1 ];
};
#define ALLOC_ALIGNMENT ( sizeof( struct hash_item ) - sizeof( struct hash_header ) )
#define ALLOC_ALIGNMENT (sizeof(struct hash_item) - sizeof(struct hash_header))
typedef struct string_set
{
@@ -57,10 +58,10 @@ typedef struct string_set
struct hash_item * * data;
} string_set;
static string_set strhash;
static int strtotal = 0;
static int strcount_in = 0;
static int strcount_out = 0;
static string_set strhash;
static int strtotal = 0;
static int strcount_in = 0;
static int strcount_out = 0;
/*
@@ -68,11 +69,11 @@ static int strcount_out = 0;
* down on internal fragmentation.
*/
# define STRING_BLOCK 4096
#define STRING_BLOCK 4096
typedef struct strblock
{
struct strblock * next;
char data[STRING_BLOCK];
char data[ STRING_BLOCK ];
} strblock;
static strblock * strblock_chain = 0;
@@ -89,18 +90,18 @@ static char * storage_finish = 0;
static char * allocate( size_t n )
{
#ifdef BJAM_NEWSTR_NO_ALLOCATE
return (char*)BJAM_MALLOC(n);
return (char *)BJAM_MALLOC( n );
#else
/* See if we can grab storage from an existing block. */
size_t remaining = storage_finish - storage_start;
n = ((n + ALLOC_ALIGNMENT - 1) / ALLOC_ALIGNMENT) * ALLOC_ALIGNMENT;
n = ( ( n + ALLOC_ALIGNMENT - 1 ) / ALLOC_ALIGNMENT ) * ALLOC_ALIGNMENT;
if ( remaining >= n )
{
char * result = storage_start;
storage_start += n;
return result;
}
else /* Must allocate a new block. */
else /* Must allocate a new block. */
{
strblock * new_block;
size_t nalloc = n;
@@ -108,7 +109,8 @@ static char * allocate( size_t n )
nalloc = STRING_BLOCK;
/* Allocate a new block and link into the chain. */
new_block = (strblock *)BJAM_MALLOC( offsetof( strblock, data[0] ) + nalloc * sizeof( new_block->data[0] ) );
new_block = (strblock *)BJAM_MALLOC( offsetof( strblock, data[ 0 ] ) +
nalloc * sizeof( new_block->data[ 0 ] ) );
if ( new_block == 0 )
return 0;
new_block->next = strblock_chain;
@@ -125,7 +127,8 @@ static char * allocate( size_t n )
#endif
}
static unsigned int hash_keyval( const char * key )
static unsigned int hash_keyval( char const * key )
{
unsigned int hash = 0;
unsigned i;
@@ -146,11 +149,11 @@ static unsigned int hash_keyval( const char * key )
}
hash += (hash >> 17);
return hash;
}
static void string_set_init(string_set * set)
static void string_set_init( string_set * set )
{
set->size = 0;
set->num = 4;
@@ -158,67 +161,67 @@ static void string_set_init(string_set * set)
memset( set->data, 0, set->num * sizeof( struct hash_item * ) );
}
static void string_set_done(string_set * set)
static void string_set_done( string_set * set )
{
BJAM_FREE( set->data );
}
static void string_set_resize(string_set *set)
static void string_set_resize( string_set * set )
{
unsigned i;
string_set new_set;
new_set.num = set->num * 2;
new_set.size = set->size;
new_set.data = (struct hash_item * *)BJAM_MALLOC( sizeof( struct hash_item * ) * new_set.num );
memset(new_set.data, 0, sizeof(struct hash_item *) * new_set.num);
new_set.data = (struct hash_item * *)BJAM_MALLOC( sizeof( struct hash_item *
) * new_set.num );
memset( new_set.data, 0, sizeof( struct hash_item * ) * new_set.num );
for ( i = 0; i < set->num; ++i )
{
while ( set->data[i] )
while ( set->data[ i ] )
{
struct hash_item * temp = set->data[i];
struct hash_item * temp = set->data[ i ];
unsigned pos = temp->header.hash % new_set.num;
set->data[i] = temp->header.next;
temp->header.next = new_set.data[pos];
new_set.data[pos] = temp;
set->data[ i ] = temp->header.next;
temp->header.next = new_set.data[ pos ];
new_set.data[ pos ] = temp;
}
}
BJAM_FREE( set->data );
*set = new_set;
}
static const char * string_set_insert ( string_set * set, const char * string )
static char const * string_set_insert( string_set * set, char const * string )
{
unsigned hash = hash_keyval( string );
unsigned pos = hash % set->num;
unsigned l;
unsigned len;
struct hash_item * result;
for ( result = set->data[pos]; result; result = result->header.next )
{
if ( strcmp( result->data, string ) == 0 )
{
for ( result = set->data[ pos ]; result; result = result->header.next )
if ( !strcmp( result->data, string ) )
return result->data;
}
}
if( set->size >= set->num )
if ( set->size >= set->num )
{
string_set_resize( set );
pos = hash % set->num;
}
l = strlen( string );
result = (struct hash_item *)allocate( sizeof( struct hash_header ) + l + 1 );
len = strlen( string ) + 1;
result = (struct hash_item *)allocate( sizeof( struct hash_header ) + len );
result->header.hash = hash;
result->header.next = set->data[pos];
result->header.next = set->data[ pos ];
#ifndef NDEBUG
result->header.magic = OBJECT_MAGIC;
#endif
memcpy( result->data, string, l + 1 );
memcpy( result->data, string, len );
assert( hash_keyval( result->data ) == result->header.hash );
set->data[pos] = result;
strtotal += l + 1;
set->data[ pos ] = result;
strtotal += len;
++set->size;
return result->data;
@@ -227,12 +230,14 @@ static const char * string_set_insert ( string_set * set, const char * string )
static struct hash_item * object_get_item( OBJECT * obj )
{
return (struct hash_item *)( (char *)obj - offsetof( struct hash_item, data ) );
return (struct hash_item *)( (char *)obj - offsetof( struct hash_item, data
) );
}
static void object_validate( OBJECT * obj )
{
assert( obj );
assert( object_get_item( obj )->header.magic == OBJECT_MAGIC );
}
@@ -241,26 +246,26 @@ static void object_validate( OBJECT * obj )
* object_new() - create an object from a string.
*/
OBJECT * object_new( const char * string )
OBJECT * object_new( char const * string )
{
#ifdef BJAM_NO_MEM_CACHE
int l = strlen( string );
struct hash_item * m = (struct hash_item *)BJAM_MALLOC( sizeof(struct hash_header) + l + 1 );
int const len = strlen( string ) + 1;
struct hash_item * const m = (struct hash_item *)BJAM_MALLOC( sizeof( struct
hash_header) + len );
strtotal += l + 1;
memcpy( m->data, string, l + 1 );
strtotal += len;
memcpy( m->data, string, len );
m->header.magic = OBJECT_MAGIC;
return (OBJECT *)m->data;
#else
if ( ! strhash.data )
if ( !strhash.data )
string_set_init( &strhash );
strcount_in += 1;
++strcount_in;
return (OBJECT *)string_set_insert( &strhash, string );
#endif
}
#ifndef object_copy
/*
@@ -273,7 +278,7 @@ OBJECT * object_copy( OBJECT * obj )
#ifdef BJAM_NO_MEM_CACHE
return object_new( object_str( obj ) );
#else
strcount_in += 1;
++strcount_in;
return obj;
#endif
}
@@ -289,18 +294,18 @@ void object_free( OBJECT * obj )
#ifdef BJAM_NO_MEM_CACHE
BJAM_FREE( object_get_item( obj ) );
#endif
strcount_out += 1;
++strcount_out;
}
/*
* object_str() - return the
* object_str() - return the OBJECT's internal C string
*/
const char * object_str( OBJECT * obj )
char const * object_str( OBJECT * obj )
{
object_validate( obj );
return (const char *)obj;
return (char const *)obj;
}
@@ -313,9 +318,9 @@ int object_equal( OBJECT * lhs, OBJECT * rhs )
object_validate( lhs );
object_validate( rhs );
#ifdef BJAM_NO_MEM_CACHE
return strcmp(object_str(lhs), object_str(rhs)) == 0;
return !strcmp( object_str( lhs ), object_str( rhs ) );
#else
assert( (lhs == rhs) == ( strcmp(object_str(lhs), object_str(rhs)) == 0 ) );
assert( ( lhs == rhs ) == !strcmp( object_str( lhs ), object_str( rhs ) ) );
return lhs == rhs;
#endif
}
@@ -343,37 +348,34 @@ unsigned int object_hash( OBJECT * obj )
void object_done()
{
#ifdef BJAM_NEWSTR_NO_ALLOCATE
unsigned i;
for ( i = 0; i < strhash.num; ++i )
{
while ( strhash.data[i] )
while ( strhash.data[ i ] )
{
struct hash_item * item = strhash.data[i];
strhash.data[i] = item->header.next;
struct hash_item * item = strhash.data[ i ];
strhash.data[ i ] = item->header.next;
BJAM_FREE( item );
}
}
#else
/* Reclaim string blocks. */
while ( strblock_chain != 0 )
while ( strblock_chain )
{
strblock * n = strblock_chain->next;
BJAM_FREE(strblock_chain);
strblock * const n = strblock_chain->next;
BJAM_FREE( strblock_chain );
strblock_chain = n;
}
#endif
string_set_done( &strhash );
if ( DEBUG_MEM )
{
printf( "%dK in strings\n", strtotal / 1024 );
/* printf( "--- %d strings of %d dangling\n", strcount_in-strcount_out, strcount_in ); */
/* if ( strcount_in != strcount_out )
printf( "--- %d strings of %d dangling\n", strcount_in -
strcount_out, strcount_in ); */
}
}

View File

@@ -11,18 +11,20 @@
/*
* PATHNAME - a name of a file, broken into <grist>dir/base/suffix(member)
*
* <grist> is salt to distinguish between targets that otherwise would
* have the same name: it never appears in the bound name of a target.
* (member) is an archive member name: the syntax is arbitrary, but must
* agree in path_parse(), path_build() and the Jambase.
* <grist> - salt to distinguish between targets that would otherwise have the
* same name - it never appears in the bound name of a target.
*
* (member) - archive member name: the syntax is arbitrary, but must agree in
* path_parse(), path_build() and the Jambase.
*/
#ifndef PATHSYS_VP_20020211_H
# define PATHSYS_VP_20020211_H
#define PATHSYS_VP_20020211_H
#include "jam.h"
#include "strings.h"
#include "object.h"
#include "strings.h"
typedef struct _pathname PATHNAME;
typedef struct _pathpart PATHPART;
@@ -35,14 +37,14 @@ struct _pathpart
struct _pathname
{
PATHPART part[6];
PATHPART part[ 6 ];
#define f_grist part[0]
#define f_root part[1]
#define f_dir part[2]
#define f_base part[3]
#define f_suffix part[4]
#define f_member part[5]
#define f_grist part[ 0 ]
#define f_root part[ 1 ]
#define f_dir part[ 2 ]
#define f_base part[ 3 ]
#define f_suffix part[ 4 ]
#define f_member part[ 5 ]
};
void path_build( PATHNAME * f, string * file, int binding );
@@ -53,42 +55,44 @@ void path_parent( PATHNAME * f );
#ifdef NT
/** Returns object_new-allocated string with long equivivalent of 'short_name'.
If none exists -- i.e. 'short_path' is already long path, it's returned
unaltered. */
/* Returns object_new-allocated string with long equivivalent of 'short_name'.
* If none exists, i.e. 'short_path' is already long, it is returned unaltered.
*/
OBJECT * short_path_to_long_path( OBJECT * short_path );
#endif
/** Given a path, returns an object that can be
used as a unique key for that path. Equivalent
paths such as a/b, A\B, and a\B on NT all yield the
same key.
/* Given a path, returns an object that can be used as a unique key for that
* path. Equivalent paths such as a/b, A\B, and a\B on NT all yield the same
* key.
*/
OBJECT * path_as_key( OBJECT * path );
void path_add_key( OBJECT * path );
/* Called as an optimization when we know we have a path that is already in its
* 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 );
#ifdef USE_PATHUNIX
/** Returns a static pointer to the system dependent path to the temporary
directory. NOTE: *without* a trailing path separator.
*/
/* Returns a static pointer to the system dependent path to the temporary
* directory. NOTE: *without* a trailing path separator.
*/
string const * path_tmpdir( void );
/** Returns a new temporary name.
*/
/* Returns a new temporary name. */
OBJECT * path_tmpnam( void );
/** Returns a new temporary path.
*/
/* Returns a new temporary path. */
OBJECT * path_tmpfile( void );
#endif
/** Give the first argument to 'main', return a full path to our executable.
Returns null in the unlikely case it cannot be determined. Caller is
responsible for freeing the string.
Implemented in jam.c
*/
/* Give the first argument to 'main', return a full path to our executable.
* Returns null in the unlikely case it cannot be determined. Caller is
* responsible for freeing the string.
*
* Implemented in jam.c
*/
char * executable_path( char const * argv0 );
void path_done( void );

View File

@@ -11,48 +11,36 @@
* (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
*/
# include "jam.h"
# include "pathsys.h"
# include "strings.h"
# include "object.h"
# include "filesys.h"
# include <time.h>
# include <stdlib.h>
# include <assert.h>
# ifndef OS_NT
# include <unistd.h>
# endif
# ifdef USE_PATHUNIX
/*
* pathunix.c - manipulate file names on UNIX, NT, OS2, AmigaOS
*
* External routines:
*
* path_parse() - split a file name into dir/base/suffix/member
* path_build() - build a filename given dir/base/suffix/member
* path_parent() - make a PATHNAME point to its parent dir
*
* File_parse() and path_build() just manipuate a string and a structure;
* File_parse() and path_build() just manipulate a string and a structure;
* they do not make system calls.
*
* 04/08/94 (seiwald) - Coherent/386 support added.
* 12/26/93 (seiwald) - handle dir/.suffix properly in path_build()
* 12/19/94 (mikem) - solaris string table insanity support
* 12/21/94 (wingerd) Use backslashes for pathnames - the NT way.
* 02/14/95 (seiwald) - parse and build /xxx properly
* 02/23/95 (wingerd) Compilers on NT can handle "/" in pathnames, so we
* should expect hdr searches to come up with strings
* like "thing/thing.h". So we need to test for "/" as
* well as "\" when parsing pathnames.
* 03/16/95 (seiwald) - fixed accursed typo on line 69.
* 05/03/96 (seiwald) - split from filent.c, fileunix.c
* 12/20/96 (seiwald) - when looking for the rightmost . in a file name,
* don't include the archive member name.
* 01/13/01 (seiwald) - turn on \ handling on UNIX, on by accident
*/
#include "jam.h"
#ifdef USE_PATHUNIX
#include "pathsys.h"
#include "filesys.h"
#include "object.h"
#include "strings.h"
#include <assert.h>
#include <stdlib.h>
#include <time.h>
#ifndef OS_NT
# include <unistd.h>
#endif
/*
* path_parse() - split a file name into dir/base/suffix/member
*/
@@ -65,26 +53,26 @@ void path_parse( char const * file, PATHNAME * f )
memset( (char *)f, 0, sizeof( *f ) );
/* Look for <grist> */
/* Look for '<grist>'. */
if ( ( file[0] == '<' ) && ( p = strchr( file, '>' ) ) )
if ( ( file[ 0 ] == '<' ) && ( p = strchr( file, '>' ) ) )
{
f->f_grist.ptr = file;
f->f_grist.len = p - file;
file = p + 1;
}
/* Look for dir/ */
/* Look for 'dir/'. */
p = strrchr( file, '/' );
# if PATH_DELIM == '\\'
#if PATH_DELIM == '\\'
/* On NT, look for dir\ as well */
{
char *p1 = strrchr( file, '\\' );
char * const p1 = strrchr( file, '\\' );
p = p1 > p ? p1 : p;
}
# endif
#endif
if ( p )
{
@@ -92,24 +80,21 @@ void path_parse( char const * file, PATHNAME * f )
f->f_dir.len = p - file;
/* Special case for / - dirname is /, not "" */
if ( !f->f_dir.len )
f->f_dir.len = 1;
++f->f_dir.len;
# if PATH_DELIM == '\\'
#if PATH_DELIM == '\\'
/* Special case for D:/ - dirname is D:/, not "D:" */
if ( f->f_dir.len == 2 && file[1] == ':' )
f->f_dir.len = 3;
# endif
if ( f->f_dir.len == 2 && file[ 1 ] == ':' )
++f->f_dir.len;
#endif
file = p + 1;
}
end = file + strlen( file );
/* Look for (member) */
/* Look for '(member)'. */
if ( ( p = strchr( file, '(' ) ) && ( end[ -1 ] == ')' ) )
{
f->f_member.ptr = p + 1;
@@ -117,15 +102,10 @@ void path_parse( char const * file, PATHNAME * f )
end = p;
}
/* Look for .suffix */
/* This would be memrchr() */
/* Look for '.suffix'. This would be memrchr(). */
p = 0;
q = file;
while ( ( q = (char *)memchr( q, '.', end - q ) ) )
p = q++;
for ( q = file; ( q = (char *)memchr( q, '.', end - q ) ); ++q )
p = q;
if ( p )
{
f->f_suffix.ptr = p;
@@ -133,135 +113,123 @@ void path_parse( char const * file, PATHNAME * f )
end = p;
}
/* Leaves base */
/* Leaves base. */
f->f_base.ptr = file;
f->f_base.len = end - file;
}
/*
* path_delims - the string of legal path delimiters
*/
static char path_delims[] = {
PATH_DELIM,
# if PATH_DELIM == '\\'
#if PATH_DELIM == '\\'
'/',
# endif
#endif
0
};
/*
* is_path_delim() - true iff c is a path delimiter
*/
static int is_path_delim( char c )
static int is_path_delim( char const c )
{
char* p = strchr( path_delims, c );
char const * const p = strchr( path_delims, c );
return p && *p;
}
/*
* as_path_delim() - convert c to a path delimiter if it isn't one
* already
* as_path_delim() - convert c to a path delimiter if it is not one already
*/
static char as_path_delim( char c )
static char as_path_delim( char const c )
{
return is_path_delim( c ) ? c : PATH_DELIM;
}
/*
* path_build() - build a filename given dir/base/suffix/member
*
* To avoid changing slash direction on NT when reconstituting paths,
* instead of unconditionally appending PATH_DELIM we check the
* past-the-end character of the previous path element. If it is in
* path_delims, we append that, and only append PATH_DELIM as a last
* resort. This heuristic is based on the fact that PATHNAME objects
* are usually the result of calling path_parse, which leaves the
* original slashes in the past-the-end position. Correctness depends
* on the assumption that all strings are zero terminated, so a
* past-the-end character will always be available.
* To avoid changing slash direction on NT when reconstituting paths, instead of
* unconditionally appending PATH_DELIM we check the past-the-end character of
* the previous path element. If it is in path_delims, we append that, and only
* append PATH_DELIM as a last resort. This heuristic is based on the fact that
* PATHNAME objects are usually the result of calling path_parse, which leaves
* the original slashes in the past-the-end position. Correctness depends on the
* assumption that all strings are zero terminated, so a past-the-end character
* will always be available.
*
* As an attendant patch, we had to ensure that backslashes are used
* explicitly in timestamp.c
* As an attendant patch, we had to ensure that backslashes are used explicitly
* in 'timestamp.c'.
*/
void
path_build(
PATHNAME *f,
string *file,
int binding )
void path_build( PATHNAME * f, string * file, int binding )
{
file_build1( f, file );
/* Don't prepend root if it's . or directory is rooted */
# if PATH_DELIM == '/'
/* Do not prepend root if it is '.' or the directory is rooted. */
if ( f->f_root.len
&& !( f->f_root.len == 1 && f->f_root.ptr[0] == '.' )
&& !( f->f_dir.len && f->f_dir.ptr[0] == '/' ) )
# else /* unix */
if ( f->f_root.len
&& !( f->f_root.len == 1 && f->f_root.ptr[0] == '.' )
&& !( f->f_dir.len && f->f_dir.ptr[0] == '/' )
&& !( f->f_dir.len && f->f_dir.ptr[0] == '\\' )
&& !( f->f_dir.len && f->f_dir.ptr[1] == ':' ) )
# endif /* unix */
&& !( f->f_root.len == 1 && f->f_root.ptr[ 0 ] == '.' )
&& !( f->f_dir.len && f->f_dir.ptr[ 0 ] == '/' )
#if PATH_DELIM == '\\'
&& !( f->f_dir.len && f->f_dir.ptr[ 0 ] == '\\' )
&& !( f->f_dir.len && f->f_dir.ptr[ 1 ] == ':' )
#endif
)
{
string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
/* If 'root' already ends with path delimeter,
don't add yet another one. */
if ( ! is_path_delim( f->f_root.ptr[f->f_root.len-1] ) )
string_push_back( file, as_path_delim( f->f_root.ptr[f->f_root.len] ) );
string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len
);
/* If 'root' already ends with a path delimeter, do not add yet another
* one.
*/
if ( !is_path_delim( f->f_root.ptr[ f->f_root.len - 1 ] ) )
string_push_back( file, as_path_delim( f->f_root.ptr[ f->f_root.len
] ) );
}
if ( f->f_dir.len )
string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len );
string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len );
/* UNIX: Put / between dir and file */
/* NT: Put \ between dir and file */
if ( f->f_dir.len && ( f->f_base.len || f->f_suffix.len ) )
{
/* UNIX: Special case for dir \ : don't add another \ */
/* NT: Special case for dir / : don't add another / */
# if PATH_DELIM == '\\'
if ( !( f->f_dir.len == 3 && f->f_dir.ptr[1] == ':' ) )
# endif
if ( !( f->f_dir.len == 1 && is_path_delim( f->f_dir.ptr[0] ) ) )
string_push_back( file, as_path_delim( f->f_dir.ptr[f->f_dir.len] ) );
}
/* Put path separator between dir and file. */
/* Special case for root dir: do not add another path separator. */
if ( f->f_dir.len && ( f->f_base.len || f->f_suffix.len )
#if PATH_DELIM == '\\'
&& !( f->f_dir.len == 3 && f->f_dir.ptr[ 1 ] == ':' )
#endif
&& !( f->f_dir.len == 1 && is_path_delim( f->f_dir.ptr[ 0 ] ) ) )
string_push_back( file, as_path_delim( f->f_dir.ptr[ f->f_dir.len ] ) );
if ( f->f_base.len )
{
string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len );
}
string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len
);
if ( f->f_suffix.len )
{
string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len );
}
string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr +
f->f_suffix.len );
if ( f->f_member.len )
{
string_push_back( file, '(' );
string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len );
string_append_range( file, f->f_member.ptr, f->f_member.ptr +
f->f_member.len );
string_push_back( file, ')' );
}
}
/*
* path_parent() - make a PATHNAME point to its parent dir
*/
void
path_parent( PATHNAME *f )
void path_parent( PATHNAME * f )
{
/* just set everything else to nothing */
/* Just clear everything. */
f->f_base.ptr =
f->f_suffix.ptr =
@@ -279,31 +247,30 @@ path_parent( PATHNAME *f )
#undef INVALID_FILE_ATTRIBUTES
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
OBJECT * path_as_key( OBJECT * path );
static void path_write_key( char * path_, string * out );
static void path_write_key( char const * const path_, string * const out );
void ShortPathToLongPath( char * short_path, string * out )
static void ShortPathToLongPath( char const * const short_path,
string * const out )
{
char const * new_element;
unsigned long saved_size;
char * p;
if ( short_path[0] == '\0' )
{
if ( short_path[ 0 ] == '\0' )
return;
}
if ( short_path[0] == '\\' && short_path[1] == '\0')
if ( short_path[ 0 ] == '\\' && short_path[ 1 ] == '\0' )
{
string_push_back( out, '\\' );
return;
}
if ( short_path[1] == ':' &&
( short_path[2] == '\0' ||
( short_path[2] == '\\' && short_path[3] == '\0' ) ) )
if ( short_path[ 1 ] == ':' &&
( short_path[ 2 ] == '\0' ||
( short_path[ 2 ] == '\\' && short_path[ 3 ] == '\0' ) ) )
{
string_push_back( out, toupper( short_path[0] ) );
string_push_back( out, toupper( short_path[ 0 ] ) );
string_push_back( out, ':' );
string_push_back( out, '\\' );
return;
@@ -315,12 +282,12 @@ void ShortPathToLongPath( char * short_path, string * out )
char saved;
new_element = p + 1;
/* special case \ */
/* special case '\' */
if ( p == short_path )
++p;
/* special case D:\ */
if ( p == short_path + 2 && short_path[1] == ':' )
/* special case 'D:\' */
if ( p == short_path + 2 && short_path[ 1 ] == ':' )
++p;
saved = *p;
@@ -329,59 +296,58 @@ void ShortPathToLongPath( char * short_path, string * out )
*p = saved;
}
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 );
if ( ! ( new_element[0] == '.' && new_element[1] == '\0' ||
new_element[0] == '.' && new_element[1] == '.'
&& new_element[2] == '\0' ) )
/* If the file exists, replace its name with its long name variant. */
{
WIN32_FIND_DATA fd;
HANDLE hf = 0;
hf = FindFirstFile( out->value, &fd );
/* If the file exists, replace the name. */
if ( hf != INVALID_HANDLE_VALUE )
char const * const n = new_element;
if ( !( n[ 0 ] == '.' && n[ 1 ] == '\0' ||
n[ 0 ] == '.' && n[ 1 ] == '.' && n[ 2 ] == '\0' ) )
{
string_truncate( out, saved_size );
string_append( out, fd.cFileName );
FindClose( hf );
WIN32_FIND_DATA fd;
HANDLE const hf = FindFirstFile( out->value, &fd );
if ( hf != INVALID_HANDLE_VALUE )
{
string_truncate( out, saved_size );
string_append( out, fd.cFileName );
FindClose( hf );
}
}
}
}
OBJECT * short_path_to_long_path( OBJECT * short_path )
{
return path_as_key( short_path );
}
struct path_key_entry
typedef struct path_key_entry
{
OBJECT * path;
OBJECT * key;
};
} path_key_entry;
static struct hash * path_key_cache;
static void path_write_key( char * path_, string * out )
static void path_write_key( char const * const path_, string * const out )
{
struct path_key_entry * result;
OBJECT * path = object_new( path_ );
path_key_entry * result;
OBJECT * const path = object_new( path_ );
int found;
/* This is only called by path_as_key, which initializes the cache. */
/* This is only called via path_as_key(), which initializes the cache. */
assert( path_key_cache );
result = (struct path_key_entry *)hash_insert( path_key_cache, path, &found );
result = (path_key_entry *)hash_insert( path_key_cache, path, &found );
if ( !found )
{
/* path_ is already normalized. */
@@ -394,46 +360,42 @@ static void path_write_key( char * path_, string * out )
object_free( path );
string_append( out, object_str( result->key ) );
}
}
static void normalize_path( string * path )
{
char * s;
for ( s = path->value; s < path->value + path->size; ++s )
{
if ( *s == '/' )
*s = '\\';
else
*s = tolower( *s );
}
/* Strip trailing "/" */
if ( path->size != 0 && path->size != 3 && path->value[ path->size - 1 ] == '\\' )
{
*s = *s == '/' ? '\\' : tolower( *s );
/* Strip trailing "/". */
if ( path->size && path->size != 3 && path->value[ path->size - 1 ] == '\\'
)
string_pop_back( path );
}
}
void path_add_key( OBJECT * path )
{
struct path_key_entry * result;
path_key_entry * result;
int found;
if ( ! path_key_cache )
path_key_cache = hashinit( sizeof( struct path_key_entry ), "path to key" );
if ( !path_key_cache )
path_key_cache = hashinit( sizeof( path_key_entry ), "path to key" );
result = (struct path_key_entry *)hash_insert( path_key_cache, path, &found );
result = (path_key_entry *)hash_insert( path_key_cache, path, &found );
if ( !found )
{
string buf[1];
string buf[ 1 ];
OBJECT * normalized;
struct path_key_entry * nresult;
path_key_entry * nresult;
result->path = path;
string_copy( buf, object_str( path ) );
normalize_path( buf );
normalized = object_new( buf->value );
string_free( buf );
nresult = (struct path_key_entry *)hash_insert( path_key_cache, normalized, &found );
nresult = (path_key_entry *)hash_insert( path_key_cache, normalized,
&found );
if ( !found || nresult == result )
{
nresult->path = object_copy( normalized );
@@ -448,28 +410,30 @@ void path_add_key( OBJECT * path )
}
}
OBJECT * path_as_key( OBJECT * path )
{
struct path_key_entry * result;
path_key_entry * result;
int found;
if ( ! path_key_cache )
path_key_cache = hashinit( sizeof( struct path_key_entry ), "path to key" );
if ( !path_key_cache )
path_key_cache = hashinit( sizeof( path_key_entry ), "path to key" );
result = (struct path_key_entry *)hash_insert( path_key_cache, path, &found );
result = (path_key_entry *)hash_insert( path_key_cache, path, &found );
if ( !found )
{
string buf[1];
string buf[ 1 ];
OBJECT * normalized;
struct path_key_entry * nresult;
path_key_entry * nresult;
result->path = path;
string_copy( buf, object_str( path ) );
normalize_path( buf );
normalized = object_new( buf->value );
nresult = (struct path_key_entry *)hash_insert( path_key_cache, normalized, &found );
nresult = (path_key_entry *)hash_insert( path_key_cache, normalized,
&found );
if ( !found || nresult == result )
{
string long_path[1];
string long_path[ 1 ];
nresult->path = normalized;
string_new( long_path );
ShortPathToLongPath( buf->value, long_path );
@@ -489,13 +453,15 @@ OBJECT * path_as_key( OBJECT * path )
return object_copy( result->key );
}
static void free_path_key_entry( void * xentry, void * data )
static void free_path_key_entry( void * xentry, void * const data )
{
struct path_key_entry * entry = (struct path_key_entry *)xentry;
path_key_entry * const entry = (path_key_entry *)xentry;
object_free( entry->path );
object_free( entry->key );
}
void path_done( void )
{
if ( path_key_cache )
@@ -505,22 +471,26 @@ void path_done( void )
}
}
#else
#else /* NT */
void path_add_key( OBJECT * path )
{
}
OBJECT * path_as_key( OBJECT * path )
{
return object_copy( path );
}
void path_done( void )
{
}
#endif
#endif /* NT */
string const * path_tmpdir()
{
@@ -549,15 +519,16 @@ string const * path_tmpdir()
return buffer;
}
OBJECT * path_tmpnam( void )
{
char name_buffer[ 64 ];
unsigned long const c0 =
# ifdef OS_NT
#ifdef OS_NT
GetCurrentProcessId();
# else
#else
getpid();
# endif
#endif
static unsigned long c1;
if ( !c1 ) c1 = time( 0 ) & 0xffff;
c1 += 1;
@@ -565,6 +536,7 @@ OBJECT * path_tmpnam( void )
return object_new( name_buffer );
}
OBJECT * path_tmpfile( void )
{
OBJECT * result;
@@ -583,4 +555,4 @@ OBJECT * path_tmpfile( void )
}
# endif /* unix, NT, OS/2, AmigaOS */
#endif /* USE_PATHUNIX */

View File

@@ -4,19 +4,6 @@
* This file is part of Jam - see jam.c for Copyright information.
*/
# include "jam.h"
# include "lists.h"
# include "parse.h"
# include "variable.h"
# include "rules.h"
# include "object.h"
# include "hash.h"
# include "modules.h"
# include "search.h"
# include "lists.h"
# include "pathsys.h"
# include "timestamp.h"
/* This file is ALSO:
* Copyright 2001-2004 David Abrahams.
* Distributed under the Boost Software License, Version 1.0.
@@ -27,7 +14,6 @@
* rules.c - access to RULEs, TARGETs, and ACTIONs
*
* External routines:
*
* bindrule() - return pointer to RULE, creating it if necessary.
* bindtarget() - return pointer to TARGET, creating it if necessary.
* touch_target() - mark a target to simulate being new.
@@ -39,11 +25,22 @@
* popsettings() - reset target specific variables to their pre-push values.
* freesettings() - delete a settings list.
* rules_done() - free RULE and TARGET tables.
*
* 04/12/94 (seiwald) - actionlist() now just appends a single action.
* 08/23/94 (seiwald) - Support for '+=' (append to variable)
*/
#include "jam.h"
#include "rules.h"
#include "hash.h"
#include "lists.h"
#include "modules.h"
#include "object.h"
#include "parse.h"
#include "pathsys.h"
#include "search.h"
#include "timestamp.h"
#include "variable.h"
static void set_rule_actions( RULE *, rule_actions * );
static void set_rule_body ( RULE *, FUNCTION * procedure );
@@ -99,19 +96,17 @@ static RULE * enter_rule( OBJECT * rulename, module_t * target_module )
* src_module.
*/
static RULE * define_rule
(
module_t * src_module,
OBJECT * rulename,
module_t * target_module
)
static RULE * define_rule( module_t * src_module, OBJECT * rulename,
module_t * target_module )
{
RULE * r = enter_rule( rulename, target_module );
if ( r->module != src_module ) /* if the rule was imported from elsewhere, clear it now */
RULE * const r = enter_rule( rulename, target_module );
if ( r->module != src_module )
{
/* If the rule was imported from elsewhere, clear it now. */
set_rule_body( r, 0 );
set_rule_actions( r, 0 );
r->module = src_module; /* r will be executed in the source module */
/* r will be executed in the source module. */
r->module = src_module;
}
return r;
}
@@ -159,7 +154,7 @@ static void bind_explicitly_located_target( void * xtarget, void * data )
TARGET * t = (TARGET *)xtarget;
if ( !( t->flags & T_FLAG_NOTFILE ) )
{
/* Check if there's a setting for LOCATE */
/* Check if there is a setting for LOCATE. */
SETTINGS * s = t->settings;
for ( ; s ; s = s->next )
{
@@ -189,7 +184,7 @@ void bind_explicitly_located_targets()
/*
* copytarget() - make a new target with the old target's name.
*
* Not entered into hash table -- for internal nodes.
* Not entered into the hash table -- for internal nodes.
*/
TARGET * copytarget( const TARGET * ot )
@@ -198,9 +193,7 @@ TARGET * copytarget( const TARGET * ot )
memset( (char *)t, '\0', sizeof( *t ) );
t->name = object_copy( ot->name );
t->boundname = object_copy( t->name );
t->flags |= T_FLAG_NOTFILE | T_FLAG_INTERNAL;
return t;
}
@@ -214,11 +207,12 @@ void touch_target( OBJECT * t )
bindtarget( t )->flags |= T_FLAG_TOUCHED;
}
/*
* target_scc() - returns the root of the strongly
* connected component that this target
* is a part of.
* target_scc() - returns the root of a strongly connected component that this
* target is a part of.
*/
TARGET * target_scc( TARGET * t )
{
TARGET * result = t;
@@ -239,13 +233,14 @@ TARGET * target_scc( TARGET * t )
* targetlist() - turn list of target names into a TARGET chain.
*
* Inputs:
* chain existing TARGETS to append to
* targets list of target names
* chain existing TARGETS to append to
* targets list of target names
*/
TARGETS * targetlist( TARGETS * chain, LIST * target_names )
{
LISTITER iter = list_begin( target_names ), end = list_end( target_names );
LISTITER iter = list_begin( target_names );
LISTITER const end = list_end( target_names );
for ( ; iter != end; iter = list_next( iter ) )
chain = targetentry( chain, bindtarget( list_item( iter ) ) );
return chain;
@@ -262,7 +257,7 @@ TARGETS * targetlist( TARGETS * chain, LIST * target_names )
TARGETS * targetentry( TARGETS * chain, TARGET * target )
{
TARGETS * c = (TARGETS *)BJAM_MALLOC( sizeof( TARGETS ) );
TARGETS * const c = (TARGETS *)BJAM_MALLOC( sizeof( TARGETS ) );
c->target = target;
if ( !chain ) chain = c;
@@ -278,27 +273,25 @@ TARGETS * targetentry( TARGETS * chain, TARGET * target )
* targetchain() - append two TARGET chains.
*
* Inputs:
* chain exisitng TARGETS to append to
* chain existing TARGETS to append to
* target new target to append
*/
TARGETS * targetchain( TARGETS * chain, TARGETS * targets )
{
if ( !targets ) return chain;
if ( !chain ) return targets;
if ( !chain ) return targets;
chain->tail->next = targets;
chain->tail = targets->tail;
return chain;
}
/*
* action_free - decrement the ACTIONs refrence count
* and (maybe) free it.
* action_free - decrement the ACTIONs refrence count and (maybe) free it.
*/
void action_free ( ACTION * action )
void action_free( ACTION * action )
{
if ( --action->refs == 0 )
{
@@ -308,22 +301,20 @@ void action_free ( ACTION * action )
}
}
/*
* actionlist() - append to an ACTION chain.
*/
ACTIONS * actionlist( ACTIONS * chain, ACTION * action )
{
ACTIONS * actions = (ACTIONS *)BJAM_MALLOC( sizeof( ACTIONS ) );
ACTIONS * const actions = (ACTIONS *)BJAM_MALLOC( sizeof( ACTIONS ) );
actions->action = action;
++action->refs;
if ( !chain ) chain = actions;
else chain->tail->next = actions;
chain->tail = actions;
actions->next = 0;
return chain;
}
@@ -335,11 +326,12 @@ static SETTINGS * settings_freelist;
*
* Adds a variable setting (varname=list) onto a chain of settings for a
* particular target. 'flag' controls the relationship between new and old
* values in the same way as in var_set() function (see variable.c). Returns
* the head of the settings chain.
* values in the same way as in var_set() function (see variable.c). Returns the
* head of the settings chain.
*/
SETTINGS * addsettings( SETTINGS * head, int flag, OBJECT * symbol, LIST * value )
SETTINGS * addsettings( SETTINGS * head, int flag, OBJECT * symbol,
LIST * value )
{
SETTINGS * v;
@@ -354,7 +346,6 @@ SETTINGS * addsettings( SETTINGS * head, int flag, OBJECT * symbol, LIST * value
if ( !v )
{
v = settings_freelist;
if ( v )
settings_freelist = v->next;
else
@@ -425,7 +416,7 @@ void freetargets( TARGETS * chain )
{
while ( chain )
{
TARGETS * n = chain->next;
TARGETS * const n = chain->next;
BJAM_FREE( chain );
chain = n;
}
@@ -440,7 +431,7 @@ void freeactions( ACTIONS * chain )
{
while ( chain )
{
ACTIONS * n = chain->next;
ACTIONS * const n = chain->next;
action_free( chain->action );
BJAM_FREE( chain );
chain = n;
@@ -456,7 +447,7 @@ void freesettings( SETTINGS * v )
{
while ( v )
{
SETTINGS * n = v->next;
SETTINGS * const n = v->next;
object_free( v->symbol );
list_free( v->value );
v->next = settings_freelist;
@@ -468,7 +459,7 @@ void freesettings( SETTINGS * v )
static void freetarget( void * xt, void * data )
{
TARGET * t = (TARGET *)xt;
TARGET * const t = (TARGET *)xt;
if ( t->name ) object_free ( t->name );
if ( t->boundname ) object_free ( t->boundname );
if ( t->settings ) freesettings( t->settings );
@@ -476,7 +467,6 @@ static void freetarget( void * xt, void * data )
if ( t->dependants ) freetargets ( t->dependants );
if ( t->parents ) freetargets ( t->parents );
if ( t->actions ) freeactions ( t->actions );
if ( t->includes )
{
freetarget( t->includes, (void *)0 );
@@ -498,7 +488,7 @@ void rules_done()
}
while ( settings_freelist )
{
SETTINGS * n = settings_freelist->next;
SETTINGS * const n = settings_freelist->next;
BJAM_FREE( settings_freelist );
settings_freelist = n;
}
@@ -516,7 +506,7 @@ void actions_refer( rule_actions * a )
/*
* actions_free() - release a reference to the given actions.
* actions_free() - release a reference to given actions.
*/
void actions_free( rule_actions * a )
@@ -529,6 +519,7 @@ void actions_free( rule_actions * a )
}
}
/*
* set_rule_body() - set the argument list and procedure of the given rule.
*/
@@ -554,7 +545,7 @@ static OBJECT * global_rule_name( RULE * r )
return object_copy( r->name );
{
char name[4096] = "";
char name[ 4096 ] = "";
if ( r->module->name )
{
strncat( name, object_str( r->module->name ), sizeof( name ) - 1 );
@@ -567,7 +558,7 @@ static OBJECT * global_rule_name( RULE * r )
/*
* global_rule() - given a rule, produce the corresponding entry in the global
* global_rule() - given a rule, produce a corresponding entry in the global
* module.
*/
@@ -591,7 +582,8 @@ static RULE * global_rule( RULE * r )
* exported to the global module as modulename.rulename.
*/
RULE * new_rule_body( module_t * m, OBJECT * rulename, FUNCTION * procedure, int exported )
RULE * new_rule_body( module_t * m, OBJECT * rulename, FUNCTION * procedure,
int exported )
{
RULE * local = define_rule( m, rulename, m );
local->exported = exported;
@@ -619,9 +611,11 @@ static void set_rule_actions( RULE * rule, rule_actions * actions )
}
static rule_actions * actions_new( FUNCTION * command, LIST * bindlist, int flags )
static rule_actions * actions_new( FUNCTION * command, LIST * bindlist,
int flags )
{
rule_actions * result = (rule_actions *)BJAM_MALLOC( sizeof( rule_actions ) );
rule_actions * const result = (rule_actions *)BJAM_MALLOC( sizeof(
rule_actions ) );
function_refer( command );
result->command = command;
result->bindlist = bindlist;
@@ -631,10 +625,11 @@ static rule_actions * actions_new( FUNCTION * command, LIST * bindlist, int flag
}
RULE * new_rule_actions( module_t * m, OBJECT * rulename, FUNCTION * command, LIST * bindlist, int flags )
RULE * new_rule_actions( module_t * m, OBJECT * rulename, FUNCTION * command,
LIST * bindlist, int flags )
{
RULE * local = define_rule( m, rulename, m );
RULE * global = global_rule( local );
RULE * const local = define_rule( m, rulename, m );
RULE * const global = global_rule( local );
set_rule_actions( local, actions_new( command, bindlist, flags ) );
set_rule_actions( global, local->actions );
return local;
@@ -643,8 +638,8 @@ RULE * new_rule_actions( module_t * m, OBJECT * rulename, FUNCTION * command, LI
/*
* Looks for a rule in the specified module, and returns it, if found. First
* checks if the rule is present in the module's rule table. Second, if name of
* the rule is in the form name1.name2 and name1 is in the list of imported
* checks if the rule is present in the module's rule table. Second, if the
* rule's name is in the form name1.name2 and name1 is in the list of imported
* modules, look in module 'name1' for rule 'name2'.
*/
@@ -686,18 +681,17 @@ RULE * lookup_rule( OBJECT * rulename, module_t * m, int local_only )
{
if ( local_only && !result->exported )
result = 0;
else
else if ( original_module != m )
{
/* Lookup started in class module. We have found a rule in class
* module, which is marked for execution in that module, or in some
* instances. Mark it for execution in the instance where we started
* the lookup.
*/
int execute_in_class = ( result->module == m );
int execute_in_some_instance = ( result->module->class_module &&
( result->module->class_module == m ) );
if ( ( original_module != m ) &&
( execute_in_class || execute_in_some_instance ) )
int const execute_in_class = result->module == m;
int const execute_in_some_instance =
result->module->class_module == m;
if ( execute_in_class || execute_in_some_instance )
result->module = original_module;
}
}

View File

@@ -13,9 +13,10 @@
#ifndef RULES_DWA_20011020_H
#define RULES_DWA_20011020_H
#include "modules.h"
#include "jam.h"
#include "function.h"
#include "modules.h"
/*
@@ -33,14 +34,6 @@
* SETTINGS - variables to set when executing a TARGET's ACTIONS.
* TARGETS - a chain of TARGETs.
* TARGET - an entity (e.g. a file) that can be built.
*
* 04/11/94 (seiwald) - Combined deps & headers into deps[2] in TARGET.
* 04/12/94 (seiwald) - actionlist() now just appends a single action.
* 06/01/94 (seiwald) - new 'actions existing' does existing sources
* 12/20/94 (seiwald) - NOTIME renamed NOTFILE.
* 01/19/95 (seiwald) - split DONTKNOW into CANTFIND/CANTMAKE.
* 02/02/95 (seiwald) - new LEAVES modifier on targets.
* 02/14/95 (seiwald) - new NOUPDATE modifier on targets.
*/
typedef struct _rule RULE;
@@ -146,19 +139,18 @@ struct _target
/* This flag was added to support a new built-in rule named "FAIL_EXPECTED" used
* to indicate that the result of running a given action should be inverted,
* i.e. ok <=> fail. This is useful for launching certain test runs from a
* Jamfile.
* i.e. ok <=> fail. Useful for launching certain test runs from a Jamfile.
*/
#define T_FLAG_FAIL_EXPECTED 0x0100 /* FAIL_EXPECTED applied */
#define T_FLAG_INTERNAL 0x0200 /* internal INCLUDES node */
/* Indicates that the target must be a file. This prevents matching non-files,
* like directories, when a target is searched.
/* Indicates that the target must be a file. Prevents matching non-files, like
* directories, when a target is searched.
*/
#define T_FLAG_ISFILE 0x0400
#define T_FLAG_PRECIOUS 0x0800
#define T_FLAG_PRECIOUS 0x0800
char binding; /* how target relates to a real file or
* folder
@@ -188,13 +180,13 @@ struct _target
#define T_FATE_STABLE 2 /* target did not need updating */
#define T_FATE_NEWER 3 /* target newer than parent */
#define T_FATE_SPOIL 4 /* >= SPOIL rebuilds parents */
#define T_FATE_ISTMP 4 /* unneeded temp target oddly present */
#define T_FATE_BUILD 5 /* >= BUILD rebuilds target */
#define T_FATE_TOUCHED 5 /* manually touched with -t */
#define T_FATE_REBUILD 6
#define T_FATE_REBUILD 6
#define T_FATE_MISSING 7 /* is missing, needs updating */
#define T_FATE_NEEDTMP 8 /* missing temp that must be rebuild */
#define T_FATE_OUTDATED 9 /* is out of date, needs updating */
@@ -230,7 +222,7 @@ struct _target
int depth; /* The depth of the target in the make0 stack. */
char * cmds; /* type-punned command list */
const char * failed;
char const * failed;
};

View File

@@ -11,16 +11,18 @@
*/
#include "jam.h"
#include "lists.h"
#include "search.h"
#include "timestamp.h"
#include "pathsys.h"
#include "variable.h"
#include "object.h"
#include "compile.h"
#include "strings.h"
#include "hash.h"
#include "filesys.h"
#include "hash.h"
#include "lists.h"
#include "object.h"
#include "pathsys.h"
#include "strings.h"
#include "timestamp.h"
#include "variable.h"
#include <string.h>
@@ -30,14 +32,10 @@ typedef struct _binding
OBJECT * target;
} BINDING;
static struct hash *explicit_bindings = 0;
static struct hash * explicit_bindings = 0;
void call_bind_rule
(
OBJECT * target_,
OBJECT * boundname_
)
void call_bind_rule( OBJECT * target_, OBJECT * boundname_ )
{
LIST * bind_rule = var_get( root_module(), constant_BINDRULE );
if ( !list_empty( bind_rule ) )
@@ -47,7 +45,7 @@ void call_bind_rule
if ( boundname && target )
{
/* Prepare the argument list. */
FRAME frame[1];
FRAME frame[ 1 ];
frame_init( frame );
/* First argument is the target name. */
@@ -70,48 +68,45 @@ void call_bind_rule
}
}
/*
* search.c - find a target along $(SEARCH) or $(LOCATE)
* First, check if LOCATE is set. If so, use it to determine
* the location of target and return, regardless of whether anything
* exists on that location.
* search.c - find a target along $(SEARCH) or $(LOCATE).
*
* Second, examine all directories in SEARCH. If there's file already
* or there's another target with the same name which was placed
* to this location via LOCATE setting, stop and return the location.
* In case of previous target, return it's name via the third argument.
* First, check if LOCATE is set. If so, use it to determine the location of
* target and return, regardless of whether anything exists at that location.
*
* This bevahiour allow to handle dependency on generated files. If
* caller does not expect that target is generated, 0 can be passed as
* the third argument.
* Second, examine all directories in SEARCH. If the file exists there or there
* is another target with the same name already placed at this location via the
* LOCATE setting, stop and return the location. In case of a previous target,
* return its name via the 'another_target' argument.
*
* This bevahiour allows handling dependencies on generated files. If caller
* does not expect that the target is generated, 0 can be passed as
* 'another_target'.
*/
OBJECT *
search(
OBJECT * target,
time_t *time,
OBJECT * * another_target,
int file
)
OBJECT * search( OBJECT * target, time_t * time, OBJECT * * another_target,
int file )
{
PATHNAME f[1];
LIST * varlist;
string buf[1];
int found = 0;
/* Will be set to 1 if target location is specified via LOCATE. */
int explicitly_located = 0;
PATHNAME f[ 1 ];
LIST * varlist;
string buf[ 1 ];
int found = 0;
OBJECT * boundname = 0;
/* Set to 1 if target location is specified via LOCATE. */
int explicitly_located = 0;
if ( another_target )
*another_target = 0;
if (! explicit_bindings )
explicit_bindings = hashinit( sizeof(BINDING),
"explicitly specified locations");
if ( !explicit_bindings )
explicit_bindings = hashinit( sizeof( BINDING ), "explicitly specified "
"locations" );
string_new( buf );
/* Parse the filename */
/* Parse the filename. */
path_parse( object_str( target ), f );
f->f_grist.ptr = 0;
@@ -136,13 +131,15 @@ search(
object_free( key );
found = 1;
}
else if ( varlist = var_get( root_module(), constant_SEARCH ), !list_empty( varlist ) )
else if ( varlist = var_get( root_module(), constant_SEARCH ),
!list_empty( varlist ) )
{
LISTITER iter = list_begin( varlist ), end = list_end( varlist );
LISTITER iter = list_begin( varlist );
LISTITER const end = list_end( varlist );
for ( ; iter != end; iter = list_next( iter ) )
{
BINDING * ba;
file_info_t *ff;
file_info_t * ff;
OBJECT * key;
OBJECT * test_path;
@@ -187,9 +184,10 @@ search(
if ( !found )
{
/* Look for the obvious */
/* This is a questionable move. Should we look in the */
/* obvious place if SEARCH is set? */
/* Look for the obvious. */
/* This is a questionable move. Should we look in the obvious place if
* SEARCH is set?
*/
OBJECT * key;
f->f_root.ptr = 0;
@@ -213,10 +211,11 @@ search(
{
int found;
BINDING * ba;
OBJECT * key = path_as_key( boundname );
/* CONSIDER: we probably should issue a warning is another file
is explicitly bound to the same location. This might break
compatibility, though. */
OBJECT * const key = path_as_key( boundname );
/* CONSIDER: We should probably issue a warning if another file is
* explicitly bound to the same location. This might break
* compatibility, though.
*/
ba = (BINDING *)hash_insert( explicit_bindings, key, &found );
if ( !found )
{
@@ -224,12 +223,10 @@ search(
ba->target = target;
}
else
{
object_free( key );
}
}
/* prepare a call to BINDRULE if the variable is set */
/* Prepare a call to BINDRULE if the variable is set. */
call_bind_rule( target, boundname );
return boundname;
@@ -238,10 +235,11 @@ search(
static void free_binding( void * xbinding, void * data )
{
BINDING * binding = (BINDING *)xbinding;
BINDING * const binding = (BINDING *)xbinding;
object_free( binding->binding );
}
void search_done( void )
{
if ( explicit_bindings )

View File

@@ -14,7 +14,8 @@
#include "object.h"
#include <time.h>
OBJECT * search( OBJECT * target, time_t * time, OBJECT * * another_target, int file );
OBJECT * search( OBJECT * target, time_t * time, OBJECT * * another_target,
int file );
void search_done( void );
#endif

View File

@@ -10,21 +10,20 @@
* (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
*/
# include "jam.h"
# include "hash.h"
# include "filesys.h"
# include "pathsys.h"
# include "timestamp.h"
# include "object.h"
# include "strings.h"
/*
* timestamp.c - get the timestamp of a file or archive member
*
* 09/22/00 (seiwald) - downshift names on OS2, too
*/
#include "jam.h"
#include "timestamp.h"
#include "filesys.h"
#include "hash.h"
#include "object.h"
#include "pathsys.h"
#include "strings.h"
/*
* BINDING - all known files
*/
@@ -35,21 +34,22 @@ struct _binding {
OBJECT * name;
short flags;
# define BIND_SCANNED 0x01 /* if directory or arch, has been scanned */
#define BIND_SCANNED 0x01 /* if directory or arch, has been scanned */
short progress;
# define BIND_INIT 0 /* never seen */
# define BIND_NOENTRY 1 /* timestamp requested but file never found */
# define BIND_SPOTTED 2 /* file found but not timed yet */
# define BIND_MISSING 3 /* file found but can't get timestamp */
# define BIND_FOUND 4 /* file found and time stamped */
#define BIND_INIT 0 /* never seen */
#define BIND_NOENTRY 1 /* timestamp requested but file never found */
#define BIND_SPOTTED 2 /* file found but not timed yet */
#define BIND_MISSING 3 /* file found but can not get timestamp */
#define BIND_FOUND 4 /* file found and time stamped */
time_t time; /* update time - 0 if not exist */
/* update time - 0 if not exist */
time_t time;
};
static struct hash * bindhash = 0;
static void time_enter( void *, OBJECT *, int, time_t );
static void time_enter( void *, OBJECT *, int const found, time_t );
static char * time_progress[] =
{
@@ -69,11 +69,11 @@ void timestamp( OBJECT * target, time_t * time )
{
PROFILE_ENTER( timestamp );
PATHNAME f1;
PATHNAME f2;
int found;
BINDING * b;
string buf[ 1 ];
PATHNAME f1;
PATHNAME f2;
int found;
BINDING * b;
string buf[ 1 ];
target = path_as_key( target );
@@ -172,19 +172,20 @@ void timestamp( OBJECT * target, time_t * time )
}
*time = b->progress == BIND_FOUND ? b->time : 0;
string_free( buf );
string_free( buf );
object_free( target );
PROFILE_EXIT( timestamp );
}
static void time_enter( void * closure, OBJECT * target, int found, time_t time )
static void time_enter( void * closure, OBJECT * target, int const found,
time_t time )
{
int item_found;
BINDING * b;
struct hash * bindhash = (struct hash *)closure;
struct hash * const bindhash = (struct hash *)closure;
target = path_as_key( target );
@@ -199,16 +200,18 @@ static void time_enter( void * closure, OBJECT * target, int found, time_t time
b->progress = found ? BIND_FOUND : BIND_SPOTTED;
if ( DEBUG_BINDSCAN )
printf( "time ( %s ) : %s\n", object_str( target ), time_progress[ b->progress ] );
printf( "time ( %s ) : %s\n", object_str( target ), time_progress[
b->progress ] );
object_free( target );
}
static void free_timestamps ( void * xbinding, void * data )
static void free_timestamps( void * xbinding, void * data )
{
object_free( ((BINDING *)xbinding)->name );
}
/*
* stamps_done() - free timestamp tables.
*/

View File

@@ -12,7 +12,8 @@
#define TIMESTAMP_H_SW_2011_11_18
#include "object.h"
#include "time.h"
#include <time.h>
void timestamp( OBJECT * target, time_t * time );
void stamps_done();

View File

@@ -6,11 +6,13 @@
# http://www.boost.org/LICENSE_1_0.txt)
import TestCmd
import copy
import fnmatch
import glob
import math
import os
import os.path
import re
import shutil
import string
@@ -29,8 +31,7 @@ annotations = []
def print_annotation(name, value, xml):
"""Writes some named bits of information about test run.
"""
"""Writes some named bits of information about the current test run."""
if xml:
print escape(name) + " {{{"
print escape(value)
@@ -40,18 +41,20 @@ def print_annotation(name, value, xml):
print value
print "}}}"
def flush_annotations(xml=0):
global annotations
for ann in annotations:
print_annotation(ann[0], ann[1], xml)
annotations = []
def clear_annotations():
global annotations
annotations = []
defer_annotations = 0
defer_annotations = 0
def set_defer_annotations(n):
global defer_annotations
@@ -59,16 +62,15 @@ def set_defer_annotations(n):
def annotate_stack_trace(tb=None):
if tb is None:
trace = TestCmd.caller(traceback.extract_stack(), 1)
else:
if tb:
trace = TestCmd.caller(traceback.extract_tb(tb), 0)
else:
trace = TestCmd.caller(traceback.extract_stack(), 1)
annotation("stacktrace", trace)
def annotation(name, value):
"""Records an annotation about the test run.
"""
"""Records an annotation about the test run."""
annotations.append((name, value))
if not defer_annotations:
flush_annotations()
@@ -83,57 +85,65 @@ def get_toolset():
# Detect the host OS.
windows = False
cygwin = False
if os.environ.get('OS', '').lower().startswith('windows'):
windows = True
if os.__dict__.has_key('uname') and \
os.uname()[0].lower().startswith('cygwin'):
windows = True
cygwin = True
suffixes = {}
cygwin = hasattr(os, 'uname') and os.uname()[0].lower().startswith('cygwin')
windows = cygwin or os.environ.get('OS', '').lower().startswith('windows')
# Configuration stating whether Boost Build is expected to automatically prepend
# prefixes to built library targets.
lib_prefix = "lib"
dll_prefix = "lib"
def prepare_prefixes_and_suffixes(toolset):
prepare_suffix_map(toolset)
prepare_library_prefix(toolset)
# Prepare the map of suffixes
def prepare_suffix_map(toolset):
global windows
"""
Set up suffix translation performed by the Boost Build testing framework
to accomodate different toolsets generating targets of the same type using
different filename extensions (suffixes).
"""
global suffixes
global cygwin
global lib_prefix
global dll_prefix
suffixes = {'.exe': '', '.dll': '.so', '.lib': '.a', '.obj': '.o'}
suffixes['.implib'] = '.no_implib_files_on_this_platform'
suffixes = {}
if windows:
suffixes = {}
if toolset in ["gcc"]:
suffixes['.lib'] = '.a' # static libs have '.a' suffix with mingw...
if toolset == "gcc":
suffixes['.lib'] = '.a' # mingw static libs use suffix '.a'.
suffixes['.obj'] = '.o'
if cygwin:
suffixes['.implib'] = '.lib.a'
else:
suffixes['.implib'] = '.lib'
if os.__dict__.has_key('uname') and (os.uname()[0] == 'Darwin'):
suffixes['.dll'] = '.dylib'
else:
suffixes['.exe'] = ''
suffixes['.dll'] = '.so'
suffixes['.lib'] = '.a'
suffixes['.obj'] = '.o'
suffixes['.implib'] = '.no_implib_files_on_this_platform'
if hasattr(os, 'uname') and os.uname()[0] == 'Darwin':
suffixes['.dll'] = '.dylib'
def prepare_library_prefix(toolset):
"""
Setup whether Boost Build is expected to automatically prepend prefixes
to its built library targets.
"""
global lib_prefix
lib_prefix = "lib"
dll_prefix = "lib"
global dll_prefix
if cygwin:
dll_prefix = "cyg"
elif windows and not toolset in ["gcc"]:
elif windows and toolset != "gcc":
dll_prefix = None
else:
dll_prefix = "lib"
def re_remove(sequence, regex):
me = re.compile(regex)
result = filter(lambda x: me.match(x), sequence)
if 0 == len(result):
if not result:
raise ValueError()
for r in result:
sequence.remove(r)
@@ -141,13 +151,12 @@ def re_remove(sequence, regex):
def glob_remove(sequence, pattern):
result = fnmatch.filter(sequence, pattern)
if 0 == len(result):
if not result:
raise ValueError()
for r in result:
sequence.remove(r)
#
# FIXME: this is copy-pasted from TestSCons.py
# Should be moved to TestCmd.py?
@@ -160,8 +169,7 @@ if os.name == 'posix':
def _status(self):
if os.WIFEXITED(self.status):
return os.WEXITSTATUS(self.status)
else:
return -1
return -1
elif os.name == 'nt':
def _failed(self, status=0):
return not self.status is None and self.status != status
@@ -194,8 +202,8 @@ class Tester(TestCmd.TestCmd):
configuration file.
`ignore_toolset_requirements` - Whether the test system should tell the run
executable to ignore toolset requirements.
`workdir` - indicates an absolute directory where the
test will be run from.
`workdir` - Absolute directory where the test will be
run from.
Optional arguments inherited from the base class:
@@ -217,7 +225,7 @@ class Tester(TestCmd.TestCmd):
ignore_toolset_requirements=True, workdir="", pass_d0=True, **keywords):
self.original_workdir = os.getcwd()
if workdir != '' and not os.path.isabs(workdir):
if workdir and not os.path.isabs(workdir):
raise ("Parameter workdir <%s> must point to an absolute "
"directory: " % workdir)
@@ -229,9 +237,11 @@ class Tester(TestCmd.TestCmd):
self.pass_toolset = pass_toolset
self.ignore_toolset_requirements = ignore_toolset_requirements
prepare_suffix_map(pass_toolset and self.toolset or 'gcc')
prepare_prefixes_and_suffixes(pass_toolset and self.toolset or 'gcc')
if not '--default-bjam' in sys.argv:
use_default_bjam = '--default-bjam' in sys.argv
if not use_default_bjam:
jam_build_dir = ""
if os.name == 'nt':
jam_build_dir = "bin.ntx86"
@@ -265,9 +275,11 @@ class Tester(TestCmd.TestCmd):
elif os.uname()[0] == "OSF1":
jam_build_dir = "bin.osf"
else:
raise "Don't know directory where Jam is built for this system: " + os.name + "/" + os.uname()[0]
raise ("Do not know directory where Jam is built for this "
"system: %s/%s" % (os.name, os.uname()[0]))
else:
raise "Don't know directory where Jam is built for this system: " + os.name
raise ("Do not know directory where Jam is built for this "
"system: %s" % os.name)
# Find where jam_src is located. Try for the debug version if it is
# lying around.
@@ -278,7 +290,7 @@ class Tester(TestCmd.TestCmd):
jam_build_dir = d
break
else:
print "Cannot find built Boost.Jam"
print("Cannot find built Boost.Jam")
sys.exit(1)
verbosity = ['-d0', '--quiet']
@@ -292,26 +304,18 @@ class Tester(TestCmd.TestCmd):
boost_build_path = self.original_workdir + "/.."
program_list = []
if '--default-bjam' in sys.argv:
if use_default_bjam:
program_list.append(executable)
inpath_bjam = True
else:
program_list.append(os.path.join(jam_build_dir, executable))
inpath_bjam = None
program_list.append('-sBOOST_BUILD_PATH="' + boost_build_path + '"')
if verbosity:
program_list += verbosity
if arguments:
program_list += arguments.split(" ")
TestCmd.TestCmd.__init__(
self
, program=program_list
, match=match
, workdir=workdir
, inpath=inpath_bjam
, **keywords)
TestCmd.TestCmd.__init__(self, program=program_list, match=match,
workdir=workdir, inpath=use_default_bjam, **keywords)
os.chdir(self.workdir)
@@ -432,9 +436,10 @@ class Tester(TestCmd.TestCmd):
#
# FIXME: Large portion copied from TestSCons.py, should be moved?
#
def run_build_system(self, extra_args="", subdir="", stdout=None, stderr="",
status=0, match=None, pass_toolset=None, use_test_config=None,
ignore_toolset_requirements=None, expected_duration=None, **kw):
def run_build_system(self, extra_args="", subdir="", stdout=None,
stderr="", status=0, match=None, pass_toolset=None,
use_test_config=None, ignore_toolset_requirements=None,
expected_duration=None, **kw):
build_time_start = time.time()
@@ -466,8 +471,8 @@ class Tester(TestCmd.TestCmd):
if pass_toolset:
kw['program'].append("toolset=" + self.toolset)
if use_test_config:
kw['program'].append('--test-config="%s"'
% os.path.join(self.original_workdir, "test-config.jam"))
kw['program'].append('--test-config="%s"' % os.path.join(
self.original_workdir, "test-config.jam"))
if ignore_toolset_requirements:
kw['program'].append("--ignore-toolset-requirements")
if "--python" in sys.argv:
@@ -482,18 +487,18 @@ class Tester(TestCmd.TestCmd):
old_last_build_time_finish = self.last_build_time_finish
self.last_build_time_finish = time.time()
if (status != None) and _failed(self, status):
if status is not None and _failed(self, status):
expect = ''
if status != 0:
expect = " (expected %d)" % status
annotation("failure", '"%s" returned %d%s'
% (kw['program'], _status(self), expect))
annotation("failure", '"%s" returned %d%s' % (kw['program'],
_status(self), expect))
annotation("reason", "unexpected status returned by bjam")
self.fail_test(1)
if not (stdout is None) and not match(self.stdout(), stdout):
if stdout is not None and not match(self.stdout(), stdout):
annotation("failure", "Unexpected stdout")
annotation("Expected STDOUT", stdout)
annotation("Actual STDOUT", self.stdout())
@@ -507,7 +512,7 @@ class Tester(TestCmd.TestCmd):
intel_workaround = re.compile("^xi(link|lib): executing.*\n", re.M)
actual_stderr = re.sub(intel_workaround, "", self.stderr())
if not (stderr is None) and not match(actual_stderr, stderr):
if stderr is not None and not match(actual_stderr, stderr):
annotation("failure", "Unexpected stderr")
annotation("Expected STDERR", stderr)
annotation("Actual STDERR", self.stderr())
@@ -515,7 +520,7 @@ class Tester(TestCmd.TestCmd):
self.maybe_do_diff(actual_stderr, stderr)
self.fail_test(1, dump_stdio=False)
if not expected_duration is None:
if expected_duration is not None:
actual_duration = self.last_build_time_finish - build_time_start
if actual_duration > expected_duration:
print "Test run lasted %f seconds while it was expected to " \
@@ -528,9 +533,10 @@ class Tester(TestCmd.TestCmd):
if self.difference.empty():
# If nothing has been changed by this build and sufficient time has
# passed since the last build that actually changed something,
# there may be no need to wait for touched or newly created files
# to get newer timestamps than the currently existing ones.
# there is no need to wait for touched or newly created files to
# start getting newer timestamps than the currently existing ones.
self.last_build_time_finish = old_last_build_time_finish
self.difference.ignore_directories()
self.unexpected_difference = copy.deepcopy(self.difference)
@@ -714,8 +720,11 @@ class Tester(TestCmd.TestCmd):
self.ignore('gmon.out')
self.ignore('*/gmon.out')
# Boost Build's 'configure' functionality (unfinished at the time)
# produces this file.
self.ignore("bin/config.log")
# Compiled Python files created when running Python based Boost Build.
self.ignore("*.pyc")
if not self.unexpected_difference.empty():
@@ -883,7 +892,8 @@ class Tester(TestCmd.TestCmd):
names = [names]
r = map(self.adjust_lib_name, names)
r = map(self.adjust_suffix, r)
r = map(lambda x, t=self.toolset: string.replace(x, "$toolset", t+"*"), r)
r = map(lambda x, t=self.toolset: string.replace(x, "$toolset", t+"*"),
r)
return r
def native_file_name(self, name):
@@ -891,11 +901,14 @@ class Tester(TestCmd.TestCmd):
elements = string.split(name, "/")
return os.path.normpath(apply(os.path.join, [self.workdir]+elements))
# Wait while time is no longer equal to the time last "run_build_system"
# call finished. Used to avoid subsequent builds treating existing files as
# 'current'.
def wait_for_time_change_since_last_build(self):
while 1:
"""
Wait until newly assigned file system timestamps are larger than the
one assigned to files created by our previous build run. Used to make
subsequent builds correctly recognize newly created or touched files.
"""
while True:
# In fact, I'm not sure why "+ 2" as opposed to "+ 1" is needed but
# empirically, "+ 1" sometimes causes 'touch' and other functions
# not to bump the file time enough for a rebuild to happen.
@@ -915,10 +928,7 @@ class List:
elements = string.split(s)
else:
elements = s
self.l = []
for e in elements:
self.l.append(string.replace(e, '\001', ' '))
self.l = [string.replace(e, '\001', ' ') for e in elements]
def __len__(self):
return len(self.l)
@@ -964,4 +974,4 @@ class List:
if __name__ == '__main__':
assert str(List("foo bar") * "/baz") == "['foo/baz', 'bar/baz']"
assert repr("foo/" * List("bar baz")) == "__main__.List('foo/bar foo/baz')"
print 'tests passed'
print('tests passed')

View File

@@ -21,6 +21,7 @@ or NO RESULT respectively and exiting with status 0 (success), 1 or 2
respectively. This allows for a distinction between an actual failed test and a
test that could not be properly evaluated because of an external condition (such
as a full file system or incorrect permissions).
"""
# Copyright 2000 Steven Knight
@@ -102,9 +103,10 @@ def caller(tblist, skip):
def fail_test(self=None, condition=True, function=None, skip=0):
"""Cause the test to fail.
By default, the fail_test() method reports that the test FAILED and exits
with a status of 1. If a condition argument is supplied, the test fails only
if the condition is true.
By default, the fail_test() method reports that the test FAILED and exits
with a status of 1. If a condition argument is supplied, the test fails
only if the condition is true.
"""
if not condition:
return
@@ -131,9 +133,10 @@ in directory: """ + os.getcwd() )
def no_result(self=None, condition=True, function=None, skip=0):
"""Causes a test to exit with no valid result.
By default, the no_result() method reports NO RESULT for the test and exits
with a status of 2. If a condition argument is supplied, the test fails only
if the condition is true.
By default, the no_result() method reports NO RESULT for the test and
exits with a status of 2. If a condition argument is supplied, the test
fails only if the condition is true.
"""
if not condition:
return
@@ -158,9 +161,10 @@ def no_result(self=None, condition=True, function=None, skip=0):
def pass_test(self=None, condition=True, function=None):
"""Causes a test to pass.
By default, the pass_test() method reports PASSED for the test and exits
By default, the pass_test() method reports PASSED for the test and exits
with a status of 0. If a condition argument is supplied, the test passes
only if the condition is true.
"""
if not condition:
return
@@ -171,8 +175,10 @@ def pass_test(self=None, condition=True, function=None):
def match_exact(lines=None, matches=None):
"""Returns whether the given lists or strings containing lines separated
"""
Returns whether the given lists or strings containing lines separated
using newline characters contain exactly the same data.
"""
if not type(lines) is ListType:
lines = split(lines, "\n")
@@ -187,9 +193,11 @@ def match_exact(lines=None, matches=None):
def match_re(lines=None, res=None):
"""Given lists or strings contain lines separated using newline characters.
"""
Given lists or strings contain lines separated using newline characters.
This function matches those lines one by one, interpreting the lines in the
res parameter as regular expressions.
"""
if not type(lines) is ListType:
lines = split(lines, "\n")
@@ -204,42 +212,35 @@ def match_re(lines=None, res=None):
class TestCmd:
"""Class TestCmd.
"""
def __init__(self, description=None, program=None, workdir=None,
subdir=None, verbose=False, match=None, inpath=None):
self._cwd = os.getcwd()
self.description_set(description)
if inpath:
self.program = program
else:
self.program_set(program)
self.program_set(program, inpath)
self.verbose_set(verbose)
if not match is None:
self.match_func = match
else:
if match is None:
self.match_func = match_re
else:
self.match_func = match
self._dirlist = []
self._preserve = {'pass_test': 0, 'fail_test': 0, 'no_result': 0}
if os.environ.has_key('PRESERVE') and not os.environ['PRESERVE'] is '':
self._preserve['pass_test'] = os.environ['PRESERVE']
self._preserve['fail_test'] = os.environ['PRESERVE']
self._preserve['no_result'] = os.environ['PRESERVE']
env = os.environ.get('PRESERVE')
if env:
self._preserve['pass_test'] = env
self._preserve['fail_test'] = env
self._preserve['no_result'] = env
else:
try:
self._preserve['pass_test'] = os.environ['PRESERVE_PASS']
except KeyError:
pass
try:
self._preserve['fail_test'] = os.environ['PRESERVE_FAIL']
except KeyError:
pass
try:
self._preserve['no_result'] = os.environ['PRESERVE_NO_RESULT']
except KeyError:
pass
env = os.environ.get('PRESERVE_PASS')
if env is not None:
self._preserve['pass_test'] = env
env = os.environ.get('PRESERVE_FAIL')
if env is not None:
self._preserve['fail_test'] = env
env = os.environ.get('PRESERVE_PASS')
if env is not None:
self._preserve['PRESERVE_NO_RESULT'] = env
self._stdout = []
self._stderr = []
self.status = None
@@ -254,7 +255,8 @@ class TestCmd:
return "%x" % id(self)
def cleanup(self, condition=None):
"""Removes any temporary working directories for the specified TestCmd
"""
Removes any temporary working directories for the specified TestCmd
environment. If the environment variable PRESERVE was set when the
TestCmd environment was created, temporary working directories are not
removed. If any of the environment variables PRESERVE_PASS,
@@ -264,9 +266,10 @@ class TestCmd:
Temporary working directories are also preserved for conditions
specified via the preserve method.
Typically, this method is not called directly, but is used when the
Typically, this method is not called directly, but is used when the
script exits to clean up temporary working directories as appropriate
for the exit status.
"""
if not self._dirlist:
return
@@ -274,13 +277,13 @@ class TestCmd:
condition = self.condition
if self._preserve[condition]:
for dir in self._dirlist:
print "Preserved directory", dir
print("Preserved directory %s" % dir)
else:
list = self._dirlist[:]
list.reverse()
for dir in list:
self.writable(dir, 1)
shutil.rmtree(dir, ignore_errors = 1)
shutil.rmtree(dir, ignore_errors=1)
self._dirlist = []
self.workdir = None
@@ -292,13 +295,11 @@ class TestCmd:
pass
def description_set(self, description):
"""Set the description of the functionality being tested.
"""
"""Set the description of the functionality being tested."""
self.description = description
def fail_test(self, condition=True, function=None, skip=0):
"""Cause the test to fail.
"""
"""Cause the test to fail."""
if not condition:
return
self.condition = 'fail_test'
@@ -308,23 +309,19 @@ class TestCmd:
skip = skip)
def match(self, lines, matches):
"""Compare actual and expected file contents.
"""
"""Compare actual and expected file contents."""
return self.match_func(lines, matches)
def match_exact(self, lines, matches):
"""Compare actual and expected file contents.
"""
"""Compare actual and expected file content exactly."""
return match_exact(lines, matches)
def match_re(self, lines, res):
"""Compare actual and expected file contents.
"""
"""Compare file content with a regular expression."""
return match_re(lines, res)
def no_result(self, condition=True, function=None, skip=0):
"""Report that the test could not be run.
"""
"""Report that the test could not be run."""
if not condition:
return
self.condition = 'no_result'
@@ -334,38 +331,40 @@ class TestCmd:
skip = skip)
def pass_test(self, condition=True, function=None):
"""Cause the test to pass.
"""
"""Cause the test to pass."""
if not condition:
return
self.condition = 'pass_test'
pass_test(self = self, condition = condition, function = function)
pass_test(self, condition, function)
def preserve(self, *conditions):
"""Arrange for the temporary working directories for the specified
"""
Arrange for the temporary working directories for the specified
TestCmd environment to be preserved for one or more conditions. If no
conditions are specified, arranges for the temporary working directories
to be preserved for all conditions.
conditions are specified, arranges for the temporary working
directories to be preserved for all conditions.
"""
if conditions is ():
conditions = ('pass_test', 'fail_test', 'no_result')
for cond in conditions:
self._preserve[cond] = 1
def program_set(self, program):
"""Set the executable program or script to be tested.
"""
if program and program[0] and not os.path.isabs(program[0]):
def program_set(self, program, inpath):
"""Set the executable program or script to be tested."""
if not inpath and program and not os.path.isabs(program[0]):
program[0] = os.path.join(self._cwd, program[0])
self.program = program
def read(self, file, mode='rb'):
"""Reads and returns the contents of the specified file name. The file
name may be a list, in which case the elements are concatenated with the
os.path.join() method. The file is assumed to be under the temporary
working directory unless it is an absolute path name. The I/O mode for
the file may be specified; it must begin with an 'r'. The default is
'rb' (binary read).
"""
Reads and returns the contents of the specified file name. The file
name may be a list, in which case the elements are concatenated with
the os.path.join() method. The file is assumed to be under the
temporary working directory unless it is an absolute path name. The I/O
mode for the file may be specified; it must begin with an 'r'. The
default is 'rb' (binary read).
"""
if type(file) is ListType:
file = apply(os.path.join, tuple(file))
@@ -376,9 +375,11 @@ class TestCmd:
return open(file, mode).read()
def run(self, program=None, arguments=None, chdir=None, stdin=None):
"""Runs a test of the program or script for the test environment.
"""
Runs a test of the program or script for the test environment.
Standard output and error output are saved for future retrieval via the
stdout() and stderr() methods.
"""
if chdir:
oldcwd = os.getcwd()
@@ -417,8 +418,8 @@ class TestCmd:
# This is a workaround for a longstanding Python bug on Windows
# when using os.popen(), os.system() and similar functions to
# execute a command containing quote characters. The bug seems
# to be related to the quote stripping functionality used by the
# Windows cmd.exe interpreter when its /S is not specified.
# to be related to the quote stripping functionality used by
# the Windows cmd.exe interpreter when its /S is not specified.
#
# Cleaned up quote from the cmd.exe help screen as displayed on
# Windows XP SP2:
@@ -441,15 +442,15 @@ class TestCmd:
# command line, preserving any text after the last quote
# character.
#
# This causes some commands containing quotes not to be executed
# correctly. For example:
# This causes some commands containing quotes not to be
# executed correctly. For example:
#
# "\Long folder name\aaa.exe" --name="Jurko" --no-surname
# "\Long folder name\aaa.exe" --name="Foo" --no-surname
#
# would get its outermost quotes stripped and would be executed
# as:
#
# \Long folder name\aaa.exe" --name="Jurko --no-surname
# \Long folder name\aaa.exe" --name="Foo --no-surname
#
# which would report an error about '\Long' not being a valid
# command.
@@ -464,8 +465,8 @@ class TestCmd:
# not work correctly should Python ever fix this bug.
# (01.05.2008.) (Jurko)
if command_string.find('"') != -1:
command_string = '"' + command_string + '"'
(tochild, fromchild, childerr) = os.popen3(command_string)
command_string = '"%s"' % command_string
tochild, fromchild, childerr = os.popen3(command_string)
if stdin:
if type(stdin) is ListType:
for line in stdin:
@@ -501,10 +502,12 @@ class TestCmd:
os.chdir(oldcwd)
def stderr(self, run=None):
"""Returns the error output from the specified run number. If there is
"""
Returns the error output from the specified run number. If there is
no specified run number, then returns the error output of the last run.
If the run number is less than zero, then returns the error output from
that many runs back from the current run.
"""
if not run:
run = len(self._stderr)
@@ -516,10 +519,12 @@ class TestCmd:
return self._stderr[run]
def stdout(self, run=None):
"""Returns the standard output from the specified run number. If there
is no specified run number, then returns the standard output of the last
run. If the run number is less than zero, then returns the standard
output from that many runs back from the current run.
"""
Returns the standard output from the specified run number. If there
is no specified run number, then returns the standard output of the
last run. If the run number is less than zero, then returns the
standard output from that many runs back from the current run.
"""
if not run:
run = len(self._stdout)
@@ -531,15 +536,17 @@ class TestCmd:
return self._stdout[run]
def subdir(self, *subdirs):
"""Create new subdirectories under the temporary working directory, one
"""
Create new subdirectories under the temporary working directory, one
for each argument. An argument may be a list, in which case the list
elements are concatenated using the os.path.join() method.
Subdirectories multiple levels deep must be created using a separate
argument for each level:
test.subdir('sub', ['sub', 'dir'], ['sub', 'dir', 'ectory'])
test.subdir('sub', ['sub', 'dir'], ['sub', 'dir', 'ectory'])
Returns the number of subdirectories actually created.
"""
count = 0
for sub in subdirs:
@@ -553,14 +560,16 @@ class TestCmd:
except:
pass
else:
count = count + 1
count += 1
return count
def unlink (self, file):
"""Unlinks the specified file name. The file name may be a list, in
"""
Unlinks the specified file name. The file name may be a list, in
which case the elements are concatenated using the os.path.join()
method. The file is assumed to be under the temporary working directory
unless it is an absolute path name.
"""
if type(file) is ListType:
file = apply(os.path.join, tuple(file))
@@ -574,14 +583,15 @@ class TestCmd:
self.verbose = verbose
def workdir_set(self, path):
"""Creates a temporary working directory with the specified path name.
If the path is a null string (''), a unique directory name is created.
"""
Creates a temporary working directory with the specified path name.
If the path is a null string (''), a unique directory name is created.
"""
if os.path.isabs(path):
self.workdir = path
else:
if (path != None):
if path != None:
if path == '':
path = tempfile.mktemp()
if path != None:
@@ -592,8 +602,8 @@ class TestCmd:
_Cleanup.index(self)
except ValueError:
_Cleanup.append(self)
# We'd like to set self.workdir like this:
# self.workdir = path
# We would like to set self.workdir like this:
# self.workdir = path
# But symlinks in the path will report things differently from
# os.getcwd(), so chdir there and back to fetch the canonical
# path.
@@ -605,31 +615,31 @@ class TestCmd:
self.workdir = None
def workpath(self, *args):
"""Returns the absolute path name to a subdirectory or file within the
"""
Returns the absolute path name to a subdirectory or file within the
current temporary working directory. Concatenates the temporary working
directory name with the specified arguments using the os.path.join()
method.
"""
return apply(os.path.join, (self.workdir,) + tuple(args))
def writable(self, top, write):
"""Make the specified directory tree writable (write == 1) or not
(write == None).
"""
Make the specified directory tree writable (write == 1) or not
(write == None).
"""
def _walk_chmod(arg, dirname, names):
st = os.stat(dirname)
os.chmod(dirname, arg(st[stat.ST_MODE]))
for name in names:
n = os.path.join(dirname, name)
st = os.stat(n)
os.chmod(n, arg(st[stat.ST_MODE]))
fullname = os.path.join(dirname, name)
st = os.stat(fullname)
os.chmod(fullname, arg(st[stat.ST_MODE]))
def _mode_writable(mode):
return stat.S_IMODE(mode|0200)
def _mode_non_writable(mode):
return stat.S_IMODE(mode&~0200)
_mode_writable = lambda mode: stat.S_IMODE(mode|0200)
_mode_non_writable = lambda mode: stat.S_IMODE(mode&~0200)
if write:
f = _mode_writable
@@ -641,12 +651,14 @@ class TestCmd:
pass # Ignore any problems changing modes.
def write(self, file, content, mode='wb'):
"""Writes the specified content text (second argument) to the specified
"""
Writes the specified content text (second argument) to the specified
file name (first argument). The file name may be a list, in which case
the elements are concatenated using the os.path.join() method. The file
is created under the temporary working directory. Any subdirectories in
the path must already exist. The I/O mode for the file may be specified;
it must begin with a 'w'. The default is 'wb' (binary write).
"""
if type(file) is ListType:
file = apply(os.path.join, tuple(file))

View File

@@ -19,8 +19,8 @@ toolset = BoostBuild.get_toolset()
# Clear environment for testing.
#
for s in ('BOOST_ROOT', 'BOOST_BUILD_PATH', 'JAM_TOOLSET', 'BCCROOT', 'MSVCDir',
'MSVC', 'MSVCNT', 'MINGW', 'watcom' ):
for s in ('BOOST_ROOT', 'BOOST_BUILD_PATH', 'JAM_TOOLSET', 'BCCROOT',
'MSVCDir', 'MSVC', 'MSVCNT', 'MINGW', 'watcom'):
try:
del os.environ[s]
except: