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

Major stylistic changes throughout the Boost Jam source base. No implementation changes.

Cleanup done while researching the Boost Jam internals. Added better implementation description comments at many places. Cleaned up the 'dependant' and 'dependency' terminology that got mixed up in several places. Renamed several functions to use underscores as word separators.

[SVN r48480]
This commit is contained in:
Jurko Gospodnetić
2008-08-30 23:56:49 +00:00
parent cd77b34011
commit 2f36e7187f
52 changed files with 5947 additions and 6187 deletions

View File

@@ -221,7 +221,7 @@ else
# Special targets defined in this file:
#
# all - parent of first, shell, files, lib, exe
# first - first dependent of 'all', for potential initialization
# first - first dependency of 'all', for potential initialization
# shell - parent of all Shell targets
# files - parent of all File targets
# lib - parent of all Library targets
@@ -1607,14 +1607,14 @@ rule SubDir
#
# d1 ... are the directory elements that lead to this directory
# from $(TOP). We construct the system dependent path from these
# directory elements in order to set search&locate stuff.
# directory elements in order to set search & locate stuff.
#
if ! $($(<[1]))
{
if ! $(<[1])
{
EXIT SubDir syntax error ;
EXIT SubDir syntax error ;
}
$(<[1]) = [ FSubDir $(<[2-]) ] ;
@@ -1730,14 +1730,13 @@ rule Yacc
Clean clean : $(<) $(_h) ;
}
# make sure someone includes $(_h) else it will be
# a deadly independent target
# Make sure someone includes $(_h) else it will be a deadly independent
# target.
INCLUDES $(<) : $(_h) ;
}
#
# Utility rules; no side effects on these
# Utility rules; no side effects on these.
#
rule FGrist

File diff suppressed because it is too large Load Diff

View File

@@ -11,14 +11,18 @@
#include "hash.h"
static struct hash* classes = 0;
static void check_defined(LIST* class_names)
static struct hash * classes = 0;
static void check_defined( LIST * class_names )
{
for (; class_names; class_names = class_names->next) {
char** p = &class_names->string;
if (!hashcheck(classes, (HASHDATA**)&p)) {
printf("Class %s is not defined\n", class_names->string);
for ( ; class_names; class_names = class_names->next )
{
char * * p = &class_names->string;
if ( !hashcheck( classes, (HASHDATA * *)&p ) )
{
printf( "Class %s is not defined\n", class_names->string );
abort();
}
}
@@ -27,107 +31,111 @@ static void check_defined(LIST* class_names)
static char * class_module_name( char * declared_name )
{
string name[1];
string name[ 1 ];
char * result;
string_new(name);
string_append(name, "class@");
string_append(name, declared_name);
string_new( name );
string_append( name, "class@" );
string_append( name, declared_name );
result = newstr(name->value);
string_free(name);
result = newstr( name->value );
string_free( name );
return result;
}
struct import_base_data {
char* base_name;
module_t* base_module;
module_t* class_module;
struct import_base_data
{
char * base_name;
module_t * base_module;
module_t * class_module;
};
static void import_base_rule(void* r_, void* d_)
static void import_base_rule( void * r_, void * d_ )
{
RULE* r = (RULE*)r_;
RULE* ir1;
RULE* ir2;
struct import_base_data* d = (struct import_base_data*)d_;
string qualified_name[1];
int basename_lenght = strlen(d->base_name)+1;
RULE * r = (RULE *)r_;
RULE * ir1;
RULE * ir2;
struct import_base_data * d = (struct import_base_data *)d_;
string qualified_name[ 1 ];
string_new(qualified_name);
string_append(qualified_name, d->base_name);
string_push_back(qualified_name, '.');
string_append(qualified_name, r->name);
string_new ( qualified_name );
string_append ( qualified_name, d->base_name );
string_push_back( qualified_name, '.' );
string_append ( qualified_name, r->name );
ir1 = import_rule(r, d->class_module, r->name);
ir2 = import_rule(r, d->class_module, qualified_name->value);
ir1 = import_rule( r, d->class_module, r->name );
ir2 = import_rule( r, d->class_module, qualified_name->value );
/* Copy 'exported' flag. */
ir1->exported = ir2->exported = r->exported;
/* If we're importing class method, localize it. */
if (r->module == d->base_module
|| r->module->class_module && r->module->class_module == d->base_module) {
/* If we are importing a class method, localize it. */
if ( ( r->module == d->base_module ) || ( r->module->class_module &&
( r->module->class_module == d->base_module ) ) )
ir1->module = ir2->module = d->class_module;
}
string_free(qualified_name);
string_free( qualified_name );
}
/** For each exported rule 'n', declared in class module for base,
imports that rule in 'class' as 'n' and as 'base.n'. Imported
rules are localized and marked as exported.
*/
static void import_base_rules(module_t* class, char* base)
/*
* For each exported rule 'n', declared in class module for base, imports that
* rule in 'class' as 'n' and as 'base.n'. Imported rules are localized and
* marked as exported.
*/
static void import_base_rules( module_t * class, char * base )
{
module_t* base_module = bindmodule(class_module_name(base));
module_t * base_module = bindmodule( class_module_name( base ) );
struct import_base_data d;
d.base_name = base;
d.base_module = base_module;
d.class_module = class;
if (base_module->rules)
hashenumerate(base_module->rules, import_base_rule, &d);
if ( base_module->rules )
hashenumerate( base_module->rules, import_base_rule, &d );
import_module( imported_modules(base_module), class );
import_module( imported_modules( base_module ), class );
}
char * make_class_module( LIST * xname, LIST * bases, FRAME * frame )
{
char* name = class_module_name(xname->string);
char** pp = &xname->string;
module_t* class_module = 0;
module_t* outer_module = frame->module;
char * name = class_module_name( xname->string );
char * * pp = &xname->string;
module_t * class_module = 0;
module_t * outer_module = frame->module;
if ( !classes )
classes = hashinit(sizeof(char*), "classes");
classes = hashinit( sizeof( char * ), "classes" );
if ( hashcheck( classes, (HASHDATA**)&pp ) )
if ( hashcheck( classes, (HASHDATA * *)&pp ) )
{
printf("Class %s already defined\n", xname->string);
printf( "Class %s already defined\n", xname->string );
abort();
}
else
{
hashenter(classes, (HASHDATA**)&pp);
hashenter( classes, (HASHDATA * *)&pp );
}
check_defined(bases);
check_defined( bases );
class_module = bindmodule(name);
class_module = bindmodule( name );
exit_module( outer_module );
enter_module( class_module );
var_set("__name__", xname, VAR_SET);
var_set("__bases__", bases, VAR_SET);
var_set( "__name__", xname, VAR_SET );
var_set( "__bases__", bases, VAR_SET );
exit_module( class_module );
enter_module( outer_module );
for(; bases; bases = bases->next)
import_base_rules(class_module, bases->string);
for ( ; bases; bases = bases->next )
import_base_rules( class_module, bases->string );
return name;
}

View File

@@ -14,30 +14,26 @@
* command.c - maintain lists of commands
*/
# include "jam.h"
#include "jam.h"
# include "lists.h"
# include "parse.h"
# include "variable.h"
# include "rules.h"
#include "lists.h"
#include "parse.h"
#include "variable.h"
#include "rules.h"
#include "command.h"
#include <limits.h>
#include <string.h>
# include "command.h"
# include <limits.h>
# include <string.h>
/*
* cmd_new() - return a new CMD or 0 if too many args
*/
CMD *
cmd_new(
RULE *rule,
LIST *targets,
LIST *sources,
LIST *shell )
CMD * cmd_new( RULE * rule, LIST * targets, LIST * sources, LIST * shell )
{
CMD *cmd = (CMD *)BJAM_MALLOC( sizeof( CMD ) );
/* lift line-length limitation entirely when JAMSHELL is just "%" */
CMD * cmd = (CMD *)BJAM_MALLOC( sizeof( CMD ) );
/* Lift line-length limitation entirely when JAMSHELL is just "%". */
int no_limit = ( shell && !strcmp(shell->string,"%") && !list_next(shell) );
int max_line = MAXLINE;
int allocated = -1;
@@ -53,9 +49,9 @@ cmd_new(
do
{
BJAM_FREE(cmd->buf); /* free any buffer from previous iteration */
BJAM_FREE( cmd->buf ); /* free any buffer from previous iteration */
cmd->buf = (char*)BJAM_MALLOC_ATOMIC(max_line + 1);
cmd->buf = (char*)BJAM_MALLOC_ATOMIC( max_line + 1 );
if ( cmd->buf == 0 )
break;
@@ -64,11 +60,11 @@ cmd_new(
max_line = max_line * 2;
}
while( allocated < 0 && max_line < INT_MAX / 2 );
while ( ( allocated < 0 ) && ( max_line < INT_MAX / 2 ) );
if ( !no_limit )
{
/* Bail if the result won't fit in MAXLINE */
/* Bail if the result will not fit in MAXLINE. */
char * s = cmd->buf;
while ( *s )
{
@@ -76,7 +72,7 @@ cmd_new(
if ( l > MAXLINE )
{
/* We don't free targets/sources/shell if bailing. */
/* We do not free targets/sources/shell if bailing. */
cmd_free( cmd );
return 0;
}
@@ -90,12 +86,12 @@ cmd_new(
return cmd;
}
/*
* cmd_free() - free a CMD
*/
void
cmd_free( CMD *cmd )
void cmd_free( CMD * cmd )
{
lol_free( &cmd->args );
list_free( cmd->shell );

View File

@@ -22,37 +22,40 @@
*
* Structures:
*
* CMD - an action, ready to be formatted into a buffer and executed
* CMD - an action, ready to be formatted into a buffer and executed.
*
* External routines:
*
* cmd_new() - return a new CMD or 0 if too many args
* cmd_free() - delete CMD and its parts
* cmd_next() - walk the CMD chain
* cmd_new() - return a new CMD or 0 if too many args.
* cmd_free() - delete CMD and its parts.
* cmd_next() - walk the CMD chain.
*/
/*
* CMD - an action, ready to be formatted into a buffer and executed
* CMD - an action, ready to be formatted into a buffer and executed.
*/
typedef struct _cmd CMD;
struct _cmd
{
CMD *next;
CMD *tail; /* valid on in head */
RULE *rule; /* rule->actions contains shell script */
LIST *shell; /* $(SHELL) value */
LOL args; /* LISTs for $(<), $(>) */
char* buf; /* actual commands */
} ;
CMD * next;
CMD * tail; /* valid on in head */
RULE * rule; /* rule->actions contains shell script */
LIST * shell; /* $(SHELL) value */
LOL args; /* LISTs for $(<), $(>) */
char * buf; /* actual commands */
};
CMD *cmd_new(
RULE *rule, /* rule (referenced) */
LIST *targets, /* $(<) (freed) */
LIST *sources, /* $(>) (freed) */
LIST *shell ); /* $(SHELL) (freed) */
CMD * cmd_new
(
RULE * rule, /* rule (referenced) */
LIST * targets, /* $(<) (freed) */
LIST * sources, /* $(>) (freed) */
LIST * shell /* $(SHELL) (freed) */
);
void cmd_free( CMD *cmd );
void cmd_free( CMD * );
# define cmd_next( c ) ((c)->next)
#define cmd_next( c ) ( ( c )->next )

File diff suppressed because it is too large Load Diff

View File

@@ -4,45 +4,47 @@
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
*/
# include "jam.h"
#include "jam.h"
# include "hash.h"
#include "hash.h"
# include <time.h>
# include <assert.h>
#include <time.h>
#include <assert.h>
static profile_frame* profile_stack = 0;
static struct hash* profile_hash = 0;
static profile_info profile_other = { "[OTHER]", 0, 0, 0, 0, 0 };
static profile_info profile_total = { "[TOTAL]", 0, 0, 0, 0, 0 };
profile_frame* profile_init( char* rulename, profile_frame* frame )
static profile_frame * profile_stack = 0;
static struct hash * profile_hash = 0;
static profile_info profile_other = { "[OTHER]", 0, 0, 0, 0, 0 };
static profile_info profile_total = { "[TOTAL]", 0, 0, 0, 0, 0 };
profile_frame * profile_init( char * rulename, profile_frame * frame )
{
if ( DEBUG_PROFILE ) profile_enter(rulename,frame);
if ( DEBUG_PROFILE ) profile_enter( rulename, frame );
return frame;
}
void profile_enter( char* rulename, profile_frame* frame )
void profile_enter( char * rulename, profile_frame * frame )
{
if ( DEBUG_PROFILE )
{
clock_t start = clock();
profile_info info, *p = &info;
profile_info info;
profile_info * p = &info;
if ( !rulename ) p = &profile_other;
if ( !profile_hash )
{
if ( rulename ) profile_hash = hashinit(sizeof(profile_info), "profile");
}
if ( !profile_hash && rulename )
profile_hash = hashinit( sizeof( profile_info ), "profile" );
info.name = rulename;
if ( rulename && hashenter( profile_hash, (HASHDATA **)&p ) )
if ( rulename && hashenter( profile_hash, (HASHDATA * *)&p ) )
p->cumulative = p->net = p->num_entries = p->stack_count = p->memory = 0;
++(p->num_entries);
++(p->stack_count);
++p->num_entries;
++p->stack_count;
frame->info = p;
@@ -72,22 +74,24 @@ void profile_exit( profile_frame * frame )
{
if ( DEBUG_PROFILE )
{
/* cumulative time for this call */
/* Cumulative time for this call. */
clock_t t = clock() - frame->entry_time - frame->overhead;
/* If this rule is already present on the stack, don't add the time for
this instance. */
* this instance.
*/
if ( frame->info->stack_count == 1 )
frame->info->cumulative += t;
/* Net time does not depend on presense of the same rule in call stack. */
/* Net time does not depend on presense of the same rule in call stack.
*/
frame->info->net += t - frame->subrules;
if ( frame->caller )
{
/* caller's cumulative time must account for this overhead */
/* Caller's cumulative time must account for this overhead. */
frame->caller->overhead += frame->overhead;
frame->caller->subrules += t;
}
/* pop this stack frame */
/* Pop this stack frame. */
--frame->info->stack_count;
profile_stack = frame->caller;
}
@@ -97,24 +101,21 @@ void profile_exit( profile_frame * frame )
static void dump_profile_entry( void * p_, void * ignored )
{
profile_info * p = (profile_info *)p_;
unsigned long mem_each = (p->memory/(p->num_entries ? p->num_entries : 1));
unsigned long mem_each = ( p->memory / ( p->num_entries ? p->num_entries : 1 ) );
double cumulative = p->cumulative;
double net = p->net;
double q = p->net;
q /= (p->num_entries ? p->num_entries : 1);
q /= ( p->num_entries ? p->num_entries : 1 );
cumulative /= CLOCKS_PER_SEC;
net /= CLOCKS_PER_SEC;
q /= CLOCKS_PER_SEC;
if (!ignored)
if ( !ignored )
{
profile_total.cumulative += p->net;
profile_total.memory += p->memory;
}
printf("%10d %12.6f %12.6f %12.8f %10d %10d %s\n",
p->num_entries,
cumulative,net,q,
p->memory, mem_each,
p->name);
printf( "%10d %12.6f %12.6f %12.8f %10d %10d %s\n", p->num_entries,
cumulative, net, q, p->memory, mem_each, p->name );
}
@@ -122,10 +123,8 @@ void profile_dump()
{
if ( profile_hash )
{
printf( "%10s %12s %12s %12s %10s %10s %s\n",
"--count--", "--gross--", "--net--", "--each--",
"--mem--", "--each--",
"--name--" );
printf( "%10s %12s %12s %12s %10s %10s %s\n", "--count--", "--gross--",
"--net--", "--each--", "--mem--", "--each--", "--name--" );
hashenumerate( profile_hash, dump_profile_entry, 0 );
dump_profile_entry( &profile_other, 0 );
dump_profile_entry( &profile_total, (void *)1 );

View File

@@ -6,8 +6,9 @@
#ifndef BJAM_DEBUG_H
#define BJAM_DEBUG_H
# include "jam.h"
# include <time.h>
#include "jam.h"
#include <time.h>
struct profile_info
{
@@ -41,13 +42,13 @@ struct profile_frame
};
typedef struct profile_frame profile_frame;
profile_frame * profile_init( char* rulename, profile_frame* frame );
void profile_enter( char* rulename, profile_frame* frame );
profile_frame * profile_init( char * rulename, profile_frame * frame );
void profile_enter( char* rulename, profile_frame * frame );
void profile_memory( long mem );
void profile_exit(profile_frame* frame);
void profile_exit( profile_frame * frame );
void profile_dump();
#define PROFILE_ENTER(scope) profile_frame PROF_ ## scope, *PROF_ ## scope ## _p = profile_init(#scope,&PROF_ ## scope)
#define PROFILE_EXIT(scope) profile_exit(PROF_ ## scope ## _p)
#define PROFILE_ENTER( scope ) profile_frame PROF_ ## scope, *PROF_ ## scope ## _p = profile_init( #scope, &PROF_ ## scope )
#define PROFILE_EXIT( scope ) profile_exit( PROF_ ## scope ## _p )
#endif

View File

@@ -5,7 +5,10 @@
*/
/*
* execcmd.h - execute a shell script
* execcmd.h - execute a shell script.
*
* Defines the interface to be implemented in platform specific implementation
* modules.
*
* 05/04/94 (seiwald) - async multiprocess interface
*/
@@ -23,18 +26,20 @@ typedef struct timing_info
time_t end;
} timing_info;
void execcmd(
char *string,
void (*func)( void *closure, int status, timing_info*, char *, char * ),
void *closure,
LIST *shell,
char *action,
char *target);
void exec_cmd
(
char * string,
void (* func)( void * closure, int status, timing_info *, char *, char * ),
void * closure,
LIST * shell,
char * action,
char * target
);
int execwait();
int exec_wait();
# define EXEC_CMD_OK 0
# define EXEC_CMD_FAIL 1
# define EXEC_CMD_INTR 2
#define EXEC_CMD_OK 0
#define EXEC_CMD_FAIL 1
#define EXEC_CMD_INTR 2
#endif

View File

@@ -4,12 +4,12 @@
* This file is part of Jam - see jam.c for Copyright information.
*/
# include "jam.h"
# include "lists.h"
# include "execcmd.h"
# include <errno.h>
#include "jam.h"
#include "lists.h"
#include "execcmd.h"
#include <errno.h>
# ifdef OS_MAC
#ifdef OS_MAC
/*
* execunix.c - execute a shell script on UNIX
@@ -29,39 +29,41 @@
* Don't just set JAMSHELL to /bin/sh - it won't work!
*
* External routines:
* execcmd() - launch an async command execution
* execwait() - wait and drive at most one execution completion
* exec_cmd() - launch an async command execution.
* exec_wait() - wait and drive at most one execution completion.
*
* Internal routines:
* onintr() - bump intr to note command interruption
* onintr() - bump intr to note command interruption.
*
* 04/08/94 (seiwald) - Coherent/386 support added.
* 05/04/94 (seiwald) - async multiprocess interface
* 01/22/95 (seiwald) - $(JAMSHELL) support
*/
/*
* execcmd() - launch an async command execution
* exec_cmd() - launch an async command execution.
*/
void execcmd(
char *string,
void (*func)( void *closure, int status, timing_info*, char *, char * ),
void *closure,
LIST *shell )
void exec_cmd
(
char * string,
void (* func)( void * closure, int status, timing_info *, char *, char * ),
void * closure,
LIST * shell
)
{
printf( "%s", string );
(*func)( closure, EXEC_CMD_OK );
}
/*
* execwait() - wait and drive at most one execution completion
* exec_wait() - wait and drive at most one execution completion.
*/
int
execwait()
int exec_wait()
{
return 0;
}
# endif /* OS_MAC */
#endif /* OS_MAC */

File diff suppressed because it is too large Load Diff

View File

@@ -5,33 +5,35 @@
* This file is part of Jam - see jam.c for Copyright information.
*/
# include "jam.h"
# include "lists.h"
# include "execcmd.h"
# include "output.h"
# include <errno.h>
# include <signal.h>
# include <stdio.h>
# include <time.h>
# include <unistd.h> /* needed for vfork(), _exit() prototypes */
# include <sys/resource.h>
# include <sys/times.h>
# include <sys/wait.h>
#include "jam.h"
#include "lists.h"
#include "execcmd.h"
#include "output.h"
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h> /* needed for vfork(), _exit() prototypes */
#include <sys/resource.h>
#include <sys/times.h>
#include <sys/wait.h>
#if defined(sun) || defined(__sun) || defined(linux)
#include <wait.h>
#include <wait.h>
#endif
# ifdef USE_EXECUNIX
# include <sys/times.h>
#ifdef USE_EXECUNIX
# if defined(__APPLE__)
# define NO_VFORK
# endif
#include <sys/times.h>
#if defined(__APPLE__)
#define NO_VFORK
#endif
#ifdef NO_VFORK
#define vfork() fork()
#endif
# ifdef NO_VFORK
# define vfork() fork()
# endif
/*
* execunix.c - execute a shell script on UNIX/WinNT/OS2/AmigaOS
@@ -44,19 +46,18 @@
*
* Each word must be an individual element in a jam variable value.
*
* In $(JAMSHELL), % expands to the command string and ! expands to
* the slot number (starting at 1) for multiprocess (-j) invocations.
* If $(JAMSHELL) doesn't include a %, it is tacked on as the last
* argument.
* In $(JAMSHELL), % expands to the command string and ! expands to the slot
* number (starting at 1) for multiprocess (-j) invocations. If $(JAMSHELL) does
* not include a %, it is tacked on as the last argument.
*
* Don't just set JAMSHELL to /bin/sh or cmd.exe - it won't work!
* Do not just set JAMSHELL to /bin/sh or cmd.exe - it will not work!
*
* External routines:
* execcmd() - launch an async command execution
* execwait() - wait and drive at most one execution completion
* exec_cmd() - launch an async command execution.
* exec_wait() - wait and drive at most one execution completion.
*
* Internal routines:
* onintr() - bump intr to note command interruption
* onintr() - bump intr to note command interruption.
*
* 04/08/94 (seiwald) - Coherent/386 support added.
* 05/04/94 (seiwald) - async multiprocess interface
@@ -96,450 +97,466 @@ static struct
* onintr() - bump intr to note command interruption
*/
void
onintr( int disp )
void onintr( int disp )
{
intr++;
++intr;
printf( "...interrupted\n" );
}
/*
* execcmd() - launch an async command execution
* exec_cmd() - launch an async command execution.
*/
void
execcmd(
char *string,
void exec_cmd
(
char * string,
void (*func)( void *closure, int status, timing_info*, char *, char * ),
void *closure,
LIST *shell,
char *action,
char *target )
void * closure,
LIST * shell,
char * action,
char * target
)
{
static int initialized = 0;
int out[2], err[2];
int slot, len;
char *argv[ MAXARGC + 1 ]; /* +1 for NULL */
static int initialized = 0;
int out[2];
int err[2];
int slot;
int len;
char * argv[ MAXARGC + 1 ]; /* +1 for NULL */
/* Find a slot in the running commands table for this one. */
for ( slot = 0; slot < MAXJOBS; ++slot )
if ( !cmdtab[ slot ].pid )
break;
for( slot = 0; slot < MAXJOBS; slot++ )
if( !cmdtab[ slot ].pid )
break;
if( slot == MAXJOBS )
if ( slot == MAXJOBS )
{
printf( "no slots for child!\n" );
exit( EXITBAD );
}
/* Forumulate argv */
/* If shell was defined, be prepared for % and ! subs. */
/* Otherwise, use stock /bin/sh (on unix) or cmd.exe (on NT). */
if( shell )
/* Forumulate argv. If shell was defined, be prepared for % and ! subs.
* Otherwise, use stock /bin/sh on unix or cmd.exe on NT.
*/
if ( shell )
{
int i;
int i;
char jobno[4];
int gotpercent = 0;
int gotpercent = 0;
sprintf( jobno, "%d", slot + 1 );
for( i = 0; shell && i < MAXARGC; i++, shell = list_next( shell ) )
for ( i = 0; shell && i < MAXARGC; ++i, shell = list_next( shell ) )
{
switch( shell->string[0] )
{
case '%': argv[i] = string; gotpercent++; break;
case '!': argv[i] = jobno; break;
default: argv[i] = shell->string;
}
if( DEBUG_EXECCMD )
printf( "argv[%d] = '%s'\n", i, argv[i] );
switch ( shell->string[0] )
{
case '%': argv[ i ] = string; ++gotpercent; break;
case '!': argv[ i ] = jobno; break;
default : argv[ i ] = shell->string;
}
if ( DEBUG_EXECCMD )
printf( "argv[%d] = '%s'\n", i, argv[ i ] );
}
if( !gotpercent )
argv[i++] = string;
if ( !gotpercent )
argv[ i++ ] = string;
argv[i] = 0;
argv[ i ] = 0;
}
else
{
argv[0] = "/bin/sh";
argv[1] = "-c";
argv[2] = string;
argv[3] = 0;
argv[ 0 ] = "/bin/sh";
argv[ 1 ] = "-c";
argv[ 2 ] = string;
argv[ 3 ] = 0;
}
/* increment jobs running */
/* Increment jobs running. */
++cmdsrunning;
/* save off actual command string */
cmdtab[ slot ].command = BJAM_MALLOC_ATOMIC(strlen(string)+1);
strcpy(cmdtab[slot].command, string);
/* Save off actual command string. */
cmdtab[ slot ].command = BJAM_MALLOC_ATOMIC( strlen( string ) + 1 );
strcpy( cmdtab[ slot ].command, string );
/* initialize only once */
if ( ! initialized ) {
times(&old_time);
initialized = 1;
}
/* Initialize only once. */
if ( !initialized )
{
times( &old_time );
initialized = 1;
}
/* create pipe from child to parent */
/* Create pipes from child to parent. */
{
if ( pipe( out ) < 0 )
exit( EXITBAD );
fcntl( out[0], F_SETFL, O_NONBLOCK );
fcntl( out[1], F_SETFL, O_NONBLOCK );
if (pipe(out) < 0)
exit(EXITBAD);
fcntl(out[0], F_SETFL, O_NONBLOCK);
fcntl(out[1], F_SETFL, O_NONBLOCK);
if (pipe(err) < 0)
exit(EXITBAD);
fcntl(err[0], F_SETFL, O_NONBLOCK);
fcntl(err[1], F_SETFL, O_NONBLOCK);
if ( pipe( err ) < 0 )
exit( EXITBAD );
fcntl( err[0], F_SETFL, O_NONBLOCK );
fcntl( err[1], F_SETFL, O_NONBLOCK );
}
/* Start the command */
cmdtab[ slot ].start_dt = time(0);
cmdtab[ slot ].start_dt = time(0);
if (0 < globs.timeout) {
/*
* handle hung processes by manually tracking elapsed
* time and signal process when time limit expires
*/
struct tms buf;
cmdtab[ slot ].start_time = times(&buf);
/* make a global, only do this once */
if (tps == 0) tps = sysconf(_SC_CLK_TCK);
}
if ((cmdtab[slot].pid = vfork()) == 0)
if ( 0 < globs.timeout )
{
int pid = getpid();
/*
* Handle hung processes by manually tracking elapsed time and signal
* process when time limit expires.
*/
struct tms buf;
cmdtab[ slot ].start_time = times( &buf );
close(out[0]);
close(err[0]);
/* Make a global, only do this once. */
if ( tps == 0 ) tps = sysconf( _SC_CLK_TCK );
}
dup2(out[1], STDOUT_FILENO);
if ( ( cmdtab[ slot ].pid = vfork() ) == 0 )
{
int pid = getpid();
if (globs.pipe_action == 0)
{
dup2(out[1], STDERR_FILENO);
close(err[1]);
}
else
dup2(err[1], STDERR_FILENO);
close( out[0] );
close( err[0] );
/* Make this process a process group leader
* so that when we kill it, all child
* processes of this process are terminated
* as well.
*
* we use killpg(pid, SIGKILL) to kill the
* process group leader and all its children.
*/
if (0 < globs.timeout)
{
struct rlimit r_limit;
r_limit.rlim_cur = globs.timeout;
r_limit.rlim_max = globs.timeout;
setrlimit(RLIMIT_CPU, &r_limit);
}
setpgid(pid,pid);
execvp( argv[0], argv );
perror( "execvp" );
_exit(127);
dup2( out[1], STDOUT_FILENO );
if ( globs.pipe_action == 0 )
{
dup2( out[1], STDERR_FILENO );
close( err[1] );
}
else if( cmdtab[slot].pid == -1 )
else
dup2( err[1], STDERR_FILENO );
/* Make this process a process group leader so that when we kill it, all
* child processes of this process are terminated as well. We use
* killpg(pid, SIGKILL) to kill the process group leader and all its
* children.
*/
if ( 0 < globs.timeout )
{
struct rlimit r_limit;
r_limit.rlim_cur = globs.timeout;
r_limit.rlim_max = globs.timeout;
setrlimit( RLIMIT_CPU, &r_limit );
}
setpgid( pid,pid );
execvp( argv[0], argv );
perror( "execvp" );
_exit( 127 );
}
else if ( cmdtab[ slot ].pid == -1 )
{
perror( "vfork" );
exit( EXITBAD );
}
setpgid(cmdtab[slot].pid, cmdtab[slot].pid);
setpgid( cmdtab[ slot ].pid, cmdtab[ slot ].pid );
/* close write end of pipes */
close(out[1]);
close(err[1]);
/* close write end of pipes */
close( out[1] );
close( err[1] );
/* child writes stdout to out[1], parent reads from out[0] */
cmdtab[slot].fd[OUT] = out[0];
cmdtab[slot].stream[OUT] = fdopen(cmdtab[slot].fd[OUT], "rb");
if (cmdtab[slot].stream[OUT] == NULL) {
/* child writes stdout to out[1], parent reads from out[0] */
cmdtab[ slot ].fd[ OUT ] = out[0];
cmdtab[ slot ].stream[ OUT ] = fdopen( cmdtab[ slot ].fd[ OUT ], "rb" );
if ( cmdtab[ slot ].stream[ OUT ] == NULL )
{
perror( "fdopen" );
exit( EXITBAD );
}
/* child writes stderr to err[1], parent reads from err[0] */
if (globs.pipe_action == 0)
{
close(err[0]);
}
else
{
cmdtab[ slot ].fd[ ERR ] = err[0];
cmdtab[ slot ].stream[ ERR ] = fdopen( cmdtab[ slot ].fd[ ERR ], "rb" );
if ( cmdtab[ slot ].stream[ ERR ] == NULL )
{
perror( "fdopen" );
exit( EXITBAD );
}
}
/* child writes stderr to err[1], parent reads from err[0] */
if (globs.pipe_action == 0)
/* Ensure enough room for rule and target name. */
if ( action && target )
{
len = strlen( action ) + 1;
if ( cmdtab[ slot ].action_length < len )
{
close(err[0]);
BJAM_FREE( cmdtab[ slot ].action );
cmdtab[ slot ].action = BJAM_MALLOC_ATOMIC( len );
cmdtab[ slot ].action_length = len;
}
else
strcpy( cmdtab[ slot ].action, action );
len = strlen( target ) + 1;
if ( cmdtab[ slot ].target_length < len )
{
cmdtab[slot].fd[ERR] = err[0];
cmdtab[slot].stream[ERR] = fdopen(cmdtab[slot].fd[ERR], "rb");
if (cmdtab[slot].stream[ERR] == NULL) {
perror( "fdopen" );
exit( EXITBAD );
}
BJAM_FREE( cmdtab[ slot ].target );
cmdtab[ slot ].target = BJAM_MALLOC_ATOMIC( len );
cmdtab[ slot ].target_length = len;
}
strcpy( cmdtab[ slot ].target, target );
}
else
{
BJAM_FREE( cmdtab[ slot ].action );
BJAM_FREE( cmdtab[ slot ].target );
cmdtab[ slot ].action = 0;
cmdtab[ slot ].target = 0;
cmdtab[ slot ].action_length = 0;
cmdtab[ slot ].target_length = 0;
}
/* ensure enough room for rule and target name */
if (action && target)
{
len = strlen(action) + 1;
if (cmdtab[slot].action_length < len)
{
BJAM_FREE(cmdtab[ slot ].action);
cmdtab[ slot ].action = BJAM_MALLOC_ATOMIC(len);
cmdtab[ slot ].action_length = len;
}
strcpy(cmdtab[ slot ].action, action);
len = strlen(target) + 1;
if (cmdtab[slot].target_length < len)
{
BJAM_FREE(cmdtab[ slot ].target);
cmdtab[ slot ].target = BJAM_MALLOC_ATOMIC(len);
cmdtab[ slot ].target_length = len;
}
strcpy(cmdtab[ slot ].target, target);
}
else
{
BJAM_FREE(cmdtab[ slot ].action);
BJAM_FREE(cmdtab[ slot ].target);
cmdtab[ slot ].action = 0;
cmdtab[ slot ].target = 0;
cmdtab[ slot ].action_length = 0;
cmdtab[ slot ].target_length = 0;
}
/* Save the operation for execwait() to find. */
/* Save the operation for exec_wait() to find. */
cmdtab[ slot ].func = func;
cmdtab[ slot ].closure = closure;
/* Wait until we're under the limit of concurrent commands. */
/* Don't trust globs.jobs alone. */
while( cmdsrunning >= MAXJOBS || cmdsrunning >= globs.jobs )
if( !execwait() )
break;
/* Wait until we are under the limit of concurrent commands. Do not trust
* globs.jobs alone.
*/
while ( ( cmdsrunning >= MAXJOBS ) || ( cmdsrunning >= globs.jobs ) )
if ( !exec_wait() )
break;
}
/* returns 1 if file is closed, 0 if descriptor is still live
/* Returns 1 if file is closed, 0 if descriptor is still live.
*
* i is index into cmdtab
*
* s (stream) indexes
*
* cmdtab[i].stream[s]
* cmdtab[i].buffer[s] and
* cmdtab[i].fd[s]
* s (stream) indexes:
* - cmdtab[ i ].stream[ s ]
* - cmdtab[ i ].buffer[ s ]
* - cmdtab[ i ].fd [ s ]
*/
int read_descriptor(int i, int s)
int read_descriptor( int i, int s )
{
int ret, len;
int ret;
int len;
char buffer[BUFSIZ];
while (0 < (ret = fread(buffer, sizeof(char), BUFSIZ-1, cmdtab[i].stream[s])))
while ( 0 < ( ret = fread( buffer, sizeof(char), BUFSIZ-1, cmdtab[ i ].stream[ s ] ) ) )
{
buffer[ret] = 0;
if (!cmdtab[i].buffer[s])
if ( !cmdtab[ i ].buffer[ s ] )
{
/* never been allocated */
cmdtab[i].buffer[s] = (char*)BJAM_MALLOC_ATOMIC(ret+1);
memcpy(cmdtab[i].buffer[s], buffer, ret+1);
/* Never been allocated. */
cmdtab[ i ].buffer[ s ] = (char*)BJAM_MALLOC_ATOMIC( ret + 1 );
memcpy( cmdtab[ i ].buffer[ s ], buffer, ret + 1 );
}
else
{
/* previously allocated */
char *tmp = cmdtab[i].buffer[s];
len = strlen(tmp);
cmdtab[i].buffer[s] = (char*)BJAM_MALLOC_ATOMIC(len+ret+1);
memcpy(cmdtab[i].buffer[s], tmp, len);
memcpy(cmdtab[i].buffer[s]+len, buffer, ret+1);
BJAM_FREE(tmp);
/* Previously allocated. */
char * tmp = cmdtab[ i ].buffer[ s ];
len = strlen( tmp );
cmdtab[ i ].buffer[ s ] = (char*)BJAM_MALLOC_ATOMIC( len + ret + 1 );
memcpy( cmdtab[ i ].buffer[ s ], tmp, len );
memcpy( cmdtab[ i ].buffer[ s ] + len, buffer, ret + 1 );
BJAM_FREE( tmp );
}
}
return feof(cmdtab[i].stream[s]);
return feof(cmdtab[ i ].stream[ s ]);
}
void close_streams(int i, int s)
void close_streams( int i, int s )
{
/* close the stream and pipe descriptor */
fclose(cmdtab[i].stream[s]);
cmdtab[i].stream[s] = 0;
/* Close the stream and pipe descriptor. */
fclose(cmdtab[ i ].stream[ s ]);
cmdtab[ i ].stream[ s ] = 0;
close(cmdtab[i].fd[s]);
cmdtab[i].fd[s] = 0;
close(cmdtab[ i ].fd[ s ]);
cmdtab[ i ].fd[ s ] = 0;
}
void populate_file_descriptors(int *fmax, fd_set *fds)
void populate_file_descriptors( int * fmax, fd_set * fds)
{
int i, fd_max = 0;
struct tms buf;
clock_t current = times(&buf);
clock_t current = times( &buf );
select_timeout = globs.timeout;
/* compute max read file descriptor for use in select */
/* Compute max read file descriptor for use in select. */
FD_ZERO(fds);
for (i=0; i<globs.jobs; ++i)
for ( i = 0; i < globs.jobs; ++i )
{
if (0 < cmdtab[i].fd[OUT])
if ( 0 < cmdtab[ i ].fd[ OUT ] )
{
fd_max = fd_max < cmdtab[i].fd[OUT] ? cmdtab[i].fd[OUT] : fd_max;
FD_SET(cmdtab[i].fd[OUT], fds);
fd_max = fd_max < cmdtab[ i ].fd[ OUT ] ? cmdtab[ i ].fd[ OUT ] : fd_max;
FD_SET(cmdtab[ i ].fd[ OUT ], fds);
}
if (globs.pipe_action != 0)
if ( globs.pipe_action != 0 )
{
if (0 < cmdtab[i].fd[ERR])
if (0 < cmdtab[ i ].fd[ ERR ])
{
fd_max = fd_max < cmdtab[i].fd[ERR] ? cmdtab[i].fd[ERR] : fd_max;
FD_SET(cmdtab[i].fd[ERR], fds);
fd_max = fd_max < cmdtab[ i ].fd[ ERR ] ? cmdtab[ i ].fd[ ERR ] : fd_max;
FD_SET(cmdtab[ i ].fd[ ERR ], fds);
}
}
if (globs.timeout && cmdtab[i].pid) {
clock_t consumed = (current - cmdtab[i].start_time) / tps;
if (globs.timeout && cmdtab[ i ].pid) {
clock_t consumed = (current - cmdtab[ i ].start_time) / tps;
clock_t process_timesout = globs.timeout - consumed;
if (0 < process_timesout && process_timesout < select_timeout) {
select_timeout = process_timesout;
}
if (globs.timeout <= consumed) {
killpg(cmdtab[i].pid, SIGKILL);
cmdtab[i].exit_reason = EXIT_TIMEOUT;
if ( globs.timeout <= consumed )
{
killpg( cmdtab[ i ].pid, SIGKILL );
cmdtab[ i ].exit_reason = EXIT_TIMEOUT;
}
}
}
*fmax = fd_max;
}
/*
* execwait() - wait and drive at most one execution completion
* exec_wait() - wait and drive at most one execution completion.
*/
int
execwait()
int exec_wait()
{
int i, ret, fd_max;
int pid, status, finished;
int rstat;
int i;
int ret;
int fd_max;
int pid;
int status;
int finished;
int rstat;
timing_info time_info;
fd_set fds;
struct tms new_time;
fd_set fds;
struct tms new_time;
/* Handle naive make1() which doesn't know if cmds are running. */
if( !cmdsrunning )
/* Handle naive make1() which does not know if commands are running. */
if ( !cmdsrunning )
return 0;
/* process children that signaled */
/* Process children that signaled. */
finished = 0;
while (!finished && cmdsrunning)
while ( !finished && cmdsrunning )
{
/* compute max read file descriptor for use in select */
populate_file_descriptors(&fd_max, &fds);
/* Compute max read file descriptor for use in select(). */
populate_file_descriptors( &fd_max, &fds );
if (0 < globs.timeout) {
/* force select to timeout so we can terminate expired processes */
if ( 0 < globs.timeout )
{
/* Force select() to timeout so we can terminate expired processes.
*/
tv.tv_sec = select_timeout;
tv.tv_usec = 0;
/* select will wait until: io on a descriptor, a signal, or we time out */
ret = select(fd_max+1, &fds, 0, 0, &tv);
/* select() will wait until: i/o on a descriptor, a signal, or we
* time out.
*/
ret = select( fd_max + 1, &fds, 0, 0, &tv );
}
else {
/* select will wait until io on a descriptor or a signal */
ret = select(fd_max+1, &fds, 0, 0, 0);
}
if (0 < ret)
else
{
for (i=0; i<globs.jobs; ++i)
/* select() will wait until i/o on a descriptor or a signal. */
ret = select( fd_max + 1, &fds, 0, 0, 0 );
}
if ( 0 < ret )
{
for ( i = 0; i < globs.jobs; ++i )
{
int out = 0, err = 0;
if (FD_ISSET(cmdtab[i].fd[OUT], &fds))
out = read_descriptor(i, OUT);
int out = 0;
int err = 0;
if ( FD_ISSET( cmdtab[ i ].fd[ OUT ], &fds ) )
out = read_descriptor( i, OUT );
if ((globs.pipe_action != 0) && (FD_ISSET(cmdtab[i].fd[ERR], &fds)))
err = read_descriptor(i, ERR);
if ( ( globs.pipe_action != 0 ) &&
( FD_ISSET( cmdtab[ i ].fd[ ERR ], &fds ) ) )
err = read_descriptor( i, ERR );
/* if feof on either descriptor, then we're done */
if (out || err)
/* If feof on either descriptor, then we are done. */
if ( out || err )
{
/* close the stream and pipe descriptors */
close_streams(i, OUT);
if (globs.pipe_action != 0)
close_streams(i, ERR);
/* Close the stream and pipe descriptors. */
close_streams( i, OUT );
if ( globs.pipe_action != 0 )
close_streams( i, ERR );
/* reap the child and release resources */
pid = waitpid(cmdtab[i].pid, &status, 0);
/* Reap the child and release resources. */
pid = waitpid( cmdtab[ i ].pid, &status, 0 );
if (pid == cmdtab[i].pid)
if ( pid == cmdtab[ i ].pid )
{
finished = 1;
pid = 0;
cmdtab[i].pid = 0;
cmdtab[ i ].pid = 0;
/* set reason for exit if not timed out */
if (WIFEXITED(status))
/* Set reason for exit if not timed out. */
if ( WIFEXITED( status ) )
{
if (0 == WEXITSTATUS(status))
cmdtab[i].exit_reason = EXIT_OK;
else
cmdtab[i].exit_reason = EXIT_FAIL;
cmdtab[ i ].exit_reason = 0 == WEXITSTATUS( status )
? EXIT_OK
: EXIT_FAIL;
}
/* print out the rule and target name */
out_action(cmdtab[i].action, cmdtab[i].target,
cmdtab[i].command, cmdtab[i].buffer[OUT], cmdtab[i].buffer[ERR],
cmdtab[i].exit_reason);
/* Print out the rule and target name. */
out_action( cmdtab[ i ].action, cmdtab[ i ].target,
cmdtab[ i ].command, cmdtab[ i ].buffer[ OUT ],
cmdtab[ i ].buffer[ ERR ], cmdtab[ i ].exit_reason
);
times(&new_time);
times( &new_time );
time_info.system = (double)(new_time.tms_cstime - old_time.tms_cstime) / CLOCKS_PER_SEC;
time_info.user = (double)(new_time.tms_cutime - old_time.tms_cutime) / CLOCKS_PER_SEC;
time_info.start = cmdtab[i].start_dt;
time_info.end = time(0);
time_info.system = (double)( new_time.tms_cstime - old_time.tms_cstime ) / CLOCKS_PER_SEC;
time_info.user = (double)( new_time.tms_cutime - old_time.tms_cutime ) / CLOCKS_PER_SEC;
time_info.start = cmdtab[ i ].start_dt;
time_info.end = time( 0 );
old_time = new_time;
/* Drive the completion */
/* Drive the completion. */
--cmdsrunning;
if( intr )
if ( intr )
rstat = EXEC_CMD_INTR;
else if( status != 0 )
else if ( status != 0 )
rstat = EXEC_CMD_FAIL;
else
rstat = EXEC_CMD_OK;
/* assume -p0 in effect so only pass buffer[0] containing merged output */
(*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat, &time_info, cmdtab[i].command, cmdtab[i].buffer[0] );
/* Assume -p0 in effect so only pass buffer[ 0 ]
* containing merged output.
*/
(*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat,
&time_info, cmdtab[ i ].command,
cmdtab[ i ].buffer[ 0 ] );
BJAM_FREE(cmdtab[i].buffer[OUT]);
cmdtab[i].buffer[OUT] = 0;
BJAM_FREE( cmdtab[ i ].buffer[ OUT ] );
cmdtab[ i ].buffer[ OUT ] = 0;
BJAM_FREE(cmdtab[i].buffer[ERR]);
cmdtab[i].buffer[ERR] = 0;
BJAM_FREE( cmdtab[ i ].buffer[ ERR ] );
cmdtab[ i ].buffer[ ERR ] = 0;
BJAM_FREE(cmdtab[i].command);
cmdtab[i].command = 0;
BJAM_FREE( cmdtab[ i ].command );
cmdtab[ i ].command = 0;
cmdtab[i].func = 0;
cmdtab[i].closure = 0;
cmdtab[i].start_time = 0;
cmdtab[ i ].func = 0;
cmdtab[ i ].closure = 0;
cmdtab[ i ].start_time = 0;
}
else
{
printf("unknown pid %d with errno = %d\n", pid, errno);
exit(EXITBAD);
printf( "unknown pid %d with errno = %d\n", pid, errno );
exit( EXITBAD );
}
}
}

View File

@@ -4,11 +4,11 @@
* This file is part of Jam - see jam.c for Copyright information.
*/
# include "jam.h"
# include "lists.h"
# include "execcmd.h"
#include "jam.h"
#include "lists.h"
#include "execcmd.h"
# ifdef OS_VMS
#ifdef OS_VMS
#include <stdio.h>
#include <string.h>
@@ -20,22 +20,21 @@
#include <clidef.h>
/*
* execvms.c - execute a shell script, ala VMS
* execvms.c - execute a shell script, ala VMS.
*
* The approach is this:
*
* If the command is a single line, and shorter than WRTLEN (what we
* believe to be the maximum line length), we just system() it.
* If the command is a single line, and shorter than WRTLEN (what we believe to
* be the maximum line length), we just system() it.
*
* If the command is multi-line, or longer than WRTLEN, we write the
* command block to a temp file, splitting long lines (using "-" at
* the end of the line to indicate contiuation), and then source that
* temp file. We use special logic to make sure we don't continue in
* the middle of a quoted string.
* If the command is multi-line, or longer than WRTLEN, we write the command
* block to a temp file, splitting long lines (using "-" at the end of the line
* to indicate contiuation), and then source that temp file. We use special
* logic to make sure we do not continue in the middle of a quoted string.
*
* 05/04/94 (seiwald) - async multiprocess interface; noop on VMS
* 12/20/96 (seiwald) - rewritten to handle multi-line commands well
* 01/14/96 (seiwald) - don't put -'s between "'s
* 01/14/96 (seiwald) - do not put -'s between "'s
*/
#define WRTLEN 240
@@ -44,98 +43,93 @@
/* 1 for the @ and 4 for the .com */
char tempnambuf[ L_tmpnam + 1 + 4 ] = {0};
char tempnambuf[ L_tmpnam + 1 + 4 ] = { 0 };
void
execcmd(
char *string,
void (*func)( void *closure, int status, timing_info*, char *, char * ),
void *closure,
LIST *shell,
char *rule_name,
char *target )
void exec_cmd
(
char * string,
void (* func)( void * closure, int status, timing_info *, char *, char * ),
void * closure,
LIST * shell,
char * rule_name,
char * target
)
{
char *s, *e, *p;
char * s;
char * e;
cahr * p;
int rstat = EXEC_CMD_OK;
int status;
/* See if string is more than one line */
/* discounting leading/trailing white space */
for( s = string; *s && isspace( *s ); s++ )
;
/* See if string is more than one line discounting leading/trailing white
* space.
*/
for ( s = string; *s && isspace( *s ); ++s );
e = p = strchr( s, '\n' );
while( p && isspace( *p ) )
while ( p && isspace( *p ) )
++p;
/* If multi line or long, write to com file. */
/* Otherwise, exec directly. */
if( p && *p || e - s > WRTLEN )
/* If multi line or long, write to com file. Otherwise, exec directly. */
if ( ( p && *p ) || ( e - s > WRTLEN ) )
{
FILE *f;
FILE * f;
/* Create temp file invocation "@sys$scratch:tempfile.com" */
if( !*tempnambuf )
/* Create temp file invocation "@sys$scratch:tempfile.com". */
if ( !*tempnambuf )
{
tempnambuf[0] = '@';
(void)tmpnam( tempnambuf + 1 );
strcat( tempnambuf, ".com" );
tempnambuf[0] = '@';
(void)tmpnam( tempnambuf + 1 );
strcat( tempnambuf, ".com" );
}
/* Open tempfile */
if( !( f = fopen( tempnambuf + 1, "w" ) ) )
/* Open tempfile. */
if ( !( f = fopen( tempnambuf + 1, "w" ) ) )
{
printf( "can't open command file\n" );
(*func)( closure, EXEC_CMD_FAIL );
return;
printf( "can't open command file\n" );
(*func)( closure, EXEC_CMD_FAIL );
return;
}
/* For each line of the string */
while( *string )
/* For each line of the string. */
while ( *string )
{
char *s = strchr( string, '\n' );
int len = s ? s + 1 - string : strlen( string );
char * s = strchr( string, '\n' );
int len = s ? s + 1 - string : strlen( string );
fputc( '$', f );
fputc( '$', f );
/* For each chunk of a line that needs to be split */
while( len > 0 )
{
char *q = string;
char *qe = string + MIN( len, WRTLEN );
char *qq = q;
int quote = 0;
/* Look for matching "'s */
for( ; q < qe; q++ )
if( *q == '"' && ( quote = !quote ) )
qq = q;
/* Back up to opening quote, if in one */
if( quote )
q = qq;
fwrite( string, ( q - string ), 1, f );
len -= ( q - string );
string = q;
if( len )
/* For each chunk of a line that needs to be split. */
while ( len > 0 )
{
fputc( '-', f );
fputc( '\n', f );
char * q = string;
char * qe = string + MIN( len, WRTLEN );
char * qq = q;
int quote = 0;
/* Look for matching "s. */
for ( ; q < qe; ++q )
if ( ( *q == '"' ) && ( quote = !quote ) )
qq = q;
/* Back up to opening quote, if in one. */
if ( quote )
q = qq;
fwrite( string, ( q - string ), 1, f );
len -= ( q - string );
string = q;
if ( len )
{
fputc( '-', f );
fputc( '\n', f );
}
}
}
}
fclose( f );
@@ -145,23 +139,21 @@ execcmd(
}
else
{
/* Execute single line command */
/* Strip trailing newline before execing */
if( e ) *e = 0;
/* Execute single line command. Strip trailing newline before execing.
*/
if ( e ) *e = 0;
status = system( s ) & 0x07;
}
/* Fail for error or fatal error */
/* OK on OK, warning, or info exit */
if( status == 2 || status == 4 )
/* Fail for error or fatal error. OK on OK, warning or info exit. */
if ( ( status == 2 ) || ( status == 4 ) )
rstat = EXEC_CMD_FAIL;
(*func)( closure, rstat );
}
int execwait()
int exec_wait()
{
return 0;
}

View File

@@ -28,150 +28,145 @@
*
* Internal routines:
*
* var_edit_parse() - parse : modifiers into PATHNAME structure
* var_edit_file() - copy input target name to output, modifying filename
* var_edit_shift() - do upshift/downshift mods
* var_edit_parse() - parse : modifiers into PATHNAME structure.
* var_edit_file() - copy input target name to output, modifying filename.
* var_edit_shift() - do upshift/downshift mods.
*
* 01/25/94 (seiwald) - $(X)$(UNDEF) was expanding like plain $(X)
* 04/13/94 (seiwald) - added shorthand L0 for null list pointer
* 01/11/01 (seiwald) - added support for :E=emptyvalue, :J=joinval
*/
typedef struct {
PATHNAME f; /* :GDBSMR -- pieces */
char parent; /* :P -- go to parent directory */
char filemods; /* one of the above applied */
char downshift; /* :L -- downshift result */
char upshift; /* :U -- upshift result */
char to_slashes; /* :T -- convert "\" to "/" */
char to_windows; /* :W -- convert cygwin to native paths */
PATHPART empty; /* :E -- default for empties */
PATHPART join; /* :J -- join list with char */
typedef struct
{
PATHNAME f; /* :GDBSMR -- pieces */
char parent; /* :P -- go to parent directory */
char filemods; /* one of the above applied */
char downshift; /* :L -- downshift result */
char upshift; /* :U -- upshift result */
char to_slashes; /* :T -- convert "\" to "/" */
char to_windows; /* :W -- convert cygwin to native paths */
PATHPART empty; /* :E -- default for empties */
PATHPART join; /* :J -- join list with char */
} VAR_EDITS ;
static void var_edit_parse( char *mods, VAR_EDITS *edits );
static void var_edit_file( char *in, string *out, VAR_EDITS *edits );
static void var_edit_shift( string *out, VAR_EDITS *edits );
static void var_edit_parse( char * mods, VAR_EDITS * edits );
static void var_edit_file ( char * in, string * out, VAR_EDITS * edits );
static void var_edit_shift( string * out, VAR_EDITS * edits );
#define MAGIC_COLON '\001'
#define MAGIC_LEFT '\002'
#define MAGIC_RIGHT '\003'
# define MAGIC_COLON '\001'
# define MAGIC_LEFT '\002'
# define MAGIC_RIGHT '\003'
/*
* var_expand() - variable-expand input string into list of strings
* var_expand() - variable-expand input string into list of strings.
*
* Would just copy input to output, performing variable expansion,
* except that since variables can contain multiple values the result
* of variable expansion may contain multiple values (a list). Properly
* performs "product" operations that occur in "$(var1)xxx$(var2)" or
* even "$($(var2))".
* Would just copy input to output, performing variable expansion, except that
* since variables can contain multiple values the result of variable expansion
* may contain multiple values (a list). Properly performs "product" operations
* that occur in "$(var1)xxx$(var2)" or even "$($(var2))".
*
* Returns a newly created list.
*/
LIST *
var_expand(
LIST *l,
char *in,
char *end,
LOL *lol,
int cancopyin )
LIST * var_expand( LIST * l, char * in, char * end, LOL * lol, int cancopyin )
{
char out_buf[ MAXSYM ];
string buf[1];
string out1[1]; /* Temporary buffer */
string buf[ 1 ];
string out1[ 1 ]; /* temporary buffer */
size_t prefix_length;
char *out;
char *inp = in;
char *ov; /* for temp copy of variable in outbuf */
char * out;
char * inp = in;
char * ov; /* for temp copy of variable in outbuf */
int depth;
if( DEBUG_VAREXP )
if ( DEBUG_VAREXP )
printf( "expand '%.*s'\n", end - in, in );
/* This gets alot of cases: $(<) and $(>) */
if( in[0] == '$' && in[1] == '(' && in[3] == ')' && in[4] == '\0' )
/* This gets a lot of cases: $(<) and $(>). */
if
(
( in[ 0 ] == '$' ) &&
( in[ 1 ] == '(' ) &&
( in[ 3 ] == ')' ) &&
( in[ 4 ] == '\0' )
)
{
switch( in[2] )
switch ( in[ 2 ] )
{
case '<':
return list_copy( l, lol_get( lol, 0 ) );
case '<': return list_copy( l, lol_get( lol, 0 ) );
case '>': return list_copy( l, lol_get( lol, 1 ) );
case '>':
return list_copy( l, lol_get( lol, 1 ) );
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return list_copy( l, lol_get( lol, in[2]-'1' ) );
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return list_copy( l, lol_get( lol, in[ 2 ] - '1' ) );
}
}
/* Expand @() files, to single item plus accompanying file. */
if ( in[0] == '@' && in[1] == '(' && *(end-1) == ')' )
if ( ( in[ 0 ] == '@' ) && ( in[ 1 ] == '(' ) && ( *( end - 1 ) == ')' ) )
{
/* We try the expansion until it fits within the propspective output buffer. */
/* We try the expansion until it fits within the propective output
* buffer.
*/
char * at_buf = 0;
int at_size = MAXJPATH;
int at_len = 0;
do
{
BJAM_FREE(at_buf);
at_buf = (char*)BJAM_MALLOC_ATOMIC(at_size + 1);
BJAM_FREE( at_buf );
at_buf = (char *)BJAM_MALLOC_ATOMIC( at_size + 1 );
at_len = var_string( in, at_buf, at_size, lol );
at_size *= 2;
} while ( at_len < 0 && at_size < INT_MAX / 2 );
}
while ( ( at_len < 0 ) && ( at_size < INT_MAX / 2 ) );
/* Return the result as a single item list. */
if ( at_len > 0 )
{
LIST * r;
string_copy( buf, at_buf );
r = list_new( l, newstr( buf->value) );
r = list_new( l, newstr( buf->value ) );
string_free( buf );
BJAM_FREE(at_buf);
BJAM_FREE( at_buf );
return r;
}
BJAM_FREE(at_buf);
BJAM_FREE( at_buf );
}
/* Just try simple copy of in to out. */
while ( in < end )
if ( *in++ == '$' && *in == '(' )
if ( ( *in++ == '$' ) && ( *in == '(' ) )
goto expand;
/* No variables expanded - just add copy of input string to list. */
/* Cancopyin is an optimization: if the input was already a list */
/* item, we can use the copystr() to put it on the new list. */
/* Otherwise, we use the slower newstr(). */
if( cancopyin )
{
/* 'cancopyin' is an optimization: if the input was already a list item, we
* can use copystr() to put it on the new list. Otherwise, we use the slower
* newstr().
*/
if ( cancopyin )
return list_new( l, copystr( inp ) );
}
else
{
LIST* r;
LIST * r;
string_new( buf );
string_append_range( buf, inp, end );
r = list_new( l, newstr( buf->value) );
r = list_new( l, newstr( buf->value ) );
string_free( buf );
return r;
}
expand:
string_new( buf );
string_append_range( buf, inp, in - 1); /* copy the part before '$'. */
string_append_range( buf, inp, in - 1 ); /* Copy the part before '$'. */
/*
* Input so far (ignore blanks):
*
@@ -185,23 +180,22 @@ expand:
* out_buf out
*
*
* We just copied the $ of $(...), so back up one on the output.
* We now find the matching close paren, copying the variable and
* modifiers between the $( and ) temporarily into out_buf, so that
* we can replace :'s with MAGIC_COLON. This is necessary to avoid
* being confused by modifier values that are variables containing
* :'s. Ugly.
* We just copied the $ of $(...), so back up one on the output. We now find
* the matching close paren, copying the variable and modifiers between the
* $( and ) temporarily into out_buf, so that we can replace :'s with
* MAGIC_COLON. This is necessary to avoid being confused by modifier values
* that are variables containing :'s. Ugly.
*/
depth = 1;
inp = ++in; /* skip over the '(' */
inp = ++in; /* Skip over the '('. */
while( in < end && depth )
while ( ( in < end ) && depth )
{
switch( *in++ )
switch ( *in++ )
{
case '(': depth++; break;
case ')': depth--; break;
case '(': ++depth; break;
case ')': --depth; break;
}
}
@@ -218,11 +212,11 @@ expand:
out = buf->value + prefix_length;
for ( ov = out; ov < buf->value + buf->size; ++ov )
{
switch( *ov )
switch ( *ov )
{
case ':': *ov = MAGIC_COLON; break;
case '[': *ov = MAGIC_LEFT; break;
case ']': *ov = MAGIC_RIGHT; break;
case ':': *ov = MAGIC_COLON; break;
case '[': *ov = MAGIC_LEFT ; break;
case ']': *ov = MAGIC_RIGHT; break;
}
}
@@ -238,79 +232,72 @@ expand:
* ^ ^ ^
* out_buf out ov
*
* Later we will overwrite 'variable' in out_buf, but we'll be
* done with it by then. 'variable' may be a multi-element list,
* so may each value for '$(variable element)', and so may 'remainder'.
* Thus we produce a product of three lists.
* Later we will overwrite 'variable' in out_buf, but we will be done with
* it by then. 'variable' may be a multi-element list, so may each value for
* '$(variable element)', and so may 'remainder'. Thus we produce a product
* of three lists.
*/
{
LIST *variables = 0;
LIST *remainder = 0;
LIST *vars;
LIST * variables = 0;
LIST * remainder = 0;
LIST * vars;
/* Recursively expand variable name & rest of input */
/* Recursively expand variable name & rest of input. */
if ( out < ov ) variables = var_expand( L0, out, ov, lol, 0 );
if ( in < end ) remainder = var_expand( L0, in, end, lol, 0 );
if( out < ov )
variables = var_expand( L0, out, ov, lol, 0 );
if( in < end )
remainder = var_expand( L0, in, end, lol, 0 );
/* Now produce the result chain. */
/* Now produce the result chain */
/* For each variable name */
for( vars = variables; vars; vars = list_next( vars ) )
/* For each variable name. */
for ( vars = variables; vars; vars = list_next( vars ) )
{
LIST *value, *evalue = 0;
char *colon;
char *bracket;
LIST * value = 0;
LIST * evalue = 0;
char * colon;
char * bracket;
string variable[1];
char *varname;
int sub1 = 0, sub2 = -1;
char * varname;
int sub1 = 0;
int sub2 = -1;
VAR_EDITS edits;
/* Look for a : modifier in the variable name */
/* Must copy into varname so we can modify it */
/* Look for a : modifier in the variable name. Must copy into
* varname so we can modify it.
*/
string_copy( variable, vars->string );
varname = variable->value;
if( colon = strchr( varname, MAGIC_COLON ) )
if ( colon = strchr( varname, MAGIC_COLON ) )
{
string_truncate( variable, colon - varname );
var_edit_parse( colon + 1, &edits );
}
/* Look for [x-y] subscripting */
/* sub1 and sub2 are x and y. */
/* Look for [x-y] subscripting. sub1 and sub2 are x and y. */
if ( bracket = strchr( varname, MAGIC_LEFT ) )
{
/*
** Make all syntax errors in [] subscripting
** result in the same behavior: silenty return an empty
** expansion (by setting sub2 = 0). Brute force parsing;
** May get moved into yacc someday.
*/
/* Make all syntax errors in [] subscripting result in the same
* behavior: silenty return an empty expansion (by setting sub2
* = 0). Brute force parsing; May get moved into yacc someday.
*/
char *s = bracket + 1;
char * s = bracket + 1;
string_truncate( variable, bracket - varname );
do /* so we can use "break" */
{
/* Allow negative indexes. */
if (! isdigit( *s ) && ! ( *s == '-') )
if ( !isdigit( *s ) && ( *s != '-' ) )
{
sub2 = 0;
break;
}
sub1 = atoi(s);
sub1 = atoi( s );
/* Skip over the first symbol, which is either a digit or dash. */
s++;
while ( isdigit( *s ) ) s++;
++s;
while ( isdigit( *s ) ) ++s;
if ( *s == MAGIC_RIGHT )
{
@@ -318,13 +305,13 @@ expand:
break;
}
if ( *s != '-')
if ( *s != '-' )
{
sub2 = 0;
break;
}
s++;
++s;
if ( *s == MAGIC_RIGHT )
{
@@ -332,119 +319,114 @@ expand:
break;
}
if (! isdigit( *s ) && ! ( *s == '-') )
if ( !isdigit( *s ) && ( *s != '-' ) )
{
sub2 = 0;
break;
}
/* First, compute the index of the last element. */
sub2 = atoi(s);
s++;
while ( isdigit( *s ) ) s++;
sub2 = atoi( s );
while ( isdigit( *++s ) );
if ( *s != MAGIC_RIGHT)
if ( *s != MAGIC_RIGHT )
sub2 = 0;
} while (0);
} while ( 0 );
/*
** Anything but the end of the string, or the colon
** introducing a modifier is a syntax error.
*/
s++;
if (*s && *s != MAGIC_COLON)
/* Anything but the end of the string, or the colon introducing
* a modifier is a syntax error.
*/
++s;
if ( *s && ( *s != MAGIC_COLON ) )
sub2 = 0;
*bracket = '\0';
}
/* Get variable value, specially handling $(<), $(>), $(n) */
/* Get variable value, with special handling for $(<), $(>), $(n).
*/
if ( !varname[1] )
{
if ( varname[0] == '<' )
value = lol_get( lol, 0 );
else if ( varname[0] == '>' )
value = lol_get( lol, 1 );
else if ( ( varname[0] >= '1' ) && ( varname[0] <= '9' ) )
value = lol_get( lol, varname[0] - '1' );
}
if( varname[0] == '<' && !varname[1] )
value = lol_get( lol, 0 );
else if( varname[0] == '>' && !varname[1] )
value = lol_get( lol, 1 );
else if( varname[0] >= '1' && varname[0] <= '9' && !varname[1] )
value = lol_get( lol, varname[0] - '1' );
else
if ( !value )
value = var_get( varname );
/* Handle negitive indexes: part two. */
{
int length = list_length( value );
if (sub1 < 0)
if ( sub1 < 0 )
sub1 = length + sub1;
else
sub1 -= 1;
if (sub2 < 0)
if ( sub2 < 0 )
sub2 = length + 1 + sub2 - sub1;
else
sub2 -= sub1;
/*
** The "sub2 < 0" test handles the semantic error
** of sub2 < sub1.
*/
/* The "sub2 < 0" test handles the semantic error of sub2 <
* sub1.
*/
if ( sub2 < 0 )
sub2 = 0;
}
/* The fast path: $(x) - just copy the variable value. */
/* This is only an optimization */
if( out == out_buf && !bracket && !colon && in == end )
/* The fast path: $(x) - just copy the variable value. This is only
* an optimization.
*/
if ( ( out == out_buf ) && !bracket && !colon && ( in == end ) )
{
string_free( variable );
l = list_copy( l, value );
continue;
}
/* Handle start subscript */
while( sub1 > 0 && value )
/* Handle start subscript. */
while ( ( sub1 > 0 ) && value )
--sub1, value = list_next( value );
/* Empty w/ :E=default? */
if( !value && colon && edits.empty.ptr )
/* Empty w/ :E=default?. */
if ( !value && colon && edits.empty.ptr )
evalue = value = list_new( L0, newstr( edits.empty.ptr ) );
/* For each variable value */
/* For each variable value. */
string_new( out1 );
for( ; value; value = list_next( value ) )
for ( ; value; value = list_next( value ) )
{
LIST *rem;
LIST * rem;
size_t postfix_start;
/* Handle end subscript (length actually) */
/* Handle end subscript (length actually). */
if( sub2 >= 0 && --sub2 < 0 )
if ( sub2 >= 0 && --sub2 < 0 )
break;
string_truncate( buf, prefix_length );
/* Apply : mods, if present */
if( colon && edits.filemods )
if ( colon && edits.filemods )
var_edit_file( value->string, out1, &edits );
else
string_append( out1, value->string );
if( colon && ( edits.upshift || edits.downshift || edits.to_slashes || edits.to_windows ) )
if ( colon && ( edits.upshift || edits.downshift || edits.to_slashes || edits.to_windows ) )
var_edit_shift( out1, &edits );
/* Handle :J=joinval */
/* If we have more values for this var, just */
/* keep appending them (with the join value) */
/* rather than creating separate LIST elements. */
if( colon && edits.join.ptr &&
/* If we have more values for this var, just keep appending them
* (using the join value) rather than creating separate LIST
* elements.
*/
if ( colon && edits.join.ptr &&
( list_next( value ) || list_next( vars ) ) )
{
string_append( out1, edits.join.ptr );
@@ -456,21 +438,18 @@ expand:
string_new( out1 );
/* If no remainder, append result to output chain. */
if( in == end )
if ( in == end )
{
l = list_new( l, newstr( buf->value ) );
continue;
}
/* For each remainder, append the complete string */
/* to the output chain. */
/* Remember the end of the variable expansion so */
/* we can just tack on each instance of 'remainder' */
/* For each remainder, append the complete string to the output
* chain. Remember the end of the variable expansion so we can
* just tack on each instance of 'remainder'.
*/
postfix_start = buf->size;
for( rem = remainder; rem; rem = list_next( rem ) )
for ( rem = remainder; rem; rem = list_next( rem ) )
{
string_truncate( buf, postfix_start );
string_append( buf, rem->string );
@@ -479,23 +458,18 @@ expand:
}
string_free( out1 );
/* Toss used empty */
if( evalue )
/* Toss used empty. */
if ( evalue )
list_free( evalue );
string_free( variable );
}
/* variables & remainder were gifts from var_expand */
/* and must be freed */
/* variables & remainder were gifts from var_expand and must be freed. */
if ( variables ) list_free( variables );
if ( remainder ) list_free( remainder );
if( variables )
list_free( variables );
if( remainder)
list_free( remainder );
if( DEBUG_VAREXP )
if ( DEBUG_VAREXP )
{
printf( "expanded to " );
list_print( l );
@@ -507,16 +481,17 @@ expand:
}
}
/*
* var_edit_parse() - parse : modifiers into PATHNAME structure
*
* The : modifiers in a $(varname:modifier) currently support replacing
* or omitting elements of a filename, and so they are parsed into a
* PATHNAME structure (which contains pointers into the original string).
* The : modifiers in a $(varname:modifier) currently support replacing or
* omitting elements of a filename, and so they are parsed into a PATHNAME
* structure (which contains pointers into the original string).
*
* Modifiers of the form "X=value" replace the component X with
* the given value. Modifiers without the "=value" cause everything
* but the component X to be omitted. X is one of:
* Modifiers of the form "X=value" replace the component X with the given value.
* Modifiers without the "=value" cause everything but the component X to be
* omitted. X is one of:
*
* G <grist>
* D directory name
@@ -542,166 +517,133 @@ expand:
* var_edit_file() below and path_build() obligingly follow this convention.
*/
static void
var_edit_parse(
char *mods,
VAR_EDITS *edits )
static void var_edit_parse( char * mods, VAR_EDITS * edits )
{
int havezeroed = 0;
memset( (char *)edits, 0, sizeof( *edits ) );
while( *mods )
while ( *mods )
{
char *p;
PATHPART *fp;
char * p;
PATHPART * fp;
switch( *mods++ )
switch ( *mods++ )
{
case 'L': edits->downshift = 1; continue;
case 'U': edits->upshift = 1; continue;
case 'P': edits->parent = edits->filemods = 1; continue;
case 'E': fp = &edits->empty; goto strval;
case 'J': fp = &edits->join; goto strval;
case 'G': fp = &edits->f.f_grist; goto fileval;
case 'R': fp = &edits->f.f_root; goto fileval;
case 'D': fp = &edits->f.f_dir; goto fileval;
case 'B': fp = &edits->f.f_base; goto fileval;
case 'S': fp = &edits->f.f_suffix; goto fileval;
case 'M': fp = &edits->f.f_member; goto fileval;
case 'L': edits->downshift = 1; continue;
case 'U': edits->upshift = 1; continue;
case 'P': edits->parent = edits->filemods = 1; continue;
case 'E': fp = &edits->empty; goto strval;
case 'J': fp = &edits->join; goto strval;
case 'G': fp = &edits->f.f_grist; goto fileval;
case 'R': fp = &edits->f.f_root; goto fileval;
case 'D': fp = &edits->f.f_dir; goto fileval;
case 'B': fp = &edits->f.f_base; goto fileval;
case 'S': fp = &edits->f.f_suffix; goto fileval;
case 'M': fp = &edits->f.f_member; goto fileval;
case 'T': edits->to_slashes = 1; continue;
case 'W': edits->to_windows = 1; continue;
default: return; /* should complain, but so what... */
default:
return; /* Should complain, but so what... */
}
fileval:
/* Handle :CHARS, where each char (without a following =) */
/* selects a particular file path element. On the first such */
/* char, we deselect all others (by setting ptr = "", len = 0) */
/* and for each char we select that element (by setting ptr = 0) */
/* Handle :CHARS, where each char (without a following =) selects a
* particular file path element. On the first such char, we deselect all
* others (by setting ptr = "", len = 0) and for each char we select
* that element (by setting ptr = 0).
*/
edits->filemods = 1;
if( *mods != '=' )
if ( *mods != '=' )
{
int i;
if ( !havezeroed++ )
{
int i;
for ( i = 0; i < 6; ++i )
{
edits->f.part[ i ].len = 0;
edits->f.part[ i ].ptr = "";
}
}
if( !havezeroed++ )
for( i = 0; i < 6; i++ )
{
edits->f.part[ i ].len = 0;
edits->f.part[ i ].ptr = "";
}
fp->ptr = 0;
continue;
fp->ptr = 0;
continue;
}
strval:
/* Handle :X=value, or :X */
if( *mods != '=' )
if ( *mods != '=' )
{
fp->ptr = "";
fp->len = 0;
fp->ptr = "";
fp->len = 0;
}
else if( p = strchr( mods, MAGIC_COLON ) )
else if ( p = strchr( mods, MAGIC_COLON ) )
{
*p = 0;
fp->ptr = ++mods;
fp->len = p - mods;
mods = p + 1;
*p = 0;
fp->ptr = ++mods;
fp->len = p - mods;
mods = p + 1;
}
else
{
fp->ptr = ++mods;
fp->len = strlen( mods );
mods += fp->len;
fp->ptr = ++mods;
fp->len = strlen( mods );
mods += fp->len;
}
}
}
/*
* var_edit_file() - copy input target name to output, modifying filename
* var_edit_file() - copy input target name to output, modifying filename.
*/
static void
var_edit_file(
char *in,
string *out,
VAR_EDITS *edits )
static void var_edit_file( char * in, string * out, VAR_EDITS * edits )
{
PATHNAME pathname;
/* Parse apart original filename, putting parts into "pathname" */
/* Parse apart original filename, putting parts into "pathname". */
path_parse( in, &pathname );
/* Replace any pathname with edits->f */
if ( edits->f.f_grist .ptr ) pathname.f_grist = edits->f.f_grist;
if ( edits->f.f_root .ptr ) pathname.f_root = edits->f.f_root;
if ( edits->f.f_dir .ptr ) pathname.f_dir = edits->f.f_dir;
if ( edits->f.f_base .ptr ) pathname.f_base = edits->f.f_base;
if ( edits->f.f_suffix.ptr ) pathname.f_suffix = edits->f.f_suffix;
if ( edits->f.f_member.ptr ) pathname.f_member = edits->f.f_member;
if( edits->f.f_grist.ptr )
pathname.f_grist = edits->f.f_grist;
if( edits->f.f_root.ptr )
pathname.f_root = edits->f.f_root;
if( edits->f.f_dir.ptr )
pathname.f_dir = edits->f.f_dir;
if( edits->f.f_base.ptr )
pathname.f_base = edits->f.f_base;
if( edits->f.f_suffix.ptr )
pathname.f_suffix = edits->f.f_suffix;
if( edits->f.f_member.ptr )
pathname.f_member = edits->f.f_member;
/* If requested, modify pathname to point to parent */
if( edits->parent )
/* If requested, modify pathname to point to parent. */
if ( edits->parent )
path_parent( &pathname );
/* Put filename back together */
/* Put filename back together. */
path_build( &pathname, out, 0 );
}
/*
* var_edit_shift() - do upshift/downshift mods
* var_edit_shift() - do upshift/downshift mods.
*/
static void
var_edit_shift(
string *out,
VAR_EDITS *edits )
static void var_edit_shift( string * out, VAR_EDITS * edits )
{
/* Handle upshifting, downshifting and slash translation now */
char *p;
/* Handle upshifting, downshifting and slash translation now. */
char * p;
for ( p = out->value; *p; ++p)
{
if (edits->upshift)
{
if ( edits->upshift )
*p = toupper( *p );
}
else if ( edits->downshift )
{
*p = tolower( *p );
}
if ( edits->to_slashes )
{
if ( *p == '\\')
*p = '/';
}
if ( edits->to_slashes && ( *p == '\\' ) )
*p = '/';
# ifdef OS_CYGWIN
if ( edits->to_windows )
{
char result[MAX_PATH + 1];
cygwin_conv_to_win32_path(out->value, result);
assert(strlen(result) <= MAX_PATH);
char result[ MAX_PATH + 1 ];
cygwin_conv_to_win32_path( out->value, result );
assert( strlen( result ) <= MAX_PATH );
string_free( out );
string_copy( out, result );
}
@@ -710,64 +652,61 @@ var_edit_shift(
out->size = p - out->value;
}
#ifndef NDEBUG
void var_expand_unit_test()
{
LOL lol[1];
LIST* l, *l2;
LIST *expected = list_new( list_new( L0, newstr( "axb" ) ), newstr( "ayb" ) );
LIST *e2;
LOL lol[ 1 ];
LIST * l;
LIST * l2;
LIST * expected = list_new( list_new( L0, newstr( "axb" ) ), newstr( "ayb" ) );
LIST * e2;
char axyb[] = "a$(xy)b";
char azb[] = "a$($(z))b";
char path[] = "$(p:W)";
# ifdef OS_CYGWIN
char cygpath[256];
cygwin_conv_to_posix_path("c:\\foo\\bar", cygpath);
# else
# ifdef OS_CYGWIN
char cygpath[ 256 ];
cygwin_conv_to_posix_path( "c:\\foo\\bar", cygpath );
# else
char cygpath[] = "/cygdrive/c/foo/bar";
# endif
# endif
lol_init(lol);
var_set("xy", list_new( list_new( L0, newstr( "x" ) ), newstr( "y" ) ), VAR_SET );
var_set("z", list_new( L0, newstr( "xy" ) ), VAR_SET );
var_set("p", list_new( L0, newstr( cygpath ) ), VAR_SET );
var_set( "xy", list_new( list_new( L0, newstr( "x" ) ), newstr( "y" ) ), VAR_SET );
var_set( "z", list_new( L0, newstr( "xy" ) ), VAR_SET );
var_set( "p", list_new( L0, newstr( cygpath ) ), VAR_SET );
l = var_expand( 0, axyb, axyb + sizeof(axyb) - 1, lol, 0 );
for ( l2 = l, e2 = expected; l2 && e2; l2 = list_next(l2), e2 = list_next(e2) )
l = var_expand( 0, axyb, axyb + sizeof( axyb ) - 1, lol, 0 );
for ( l2 = l, e2 = expected; l2 && e2; l2 = list_next( l2 ), e2 = list_next( e2 ) )
assert( !strcmp( e2->string, l2->string ) );
assert(l2 == 0 && e2 == 0);
list_free(l);
assert( l2 == 0 );
assert( e2 == 0 );
list_free( l );
l = var_expand( 0, azb, azb + sizeof(azb) - 1, lol, 0 );
for ( l2 = l, e2 = expected; l2 && e2; l2 = list_next(l2), e2 = list_next(e2) )
l = var_expand( 0, azb, azb + sizeof( azb ) - 1, lol, 0 );
for ( l2 = l, e2 = expected; l2 && e2; l2 = list_next( l2 ), e2 = list_next( e2 ) )
assert( !strcmp( e2->string, l2->string ) );
assert(l2 == 0 && e2 == 0);
list_free(l);
assert( l2 == 0 );
assert( e2 == 0 );
list_free( l );
l = var_expand( 0, path, path + sizeof(path) - 1, lol, 0 );
assert(l != 0);
assert(list_next(l) == 0);
# ifdef OS_CYGWIN
/* On some installations of cygwin the drive letter is expanded to other case. */
/* This has been reported to be the case if cygwin has been installed to C:\ */
/* as opposed to C:\cygwin */
/* Since case of the drive letter will not matter, we allow for both. */
assert( 0 == strcmp( l->string, "c:\\foo\\bar" )
|| 0 == strcmp( l->string, "C:\\foo\\bar") );
# else
l = var_expand( 0, path, path + sizeof( path ) - 1, lol, 0 );
assert( l != 0 );
assert( list_next( l ) == 0 );
# ifdef OS_CYGWIN
/* On some installations of cygwin the drive letter is expanded to other
* case. This has been reported to be the case if cygwin has been installed
* to C:\ as opposed to C:\cygwin. Since case of the drive letter will not
* matter, we allow for both.
*/
assert( !strcmp( l->string, "c:\\foo\\bar" ) ||
!strcmp( l->string, "C:\\foo\\bar" ) );
# else
assert( !strcmp( l->string, cygpath ) );
# endif
list_free(l);
list_free(expected);
lol_free(lol);
# endif
list_free( l );
list_free( expected );
lol_free( lol );
}
#endif
/*
Local Variables:
tab-width: 8
End:
*/

View File

@@ -43,26 +43,23 @@
* 11/21/96 (peterk) - BEOS does not have Unix-style archives
*/
void CopyC2PStr(const char * cstr, StringPtr pstr)
void CopyC2PStr( char const * cstr, StringPtr pstr )
{
int len;
for ( len = 0; *cstr && len < 255; pstr[++len] = *cstr++ );
pstr[0] = len;
for ( len = 0; *cstr && ( len < 255 ); pstr[ ++len ] = *cstr++ );
pstr[ 0 ] = len;
}
/*
* file_dirscan() - scan a directory for files
* file_dirscan() - scan a directory for files.
*/
void
file_dirscan(
char *dir,
scanback func,
void *closure )
void file_dirscan( char * dir, scanback func, void * closure )
{
PATHNAME f;
string filename[1];
string filename[ 1 ];
unsigned char fullPath[ 512 ];
FSSpec spec;
@@ -71,58 +68,57 @@ file_dirscan(
CInfoPBRec lastInfo;
int index = 1;
/* First enter directory itself */
/* First enter directory itself. */
memset( (char *)&f, '\0', sizeof( f ) );
f.f_dir.ptr = dir;
f.f_dir.len = strlen(dir);
if( DEBUG_BINDSCAN )
if ( DEBUG_BINDSCAN )
printf( "scan directory %s\n", dir );
/* Special case ":" - enter it */
if( f.f_dir.len == 1 && f.f_dir.ptr[0] == ':' )
if ( ( f.f_dir.len == 1 ) && ( f.f_dir.ptr[0] == ':' ) )
(*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
/* Now enter contents of directory */
vol.ioNamePtr = volName;
if( PBHGetVolSync( &vol ) )
if ( PBHGetVolSync( &vol ) )
return;
CopyC2PStr( dir, fullPath );
if( FSMakeFSSpec( vol.ioWDVRefNum, vol.ioWDDirID, fullPath, &spec ) )
if ( FSMakeFSSpec( vol.ioWDVRefNum, vol.ioWDDirID, fullPath, &spec ) )
return;
lastInfo.dirInfo.ioVRefNum = spec.vRefNum;
lastInfo.dirInfo.ioDrDirID = spec.parID;
lastInfo.dirInfo.ioNamePtr = spec.name;
lastInfo.dirInfo.ioFDirIndex = 0;
lastInfo.dirInfo.ioACUser = 0;
lastInfo.dirInfo.ioVRefNum = spec.vRefNum;
lastInfo.dirInfo.ioDrDirID = spec.parID;
lastInfo.dirInfo.ioNamePtr = spec.name;
lastInfo.dirInfo.ioFDirIndex = 0;
lastInfo.dirInfo.ioACUser = 0;
if( PBGetCatInfoSync(&lastInfo) )
if ( PBGetCatInfoSync( &lastInfo ) )
return;
if (!(lastInfo.dirInfo.ioFlAttrib & 0x10))
if ( !( lastInfo.dirInfo.ioFlAttrib & 0x10 ) )
return;
// ioDrDirID must be reset each time.
/* ioDrDirID must be reset each time. */
spec.parID = lastInfo.dirInfo.ioDrDirID;
string_new( filename );
for( ;; )
for ( ; ; )
{
lastInfo.dirInfo.ioVRefNum = spec.vRefNum;
lastInfo.dirInfo.ioDrDirID = spec.parID;
lastInfo.dirInfo.ioNamePtr = fullPath;
lastInfo.dirInfo.ioFDirIndex = index++;
if( PBGetCatInfoSync(&lastInfo) )
if ( PBGetCatInfoSync( &lastInfo ) )
return;
f.f_base.ptr = (char *)fullPath + 1;
@@ -135,18 +131,16 @@ file_dirscan(
string_free( filename );
}
/*
* file_time() - get timestamp of file, if not done by file_dirscan()
* file_time() - get timestamp of file, if not done by file_dirscan().
*/
int
file_time(
char *filename,
time_t *time )
int file_time( char * filename, time_t * time )
{
struct stat statbuf;
if( stat( filename, &statbuf ) < 0 )
if ( stat( filename, &statbuf ) < 0 )
return -1;
*time = statbuf.st_mtime;
@@ -155,32 +149,22 @@ file_time(
}
int file_is_file(char* filename)
int file_is_file( char * filename )
{
struct stat statbuf;
if( stat( filename, &statbuf ) < 0 )
if ( stat( filename, &statbuf ) < 0 )
return -1;
if ( S_ISREG( statbuf.st_mode ) )
return 1;
else
return 0;
return S_ISREG( statbuf.st_mode ) ? 1 : 0;
}
/*
* file_archscan() - scan an archive for files
* file_archscan() - scan an archive for files.
*/
void
file_archscan(
char *archive,
scanback func,
void *closure )
void file_archscan( char * archive, scanback func, void * closure )
{
}
# endif /* macintosh */

View File

@@ -56,13 +56,9 @@
* file_dirscan() - scan a directory for files
*/
void
file_dirscan(
char *dir,
scanback func,
void *closure )
void file_dirscan( char * dir, scanback func, void * closure )
{
PROFILE_ENTER(FILE_DIRSCAN);
PROFILE_ENTER( FILE_DIRSCAN );
file_info_t * d = 0;
@@ -72,21 +68,21 @@ file_dirscan(
d = file_query( dir );
if ( ! d || ! d->is_dir )
if ( !d || !d->is_dir )
{
PROFILE_EXIT(FILE_DIRSCAN);
PROFILE_EXIT( FILE_DIRSCAN );
return;
}
if ( ! d->files )
if ( !d->files )
{
PATHNAME f;
string filespec[1];
string filename[1];
string filespec[ 1 ];
string filename[ 1 ];
long handle;
int ret;
struct _finddata_t finfo[1];
LIST* files = L0;
struct _finddata_t finfo[ 1 ];
LIST * files = L0;
int d_length = strlen( d->name );
memset( (char *)&f, '\0', sizeof( f ) );
@@ -116,16 +112,16 @@ file_dirscan(
if ( DEBUG_BINDSCAN )
printf( "scan directory %s\n", dir );
# if defined(__BORLANDC__) && __BORLANDC__ < 0x550
#if defined(__BORLANDC__) && __BORLANDC__ < 0x550
if ( ret = findfirst( filespec->value, finfo, FA_NORMAL | FA_DIREC ) )
{
string_free( filespec );
PROFILE_EXIT(FILE_DIRSCAN);
PROFILE_EXIT( FILE_DIRSCAN );
return;
}
string_new( filename );
while( !ret )
string_new ( filename );
while ( !ret )
{
file_info_t * ff = 0;
@@ -147,15 +143,15 @@ file_dirscan(
# else
handle = _findfirst( filespec->value, finfo );
if( ret = ( handle < 0L ) )
if ( ret = ( handle < 0L ) )
{
string_free( filespec );
PROFILE_EXIT(FILE_DIRSCAN);
PROFILE_EXIT( FILE_DIRSCAN );
return;
}
string_new( filename );
while( !ret )
while ( !ret )
{
file_info_t * ff = 0;
@@ -165,7 +161,7 @@ file_dirscan(
string_truncate( filename, 0 );
path_build( &f, filename, 0 );
files = list_new( files, newstr(filename->value) );
files = list_new( files, newstr( filename->value ) );
ff = file_info( filename->value );
ff->is_file = finfo->attrib & _A_SUBDIR ? 0 : 1;
ff->is_dir = finfo->attrib & _A_SUBDIR ? 1 : 0;
@@ -186,9 +182,9 @@ file_dirscan(
/* Special case \ or d:\ : enter it */
{
unsigned long len = strlen(d->name);
if( len == 1 && d->name[0] == '\\' )
if ( len == 1 && d->name[0] == '\\' )
(*func)( closure, d->name, 1 /* stat()'ed */, d->time );
else if( len == 3 && d->name[1] == ':' )
else if ( len == 3 && d->name[1] == ':' )
(*func)( closure, d->name, 1 /* stat()'ed */, d->time );
}
@@ -204,7 +200,7 @@ file_dirscan(
}
}
PROFILE_EXIT(FILE_DIRSCAN);
PROFILE_EXIT( FILE_DIRSCAN );
}
file_info_t * file_query( char * filename )
@@ -214,7 +210,7 @@ file_info_t * file_query( char * filename )
{
struct stat statbuf;
if( stat( *filename ? filename : ".", &statbuf ) < 0 )
if ( stat( *filename ? filename : ".", &statbuf ) < 0 )
return 0;
ff->is_file = statbuf.st_mode & S_IFREG ? 1 : 0;
@@ -284,10 +280,10 @@ file_archscan(
long offset;
int fd;
if( ( fd = open( archive, O_RDONLY | O_BINARY, 0 ) ) < 0 )
if ( ( fd = open( archive, O_RDONLY | O_BINARY, 0 ) ) < 0 )
return;
if( read( fd, buf, SARMAG ) != SARMAG ||
if ( read( fd, buf, SARMAG ) != SARMAG ||
strncmp( ARMAG, buf, SARMAG ) )
{
close( fd );
@@ -296,10 +292,10 @@ file_archscan(
offset = SARMAG;
if( DEBUG_BINDSCAN )
if ( DEBUG_BINDSCAN )
printf( "scan archive %s\n", archive );
while( read( fd, &ar_hdr, SARHDR ) == SARHDR &&
while ( ( read( fd, &ar_hdr, SARHDR ) == SARHDR ) &&
!memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG ) )
{
long lar_date;
@@ -329,33 +325,33 @@ file_archscan(
}
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 offset of the string in the string table represented
** in ASCII decimals.
*/
name = string_table + atoi( ar_hdr.ar_name + 1 );
for ( endname = name; *endname && *endname != '\n'; ++endname) {}
name = string_table + atoi( ar_hdr.ar_name + 1 );
for ( endname = name; *endname && *endname != '\n'; ++endname) {}
}
else
{
/* normal name */
name = ar_hdr.ar_name;
endname = name + sizeof( ar_hdr.ar_name );
/* normal name */
name = ar_hdr.ar_name;
endname = name + sizeof( ar_hdr.ar_name );
}
/* strip trailing white-space, slashes, and backslashes */
while( endname-- > name )
if( !isspace(*endname) && *endname != '\\' && *endname != '/' )
break;
while ( endname-- > name )
if ( !isspace(*endname) && ( *endname != '\\' ) && ( *endname != '/' ) )
break;
*++endname = 0;
/* strip leading directory names, an NT specialty */
if( c = strrchr( name, '/' ) )
if ( c = strrchr( name, '/' ) )
name = c + 1;
if( c = strrchr( name, '\\' ) )
if ( c = strrchr( name, '\\' ) )
name = c + 1;
sprintf( buf, "%s(%.*s)", archive, endname - name, name );

View File

@@ -68,9 +68,9 @@ file_dirscan(
/* Special case \ or d:\ : enter it */
string_copy( filespec, dir );
if( f.f_dir.len == 1 && f.f_dir.ptr[0] == '\\' )
if ( f.f_dir.len == 1 && f.f_dir.ptr[0] == '\\' )
(*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
else if( f.f_dir.len == 3 && f.f_dir.ptr[1] == ':' )
else if ( f.f_dir.len == 3 && f.f_dir.ptr[1] == ':' )
(*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
else
string_push_back( filespec, '/' );
@@ -79,14 +79,14 @@ file_dirscan(
/* Now enter contents of directory */
if( DEBUG_BINDSCAN )
if ( DEBUG_BINDSCAN )
printf( "scan directory %s\n", filespec->value );
/* Time info in dos find_t is not very useful. It consists */
/* of a separate date and time, and putting them together is */
/* not easy. So we leave that to a later stat() call. */
if( !_dos_findfirst( filespec->value, _A_NORMAL|_A_RDONLY|_A_SUBDIR, finfo ) )
if ( !_dos_findfirst( filespec->value, _A_NORMAL|_A_RDONLY|_A_SUBDIR, finfo ) )
{
string filename[1];
string_new( filename );
@@ -99,7 +99,7 @@ file_dirscan(
path_build( &f, filename, 0 );
(*func)( closure, filename->value, 0 /* not stat()'ed */, (time_t)0 );
}
while( !_dos_findnext( finfo ) );
while ( !_dos_findnext( finfo ) );
string_free( filename );
}
}
@@ -118,7 +118,7 @@ file_time(
struct stat statbuf;
if( stat( filename, &statbuf ) < 0 )
if ( stat( filename, &statbuf ) < 0 )
return -1;
*time = statbuf.st_mtime;

View File

@@ -5,33 +5,30 @@
# include "filesys.h"
# include "lists.h"
void
file_build1(
PATHNAME *f,
string* file)
void file_build1( PATHNAME * f, string * file )
{
if( DEBUG_SEARCH )
if ( DEBUG_SEARCH )
{
printf("build file: ");
if( f->f_root.len )
printf("build file: ");
if ( f->f_root.len )
printf( "root = '%.*s' ", f->f_root.len, f->f_root.ptr );
if( f->f_dir.len )
if ( f->f_dir.len )
printf( "dir = '%.*s' ", f->f_dir.len, f->f_dir.ptr );
if( f->f_base.len )
if ( f->f_base.len )
printf( "base = '%.*s' ", f->f_base.len, f->f_base.ptr );
printf( "\n" );
printf( "\n" );
}
/* Start with the grist. If the current grist isn't */
/* surrounded by <>'s, add them. */
if( f->f_grist.len )
if ( f->f_grist.len )
{
if( f->f_grist.ptr[0] != '<' )
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, '>' );
}
}

View File

@@ -31,29 +31,29 @@ int file_time( char *filename, time_t *time );
void file_build1(PATHNAME *f, string* file) ;
int file_is_file(char* filename);
struct file_info_t {
char * name;
short is_file;
short is_dir;
unsigned long size;
time_t time;
LIST * files;
} ;
typedef struct file_info_t file_info_t ;
struct file_info_t
{
char * name;
short is_file;
short is_dir;
unsigned long size;
time_t time;
LIST * files;
};
/* Creates a pointer to information about file
'filename', creating it as necessary. If
created, the structure will be default initialized. */
file_info_t * file_info(char * filename);
/* Returns information about a file, queries the OS
if needed. */
file_info_t * file_query(char * filename);
/* Creates a pointer to information about file 'filename', creating it as
* necessary. If created, the structure will be default initialized.
*/
file_info_t * file_info( char * filename );
/* Returns information about a file, queries the OS if needed. */
file_info_t * file_query( char * filename );
void file_done();
/** Marks a path/file to be removed when jam exits.
*/
/* Marks a path/file to be removed when jam exits. */
void file_remove_atexit( const char * path );
#endif

View File

@@ -119,25 +119,22 @@ struct ar_hdr /* archive file member header - printable ascii */
* 11/21/96 (peterk) - BEOS does not have Unix-style archives
*/
/*
* file_dirscan() - scan a directory for files
* file_dirscan() - scan a directory for files.
*/
void
file_dirscan(
char *dir,
scanback func,
void *closure )
void file_dirscan( char * dir, scanback func, void * closure )
{
PROFILE_ENTER(FILE_DIRSCAN);
PROFILE_ENTER( FILE_DIRSCAN );
file_info_t * d = 0;
d = file_query( dir );
if ( ! d || ! d->is_dir )
if ( !d || !d->is_dir )
{
PROFILE_EXIT(FILE_DIRSCAN);
PROFILE_EXIT( FILE_DIRSCAN );
return;
}
@@ -158,19 +155,19 @@ file_dirscan(
dir = *dir ? dir : ".";
/* Now enter contents of directory */
/* Now enter contents of directory. */
if( !( dd = opendir( dir ) ) )
if ( !( dd = opendir( dir ) ) )
{
PROFILE_EXIT(FILE_DIRSCAN);
PROFILE_EXIT( FILE_DIRSCAN );
return;
}
if( DEBUG_BINDSCAN )
if ( DEBUG_BINDSCAN )
printf( "scan directory %s\n", dir );
string_new( filename );
while( dirent = readdir( dd ) )
while ( dirent = readdir( dd ) )
{
file_info_t * ff = 0;
@@ -198,7 +195,7 @@ file_dirscan(
/* Special case / : enter it */
{
unsigned long len = strlen(d->name);
if( len == 1 && d->name[0] == '/' )
if ( ( len == 1 ) && ( d->name[0] == '/' ) )
(*func)( closure, d->name, 1 /* stat()'ed */, d->time );
}
@@ -214,9 +211,10 @@ file_dirscan(
}
}
PROFILE_EXIT(FILE_DIRSCAN);
PROFILE_EXIT( FILE_DIRSCAN );
}
file_info_t * file_query( char * filename )
{
file_info_t * ff = file_info( filename );
@@ -224,7 +222,7 @@ file_info_t * file_query( char * filename )
{
struct stat statbuf;
if( stat( *filename ? filename : ".", &statbuf ) < 0 )
if ( stat( *filename ? filename : ".", &statbuf ) < 0 )
return 0;
ff->is_file = statbuf.st_mode & S_IFREG ? 1 : 0;
@@ -280,10 +278,10 @@ file_archscan(
char *string_table = 0;
int fd;
if( ( fd = open( archive, O_RDONLY, 0 ) ) < 0 )
if ( ( fd = open( archive, O_RDONLY, 0 ) ) < 0 )
return;
if( read( fd, buf, SARMAG ) != SARMAG ||
if ( read( fd, buf, SARMAG ) != SARMAG ||
strncmp( ARMAG, buf, SARMAG ) )
{
close( fd );
@@ -292,24 +290,25 @@ file_archscan(
offset = SARMAG;
if( DEBUG_BINDSCAN )
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 )
#endif
) )
{
char lar_name_[257];
char* lar_name = lar_name_ + 1;
long lar_date;
long lar_size;
long lar_offset;
char *c;
char *src, *dest;
char lar_name_[257];
char * lar_name = lar_name_ + 1;
long lar_date;
long lar_size;
long lar_offset;
char * c;
char * src;
char * dest;
strncpy( lar_name, ar_hdr.ar_name, sizeof(ar_hdr.ar_name) );
@@ -346,8 +345,7 @@ file_archscan(
}
c = lar_name - 1;
while( *++c != ' ' && *c != '/' )
;
while ( ( *++c != ' ' ) && ( *c != '/' ) ) ;
*c = '\0';
if ( DEBUG_BINDSCAN )
@@ -385,26 +383,26 @@ static void file_archscan_small(
char buf[ MAXJPATH ];
long offset;
if( read( fd, (char *)&fl_hdr, FL_HSZ ) != FL_HSZ)
if ( read( fd, (char *)&fl_hdr, FL_HSZ ) != FL_HSZ)
return;
sscanf( fl_hdr.fl_fstmoff, "%ld", &offset );
if( DEBUG_BINDSCAN )
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;
long lar_date;
int lar_namlen;
sscanf( ar_hdr.hdr.ar_namlen, "%d", &lar_namlen );
sscanf( ar_hdr.hdr.ar_date, "%ld", &lar_date );
sscanf( ar_hdr.hdr.ar_nxtmem, "%ld", &offset );
sscanf( ar_hdr.hdr.ar_namlen, "%d" , &lar_namlen );
sscanf( ar_hdr.hdr.ar_date , "%ld", &lar_date );
sscanf( ar_hdr.hdr.ar_nxtmem, "%ld", &offset );
if( !lar_namlen )
if ( !lar_namlen )
continue;
ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0';
@@ -431,26 +429,26 @@ static void file_archscan_big(
char buf[ MAXJPATH ];
long long offset;
if( read( fd, (char *)&fl_hdr, FL_HSZ_BIG) != FL_HSZ_BIG)
if ( read( fd, (char *)&fl_hdr, FL_HSZ_BIG) != FL_HSZ_BIG)
return;
sscanf( fl_hdr.fl_fstmoff, "%lld", &offset );
if( DEBUG_BINDSCAN )
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;
long lar_date;
int lar_namlen;
sscanf( ar_hdr.hdr.ar_namlen, "%d", &lar_namlen );
sscanf( ar_hdr.hdr.ar_date, "%ld", &lar_date );
sscanf( ar_hdr.hdr.ar_nxtmem, "%lld", &offset );
sscanf( ar_hdr.hdr.ar_namlen, "%d" , &lar_namlen );
sscanf( ar_hdr.hdr.ar_date , "%ld" , &lar_date );
sscanf( ar_hdr.hdr.ar_nxtmem, "%lld", &offset );
if( !lar_namlen )
if ( !lar_namlen )
continue;
ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0';
@@ -469,10 +467,10 @@ void file_archscan(char *archive, scanback func, void *closure)
int fd;
char fl_magic[SAIAMAG];
if(( fd = open(archive, O_RDONLY, 0)) < 0)
if (( fd = open(archive, O_RDONLY, 0)) < 0)
return;
if(read( fd, fl_magic, SAIAMAG) != SAIAMAG
if (read( fd, fl_magic, SAIAMAG) != SAIAMAG
|| lseek(fd, 0, SEEK_SET) == -1)
{
close(fd);

View File

@@ -153,7 +153,7 @@ file_dirscan(
status = sys$parse( &xfab );
if( DEBUG_BINDSCAN )
if ( DEBUG_BINDSCAN )
printf( "scan directory %s\n", dir );
if ( !( status & 1 ) )
@@ -163,17 +163,17 @@ file_dirscan(
/* Add bogus directory for [000000] */
if( !strcmp( dir, "[000000]" ) )
if ( !strcmp( dir, "[000000]" ) )
{
(*func)( closure, "[000000]", 1 /* time valid */, 1 /* old but true */ );
}
/* Add bogus directory for [] */
if( !strcmp( dir, "[]" ) )
if ( !strcmp( dir, "[]" ) )
{
(*func)( closure, "[]", 1 /* time valid */, 1 /* old but true */ );
(*func)( closure, "[-]", 1 /* time valid */, 1 /* old but true */ );
(*func)( closure, "[]", 1 /* time valid */, 1 /* old but true */ );
(*func)( closure, "[-]", 1 /* time valid */, 1 /* old but true */ );
}
string_new( filename2 );
@@ -196,7 +196,7 @@ file_dirscan(
/* .xxx is a file with a suffix */
/* . is no suffix at all */
if( xnam.nam$b_type == 4 && !strncmp( xnam.nam$l_type, ".DIR", 4 ) )
if ( xnam.nam$b_type == 4 && !strncmp( xnam.nam$l_type, ".DIR", 4 ) )
{
/* directory */
sprintf( dirname, "[.%.*s]", xnam.nam$b_name, xnam.nam$l_name );
@@ -222,12 +222,12 @@ file_dirscan(
path_build( &f, filename2, 0 );
/*
if( DEBUG_SEARCH )
if ( DEBUG_SEARCH )
printf("root '%s' base %.*s suf %.*s = %s\n",
dir,
xnam.nam$b_name, xnam.nam$l_name,
xnam.nam$b_type, xnam.nam$l_type,
filename2);
filename2 );
*/
(*func)( closure, filename2->value, 1 /* time valid */, time );
@@ -280,10 +280,10 @@ file_archmember(
file_cvttime( &mhd->mhd$l_datim, &library_date );
for ( i = 0, p = module->dsc$a_pointer; i < module->dsc$w_length; i++, p++ )
filename[i] = *p;
for ( i = 0, p = module->dsc$a_pointer; i < module->dsc$w_length; ++i, ++p )
filename[ i ] = *p;
filename[i] = '\0';
filename[ i ] = '\0';
sprintf( buf, "%s(%s.obj)", VMS_archive, filename );
@@ -292,11 +292,8 @@ file_archmember(
return ( 1 );
}
void
file_archscan(
char *archive,
scanback func,
void *closure )
void file_archscan( char * archive, scanback func, void * closure )
{
static struct dsc$descriptor_s library =
{0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
@@ -313,14 +310,14 @@ file_archscan(
status = lbr$ini_control( &context, &lfunc, &typ, NULL );
if ( !( status & 1 ) )
return;
return;
library.dsc$a_pointer = archive;
library.dsc$w_length = strlen( archive );
status = lbr$open( &context, &library, NULL, NULL, NULL, NULL, NULL );
if ( !( status & 1 ) )
return;
return;
(void) lbr$get_index( &context, &index, file_archmember, NULL );
@@ -328,4 +325,3 @@ file_archscan(
}
# endif /* VMS */

View File

@@ -29,91 +29,86 @@
# define CHECK_BIT( tab, bit ) ( tab[ (bit)/8 ] & (1<<( (bit)%8 )) )
# define BITLISTSIZE 16 /* bytes used for [chars] in compiled expr */
static void globchars( char *s, char *e, char *b );
static void globchars( char * s, char * e, char * b );
/*
* glob() - match a string against a simple pattern
* glob() - match a string against a simple pattern.
*/
int
glob(
register char *c,
register char *s )
int glob( char * c, char * s )
{
char bitlist[ BITLISTSIZE ];
char *here;
char bitlist[ BITLISTSIZE ];
char * here;
for( ;; )
switch( *c++ )
for ( ; ; )
switch ( *c++ )
{
case '\0':
return *s ? -1 : 0;
case '?':
if( !*s++ )
if ( !*s++ )
return 1;
break;
case '[':
/* scan for matching ] */
/* Scan for matching ]. */
here = c;
do if( !*c++ )
return 1;
while( here == c || *c != ']' );
c++;
do if ( !*c++ ) return 1;
while ( ( here == c ) || ( *c != ']' ) );
++c;
/* build character class bitlist */
/* Build character class bitlist. */
globchars( here, c, bitlist );
if( !CHECK_BIT( bitlist, *(unsigned char *)s ) )
if ( !CHECK_BIT( bitlist, *(unsigned char *)s ) )
return 1;
s++;
++s;
break;
case '*':
here = s;
while ( *s )
s++;
++s;
/* Try to match the rest of the pattern in a recursive */
/* call. If the match fails we'll back up chars, retrying. */
while( s != here )
while ( s != here )
{
int r;
/* A fast path for the last token in a pattern */
/* A fast path for the last token in a pattern. */
r = *c ? glob( c, s ) : *s ? -1 : 0;
if( !r )
if ( !r )
return 0;
else if( r < 0 )
if ( r < 0 )
return 1;
--s;
}
break;
case '\\':
/* Force literal match of next char. */
if( !*c || *s++ != *c++ )
if ( !*c || ( *s++ != *c++ ) )
return 1;
break;
default:
if( *s++ != c[-1] )
if ( *s++ != c[ -1 ] )
return 1;
break;
}
}
/*
* globchars() - build a bitlist to check for character group match
* globchars() - build a bitlist to check for character group match.
*/
static void globchars( char * s, char * e, char * b )
@@ -122,21 +117,26 @@ static void globchars( char * s, char * e, char * b )
memset( b, '\0', BITLISTSIZE );
if( *s == '^')
neg++, s++;
if ( *s == '^' )
{
++neg;
++s;
}
while( s < e )
while ( s < e )
{
int c;
if( s+2 < e && s[1] == '-' )
if ( ( s + 2 < e ) && ( s[1] == '-' ) )
{
for( c = s[0]; c <= s[2]; c++ )
b[ c/8 ] |= (1<<(c%8));
for ( c = s[0]; c <= s[2]; ++c )
b[ c/8 ] |= ( 1 << ( c % 8 ) );
s += 3;
} else {
}
else
{
c = *s++;
b[ c/8 ] |= (1<<(c%8));
b[ c/8 ] |= ( 1 << ( c % 8 ) );
}
}
@@ -147,7 +147,6 @@ static void globchars( char * s, char * e, char * b )
b[ i ] ^= 0377;
}
/* Don't include \0 in either $[chars] or $[^chars] */
/* Do not include \0 in either $[chars] or $[^chars]. */
b[0] &= 0376;
}

View File

@@ -33,21 +33,25 @@ char *hashsccssid="@(#)hash.c 1.14 () 6/20/88";
/* Header attached to all data items entered into a hash table. */
struct hashhdr {
struct item *next;
unsigned int keyval; /* for quick comparisons */
} ;
struct hashhdr
{
struct item * next;
unsigned int keyval; /* for quick comparisons */
};
/* This structure overlays the one handed to hashenter(). */
/* It's actual size is given to hashinit(). */
/* This structure overlays the one handed to hashenter(). Its actual size is
* given to hashinit().
*/
struct hashdata {
char *key;
struct hashdata
{
char * key;
/* rest of user data */
} ;
};
typedef struct item {
struct hashhdr hdr;
typedef struct item
{
struct hashhdr hdr;
struct hashdata data;
} ITEM ;
@@ -85,8 +89,8 @@ struct hash
} lists[ MAX_LISTS ];
} items;
char *name; /* just for hashstats() */
} ;
char * name; /* just for hashstats() */
};
static void hashrehash( struct hash *hp );
static void hashstat( struct hash *hp );
@@ -100,7 +104,7 @@ static unsigned int hash_keyval( const char * key_ )
{
const unsigned char * key = (const unsigned char *)key_;
unsigned int keyval = *key;
while( *key )
while ( *key )
keyval = keyval * 2147059363 + *key++;
return keyval;
}
@@ -116,14 +120,14 @@ static ITEM * hash_search(
struct hash *hp,
unsigned int keyval,
const char * keydata,
ITEM ** previous )
ITEM * * previous )
{
ITEM * i = *hash_bucket(hp,keyval);
ITEM * p = 0;
for ( ; i; i = i->hdr.next )
{
if( keyval == i->hdr.keyval &&
if ( ( keyval == i->hdr.keyval ) &&
!strcmp( i->data.key, keydata ) )
{
if (previous)
@@ -192,10 +196,10 @@ hashitem(
profile_enter( 0, prof );
#endif
if( enter && !hp->items.more )
if ( enter && !hp->items.more )
hashrehash( hp );
if( !enter && !hp->items.nel )
if ( !enter && !hp->items.nel )
{
#ifdef HASH_DEBUG_PROFILE
if ( DEBUG_PROFILE )
@@ -266,7 +270,7 @@ static void hashrehash( register struct hash *hp )
hp->items.lists[i].base = hp->items.next;
hp->items.nel += hp->items.more;
if( hp->tab.base )
if ( hp->tab.base )
hash_mem_free( hp->items.datalen, (char *)hp->tab.base );
hp->tab.nel = hp->items.nel * hp->bloat;
@@ -274,12 +278,12 @@ static void hashrehash( register struct hash *hp )
memset( (char *)hp->tab.base, '\0', hp->tab.nel * sizeof( ITEM * ) );
for( i = 0; i < hp->items.list; i++ )
for ( i = 0; i < hp->items.list; ++i )
{
int nel = hp->items.lists[i].nel;
char *next = hp->items.lists[i].base;
for( ; nel--; next += hp->items.size )
for ( ; nel--; next += hp->items.size )
{
register ITEM *i = (ITEM *)next;
ITEM **ip = hp->tab.base + i->hdr.keyval % hp->tab.nel;
@@ -292,20 +296,20 @@ static void hashrehash( register struct hash *hp )
}
}
void hashenumerate( struct hash *hp, void (*f)(void*,void*), void* data )
void hashenumerate( struct hash * hp, void (* f)( void *, void * ), void * data )
{
int i;
for( i = 0; i <= hp->items.list; i++ )
for ( i = 0; i <= hp->items.list; ++i )
{
char *next = hp->items.lists[i].base;
char * next = hp->items.lists[i].base;
int nel = hp->items.lists[i].nel;
if ( i == hp->items.list )
nel -= hp->items.more;
for( ; nel--; next += hp->items.size )
for ( ; nel--; next += hp->items.size )
{
register ITEM * i = (ITEM *)next;
if ( i->data.key != 0 ) /* don't enumerate freed items */
ITEM * i = (ITEM *)next;
if ( i->data.key != 0 ) /* DO not enumerate freed items. */
f( &i->data, data );
}
}
@@ -350,15 +354,15 @@ hashdone( struct hash *hp )
{
int i;
if( !hp )
if ( !hp )
return;
if( DEBUG_MEM || DEBUG_PROFILE )
if ( DEBUG_MEM || DEBUG_PROFILE )
hashstat( hp );
if( hp->tab.base )
if ( hp->tab.base )
hash_mem_free( hp->items.datalen, (char *)hp->tab.base );
for( i = 0; i <= hp->items.list; i++ )
for ( i = 0; i <= hp->items.list; ++i )
hash_mem_free( hp->items.datalen, hp->items.lists[i].base );
hash_mem_free( hp->items.datalen, (char *)hp );
}
@@ -399,21 +403,21 @@ static void hash_mem_finalizer(char * key, struct hash * hp)
/* ---- */
static void
hashstat( struct hash *hp )
static void hashstat( struct hash * hp )
{
ITEM **tab = hp->tab.base;
ITEM * * tab = hp->tab.base;
int nel = hp->tab.nel;
int count = 0;
int sets = 0;
int run = ( tab[ nel - 1 ] != (ITEM *)0 );
int i, here;
int i;
int here;
for( i = nel; i > 0; i-- )
for ( i = nel; i > 0; --i )
{
if( here = ( *tab++ != (ITEM *)0 ) )
if ( here = ( *tab++ != (ITEM *)0 ) )
count++;
if( here && !run )
if ( here && !run )
sets++;
run = here;
}

View File

@@ -13,13 +13,13 @@
typedef struct hashdata HASHDATA;
struct hash * hashinit( int datalen, char *name );
int hashitem( struct hash *hp, HASHDATA **data, int enter );
void hashdone( struct hash *hp );
void hashenumerate( struct hash *hp, void (*f)(void*,void*), void* data );
int hash_free( struct hash *hp, HASHDATA *data);
struct hash * hashinit ( int datalen, char * name );
int hashitem ( struct hash * hp, HASHDATA * * data, int enter );
void hashdone ( struct hash * hp );
void hashenumerate( struct hash * hp, void (* f)( void *, void * ), void * data );
int hash_free ( struct hash * hp, HASHDATA * data);
# define hashenter( hp, data ) (!hashitem( hp, data, !0 ))
# define hashcheck( hp, data ) hashitem( hp, data, 0 )
#define hashenter( hp, data ) ( !hashitem( hp, data, !0 ) )
#define hashcheck( hp, data ) hashitem( hp, data, 0 )
#endif

View File

@@ -19,41 +19,41 @@
/*
* Craig W. McPheeters, Alias|Wavefront.
*
* hcache.c hcache.h - handle cacheing of #includes in source files
* hcache.c hcache.h - handle cacheing of #includes in source files.
*
* Create a cache of files scanned for headers. When starting jam,
* look for the cache file and load it if present. When finished the
* binding phase, create a new header cache. The cache contains
* files, their timestamps and the header 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
* Create a cache of files scanned for headers. When starting jam, look for the
* cache file and load it if present. When finished the binding phase, create a
* new header cache. The cache contains files, their timestamps and the header
* 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.)
*
* External routines:
* hcache_init() - read and parse the local .jamdeps file.
* hcache_done() - write a new .jamdeps file
* hcache() - return list of headers on target. Use cache or do a scan.
* hcache_done() - write a new .jamdeps file.
* hcache() - return list of headers on target. Use cache or do a scan.
*
* The dependency file format is an ascii file with 1 line per target.
* Each line has the following fields:
* 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
* */
struct hcachedata {
char *boundname;
time_t time;
LIST *includes;
LIST *hdrscan; /* the HDRSCAN value for this target */
int age; /* if too old, we'll remove it from cache */
struct hcachedata *next;
} ;
*/
typedef struct hcachedata HCACHEDATA ;
struct hcachedata
{
char * boundname;
time_t time;
LIST * includes;
LIST * hdrscan; /* the HDRSCAN value for this target */
int age; /* if too old, we'll remove it from cache */
HCACHEDATA * next;
};
static struct hash *hcachehash = 0;
static HCACHEDATA *hcachelist = 0;
static struct hash * hcachehash = 0;
static HCACHEDATA * hcachelist = 0;
static int queries = 0;
static int hits = 0;
@@ -62,115 +62,115 @@ static int hits = 0;
#define CACHE_RECORD_HEADER "header"
#define CACHE_RECORD_END "end"
/*
* Return the name of the header cache file. May return NULL.
* Return the name of the header cache file. May return NULL.
*
* The user sets this by setting the HCACHEFILE variable in a Jamfile.
* We cache the result so the user can't change the cache file during
* header scanning.
* The user sets this by setting the HCACHEFILE variable in a Jamfile. We cache
* the result so the user can not change the cache file during header scanning.
*/
static char*
cache_name(void)
static char * cache_name( void )
{
static char* name = 0;
if (!name) {
LIST *hcachevar = var_get("HCACHEFILE");
static char * name = 0;
if ( !name )
{
LIST * hcachevar = var_get( "HCACHEFILE" );
if (hcachevar) {
TARGET *t = bindtarget( hcachevar->string );
if ( hcachevar )
{
TARGET * t = bindtarget( hcachevar->string );
pushsettings( t->settings );
/* Don't expect cache file to be generated, so pass 0
as third argument to search.
Expect the location to be specified via LOCATE,
so pass 0 as fourth arugment. */
t->boundname = search( t->name, &t->time, 0, 0 );
popsettings( t->settings );
pushsettings( t->settings );
/* Do not expect the cache file to be generated, so pass 0 as the
* third argument to search. Expect the location to be specified via
* LOCATE, so pass 0 as the fourth arugment.
*/
t->boundname = search( t->name, &t->time, 0, 0 );
popsettings( t->settings );
if (hcachevar) {
name = copystr(t->boundname);
if ( hcachevar )
name = copystr( t->boundname );
}
}
}
return name;
}
/*
* Return the maximum age a cache entry can have before it is purged
* from the cache.
* Return the maximum age a cache entry can have before it is purged ftom the
* cache.
*/
static int
cache_maxage(void)
static int cache_maxage( void )
{
int age = 100;
LIST *var = var_get("HCACHEMAXAGE");
if (var) {
age = atoi(var->string);
if (age < 0)
age = 0;
LIST * var = var_get( "HCACHEMAXAGE" );
if ( var )
{
age = atoi( var->string );
if ( age < 0 )
age = 0;
}
return age;
}
/*
* Read a netstring. The caveat is that the string can't contain
* ASCII 0. The returned value is as returned by newstr(), so it need
* not be freed.
* Read a netstring. The caveat is that the string can not contain ASCII 0. The
* returned value is as returned by newstr(), so it need not be freed.
*/
char*
read_netstring(FILE* f)
char * read_netstring( FILE * f )
{
unsigned long len;
static char* buf = NULL;
static char * buf = NULL;
static unsigned long buf_len = 0;
if (fscanf(f, " %9lu", &len) != 1)
return NULL;
if (fgetc(f) != (int)'\t')
return NULL;
if ( fscanf( f, " %9lu", &len ) != 1 )
return NULL;
if ( fgetc( f ) != (int)'\t' )
return NULL;
if (len > 1024 * 64)
return NULL; /* sanity check */
if ( len > 1024 * 64 )
return NULL; /* sanity check */
if (len > buf_len)
if ( len > buf_len )
{
unsigned long new_len = buf_len * 2;
if (new_len < len)
new_len = len;
buf = (char*)BJAM_REALLOC(buf, new_len + 1);
if (buf)
buf_len = new_len;
unsigned long new_len = buf_len * 2;
if ( new_len < len )
new_len = len;
buf = (char *)BJAM_REALLOC( buf, new_len + 1 );
if ( buf )
buf_len = new_len;
}
if (!buf)
return NULL;
if ( !buf )
return NULL;
if (fread(buf, 1, len, f) != len)
return NULL;
if (fgetc(f) != (int)'\n')
return NULL;
if ( fread( buf, 1, len, f ) != len )
return NULL;
if ( fgetc( f ) != (int)'\n' )
return NULL;
buf[len] = 0;
return newstr(buf);
buf[ len ] = 0;
return newstr( buf );
}
/*
* Write a netstring.
*/
void
write_netstring(FILE* f, const char* s)
void write_netstring( FILE * f, char const * s )
{
if (!s)
s = "";
fprintf(f, "%lu\t%s\n", strlen(s), s);
if ( !s )
s = "";
fprintf( f, "%lu\t%s\n", strlen( s ), s );
}
void
hcache_init()
void hcache_init()
{
HCACHEDATA cachedata;
HCACHEDATA * c;
@@ -179,182 +179,188 @@ hcache_init()
int header_count = 0;
char * hcachename;
hcachehash = hashinit (sizeof (HCACHEDATA), "hcache");
hcachehash = hashinit( sizeof( HCACHEDATA ), "hcache" );
if (! (hcachename = cache_name()))
if ( !( hcachename = cache_name() ) )
return;
if (! (f = fopen (hcachename, "rb" )))
if ( !( f = fopen( hcachename, "rb" ) ) )
return;
version = read_netstring(f);
if (!version || strcmp(version, CACHE_FILE_VERSION)) {
fclose(f);
return;
}
while (1)
version = read_netstring( f );
if ( !version || strcmp( version, CACHE_FILE_VERSION ) )
{
char* record_type;
char *time_str;
char *age_str;
char *includes_count_str;
char *hdrscan_count_str;
int i, count;
LIST *l;
record_type = read_netstring(f);
if (!record_type) {
fprintf(stderr, "invalid %s\n", hcachename);
goto bail;
}
if (!strcmp(record_type, CACHE_RECORD_END)) {
break;
}
if (strcmp(record_type, CACHE_RECORD_HEADER)) {
fprintf(stderr, "invalid %s with record separator <%s>\n",
hcachename, record_type ? record_type : "<null>");
goto bail;
fclose( f );
return;
}
c = &cachedata;
c->boundname = read_netstring(f);
time_str = read_netstring(f);
age_str = read_netstring(f);
includes_count_str = read_netstring(f);
if (!c->boundname || !time_str || !age_str
|| !includes_count_str)
while ( 1 )
{
fprintf(stderr, "invalid %s\n", hcachename);
goto bail;
}
char * record_type;
char * time_str;
char * age_str;
char * includes_count_str;
char * hdrscan_count_str;
int i;
int count;
LIST * l;
c->time = atoi(time_str);
c->age = atoi(age_str) + 1;
count = atoi(includes_count_str);
for (l = 0, i = 0; i < count; i++) {
char* s = read_netstring(f);
if (!s) {
fprintf(stderr, "invalid %s\n", hcachename);
goto bail;
record_type = read_netstring( f );
if ( !record_type )
{
fprintf( stderr, "invalid %s\n", hcachename );
goto bail;
}
l = list_new(l, s);
}
c->includes = l;
hdrscan_count_str = read_netstring(f);
if (!includes_count_str) {
list_free(c->includes);
fprintf(stderr, "invalid %s\n", hcachename);
goto bail;
}
count = atoi(hdrscan_count_str);
for (l = 0, i = 0; i < count; i++) {
char* s = read_netstring(f);
if (!s) {
fprintf(stderr, "invalid %s\n", hcachename);
goto bail;
if ( !strcmp( record_type, CACHE_RECORD_END ) )
break;
if ( strcmp( record_type, CACHE_RECORD_HEADER ) )
{
fprintf( stderr, "invalid %s with record separator <%s>\n",
hcachename, record_type ? record_type : "<null>" );
goto bail;
}
l = list_new(l, s);
}
c->hdrscan = l;
if (!hashenter(hcachehash, (HASHDATA **)&c)) {
fprintf(stderr, "can't insert header cache item, bailing on %s\n",
hcachename);
goto bail;
c = &cachedata;
c->boundname = read_netstring( f );
time_str = read_netstring( f );
age_str = read_netstring( f );
includes_count_str = read_netstring( f );
if ( !c->boundname || !time_str || !age_str || !includes_count_str )
{
fprintf( stderr, "invalid %s\n", hcachename );
goto bail;
}
c->time = atoi( time_str );
c->age = atoi( age_str ) + 1;
count = atoi( includes_count_str );
for ( l = 0, i = 0; i < count; ++i )
{
char * s = read_netstring( f );
if ( !s )
{
fprintf( stderr, "invalid %s\n", hcachename );
goto bail;
}
l = list_new( l, s );
}
c->includes = l;
hdrscan_count_str = read_netstring( f );
if ( !includes_count_str )
{
list_free( c->includes );
fprintf( stderr, "invalid %s\n", hcachename );
goto bail;
}
count = atoi( hdrscan_count_str );
for ( l = 0, i = 0; i < count; ++i )
{
char * s = read_netstring( f );
if ( !s )
{
fprintf( stderr, "invalid %s\n", hcachename );
goto bail;
}
l = list_new( l, s );
}
c->hdrscan = l;
if ( !hashenter( hcachehash, (HASHDATA * *)&c ) )
{
fprintf( stderr, "can't insert header cache item, bailing on %s\n",
hcachename );
goto bail;
}
c->next = hcachelist;
hcachelist = c;
++header_count;
}
c->next = hcachelist;
hcachelist = c;
header_count++;
}
if (DEBUG_HEADER) {
printf("hcache read from file %s\n", hcachename);
}
if ( DEBUG_HEADER )
printf( "hcache read from file %s\n", hcachename );
bail:
fclose(f);
fclose( f );
}
void
hcache_done()
void hcache_done()
{
FILE *f;
HCACHEDATA *c;
int header_count = 0;
char* hcachename;
int maxage;
FILE * f;
HCACHEDATA * c;
int header_count = 0;
char * hcachename;
int maxage;
if (!hcachehash)
return;
if ( !hcachehash )
return;
if (! (hcachename = cache_name()))
return;
if ( !( hcachename = cache_name() ) )
return;
if (! (f = fopen (hcachename, "wb" )))
return;
if ( !( f = fopen( hcachename, "wb" ) ) )
return;
maxage = cache_maxage();
/* print out the version */
write_netstring(f, CACHE_FILE_VERSION);
/* Print out the version. */
write_netstring( f, CACHE_FILE_VERSION );
c = hcachelist;
for (c = hcachelist; c; c = c->next) {
LIST *l;
char time_str[30];
char age_str[30];
char includes_count_str[30];
char hdrscan_count_str[30];
for ( c = hcachelist; c; c = c->next )
{
LIST * l;
char time_str[ 30 ];
char age_str[ 30 ];
char includes_count_str[ 30 ];
char hdrscan_count_str[ 30 ];
if (maxage == 0)
c->age = 0;
else if (c->age > maxage)
continue;
if ( maxage == 0 )
c->age = 0;
else if ( c->age > maxage )
continue;
sprintf(includes_count_str, "%lu", list_length(c->includes));
sprintf(hdrscan_count_str, "%lu", list_length(c->hdrscan));
sprintf(time_str, "%lu", c->time);
sprintf(age_str, "%lu", c->age);
sprintf( includes_count_str, "%lu", list_length( c->includes ) );
sprintf( hdrscan_count_str, "%lu", list_length( c->hdrscan ) );
sprintf( time_str, "%lu", c->time );
sprintf( age_str, "%lu", c->age );
write_netstring(f, CACHE_RECORD_HEADER);
write_netstring(f, c->boundname);
write_netstring(f, time_str);
write_netstring(f, age_str);
write_netstring(f, includes_count_str);
for (l = c->includes; l; l = list_next(l)) {
write_netstring(f, l->string);
write_netstring( f, CACHE_RECORD_HEADER );
write_netstring( f, c->boundname );
write_netstring( f, time_str );
write_netstring( f, age_str );
write_netstring( f, includes_count_str );
for ( l = c->includes; l; l = list_next( l ) )
write_netstring( f, l->string );
write_netstring( f, hdrscan_count_str );
for ( l = c->hdrscan; l; l = list_next( l ) )
write_netstring( f, l->string );
fputs( "\n", f );
++header_count;
}
write_netstring(f, hdrscan_count_str);
for (l = c->hdrscan; l; l = list_next(l)) {
write_netstring(f, l->string);
}
fputs("\n", f);
header_count++;
}
write_netstring(f, CACHE_RECORD_END);
write_netstring( f, CACHE_RECORD_END );
if (DEBUG_HEADER) {
printf("hcache written to %s. %d dependencies, %.0f%% hit rate\n",
hcachename, header_count,
queries ? 100.0 * hits / queries : 0);
}
if ( DEBUG_HEADER )
printf( "hcache written to %s. %d dependencies, %.0f%% hit rate\n",
hcachename, header_count, queries ? 100.0 * hits / queries : 0 );
fclose (f);
fclose ( f );
}
LIST *
hcache (TARGET *t, int rec, regexp *re[], LIST *hdrscan)
LIST * hcache( TARGET * t, int rec, regexp * re[], LIST * hdrscan )
{
HCACHEDATA cachedata, *c = &cachedata;
LIST *l = 0;
HCACHEDATA cachedata;
HCACHEDATA * c = &cachedata;
LIST * l = 0;
++queries;
@@ -413,7 +419,7 @@ hcache (TARGET *t, int rec, regexp *re[], LIST *hdrscan)
}
}
/* 'c' points at the cache entry. Its out of date. */
/* 'c' points at the cache entry. Its out of date. */
l = headers1 (0, t->boundname, rec, re);

View File

@@ -46,17 +46,17 @@
* just to invoke a rule.
*/
static LIST *header_macros1( LIST *l, char *file, int rec, regexp *re[] );
static LIST * header_macros1( LIST * l, char * file, int rec, regexp * re[] );
/* this type is used to store a dictionary of file header macros */
typedef struct header_macro
{
char* symbol;
char* filename; /* we could maybe use a LIST here ?? */
char * symbol;
char * filename; /* we could maybe use a LIST here ?? */
} HEADER_MACRO;
static struct hash* header_macros_hash = 0;
static struct hash * header_macros_hash = 0;
/*
* headers() - scan a target for include files and call HDRRULE
@@ -84,12 +84,13 @@ macro_headers( TARGET *t )
"[<\"]([^\">]*)[\">].*$" );
}
if( !( f = fopen( t->boundname, "r" ) ) )
if ( !( f = fopen( t->boundname, "r" ) ) )
return;
while( fgets( buf, sizeof( buf ), f ) )
while ( fgets( buf, sizeof( buf ), f ) )
{
HEADER_MACRO var, *v = &var;
HEADER_MACRO var;
HEADER_MACRO *v = &var;
if ( regexec( re, buf ) && re->startp[1] )
{
@@ -121,19 +122,18 @@ macro_headers( TARGET *t )
}
char*
macro_header_get( const char* macro_name )
char * macro_header_get( const char * macro_name )
{
HEADER_MACRO var, *v = &var;
HEADER_MACRO var;
HEADER_MACRO * v = &var;
v->symbol = (char*)macro_name;
v->symbol = (char* )macro_name;
if( header_macros_hash && hashcheck( header_macros_hash, (HASHDATA **)&v ) )
{
if ( DEBUG_HEADER )
printf( "### macro '%s' evaluated to '%s'\n", macro_name, v->filename );
return v->filename;
}
return 0;
if ( header_macros_hash && hashcheck( header_macros_hash, (HASHDATA **)&v ) )
{
if ( DEBUG_HEADER )
printf( "### macro '%s' evaluated to '%s'\n", macro_name, v->filename );
return v->filename;
}
return 0;
}

View File

@@ -58,24 +58,23 @@ static LIST *headers1( LIST *l, char *file, int rec, regexp *re[]);
void
headers( TARGET *t )
{
LIST *hdrscan;
LIST *hdrrule;
LIST *headlist = 0;
regexp *re[ MAXINC ];
LIST * hdrscan;
LIST * hdrrule;
LIST * headlist = 0;
regexp * re[ MAXINC ];
int rec = 0;
if( !( hdrscan = var_get( "HDRSCAN" ) ) ||
if ( !( hdrscan = var_get( "HDRSCAN" ) ) ||
!( hdrrule = var_get( "HDRRULE" ) ) )
return;
if( DEBUG_HEADER )
if ( DEBUG_HEADER )
printf( "header scan %s\n", t->name );
/* Compile all regular expressions in HDRSCAN */
while( rec < MAXINC && hdrscan )
while ( ( rec < MAXINC ) && hdrscan )
{
re[rec++] = regex_compile( hdrscan->string );
re[ rec++ ] = regex_compile( hdrscan->string );
hdrscan = list_next( hdrscan );
}
@@ -91,7 +90,7 @@ headers( TARGET *t )
lol_add( frame->args, headers1( headlist, t->boundname, rec, re ) );
#endif
if( lol_get( frame->args, 1 ) )
if ( lol_get( frame->args, 1 ) )
{
/* The third argument to HDRRULE is the bound name of
* $(<) */
@@ -100,14 +99,14 @@ headers( TARGET *t )
list_free( evaluate_rule( hdrrule->string, frame ) );
}
/* Clean up */
/* Clean up. */
frame_free( frame );
}
}
/*
* headers1() - using regexp, scan a file and build include LIST
* headers1() - using regexp, scan a file and build include LIST.
*/
#ifdef OPT_HEADER_CACHE_EXT
@@ -116,16 +115,15 @@ LIST *
static LIST *
#endif
headers1(
LIST *l,
char *file,
LIST * l,
char * file,
int rec,
regexp *re[] )
regexp * re[] )
{
FILE *f;
char buf[ 1024 ];
int i;
static regexp *re_macros = 0;
FILE * f;
char buf[ 1024 ];
int i;
static regexp * re_macros = 0;
#ifdef OPT_IMPROVED_PATIENCE_EXT
static int count = 0;
@@ -134,63 +132,61 @@ headers1(
printf("...patience...\n");
#endif
/* the following regexp is used to detect cases where a */
/* file is included through a line line "#include MACRO" */
if ( re_macros == 0 )
{
re_macros = regex_compile(
"^[ ]*#[ ]*include[ ]*([A-Za-z][A-Za-z0-9_]*).*$" );
}
/* the following regexp is used to detect cases where a */
/* file is included through a line line "#include MACRO" */
if ( re_macros == 0 )
re_macros = regex_compile(
"^[ ]*#[ ]*include[ ]*([A-Za-z][A-Za-z0-9_]*).*$" );
if( !( f = fopen( file, "r" ) ) )
if ( !( f = fopen( file, "r" ) ) )
return l;
while( fgets( buf, sizeof( buf ), f ) )
while ( fgets( buf, sizeof( buf ), f ) )
{
int size = strlen (buf);
/* Remove trailing \r and \n, if any. */
while (size > 0
&& (buf[size-1] == '\n' && buf[size-1] == '\r'))
{
buf[size-1] = '\0';
--size;
}
for( i = 0; i < rec; i++ )
if( regexec( re[i], buf ) && re[i]->startp[1] )
int size = strlen( buf );
/* Remove trailing \r and \n, if any. */
while ( ( size > 0 ) &&
( buf[ size - 1 ] == '\n' ) &&
( buf[ size - 1 ] == '\r' ) )
{
re[i]->endp[1][0] = '\0';
if( DEBUG_HEADER )
printf( "header found: %s\n", re[i]->startp[1] );
l = list_new( l, newstr( re[i]->startp[1] ) );
buf[ size - 1 ] = '\0';
--size;
}
/* special treatment for #include MACRO */
if ( regexec( re_macros, buf ) && re_macros->startp[1] )
for ( i = 0; i < rec; ++i )
if ( regexec( re[i], buf ) && re[i]->startp[1] )
{
char* header_filename;
re_macros->endp[1][0] = '\0';
re[i]->endp[1][0] = '\0';
if ( DEBUG_HEADER )
printf( "macro header found: %s", re_macros->startp[1] );
printf( "header found: %s\n", re[i]->startp[1] );
header_filename = macro_header_get( re_macros->startp[1] );
if ( header_filename )
{
if ( DEBUG_HEADER )
printf( " resolved to '%s'\n", header_filename );
l = list_new( l, newstr( header_filename ) );
}
else
{
if ( DEBUG_HEADER )
printf( " ignored !!\n" );
}
l = list_new( l, newstr( re[i]->startp[1] ) );
}
/* special treatment for #include MACRO */
if ( regexec( re_macros, buf ) && re_macros->startp[1] )
{
char* header_filename;
re_macros->endp[1][0] = '\0';
if ( DEBUG_HEADER )
printf( "macro header found: %s", re_macros->startp[1] );
header_filename = macro_header_get( re_macros->startp[1] );
if ( header_filename )
{
if ( DEBUG_HEADER )
printf( " resolved to '%s'\n", header_filename );
l = list_new( l, newstr( header_filename ) );
}
else
{
if ( DEBUG_HEADER )
printf( " ignored !!\n" );
}
}
}
fclose( f );
@@ -198,8 +194,8 @@ headers1(
return l;
}
void
regerror( char *s )
void regerror( char * s )
{
printf( "re error %s\n", s );
}

View File

@@ -103,132 +103,122 @@
* 01/10/01 (seiwald) - pathsys.h split from filesys.h
*/
# include "jam.h"
# include "option.h"
# include "patchlevel.h"
#include "jam.h"
#include "option.h"
#include "patchlevel.h"
/* These get various function declarations. */
# include "lists.h"
# include "parse.h"
# include "variable.h"
# include "compile.h"
# include "builtins.h"
# include "rules.h"
# include "newstr.h"
# include "scan.h"
# include "timestamp.h"
# include "make.h"
# include "strings.h"
# include "expand.h"
# include "filesys.h"
# include "output.h"
#include "lists.h"
#include "parse.h"
#include "variable.h"
#include "compile.h"
#include "builtins.h"
#include "rules.h"
#include "newstr.h"
#include "scan.h"
#include "timestamp.h"
#include "make.h"
#include "strings.h"
#include "expand.h"
#include "filesys.h"
#include "output.h"
/* Macintosh is "special" */
#ifdef OS_MAC
#include <QuickDraw.h>
#endif
# ifdef OS_MAC
# include <QuickDraw.h>
# endif
/* And UNIX for this. */
#ifdef unix
#include <sys/utsname.h>
#include <signal.h>
#endif
/* And UNIX for this */
# ifdef unix
# include <sys/utsname.h>
# include <signal.h>
# endif
struct globs globs = {
struct globs globs =
{
0, /* noexec */
1, /* jobs */
0, /* quitquick */
0, /* newestfirst */
0, /* pipes action stdout and stderr merged to action output */
# ifdef OS_MAC
{ 0, 0 }, /* debug - suppress tracing output */
# else
{ 0, 1 }, /* debug ... */
# endif
0, /* pipes action stdout and stderr merged to action output */
#ifdef OS_MAC
{ 0, 0 }, /* debug - suppress tracing output */
#else
{ 0, 1 }, /* debug ... */
#endif
0, /* output commands, not run them */
0 /* action timeout */
} ;
0 /* action timeout */
};
/* Symbols to be defined as true for use in Jambase */
/* Symbols to be defined as true for use in Jambase. */
static char * othersyms[] = { OSMAJOR, OSMINOR, OSPLAT, JAMVERSYM, 0 };
static char *othersyms[] = { OSMAJOR, OSMINOR, OSPLAT, JAMVERSYM, 0 } ;
/* Known for sure:
* mac needs arg_enviro
* OS2 needs extern environ
*/
# ifdef OS_MAC
# define use_environ arg_environ
# ifdef MPW
QDGlobals qd;
# endif
# endif
/* on Win32-LCC */
# if defined( OS_NT ) && defined( __LCC__ )
# define use_environ _environ
# endif
# if defined( __MWERKS__)
# define use_environ _environ
extern char **_environ;
#ifdef OS_MAC
#define use_environ arg_environ
#ifdef MPW
QDGlobals qd;
#endif
#endif
# ifndef use_environ
# define use_environ environ
# if !defined( __WATCOM__ ) && !defined( OS_OS2 ) && !defined( OS_NT )
extern char **environ;
# endif
# endif
/* on Win32-LCC */
#if defined( OS_NT ) && defined( __LCC__ )
#define use_environ _environ
#endif
# if YYDEBUG != 0
extern int yydebug;
# endif
# if defined( __MWERKS__)
#define use_environ _environ
extern char * * _environ;
#endif
#ifndef use_environ
#define use_environ environ
#if !defined( __WATCOM__ ) && !defined( OS_OS2 ) && !defined( OS_NT )
extern char **environ;
#endif
#endif
#if YYDEBUG != 0
extern int yydebug;
#endif
#ifndef NDEBUG
static void run_unit_tests()
{
# if defined( USE_EXECNT )
#if defined( USE_EXECNT )
extern void execnt_unit_test();
execnt_unit_test();
# endif
#endif
string_unit_test();
var_expand_unit_test();
}
#endif
#ifdef HAVE_PYTHON
extern PyObject*
bjam_call(PyObject *self, PyObject *args);
extern PyObject*
bjam_import_rule(PyObject* self, PyObject* args);
extern PyObject*
bjam_define_action(PyObject* self, PyObject* args);
extern PyObject*
bjam_variable(PyObject* self, PyObject* args);
extern PyObject*
bjam_backtrace(PyObject* self, PyObject *args);
extern PyObject * bjam_call ( PyObject * self, PyObject * args );
extern PyObject * bjam_import_rule ( PyObject * self, PyObject * args );
extern PyObject * bjam_define_action( PyObject * self, PyObject * args );
extern PyObject * bjam_variable ( PyObject * self, PyObject * args );
extern PyObject * bjam_backtrace ( PyObject * self, PyObject * args );
#endif
int main( int argc, char **argv, char **arg_environ )
int main( int argc, char * * argv, char * * arg_environ )
{
int n;
char *s;
struct option optv[N_OPTS];
const char *all = "all";
int anyhow = 0;
int status;
int arg_c = argc;
char ** arg_v = argv;
const char *progname = argv[0];
int n;
char * s;
struct option optv[N_OPTS];
char const * all = "all";
int anyhow = 0;
int status;
int arg_c = argc;
char * * arg_v = argv;
char const * progname = argv[0];
BJAM_MEM_INIT();
@@ -236,9 +226,10 @@ int main( int argc, char **argv, char **arg_environ )
InitGraf(&qd.thePort);
# endif
argc--, argv++;
--argc;
++argv;
if( getoptions( argc, argv, "-:l:d:j:p:f:gs:t:ano:qv", optv ) < 0 )
if ( getoptions( argc, argv, "-:l:d:j:p:f:gs:t:ano:qv", optv ) < 0 )
{
printf( "\nusage: %s [ options ] targets...\n\n", progname );
@@ -261,8 +252,7 @@ int main( int argc, char **argv, char **arg_environ )
}
/* Version info. */
if( ( s = getoptval( optv, 'v', 0 ) ) )
if ( ( s = getoptval( optv, 'v', 0 ) ) )
{
printf( "Boost.Jam " );
printf( "Version %s. %s.\n", VERSION, OSMINOR );
@@ -275,268 +265,256 @@ int main( int argc, char **argv, char **arg_environ )
return EXITOK;
}
/* Pick up interesting options */
if( ( s = getoptval( optv, 'n', 0 ) ) )
/* Pick up interesting options. */
if ( ( s = getoptval( optv, 'n', 0 ) ) )
globs.noexec++, globs.debug[2] = 1;
if( ( s = getoptval( optv, 'p', 0 ) ) )
if ( ( s = getoptval( optv, 'p', 0 ) ) )
{
/* undocumented -p3 (acts like both -p1 -p2) means separate pipe action stdout and stderr */
globs.pipe_action = atoi(s);
if (3 < globs.pipe_action || globs.pipe_action < 0)
/* Undocumented -p3 (acts like both -p1 -p2) means separate pipe action
* stdout and stderr.
*/
globs.pipe_action = atoi( s );
if ( ( 3 < globs.pipe_action ) || ( globs.pipe_action < 0 ) )
{
printf( "Invalid pipe descriptor '%d', valid values are -p[0..3].\n", globs.pipe_action);
exit(EXITBAD);
printf(
"Invalid pipe descriptor '%d', valid values are -p[0..3].\n",
globs.pipe_action );
exit( EXITBAD );
}
}
if( ( s = getoptval( optv, 'q', 0 ) ) )
globs.quitquick = 1;
if ( ( s = getoptval( optv, 'q', 0 ) ) )
globs.quitquick = 1;
if( ( s = getoptval( optv, 'a', 0 ) ) )
if ( ( s = getoptval( optv, 'a', 0 ) ) )
anyhow++;
if( ( s = getoptval( optv, 'j', 0 ) ) )
if ( ( s = getoptval( optv, 'j', 0 ) ) )
globs.jobs = atoi( s );
if( ( s = getoptval( optv, 'g', 0 ) ) )
if ( ( s = getoptval( optv, 'g', 0 ) ) )
globs.newestfirst = 1;
if( ( s = getoptval( optv, 'l', 0 ) ) )
if ( ( s = getoptval( optv, 'l', 0 ) ) )
globs.timeout = atoi( s );
/* Turn on/off debugging */
for( n = 0; s = getoptval( optv, 'd', n ); n++ )
for ( n = 0; s = getoptval( optv, 'd', n ); ++n )
{
int i;
/* First -d, turn off defaults. */
if( !n )
for( i = 0; i < DEBUG_MAX; i++ )
if ( !n )
for ( i = 0; i < DEBUG_MAX; ++i )
globs.debug[i] = 0;
i = atoi( s );
if( i < 0 || i >= DEBUG_MAX )
if ( ( i < 0 ) || ( i >= DEBUG_MAX ) )
{
printf( "Invalid debug level '%s'.\n", s );
continue;
}
/* n turns on levels 1-n */
/* +n turns on level n */
if( *s == '+' )
/* n turns on levels 1-n. */
/* +n turns on level n. */
if ( *s == '+' )
globs.debug[i] = 1;
else while( i )
else while ( i )
globs.debug[i--] = 1;
}
{ PROFILE_ENTER(MAIN);
#ifdef HAVE_PYTHON
{
PROFILE_ENTER(MAIN_PYTHON);
Py_Initialize();
PROFILE_ENTER( MAIN );
#ifdef HAVE_PYTHON
{
static PyMethodDef BjamMethods[] = {
{"call", bjam_call, METH_VARARGS,
"Call the specified bjam rule."},
{"import_rule", bjam_import_rule, METH_VARARGS,
"Imports Python callable to bjam."},
{"define_action", bjam_define_action, METH_VARARGS,
"Defines a command line action."},
{"variable", bjam_variable, METH_VARARGS,
"Obtains a variable from bjam's global module."},
{"backtrace", bjam_backtrace, METH_VARARGS,
"Returns bjam backtrace from the last call into Python."},
{NULL, NULL, 0, NULL}
};
PROFILE_ENTER( MAIN_PYTHON );
Py_Initialize();
{
static PyMethodDef BjamMethods[] = {
{"call", bjam_call, METH_VARARGS,
"Call the specified bjam rule."},
{"import_rule", bjam_import_rule, METH_VARARGS,
"Imports Python callable to bjam."},
{"define_action", bjam_define_action, METH_VARARGS,
"Defines a command line action."},
{"variable", bjam_variable, METH_VARARGS,
"Obtains a variable from bjam's global module."},
{"backtrace", bjam_backtrace, METH_VARARGS,
"Returns bjam backtrace from the last call into Python."},
{NULL, NULL, 0, NULL}
};
Py_InitModule( "bjam", BjamMethods );
Py_InitModule( "bjam", BjamMethods );
}
PROFILE_EXIT( MAIN_PYTHON );
}
PROFILE_EXIT(MAIN_PYTHON);
}
#endif
#endif
#ifndef NDEBUG
run_unit_tests();
run_unit_tests();
#endif
#if YYDEBUG != 0
if ( DEBUG_PARSE )
yydebug = 1;
if ( DEBUG_PARSE )
yydebug = 1;
#endif
/* Set JAMDATE first */
/* Set JAMDATE. */
var_set( "JAMDATE", list_new( L0, outf_time(time(0)) ), VAR_SET );
var_set( "JAMDATE", list_new( L0, outf_time(time(0)) ), VAR_SET );
/* Set JAM_VERSION. */
var_set( "JAM_VERSION",
list_new( list_new( list_new( L0,
newstr( VERSION_MAJOR_SYM ) ),
newstr( VERSION_MINOR_SYM ) ),
newstr( VERSION_PATCH_SYM ) ),
VAR_SET );
var_set( "JAM_VERSION",
list_new( list_new( list_new( L0, newstr( VERSION_MAJOR_SYM ) ),
newstr( VERSION_MINOR_SYM ) ),
newstr( VERSION_PATCH_SYM ) ),
VAR_SET );
/* And JAMUNAME */
# ifdef unix
{
struct utsname u;
if( uname( &u ) >= 0 )
/* Set JAMUNAME. */
#ifdef unix
{
var_set( "JAMUNAME",
list_new(
struct utsname u;
if ( uname( &u ) >= 0 )
{
var_set( "JAMUNAME",
list_new(
list_new(
list_new(
list_new( L0,
newstr( u.sysname ) ),
newstr( u.nodename ) ),
newstr( u.release ) ),
newstr( u.version ) ),
newstr( u.machine ) ), VAR_SET );
}
}
# endif /* unix */
/* load up environment variables */
/* first into global module, with splitting, for backward compatibility */
var_defines( use_environ, 1 );
/* then into .ENVIRON, without splitting */
enter_module( bindmodule(".ENVIRON") );
var_defines( use_environ, 0 );
exit_module( bindmodule(".ENVIRON") );
/*
* Jam defined variables OS, OSPLAT
* We load them after environment, so that
* setting OS in environment does not
* change Jam notion of the current platform.
*/
var_defines( othersyms, 1 );
/* Load up variables set on command line. */
for( n = 0; s = getoptval( optv, 's', n ); n++ )
{
char *symv[2];
symv[0] = s;
symv[1] = 0;
var_defines( symv, 1 );
enter_module( bindmodule(".ENVIRON") );
var_defines( symv, 0 );
exit_module( bindmodule(".ENVIRON") );
}
/* Set the ARGV to reflect the complete list of arguments of invocation. */
for ( n = 0; n < arg_c; ++n )
{
var_set( "ARGV", list_new( L0, newstr( arg_v[n] ) ), VAR_APPEND );
}
/* Initialize built-in rules */
load_builtins();
/* Add the targets in the command line to update list */
for ( n = 1; n < arg_c; ++n )
{
if ( arg_v[n][0] == '-' )
{
char *f = "-:l:d:j:f:gs:t:ano:qv";
for( ; *f; f++ ) if( *f == arg_v[n][1] ) break;
if ( f[1] == ':' && arg_v[n][2] == '\0' ) { ++n; }
}
else
{
mark_target_for_updating(arg_v[n]);
}
}
/* Parse ruleset */
{
FRAME frame[1];
frame_init( frame );
for( n = 0; s = getoptval( optv, 'f', n ); n++ )
parse_file( s, frame );
if( !n )
parse_file( "+", frame );
}
status = yyanyerrors();
/* Manually touch -t targets */
for( n = 0; s = getoptval( optv, 't', n ); n++ )
touchtarget( s );
/* If an output file is specified, set globs.cmdout to that */
if( s = getoptval( optv, 'o', 0 ) )
{
if( !( globs.cmdout = fopen( s, "w" ) ) )
{
printf( "Failed to write to '%s'\n", s );
exit( EXITBAD );
}
globs.noexec++;
}
/* Now make target */
{
PROFILE_ENTER(MAIN_MAKE);
LIST * targets = targets_to_update();
if ( !targets )
{
status |= make( 1, &all, anyhow );
}
else
{
int targets_count = list_length(targets);
const char **targets2 = (const char **)BJAM_MALLOC(targets_count * sizeof(char *));
int n = 0;
for ( ; targets; targets = list_next(targets) )
{
targets2[n++] = targets->string;
list_new(
list_new( L0,
newstr( u.sysname ) ),
newstr( u.nodename ) ),
newstr( u.release ) ),
newstr( u.version ) ),
newstr( u.machine ) ), VAR_SET );
}
status |= make( targets_count, targets2, anyhow );
free(targets);
}
#endif /* unix */
/* Load up environment variables. */
/* First into the global module, with splitting, for backward
* compatibility.
*/
var_defines( use_environ, 1 );
/* Then into .ENVIRON, without splitting. */
enter_module( bindmodule(".ENVIRON") );
var_defines( use_environ, 0 );
exit_module( bindmodule(".ENVIRON") );
/*
* Jam defined variables OS & OSPLAT. We load them after environment, so
* that setting OS in environment does not change Jam's notion of the
* current platform.
*/
var_defines( othersyms, 1 );
/* Load up variables set on command line. */
for ( n = 0; s = getoptval( optv, 's', n ); ++n )
{
char *symv[2];
symv[ 0 ] = s;
symv[ 1 ] = 0;
var_defines( symv, 1 );
enter_module( bindmodule(".ENVIRON") );
var_defines( symv, 0 );
exit_module( bindmodule(".ENVIRON") );
}
PROFILE_EXIT(MAIN_MAKE);
/* Set the ARGV to reflect the complete list of arguments of invocation.
*/
for ( n = 0; n < arg_c; ++n )
var_set( "ARGV", list_new( L0, newstr( arg_v[n] ) ), VAR_APPEND );
/* Initialize built-in rules. */
load_builtins();
/* Add the targets in the command line to the update list. */
for ( n = 1; n < arg_c; ++n )
{
if ( arg_v[ n ][ 0 ] == '-' )
{
char * f = "-:l:d:j:f:gs:t:ano:qv";
for ( ; *f; ++f ) if ( *f == arg_v[ n ][ 1 ] ) break;
if ( ( f[ 1 ] == ':' ) && ( arg_v[ n ][ 2 ] == '\0' ) ) ++n;
}
else
{
mark_target_for_updating( arg_v[ n ] );
}
}
/* Parse ruleset. */
{
FRAME frame[ 1 ];
frame_init( frame );
for ( n = 0; s = getoptval( optv, 'f', n ); ++n )
parse_file( s, frame );
if ( !n )
parse_file( "+", frame );
}
status = yyanyerrors();
/* Manually touch -t targets. */
for ( n = 0; s = getoptval( optv, 't', n ); ++n )
touch_target( s );
/* If an output file is specified, set globs.cmdout to that. */
if ( s = getoptval( optv, 'o', 0 ) )
{
if ( !( globs.cmdout = fopen( s, "w" ) ) )
{
printf( "Failed to write to '%s'\n", s );
exit( EXITBAD );
}
++globs.noexec;
}
/* Now make target. */
{
PROFILE_ENTER( MAIN_MAKE );
LIST * targets = targets_to_update();
if ( !targets )
{
status |= make( 1, &all, anyhow );
}
else
{
int targets_count = list_length( targets );
const char * * targets2 = (const char * *)
BJAM_MALLOC( targets_count * sizeof( char * ) );
int n = 0;
for ( ; targets; targets = list_next( targets ) )
targets2[ n++ ] = targets->string;
status |= make( targets_count, targets2, anyhow );
free( targets );
}
PROFILE_EXIT( MAIN_MAKE );
}
PROFILE_EXIT( MAIN );
}
PROFILE_EXIT(MAIN); }
if ( DEBUG_PROFILE )
profile_dump();
/* Widely scattered cleanup */
/* Widely scattered cleanup. */
var_done();
file_done();
donerules();
donestamps();
donestr();
rules_done();
stamps_done();
str_done();
/* close cmdout */
if( globs.cmdout )
/* Close cmdout. */
if ( globs.cmdout )
fclose( globs.cmdout );
#ifdef HAVE_PYTHON

View File

@@ -49,80 +49,81 @@
* VMS, OPENVMS
*/
# ifdef VMS
#ifdef VMS
# include <types.h>
# include <file.h>
# include <stat.h>
# include <stdio.h>
# include <ctype.h>
# include <stdlib.h>
# include <signal.h>
# include <string.h>
# include <time.h>
# include <unistd.h>
# include <unixlib.h>
#include <types.h>
#include <file.h>
#include <stat.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <unixlib.h>
# define OSMINOR "OS=VMS"
# define OSMAJOR "VMS=true"
# define OS_VMS
# define MAXLINE 1024 /* longest 'together' actions */
# define SPLITPATH ','
# define EXITOK 1
# define EXITBAD 0
# define DOWNSHIFT_PATHS
#define OSMINOR "OS=VMS"
#define OSMAJOR "VMS=true"
#define OS_VMS
#define MAXLINE 1024 /* longest 'together' actions */
#define SPLITPATH ','
#define EXITOK 1
#define EXITBAD 0
#define DOWNSHIFT_PATHS
/* This may be inaccurate */
# ifndef __DECC
# define OSPLAT "OSPLAT=VAX"
# endif
/* This may be inaccurate. */
#ifndef __DECC
#define OSPLAT "OSPLAT=VAX"
#endif
# endif
#endif
/*
* Windows NT
*/
# ifdef NT
#ifdef NT
# include <fcntl.h>
# include <stdlib.h>
# include <stdio.h>
# include <ctype.h>
# include <malloc.h>
# ifndef __MWERKS__
# include <memory.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <malloc.h>
#ifndef __MWERKS__
#include <memory.h>
#endif
# include <signal.h>
# include <string.h>
# include <time.h>
#include <signal.h>
#include <string.h>
#include <time.h>
# define OSMAJOR "NT=true"
# define OSMINOR "OS=NT"
# define OS_NT
# define SPLITPATH ';'
/* Windows NT 3.51 only allows 996 chars per line, but we deal */
/* with problem in "execnt.c". */
# define MAXLINE (maxline()) /* longest 'together' actions */
# define USE_EXECNT
# define USE_PATHUNIX
# define PATH_DELIM '\\'
# define DOWNSHIFT_PATHS
#define OSMAJOR "NT=true"
#define OSMINOR "OS=NT"
#define OS_NT
#define SPLITPATH ';'
/* Windows NT 3.51 only allows 996 chars per line, but we deal with the problem
* in "execnt.c".
*/
#define MAXLINE (maxline()) /* longest 'together' actions */
#define USE_EXECNT
#define USE_PATHUNIX
#define PATH_DELIM '\\'
#define DOWNSHIFT_PATHS
/* AS400 cross-compile from NT */
/* AS400 cross-compile from NT. */
# ifdef AS400
# undef OSMINOR
# undef OSMAJOR
# define OSMAJOR "AS400=true"
# define OSMINOR "OS=AS400"
# define OS_AS400
# endif
#ifdef AS400
#undef OSMINOR
#undef OSMAJOR
#define OSMAJOR "AS400=true"
#define OSMINOR "OS=AS400"
#define OS_AS400
#endif
/* Metrowerks Standard Library on Windows. */
# ifdef __MSL__
#undef HAVE_POPEN
#ifdef __MSL__
#undef HAVE_POPEN
#endif
# endif
@@ -131,435 +132,440 @@
* Windows MingW32
*/
# ifdef MINGW
#ifdef MINGW
# include <fcntl.h>
# include <stdlib.h>
# include <stdio.h>
# include <ctype.h>
# include <malloc.h>
# include <memory.h>
# include <signal.h>
# include <string.h>
# include <time.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <malloc.h>
#include <memory.h>
#include <signal.h>
#include <string.h>
#include <time.h>
# define OSMAJOR "MINGW=true"
# define OSMINOR "OS=MINGW"
# define OS_NT
# define SPLITPATH ';'
# define MAXLINE 996 /* longest 'together' actions */
# define USE_EXECUNIX
# define USE_PATHUNIX
# define PATH_DELIM '\\'
# define DOWNSHIFT_PATHS
#define OSMAJOR "MINGW=true"
#define OSMINOR "OS=MINGW"
#define OS_NT
#define SPLITPATH ';'
#define MAXLINE 996 /* longest 'together' actions */
#define USE_EXECUNIX
#define USE_PATHUNIX
#define PATH_DELIM '\\'
#define DOWNSHIFT_PATHS
# endif
#endif
/*
* OS2
*/
# ifdef __OS2__
#ifdef __OS2__
# include <fcntl.h>
# include <stdlib.h>
# include <stdio.h>
# include <ctype.h>
# include <malloc.h>
# include <signal.h>
# include <string.h>
# include <time.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <malloc.h>
#include <signal.h>
#include <string.h>
#include <time.h>
# define OSMAJOR "OS2=true"
# define OSMINOR "OS=OS2"
# define OS_OS2
# define SPLITPATH ';'
# define MAXLINE 996 /* longest 'together' actions */
# define USE_EXECUNIX
# define USE_PATHUNIX
# define PATH_DELIM '\\'
# define DOWNSHIFT_PATHS
#define OSMAJOR "OS2=true"
#define OSMINOR "OS=OS2"
#define OS_OS2
#define SPLITPATH ';'
#define MAXLINE 996 /* longest 'together' actions */
#define USE_EXECUNIX
#define USE_PATHUNIX
#define PATH_DELIM '\\'
#define DOWNSHIFT_PATHS
# ifdef __EMX__
# define USE_FILEUNIX
# endif
#ifdef __EMX__
#define USE_FILEUNIX
#endif
# endif
#endif
/*
* Macintosh MPW
*/
# ifdef macintosh
#ifdef macintosh
# include <time.h>
# include <stdlib.h>
# include <string.h>
# include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
# define OSMAJOR "MAC=true"
# define OSMINOR "OS=MAC"
# define OS_MAC
# define SPLITPATH ','
#define OSMAJOR "MAC=true"
#define OSMINOR "OS=MAC"
#define OS_MAC
#define SPLITPATH ','
# endif
#endif
/*
* God fearing UNIX
* God fearing UNIX.
*/
# ifndef OSMINOR
#ifndef OSMINOR
# define OSMAJOR "UNIX=true"
# define USE_EXECUNIX
# define USE_FILEUNIX
# define USE_PATHUNIX
# define PATH_DELIM '/'
#define OSMAJOR "UNIX=true"
#define USE_EXECUNIX
#define USE_FILEUNIX
#define USE_PATHUNIX
#define PATH_DELIM '/'
# ifdef _AIX
# define unix
# define MAXLINE 23552 /* 24k - 1k, longest 'together' actions */
# define OSMINOR "OS=AIX"
# define OS_AIX
# define NO_VFORK
# endif
# ifdef AMIGA
# define OSMINOR "OS=AMIGA"
# define OS_AMIGA
# endif
# ifdef __BEOS__
# define unix
# define OSMINOR "OS=BEOS"
# define OS_BEOS
# define NO_VFORK
# endif
# ifdef __bsdi__
# define OSMINOR "OS=BSDI"
# define OS_BSDI
# endif
# if defined (COHERENT) && defined (_I386)
# define OSMINOR "OS=COHERENT"
# define OS_COHERENT
# define NO_VFORK
# endif
# if defined(__cygwin__) || defined(__CYGWIN__)
# define OSMINOR "OS=CYGWIN"
# define OS_CYGWIN
# endif
# if defined(__FreeBSD__) && !defined(__DragonFly__)
# define OSMINOR "OS=FREEBSD"
# define OS_FREEBSD
# endif
# ifdef __DragonFly__
# define OSMINOR "OS=DRAGONFLYBSD"
# define OS_DRAGONFLYBSD
# endif
# ifdef __DGUX__
# define OSMINOR "OS=DGUX"
# define OS_DGUX
# endif
# ifdef __hpux
# define OSMINOR "OS=HPUX"
# define OS_HPUX
# endif
# ifdef __OPENNT
# define unix
# define OSMINOR "OS=INTERIX"
# define OS_INTERIX
# define NO_VFORK
# endif
# ifdef __sgi
# define OSMINOR "OS=IRIX"
# define OS_IRIX
# define NO_VFORK
# endif
# ifdef __ISC
# define OSMINOR "OS=ISC"
# define OS_ISC
# define NO_VFORK
# endif
# ifdef linux
# define OSMINOR "OS=LINUX"
# define OS_LINUX
# endif
# ifdef __Lynx__
# define OSMINOR "OS=LYNX"
# define OS_LYNX
# define NO_VFORK
# define unix
# endif
# ifdef __MACHTEN__
# define OSMINOR "OS=MACHTEN"
# define OS_MACHTEN
# endif
# ifdef mpeix
# define unix
# define OSMINOR "OS=MPEIX"
# define OS_MPEIX
# define NO_VFORK
# endif
# ifdef __MVS__
# define unix
# define OSMINOR "OS=MVS"
# define OS_MVS
# endif
# ifdef _ATT4
# define OSMINOR "OS=NCR"
# define OS_NCR
# endif
# ifdef __NetBSD__
# define unix
# define OSMINOR "OS=NETBSD"
# define OS_NETBSD
# define NO_VFORK
# endif
# ifdef __QNX__
# define unix
# ifdef __QNXNTO__
# define OSMINOR "OS=QNXNTO"
# define OS_QNXNTO
# else
# define OSMINOR "OS=QNX"
# define OS_QNX
# define NO_VFORK
# define MAXLINE 996
# endif
# endif
# ifdef NeXT
# ifdef __APPLE__
# define OSMINOR "OS=RHAPSODY"
# define OS_RHAPSODY
# else
# define OSMINOR "OS=NEXT"
# define OS_NEXT
# endif
# endif
# ifdef __APPLE__
# define unix
# define OSMINOR "OS=MACOSX"
# define OS_MACOSX
# endif
# ifdef __osf__
# ifndef unix
# define unix
# endif
# define OSMINOR "OS=OSF"
# define OS_OSF
# endif
# ifdef _SEQUENT_
# define OSMINOR "OS=PTX"
# define OS_PTX
# endif
# ifdef M_XENIX
# define OSMINOR "OS=SCO"
# define OS_SCO
# define NO_VFORK
# endif
# ifdef sinix
# define unix
# define OSMINOR "OS=SINIX"
# define OS_SINIX
# endif
# ifdef sun
# if defined(__svr4__) || defined(__SVR4)
# define OSMINOR "OS=SOLARIS"
# define OS_SOLARIS
# else
# define OSMINOR "OS=SUNOS"
# define OS_SUNOS
# endif
# endif
# ifdef ultrix
# define OSMINOR "OS=ULTRIX"
# define OS_ULTRIX
# endif
# ifdef _UNICOS
# define OSMINOR "OS=UNICOS"
# define OS_UNICOS
# endif
# if defined(__USLC__) && !defined(M_XENIX)
# define OSMINOR "OS=UNIXWARE"
# define OS_UNIXWARE
# endif
# ifdef __OpenBSD__
# define OSMINOR "OS=OPENBSD"
# define OS_OPENBSD
# define unix
# endif
# if defined (__FreeBSD_kernel__) && !defined(__FreeBSD__)
# define OSMINOR "OS=KFREEBSD"
# define OS_KFREEBSD
# endif
# ifndef OSMINOR
# define OSMINOR "OS=UNKNOWN"
# endif
#ifdef _AIX
#define unix
#define MAXLINE 23552 /* 24k - 1k, longest 'together' actions */
#define OSMINOR "OS=AIX"
#define OS_AIX
#define NO_VFORK
#endif
#ifdef AMIGA
#define OSMINOR "OS=AMIGA"
#define OS_AMIGA
#endif
#ifdef __BEOS__
#define unix
#define OSMINOR "OS=BEOS"
#define OS_BEOS
#define NO_VFORK
#endif
#ifdef __bsdi__
#define OSMINOR "OS=BSDI"
#define OS_BSDI
#endif
#if defined (COHERENT) && defined (_I386)
#define OSMINOR "OS=COHERENT"
#define OS_COHERENT
#define NO_VFORK
#endif
#if defined(__cygwin__) || defined(__CYGWIN__)
#define OSMINOR "OS=CYGWIN"
#define OS_CYGWIN
#endif
#if defined(__FreeBSD__) && !defined(__DragonFly__)
#define OSMINOR "OS=FREEBSD"
#define OS_FREEBSD
#endif
#ifdef __DragonFly__
#define OSMINOR "OS=DRAGONFLYBSD"
#define OS_DRAGONFLYBSD
#endif
#ifdef __DGUX__
#define OSMINOR "OS=DGUX"
#define OS_DGUX
#endif
#ifdef __hpux
#define OSMINOR "OS=HPUX"
#define OS_HPUX
#endif
#ifdef __OPENNT
#define unix
#define OSMINOR "OS=INTERIX"
#define OS_INTERIX
#define NO_VFORK
#endif
#ifdef __sgi
#define OSMINOR "OS=IRIX"
#define OS_IRIX
#define NO_VFORK
#endif
#ifdef __ISC
#define OSMINOR "OS=ISC"
#define OS_ISC
#define NO_VFORK
#endif
#ifdef linux
#define OSMINOR "OS=LINUX"
#define OS_LINUX
#endif
#ifdef __Lynx__
#define OSMINOR "OS=LYNX"
#define OS_LYNX
#define NO_VFORK
#define unix
#endif
#ifdef __MACHTEN__
#define OSMINOR "OS=MACHTEN"
#define OS_MACHTEN
#endif
#ifdef mpeix
#define unix
#define OSMINOR "OS=MPEIX"
#define OS_MPEIX
#define NO_VFORK
#endif
#ifdef __MVS__
#define unix
#define OSMINOR "OS=MVS"
#define OS_MVS
#endif
#ifdef _ATT4
#define OSMINOR "OS=NCR"
#define OS_NCR
#endif
#ifdef __NetBSD__
#define unix
#define OSMINOR "OS=NETBSD"
#define OS_NETBSD
#define NO_VFORK
#endif
#ifdef __QNX__
#define unix
#ifdef __QNXNTO__
#define OSMINOR "OS=QNXNTO"
#define OS_QNXNTO
#else
#define OSMINOR "OS=QNX"
#define OS_QNX
#define NO_VFORK
#define MAXLINE 996
#endif
#endif
#ifdef NeXT
#ifdef __APPLE__
#define OSMINOR "OS=RHAPSODY"
#define OS_RHAPSODY
#else
#define OSMINOR "OS=NEXT"
#define OS_NEXT
#endif
#endif
#ifdef __APPLE__
#define unix
#define OSMINOR "OS=MACOSX"
#define OS_MACOSX
#endif
#ifdef __osf__
#ifndef unix
#define unix
#endif
#define OSMINOR "OS=OSF"
#define OS_OSF
#endif
#ifdef _SEQUENT_
#define OSMINOR "OS=PTX"
#define OS_PTX
#endif
#ifdef M_XENIX
#define OSMINOR "OS=SCO"
#define OS_SCO
#define NO_VFORK
#endif
#ifdef sinix
#define unix
#define OSMINOR "OS=SINIX"
#define OS_SINIX
#endif
#ifdef sun
#if defined(__svr4__) || defined(__SVR4)
#define OSMINOR "OS=SOLARIS"
#define OS_SOLARIS
#else
#define OSMINOR "OS=SUNOS"
#define OS_SUNOS
#endif
#endif
#ifdef ultrix
#define OSMINOR "OS=ULTRIX"
#define OS_ULTRIX
#endif
#ifdef _UNICOS
#define OSMINOR "OS=UNICOS"
#define OS_UNICOS
#endif
#if defined(__USLC__) && !defined(M_XENIX)
#define OSMINOR "OS=UNIXWARE"
#define OS_UNIXWARE
#endif
#ifdef __OpenBSD__
#define OSMINOR "OS=OPENBSD"
#define OS_OPENBSD
#define unix
#endif
#if defined (__FreeBSD_kernel__) && !defined(__FreeBSD__)
#define OSMINOR "OS=KFREEBSD"
#define OS_KFREEBSD
#endif
#ifndef OSMINOR
#define OSMINOR "OS=UNKNOWN"
#endif
/* All the UNIX includes */
# include <sys/types.h>
# include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
# ifndef OS_MPEIX
# include <sys/file.h>
# endif
#ifndef OS_MPEIX
#include <sys/file.h>
#endif
# include <fcntl.h>
# include <stdio.h>
# include <ctype.h>
# include <signal.h>
# include <string.h>
# include <time.h>
#include <fcntl.h>
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#include <string.h>
#include <time.h>
# ifndef OS_QNX
# include <memory.h>
# endif
#ifndef OS_QNX
#include <memory.h>
#endif
# ifndef OS_ULTRIX
# include <stdlib.h>
# endif
#ifndef OS_ULTRIX
#include <stdlib.h>
#endif
# if !defined(OS_BSDI) && \
!defined(OS_FREEBSD) && \
!defined(OS_DRAGONFLYBSD) && \
!defined(OS_NEXT) && \
!defined(OS_MACHTEN) && \
!defined(OS_MACOSX) && \
!defined(OS_RHAPSODY) && \
!defined(OS_MVS) && \
!defined(OS_OPENBSD)
# include <malloc.h>
# endif
#if !defined( OS_BSDI ) && \
!defined( OS_FREEBSD ) && \
!defined( OS_DRAGONFLYBSD ) && \
!defined( OS_NEXT ) && \
!defined( OS_MACHTEN ) && \
!defined( OS_MACOSX ) && \
!defined( OS_RHAPSODY ) && \
!defined( OS_MVS ) && \
!defined( OS_OPENBSD )
#include <malloc.h>
#endif
# endif
#endif
/*
* OSPLAT definitions - suppressed when it's a one-of-a-kind
* OSPLAT definitions - suppressed when it is a one-of-a-kind.
*/
# if defined( _M_PPC ) || \
defined( PPC ) || \
defined( ppc ) || \
defined( __powerpc__ ) || \
defined( __ppc__ )
# define OSPLAT "OSPLAT=PPC"
# endif
#if defined( _M_PPC ) || \
defined( PPC ) || \
defined( ppc ) || \
defined( __powerpc__ ) || \
defined( __ppc__ )
#define OSPLAT "OSPLAT=PPC"
#endif
# if defined( _ALPHA_ ) || \
defined( __alpha__ )
# define OSPLAT "OSPLAT=AXP"
# endif
#if defined( _ALPHA_ ) || \
defined( __alpha__ )
#define OSPLAT "OSPLAT=AXP"
#endif
# if defined( _i386_ ) || \
defined( __i386__ ) || \
defined( _M_IX86 )
# define OSPLAT "OSPLAT=X86"
# endif
#if defined( _i386_ ) || \
defined( __i386__ ) || \
defined( _M_IX86 )
#define OSPLAT "OSPLAT=X86"
#endif
# if defined( __ia64__ ) || defined( __IA64__ ) || defined( __ia64 )
# define OSPLAT "OSPLAT=IA64"
# endif
#if defined( __ia64__ ) || \
defined( __IA64__ ) || \
defined( __ia64 )
#define OSPLAT "OSPLAT=IA64"
#endif
# if \
defined( __x86_64__ ) || \
defined( __amd64__ ) || \
defined( _M_AMD64 )
# define OSPLAT "OSPLAT=X86_64"
# endif
#if defined( __x86_64__ ) || \
defined( __amd64__ ) || \
defined( _M_AMD64 )
#define OSPLAT "OSPLAT=X86_64"
#endif
# ifdef __sparc__
# define OSPLAT "OSPLAT=SPARC"
# endif
#ifdef __sparc__
#define OSPLAT "OSPLAT=SPARC"
#endif
# ifdef __mips__
# define OSPLAT "OSPLAT=MIPS"
# endif
#ifdef __mips__
#define OSPLAT "OSPLAT=MIPS"
#endif
# ifdef __arm__
# define OSPLAT "OSPLAT=ARM"
# endif
#ifdef __arm__
#define OSPLAT "OSPLAT=ARM"
#endif
# ifdef __s390__
# define OSPLAT "OSPLAT=390"
# endif
#ifdef __s390__
#define OSPLAT "OSPLAT=390"
#endif
# ifdef __hppa
# define OSPLAT "OSPLAT=PARISC"
# endif
#ifdef __hppa
#define OSPLAT "OSPLAT=PARISC"
#endif
# ifndef OSPLAT
# define OSPLAT ""
# endif
#ifndef OSPLAT
#define OSPLAT ""
#endif
/*
* Jam implementation misc.
*/
# ifndef MAXLINE
# define MAXLINE 102400 /* longest 'together' actions' */
# endif
#ifndef MAXLINE
#define MAXLINE 102400 /* longest 'together' actions' */
#endif
# ifndef EXITOK
# define EXITOK 0
# define EXITBAD 1
# endif
#ifndef EXITOK
#define EXITOK 0
#define EXITBAD 1
#endif
# ifndef SPLITPATH
# define SPLITPATH ':'
# endif
#ifndef SPLITPATH
#define SPLITPATH ':'
#endif
/* You probably don't need to muck with these. */
/* You probably do not need to muck with these. */
# define MAXSYM 1024 /* longest symbol in the environment */
# define MAXJPATH 1024 /* longest filename */
#define MAXSYM 1024 /* longest symbol in the environment */
#define MAXJPATH 1024 /* longest filename */
# define MAXJOBS 64 /* silently enforce -j limit */
# define MAXARGC 32 /* words in $(JAMSHELL) */
#define MAXJOBS 64 /* silently enforced -j limit */
#define MAXARGC 32 /* words in $(JAMSHELL) */
/* Jam private definitions below. */
# define DEBUG_MAX 14
#define DEBUG_MAX 14
struct globs {
int noexec;
int jobs;
int quitquick;
int newestfirst; /* build newest sources first */
int pipe_action;
char debug[DEBUG_MAX];
FILE *cmdout; /* print cmds, not run them */
long timeout; /* number of seconds to limit actions to, default 0 for no limit. */
int dart; /* output build and test results formatted for Dart */
} ;
struct globs
{
int noexec;
int jobs;
int quitquick;
int newestfirst; /* build newest sources first */
int pipe_action;
char debug[ DEBUG_MAX ];
FILE * cmdout; /* print cmds, not run them */
long timeout; /* number of seconds to limit actions to,
* default 0 for no limit.
*/
int dart; /* output build and test results formatted for Dart */
};
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_BIND ( globs.debug[ 3 ] ) /* show when files bound */
#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_BIND ( globs.debug[ 3 ] ) /* show when files bound */
# define DEBUG_EXECCMD ( globs.debug[ 4 ] ) /* show execcmds()'s work */
#define DEBUG_EXECCMD ( globs.debug[ 4 ] ) /* show execcmds()'s work */
# define DEBUG_COMPILE ( globs.debug[ 5 ] ) /* show rule invocations */
#define DEBUG_COMPILE ( globs.debug[ 5 ] ) /* show rule invocations */
# 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_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_VARSET ( globs.debug[ 7 ] ) /* show variable settings */
# define DEBUG_VARGET ( globs.debug[ 8 ] ) /* show variable fetches */
# define DEBUG_VAREXP ( globs.debug[ 8 ] ) /* show variable expansions */
# define DEBUG_IF ( globs.debug[ 8 ] ) /* show 'if' calculations */
# define DEBUG_LISTS ( globs.debug[ 9 ] ) /* show list manipulation */
# define DEBUG_SCAN ( globs.debug[ 9 ] ) /* show scanner tokens */
# define DEBUG_MEM ( globs.debug[ 9 ] ) /* show memory use */
#define DEBUG_VARSET ( globs.debug[ 7 ] ) /* show variable settings */
#define DEBUG_VARGET ( globs.debug[ 8 ] ) /* show variable fetches */
#define DEBUG_VAREXP ( globs.debug[ 8 ] ) /* show variable expansions */
#define DEBUG_IF ( globs.debug[ 8 ] ) /* show 'if' calculations */
#define DEBUG_LISTS ( globs.debug[ 9 ] ) /* show list manipulation */
#define DEBUG_SCAN ( globs.debug[ 9 ] ) /* show scanner tokens */
#define DEBUG_MEM ( globs.debug[ 9 ] ) /* show memory use */
# 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_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() */
/* Everyone gets the memory definitions. */
#include "mem.h"

View File

@@ -31,16 +31,13 @@ static LIST *freelist = 0; /* junkpile for list_free() */
* list_append() - append a list onto another one, returning total
*/
LIST *
list_append(
LIST *l,
LIST *nl )
LIST * list_append( LIST * l, LIST * nl )
{
if( !nl )
if ( !nl )
{
/* Just return l */
}
else if( !l )
else if ( !l )
{
l = nl;
}
@@ -58,21 +55,18 @@ list_append(
* list_new() - tack a string onto the end of a list of strings
*/
LIST *
list_new(
LIST *head,
char *string )
LIST * list_new( LIST * head, char * string )
{
LIST *l;
LIST * l;
if( DEBUG_LISTS )
if ( DEBUG_LISTS )
printf( "list > %s <\n", string );
/* Get list struct from freelist, if one available. */
/* Otherwise allocate. */
/* If from freelist, must free string first */
if( freelist )
if ( freelist )
{
l = freelist;
freestr( l->string );
@@ -87,7 +81,7 @@ list_new(
/* If adding to chain, tack us on. */
/* Tail must point to this new, last element. */
if( !head ) head = l;
if ( !head ) head = l;
else head->tail->next = l;
head->tail = l;
l->next = 0;
@@ -97,104 +91,96 @@ list_new(
return head;
}
/*
* list_copy() - copy a whole list of strings (nl) onto end of another (l)
* list_copy() - copy a whole list of strings (nl) onto end of another (l).
*/
LIST *
list_copy(
LIST *l,
LIST *nl )
LIST * list_copy( LIST * l, LIST * nl )
{
for( ; nl; nl = list_next( nl ) )
for ( ; nl; nl = list_next( nl ) )
l = list_new( l, copystr( nl->string ) );
return l;
}
/*
* list_sublist() - copy a subset of a list of strings
* list_sublist() - copy a subset of a list of strings.
*/
LIST *
list_sublist(
LIST *l,
int start,
int count )
LIST * list_sublist( LIST * l, int start, int count )
{
LIST *nl = 0;
for( ; l && start--; l = list_next( l ) )
;
for( ; l && count--; l = list_next( l ) )
LIST * nl = 0;
for ( ; l && start--; l = list_next( l ) );
for ( ; l && count--; l = list_next( l ) )
nl = list_new( nl, copystr( l->string ) );
return nl;
}
static int str_ptr_compare(const void *va, const void *vb)
static int str_ptr_compare( void const * va, void const * vb )
{
char* a = *( (char**)va );
char* b = *( (char**)vb );
char * a = *( (char * *)va );
char * b = *( (char * *)vb );
return strcmp(a, b);
}
LIST *
list_sort(
LIST *l)
{
int len, ii;
char** strings;
LIST* listp;
LIST* result = 0;
if (!l)
LIST * list_sort( LIST * l )
{
int len;
int ii;
char * * strings;
LIST * listp;
LIST * result = 0;
if ( !l )
return L0;
len = list_length(l);
strings = (char**)BJAM_MALLOC( len * sizeof(char*) );
len = list_length( l );
strings = (char * *)BJAM_MALLOC( len * sizeof(char*) );
listp = l;
for (ii = 0; ii < len; ++ii) {
strings[ii] = listp->string;
for ( ii = 0; ii < len; ++ii )
{
strings[ ii ] = listp->string;
listp = listp->next;
}
qsort(strings, len, sizeof(char*), str_ptr_compare);
qsort( strings, len, sizeof( char * ), str_ptr_compare );
for (ii = 0; ii < len; ++ii) {
result = list_append( result, list_new(0, strings[ii]) );
}
for ( ii = 0; ii < len; ++ii )
result = list_append( result, list_new( 0, strings[ ii ] ) );
BJAM_FREE(strings);
BJAM_FREE( strings );
return result;
}
/*
* list_free() - free a list of strings
*/
void
list_free( LIST *head )
void list_free( LIST * head )
{
/* Just tack onto freelist. */
if( head )
if ( head )
{
head->tail->next = freelist;
freelist = head;
}
}
/*
* list_pop_front() - remove the front element from a list of strings
*/
LIST * list_pop_front( LIST *l )
LIST * list_pop_front( LIST * l )
{
LIST * result = l->next;
if( result )
if ( result )
{
result->tail = l->tail;
l->next = L0;
@@ -204,56 +190,53 @@ LIST * list_pop_front( LIST *l )
return result;
}
/*
* list_print() - print a list of strings to stdout
*/
void
list_print( LIST *l )
void list_print( LIST * l )
{
LIST *p = 0;
for( ; l; p = l, l = list_next( l ) )
if ( p )
printf( "%s ", p->string );
LIST * p = 0;
for ( ; l; p = l, l = list_next( l ) )
if ( p )
printf( "%s", p->string );
printf( "%s ", p->string );
if ( p )
printf( "%s", p->string );
}
/*
* list_length() - return the number of items in the list
*/
int
list_length( LIST *l )
int list_length( LIST * l )
{
int n = 0;
for( ; l; l = list_next( l ), ++n )
;
for ( ; l; l = list_next( l ), ++n );
return n;
}
int
list_in(LIST* l, char* value)
int list_in( LIST * l, char * value )
{
for(; l; l = l->next)
if (strcmp(l->string, value) == 0)
for ( ; l; l = l->next )
if ( strcmp( l->string, value ) == 0 )
return 1;
return 0;
}
LIST *
list_unique( LIST *sorted_list)
{
LIST* result = 0;
LIST* last_added = 0;
for(; sorted_list; sorted_list = sorted_list->next)
LIST * list_unique( LIST * sorted_list )
{
LIST * result = 0;
LIST * last_added = 0;
for ( ; sorted_list; sorted_list = sorted_list->next )
{
if (!last_added || strcmp(sorted_list->string, last_added->string) != 0)
if ( !last_added || strcmp( sorted_list->string, last_added->string ) != 0 )
{
result = list_new(result, sorted_list->string);
result = list_new( result, sorted_list->string );
last_added = sorted_list;
}
}
@@ -262,68 +245,61 @@ list_unique( LIST *sorted_list)
/*
* lol_init() - initialize a LOL (list of lists)
* lol_init() - initialize a LOL (list of lists).
*/
void
lol_init( LOL *lol )
void lol_init( LOL * lol )
{
lol->count = 0;
}
/*
* lol_add() - append a LIST onto an LOL
* lol_add() - append a LIST onto an LOL.
*/
void
lol_add(
LOL *lol,
LIST *l )
void lol_add( LOL * lol, LIST * l )
{
if( lol->count < LOL_MAX )
if ( lol->count < LOL_MAX )
lol->list[ lol->count++ ] = l;
}
/*
* lol_free() - free the LOL and its LISTs
* lol_free() - free the LOL and its LISTs.
*/
void
lol_free( LOL *lol )
void lol_free( LOL * lol )
{
int i;
for( i = 0; i < lol->count; i++ )
list_free( lol->list[i] );
for ( i = 0; i < lol->count; ++i )
list_free( lol->list[ i ] );
lol->count = 0;
}
/*
* lol_get() - return one of the LISTs in the LOL
* lol_get() - return one of the LISTs in the LOL.
*/
LIST *
lol_get(
LOL *lol,
int i )
LIST * lol_get( LOL * lol, int i )
{
return i < lol->count ? lol->list[i] : 0;
return i < lol->count ? lol->list[ i ] : 0;
}
/*
* lol_print() - debug print LISTS separated by ":"
* lol_print() - debug print LISTS separated by ":".
*/
void
lol_print( LOL *lol )
void lol_print( LOL * lol )
{
int i;
for( i = 0; i < lol->count; i++ )
for ( i = 0; i < lol->count; ++i )
{
if( i )
printf( " : " );
list_print( lol->list[i] );
if ( i )
printf( " : " );
list_print( lol->list[ i ] );
}
}

View File

@@ -55,7 +55,7 @@ struct _list {
LIST *next;
LIST *tail; /* only valid in head node */
char *string; /* private copy */
} ;
};
/*
* LOL - list of LISTs
@@ -68,7 +68,7 @@ typedef struct _lol LOL;
struct _lol {
int count;
LIST *list[ LOL_MAX ];
} ;
};
LIST * list_append( LIST *l, LIST *nl );
LIST * list_copy( LIST *l, LIST *nl );

View File

@@ -11,16 +11,15 @@
*/
/*
* make.c - bring a target up to date, once rules are in place
* make.c - bring a target up to date, once rules are in place.
*
* This modules controls the execution of rules to bring a target and
* its dependencies up to date. It is invoked after the targets, rules,
* et. al. described in rules.h are created by the interpreting of the
* jam files.
* This modules controls the execution of rules to bring a target and its
* dependencies up to date. It is invoked after the targets, rules, et. al.
* described in rules.h are created by the interpreting jam files.
*
* This file contains the main make() entry point and the first pass
* make0(). The second pass, make1(), which actually does the command
* execution, is in make1.c.
* This file contains the main make() entry point and the first pass make0().
* The second pass, make1(), which actually does the command execution, is in
* make1.c.
*
* External routines:
* make() - make a target, given its name
@@ -29,91 +28,89 @@
* 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
* 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 aren't seen as dependents on themselves.
* 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)
* 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 "jam.h"
# include "lists.h"
# include "parse.h"
# include "variable.h"
# include "rules.h"
#include "lists.h"
#include "parse.h"
#include "variable.h"
#include "rules.h"
#ifdef OPT_HEADER_CACHE_EXT
# include "hcache.h"
#include "hcache.h"
#endif
# include "search.h"
# include "newstr.h"
# include "make.h"
# include "headers.h"
# include "command.h"
# include <assert.h>
#include "search.h"
#include "newstr.h"
#include "make.h"
#include "headers.h"
#include "command.h"
#include <assert.h>
# ifndef max
# define max( a,b ) ((a)>(b)?(a):(b))
# endif
#ifndef max
#define max( a,b ) ((a)>(b)?(a):(b))
#endif
static TARGETS *make0sort( TARGETS *c );
static TARGETS * make0sort( TARGETS * c );
#ifdef OPT_GRAPH_DEBUG_EXT
static void dependGraphOutput( TARGET *t, int depth );
static void dependGraphOutput( TARGET * t, int depth );
#endif
static const char *target_fate[] =
static const char * target_fate[] =
{
"init", /* T_FATE_INIT */
"making", /* T_FATE_MAKING */
"stable", /* T_FATE_STABLE */
"newer", /* T_FATE_NEWER */
"temp", /* T_FATE_ISTMP */
"touched", /* T_FATE_TOUCHED */
"rebuild", /* T_FATE_REBUILD */
"missing", /* T_FATE_MISSING */
"needtmp", /* T_FATE_NEEDTMP */
"init", /* T_FATE_INIT */
"making", /* T_FATE_MAKING */
"stable", /* T_FATE_STABLE */
"newer", /* T_FATE_NEWER */
"temp", /* T_FATE_ISTMP */
"touched", /* T_FATE_TOUCHED */
"rebuild", /* T_FATE_REBUILD */
"missing", /* T_FATE_MISSING */
"needtmp", /* T_FATE_NEEDTMP */
"old", /* T_FATE_OUTDATED */
"update", /* T_FATE_UPDATE */
"update", /* T_FATE_UPDATE */
"nofind", /* T_FATE_CANTFIND */
"nomake" /* T_FATE_CANTMAKE */
} ;
};
static const char *target_bind[] =
static const char * target_bind[] =
{
"unbound",
"missing",
"parents",
"exists",
} ;
};
# define spaces(x) ( " " + ( x > 20 ? 0 : 20-x ) )
/*
* make() - make a target, given its name
* make() - make a target, given its name.
*/
int
make(
int n_targets,
const char **targets,
int anyhow )
int make( int n_targets, char const * * targets, int anyhow )
{
int i;
COUNTS counts[1];
int status = 0; /* 1 if anything fails */
int i;
COUNTS counts[ 1 ];
int status = 0; /* 1 if anything fails */
#ifdef OPT_HEADER_CACHE_EXT
hcache_init();
@@ -121,47 +118,40 @@ make(
memset( (char *)counts, 0, sizeof( *counts ) );
/* First bind all targets with LOCATE_TARGET setting. This is
needed to correctly handle dependencies to generated headers.
*/
/* First bind all targets with LOCATE_TARGET setting. This is needed to
* correctly handle dependencies to generated headers.
*/
bind_explicitly_located_targets();
{ PROFILE_ENTER(MAKE_MAKE0);
for( i = 0; i < n_targets; i++ )
{
TARGET *t = bindtarget( targets[i] );
make0( t, 0, 0, counts, anyhow );
PROFILE_ENTER( MAKE_MAKE0 );
for ( i = 0; i < n_targets; ++i )
make0( bindtarget( targets[ i ] ), 0, 0, counts, anyhow );
PROFILE_EXIT( MAKE_MAKE0 );
}
PROFILE_EXIT(MAKE_MAKE0); }
#ifdef OPT_GRAPH_DEBUG_EXT
if ( DEBUG_GRAPH )
{
for( i = 0; i < n_targets; i++ )
{
TARGET *t = bindtarget( targets[i] );
dependGraphOutput( t, 0 );
}
}
for ( i = 0; i < n_targets; ++i )
dependGraphOutput( bindtarget( targets[ i ] ), 0 );
#endif
if ( DEBUG_MAKE )
{
if ( counts->targets )
printf( "...found %d target%s...\n", counts->targets,
printf( "...found %d target%s...\n", counts->targets,
counts->targets > 1 ? "s" : "" );
if ( counts->temp )
printf( "...using %d temp target%s...\n", counts->temp,
printf( "...using %d temp target%s...\n", counts->temp,
counts->temp > 1 ? "s" : "" );
if ( counts->updating )
printf( "...updating %d target%s...\n", counts->updating,
printf( "...updating %d target%s...\n", counts->updating,
counts->updating > 1 ? "s" : "" );
if ( counts->cantfind )
printf( "...can't find %d target%s...\n", counts->cantfind,
printf( "...can't find %d target%s...\n", counts->cantfind,
counts->cantfind > 1 ? "s" : "" );
if ( counts->cantmake )
printf( "...can't make %d target%s...\n", counts->cantmake,
printf( "...can't make %d target%s...\n", counts->cantmake,
counts->cantmake > 1 ? "s" : "" );
}
@@ -171,94 +161,106 @@ make(
status = counts->cantfind || counts->cantmake;
{ PROFILE_ENTER(MAKE_MAKE1);
for( i = 0; i < n_targets; i++ )
status |= make1( bindtarget( targets[i] ) );
PROFILE_EXIT(MAKE_MAKE1); }
{
PROFILE_ENTER( MAKE_MAKE1 );
for ( i = 0; i < n_targets; ++i )
status |= make1( bindtarget( targets[ i ] ) );
PROFILE_EXIT( MAKE_MAKE1 );
}
return status;
}
/* Force any dependents of t that have already at least begun being
* visited by make0 to be updated.
*/
static void update_dependents(TARGET* t)
{
TARGETS *q;
for (q = t->dependents; q; q = q->next)
/* Force any dependants of t that have already at least begun being visited by
* make0() to be updated.
*/
static void update_dependants( TARGET * t )
{
TARGETS * q;
for ( q = t->dependants; q; q = q->next )
{
TARGET* p = q->target;
TARGET * p = q->target;
char fate0 = p->fate;
/* If we've already at least begun visiting it and
* we're not already rebuilding it for other reasons
/* If we have already at least begun visiting it and we are not already
* rebuilding it for other reasons.
*/
if (fate0 != T_FATE_INIT && fate0 < T_FATE_BUILD)
if ( ( fate0 != T_FATE_INIT ) && ( fate0 < T_FATE_BUILD ) )
{
p->fate = T_FATE_UPDATE;
if (DEBUG_FATE)
if ( DEBUG_FATE )
{
printf( "fate change %s from %s to %s (as dependent of %s)\n",
p->name, target_fate[fate0], target_fate[p->fate], t->name);
printf( "fate change %s from %s to %s (as dependant of %s)\n",
p->name, target_fate[ fate0 ], target_fate[ p->fate ], t->name );
}
/* If we're done visiting it, go back and make sure its
* dependents get rebuilt.
/* If we are done visiting it, go back and make sure its dependants
* get rebuilt.
*/
if (fate0 > T_FATE_MAKING)
update_dependents(p);
if ( fate0 > T_FATE_MAKING )
update_dependants( p );
}
}
}
/* Make sure that all of t's rebuilds get rebuilt */
static void force_rebuilds(TARGET* t)
{
TARGETS* d;
for (d = t->rebuilds; d; d = d->next)
{
TARGET* r = d->target;
/* If it's not already being rebuilt for other reasons */
if (r->fate < T_FATE_BUILD)
{
if (DEBUG_FATE)
printf( "fate change %s from %s to %s (by rebuild)\n",
r->name, target_fate[r->fate], target_fate[T_FATE_REBUILD]);
/* Force rebuild it */
r->fate = T_FATE_REBUILD;
/* And make sure its dependents are updated too */
update_dependents(r);
}
}
}
/*
* make0() - bind and scan everything to make a TARGET
*
* Make0() recursively binds a target, searches for #included headers,
* calls itself on those headers, and calls itself on any dependents.
* Make sure that all of t's rebuilds get rebuilt.
*/
void
make0(
TARGET *t,
TARGET *p, /* parent */
int depth, /* for display purposes */
COUNTS *counts, /* for reporting */
int anyhow ) /* forcibly touch all (real) targets */
static void force_rebuilds( TARGET * t )
{
TARGETS *c, *d, *incs;
TARGET *ptime = t;
time_t last;
time_t leaf;
time_t hlast;
int fate;
const char *flag = "";
SETTINGS *s;
TARGETS * d;
for ( d = t->rebuilds; d; d = d->next )
{
TARGET * r = d->target;
/* If it is not already being rebuilt for other reasons. */
if ( r->fate < T_FATE_BUILD )
{
if ( DEBUG_FATE )
printf( "fate change %s from %s to %s (by rebuild)\n",
r->name, target_fate[ r->fate ], target_fate[ T_FATE_REBUILD ] );
/* Force rebuild it. */
r->fate = T_FATE_REBUILD;
/* And make sure its dependants are updated too. */
update_dependants( r );
}
}
}
/*
* make0() - bind and scan everything to make a TARGET.
*
* Recursively binds a target, searches for #included headers, calls itself on
* those headers and any dependencies.
*/
void make0
(
TARGET * t,
TARGET * p, /* parent */
int depth, /* for display purposes */
COUNTS * counts, /* for reporting */
int anyhow
) /* forcibly touch all (real) targets */
{
TARGETS * c;
TARGETS * d;
TARGET * ptime = t;
time_t last;
time_t leaf;
time_t hlast;
int fate;
char const * flag = "";
SETTINGS * s;
#ifdef OPT_GRAPH_DEBUG_EXT
int savedFate, oldTimeStamp;
@@ -286,7 +288,7 @@ make0(
pushsettings( s );
/* Step 2b: find and timestamp the target file (if it is a file). */
if ( t->binding == T_BIND_UNBOUND && !( t->flags & T_FLAG_NOTFILE ) )
if ( ( t->binding == T_BIND_UNBOUND ) && !( t->flags & T_FLAG_NOTFILE ) )
{
char * another_target;
t->boundname = search( t->name, &t->time, &another_target,
@@ -296,19 +298,19 @@ make0(
* depending on us will depend on that other target as well.
*/
if ( another_target )
add_include( t, bindtarget( another_target ) );
target_include( t, bindtarget( another_target ) );
t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING;
}
/* INTERNAL, NOTFILE header nodes have the time of their parents. */
if ( p && t->flags & T_FLAG_INTERNAL )
if ( p && ( t->flags & T_FLAG_INTERNAL ) )
ptime = p;
/* If temp file doesn't exist but parent does, use parent */
if ( p && t->flags & T_FLAG_TEMP &&
t->binding == T_BIND_MISSING &&
p->binding != T_BIND_MISSING )
/* If temp file does not exist but parent does, use parent. */
if ( p && ( t->flags & T_FLAG_TEMP ) &&
( t->binding == T_BIND_MISSING ) &&
( p->binding != T_BIND_MISSING ) )
{
t->binding = T_BIND_PARENTS;
ptime = p;
@@ -330,7 +332,7 @@ make0(
if ( t->binding == T_BIND_EXISTS )
headers( t );
/* Step 2d: reset "on target" variables */
/* Step 2d: reset "on target" variables. */
popsettings( s );
freesettings( s );
@@ -341,82 +343,69 @@ make0(
if ( DEBUG_BIND )
{
if ( strcmp( t->name, t->boundname ) )
{
printf( "bind\t--\t%s%s: %s\n",
spaces( depth ), t->name, t->boundname );
}
switch( t->binding )
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 ), t->name, target_bind[ t->binding ] );
break;
printf( "time\t--\t%s%s: %s\n",
spaces( depth ), t->name, target_bind[ t->binding ] );
break;
case T_BIND_EXISTS:
printf( "time\t--\t%s%s: %s",
spaces( depth ), t->name, ctime( &t->time ) );
break;
printf( "time\t--\t%s%s: %s",
spaces( depth ), t->name, ctime( &t->time ) );
break;
}
}
/*
* Step 3: recursively make0() dependants & headers.
* Step 3: recursively make0() dependencies & headers.
*/
/* Step 3a: recursively make0() dependants. */
for( c = t->depends; c; c = c->next )
/* Step 3a: recursively make0() dependencies. */
for ( c = t->depends; c; c = c->next )
{
int internal = t->flags & T_FLAG_INTERNAL;
/* Seems like it's not relevant for us....
if ( DEBUG_DEPENDS )
printf( "%s \"%s\" : \"%s\" ;\n",
internal ? "Includes" : "Depends",
t->name, c->target->name );
*/
/* Warn about circular deps, except for includes, */
/* which include each other alot. */
/* Warn about circular deps, except for includes, which include each
* other alot.
*/
if ( c->target->fate == T_FATE_INIT )
make0( c->target, ptime, depth + 1, counts, anyhow );
make0( c->target, ptime, depth + 1, counts, anyhow );
else if ( c->target->fate == T_FATE_MAKING && !internal )
printf( "warning: %s depends on itself\n", c->target->name );
printf( "warning: %s depends on itself\n", c->target->name );
}
/* Step 3b: recursively make0() internal includes node */
/* Step 3b: recursively make0() internal includes node. */
if ( t->includes )
make0( t->includes, p, depth + 1, counts, anyhow );
/* Step 3c: add dependents' includes to our direct dependencies */
incs = 0;
for( c = t->depends; c; c = c->next )
if ( c->target->includes )
incs = targetentry( incs, c->target->includes );
t->depends = targetchain( t->depends, incs );
/* Step 3c: add dependencies' includes to our direct dependencies. */
{
TARGETS * incs = 0;
for ( c = t->depends; c; c = c->next )
if ( c->target->includes )
incs = targetentry( incs, c->target->includes );
t->depends = targetchain( t->depends, incs );
}
/*
* Step 4: compute time & fate
*/
/* Step 4a: pick up dependants' time and fate */
/* Step 4a: pick up dependencies' time and fate */
last = 0;
leaf = 0;
fate = T_FATE_STABLE;
for ( c = t->depends; c; c = c->next )
{
/* If LEAVES has been applied, we only heed the timestamps of */
/* the leaf source nodes. */
/* If LEAVES has been applied, we only heed the timestamps of the leaf
* source nodes.
*/
leaf = max( leaf, c->target->leaf );
if ( t->flags & T_FLAG_LEAVES )
@@ -430,13 +419,11 @@ make0(
#ifdef OPT_GRAPH_DEBUG_EXT
if ( DEBUG_FATE )
if ( fate < c->target->fate )
printf( "fate change %s from %s to %s by dependency %s\n",
t->name,
target_fate[fate], target_fate[c->target->fate],
c->target->name);
if ( fate < c->target->fate )
printf( "fate change %s from %s to %s by dependency %s\n",
t->name, target_fate[fate], target_fate[c->target->fate],
c->target->name );
#endif
}
/* Step 4b: pick up included headers time */
@@ -448,29 +435,26 @@ make0(
hlast = t->includes ? t->includes->time : 0;
/* Step 4c: handle NOUPDATE oddity */
/*
* If a NOUPDATE file exists, make dependents eternally old.
* Don't inherit our fate from our dependents. Decide fate
* based only upon other flags and our binding (done later).
/* Step 4c: handle NOUPDATE oddity.
*
* If a NOUPDATE file exists, mark it as having eternally old dependencies.
* Do not inherit our fate from our dependencies. Decide fate based only on
* other flags and our binding (done later).
*/
if ( t->flags & T_FLAG_NOUPDATE )
{
#ifdef OPT_GRAPH_DEBUG_EXT
if ( DEBUG_FATE )
if ( fate != T_FATE_STABLE )
printf( "fate change %s back to stable, NOUPDATE.\n",
t->name);
if ( fate != T_FATE_STABLE )
printf( "fate change %s back to stable, NOUPDATE.\n", t->name
);
#endif
last = 0;
t->time = 0;
/*
* Don't inherit our fate from our dependents. Decide fate
* based only upon other flags and our binding (done later).
/* Do not inherit our fate from our dependencies. Decide fate based only
* upon other flags and our binding (done later).
*/
fate = T_FATE_STABLE;
}
@@ -479,7 +463,7 @@ make0(
/*
In English:
If can't find or make child, can't make target.
If can not find or make child, can not make target.
If children changed, make target.
If target missing, make it.
If children newer, make target.
@@ -512,21 +496,21 @@ make0(
{
fate = T_FATE_MISSING;
}
else if ( t->binding == T_BIND_EXISTS && last > t->time )
else if ( ( t->binding == T_BIND_EXISTS ) && ( last > t->time ) )
{
#ifdef OPT_GRAPH_DEBUG_EXT
oldTimeStamp = 1;
#endif
fate = T_FATE_OUTDATED;
}
else if ( t->binding == T_BIND_PARENTS && last > p->time )
else if ( ( t->binding == T_BIND_PARENTS ) && ( last > p->time ) )
{
#ifdef OPT_GRAPH_DEBUG_EXT
oldTimeStamp = 1;
#endif
fate = T_FATE_NEEDTMP;
}
else if ( t->binding == T_BIND_PARENTS && hlast > p->time )
else if ( ( t->binding == T_BIND_PARENTS ) && ( hlast > p->time ) )
{
fate = T_FATE_NEEDTMP;
}
@@ -538,12 +522,12 @@ make0(
{
fate = T_FATE_TOUCHED;
}
else if ( t->binding == T_BIND_EXISTS && t->flags & T_FLAG_TEMP )
else if ( ( t->binding == T_BIND_EXISTS ) && ( t->flags & T_FLAG_TEMP ) )
{
fate = T_FATE_ISTMP;
}
else if ( t->binding == T_BIND_EXISTS && p &&
p->binding != T_BIND_UNBOUND && t->time > p->time )
else if ( ( t->binding == T_BIND_EXISTS ) && p &&
( p->binding != T_BIND_UNBOUND ) && ( t->time > p->time ) )
{
#ifdef OPT_GRAPH_DEBUG_EXT
oldTimeStamp = 1;
@@ -555,63 +539,63 @@ make0(
fate = T_FATE_STABLE;
}
#ifdef OPT_GRAPH_DEBUG_EXT
if ( DEBUG_FATE && fate != savedFate )
if ( DEBUG_FATE && ( fate != savedFate ) )
if ( savedFate == T_FATE_STABLE )
printf( "fate change %s set to %s%s\n",
t->name, target_fate[fate],
oldTimeStamp ? " (by timestamp)" : "" );
printf( "fate change %s set to %s%s\n", t->name,
target_fate[ fate ], oldTimeStamp ? " (by timestamp)" : "" );
else
printf( "fate change %s from %s to %s%s\n",
t->name, target_fate[savedFate], target_fate[fate],
oldTimeStamp ? " (by timestamp)" : "" );
printf( "fate change %s from %s to %s%s\n", t->name,
target_fate[ savedFate ], target_fate[ fate ],
oldTimeStamp ? " (by timestamp)" : "" );
#endif
/* Step 4e: handle missing files */
/* If it's missing and there are no actions to create it, boom. */
/* If we can't make a target we don't care about, 'sokay */
/* If it is missing and there are no actions to create it, boom. */
/* If we can not make a target we do not care about it, okay. */
/* We could insist that there are updating actions for all missing */
/* files, but if they have dependents we just pretend it's NOTFILE. */
/* files, but if they have dependencies we just pretend it is a NOTFILE. */
if ( fate == T_FATE_MISSING && !t->actions && !t->depends )
if ( ( fate == T_FATE_MISSING ) && !t->actions && !t->depends )
{
if ( t->flags & T_FLAG_NOCARE )
{
#ifdef OPT_GRAPH_DEBUG_EXT
if ( DEBUG_FATE )
printf( "fate change %s to STABLE from %s, "
"no actions, no dependents and don't care\n",
t->name, target_fate[fate]);
if ( DEBUG_FATE )
printf( "fate change %s to STABLE from %s, "
"no actions, no dependencies and do not care\n",
t->name, target_fate[ fate ] );
#endif
fate = T_FATE_STABLE;
fate = T_FATE_STABLE;
}
else
{
printf( "don't know how to make %s\n", t->name );
fate = T_FATE_CANTFIND;
printf( "don't know how to make %s\n", t->name );
fate = T_FATE_CANTFIND;
}
}
/* Step 4f: propagate dependents' time & fate. */
/* Step 4f: propagate dependencies' time & fate. */
/* Set leaf time to be our time only if this is a leaf. */
t->time = max( t->time, last );
t->leaf = leaf ? leaf : t->time ;
/* This target's fate may have been updated by virtue of following
* some target's rebuilds list, so only allow it to be increased
* to the fate we've calculated. Otherwise, grab its new fate.
/* This target's fate may have been updated by virtue of following some
* target's rebuilds list, so only allow it to be increased to the fate we
* have calculated. Otherwise, grab its new fate.
*/
if (fate > t->fate)
if ( fate > t->fate )
t->fate = fate;
else
fate = t->fate;
/* Step 4g: if this target needs to be built, force rebuild
* everything in this target's rebuilds list */
if (fate >= T_FATE_BUILD && fate < T_FATE_BROKEN)
force_rebuilds(t);
/* Step 4g: if this target needs to be built, force rebuild everything in
* this target's rebuilds list.
*/
if ( ( fate >= T_FATE_BUILD ) && ( fate < T_FATE_BROKEN ) )
force_rebuilds( t );
/*
* Step 5: sort dependents by their update time.
* Step 5: sort dependencies by their update time.
*/
if ( globs.newestfirst )
@@ -621,12 +605,12 @@ make0(
* Step 6: a little harmless tabulating for tracing purposes
*/
/* Don't count or report interal includes nodes. */
/* Do not count or report interal includes nodes. */
if ( t->flags & T_FLAG_INTERNAL )
return;
if (counts) {
if ( counts )
{
#ifdef OPT_IMPROVED_PATIENCE_EXT
++counts->targets;
#else
@@ -635,24 +619,24 @@ make0(
#endif
if ( fate == T_FATE_ISTMP )
counts->temp++;
++counts->temp;
else if ( fate == T_FATE_CANTFIND )
counts->cantfind++;
else if ( fate == T_FATE_CANTMAKE && t->actions )
counts->cantmake++;
else if ( fate >= T_FATE_BUILD && fate < T_FATE_BROKEN && t->actions )
counts->updating++;
++counts->cantfind;
else if ( ( fate == T_FATE_CANTMAKE ) && t->actions )
++counts->cantmake;
else if ( ( fate >= T_FATE_BUILD ) && ( fate < T_FATE_BROKEN ) &&
t->actions )
++counts->updating;
}
if ( !( t->flags & T_FLAG_NOTFILE ) && fate >= T_FATE_SPOIL )
if ( !( t->flags & T_FLAG_NOTFILE ) && ( fate >= T_FATE_SPOIL ) )
flag = "+";
else if ( t->binding == T_BIND_EXISTS && p && t->time > p->time )
else if ( ( t->binding == T_BIND_EXISTS ) && p && ( t->time > p->time ) )
flag = "*";
if ( DEBUG_MAKEPROG )
printf( "made%s\t%s\t%s%s\n",
flag, target_fate[ t->fate ],
spaces( depth ), t->name );
printf( "made%s\t%s\t%s%s\n", flag, target_fate[ t->fate ],
spaces( depth ), t->name );
}
@@ -660,13 +644,13 @@ make0(
static const char * target_name( TARGET * t )
{
static char buf[1000];
if (t->flags & T_FLAG_INTERNAL) {
sprintf(buf, "%s (internal node)", t->name);
static char buf[ 1000 ];
if ( t->flags & T_FLAG_INTERNAL )
{
sprintf( buf, "%s (internal node)", t->name );
return buf;
} else {
return t->name;
}
return t->name;
}
@@ -689,56 +673,56 @@ static void dependGraphOutput( TARGET * t, int depth )
case T_FATE_MISSING:
case T_FATE_OUTDATED:
case T_FATE_UPDATE:
printf( "->%s%2d Name: %s\n", spaces(depth), depth, target_name(t) );
printf( "->%s%2d Name: %s\n", spaces( depth ), depth, target_name( t ) );
break;
default:
printf( " %s%2d Name: %s\n", spaces(depth), depth, target_name(t) );
printf( " %s%2d Name: %s\n", spaces( depth ), depth, target_name( t ) );
break;
}
if ( strcmp( t->name, t->boundname ) )
printf( " %s Loc: %s\n", spaces(depth), t->boundname );
printf( " %s Loc: %s\n", spaces( depth ), t->boundname );
switch ( t->fate )
{
case T_FATE_STABLE:
printf( " %s : Stable\n", spaces(depth) );
printf( " %s : Stable\n", spaces( depth ) );
break;
case T_FATE_NEWER:
printf( " %s : Newer\n", spaces(depth) );
printf( " %s : Newer\n", spaces( depth ) );
break;
case T_FATE_ISTMP:
printf( " %s : Up to date temp file\n", spaces(depth) );
printf( " %s : Up to date temp file\n", spaces( depth ) );
break;
case T_FATE_NEEDTMP:
printf( " %s : Temporary file, to be updated\n", spaces(depth) );
printf( " %s : Temporary file, to be updated\n", spaces( depth ) );
break;
case T_FATE_TOUCHED:
printf( " %s : Been touched, updating it\n", spaces(depth) );
printf( " %s : Been touched, updating it\n", spaces( depth ) );
break;
case T_FATE_MISSING:
printf( " %s : Missing, creating it\n", spaces(depth) );
printf( " %s : Missing, creating it\n", spaces( depth ) );
break;
case T_FATE_OUTDATED:
printf( " %s : Outdated, updating it\n", spaces(depth) );
printf( " %s : Outdated, updating it\n", spaces( depth ) );
break;
case T_FATE_REBUILD:
printf( " %s : Rebuild, updating it\n", spaces(depth) );
printf( " %s : Rebuild, updating it\n", spaces( depth ) );
break;
case T_FATE_UPDATE:
printf( " %s : Updating it\n", spaces(depth) );
printf( " %s : Updating it\n", spaces( depth ) );
break;
case T_FATE_CANTFIND:
printf( " %s : Can not find it\n", spaces(depth) );
printf( " %s : Can not find it\n", spaces( depth ) );
break;
case T_FATE_CANTMAKE:
printf( " %s : Can make it\n", spaces(depth) );
printf( " %s : Can make it\n", spaces( depth ) );
break;
}
if ( t->flags & ~T_FLAG_VISITED )
{
printf( " %s : ", spaces(depth) );
printf( " %s : ", spaces( depth ) );
if ( t->flags & T_FLAG_TEMP ) printf( "TEMPORARY " );
if ( t->flags & T_FLAG_NOCARE ) printf( "NOCARE " );
if ( t->flags & T_FLAG_NOTFILE ) printf( "NOTFILE " );
@@ -750,11 +734,11 @@ 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[ c->target->fate ] );
printf( " %s : Depends on %s (%s)", spaces( depth ),
target_name( c->target ), target_fate[ c->target->fate ] );
if ( c->target->time == t->time )
printf( " (max time)");
printf("\n");
printf( "\n" );
}
for ( c = t->depends; c; c = c->next )
@@ -764,36 +748,36 @@ static void dependGraphOutput( TARGET * t, int depth )
/*
* make0sort() - reorder TARGETS chain by their time (newest to oldest)
* make0sort() - reorder TARGETS chain by their time (newest to oldest).
*
* We walk chain, taking each item and inserting it on the sorted result, with
* newest items at the front. This involves updating each of the TARGETS'
* c->next and c->tail. Note that we make c->tail a valid prev pointer for every
* entry. Normally, it is only valid at the head, where prev == tail. Note also
* that while tail is a loop, next ends at the end of the chain.
*/
static TARGETS * make0sort( TARGETS * chain )
{
PROFILE_ENTER(MAKE_MAKE0SORT);
PROFILE_ENTER( MAKE_MAKE0SORT );
TARGETS * result = 0;
/* We walk chain, taking each item and inserting it on the sorted result, */
/* with newest items at the front. This involves updating each of the */
/* TARGETS' c->next and c->tail. Note that we make c->tail a valid prev */
/* pointer for every entry. Normally, it is only valid at the head, where */
/* prev == tail. Note also that while tail is a loop, next ends at the */
/* end of the chain. */
/* Walk the current target list. */
while( chain )
while ( chain )
{
TARGETS *c = chain;
TARGETS *s = result;
TARGETS * c = chain;
TARGETS * s = result;
chain = chain->next;
/* Find point s in result for c. */
while( s && s->target->time > c->target->time )
s = s->next;
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). Do not even think of deciphering
* this.
*/
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 */
@@ -802,7 +786,7 @@ static TARGETS * make0sort( TARGETS * chain )
s->tail = c; /* make next's prev us */
}
PROFILE_EXIT(MAKE_MAKE0SORT);
PROFILE_EXIT( MAKE_MAKE0SORT );
return result;
}

File diff suppressed because it is too large Load Diff

View File

@@ -26,103 +26,95 @@
*
*/
# include <stdio.h>
# include <string.h>
#include <stdio.h>
#include <string.h>
int main( int argc, char **argv, char **envp )
int main( int argc, char * * argv, char * * envp )
{
char buf[ 1024 ];
FILE *fin;
FILE *fout;
char *p;
FILE * fin;
FILE * fout;
char * p;
int doDotC = 0;
if( argc < 3 )
if ( argc < 3 )
{
fprintf( stderr, "usage: %s jambase.c Jambase ...\n", argv[0] );
fprintf( stderr, "usage: %s jambase.c Jambase ...\n", argv[ 0 ] );
return -1;
}
if( !( fout = fopen( argv[1], "w" ) ) )
if ( !( fout = fopen( argv[1], "w" ) ) )
{
perror( argv[1] );
perror( argv[ 1 ] );
return -1;
}
/* If the file ends in .c generate a C source file */
if( ( p = strrchr( argv[1], '.' ) ) && !strcmp( p, ".c" ) )
/* If the file ends in .c generate a C source file. */
if ( ( p = strrchr( argv[1], '.' ) ) && !strcmp( p, ".c" ) )
doDotC++;
/* Now process the files */
/* Now process the files. */
argc -= 2, argv += 2;
argc -= 2;
argv += 2;
if( doDotC )
if ( doDotC )
{
fprintf( fout, "/* Generated by mkjambase from Jambase */\n" );
fprintf( fout, "char *jambase[] = {\n" );
}
for( ; argc--; argv++ )
for ( ; argc--; ++argv )
{
if( !( fin = fopen( *argv, "r" ) ) )
if ( !( fin = fopen( *argv, "r" ) ) )
{
perror( *argv );
return -1;
perror( *argv );
return -1;
}
if( doDotC )
{
fprintf( fout, "/* %s */\n", *argv );
}
if ( doDotC )
fprintf( fout, "/* %s */\n", *argv );
else
fprintf( fout, "### %s ###\n", *argv );
while ( fgets( buf, sizeof( buf ), fin ) )
{
fprintf( fout, "### %s ###\n", *argv );
}
while( fgets( buf, sizeof( buf ), fin ) )
{
if( doDotC )
{
char *p = buf;
/* Strip leading whitespace. */
while( *p == ' ' || *p == '\t' || *p == '\n' )
p++;
/* Drop comments and empty lines. */
if( *p == '#' || !*p )
continue;
/* Copy */
putc( '"', fout );
for( ; *p && *p != '\n'; p++ )
switch( *p )
if ( doDotC )
{
case '\\': putc( '\\', fout ); putc( '\\', fout ); break;
case '"': putc( '\\', fout ); putc( '"', fout ); break;
case '\r': break;
default: putc( *p, fout ); break;
char * p = buf;
/* Strip leading whitespace. */
while ( ( *p == ' ' ) || ( *p == '\t' ) || ( *p == '\n' ) )
++p;
/* Drop comments and empty lines. */
if ( ( *p == '#' ) || !*p )
continue;
/* Copy. */
putc( '"', fout );
for ( ; *p && ( *p != '\n' ); ++p )
switch ( *p )
{
case '\\': putc( '\\', fout ); putc( '\\', fout ); break;
case '"' : putc( '\\', fout ); putc( '"' , fout ); break;
case '\r': break;
default: putc( *p, fout ); break;
}
fprintf( fout, "\\n\",\n" );
}
else
{
fprintf( fout, "%s", buf );
}
fprintf( fout, "\\n\",\n" );
}
else
{
fprintf( fout, "%s", buf );
}
}
fclose( fin );
}
if( doDotC )
if ( doDotC )
fprintf( fout, "0 };\n" );
fclose( fout );

View File

@@ -33,16 +33,17 @@ static char * new_module_str( module_t * m, char * suffix )
module_t * bindmodule( char * name )
{
PROFILE_ENTER(BINDMODULE);
PROFILE_ENTER( BINDMODULE );
string s;
module_t m_, *m = &m_;
module_t m_;
module_t * m = &m_;
if( !module_hash )
if ( !module_hash )
module_hash = hashinit( sizeof( module_t ), "modules" );
string_new( &s );
if (name)
if ( name )
{
string_append( &s, name );
string_push_back( &s, '.' );
@@ -50,7 +51,7 @@ module_t * bindmodule( char * name )
m->name = s.value;
if ( hashenter( module_hash, (HASHDATA **)&m ) )
if ( hashenter( module_hash, (HASHDATA * *)&m ) )
{
m->name = newstr( m->name );
m->variables = 0;
@@ -62,35 +63,38 @@ module_t * bindmodule( char * name )
}
string_free( &s );
PROFILE_EXIT(BINDMODULE);
PROFILE_EXIT( BINDMODULE );
return m;
}
/*
* demand_rules() - Get the module's "rules" hash on demand
* demand_rules() - Get the module's "rules" hash on demand.
*/
struct hash* demand_rules( module_t* m )
struct hash * demand_rules( module_t * m )
{
if ( !m->rules )
m->rules = hashinit( sizeof( RULE ), new_module_str( m, "rules" ) );
return m->rules;
}
/*
* delete_module() - wipe out the module's rules and variables
* delete_module() - wipe out the module's rules and variables.
*/
static void delete_rule_( void* xrule, void* data )
static void delete_rule_( void * xrule, void * data )
{
rule_free( (RULE*)xrule );
rule_free( (RULE *)xrule );
}
void delete_module( module_t* m )
void delete_module( module_t * m )
{
/* clear out all the rules */
/* Clear out all the rules. */
if ( m->rules )
{
hashenumerate( m->rules, delete_rule_, (void*)0 );
hashenumerate( m->rules, delete_rule_, (void *)0 );
hashdone( m->rules );
m->rules = 0;
}
@@ -104,15 +108,16 @@ void delete_module( module_t* m )
}
}
module_t* root_module()
module_t * root_module()
{
static module_t* root = 0;
static module_t * root = 0;
if ( !root )
root = bindmodule(0);
root = bindmodule( 0 );
return root;
}
void enter_module( module_t* m )
void enter_module( module_t * m )
{
var_hash_swap( &m->variables );
}
@@ -126,7 +131,7 @@ void exit_module( module_t * m )
void import_module( LIST * module_names, module_t * target_module )
{
PROFILE_ENTER(IMPORT_MODULE);
PROFILE_ENTER( IMPORT_MODULE );
struct hash * h;
@@ -141,7 +146,7 @@ void import_module( LIST * module_names, module_t * target_module )
hashenter( h, (HASHDATA * *)&ss );
}
PROFILE_EXIT(IMPORT_MODULE);
PROFILE_EXIT( IMPORT_MODULE );
}

View File

@@ -22,7 +22,7 @@
* newstr() - return a dynamically allocated copy of a string
* copystr() - return a copy of a string previously returned by newstr()
* freestr() - free a string returned by newstr() or copystr()
* donestr() - free string tables
* str_done() - free string tables
*
* Once a string is passed to newstr(), the returned string is readonly.
*
@@ -31,62 +31,65 @@
* Strings are never actually freed.
*/
typedef char *STRING;
typedef char * STRING;
static struct hash * strhash = 0;
static int strtotal = 0;
static int strcount_in = 0;
static int strcount_out = 0;
static struct hash *strhash = 0;
static int strtotal = 0;
static int strcount_in = 0;
static int strcount_out = 0;
/*
* Immortal string allocator implementation speeds string allocation
* and cuts down on internal fragmentation
* Immortal string allocator implementation speeds string allocation and cuts
* down on internal fragmentation.
*/
# define STRING_BLOCK 4096
typedef struct strblock
{
struct strblock* next;
char data[STRING_BLOCK];
struct strblock * next;
char data[STRING_BLOCK];
} strblock;
static strblock* strblock_chain = 0;
static strblock * strblock_chain = 0;
/* Storage remaining in the current strblock */
static char* storage_start = 0;
static char* storage_finish = 0;
static char * storage_start = 0;
static char * storage_finish = 0;
/*
* allocate() - Allocate n bytes of immortal string storage
* allocate() - Allocate n bytes of immortal string storage.
*/
static char* allocate(size_t n)
static char * allocate( size_t const n )
{
#ifdef BJAM_NEWSTR_NO_ALLOCATE
#ifdef BJAM_NEWSTR_NO_ALLOCATE
return (char*)BJAM_MALLOC_ATOMIC(n);
#else
/* See if we can grab storage from an existing block */
#else
/* See if we can grab storage from an existing block. */
size_t remaining = storage_finish - storage_start;
if ( remaining >= n )
{
char* result = storage_start;
char * result = storage_start;
storage_start += n;
return result;
}
else /* Must allocate a new block */
else /* Must allocate a new block. */
{
strblock* new_block;
strblock * new_block;
size_t nalloc = n;
if ( nalloc < STRING_BLOCK )
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]) );
/* Allocate a new block and link into the chain. */
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;
strblock_chain = new_block;
/* Take future allocations out of the larger remaining space */
/* Take future allocations out of the larger remaining space. */
if ( remaining < nalloc - n )
{
storage_start = new_block->data + n;
@@ -94,27 +97,28 @@ static char* allocate(size_t n)
}
return new_block->data;
}
#endif
#endif
}
/*
* newstr() - return a dynamically allocated copy of a string
* newstr() - return a dynamically allocated copy of a string.
*/
char *
newstr( char *string )
char * newstr( char * string )
{
STRING str, *s = &str;
STRING str;
STRING * s = &str;
if( !strhash )
if ( !strhash )
strhash = hashinit( sizeof( STRING ), "strings" );
*s = string;
if( hashenter( strhash, (HASHDATA **)&s ) )
if ( hashenter( strhash, (HASHDATA **)&s ) )
{
int l = strlen( string );
char *m = (char *)allocate( l + 1 );
char * m = (char *)allocate( l + 1 );
strtotal += l + 1;
memcpy( m, string, l + 1 );
@@ -125,45 +129,45 @@ newstr( char *string )
return *s;
}
/*
* copystr() - return a copy of a string previously returned by newstr()
*/
char *
copystr( char *s )
char * copystr( char * s )
{
strcount_in += 1;
return s;
}
/*
* freestr() - free a string returned by newstr() or copystr()
*/
void
freestr( char *s )
void freestr( char * s )
{
strcount_out += 1;
}
/*
* donestr() - free string tables
* str_done() - free string tables.
*/
void
donestr()
void str_done()
{
/* Reclaim string blocks */
/* Reclaim string blocks. */
while ( strblock_chain != 0 )
{
strblock* n = strblock_chain->next;
strblock * n = strblock_chain->next;
BJAM_FREE(strblock_chain);
strblock_chain = n;
}
hashdone( strhash );
if( DEBUG_MEM )
if ( DEBUG_MEM )
printf( "%dK in strings\n", strtotal / 1024 );
/* printf( "--- %d strings of %d dangling\n", strcount_in-strcount_out, strcount_in ); */

View File

@@ -8,7 +8,7 @@
* newstr.h - string manipulation routines
*/
char *newstr( char *string );
char *copystr( char *s );
void freestr( char *s );
void donestr();
char * copystr ( char * );
void freestr ( char * );
char * newstr ( char * );
void str_done();

View File

@@ -17,67 +17,63 @@
* was supplied for an option that does not require one."
*/
int
getoptions(
int argc,
char **argv,
char *opts,
option *optv )
int getoptions( int argc, char * * argv, char * opts, option * optv )
{
int i;
int optc = N_OPTS;
memset( (char *)optv, '\0', sizeof( *optv ) * N_OPTS );
for( i = 0; i < argc; i++ )
for ( i = 0; i < argc; ++i )
{
char *arg;
char *arg;
if( argv[i][0] != '-' || ( argv[i][1] != '-' && !isalpha( argv[i][1] ) ) )
continue;
if ( ( argv[ i ][ 0 ] != '-' ) ||
( ( argv[ i ][ 1 ] != '-' ) && !isalpha( argv[ i ][ 1 ] ) ) )
continue;
if( !optc-- )
{
printf( "too many options (%d max)\n", N_OPTS );
return -1;
}
for( arg = &argv[i][1]; *arg; arg++ )
{
char *f;
for( f = opts; *f; f++ )
if( *f == *arg )
break;
if( !*f )
if ( !optc-- )
{
printf( "Invalid option: -%c\n", *arg );
return -1;
printf( "too many options (%d max)\n", N_OPTS );
return -1;
}
optv->flag = *f;
for ( arg = &argv[ i ][ 1 ]; *arg; ++arg )
{
char * f;
if( f[1] != ':' )
{
optv++->val = "true";
for ( f = opts; *f; ++f )
if ( *f == *arg )
break;
if ( !*f )
{
printf( "Invalid option: -%c\n", *arg );
return -1;
}
optv->flag = *f;
if ( f[ 1 ] != ':' )
{
optv++->val = "true";
}
else if ( arg[ 1 ] )
{
optv++->val = &arg[1];
break;
}
else if ( ++i < argc )
{
optv++->val = argv[ i ];
break;
}
else
{
printf( "option: -%c needs argument\n", *f );
return -1;
}
}
else if( arg[1] )
{
optv++->val = &arg[1];
break;
}
else if( ++i < argc )
{
optv++->val = argv[i];
break;
}
else
{
printf( "option: -%c needs argument\n", *f );
return -1;
}
}
}
return i;

View File

@@ -35,34 +35,31 @@ parse_file( char *f, FRAME* frame )
/* Suspend scan of current file */
/* and push this new file in the stream */
yyfparse(f);
yyfparse( f );
/* Now parse each block of rules and execute it. */
/* Execute it outside of the parser so that recursive */
/* calls to yyrun() work (no recursive yyparse's). */
for(;;)
for ( ; ; )
{
PARSE *p;
/* Filled by yyparse() calling parse_save() */
/* Filled by yyparse() calling parse_save(). */
yypsave = 0;
/* If parse error or empty parse, outta here */
if( yyparse() || !( p = yypsave ) )
break;
/* If parse error or empty parse, outta here. */
if ( yyparse() || !( p = yypsave ) )
break;
/* Run the parse tree. */
parse_evaluate( p, frame );
parse_evaluate( p, frame );
parse_free( p );
}
}
void
parse_save( PARSE *p )
void parse_save( PARSE * p )
{
yypsave = p;
}

View File

@@ -37,7 +37,7 @@ struct _PARSE {
char* rulename;
char* file;
int line;
} ;
};
void parse_file( char *f, FRAME* frame );
void parse_save( PARSE *p );

View File

@@ -63,7 +63,7 @@ path_parse(
/* 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;
@@ -72,7 +72,7 @@ path_parse(
/* Look for dir: */
if( p = strrchr( file, DELIM ) )
if ( p = strrchr( file, DELIM ) )
{
f->f_dir.ptr = file;
f->f_dir.len = p - file;
@@ -80,18 +80,17 @@ path_parse(
/* All :'s? Include last : as part of directory name */
while( p > f->f_dir.ptr && *--p == DELIM )
;
while ( ( p > f->f_dir.ptr ) && ( *--p == DELIM ) );
if( p == f->f_dir.ptr )
f->f_dir.len++;
if ( p == f->f_dir.ptr )
++f->f_dir.len;
}
end = file + strlen( file );
/* Look for (member) */
/* Look for (member). */
if( ( p = strchr( file, '(' ) ) && end[-1] == ')' )
if ( ( p = strchr( file, '(' ) ) && ( end[-1] == ')' ) )
{
f->f_member.ptr = p + 1;
f->f_member.len = end - p - 2;
@@ -104,10 +103,10 @@ path_parse(
p = 0;
q = file;
while( q = memchr( q, '.', end - q ) )
while ( q = memchr( q, '.', end - q ) )
p = q++;
if( p )
if ( p )
{
f->f_suffix.ptr = p;
f->f_suffix.len = end - p;
@@ -144,31 +143,27 @@ char grid[5][5] = {
/* DOTDOT */ { G_ROOT, G_ROOT, G_DDDD, G_DIR, G_DTDR },
/* ABS */ { G_ROOT, G_ROOT, G_ROOT, G_DIR, G_CAT },
/* REL */ { G_ROOT, G_ROOT, G_ROOT, G_DIR, G_CAT }
} ;
};
static int
file_flags(
char *ptr,
int len )
static int file_flags( char * ptr, int len )
{
if( !len )
if ( !len )
return DIR_EMPTY;
if( len == 1 && ptr[0] == DELIM )
if ( ( len == 1 ) && ( ptr[0] == DELIM ) )
return DIR_DOT;
if( len == 2 && ptr[0] == DELIM && ptr[1] == DELIM )
if ( ( len == 2 ) && ( ptr[0] == DELIM ) && ( ptr[1] == DELIM ) )
return DIR_DOTDOT;
if( ptr[0] == DELIM )
if ( ptr[0] == DELIM )
return DIR_REL;
return DIR_ABS;
}
void
path_build(
PATHNAME *f,
string* file,
int binding )
void path_build( PATHNAME * f, string * file, int binding )
{
int dflag, rflag, act;
int dflag;
int rflag;
int act;
file_build1( f, file );
@@ -177,7 +172,7 @@ path_build(
dflag = file_flags( f->f_dir.ptr, f->f_dir.len );
rflag = file_flags( f->f_root.ptr, f->f_root.len );
switch( act = grid[ rflag ][ dflag ] )
switch ( act = grid[ rflag ][ dflag ] )
{
case G_DTDR:
{
@@ -199,7 +194,7 @@ path_build(
case G_CAT:
/* prepend root to dir */
string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
if( file->value[file->size - 1] == DELIM )
if ( file->value[ file->size - 1 ] == DELIM )
string_pop_back( file );
string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len );
break;
@@ -210,44 +205,40 @@ path_build(
break;
}
/* Put : between dir and file (if none already) */
/* Put : between dir and file (if none already). */
if( act != G_MT &&
file->value[file->size - 1] != DELIM &&
if ( ( act != G_MT ) &&
( file->value[ file->size - 1 ] != DELIM ) &&
( f->f_base.len || f->f_suffix.len ) )
{
string_push_back( file, DELIM );
}
if( f->f_base.len )
{
if ( 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 )
{
if ( 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 )
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_push_back( file, ')' );
}
if( DEBUG_SEARCH )
printf(" -> '%s'\n", file->value);
if ( DEBUG_SEARCH )
printf( " -> '%s'\n", file->value );
}
/*
* 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 set everything else to nothing. */
f->f_base.ptr =
f->f_suffix.ptr =

View File

@@ -28,38 +28,39 @@
typedef struct _pathname PATHNAME;
typedef struct _pathpart PATHPART;
struct _pathpart {
char *ptr;
int len;
struct _pathpart
{
char * ptr;
int len;
};
struct _pathname {
struct _pathname
{
PATHPART part[6];
# ifdef OS_VMS
#ifdef OS_VMS
int parent;
# endif
#endif
# 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 );
void path_build1( PATHNAME * f, string * file );
void path_build( PATHNAME *f, string *file, int binding );
void path_build1( PATHNAME *f, string *file );
void path_parse( char *file, PATHNAME *f );
void path_parent( PATHNAME *f );
void path_parse( char * file, PATHNAME * f );
void path_parent( PATHNAME * f );
#ifdef NT
/** Returns newstr-allocated string with long equivivalent of 'short_name'.
If none exists -- i.e. 'short_path' is already long path, it's returned
unaltered. */
char* short_path_to_long_path(char* short_path);
char * short_path_to_long_path( char * short_path );
#endif
@@ -67,15 +68,15 @@ char* short_path_to_long_path(char* short_path);
/** Returns a static pointer to the system dependent path to the temporary
directory. NOTE: *without* a trailing path separator.
*/
const char * path_tmpdir(void);
const char * path_tmpdir( void );
/** Returns a new temporary name.
*/
const char * path_tmpnam(void);
const char * path_tmpnam( void );
/** Returns a new temporary path.
*/
const char * path_tmpfile(void);
const char * path_tmpfile( void );
#endif
#endif

View File

@@ -56,19 +56,17 @@
* path_parse() - split a file name into dir/base/suffix/member
*/
void
path_parse(
char *file,
PATHNAME *f )
void path_parse( char * file, PATHNAME * f )
{
char *p, *q;
char *end;
char * p;
char * q;
char * end;
memset( (char *)f, 0, sizeof( *f ) );
/* 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;
@@ -87,21 +85,21 @@ path_parse(
}
# endif
if( p )
if ( p )
{
f->f_dir.ptr = file;
f->f_dir.len = p - file;
/* Special case for / - dirname is /, not "" */
if( !f->f_dir.len )
if ( !f->f_dir.len )
f->f_dir.len = 1;
# 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;
if ( f->f_dir.len == 2 && file[1] == ':' )
f->f_dir.len = 3;
# endif
file = p + 1;
@@ -111,7 +109,7 @@ path_parse(
/* Look for (member) */
if( ( p = strchr( file, '(' ) ) && end[-1] == ')' )
if ( ( p = strchr( file, '(' ) ) && ( end[ -1 ] == ')' ) )
{
f->f_member.ptr = p + 1;
f->f_member.len = end - p - 2;
@@ -124,10 +122,10 @@ path_parse(
p = 0;
q = file;
while( q = (char *)memchr( q, '.', end - q ) )
while ( q = (char *)memchr( q, '.', end - q ) )
p = q++;
if( p )
if ( p )
{
f->f_suffix.ptr = p;
f->f_suffix.len = end - p;
@@ -197,13 +195,13 @@ path_build(
/* Don't prepend root if it's . or directory is rooted */
# if PATH_DELIM == '/'
if( f->f_root.len
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
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] == '\\' )
@@ -215,41 +213,39 @@ path_build(
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] ) )
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 )
{
if ( 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 ) )
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] == ':' ) )
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] ) ) )
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] ) );
}
if( f->f_base.len )
if ( 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 )
if ( 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 )
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 );

View File

@@ -38,22 +38,20 @@
*/
/*
* path_parse() - split a file name into dir/base/suffix/member
* path_parse() - split a file name into dir/base/suffix/member.
*/
void
path_parse(
char *file,
PATHNAME *f )
void path_parse( char * file, PATHNAME * f )
{
char *p, *q;
char *end;
char * p;
char * q;
char * end;
memset( (char *)f, 0, sizeof( *f ) );
/* 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;
@@ -62,7 +60,7 @@ path_parse(
/* Look for dev:[dir] or dev: */
if( ( p = strchr( file, ']' ) ) || ( p = strchr( file, ':' ) ) )
if ( ( p = strchr( file, ']' ) ) || ( p = strchr( file, ':' ) ) )
{
f->f_dir.ptr = file;
f->f_dir.len = p + 1 - file;
@@ -71,9 +69,9 @@ path_parse(
end = file + strlen( file );
/* Look for (member) */
/* Look for (member). */
if( ( p = strchr( file, '(' ) ) && end[-1] == ')' )
if ( ( p = strchr( file, '(' ) ) && ( end[ -1 ] == ')' ) )
{
f->f_member.ptr = p + 1;
f->f_member.len = end - p - 2;
@@ -81,28 +79,26 @@ path_parse(
}
/* Look for .suffix */
/* This would be memrchr() */
/* This would be memrchr(). */
p = 0;
q = file;
while( q = (char *)memchr( q, '.', end - q ) )
while ( q = (char *)memchr( q, '.', end - q ) )
p = q++;
if( p )
if ( p )
{
f->f_suffix.ptr = p;
f->f_suffix.len = end - p;
end = p;
}
/* Leaves base */
/* Leaves base. */
f->f_base.ptr = file;
f->f_base.len = end - file;
/* Is this a directory without a file spec? */
f->parent = 0;
}
@@ -159,39 +155,33 @@ static int grid[7][7] = {
/* ABSDIR */ G_ROOT, G_DIR, G_DIR, G_DRD, G_DIR, G_DIR, G_DIR,
/* ROOT */ G_ROOT, G_DIR, G_DIR, G_VRD, G_DIR, G_DIR, G_DIR,
} ;
};
struct dirinf {
struct dirinf
{
int flags;
struct {
char *ptr;
int len;
struct
{
char * ptr;
int len;
} dev, dir;
} ;
};
static char *
strnchr(
char *buf,
int c,
int len )
static char * strnchr( char * buf, int c, int len )
{
while( len-- )
if( *buf && *buf++ == c )
return buf - 1;
while ( len-- )
if ( *buf && ( *buf++ == c ) )
return buf - 1;
return 0;
}
static void
dir_flags(
char *buf,
int len,
struct dirinf *i )
{
char *p;
if( !buf || !len )
static void dir_flags( char * buf, int len, struct dirinf * i )
{
char * p;
if ( !buf || !len )
{
i->flags = DIR_EMPTY;
i->dev.ptr =
@@ -199,7 +189,7 @@ dir_flags(
i->dev.len =
i->dir.len = 0;
}
else if( p = strnchr( buf, ':', len ) )
else if ( p = strnchr( buf, ':', len ) )
{
i->dev.ptr = buf;
i->dev.len = p + 1 - buf;
@@ -214,45 +204,41 @@ dir_flags(
i->dir.ptr = buf;
i->dir.len = len;
if( *buf == '[' && buf[1] == ']' )
i->flags = DIR_EMPTY;
else if( *buf == '[' && buf[1] == '.' )
i->flags = DIR_DOTDIR;
else if( *buf == '[' && buf[1] == '-' )
i->flags = DIR_DASHDIR;
if ( ( *buf == '[' ) && ( buf[1] == ']' ) )
i->flags = DIR_EMPTY;
else if ( ( *buf == '[' ) && ( buf[1] == '.' ) )
i->flags = DIR_DOTDIR;
else if ( ( *buf == '[' ) && ( buf[1] == '-' ) )
i->flags = DIR_DASHDIR;
else
i->flags = DIR_ABSDIR;
i->flags = DIR_ABSDIR;
}
/* But if its rooted in any way */
/* But if its rooted in any way. */
if( i->dir.len == 8 && !strncmp( i->dir.ptr, "[000000]", 8 ) )
if ( ( i->dir.len == 8 ) && !strncmp( i->dir.ptr, "[000000]", 8 ) )
i->flags = DIR_ROOT;
}
/*
* path_build() - build a filename given dir/base/suffix/member
*/
void
path_build(
PATHNAME *f,
string *file,
int binding )
void path_build( PATHNAME * f, string * file, int binding )
{
struct dirinf root, dir;
struct dirinf root;
struct dirinf dir;
int g;
file_build1( f, file );
/* Get info on root and dir for combining. */
dir_flags( f->f_root.ptr, f->f_root.len, &root );
dir_flags( f->f_dir.ptr, f->f_dir.len, &dir );
/* Combine */
switch( g = grid[ root.flags ][ dir.flags ] )
/* Combine. */
switch ( g = grid[ root.flags ][ dir.flags ] )
{
case G_DIR:
/* take dir */
@@ -277,12 +263,12 @@ path_build(
/* sanity checks: root ends with ] */
if( file->value[file->size - 1] == ']' )
if ( file->value[file->size - 1] == ']' )
string_pop_back( file );
/* Add . if separating two -'s */
if( g == G_DDD )
if ( g == G_DDD )
string_push_back( file, '.' );
/* skip [ of dir */
@@ -299,11 +285,9 @@ path_build(
}
# ifdef DEBUG
if( DEBUG_SEARCH && ( root.flags || dir.flags ) )
{
if ( DEBUG_SEARCH && ( root.flags || dir.flags ) )
printf( "%d x %d = %d (%s)\n", root.flags, dir.flags,
grid[ root.flags ][ dir.flags ], file->value );
}
# endif
/*
@@ -315,35 +299,38 @@ path_build(
* [] []
*/
if( file->value[file->size - 1] == ']' && f->parent )
if ( ( file->value[ file->size - 1 ] == ']' ) && f->parent )
{
char* p = file->value + file->size;
while( p-- > file->value )
char * p = file->value + file->size;
while ( p-- > file->value )
{
if( *p == '.' )
if ( *p == '.' )
{
/* If we've truncated everything and left with '[',
return empty string. */
if (p == file->value + 1)
if ( p == file->value + 1 )
string_truncate( file, 0 );
else {
else
{
string_truncate( file, p - file->value );
string_push_back( file, ']' );
}
break;
}
else if( *p == '-' )
if ( *p == '-' )
{
/* handle .- or - */
if( p > file->value && p[-1] == '.' )
if ( ( p > file->value ) && ( p[ -1 ] == '.' ) )
--p;
*p++ = ']';
break;
}
else if( *p == '[' )
if ( *p == '[' )
{
if( p[1] == ']' )
if ( p[ 1 ] == ']' )
{
/* CONSIDER: I don't see any use of this code. We immediately
break, and 'p' is a local variable. */
@@ -360,26 +347,21 @@ path_build(
}
/* Now copy the file pieces. */
if( f->f_base.len )
if ( f->f_base.len )
{
string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len );
}
/* If there is no suffix, we append a "." onto all generated */
/* names. This keeps VMS from appending its own (wrong) idea */
/* of what the suffix should be. */
if( f->f_suffix.len )
{
/* If there is no suffix, we append a "." onto all generated names. This
* keeps VMS from appending its own (wrong) idea of what the suffix should
* be.
*/
if ( f->f_suffix.len )
string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len );
}
else if( binding && f->f_base.len )
{
else if ( binding && f->f_base.len )
string_push_back( file, '.' );
}
if( f->f_member.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 );
@@ -387,8 +369,8 @@ path_build(
}
# ifdef DEBUG
if( DEBUG_SEARCH )
printf("built %.*s + %.*s / %.*s suf %.*s mem %.*s -> %s\n",
if ( DEBUG_SEARCH )
printf( "built %.*s + %.*s / %.*s suf %.*s mem %.*s -> %s\n",
f->f_root.len, f->f_root.ptr,
f->f_dir.len, f->f_dir.ptr,
f->f_base.len, f->f_base.ptr,
@@ -398,14 +380,14 @@ path_build(
# endif
}
/*
* path_parent() - make a PATHNAME point to its parent dir
*/
void
path_parent( PATHNAME *f )
void path_parent( PATHNAME * f )
{
if( f->f_base.len )
if ( f->f_base.len )
{
f->f_base.ptr =
f->f_suffix.ptr =

View File

@@ -37,53 +37,54 @@
*** THIS IS AN ALTERED VERSION. It was altered by Christopher Seiwald
*** seiwald@perforce.com, on 20 January 2000, to use function prototypes.
*
* Beware that some of this code is subtly aware of the way operator
* precedence is structured in regular expressions. Serious changes in
* regular-expression syntax might require a total rethink.
* Beware that some of this code is subtly aware of the way operator precedence
* is structured in regular expressions. Serious changes in regular-expression
* syntax might require a total rethink.
*/
#include "jam.h"
#include "regexp.h"
#include <stdio.h>
#include <ctype.h>
#ifndef ultrix
#include <stdlib.h>
#include <stdlib.h>
#endif
#include <string.h>
/*
* The "internal use only" fields in regexp.h are present to pass info from
* compile to execute that permits the execute phase to run lots faster on
* simple cases. They are:
*
* regstart char that must begin a match; '\0' if none obvious
* reganch is the match anchored (at beginning-of-line only)?
* regmust string (pointer into program) that match must include, or NULL
* regmlen length of regmust string
* simple cases. They are:
:
* regstart char that must begin a match; '\0' if none obvious.
* reganch is the match anchored (at beginning-of-line only)?
* regmust string (pointer into program) that match must include, or NULL.
* regmlen length of regmust string.
*
* Regstart and reganch permit very fast decisions on suitable starting points
* for a match, cutting down the work a lot. Regmust permits fast rejection
* of lines that cannot possibly match. The regmust tests are costly enough
* that regcomp() supplies a regmust only if the r.e. contains something
* potentially expensive (at present, the only such thing detected is * or +
* at the start of the r.e., which can involve a lot of backup). Regmlen is
* supplied because the test in regexec() needs it and regcomp() is computing
* it anyway.
* for a match, cutting down the work a lot. Regmust permits fast rejection of
* lines that cannot possibly match. The regmust tests are costly enough that
* regcomp() supplies a regmust only if the r.e. contains something potentially
* expensive (at present, the only such thing detected is * or + at the start of
* the r.e., which can involve a lot of backup). Regmlen is supplied because the
* test in regexec() needs it and regcomp() is computing it anyway.
*/
/*
* Structure for regexp "program". This is essentially a linear encoding
* of a nondeterministic finite-state machine (aka syntax charts or
* "railroad normal form" in parsing technology). Each node is an opcode
* plus a "next" pointer, possibly plus an operand. "Next" pointers of
* all nodes except BRANCH implement concatenation; a "next" pointer with
* a BRANCH on both ends of it is connecting two alternatives. (Here we
* have one of the subtle syntax dependencies: an individual BRANCH (as
* opposed to a collection of them) is never concatenated with anything
* because of operator precedence.) The operand of some types of node is
* a literal string; for others, it is a node leading into a sub-FSM. In
* particular, the operand of a BRANCH node is the first node of the branch.
* (NB this is *not* a tree structure: the tail of the branch connects
* to the thing following the set of BRANCHes.) The opcodes are:
* Structure for regexp "program". This is essentially a linear encoding of a
* nondeterministic finite-state machine (aka syntax charts or "railroad normal
* form" in parsing technology). Each node is an opcode plus a "next" pointer,
* possibly plus an operand. "Next" pointers of all nodes except BRANCH
* implement concatenation; a "next" pointer with a BRANCH on both ends of it is
* connecting two alternatives. [Here we have one of the subtle syntax
* dependencies: an individual BRANCH, as opposed to a collection of them, is
* never concatenated with anything because of operator precedence.] The operand
* of some types of node is a literal string; for others, it is a node leading
* into a sub-FSM. In particular, the operand of a BRANCH node is the first node
* of the branch. [NB this is *not* a tree structure: the tail of the branch
* connects to the thing following the set of BRANCHes.] The opcodes are:
*/
/* definition number opnd? meaning */
@@ -105,6 +106,7 @@
/* OPEN+1 is number 1, etc. */
#define CLOSE 30 /* no Analogous to OPEN. */
/*
* Opcode notes:
*
@@ -809,23 +811,25 @@ regexec(
}
/* If there is a "must appear" string, look for it. */
if (prog->regmust != NULL) {
if ( prog->regmust != NULL )
{
s = (char *)string;
while ((s = strchr(s, prog->regmust[0])) != NULL) {
if (strncmp(s, prog->regmust, prog->regmlen) == 0)
while ( ( s = strchr( s, prog->regmust[ 0 ] ) ) != NULL )
{
if ( !strncmp( s, prog->regmust, prog->regmlen ) )
break; /* Found it. */
s++;
++s;
}
if (s == NULL) /* Not present. */
return(0);
if ( s == NULL ) /* Not present. */
return 0;
}
/* Mark beginning of line for ^ . */
regbol = (char *)string;
/* Simplest case: anchored match need be tried only once. */
if (prog->reganch)
return(regtry(prog, string));
if ( prog->reganch )
return regtry( prog, string );
/* Messy cases: unanchored match. */
s = (char *)string;
@@ -837,27 +841,29 @@ regexec(
s++;
}
else
/* We don't -- general case. */
/* We do not -- general case. */
do {
if (regtry(prog, s))
return(1);
} while (*s++ != '\0');
if ( regtry( prog, s ) )
return( 1 );
} while ( *s++ != '\0' );
/* Failure. */
return(0);
return 0;
}
/*
- regtry - try match at specific point
* regtry() - try match at specific point.
*/
static int /* 0 failure, 1 success */
regtry(
regexp *prog,
char *string )
{
register int i;
register char **sp;
register char **ep;
register char * * sp;
register char * * ep;
reginput = string;
regstartp = prog->startp;
@@ -865,33 +871,37 @@ regtry(
sp = prog->startp;
ep = prog->endp;
for (i = NSUBEXP; i > 0; i--) {
for ( i = NSUBEXP; i > 0; --i )
{
*sp++ = NULL;
*ep++ = NULL;
}
if (regmatch(prog->program + 1)) {
prog->startp[0] = string;
prog->endp[0] = reginput;
return(1);
} else
return(0);
if ( regmatch( prog->program + 1 ) )
{
prog->startp[ 0 ] = string;
prog->endp[ 0 ] = reginput;
return 1;
}
else
return 0;
}
/*
- regmatch - main matching routine
* regmatch() - main matching routine.
*
* Conceptually the strategy is simple: check to see whether the current
* node matches, call self recursively to see whether the rest matches,
* and then act accordingly. In practice we make some effort to avoid
* recursion, in particular by going through "ordinary" nodes (that don't
* need to know whether the rest of the match failed) by a loop instead of
* by recursion.
* Conceptually the strategy is simple: check to see whether the current node
* matches, call self recursively to see whether the rest matches, and then act
* accordingly. In practice we make some effort to avoid recursion, in
* particular by going through "ordinary" nodes (that do not need to know
* whether the rest of the match failed) by a loop instead of by recursion.
*/
static int /* 0 failure, 1 success */
regmatch( char *prog )
regmatch( char * prog )
{
register char *scan; /* Current node. */
char *next; /* Next node. */
char * scan; /* Current node. */
char * next; /* Next node. */
scan = prog;
#ifdef DEBUG

View File

@@ -28,45 +28,44 @@
*
* External routines:
*
* bindrule() - return pointer to RULE, creating it if necessary
* bindtarget() - return pointer to TARGET, creating it if necessary
* touchtarget() - mark a target to simulate being new
* targetlist() - turn list of target names into a TARGET chain
* targetentry() - add a TARGET to a chain of TARGETS
* actionlist() - append to an ACTION chain
* addsettings() - add a deferred "set" command to a target
#ifndef OPT_FIX_TARGET_VARIABLES_EXT
* usesettings() - set all target specific variables
#endif
* pushsettings() - set all target specific variables
* popsettings() - reset target specific variables to their pre-push values
* freesettings() - delete a settings list
* donerules() - free RULE and TARGET tables
* 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.
* targetlist() - turn list of target names into a TARGET chain.
* targetentry() - add a TARGET to a chain of TARGETS.
* actionlist() - append to an ACTION chain.
* addsettings() - add a deferred "set" command to a target.
* pushsettings() - set all target specific variables.
* 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)
*/
static void set_rule_actions( RULE* rule, rule_actions* actions );
static void set_rule_body( RULE* rule, argument_list* args, PARSE* procedure );
static struct hash *targethash = 0;
static void set_rule_actions( RULE *, rule_actions * );
static void set_rule_body ( RULE *, argument_list *, PARSE * procedure );
typedef struct _located_target LOCATED_TARGET ;
static struct hash * targethash = 0;
struct _located_target
{
char * file_name;
TARGET * target;
};
typedef struct _located_target LOCATED_TARGET ;
static struct hash * located_targets = 0;
/*
* add_include() - adds the 'included' TARGET to the list of targets included by
* the 'including' TARGET. Such targets are modeled as dependencies of the
* target_include() - adds the 'included' TARGET to the list of targets included
* by the 'including' TARGET. Such targets are modeled as dependencies of the
* internal include node belonging to the 'including' TARGET.
*/
void add_include( TARGET * including, TARGET * included )
void target_include( TARGET * including, TARGET * included )
{
TARGET * internal;
if ( !including->includes )
@@ -83,6 +82,7 @@ void add_include( TARGET * including, TARGET * included )
* enter_rule() - return pointer to RULE, creating it if necessary in
* target_module.
*/
static RULE * enter_rule( char * rulename, module_t * target_module )
{
RULE rule;
@@ -145,52 +145,53 @@ void rule_free( RULE * r )
r->actions = 0;
}
/*
* bindtarget() - return pointer to TARGET, creating it if necessary
* bindtarget() - return pointer to TARGET, creating it if necessary.
*/
TARGET *
bindtarget( const char *targetname )
TARGET * bindtarget( char const * target_name )
{
TARGET target, *t = &target;
TARGET target;
TARGET * t = &target;
if( !targethash )
if ( !targethash )
targethash = hashinit( sizeof( TARGET ), "targets" );
/* Perforce added const everywhere. No time to merge that change. */
#ifdef NT
targetname = short_path_to_long_path( (char*)targetname );
target_name = short_path_to_long_path( (char *)target_name );
#endif
t->name = (char*)targetname;
t->name = (char *)target_name;
if( hashenter( targethash, (HASHDATA **)&t ) )
if ( hashenter( targethash, (HASHDATA * *)&t ) )
{
memset( (char *)t, '\0', sizeof( *t ) );
t->name = newstr( (char*)targetname ); /* never freed */
t->boundname = t->name; /* default for T_FLAG_NOTFILE */
t->name = newstr( (char *)target_name ); /* never freed */
t->boundname = t->name; /* default for T_FLAG_NOTFILE */
}
return t;
}
static void bind_explicitly_located_target(void* xtarget, void* data)
static void bind_explicitly_located_target( void * xtarget, void * data )
{
TARGET* t = (TARGET*)xtarget;
if (! (t->flags & T_FLAG_NOTFILE) )
TARGET * t = (TARGET *)xtarget;
if ( !( t->flags & T_FLAG_NOTFILE ) )
{
/* Check if there's a setting for LOCATE */
SETTINGS* s = t->settings;
for(; s ; s = s->next)
SETTINGS * s = t->settings;
for ( ; s ; s = s->next )
{
if (strcmp(s->symbol, "LOCATE") == 0)
if ( strcmp( s->symbol, "LOCATE" ) == 0 )
{
pushsettings(t->settings);
/* We're binding a target with explicit LOCATE. So
third argument is of now use: nothing will be returned
through it. */
pushsettings( t->settings );
/* We are binding a target with explicit LOCATE. So third
* argument is of no use: nothing will be returned through it.
*/
t->boundname = search( t->name, &t->time, 0, 0 );
popsettings(t->settings);
popsettings( t->settings );
break;
}
}
@@ -200,24 +201,25 @@ static void bind_explicitly_located_target(void* xtarget, void* data)
void bind_explicitly_located_targets()
{
if (targethash)
hashenumerate(targethash, bind_explicitly_located_target, (void*)0);
if ( targethash )
hashenumerate( targethash, bind_explicitly_located_target, (void *)0 );
}
/* TODO: it is probably not a good idea to use functions in other modules like
that. */
void call_bind_rule(char* target, char* boundname);
/* TODO: It is probably not a good idea to use functions in other modules like
this. */
void call_bind_rule( char * target, char * boundname );
TARGET* search_for_target ( char * name, LIST* search_path )
TARGET * search_for_target ( char * name, LIST * search_path )
{
PATHNAME f[1];
string buf[1];
LOCATED_TARGET lt, *lta = &lt;
LOCATED_TARGET lt;
LOCATED_TARGET * lta = &lt;
time_t time;
int found = 0;
TARGET* result;
TARGET * result;
string_new( buf );
@@ -226,7 +228,7 @@ TARGET* search_for_target ( char * name, LIST* search_path )
f->f_grist.ptr = 0;
f->f_grist.len = 0;
while( search_path )
while ( search_path )
{
f->f_root.ptr = search_path->string;
f->f_root.len = strlen( search_path->string );
@@ -236,18 +238,17 @@ TARGET* search_for_target ( char * name, LIST* search_path )
lt.file_name = buf->value ;
if (! located_targets )
if ( !located_targets )
located_targets = hashinit( sizeof(LOCATED_TARGET),
"located targets" );
if ( hashcheck( located_targets, (HASHDATA **)&lta ) )
if ( hashcheck( located_targets, (HASHDATA * *)&lta ) )
{
return lta->target;
}
timestamp( buf->value, &time );
if (time)
if ( time )
{
found = 1;
break;
@@ -256,7 +257,7 @@ TARGET* search_for_target ( char * name, LIST* search_path )
search_path = list_next( search_path );
}
if ( ! found )
if ( !found )
{
f->f_root.ptr = 0;
f->f_root.len = 0;
@@ -281,16 +282,14 @@ TARGET* search_for_target ( char * name, LIST* search_path )
/*
* copytarget() - make a new target with the old target's name
* copytarget() - make a new target with the old target's name.
*
* Not entered into hash table -- for internal nodes.
*/
TARGET * copytarget( const TARGET * ot )
{
TARGET *t;
t = (TARGET *)BJAM_MALLOC( sizeof( *t ) );
TARGET * t = (TARGET *)BJAM_MALLOC( sizeof( *t ) );
memset( (char *)t, '\0', sizeof( *t ) );
t->name = copystr( ot->name );
t->boundname = t->name;
@@ -300,56 +299,47 @@ TARGET * copytarget( const TARGET * ot )
return t;
}
/*
* touchtarget() - mark a target to simulate being new
* touch_target() - mark a target to simulate being new.
*/
void
touchtarget( char *t )
void touch_target( char * t )
{
bindtarget( t )->flags |= T_FLAG_TOUCHED;
}
/*
* targetlist() - turn list of target names into a TARGET chain
* targetlist() - turn list of target names into a TARGET chain.
*
* Inputs:
* chain existing TARGETS to append to
* targets list of target names
*/
TARGETS *
targetlist(
TARGETS *chain,
LIST *targets )
TARGETS * targetlist( TARGETS * chain, LIST * target_names )
{
for( ; targets; targets = list_next( targets ) )
chain = targetentry( chain, bindtarget( targets->string ) );
for ( ; target_names; target_names = list_next( target_names ) )
chain = targetentry( chain, bindtarget( target_names->string ) );
return chain;
}
/*
* targetentry() - add a TARGET to a chain of TARGETS
* targetentry() - add a TARGET to a chain of TARGETS.
*
* Inputs:
* chain existing TARGETS to append to
* target new target to append
*/
TARGETS *
targetentry(
TARGETS *chain,
TARGET *target )
TARGETS * targetentry( TARGETS * chain, TARGET * target )
{
TARGETS *c;
c = (TARGETS *)BJAM_MALLOC( sizeof( TARGETS ) );
TARGETS * c = (TARGETS *)BJAM_MALLOC( sizeof( TARGETS ) );
c->target = target;
if( !chain ) chain = c;
if ( !chain ) chain = c;
else chain->tail->next = c;
chain->tail = c;
c->next = 0;
@@ -357,25 +347,21 @@ targetentry(
return chain;
}
/*
* targetchain() - append two TARGET chains
* targetchain() - append two TARGET chains.
*
* Inputs:
* chain exisitng TARGETS to append to
* target new target to append
*/
TARGETS *
targetchain(
TARGETS *chain,
TARGETS *targets )
TARGETS * targetchain( TARGETS * chain, TARGETS * targets )
{
TARGETS *c;
TARGETS * c;
if( !targets )
return chain;
else if( !chain )
return targets;
if ( !targets ) return chain;
if ( !chain ) return targets;
chain->tail->next = targets;
chain->tail = targets->tail;
@@ -384,19 +370,16 @@ targetchain(
}
/*
* actionlist() - append to an ACTION chain
* actionlist() - append to an ACTION chain.
*/
ACTIONS *
actionlist(
ACTIONS *chain,
ACTION *action )
ACTIONS * actionlist( ACTIONS * chain, ACTION * action )
{
ACTIONS *actions = (ACTIONS *)BJAM_MALLOC( sizeof( ACTIONS ) );
ACTIONS * actions = (ACTIONS *)BJAM_MALLOC( sizeof( ACTIONS ) );
actions->action = action;
if( !chain ) chain = actions;
if ( !chain ) chain = actions;
else chain->tail->next = actions;
chain->tail = actions;
actions->next = 0;
@@ -404,126 +387,105 @@ actionlist(
return chain;
}
static SETTINGS* settings_freelist;
static SETTINGS * settings_freelist;
/*
* addsettings() - add a deferred "set" command to a target
* addsettings() - add a deferred "set" command to a target.
*
* 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 chain of settings.
* 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.
*/
SETTINGS *
addsettings(
SETTINGS *head,
int flag,
char *symbol,
LIST *value )
SETTINGS * addsettings( SETTINGS * head, int flag, char * symbol, LIST * value )
{
SETTINGS *v;
SETTINGS * v;
/* Look for previous setting */
for( v = head; v; v = v->next )
if( !strcmp( v->symbol, symbol ) )
break;
/* Look for previous settings. */
for ( v = head; v; v = v->next )
if ( !strcmp( v->symbol, symbol ) )
break;
/* If not previously set, alloc a new. */
/* If appending, do so. */
/* Else free old and set new. */
if( !v )
if ( !v )
{
v = settings_freelist;
if ( v )
settings_freelist = v->next;
else
{
v = (SETTINGS *)BJAM_MALLOC( sizeof( *v ) );
}
v->symbol = newstr( symbol );
v->value = value;
v->next = head;
head = v;
}
else if( flag == VAR_APPEND )
else if ( flag == VAR_APPEND )
{
v->value = list_append( v->value, value );
}
else if( flag != VAR_DEFAULT )
else if ( flag != VAR_DEFAULT )
{
list_free( v->value );
v->value = value;
}
else
list_free( value );
else
list_free( value );
/* Return (new) head of list. */
return head;
}
/*
* pushsettings() - set all target specific variables
* pushsettings() - set all target specific variables.
*/
void
pushsettings( SETTINGS *v )
void pushsettings( SETTINGS * v )
{
for( ; v; v = v->next )
for ( ; v; v = v->next )
v->value = var_swap( v->symbol, v->value );
}
/*
* popsettings() - reset target specific variables to their pre-push values
* popsettings() - reset target specific variables to their pre-push values.
*/
void
popsettings( SETTINGS *v )
void popsettings( SETTINGS * v )
{
pushsettings( v ); /* just swap again */
}
/*
* copysettings() - duplicate a settings list, returning the new copy
* copysettings() - duplicate a settings list, returning the new copy.
*/
SETTINGS*
copysettings( SETTINGS *head )
SETTINGS * copysettings( SETTINGS * head )
{
SETTINGS *copy = 0, *v;
for (v = head; v; v = v->next)
copy = addsettings(copy, VAR_SET, v->symbol, list_copy(0, v->value));
SETTINGS * copy = 0;
SETTINGS * v;
for ( v = head; v; v = v->next )
copy = addsettings( copy, VAR_SET, v->symbol, list_copy( 0, v->value ) );
return copy;
}
/*
* freetargets() - delete a targets list
*/
void freetargets( TARGETS *chain )
{
while( chain )
{
TARGETS* n = chain->next;
BJAM_FREE( chain );
chain = n;
}
}
/*
* freeactions() - delete an action list
* freetargets() - delete a targets list.
*/
void freeactions( ACTIONS *chain )
void freetargets( TARGETS * chain )
{
while( chain )
while ( chain )
{
ACTIONS* n = chain->next;
TARGETS * n = chain->next;
BJAM_FREE( chain );
chain = n;
}
@@ -531,111 +493,132 @@ void freeactions( ACTIONS *chain )
/*
* freesettings() - delete a settings list
* freeactions() - delete an action list.
*/
void
freesettings( SETTINGS *v )
void freeactions( ACTIONS * chain )
{
while( v )
while ( chain )
{
SETTINGS *n = v->next;
ACTIONS * n = chain->next;
BJAM_FREE( chain );
chain = n;
}
}
/*
* freesettings() - delete a settings list.
*/
void freesettings( SETTINGS * v )
{
while ( v )
{
SETTINGS * n = v->next;
freestr( v->symbol );
list_free( v->value );
v->next = settings_freelist;
settings_freelist = v;
v = n;
}
}
static void freetarget( void *xt, void *data )
static void freetarget( void * xt, void * data )
{
TARGET* t = (TARGET *)xt;
if ( t->settings )
freesettings( t->settings );
if ( t->depends )
freetargets( t->depends );
if ( t->includes )
freetarget( t->includes, (void*)0);
if ( t->actions )
freeactions( t->actions );
TARGET * t = (TARGET *)xt;
if ( t->settings ) freesettings( t->settings );
if ( t->depends ) freetargets ( t->depends );
if ( t->includes ) freetarget ( t->includes, (void *)0 );
if ( t->actions ) freeactions ( t->actions );
}
/*
* donerules() - free TARGET tables
* rules_done() - free RULE and TARGET tables.
*/
void
donerules()
void rules_done()
{
hashenumerate( targethash, freetarget, 0 );
hashenumerate( targethash, freetarget, 0 );
hashdone( targethash );
while ( settings_freelist )
{
SETTINGS* n = settings_freelist->next;
SETTINGS * n = settings_freelist->next;
BJAM_FREE( settings_freelist );
settings_freelist = n;
}
}
/*
* args_new() - make a new reference-counted argument list
* args_new() - make a new reference-counted argument list.
*/
argument_list* args_new()
argument_list * args_new()
{
argument_list* r = (argument_list*)BJAM_MALLOC( sizeof(argument_list) );
argument_list * r = (argument_list *)BJAM_MALLOC( sizeof(argument_list) );
r->reference_count = 0;
lol_init(r->data);
lol_init( r->data );
return r;
}
/*
* args_refer() - add a new reference to the given argument list
* args_refer() - add a new reference to the given argument list.
*/
void args_refer( argument_list* a )
void args_refer( argument_list * a )
{
++a->reference_count;
}
/*
* args_free() - release a reference to the given argument list
* args_free() - release a reference to the given argument list.
*/
void args_free( argument_list* a )
void args_free( argument_list * a )
{
if (--a->reference_count <= 0)
if ( --a->reference_count <= 0 )
{
lol_free(a->data);
BJAM_FREE(a);
lol_free( a->data );
BJAM_FREE( a );
}
}
/*
* actions_refer() - add a new reference to the given actions
* actions_refer() - add a new reference to the given actions.
*/
void actions_refer(rule_actions* a)
void actions_refer( rule_actions * a )
{
++a->reference_count;
}
/*
* actions_free() - release a reference to the given actions
* actions_free() - release a reference to the given actions.
*/
void actions_free(rule_actions* a)
void actions_free( rule_actions * a )
{
if (--a->reference_count <= 0)
if ( --a->reference_count <= 0 )
{
freestr(a->command);
list_free(a->bindlist);
BJAM_FREE(a);
freestr( a->command );
list_free( a->bindlist );
BJAM_FREE( a );
}
}
/*
* set_rule_body() - set the argument list and procedure of the given rule
* set_rule_body() - set the argument list and procedure of the given rule.
*/
static void set_rule_body( RULE* rule, argument_list* args, PARSE* procedure )
static void set_rule_body( RULE * rule, argument_list * args, PARSE * procedure )
{
if ( args )
args_refer( args );
@@ -650,59 +633,61 @@ static void set_rule_body( RULE* rule, argument_list* args, PARSE* procedure )
rule->procedure = procedure;
}
/*
* global_name() - given a rule, return the name for a corresponding rule in the global module
* global_name() - given a rule, return the name for a corresponding rule in the
* global module.
*/
static char* global_rule_name( RULE* r )
static char * global_rule_name( RULE * r )
{
if ( r->module == root_module() )
{
return r->name;
}
else
{
char name[4096] = "";
strncat(name, r->module->name, sizeof(name) - 1);
strncat(name, r->name, sizeof(name) - 1 );
return newstr(name);
strncat( name, r->module->name, sizeof( name ) - 1 );
strncat( name, r->name, sizeof( name ) - 1 );
return newstr( name);
}
}
/*
* global_rule() - given a rule, produce the corresponding entry in the global module
* global_rule() - given a rule, produce the corresponding entry in the global
* module.
*/
static RULE* global_rule( RULE* r )
static RULE * global_rule( RULE * r )
{
if ( r->module == root_module() )
{
return r;
}
else
{
char* name = global_rule_name( r );
RULE* result = define_rule( r->module, name, root_module() );
freestr(name);
char * name = global_rule_name( r );
RULE * result = define_rule( r->module, name, root_module() );
freestr( name );
return result;
}
}
/*
* new_rule_body() - make a new rule named rulename in the given
* module, with the given argument list and procedure. If exported is
* true, the rule is exported to the global module as
* modulename.rulename.
* new_rule_body() - make a new rule named rulename in the given module, with
* the given argument list and procedure. If exported is true, the rule is
* exported to the global module as modulename.rulename.
*/
RULE* new_rule_body( module_t* m, char* rulename, argument_list* args, PARSE* procedure, int exported )
RULE * new_rule_body( module_t * m, char * rulename, argument_list * args, PARSE * procedure, int exported )
{
RULE* local = define_rule( m, rulename, m );
RULE * local = define_rule( m, rulename, m );
local->exported = exported;
set_rule_body( local, args, procedure );
/* Mark the procedure with the global rule name, regardless of
* whether the rule is exported. That gives us something
* reasonably identifiable that we can use, e.g. in profiling
* output. Only do this once, since this could be called multiple
* times with the same procedure.
/* Mark the procedure with the global rule name, regardless of whether the
* rule is exported. That gives us something reasonably identifiable that we
* can use, e.g. in profiling output. Only do this once, since this could be
* called multiple times with the same procedure.
*/
if ( procedure->rulename == 0 )
procedure->rulename = global_rule_name( local );
@@ -710,19 +695,20 @@ RULE* new_rule_body( module_t* m, char* rulename, argument_list* args, PARSE* pr
return local;
}
static void set_rule_actions( RULE* rule, rule_actions* actions )
static void set_rule_actions( RULE * rule, rule_actions * actions )
{
if ( actions )
actions_refer( actions );
if ( rule->actions )
actions_free( rule->actions );
rule->actions = actions;
}
static rule_actions* actions_new( char* command, LIST* bindlist, int flags )
static rule_actions * actions_new( char * command, LIST * bindlist, int flags )
{
rule_actions* result = (rule_actions*)BJAM_MALLOC(sizeof(rule_actions));
rule_actions * result = (rule_actions *)BJAM_MALLOC( sizeof( rule_actions ) );
result->command = copystr( command );
result->bindlist = bindlist;
result->flags = flags;
@@ -730,88 +716,95 @@ static rule_actions* actions_new( char* command, LIST* bindlist, int flags )
return result;
}
RULE* new_rule_actions( module_t* m, char* rulename, char* command, LIST* bindlist, int flags )
RULE * new_rule_actions( module_t * m, char * rulename, char * command, LIST * bindlist, int flags )
{
RULE* local = define_rule( m, rulename, m );
RULE* global = global_rule( local );
RULE * local = define_rule( m, rulename, m );
RULE * global = global_rule( local );
set_rule_actions( local, actions_new( command, bindlist, flags ) );
set_rule_actions( global, local->actions );
return local;
}
/* 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 modules, look in module 'name1' for rule 'name2'.
*/
RULE *lookup_rule( char *rulename, module_t *m, int local_only )
/*
* 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
* modules, look in module 'name1' for rule 'name2'.
*/
RULE * lookup_rule( char * rulename, module_t * m, int local_only )
{
RULE rule, *r = &rule, *result = 0;
module_t* original_module = m;
RULE rule;
RULE * r = &rule;
RULE * result = 0;
module_t * original_module = m;
r->name = rulename;
if (m->class_module)
if ( m->class_module )
m = m->class_module;
if (m->rules && hashcheck( m->rules, (HASHDATA **)&r ) )
if ( m->rules && hashcheck( m->rules, (HASHDATA * *)&r ) )
result = r;
else if (!local_only && m->imported_modules) {
else if ( !local_only && m->imported_modules )
{
/* Try splitting the name into module and rule. */
char *p = strchr(r->name, '.') ;
if (p) {
char *p = strchr( r->name, '.' ) ;
if ( p )
{
*p = '\0';
/* Now, r->name keeps the module name, and p+1 keeps the rule name. */
if (hashcheck( m->imported_modules, (HASHDATA **)&r))
{
result = lookup_rule(p+1, bindmodule(rulename), 1);
}
/* Now, r->name keeps the module name, and p+1 keeps the rule name.
*/
if ( hashcheck( m->imported_modules, (HASHDATA * *)&r ) )
result = lookup_rule( p + 1, bindmodule( rulename ), 1 );
*p = '.';
}
}
if (result)
if ( result )
{
if (local_only && !result->exported)
if ( local_only && !result->exported )
result = 0;
else
{
/* Lookup started in class module. We've 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've started 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))
/* 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 ) )
result->module = original_module;
}
}
return result;
}
RULE *bindrule( char *rulename, module_t* m)
RULE * bindrule( char * rulename, module_t * m )
{
RULE *result;
result = lookup_rule(rulename, m, 0);
if (!result)
result = lookup_rule(rulename, root_module(), 0);
/* We've only one caller, 'evaluate_rule', which will complain about
calling underfined rule. We could issue the error
here, but we don't have necessary information, such as frame.
*/
if (!result)
RULE * result = lookup_rule( rulename, m, 0 );
if ( !result )
result = lookup_rule( rulename, root_module(), 0 );
/* We have only one caller, 'evaluate_rule', which will complain about
* calling an undefined rule. We could issue the error here, but we do not
* have the necessary information, such as frame.
*/
if ( !result )
result = enter_rule( rulename, m );
return result;
}
RULE* import_rule( RULE* source, module_t* m, char* name )
RULE * import_rule( RULE * source, module_t * m, char * name )
{
RULE* dest = define_rule( source->module, name, m );
RULE * dest = define_rule( source->module, name, m );
set_rule_body( dest, source->arguments, source->procedure );
set_rule_actions( dest, source->actions );
return dest;

View File

@@ -11,11 +11,12 @@
*/
#ifndef RULES_DWA_20011020_H
# define RULES_DWA_20011020_H
#define RULES_DWA_20011020_H
#include "modules.h"
#include "jam.h"
#include "parse.h"
# include "modules.h"
# include "jam.h"
# include "parse.h"
/*
* rules.h - targets, rules, and related information
@@ -26,12 +27,12 @@
*
* The following are defined:
*
* RULE - a generic jam rule, the product of RULE and ACTIONS
* ACTIONS - a chain of ACTIONs
* ACTION - a RULE instance with targets and sources
* SETTINGS - variables to set when executing a TARGET's ACTIONS
* TARGETS - a chain of TARGETs
* TARGET - a file or "thing" that can be built
* RULE - a generic jam rule, the product of RULE and ACTIONS.
* ACTIONS - a chain of ACTIONs.
* ACTION - a RULE instance with targets and sources.
* 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.
@@ -49,29 +50,29 @@ typedef struct _action ACTION;
typedef struct _actions ACTIONS;
typedef struct _settings SETTINGS ;
/* RULE - a generic jam rule, the product of RULE and ACTIONS */
/* RULE - a generic jam rule, the product of RULE and ACTIONS. */
/* A rule's argument list */
/* A rule's argument list. */
struct argument_list
{
int reference_count;
LOL data[1];
};
/* The build actions corresponding to a rule */
/* Build actions corresponding to a rule. */
struct rule_actions
{
int reference_count;
char* command; /* command string from ACTIONS */
LIST* bindlist;
int flags; /* modifiers on ACTIONS */
int reference_count;
char * command; /* command string from ACTIONS */
LIST * bindlist;
int flags; /* modifiers on ACTIONS */
# define RULE_NEWSRCS 0x01 /* $(>) is updated sources only */
# define RULE_TOGETHER 0x02 /* combine actions on single target */
# define RULE_IGNORE 0x04 /* ignore return status of executes */
# define RULE_QUIETLY 0x08 /* don't mention it unless verbose */
# define RULE_PIECEMEAL 0x10 /* split exec so each $(>) is small */
# define RULE_EXISTING 0x20 /* $(>) is pre-exisitng sources only */
#define RULE_NEWSRCS 0x01 /* $(>) is updated sources only */
#define RULE_TOGETHER 0x02 /* combine actions on single target */
#define RULE_IGNORE 0x04 /* ignore return status of executes */
#define RULE_QUIETLY 0x08 /* do not mention it unless verbose */
#define RULE_PIECEMEAL 0x10 /* split exec so each $(>) is small */
#define RULE_EXISTING 0x20 /* $(>) is pre-exisitng sources only */
};
typedef struct rule_actions rule_actions;
@@ -94,175 +95,183 @@ struct _rule
#endif
};
/* ACTIONS - a chain of ACTIONs */
/* ACTIONS - a chain of ACTIONs. */
struct _actions
{
ACTIONS * next;
ACTIONS * tail; /* valid only for head */
ACTION * action;
};
struct _actions {
ACTIONS *next;
ACTIONS *tail; /* valid only for head */
ACTION *action;
} ;
/* ACTION - a RULE instance with targets and sources. */
struct _action
{
RULE * rule;
TARGETS * targets;
TARGETS * sources; /* aka $(>) */
char running; /* has been started */
char status; /* see TARGET status */
};
/* ACTION - a RULE instance with targets and sources */
/* SETTINGS - variables to set when executing a TARGET's ACTIONS. */
struct _settings
{
SETTINGS * next;
char * symbol; /* symbol name for var_set() */
LIST * value; /* symbol value for var_set() */
};
struct _action {
RULE *rule;
TARGETS *targets;
TARGETS *sources; /* aka $(>) */
char running; /* has been started */
char status; /* see TARGET status */
} ;
/* TARGETS - a chain of TARGETs. */
struct _targets
{
TARGETS * next;
TARGETS * tail; /* valid only for head */
TARGET * target;
};
/* SETTINGS - variables to set when executing a TARGET's ACTIONS */
/* TARGET - an entity (e.g. a file) that can be built. */
struct _target
{
char * name;
char * boundname; /* if search() relocates target */
ACTIONS * actions; /* rules to execute, if any */
SETTINGS * settings; /* variables to define */
struct _settings {
SETTINGS *next;
char *symbol; /* symbol name for var_set() */
LIST *value; /* symbol value for var_set() */
} ;
short flags; /* status info */
/* TARGETS - a chain of TARGETs */
#define T_FLAG_TEMP 0x0001 /* TEMPORARY applied */
#define T_FLAG_NOCARE 0x0002 /* NOCARE applied */
#define T_FLAG_NOTFILE 0x0004 /* NOTFILE applied */
#define T_FLAG_TOUCHED 0x0008 /* ALWAYS applied or -t target */
#define T_FLAG_LEAVES 0x0010 /* LEAVES applied */
#define T_FLAG_NOUPDATE 0x0020 /* NOUPDATE applied */
#define T_FLAG_VISITED 0x0040 /* CWM: Used in debugging */
struct _targets {
TARGETS *next;
TARGETS *tail; /* valid only for head */
TARGET *target;
} ;
/* This flag has been added to support a new built-in rule named "RMBAD". It is
* used to force removal of outdated targets whose dependencies fail to build.
*/
#define T_FLAG_RMOLD 0x0080 /* RMBAD applied */
/* TARGET - a file or "thing" that can be built */
/* 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.
*/
#define T_FLAG_FAIL_EXPECTED 0x0100 /* FAIL_EXPECTED applied */
struct _target {
char *name;
char *boundname; /* if search() relocates target */
ACTIONS *actions; /* rules to execute, if any */
SETTINGS *settings; /* variables to define */
#define T_FLAG_INTERNAL 0x0200 /* internal INCLUDES node */
short flags; /* status info */
/* Indicates that the target must be a file. This prevents matching non-files,
* like directories, when a target is searched.
*/
#define T_FLAG_ISFILE 0x0400
# define T_FLAG_TEMP 0x0001 /* TEMPORARY applied */
# define T_FLAG_NOCARE 0x0002 /* NOCARE applied */
# define T_FLAG_NOTFILE 0x0004 /* NOTFILE applied */
# define T_FLAG_TOUCHED 0x0008 /* ALWAYS applied or -t target */
# define T_FLAG_LEAVES 0x0010 /* LEAVES applied */
# define T_FLAG_NOUPDATE 0x0020 /* NOUPDATE applied */
# define T_FLAG_VISITED 0x0040 /* CWM: Used in debugging */
char binding; /* how target relates to a real file or
* folder
*/
/* this flag was added to support a new builtin rule named "RMBAD" */
/* it is used to force removal of outdated targets whose dependencies
* fail to build */
#define T_BIND_UNBOUND 0 /* a disembodied name */
#define T_BIND_MISSING 1 /* could not find real file */
#define T_BIND_PARENTS 2 /* using parent's timestamp */
#define T_BIND_EXISTS 3 /* real file, timestamp valid */
# define T_FLAG_RMOLD 0x0080 /* RMBAD applied */
TARGETS * depends; /* dependencies */
TARGETS * dependants; /* the inverse of dependencies */
TARGETS * rebuilds; /* targets that should be force-rebuilt
* whenever this one is
*/
TARGET * includes; /* internal includes node */
TARGET * original_target; /* original_target->includes = this */
char rescanned;
/* this flag was added to support a new builting rule named "FAIL_EXPECTED" */
/* it is used to indicate that the result of running a given action should */
/* be inverted (i.e. ok <=> fail). This is useful to launch certain test */
/* runs from a Jamfile.. */
/* */
# define T_FLAG_FAIL_EXPECTED 0x0100 /* FAIL_EXPECTED applied */
time_t time; /* update time */
time_t leaf; /* update time of leaf sources */
# define T_FLAG_INTERNAL 0x0200 /* internal INCLUDES node */
char fate; /* make0()'s diagnosis */
/* Indicates that the target must be a file. This prevents matching non-files,
like directories, when a target is searched. */
#define T_FLAG_ISFILE 0x0400
#define T_FATE_INIT 0 /* nothing done to target */
#define T_FATE_MAKING 1 /* make0(target) on stack */
#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_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 */
#define T_FATE_UPDATE 10 /* deps updated, needs updating */
#define T_FATE_BROKEN 11 /* >= BROKEN ruins parents */
#define T_FATE_CANTFIND 11 /* no rules to make missing target */
#define T_FATE_CANTMAKE 12 /* can not find dependencies */
char progress; /* tracks make1() progress */
#define T_MAKE_INIT 0 /* make1(target) not yet called */
#define T_MAKE_ONSTACK 1 /* make1(target) on stack */
#define T_MAKE_ACTIVE 2 /* make1(target) in make1b() */
#define T_MAKE_RUNNING 3 /* make1(target) running commands */
#define T_MAKE_DONE 4 /* make1(target) done */
#ifdef OPT_SEMAPHORE
# define T_MAKE_SEMAPHORE 5 /* Special target type for semaphores */
#define T_MAKE_SEMAPHORE 5 /* Special target type for semaphores */
#endif
char binding; /* how target relates to real file */
# define T_BIND_UNBOUND 0 /* a disembodied name */
# define T_BIND_MISSING 1 /* couldn't find real file */
#ifdef OPT_SEMAPHORE
TARGET *semaphore; /* used in serialization */
#endif
# define T_BIND_PARENTS 2 /* using parent's timestamp */
# define T_BIND_EXISTS 3 /* real file, timestamp valid */
TARGETS *depends; /* dependencies */
TARGETS *dependents;/* the inverse of dependencies */
TARGETS *rebuilds; /* targets that should be force-rebuilt whenever this one is */
TARGET *includes; /* internal includes node */
TARGET *original_target; /* original_target->includes = this */
char rescanned;
time_t time; /* update time */
time_t leaf; /* update time of leaf sources */
char fate; /* make0()'s diagnosis */
# define T_FATE_INIT 0 /* nothing done to target */
# define T_FATE_MAKING 1 /* make0(target) on stack */
# define T_FATE_STABLE 2 /* target didn't 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_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 */
# define T_FATE_UPDATE 10 /* deps updated, needs updating */
# define T_FATE_BROKEN 11 /* >= BROKEN ruins parents */
# define T_FATE_CANTFIND 11 /* no rules to make missing target */
# define T_FATE_CANTMAKE 12 /* can't find dependents */
char progress; /* tracks make1() progress */
# define T_MAKE_INIT 0 /* make1(target) not yet called */
# define T_MAKE_ONSTACK 1 /* make1(target) on stack */
# define T_MAKE_ACTIVE 2 /* make1(target) in make1b() */
# define T_MAKE_RUNNING 3 /* make1(target) running commands */
# define T_MAKE_DONE 4 /* make1(target) done */
char status; /* execcmd() result */
int asynccnt; /* child deps outstanding */
TARGETS *parents; /* used by make1() for completion */
char *cmds; /* type-punned command list */
char* failed;
} ;
void add_include( TARGET * including, TARGET * included );
RULE * bindrule ( char * rulename, module_t* );
RULE* import_rule( RULE* source, module_t* m, char* name );
RULE* new_rule_body( module_t* m, char* rulename, argument_list* args, PARSE* procedure, int exprt );
RULE* new_rule_actions( module_t* m, char* rulename, char* command, LIST* bindlist, int flags );
TARGET *bindtarget( const char *targetname );
TARGET *copytarget( const TARGET *t );
void bind_explicitly_located_targets();
TARGET* search_for_target( char * name, LIST* search_path );
void touchtarget( char *t );
TARGETS *targetlist( TARGETS *chain, LIST *targets );
TARGETS *targetentry( TARGETS *chain, TARGET *target );
TARGETS *targetchain( TARGETS *chain, TARGETS *targets );
void freetargets( TARGETS *chain );
ACTIONS *actionlist( ACTIONS *chain, ACTION *action );
void freeactions( ACTIONS *chain );
SETTINGS *addsettings( SETTINGS *head, int flag, char *symbol, LIST *value );
void pushsettings( SETTINGS *v );
void popsettings( SETTINGS *v );
SETTINGS *copysettings( SETTINGS *v );
void freesettings( SETTINGS *v );
void rule_free( RULE *r );
void donerules();
argument_list* args_new();
void args_refer( argument_list* );
void args_free( argument_list* );
void actions_refer(rule_actions*);
void actions_free(rule_actions*);
TARGET * semaphore; /* used in serialization */
#endif
char status; /* exec_cmd() result */
int asynccnt; /* child deps outstanding */
TARGETS * parents; /* used by make1() for completion */
char * cmds; /* type-punned command list */
char * failed;
};
/* Action related functions. */
ACTIONS * actionlist ( ACTIONS *, ACTION * );
void freeactions ( ACTIONS * );
SETTINGS * addsettings ( SETTINGS *, int flag, char * symbol, LIST * value );
void pushsettings ( SETTINGS * );
void popsettings ( SETTINGS * );
SETTINGS * copysettings ( SETTINGS * );
void freesettings ( SETTINGS * );
void actions_refer( rule_actions * );
void actions_free ( rule_actions * );
/* Argument list related functions. */
void args_free ( argument_list * );
argument_list * args_new ();
void args_refer( argument_list * );
/* Rule related functions. */
RULE * bindrule ( char * rulename, module_t * );
RULE * import_rule ( RULE * source, module_t *, char * name );
RULE * new_rule_body ( module_t *, char * rulename, argument_list *, PARSE * procedure, int exprt );
RULE * new_rule_actions( module_t *, char * rulename, char * command, LIST * bindlist, int flags );
void rule_free ( RULE * );
/* Target related functions. */
void bind_explicitly_located_targets();
TARGET * bindtarget ( char const * target_name );
TARGET * copytarget ( TARGET const * t );
void freetargets ( TARGETS * );
TARGET * search_for_target ( char * name, LIST * search_path );
TARGETS * targetchain ( TARGETS * chain, TARGETS * );
TARGETS * targetentry ( TARGETS * chain, TARGET * );
void target_include ( TARGET * including, TARGET * included );
TARGETS * targetlist ( TARGETS * chain, LIST * target_names );
void touch_target ( char * t );
/* Final module cleanup. */
void rules_done();
#endif

View File

@@ -25,38 +25,41 @@
* defined before Linux's yacc tries to redefine it.
*/
struct keyword {
char *word;
int type;
} keywords[] = {
# include "jamgramtab.h"
struct keyword
{
char * word;
int type;
} keywords[] =
{
#include "jamgramtab.h"
{ 0, 0 }
} ;
};
struct include {
struct include *next; /* next serial include file */
char *string; /* pointer into current line */
char **strings; /* for yyfparse() -- text to parse */
FILE *file; /* for yyfparse() -- file being read */
char *fname; /* for yyfparse() -- file name */
int line; /* line counter for error messages */
char buf[ 512 ]; /* for yyfparse() -- line buffer */
} ;
struct include
{
struct include * next; /* next serial include file */
char * string; /* pointer into current line */
char * * strings; /* for yyfparse() -- text to parse */
FILE * file; /* for yyfparse() -- file being read */
char * fname; /* for yyfparse() -- file name */
int line; /* line counter for error messages */
char buf[ 512 ]; /* for yyfparse() -- line buffer */
};
static struct include *incp = 0; /* current file; head of chain */
static struct include * incp = 0; /* current file; head of chain */
static int scanmode = SCAN_NORMAL;
static int anyerrors = 0;
static char *symdump( YYSTYPE *s );
static char * symdump( YYSTYPE * );
# define BIGGEST_TOKEN 10240 /* no single token can be larger */
/*
* Set parser mode: normal, string, or keyword
*/
void
yymode( int n )
void yymode( int n )
{
scanmode = n;
}
@@ -64,7 +67,7 @@ yymode( int n )
void
yyerror( char *s )
{
if( incp )
if ( incp )
printf( "%s:%d: ", incp->fname, incp->line );
printf( "%s at %s\n", s, symdump( &yylval ) );
@@ -95,7 +98,7 @@ yyfparse( char *s )
/* If the filename is "+", it means use the internal jambase. */
if( !strcmp( s, "+" ) )
if ( !strcmp( s, "+" ) )
i->strings = jambase;
}
@@ -111,7 +114,7 @@ yyline()
{
struct include *i = incp;
if( !incp )
if ( !incp )
return EOF;
/* Once we start reading from the input stream, we reset the */
@@ -120,16 +123,16 @@ yyline()
/* If there is more data in this line, return it. */
if( *i->string )
if ( *i->string )
return *i->string++;
/* If we're reading from an internal string list, go to the */
/* next string. */
if( i->strings )
if ( i->strings )
{
if( !*i->strings )
goto next;
if ( !*i->strings )
goto next;
i->line++;
i->string = *(i->strings++);
@@ -138,19 +141,17 @@ yyline()
/* If necessary, open the file */
if( !i->file )
if ( !i->file )
{
FILE *f = stdin;
if( strcmp( i->fname, "-" ) && !( f = fopen( i->fname, "r" ) ) )
perror( i->fname );
FILE * f = stdin;
if ( strcmp( i->fname, "-" ) && !( f = fopen( i->fname, "r" ) ) )
perror( i->fname );
i->file = f;
}
/* If there's another line in this file, start it. */
if( i->file && fgets( i->buf, sizeof( i->buf ), i->file ) )
if ( i->file && fgets( i->buf, sizeof( i->buf ), i->file ) )
{
i->line++;
i->string = i->buf;
@@ -165,7 +166,7 @@ yyline()
/* Close file, free name */
if( i->file && i->file != stdin )
if ( i->file && i->file != stdin )
fclose( i->file );
freestr( i->fname );
BJAM_FREE( (char *)i );
@@ -188,66 +189,62 @@ yyline()
# define yychar() ( *incp->string ? *incp->string++ : yyline() )
# define yyprev() ( incp->string-- )
int
yylex()
int yylex()
{
int c;
char buf[BIGGEST_TOKEN];
char *b = buf;
char buf[ BIGGEST_TOKEN ];
char * b = buf;
if( !incp )
if ( !incp )
goto eof;
/* Get first character (whitespace or of token) */
c = yychar();
if( scanmode == SCAN_STRING )
if ( scanmode == SCAN_STRING )
{
/* If scanning for a string (action's {}'s), look for the */
/* closing brace. We handle matching braces, if they match! */
int nest = 1;
while( c != EOF && b < buf + sizeof( buf ) )
while ( c != EOF && b < ( buf + sizeof( buf ) ) )
{
if( c == '{' )
nest++;
if ( c == '{' )
nest++;
if( c == '}' && !--nest )
break;
if ( ( c == '}' ) && !--nest )
break;
*b++ = c;
c = yychar();
/* turn trailing "\r\n" sequences into plain "\n"
* for Cygwin
*/
if (c == '\n' && b[-1] == '\r')
--b;
/* Turn trailing "\r\n" sequences into plain "\n" for Cygwin. */
if ( ( c == '\n' ) && ( b[ -1 ] == '\r' ) )
--b;
}
/* We ate the ending brace -- regurgitate it. */
if( c != EOF )
yyprev();
if ( c != EOF )
yyprev();
/* Check obvious errors. */
if( b == buf + sizeof( buf ) )
if ( b == buf + sizeof( buf ) )
{
yyerror( "action block too big" );
goto eof;
yyerror( "action block too big" );
goto eof;
}
if( nest )
if ( nest )
{
yyerror( "unmatched {} in action block" );
goto eof;
yyerror( "unmatched {} in action block" );
goto eof;
}
*b = 0;
* b = 0;
yylval.type = STRING;
yylval.string = newstr( buf );
yylval.file = incp->fname;
@@ -256,32 +253,29 @@ yylex()
}
else
{
char *b = buf;
struct keyword *k;
char * b = buf;
struct keyword * k;
int inquote = 0;
int notkeyword;
/* Eat white space */
for( ;; )
for ( ;; )
{
/* Skip past white space */
while( c != EOF && isspace( c ) )
/* Skip past white space. */
while ( ( c != EOF ) && isspace( c ) )
c = yychar();
/* Not a comment? Swallow up comment line. */
if( c != '#' )
if ( c != '#' )
break;
while( ( c = yychar() ) != EOF && c != '\n' )
;
while ( ( ( c = yychar() ) != EOF ) && ( c != '\n' ) ) ;
}
/* c now points to the first character of a token. */
if( c == EOF )
goto eof;
if ( c == EOF )
goto eof;
yylval.file = incp->fname;
yylval.line = incp->line;
@@ -295,46 +289,48 @@ yylex()
/* "'s get stripped but preserve white space */
/* \ protects next character */
while(
c != EOF &&
b < buf + sizeof( buf ) &&
( inquote || !isspace( c ) ) )
while
(
( c != EOF ) &&
( b < buf + sizeof( buf ) ) &&
( inquote || !isspace( c ) )
)
{
if( c == '"' )
{
/* begin or end " */
inquote = !inquote;
notkeyword = 1;
}
else if( c != '\\' )
{
/* normal char */
*b++ = c;
}
else if( ( c = yychar()) != EOF )
{
/* \c */
*b++ = c;
notkeyword = 1;
}
else
{
/* \EOF */
break;
}
if ( c == '"' )
{
/* begin or end " */
inquote = !inquote;
notkeyword = 1;
}
else if ( c != '\\' )
{
/* normal char */
*b++ = c;
}
else if ( ( c = yychar()) != EOF )
{
/* \c */
*b++ = c;
notkeyword = 1;
}
else
{
/* \EOF */
break;
}
c = yychar();
c = yychar();
}
/* Check obvious errors. */
if( b == buf + sizeof( buf ) )
if ( b == buf + sizeof( buf ) )
{
yyerror( "string too big" );
goto eof;
}
if( inquote )
if ( inquote )
{
yyerror( "unmatched \" in string" );
goto eof;
@@ -342,7 +338,7 @@ yylex()
/* We looked ahead a character - back up. */
if( c != EOF )
if ( c != EOF )
yyprev();
/* scan token table */
@@ -352,22 +348,22 @@ yylex()
*b = 0;
yylval.type = ARG;
if( !notkeyword && !( isalpha( *buf ) && scanmode == SCAN_PUNCT ) )
if ( !notkeyword && !( isalpha( *buf ) && scanmode == SCAN_PUNCT ) )
{
for( k = keywords; k->word; k++ )
if( *buf == *k->word && !strcmp( k->word, buf ) )
{
yylval.type = k->type;
yylval.string = k->word; /* used by symdump */
break;
}
for ( k = keywords; k->word; ++k )
if ( ( *buf == *k->word ) && !strcmp( k->word, buf ) )
{
yylval.type = k->type;
yylval.string = k->word; /* used by symdump */
break;
}
}
if( yylval.type == ARG )
if ( yylval.type == ARG )
yylval.string = newstr( buf );
}
if( DEBUG_SCAN )
if ( DEBUG_SCAN )
printf( "scan %s\n", symdump( &yylval ) );
return yylval.type;
@@ -384,34 +380,24 @@ static char *
symdump( YYSTYPE *s )
{
static char buf[ BIGGEST_TOKEN + 20 ];
switch( s->type )
switch ( s->type )
{
case EOF:
sprintf( buf, "EOF" );
break;
case 0:
sprintf( buf, "unknown symbol %s", s->string );
break;
case ARG:
sprintf( buf, "argument %s", s->string );
break;
case STRING:
sprintf( buf, "string \"%s\"", s->string );
break;
default:
sprintf( buf, "keyword %s", s->string );
break;
case EOF : sprintf( buf, "EOF" ); break;
case 0 : sprintf( buf, "unknown symbol %s", s->string ); break;
case ARG : sprintf( buf, "argument %s" , s->string ); break;
case STRING: sprintf( buf, "string \"%s\"" , s->string ); break;
default : sprintf( buf, "keyword %s" , s->string ); break;
}
return buf;
}
/* Get information about the current file and line, for those epsilon
* transitions that produce a parse
* transitions that produce a parse.
*/
void yyinput_stream( char** name, int* line )
void yyinput_stream( char * * name, int * line )
{
if (incp)
if ( incp )
{
*name = incp->fname;
*line = incp->line;

View File

@@ -10,51 +10,58 @@
* (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
*/
# include "jam.h"
# include "lists.h"
# include "search.h"
# include "timestamp.h"
# include "pathsys.h"
# include "variable.h"
# include "newstr.h"
# include "compile.h"
# include "strings.h"
# include "hash.h"
# include "filesys.h"
# include <string.h>
#include "jam.h"
#include "lists.h"
#include "search.h"
#include "timestamp.h"
#include "pathsys.h"
#include "variable.h"
#include "newstr.h"
#include "compile.h"
#include "strings.h"
#include "hash.h"
#include "filesys.h"
#include <string.h>
typedef struct _binding {
char* binding;
char* target;
typedef struct _binding
{
char * binding;
char * target;
} BINDING;
static struct hash *explicit_bindings = 0;
void call_bind_rule(
char* target_,
char* boundname_ )
{
LIST* bind_rule = var_get( "BINDRULE" );
if( bind_rule )
{
/* No guarantee that target is an allocated string, so be on the
* safe side */
char* target = copystr( target_ );
/* Likewise, don't rely on implementation details of newstr.c: allocate
* a copy of boundname */
char* boundname = copystr( boundname_ );
if( boundname && target )
void call_bind_rule
(
char * target_,
char * boundname_
)
{
LIST * bind_rule = var_get( "BINDRULE" );
if ( bind_rule )
{
/* No guarantee that the target is an allocated string, so be on the
* safe side.
*/
char * target = copystr( target_ );
/* Likewise, do not rely on implementation details of newstr.c: allocate
* a copy of boundname.
*/
char * boundname = copystr( boundname_ );
if ( boundname && target )
{
/* Prepare the argument list */
/* Prepare the argument list. */
FRAME frame[1];
frame_init( frame );
/* First argument is the target name */
/* First argument is the target name. */
lol_add( frame->args, list_new( L0, target ) );
lol_add( frame->args, list_new( L0, boundname ) );
if( lol_get( frame->args, 1 ) )
if ( lol_get( frame->args, 1 ) )
evaluate_rule( bind_rule->string, frame );
/* Clean up */
@@ -62,9 +69,9 @@ void call_bind_rule(
}
else
{
if( boundname )
if ( boundname )
freestr( boundname );
if( target )
if ( target )
freestr( target );
}
}
@@ -102,7 +109,7 @@ search(
int explicitly_located = 0;
char *boundname = 0;
if( another_target )
if ( another_target )
*another_target = 0;
if (! explicit_bindings )
@@ -117,14 +124,14 @@ search(
f->f_grist.ptr = 0;
f->f_grist.len = 0;
if( varlist = var_get( "LOCATE" ) )
if ( varlist = var_get( "LOCATE" ) )
{
f->f_root.ptr = varlist->string;
f->f_root.len = strlen( varlist->string );
path_build( f, buf, 1 );
if( DEBUG_SEARCH )
if ( DEBUG_SEARCH )
printf( "locate %s: %s\n", target, buf->value );
explicitly_located = 1;
@@ -132,9 +139,9 @@ search(
timestamp( buf->value, time );
found = 1;
}
else if( varlist = var_get( "SEARCH" ) )
else if ( varlist = var_get( "SEARCH" ) )
{
while( varlist )
while ( varlist )
{
BINDING b, *ba = &b;
file_info_t *ff;
@@ -145,7 +152,7 @@ search(
string_truncate( buf, 0 );
path_build( f, buf, 1 );
if( DEBUG_SEARCH )
if ( DEBUG_SEARCH )
printf( "search %s: %s\n", target, buf->value );
ff = file_query(buf->value);
@@ -153,19 +160,19 @@ search(
b.binding = buf->value;
if( hashcheck( explicit_bindings, (HASHDATA**)&ba ) )
if ( hashcheck( explicit_bindings, (HASHDATA**)&ba ) )
{
if( DEBUG_SEARCH )
if ( DEBUG_SEARCH )
printf(" search %s: found explicitly located target %s\n",
target, ba->target);
if( another_target )
if ( another_target )
*another_target = ba->target;
found = 1;
break;
}
else if( ff && ff->time )
else if ( ff && ff->time )
{
if (!file || ff->is_file)
if ( !file || ff->is_file )
{
found = 1;
break;
@@ -176,7 +183,7 @@ search(
}
}
if (!found)
if ( !found )
{
/* Look for the obvious */
/* This is a questionable move. Should we look in the */
@@ -188,7 +195,7 @@ search(
string_truncate( buf, 0 );
path_build( f, buf, 1 );
if( DEBUG_SEARCH )
if ( DEBUG_SEARCH )
printf( "search %s: %s\n", target, buf->value );
timestamp( buf->value, time );
@@ -197,15 +204,16 @@ search(
boundname = newstr( buf->value );
string_free( buf );
if (explicitly_located)
if ( explicitly_located )
{
BINDING b, *ba = &b;
BINDING b;
BINDING * ba = &b;
b.binding = boundname;
b.target = target;
/* CONSIDER: we probably should issue a warning is another file
is explicitly bound to the same location. This might break
compatibility, though. */
hashenter(explicit_bindings, (HASHDATA**)&ba);
hashenter( explicit_bindings, (HASHDATA * *)&ba );
}
/* prepare a call to BINDRULE if the variable is set */

View File

@@ -46,83 +46,79 @@ struct _binding {
# define BIND_FOUND 4 /* file found and time stamped */
time_t time; /* update time - 0 if not exist */
} ;
};
static struct hash *bindhash = 0;
static void time_enter( void *, char *, int , time_t );
static struct hash * bindhash = 0;
static void time_enter( void *, char *, int, time_t );
static char *time_progress[] =
static char * time_progress[] =
{
"INIT",
"NOENTRY",
"SPOTTED",
"MISSING",
"FOUND"
} ;
};
/*
* timestamp() - return timestamp on a file, if present
* timestamp() - return timestamp on a file, if present.
*/
void
timestamp(
char *target,
time_t *time )
void timestamp( char * target, time_t * time )
{
PROFILE_ENTER(timestamp);
PROFILE_ENTER( timestamp );
PATHNAME f1, f2;
BINDING binding, *b = &binding;
string buf[1];
string path;
char *p;
PATHNAME f1;
PATHNAME f2;
BINDING binding;
BINDING * b = &binding;
string buf[ 1 ];
string path;
char * p;
# ifdef DOWNSHIFT_PATHS
string_copy( &path, target );
p = path.value;
#ifdef DOWNSHIFT_PATHS
string_copy( &path, target );
p = path.value;
do
{
*p = tolower( *p );
# ifdef NT
/* On NT, we must use backslashes or the file won't be found. */
if (*p == '/')
#ifdef NT
/* On NT, we must use backslashes or the file will not be found. */
if ( *p == '/' )
*p = PATH_DELIM;
# endif
#endif
}
while( *p++ );
while ( *p++ );
target = path.value;
# endif
string_new( buf );
#endif /* #ifdef DOWNSHIFT_PATHS */
string_new( buf );
if( !bindhash )
if ( !bindhash )
bindhash = hashinit( sizeof( BINDING ), "bindings" );
/* Quick path - is it there? */
b->name = target;
b->time = b->flags = 0;
b->progress = BIND_INIT;
if( hashenter( bindhash, (HASHDATA **)&b ) )
b->name = newstr( target ); /* never freed */
if ( hashenter( bindhash, (HASHDATA * *)&b ) )
b->name = newstr( target ); /* never freed */
if( b->progress != BIND_INIT )
if ( b->progress != BIND_INIT )
goto afterscanning;
b->progress = BIND_NOENTRY;
/* Not found - have to scan for it */
/* Not found - have to scan for it. */
path_parse( target, &f1 );
/* Scan directory if not already done so */
/* Scan directory if not already done so. */
{
BINDING binding, *b = &binding;
BINDING binding;
BINDING * b = &binding;
f2 = f1;
f2.f_grist.len = 0;
@@ -133,100 +129,96 @@ timestamp(
b->time = b->flags = 0;
b->progress = BIND_INIT;
if( hashenter( bindhash, (HASHDATA **)&b ) )
b->name = newstr( buf->value ); /* never freed */
if ( hashenter( bindhash, (HASHDATA * *)&b ) )
b->name = newstr( buf->value ); /* never freed */
if( !( b->flags & BIND_SCANNED ) )
if ( !( b->flags & BIND_SCANNED ) )
{
file_dirscan( buf->value, time_enter, bindhash );
b->flags |= BIND_SCANNED;
file_dirscan( buf->value, time_enter, bindhash );
b->flags |= BIND_SCANNED;
}
}
/* Scan archive if not already done so */
if( f1.f_member.len )
/* Scan archive if not already done so. */
if ( f1.f_member.len )
{
BINDING binding, *b = &binding;
BINDING binding;
BINDING * b = &binding;
f2 = f1;
f2.f_grist.len = 0;
f2.f_member.len = 0;
string_truncate( buf, 0 );
string_truncate( buf, 0 );
path_build( &f2, buf, 0 );
b->name = buf->value;
b->time = b->flags = 0;
b->progress = BIND_INIT;
if( hashenter( bindhash, (HASHDATA **)&b ) )
b->name = newstr( buf->value ); /* never freed */
if ( hashenter( bindhash, (HASHDATA * *)&b ) )
b->name = newstr( buf->value ); /* never freed */
if( !( b->flags & BIND_SCANNED ) )
if ( !( b->flags & BIND_SCANNED ) )
{
file_archscan( buf->value, time_enter, bindhash );
b->flags |= BIND_SCANNED;
file_archscan( buf->value, time_enter, bindhash );
b->flags |= BIND_SCANNED;
}
}
afterscanning:
if( b->progress == BIND_SPOTTED )
if ( b->progress == BIND_SPOTTED )
{
if( file_time( b->name, &b->time ) < 0 )
b->progress = BIND_MISSING;
else
b->progress = BIND_FOUND;
b->progress = file_time( b->name, &b->time ) < 0
? BIND_MISSING
: BIND_FOUND;
}
*time = b->progress == BIND_FOUND ? b->time : 0;
string_free( buf );
# ifdef DOWNSHIFT_PATHS
string_free( &path );
#ifdef DOWNSHIFT_PATHS
string_free( &path );
#endif
PROFILE_EXIT(timestamp);
PROFILE_EXIT( timestamp );
}
static void
time_enter(
void *closure,
char *target,
int found,
time_t time )
{
BINDING binding, *b = &binding;
struct hash *bindhash = (struct hash *)closure;
# ifdef DOWNSHIFT_PATHS
static void time_enter( void * closure, char * target, int found, time_t time )
{
BINDING binding;
BINDING * b = &binding;
struct hash * bindhash = (struct hash *)closure;
#ifdef DOWNSHIFT_PATHS
char path[ MAXJPATH ];
char *p = path;
char * p = path;
do *p++ = tolower( *target );
while( *target++ );
while ( *target++ );
target = path;
# endif
#endif
b->name = target;
b->flags = 0;
if( hashenter( bindhash, (HASHDATA **)&b ) )
b->name = newstr( target ); /* never freed */
if ( hashenter( bindhash, (HASHDATA * *)&b ) )
b->name = newstr( target ); /* never freed */
b->time = time;
b->progress = found ? BIND_FOUND : BIND_SPOTTED;
if( DEBUG_BINDSCAN )
printf( "time ( %s ) : %s\n", target, time_progress[b->progress] );
if ( DEBUG_BINDSCAN )
printf( "time ( %s ) : %s\n", target, time_progress[ b->progress ] );
}
/*
* donestamps() - free timestamp tables
* stamps_done() - free timestamp tables.
*/
void
donestamps()
void stamps_done()
{
hashdone( bindhash );
}

View File

@@ -8,5 +8,5 @@
* timestamp.h - get the timestamp of a file or archive member
*/
void timestamp( char *target, time_t *time );
void donestamps();
void timestamp( char * target, time_t * time );
void stamps_done();

View File

@@ -12,35 +12,35 @@
* (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
*/
# include "jam.h"
# include "lists.h"
# include "parse.h"
# include "variable.h"
# include "expand.h"
# include "hash.h"
# include "filesys.h"
# include "newstr.h"
# include "strings.h"
# include "pathsys.h"
# include <stdlib.h>
# include <stdio.h>
#include "jam.h"
#include "lists.h"
#include "parse.h"
#include "variable.h"
#include "expand.h"
#include "hash.h"
#include "filesys.h"
#include "newstr.h"
#include "strings.h"
#include "pathsys.h"
#include <stdlib.h>
#include <stdio.h>
/*
* variable.c - handle jam multi-element variables
* variable.c - handle Jam multi-element variables.
*
* External routines:
*
* var_defines() - load a bunch of variable=value settings
* var_string() - expand a string with variables in it
* var_get() - get value of a user defined symbol
* var_set() - set a variable in jam's user defined symbol table
* var_swap() - swap a variable's value with the given one
* var_done() - free variable tables
* var_defines() - load a bunch of variable=value settings.
* var_string() - expand a string with variables in it.
* var_get() - get value of a user defined symbol.
* var_set() - set a variable in jam's user defined symbol table.
* var_swap() - swap a variable's value with the given one.
* var_done() - free variable tables.
*
* Internal routines:
*
* var_enter() - make new var symbol table entry, returning var ptr
* var_dump() - dump a variable to stdout
* var_enter() - make new var symbol table entry, returning var ptr.
* var_dump() - dump a variable to stdout.
*
* 04/13/94 (seiwald) - added shorthand L0 for null list pointer
* 08/23/94 (seiwald) - Support for '+=' (append to variable)
@@ -57,28 +57,30 @@ static struct hash *varhash = 0;
typedef struct _variable VARIABLE ;
struct _variable {
char *symbol;
LIST *value;
} ;
struct _variable
{
char * symbol;
LIST * value;
};
static VARIABLE *var_enter( char *symbol );
static void var_dump( char *symbol, LIST *value, char *what );
static VARIABLE * var_enter( char * symbol );
static void var_dump( char * symbol, LIST * value, char * what );
/*
* var_hash_swap() - swap all variable settings with those passed
*
* Used to implement separate settings spaces for modules
*/
void var_hash_swap( struct hash** new_vars )
void var_hash_swap( struct hash * * new_vars )
{
struct hash* old = varhash;
struct hash * old = varhash;
varhash = *new_vars;
*new_vars = old;
}
/*
* var_defines() - load a bunch of variable=value settings
*
@@ -92,224 +94,214 @@ void var_hash_swap( struct hash** new_vars )
* Otherwise, split the value at blanks.
*/
void
var_defines( char *const* e, int preprocess )
void var_defines( char * const * e, int preprocess )
{
string buf[1];
string_new( buf );
for( ; *e; e++ )
for ( ; *e; ++e )
{
char *val;
char * val;
# ifdef OS_MAC
/* On the mac (MPW), the var=val is actually var\0val */
/* Think different. */
if( ( val = strchr( *e, '=' ) ) || ( val = *e + strlen( *e ) ) )
if ( ( val = strchr( *e, '=' ) ) || ( val = *e + strlen( *e ) ) )
# else
if( val = strchr( *e, '=' ) )
if ( val = strchr( *e, '=' ) )
# endif
{
LIST *l = L0;
char *pp, *p;
LIST * l = L0;
char * pp;
char * p;
# ifdef OPT_NO_EXTERNAL_VARIABLE_SPLIT
char split = '\0';
char split = '\0';
# else
# ifdef OS_MAC
char split = ',';
# else
char split = ' ';
# ifdef OS_MAC
char split = ',';
# else
char split = ' ';
# endif
# endif
# endif
size_t len = strlen(val + 1);
size_t len = strlen( val + 1 );
int quoted = val[1] == '"' && val[len] == '"' && len > 1;
int quoted = ( val[1] == '"' ) && ( val[len] == '"' ) &&
( len > 1 );
if ( quoted && preprocess )
if ( quoted && preprocess )
{
string_append_range( buf, val + 2, val + len );
l = list_new( l, newstr( buf->value ) );
string_truncate( buf, 0 );
}
else
{
/* Split *PATH at :'s, not spaces. */
if ( val - 4 >= *e )
{
string_append_range( buf, val + 2, val + len );
if ( !strncmp( val - 4, "PATH", 4 ) ||
!strncmp( val - 4, "Path", 4 ) ||
!strncmp( val - 4, "path", 4 ) )
split = SPLITPATH;
}
/* Do the split. */
for
(
pp = val + 1;
preprocess && ( ( p = strchr( pp, split ) ) != 0 );
pp = p + 1
)
{
string_append_range( buf, pp, p );
l = list_new( l, newstr( buf->value ) );
string_truncate( buf, 0 );
}
else
{
/* Split *PATH at :'s, not spaces */
if( val - 4 >= *e )
{
if( !strncmp( val - 4, "PATH", 4 ) ||
!strncmp( val - 4, "Path", 4 ) ||
!strncmp( val - 4, "path", 4 ) )
split = SPLITPATH;
}
l = list_new( l, newstr( pp ) );
}
/* Do the split */
for(
pp = val + 1;
preprocess && (p = strchr( pp, split )) != 0;
pp = p + 1 )
{
string_append_range( buf, pp, p );
l = list_new( l, newstr( buf->value ) );
string_truncate( buf, 0 );
}
l = list_new( l, newstr( pp ) );
}
/* Get name */
string_append_range( buf, *e, val );
var_set( buf->value, l, VAR_SET );
string_truncate( buf, 0 );
/* Get name. */
string_append_range( buf, *e, val );
var_set( buf->value, l, VAR_SET );
string_truncate( buf, 0 );
}
}
string_free( buf );
string_free( buf );
}
/*
* var_string() - expand a string with variables in it
*
* Copies in to out; doesn't modify targets & sources.
*/
int
var_string(
char *in,
char *out,
int outsize,
LOL *lol )
int var_string( char * in, char * out, int outsize, LOL * lol )
{
char *out0 = out;
char *oute = out + outsize - 1;
char * out0 = out;
char * oute = out + outsize - 1;
while( *in )
while ( *in )
{
char *lastword;
int dollar = 0;
char * lastword;
int dollar = 0;
/* Copy white space */
while( isspace( *in ) )
/* Copy white space. */
while ( isspace( *in ) )
{
if( out >= oute )
if ( out >= oute )
return -1;
*out++ = *in++;
}
lastword = out;
/* Copy non-white space, watching for variables */
while( *in && !isspace( *in ) )
/* Copy non-white space, watching for variables. */
while ( *in && !isspace( *in ) )
{
if( out >= oute )
if ( out >= oute )
return -1;
if( in[0] == '$' && in[1] == '(' )
if ( ( in[ 0 ] == '$' ) && ( in[ 1 ] == '(' ) )
{
dollar++;
++dollar;
*out++ = *in++;
}
#ifdef OPT_AT_FILES
else if ( in[0] == '@' && in[1] == '(' )
else if ( ( in[ 0 ] == '@' ) && ( in[ 1 ] == '(' ) )
{
int depth = 1;
char *ine = in + 2;
char *split = 0;
char * ine = in + 2;
char * split = 0;
/* Scan the content of the response file @() section. */
while( *ine && depth > 0 )
while ( *ine && ( depth > 0 ) )
{
switch( *ine )
switch ( *ine )
{
case '(':
++depth;
break;
case ')':
--depth;
break;
case '(': ++depth; break;
case ')': --depth; break;
case ':':
if( depth == 1 && ine[1] == 'E' && ine[2] == '=' )
{
if ( ( depth == 1 ) && ( ine[ 1 ] == 'E' ) && ( ine[ 2 ] == '=' ) )
split = ine;
}
break;
}
++ine;
}
if (!split)
if ( !split )
{
/* the @() reference doesn't match the @(foo:E=bar) format.
hence we leave it alone by copying directly to output. */
int l = 0;
if ( out+2 >= oute ) return -1;
*(out++) = '@';
*(out++) = '(';
l = var_string(in+2,out,oute-out,lol);
if ( out + 2 >= oute ) return -1;
*( out++ ) = '@';
*( out++ ) = '(';
l = var_string( in + 2, out, oute - out, lol );
if ( l < 0 ) return -1;
out += l;
if ( out+1 >= oute ) return -1;
*(out++) = ')';
if ( out + 1 >= oute ) return -1;
*( out++ ) = ')';
}
else if ( depth == 0 )
{
string file_name_v;
int file_name_l = 0;
const char * file_name_s = 0;
/* expand the temporary file name var inline */
/* Expand the temporary file name var inline. */
#if 0
string_copy(&file_name_v,"$(");
string_append_range(&file_name_v,in+2,split);
string_push_back(&file_name_v,')');
string_copy( &file_name_v, "$(" );
string_append_range( &file_name_v, in + 2, split );
string_push_back( &file_name_v, ')' );
#else
string_new(&file_name_v);
string_append_range(&file_name_v,in+2,split);
string_new( &file_name_v );
string_append_range( &file_name_v, in + 2, split );
#endif
file_name_l = var_string(file_name_v.value,out,oute-out+1,lol);
string_free(&file_name_v);
file_name_l = var_string( file_name_v.value, out, oute - out + 1, lol );
string_free( &file_name_v );
if ( file_name_l < 0 ) return -1;
file_name_s = out;
/* for stdout/stderr we will create a temp file and generate
a command that outputs the content as needed. */
if ( strcmp( "STDOUT", out ) == 0 || strcmp( "STDERR", out ) == 0 )
/* For stdout/stderr we will create a temp file and generate
* a command that outputs the content as needed.
*/
if ( ( strcmp( "STDOUT", out ) == 0 ) ||
( strcmp( "STDERR", out ) == 0 ) )
{
int err_redir = strcmp( "STDERR", out ) == 0;
out[0] = '\0';
out[ 0 ] = '\0';
file_name_s = path_tmpfile();
file_name_l = strlen(file_name_s);
#ifdef OS_NT
if ( (out+7+file_name_l+(err_redir?5:0)) >= oute ) return -1;
sprintf( out,"type \"%s\"%s",
file_name_s,
if ( ( out + 7 + file_name_l + ( err_redir ? 5 : 0 ) ) >= oute )
return -1;
sprintf( out,"type \"%s\"%s", file_name_s,
err_redir ? " 1>&2" : "" );
#else
if ( (out+6+file_name_l+(err_redir?5:0)) >= oute ) return -1;
sprintf( out,"cat \"%s\"%s",
file_name_s,
if ( ( out + 6 + file_name_l + ( err_redir ? 5 : 0 ) ) >= oute )
return -1;
sprintf( out,"cat \"%s\"%s", file_name_s,
err_redir ? " 1>&2" : "" );
#endif
/* we also make sure that the temp files created by this
get nuked eventually. */
/* We also make sure that the temp files created by this
* get nuked eventually.
*/
file_remove_atexit( file_name_s );
}
/* expand the file value into the file reference */
var_string_to_file( split+3, ine-split-4, file_name_s, lol );
/* Expand the file value into the file reference. */
var_string_to_file( split + 3, ine - split - 4, file_name_s,
lol );
/* continue on with the expansion */
out += strlen(out);
/* Continue on with the expansion. */
out += strlen( out );
}
/* and continue with the parsing just past the @() reference */
/* And continue with the parsing just past the @() reference. */
in = ine;
}
#endif
@@ -320,19 +312,17 @@ var_string(
}
/* Add zero to 'out' so that 'lastword' is correctly zero-terminated. */
if (out >= oute)
if ( out >= oute )
return -1;
/* Don't increment, intentionally. */
*out= '\0';
/* Do not increment, intentionally. */
*out = '\0';
/* If a variable encountered, expand it and and embed the */
/* space-separated members of the list in the output. */
if( dollar )
/* If a variable encountered, expand it and and embed the
* space-separated members of the list in the output.
*/
if ( dollar )
{
LIST *l;
l = var_expand( L0, lastword, out, lol, 0 );
LIST * l = var_expand( L0, lastword, out, lol, 0 );
out = lastword;
@@ -340,8 +330,8 @@ var_string(
{
int so = strlen( l->string );
if( out + so >= oute )
return -1;
if ( out + so >= oute )
return -1;
strcpy( out, l->string );
out += so;
@@ -353,7 +343,7 @@ var_string(
}
}
if( out >= oute )
if ( out >= oute )
return -1;
*out++ = '\0';
@@ -361,9 +351,10 @@ var_string(
return out - out0;
}
void var_string_to_file( const char * in, int insize, const char * out, LOL * lol )
{
const char * ine = in+insize;
char const * ine = in + insize;
FILE * out_file = 0;
int out_debug = DEBUG_EXEC ? 1 : 0;
if ( globs.noexec )
@@ -382,64 +373,57 @@ void var_string_to_file( const char * in, int insize, const char * out, LOL * lo
{
/* Handle "path to file" filenames. */
string out_name;
if ( out[0] == '"' && out[strlen(out) - 1] == '"' )
if ( ( out[ 0 ] == '"' ) && ( out[ strlen( out ) - 1 ] == '"' ) )
{
string_copy(&out_name,out+1);
string_truncate(&out_name,out_name.size-1);
string_copy( &out_name, out + 1 );
string_truncate( &out_name, out_name.size - 1 );
}
else
{
string_copy(&out_name,out);
string_copy( &out_name,out );
}
out_file = fopen( out_name.value, "w" );
if (!out_file)
if ( !out_file )
{
printf( "failed to write output file '%s'!\n", out_name.value );
exit( EXITBAD );
}
string_free(&out_name);
string_free( &out_name );
}
if ( out_debug ) printf("\nfile %s\n",out);
if ( out_debug ) printf( "\nfile %s\n", out );
while( *in && in < ine )
while ( *in && ( in < ine ) )
{
int dollar = 0;
const char * output_0 = in;
const char * output_1 = in;
/* Copy white space */
while ( output_1 < ine && *output_1 && isspace( *output_1 ) )
{
/* Copy white space. */
while ( ( output_1 < ine ) && isspace( *output_1 ) )
++output_1;
}
if ( output_0 < output_1 )
{
if ( out_file ) fwrite(output_0,output_1-output_0,1,out_file);
if ( out_debug ) fwrite(output_0,output_1-output_0,1,stdout);
if ( out_file ) fwrite( output_0, output_1 - output_0, 1, out_file );
if ( out_debug ) fwrite( output_0, output_1 - output_0, 1, stdout );
}
output_0 = output_1;
/* Copy non-white space, watching for variables */
while( output_1 < ine && *output_1 && !isspace( *output_1 ) )
/* Copy non-white space, watching for variables. */
while ( ( output_1 < ine ) && *output_1 && !isspace( *output_1 ) )
{
if( output_1[0] == '$' && output_1[1] && output_1[1] == '(' )
{
dollar++;
}
if ( ( output_1[ 0 ] == '$' ) && ( output_1[ 1 ] == '(' ) )
++dollar;
++output_1;
}
/* If a variable encountered, expand it and embed the */
/* space-separated members of the list in the output. */
if( dollar )
/* If a variable encountered, expand it and embed the space-separated
* members of the list in the output.
*/
if ( dollar )
{
LIST *l;
l = var_expand( L0, (char*)output_0, (char*)output_1, lol, 0 );
LIST * l = var_expand( L0, (char *)output_0, (char *)output_1, lol, 0 );
while ( l )
{
@@ -457,45 +441,45 @@ void var_string_to_file( const char * in, int insize, const char * out, LOL * lo
}
else if ( output_0 < output_1 )
{
if ( out_file ) fwrite(output_0,output_1-output_0,1,out_file);
if ( out_debug ) fwrite(output_0,output_1-output_0,1,stdout);
if ( out_file ) fwrite( output_0, output_1 - output_0, 1, out_file );
if ( out_debug ) fwrite( output_0, output_1 - output_0, 1, stdout );
}
in = output_1;
}
if ( out_file && out_file != stdout && out_file != stderr )
if ( out_file && ( out_file != stdout ) && ( out_file != stderr ) )
{
fflush( out_file );
fclose( out_file );
}
if ( out_debug ) fputc('\n',stdout);
if ( out_debug ) fputc( '\n', stdout );
}
/*
* var_get() - get value of a user defined symbol
* var_get() - get value of a user defined symbol.
*
* Returns NULL if symbol unset.
*/
LIST *
var_get( char *symbol )
LIST * var_get( char * symbol )
{
LIST * result = 0;
#ifdef OPT_AT_FILES
#ifdef OPT_AT_FILES
/* Some "fixed" variables... */
if ( strcmp( "TMPDIR", symbol ) == 0 )
{
result = list_new( L0, newstr( (char*)path_tmpdir() ) );
result = list_new( L0, newstr( (char *)path_tmpdir() ) );
}
else if ( strcmp( "TMPNAME", symbol ) == 0 )
{
result = list_new( L0, newstr( (char*)path_tmpnam() ) );
result = list_new( L0, newstr( (char *)path_tmpnam() ) );
}
else if ( strcmp( "TMPFILE", symbol ) == 0 )
{
result = list_new( L0, newstr( (char*)path_tmpfile() ) );
result = list_new( L0, newstr( (char *)path_tmpfile() ) );
}
else if ( strcmp( "STDOUT", symbol ) == 0 )
{
@@ -506,15 +490,16 @@ var_get( char *symbol )
result = list_new( L0, newstr( "STDERR" ) );
}
else
#endif
#endif
{
VARIABLE var, *v = &var;
VARIABLE var;
VARIABLE * v = &var;
v->symbol = symbol;
if( varhash && hashcheck( varhash, (HASHDATA **)&v ) )
if ( varhash && hashcheck( varhash, (HASHDATA * *)&v ) )
{
if( DEBUG_VARGET )
if ( DEBUG_VARGET )
var_dump( v->symbol, v->value, "get" );
result = v->value;
}
@@ -522,29 +507,25 @@ var_get( char *symbol )
return result;
}
/*
* var_set() - set a variable in jam's user defined symbol table
* var_set() - set a variable in Jam's user defined symbol table.
*
* 'flag' controls the relationship between new and old values of
* the variable: SET replaces the old with the new; APPEND appends
* the new to the old; DEFAULT only uses the new if the variable
* was previously unset.
* 'flag' controls the relationship between new and old values of the variable:
* SET replaces the old with the new; APPEND appends the new to the old; DEFAULT
* only uses the new if the variable was previously unset.
*
* Copies symbol. Takes ownership of value.
* Copies symbol. Takes ownership of value.
*/
void
var_set(
char *symbol,
LIST *value,
int flag )
void var_set( char * symbol, LIST * value, int flag )
{
VARIABLE *v = var_enter( symbol );
VARIABLE * v = var_enter( symbol );
if( DEBUG_VARSET )
if ( DEBUG_VARSET )
var_dump( symbol, value, "set" );
switch( flag )
switch ( flag )
{
case VAR_SET:
/* Replace value */
@@ -559,85 +540,78 @@ var_set(
case VAR_DEFAULT:
/* Set only if unset */
if( !v->value )
v->value = value;
if ( !v->value )
v->value = value;
else
list_free( value );
list_free( value );
break;
}
}
/*
* var_swap() - swap a variable's value with the given one
* var_swap() - swap a variable's value with the given one.
*/
LIST *
var_swap(
char *symbol,
LIST *value )
LIST * var_swap( char * symbol, LIST * value )
{
VARIABLE *v = var_enter( symbol );
LIST *oldvalue = v->value;
if( DEBUG_VARSET )
VARIABLE * v = var_enter( symbol );
LIST * oldvalue = v->value;
if ( DEBUG_VARSET )
var_dump( symbol, value, "set" );
v->value = value;
return oldvalue;
}
/*
* var_enter() - make new var symbol table entry, returning var ptr
* var_enter() - make new var symbol table entry, returning var ptr.
*/
static VARIABLE *
var_enter( char *symbol )
static VARIABLE * var_enter( char * symbol )
{
VARIABLE var, *v = &var;
VARIABLE var;
VARIABLE * v = &var;
if( !varhash )
if ( !varhash )
varhash = hashinit( sizeof( VARIABLE ), "variables" );
v->symbol = symbol;
v->value = 0;
if( hashenter( varhash, (HASHDATA **)&v ) )
v->symbol = newstr( symbol ); /* never freed */
if ( hashenter( varhash, (HASHDATA * *)&v ) )
v->symbol = newstr( symbol ); /* never freed */
return v;
}
/*
* var_dump() - dump a variable to stdout
* var_dump() - dump a variable to stdout.
*/
static void
var_dump(
char *symbol,
LIST *value,
char *what )
static void var_dump( char * symbol, LIST * value, char * what )
{
printf( "%s %s = ", what, symbol );
list_print( value );
printf( "\n" );
}
/*
* var_done() - free variable tables
* var_done() - free variable tables.
*/
static void delete_var_( void* xvar, void* data )
static void delete_var_( void * xvar, void * data )
{
VARIABLE *v = (VARIABLE*)xvar;
VARIABLE * v = (VARIABLE *)xvar;
freestr( v->symbol );
list_free( v-> value );
}
void
var_done()
void var_done()
{
hashenumerate( varhash, delete_var_, (void*)0 );
hashenumerate( varhash, delete_var_, (void *)0 );
hashdone( varhash );
}