diff options
Diffstat (limited to 'jam-files/engine/compile.c')
-rw-r--r-- | jam-files/engine/compile.c | 220 |
1 files changed, 72 insertions, 148 deletions
diff --git a/jam-files/engine/compile.c b/jam-files/engine/compile.c index cb08e24c9..db46937ca 100644 --- a/jam-files/engine/compile.c +++ b/jam-files/engine/compile.c @@ -10,146 +10,72 @@ * (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 "compile.h" -# include "variable.h" -# include "rules.h" -# include "object.h" -# include "make.h" -# include "search.h" -# include "hdrmacro.h" -# include "hash.h" -# include "modules.h" -# include "strings.h" -# include "builtins.h" -# include "class.h" -# include "constants.h" - -# include <assert.h> -# include <string.h> -# include <stdarg.h> - /* * compile.c - compile parsed jam statements * * External routines: - * - * compile_append() - append list results of two statements - * compile_eval() - evaluate if to determine which leg to compile - * compile_foreach() - compile the "for x in y" statement - * compile_if() - compile 'if' rule - * compile_while() - compile 'while' rule - * compile_include() - support for 'include' - call include() on file - * compile_list() - expand and return a list - * compile_local() - declare (and set) local variables - * compile_null() - do nothing -- a stub for parsing - * compile_on() - run rule under influence of on-target variables - * compile_rule() - compile a single user defined rule - * compile_rules() - compile a chain of rules - * compile_set() - compile the "set variable" statement - * compile_setcomp() - support for `rule` - save parse tree - * compile_setexec() - support for `actions` - save execution string - * compile_settings() - compile the "on =" (set variable on exec) statement - * compile_switch() - compile 'switch' rule - * - * Internal routines: - * - * debug_compile() - printf with indent to show rule expansion. * evaluate_rule() - execute a rule invocation * - * builtin_depends() - DEPENDS/INCLUDES rule - * builtin_echo() - ECHO rule - * builtin_exit() - EXIT rule - * builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule - * - * 02/03/94 (seiwald) - Changed trace output to read "setting" instead of - * the awkward sounding "settings". - * 04/12/94 (seiwald) - Combined build_depends() with build_includes(). - * 04/12/94 (seiwald) - actionlist() now just appends a single action. - * 04/13/94 (seiwald) - added shorthand L0 for null list pointer - * 05/13/94 (seiwald) - include files are now bound as targets, and thus - * can make use of $(SEARCH) - * 06/01/94 (seiwald) - new 'actions existing' does existing sources - * 08/23/94 (seiwald) - Support for '+=' (append to variable) - * 12/20/94 (seiwald) - NOTIME renamed NOTFILE. - * 01/22/95 (seiwald) - Exit rule. - * 02/02/95 (seiwald) - Always rule; LEAVES rule. - * 02/14/95 (seiwald) - NoUpdate rule. - * 09/11/00 (seiwald) - new evaluate_rule() for headers(). - * 09/11/00 (seiwald) - compile_xxx() now return LIST *. - * New compile_append() and compile_list() in - * support of building lists here, rather than - * in jamgram.yy. - * 01/10/00 (seiwald) - built-ins split out to builtin.c. + * Internal routines: + * debug_compile() - printf with indent to show rule expansion */ -static void debug_compile( int which, const char * s, FRAME * frame ); -int glob( const char * s, const char * c ); -/* Internal functions from builtins.c */ -void backtrace( FRAME * frame ); -void backtrace_line( FRAME * frame ); -void print_source_line( FRAME * frame ); +#include "jam.h" +#include "compile.h" -struct frame * frame_before_python_call; +#include "builtins.h" +#include "class.h" +#include "constants.h" +#include "hash.h" +#include "hdrmacro.h" +#include "make.h" +#include "modules.h" +#include "parse.h" +#include "rules.h" +#include "search.h" +#include "strings.h" +#include "variable.h" -static OBJECT * module_scope; +#include <assert.h> +#include <stdarg.h> +#include <string.h> -void frame_init( FRAME* frame ) -{ - frame->prev = 0; - frame->prev_user = 0; - lol_init(frame->args); - frame->module = root_module(); - frame->rulename = "module scope"; - frame->file = 0; - frame->line = -1; -} +static void debug_compile( int which, char const * s, FRAME * ); -void frame_free( FRAME* frame ) -{ - lol_free( frame->args ); -} +/* Internal functions from builtins.c */ +void backtrace( FRAME * ); +void backtrace_line( FRAME * ); +void print_source_line( FRAME * ); +void unknown_rule( FRAME *, char const * key, module_t *, OBJECT * rule_name ); /* - * evaluate_rule() - execute a rule invocation. + * evaluate_rule() - execute a rule invocation */ -LIST * -evaluate_rule( - OBJECT * rulename, - FRAME * frame ) +LIST * evaluate_rule( RULE * rule, OBJECT * rulename, FRAME * frame ) { LIST * result = L0; - RULE * rule; - profile_frame prof[1]; + profile_frame prof[ 1 ]; module_t * prev_module = frame->module; - rule = bindrule( rulename, frame->module ); - if ( DEBUG_COMPILE ) { /* Try hard to indicate in which module the rule is going to execute. */ - if ( rule->module != frame->module - && rule->procedure != 0 && !object_equal( rulename, function_rulename( rule->procedure ) ) ) + char buf[ 256 ] = ""; + if ( rule->module->name ) { - char buf[256] = ""; - if ( rule->module->name ) + strncat( buf, object_str( rule->module->name ), sizeof( buf ) - + 1 ); + strncat( buf, ".", sizeof( buf ) - 1 ); + if ( strncmp( buf, object_str( rule->name ), strlen( buf ) ) == 0 ) { - strncat( buf, object_str( rule->module->name ), sizeof( buf ) - 1 ); - strncat( buf, ".", sizeof( buf ) - 1 ); + buf[ 0 ] = 0; } - strncat( buf, object_str( rule->name ), sizeof( buf ) - 1 ); - debug_compile( 1, buf, frame ); - } - else - { - debug_compile( 1, object_str( rulename ), frame ); } + strncat( buf, object_str( rule->name ), sizeof( buf ) - 1 ); + debug_compile( 1, buf, frame ); lol_print( frame->args ); printf( "\n" ); @@ -172,19 +98,7 @@ evaluate_rule( /* Check traditional targets $(<) and sources $(>). */ if ( !rule->actions && !rule->procedure ) - { - backtrace_line( frame->prev ); - if ( frame->module->name ) - { - printf( "rule %s unknown in module %s\n", object_str( rule->name ), object_str( frame->module->name ) ); - } - else - { - printf( "rule %s unknown in module \n", object_str( rule->name ) ); - } - backtrace( frame->prev ); - exit( 1 ); - } + unknown_rule( frame, NULL, frame->module, rule->name ); /* If this rule will be executed for updating the targets then construct the * action for make(). @@ -192,10 +106,9 @@ evaluate_rule( if ( rule->actions ) { TARGETS * t; - ACTION * action; /* The action is associated with this instance of this rule. */ - action = (ACTION *)BJAM_MALLOC( sizeof( ACTION ) ); + ACTION * const action = (ACTION *)BJAM_MALLOC( sizeof( ACTION ) ); memset( (char *)action, '\0', sizeof( *action ) ); action->rule = rule; @@ -205,11 +118,12 @@ evaluate_rule( /* If we have a group of targets all being built using the same action * then we must not allow any of them to be used as sources unless they - * had all already been built in the first place or their joined action - * has had a chance to finish its work and build all of them anew. + * are all up to date and their action does not need to be run or their + * action has had a chance to finish its work and build all of them + * anew. * * Without this it might be possible, in case of a multi-process build, - * for their action, triggered by buiding one of the targets, to still + * for their action, triggered to building one of the targets, to still * be running when another target in the group reports as done in order * to avoid triggering the same action again and gets used prematurely. * @@ -223,7 +137,7 @@ evaluate_rule( * dependency' issue. * * TODO: Although the current implementation solves the problem of one - * of the targets getting used before its action completes its work it + * of the targets getting used before its action completes its work, it * also forces the action to run whenever any of the targets in the * group is not up to date even though some of them might not actually * be used by the targets being built. We should see how we can @@ -231,13 +145,24 @@ evaluate_rule( * action if possible and not rebuild targets not actually depending on * targets that are not up to date. * - * TODO: Using the 'include' feature might have side-effects due to - * interaction with the actual 'inclusion scanning' system. This should - * be checked. + * TODO: Current solution using fake INCLUDES relations may cause + * actions to be run when the affected targets are built by multiple + * actions. E.g. if we have the following actions registered in the + * order specified: + * (I) builds targets A & B + * (II) builds target B + * and we want to build a target depending on target A, then both + * actions (I) & (II) will be run, even though the second one does not + * have any direct relationship to target A. Consider whether this is + * desired behaviour or not. It could be that Boost Build should (or + * possibly already does) run all actions registered for a given target + * if any of them needs to be run in which case our INCLUDES relations + * are not actually causing any actions to be run that would not have + * been run without them. */ if ( action->targets ) { - TARGET * t0 = action->targets->target; + TARGET * const t0 = action->targets->target; for ( t = action->targets->next; t; t = t->next ) { target_include( t->target, t0 ); @@ -253,13 +178,12 @@ evaluate_rule( } /* Now recursively compile any parse tree associated with this rule. - * function_refer()/function_free() call pair added to ensure rule not freed - * during use. + * function_refer()/function_free() call pair added to ensure the rule does + * not get freed while in use. */ if ( rule->procedure ) { - FUNCTION * function = rule->procedure; - + FUNCTION * const function = rule->procedure; function_refer( function ); result = function_run( function, frame, stack_global() ); function_free( function ); @@ -269,7 +193,7 @@ evaluate_rule( profile_exit( prof ); if ( DEBUG_COMPILE ) - debug_compile( -1, 0, frame); + debug_compile( -1, 0, frame ); return result; } @@ -289,24 +213,25 @@ LIST * call_rule( OBJECT * rulename, FRAME * caller_frame, ... ) va_list va; LIST * result; - FRAME inner[1]; + FRAME inner[ 1 ]; frame_init( inner ); inner->prev = caller_frame; - inner->prev_user = caller_frame->module->user_module ? - caller_frame : caller_frame->prev_user; + inner->prev_user = caller_frame->module->user_module + ? caller_frame + : caller_frame->prev_user; inner->module = caller_frame->module; va_start( va, caller_frame ); for ( ; ; ) { - LIST * l = va_arg( va, LIST* ); + LIST * const l = va_arg( va, LIST * ); if ( !l ) break; lol_add( inner->args, l ); } va_end( va ); - result = evaluate_rule( rulename, inner ); + result = evaluate_rule( bindrule( rulename, inner->module ), rulename, inner ); frame_free( inner ); @@ -314,15 +239,14 @@ LIST * call_rule( OBJECT * rulename, FRAME * caller_frame, ... ) } - /* - * debug_compile() - printf with indent to show rule expansion. + * debug_compile() - printf with indent to show rule expansion */ -static void debug_compile( int which, const char * s, FRAME * frame ) +static void debug_compile( int which, char const * s, FRAME * frame ) { static int level = 0; - static char indent[36] = ">>>>|>>>>|>>>>|>>>>|>>>>|>>>>|>>>>|"; + static char indent[ 36 ] = ">>>>|>>>>|>>>>|>>>>|>>>>|>>>>|>>>>|"; if ( which >= 0 ) { |