Beispiel #1
0
LIST *
compile_setexec(
	PARSE	*parse,
	LOL	*args,
	int	*jmp )
{
	RULE	*rule = bindrule( parse->string );
	LIST	*bindlist = (*parse->left->func)( parse->left, args, jmp );
	
	/* Free old one, if present */

	if( rule->actions )
	{
	    freestr( rule->actions );
	    list_free( rule->bindlist );
	}

	rule->actions = copystr( parse->string1 );
	rule->bindlist = bindlist;
	rule->flags = parse->num;
/* commented out so jamgram.y can compile #ifdef OPT_ACTION_MAXTARGETS_EXT */
	rule->maxline = parse->num2;
	rule->maxtargets = parse->num3;
/* commented out so jamgram.y can compile #endif */

	return L0;
}
Beispiel #2
0
void call_bind_rule( OBJECT * target_, OBJECT * boundname_ )
{
    LIST * const bind_rule = var_get( root_module(), constant_BINDRULE );
    if ( !list_empty( bind_rule ) )
    {
        OBJECT * target = object_copy( target_ );
        OBJECT * boundname = object_copy( boundname_ );
        if ( boundname && target )
        {
            /* Prepare the argument list. */
            FRAME frame[ 1 ];
            frame_init( frame );

            /* First argument is the target name. */
            lol_add( frame->args, list_new( target ) );

            lol_add( frame->args, list_new( boundname ) );
            if ( lol_get( frame->args, 1 ) )
            {
                OBJECT * rulename = list_front( bind_rule );
                list_free( evaluate_rule( bindrule( rulename, root_module() ), rulename, frame ) );
            }

            /* Clean up */
            frame_free( frame );
        }
        else
        {
            if ( boundname )
                object_free( boundname );
            if ( target )
                object_free( target );
        }
    }
}
Beispiel #3
0
static void call_action_rule
(
    TARGET * target,
    int status,
    timing_info const * time,
    char const * executed_command,
    char const * command_output
)
{
    LIST * action_rule;

    pushsettings( root_module(), target->settings );
    action_rule = var_get( root_module(), constant_ACTION_RULE );
    popsettings( root_module(), target->settings );

    if ( !list_empty( action_rule ) )
    {
        /* rule action-rule (
            args * :
            target :
            command status start end user system :
            output ? ) */

        /* Prepare the argument list. */
        FRAME frame[ 1 ];
        OBJECT * rulename = list_front( action_rule );
        frame_init( frame );

        /* args * :: $(__ACTION_RULE__[2-]) */
        lol_add( frame->args, list_copy_range( action_rule, list_next(
            list_begin( action_rule ) ), list_end( action_rule ) ) );

        /* target :: the name of the target */
        lol_add( frame->args, list_new( object_copy( target->name ) ) );

        /* command status start end user system :: info about the action command
         */
        lol_add( frame->args,
            list_push_back( list_push_back( list_push_back( list_push_back( list_push_back( list_new(
                object_new( executed_command ) ),
                outf_int( status ) ),
                outf_time( &time->start ) ),
                outf_time( &time->end ) ),
                outf_double( time->user ) ),
                outf_double( time->system ) ) );

        /* output ? :: the output of the action command */
        if ( command_output )
            lol_add( frame->args, list_new( object_new( command_output ) ) );
        else
            lol_add( frame->args, L0 );

        /* Call the rule. */
        evaluate_rule( bindrule( rulename, root_module() ), rulename, frame );

        /* Clean up. */
        frame_free( frame );
    }
}
Beispiel #4
0
void headers( TARGET * t )
{
    LIST   * hdrscan;
    LIST   * hdrrule;
    #ifndef OPT_HEADER_CACHE_EXT
    LIST   * headlist = L0;
    #endif
    regexp * re[ MAXINC ];
    int rec = 0;
    LISTITER iter;
    LISTITER end;

    hdrscan = var_get( root_module(), constant_HDRSCAN );
    if ( list_empty( hdrscan ) )
        return;

    hdrrule = var_get( root_module(), constant_HDRRULE );
    if ( list_empty( hdrrule ) )
        return;

    if ( DEBUG_HEADER )
        out_printf( "header scan %s\n", object_str( t->name ) );

    /* Compile all regular expressions in HDRSCAN */
    iter = list_begin( hdrscan );
    end = list_end( hdrscan );
    for ( ; ( rec < MAXINC ) && iter != end; iter = list_next( iter ) )
    {
        re[ rec++ ] = regex_compile( list_item( iter ) );
    }

    /* Doctor up call to HDRRULE rule */
    /* Call headers1() to get LIST of included files. */
    {
        FRAME frame[ 1 ];
        frame_init( frame );
        lol_add( frame->args, list_new( object_copy( t->name ) ) );
#ifdef OPT_HEADER_CACHE_EXT
        lol_add( frame->args, hcache( t, rec, re, hdrscan ) );
#else
        lol_add( frame->args, headers1( headlist, t->boundname, rec, re ) );
#endif

        if ( lol_get( frame->args, 1 ) )
        {
            OBJECT * rulename = list_front( hdrrule );
            /* The third argument to HDRRULE is the bound name of $(<). */
            lol_add( frame->args, list_new( object_copy( t->boundname ) ) );
            list_free( evaluate_rule( bindrule( rulename, frame->module ), rulename, frame ) );
        }

        /* Clean up. */
        frame_free( frame );
    }
}
Beispiel #5
0
LIST *
compile_setcomp(
	PARSE	*parse,
	LOL	*args,
	int	*jmp )
{
	RULE	*rule = bindrule( parse->string );
	LIST	*params = 0;
	PARSE	*p;

	/* Build param list */

	for( p = parse->left; p; p = p->left )
	    params = list_append( params, p->string, 1 );

	if( DEBUG_COMPILE )
	{
	    debug_compile( 0, "rule" );
	    printf( "%s ", parse->string );
	    list_print( params );
	    printf( "\n" );
	}

	/* Free old one, if present */

	if( rule->procedure )
	    parse_free( rule->procedure );

	if( rule->params )
	    list_free( rule->params );

	rule->procedure = parse->right;
	rule->params = params;

	/* we now own this parse tree */
	/* don't let parse_free() release it */

	parse_refer( parse->right );

	return L0;
}
Beispiel #6
0
static void call_timing_rule( TARGET * target, timing_info const * const time )
{
    LIST * timing_rule;

    pushsettings( root_module(), target->settings );
    timing_rule = var_get( root_module(), constant_TIMING_RULE );
    popsettings( root_module(), target->settings );

    if ( !list_empty( timing_rule ) )
    {
        /* rule timing-rule ( args * : target : start end user system ) */

        /* Prepare the argument list. */
        FRAME frame[ 1 ];
        OBJECT * rulename = list_front( timing_rule );
        frame_init( frame );

        /* args * :: $(__TIMING_RULE__[2-]) */
        lol_add( frame->args, list_copy_range( timing_rule, list_next(
            list_begin( timing_rule ) ), list_end( timing_rule ) ) );

        /* target :: the name of the target */
        lol_add( frame->args, list_new( object_copy( target->name ) ) );

        /* start end user system :: info about the action command */
        lol_add( frame->args, list_push_back( list_push_back( list_push_back( list_new(
            outf_time( &time->start ) ),
            outf_time( &time->end ) ),
            outf_double( time->user ) ),
            outf_double( time->system ) ) );

        /* Call the rule. */
        evaluate_rule( bindrule( rulename , root_module() ), rulename, frame );

        /* Clean up. */
        frame_free( frame );
    }
}
Beispiel #7
0
LIST *
compile_setexec(
	PARSE	*parse,
	LOL	*args,
	int	*jmp )
{
	RULE	*rule = bindrule( parse->string );
	LIST	*bindlist = (*parse->left->func)( parse->left, args, jmp );
	
	/* Free old one, if present */

	if( rule->actions )
	{
	    freestr( rule->actions );
	    list_free( rule->bindlist );
	}

	rule->actions = copystr( parse->string1 );
	rule->bindlist = bindlist;
	rule->flags = parse->num;

	return L0;
}
Beispiel #8
0
LIST *
evaluate_rule(
    char  * rulename,
    FRAME * frame )
{
    LIST          * result = L0;
    RULE          * rule;
    profile_frame   prof[1];
    module_t      * prev_module = frame->module;

    LIST * l;
    {
        LOL arg_context_, * arg_context = &arg_context_;
        if ( !frame->prev )
            lol_init(arg_context);
        else
            arg_context = frame->prev->args;
        l = var_expand( L0, rulename, rulename+strlen(rulename), arg_context, 0 );
    }

    if ( !l )
    {
        backtrace_line( frame->prev );
        printf( "warning: rulename %s expands to empty string\n", rulename );
        backtrace( frame->prev );
        return result;
    }

    rulename = l->string;
    rule = bindrule( l->string, frame->module );

#ifdef HAVE_PYTHON
    if ( rule->python_function )
    {
        /* The below messing with modules is due to the way modules are
         * implemented in Jam. Suppose we are in module M1 now. The global
         * variable map actually holds 'M1' variables, and M1->variables hold
         * global variables.
         *
         * If we call Python right away, Python calls back Jam and then Jam
         * does 'module M1 { }' then Jam will try to swap the current global
         * variables with M1->variables. The result will be that global
         * variables map will hold global variables, and any variable settings
         * we do will go to the global module, not M1.
         *
         * By restoring basic state, where the global variable map holds global
         * variable, we make sure any future 'module M1' entry will work OK.
         */

        LIST * result;
        module_t * m = python_module();

        frame->module = m;

        exit_module( prev_module );
        enter_module( m );

        result = call_python_function( rule, frame );

        exit_module( m );
        enter_module ( prev_module );

        return result;
    }
#endif

    /* Drop the rule name. */
    l = list_pop_front( l );

    /* Tack the rest of the expansion onto the front of the first argument. */
    frame->args->list[0] = list_append( l, lol_get( frame->args, 0 ) );

    if ( DEBUG_COMPILE )
    {
        /* Try hard to indicate in which module the rule is going to execute. */
        if ( rule->module != frame->module
             && rule->procedure != 0 && strcmp( rulename, rule->procedure->rulename ) )
        {
            char buf[256] = "";
            strncat( buf, rule->module->name, sizeof( buf ) - 1 );
            strncat( buf, rule->name, sizeof( buf ) - 1 );
            debug_compile( 1, buf, frame );
        }
        else
        {
            debug_compile( 1, rulename, frame );
        }

        lol_print( frame->args );
        printf( "\n" );
    }

    if ( rule->procedure && rule->module != prev_module )
    {
        /* Propagate current module to nested rule invocations. */
        frame->module = rule->module;

        /* Swap variables. */
        exit_module( prev_module );
        enter_module( rule->module );
    }

    /* Record current rule name in frame. */
    if ( rule->procedure )
    {
        frame->rulename = rulename;
        /* And enter record profile info. */
        if ( DEBUG_PROFILE )
            profile_enter( rule->procedure->rulename, prof );
    }

    /* Check traditional targets $(<) and sources $(>). */
    if ( !rule->actions && !rule->procedure )
    {
        backtrace_line( frame->prev );
        printf( "rule %s unknown in module %s\n", rule->name, frame->module->name );
        backtrace( frame->prev );
        exit( 1 );
    }

    /* If this rule will be executed for updating the targets then construct the
     * action for make().
     */
    if ( rule->actions )
    {
        TARGETS * t;
        ACTION  * action;

        /* The action is associated with this instance of this rule. */
        action = (ACTION *)BJAM_MALLOC( sizeof( ACTION ) );
        memset( (char *)action, '\0', sizeof( *action ) );

        action->rule = rule;
        action->targets = targetlist( (TARGETS *)0, lol_get( frame->args, 0 ) );
        action->sources = targetlist( (TARGETS *)0, lol_get( frame->args, 1 ) );

        /* 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.
         *
         * 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
         * be running when another target in the group reports as done in order
         * to avoid triggering the same action again and gets used prematurely.
         *
         * As a quick-fix to achieve this effect we make all the targets list
         * each other as 'included targets'. More precisely, we mark the first
         * listed target as including all the other targets in the list and vice
         * versa. This makes anyone depending on any of those targets implicitly
         * depend on all of them, thus making sure none of those targets can be
         * used as sources until all of them have been built. Note that direct
         * dependencies could not have been used due to the 'circular
         * dependency' issue.
         *
         * TODO: Although the current implementation solves the problem of one
         * 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
         * correctly recognize such cases and use that to avoid running the
         * 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.
         */
        if ( action->targets )
        {
            TARGET * t0 = action->targets->target;
            for ( t = action->targets->next; t; t = t->next )
            {
                target_include( t->target, t0 );
                target_include( t0, t->target );
            }
        }

        /* Append this action to the actions of each target. */
        for ( t = action->targets; t; t = t->next )
            t->target->actions = actionlist( t->target->actions, action );
    }

    /* Now recursively compile any parse tree associated with this rule.
     * parse_refer()/parse_free() call pair added to ensure rule not freed
     * during use.
     */
    if ( rule->procedure )
    {
        SETTINGS * local_args = collect_arguments( rule, frame );
        PARSE * parse = rule->procedure;
        parse_refer( parse );

        pushsettings( local_args );
        result = parse_evaluate( parse, frame );
        popsettings( local_args );
        freesettings( local_args );

        parse_free( parse );
    }

    if ( frame->module != prev_module )
    {
        exit_module( frame->module );
        enter_module( prev_module );
    }

    if ( DEBUG_PROFILE && rule->procedure )
        profile_exit( prof );

    if ( DEBUG_COMPILE )
        debug_compile( -1, 0, frame);

    return result;
}
Beispiel #9
0
LIST *
evaluate_rule(
	const char *rulename,
	LOL	*args, 
	LIST	*result )
{
#ifdef OPT_EXPAND_RULE_NAMES_EXT
	RULE	*rule;
	char	*expanded;
	char	*c;
	int i;
	BUFFER	buff;

	buffer_init( &buff );

	if( (i = var_string( rulename, &buff, 0, args, ' ' )) < 0 )
	{
	    printf( "Failed to expand rule %s -- expansion too long\n", rulename );
	    exit( EXITBAD );
	}
	expanded = buffer_ptr( &buff );
	while ( expanded[0] == ' ' )
	    expanded++;
	while ( (c = strrchr(expanded, ' ')) )
	    *c = '\0';

	if( DEBUG_COMPILE )
	{
	    debug_compile( 1, rulename );
	    if ( strcmp(rulename, expanded) )
		printf( "-> %s  ", expanded );
	    lol_print( args );
	    printf( "\n" );
	}

	rule = bindrule( expanded );
#else	
	RULE	*rule = bindrule( rulename );

	if( DEBUG_COMPILE )
	{
	    debug_compile( 1, rulename );
	    lol_print( args );
	    printf( "\n" );
	}
#endif

#ifdef OPT_LOAD_MISSING_RULE_EXT
	if( !rule->actions && !rule->procedure )
	{
		if( ruleexists( "FindMissingRule" ) )
		{
			LOL lol;
			LIST *args = list_append( L0, expanded, 0 );
			LIST *result;

			lol_init( &lol );
			lol_add( &lol, args );
			result = evaluate_rule( "FindMissingRule", &lol, L0 );
			lol_free( &lol );

			if( list_first( result ) ) {
				rule = bindrule( list_value( list_first( result ) ) );
			}

			list_free( result );
		}
	}
#endif /* OPT_LOAD_MISSING_RULE_EXT */

	/* Check traditional targets $(<) and sources $(>) */

#ifdef OPT_IMPROVED_WARNINGS_EXT
	if( !rule->actions && !rule->procedure && !globs.silence )
	    printf( "warning: unknown rule %s %s\n", rule->name,
		   file_and_line());
#else
	if( !rule->actions && !rule->procedure )
	    printf( "warning: unknown rule %s\n", rule->name );
#endif

	/* If this rule will be executed for updating the targets */
	/* then construct the action for make(). */

	if( rule->actions )
	{
	    TARGETS	*t;
	    ACTION	*action;

	    /* The action is associated with this instance of this rule */

	    action = (ACTION *)malloc( sizeof( ACTION ) );
	    memset( (char *)action, '\0', sizeof( *action ) );

	    action->rule = rule;
#ifdef OPT_BUILTIN_NEEDS_EXT
	    action->targets = targetlist( (TARGETS *)0, lol_get( args, 0 ), 0 );
	    action->sources = targetlist( (TARGETS *)0, lol_get( args, 1 ), 0 );
	    action->autosettings = targetlist( (TARGETS *)0, lol_get( args, 2 ), 0 );
#else
	    action->targets = targetlist( (TARGETS *)0, lol_get( args, 0 ) );
	    action->sources = targetlist( (TARGETS *)0, lol_get( args, 1 ) );
#endif
#ifdef OPT_USE_CHECKSUMS_EXT
	    action->extratargets = targetlist( (TARGETS *)0, lol_get( args, 3 ), 0 );
#endif /* OPT_USE_CHECKSUMS_EXT */

#ifdef OPT_CLEAN_GLOBS_EXT
		{
			TARGETS* targets;
			for ( targets = action->targets; targets; targets = targets->next ) {
				if ( !( targets->target->flags & T_FLAG_NOTFILE ) )
					add_used_target_to_hash( targets->target );
			}
		}
#endif /* OPT_CLEAN_GLOBS_EXT */

	    /* Append this action to the actions of each target */

#ifdef OPT_MULTIPASS_EXT
	    action->pass = actionpass;
	    for( t = action->targets; t; t = t->next ) {
		t->target->progress = T_MAKE_INIT;
		t->target->actions = actionlist( t->target->actions, action );
	    }
#else
	    for( t = action->targets; t; t = t->next )
		t->target->actions = actionlist( t->target->actions, action );
#endif
	}

	/* Now recursively compile any parse tree associated with this rule */

	if( rule->procedure )
	{
	    PARSE *parse = rule->procedure;
	    SETTINGS *s = 0;
	    int jmp = JMP_NONE;
	    LISTITEM *l;
	    int i;

	    /* build parameters as local vars */
	    for( l = list_first(rule->params), i = 0; l; l = list_next(l), i++ )
		s = addsettings( s, 0, list_value(l), 
		    list_copy( L0, lol_get( args, i ) ) );

	    /* Run rule. */
	    /* Bring in local params. */
	    /* refer/free to ensure rule not freed during use. */

	    parse_refer( parse );

	    pushsettings( s );
	    result = list_appendList( result, (*parse->func)( parse, args, &jmp ) );
	    popsettings( s );
	    freesettings( s );

	    parse_free( parse );
	}

	if( DEBUG_COMPILE )
	    debug_compile( -1, 0 );

#ifdef OPT_EXPAND_RULE_NAMES_EXT
	buffer_free( &buff );
#endif

	return result;
}
Beispiel #10
0
LIST *
evaluate_rule(
	const char *rulename,
	LOL	*args, 
	LIST	*result,
	int	*jmp )
{
	RULE	*rule = bindrule( rulename );

	if( DEBUG_COMPILE )
	{
	    debug_compile( 1, rulename );
	    lol_print( args );
	    printf( "\n" );
	}

	/* Check traditional targets $(<) and sources $(>) */

	if( !rule->actions && !rule->procedure )
	    printf( "warning: unknown rule %s\n", rule->name );

	/* If this rule will be executed for updating the targets */
	/* then construct the action for make(). */

	if( rule->actions )
	{
	    TARGETS	*t;
	    ACTION	*action;

	    /* The action is associated with this instance of this rule */

	    action = (ACTION *)malloc( sizeof( ACTION ) );
	    memset( (char *)action, '\0', sizeof( *action ) );

	    action->rule = rule;
	    action->targets = targetlist( (TARGETS *)0, lol_get( args, 0 ) );
	    action->sources = targetlist( (TARGETS *)0, lol_get( args, 1 ) );

	    /* Append this action to the actions of each target */

	    for( t = action->targets; t; t = t->next )
		t->target->actions = actionlist( t->target->actions, action );
	}

	/* Now recursively compile any parse tree associated with this rule */

	if( rule->procedure )
	{
	    PARSE *parse = rule->procedure;
	    SETTINGS *s = 0;
	    LIST *l;
	    int i;

# ifdef OPT_RULE_PROFILING_EXT
		struct timeval startTime, endTime;

		if ( DEBUG_PROFILE_RULES )
			gettimeofday(&startTime, 0);
# endif

	    /* build parameters as local vars */

	    for( l = rule->params, i = 0; l; l = l->next, i++ )
		s = addsettings( s, 0, l->string, 
		    list_copy( L0, lol_get( args, i ) ) );

	    /* Run rule. */
	    /* Bring in local params. */
	    /* refer/free to ensure rule not freed during use. */

	    parse_refer( parse );

	    pushsettings( s );
	    result = list_append( result, (*parse->func)( parse, args, jmp ) );
	    popsettings( s );
	    freesettings( s );

	    parse_free( parse );

# ifdef OPT_RULE_PROFILING_EXT
		if ( DEBUG_PROFILE_RULES )
		{
			gettimeofday(&endTime, 0);

			rule->invocations++;
			rule->invocation_time
				+= (endTime.tv_sec - startTime.tv_sec) * (int64_t)1000000
					+ (endTime.tv_usec - startTime.tv_usec);
		}
# endif

	}

	if( DEBUG_COMPILE )
	    debug_compile( -1, 0 );

	return result;
}
Beispiel #11
0
// jam_action(name, function, {options})
int LS_jam_action(ls_lua_State *L)
{
    RULE* rule;
    const char* name;
    int paramIndex = 2;

    int numParams = ls_lua_gettop(L);
    if (numParams < 2) {
        //ls_luaL_error
        return 0;
    }

    if (!ls_lua_isstring(L, 1))
        return 0;
    name = ls_lua_tostring(L, 1);
    rule = bindrule(name);

    if (rule->actions) {
        freestr(rule->actions);
        rule->actions = NULL;
    }

    if (rule->bindlist) {
        list_free(rule->bindlist);
        rule->bindlist = L0;
    }

    if (ls_lua_isstring(L, 2))
        paramIndex = 2;
    else if (ls_lua_isstring(L, 3))
        paramIndex = 3;
    else {
        return 0;
    }

    rule->actions = copystr(ls_lua_tostring(L, paramIndex));
    rule->flags = 0;

    paramIndex = paramIndex == 2 ? 3 : 2;

    if (ls_lua_istable(L, paramIndex)) {
        ls_lua_getfield(L, paramIndex, "bind");
        if (ls_lua_istable(L, -1)) {
            ls_lua_pushnil(L);
            while (ls_lua_next(L, -2) != 0) {
                if (!ls_lua_tostring(L, -1)) {
                    printf("!!\n");
                    exit(1);
                }
                rule->bindlist = list_append(rule->bindlist, ls_lua_tostring(L, -1), 0);
                ls_lua_pop(L, 1);
            }
            ls_lua_pop(L, 1);
        }
        ls_lua_pop(L, 1);

        ls_lua_getfield(L, paramIndex, "updated");
        rule->flags |= ls_lua_toboolean(L, -1) ? RULE_UPDATED : 0;
        ls_lua_pop(L, 1);

        ls_lua_getfield(L, paramIndex, "together");
        rule->flags |= ls_lua_toboolean(L, -1) ? RULE_TOGETHER : 0;
        ls_lua_pop(L, 1);

        ls_lua_getfield(L, paramIndex, "ignore");
        rule->flags |= ls_lua_toboolean(L, -1) ? RULE_IGNORE : 0;
        ls_lua_pop(L, 1);

        ls_lua_getfield(L, paramIndex, "quietly");
        rule->flags |= ls_lua_toboolean(L, -1) ? RULE_QUIETLY : 0;
        ls_lua_pop(L, 1);

        ls_lua_getfield(L, paramIndex, "piecemeal");
        rule->flags |= ls_lua_toboolean(L, -1) ? RULE_PIECEMEAL : 0;
        ls_lua_pop(L, 1);

        ls_lua_getfield(L, paramIndex, "existing");
        rule->flags |= ls_lua_toboolean(L, -1) ? RULE_EXISTING : 0;
        ls_lua_pop(L, 1);

        ls_lua_getfield(L, paramIndex, "response");
        rule->flags |= ls_lua_toboolean(L, -1) ? RULE_RESPONSE : 0;
        ls_lua_pop(L, 1);

        ls_lua_getfield(L, paramIndex, "lua");
        rule->flags |= ls_lua_toboolean(L, -1) ? RULE_LUA : 0;
        ls_lua_pop(L, 1);

        ls_lua_getfield(L, paramIndex, "screenoutput");
        rule->flags |= ls_lua_toboolean(L, -1) ? RULE_SCREENOUTPUT : 0;
        ls_lua_pop(L, 1);

        ls_lua_getfield(L, paramIndex, "removeemptydirs");
        rule->flags |= ls_lua_toboolean(L, -1) ? RULE_REMOVEEMPTYDIRS : 0;
        ls_lua_pop(L, 1);

        ls_lua_getfield(L, paramIndex, "maxtargets");
        if (ls_lua_isnumber(L, -1)) {
            rule->flags |= RULE_MAXTARGETS;
            rule->maxtargets = (int)ls_lua_tonumber(L, -1);
        }
        ls_lua_pop(L, 1);

        ls_lua_getfield(L, paramIndex, "maxline");
        if (ls_lua_isnumber(L, -1)) {
            rule->flags |= RULE_MAXLINE;
            rule->maxline = (int)ls_lua_tonumber(L, -1);
        }
        ls_lua_pop(L, 1);
    }

    return 0;
}
Beispiel #12
0
void
compile_builtins()
{
    /* Note that we cannot share the PARSE object between the different */
    /* variants of a given rule name, since we do no know if the Jambase */
    /* or Jamfile will redefine one of the rules and thus free the PARSE */
    /* object. */

    bindrule( "Always" )->procedure = 
        parse_make( builtin_flags, P0, P0, C0, C0, L0, L0, T_FLAG_TOUCHED );
    bindrule( "ALWAYS" )->procedure = 
        parse_make( builtin_flags, P0, P0, C0, C0, L0, L0, T_FLAG_TOUCHED );

    bindrule( "Depends" )->procedure = 
        parse_make( builtin_depends, P0, P0, C0, C0, L0, L0, T_DEPS_DEPENDS );
    bindrule( "DEPENDS" )->procedure = 
        parse_make( builtin_depends, P0, P0, C0, C0, L0, L0, T_DEPS_DEPENDS );

    bindrule( "Echo" )->procedure = 
        parse_make( builtin_echo, P0, P0, C0, C0, L0, L0, 0 );
    bindrule( "ECHO" )->procedure = 
        parse_make( builtin_echo, P0, P0, C0, C0, L0, L0, 0 );

    bindrule( "Exit" )->procedure = 
        parse_make( builtin_exit, P0, P0, C0, C0, L0, L0, 0 );
    bindrule( "EXIT" )->procedure = 
        parse_make( builtin_exit, P0, P0, C0, C0, L0, L0, 0 );

    bindrule( "Includes" )->procedure = 
        parse_make( builtin_depends, P0, P0, C0, C0, L0, L0, T_DEPS_INCLUDES );
    bindrule( "INCLUDES" )->procedure = 
        parse_make( builtin_depends, P0, P0, C0, C0, L0, L0, T_DEPS_INCLUDES );

    bindrule( "Leaves" )->procedure = 
        parse_make( builtin_flags, P0, P0, C0, C0, L0, L0, T_FLAG_LEAVES );
    bindrule( "LEAVES" )->procedure = 
        parse_make( builtin_flags, P0, P0, C0, C0, L0, L0, T_FLAG_LEAVES );

    bindrule( "NoCare" )->procedure = 
        parse_make( builtin_flags, P0, P0, C0, C0, L0, L0, T_FLAG_NOCARE );
    bindrule( "NOCARE" )->procedure = 
        parse_make( builtin_flags, P0, P0, C0, C0, L0, L0, T_FLAG_NOCARE );

    bindrule( "NOTIME" )->procedure = 
        parse_make( builtin_flags, P0, P0, C0, C0, L0, L0, T_FLAG_NOTFILE );
    bindrule( "NotFile" )->procedure = 
        parse_make( builtin_flags, P0, P0, C0, C0, L0, L0, T_FLAG_NOTFILE );
    bindrule( "NOTFILE" )->procedure = 
        parse_make( builtin_flags, P0, P0, C0, C0, L0, L0, T_FLAG_NOTFILE );

    bindrule( "NoUpdate" )->procedure = 
        parse_make( builtin_flags, P0, P0, C0, C0, L0, L0, T_FLAG_NOUPDATE );
    bindrule( "NOUPDATE" )->procedure = 
        parse_make( builtin_flags, P0, P0, C0, C0, L0, L0, T_FLAG_NOUPDATE );

    bindrule( "Temporary" )->procedure = 
        parse_make( builtin_flags, P0, P0, C0, C0, L0, L0, T_FLAG_TEMP );
    bindrule( "TEMPORARY" )->procedure = 
        parse_make( builtin_flags, P0, P0, C0, C0, L0, L0, T_FLAG_TEMP );
}
Beispiel #13
0
LIST *
evaluate_rule(
    char    *rulename,
    FRAME *frame )
{
    LIST      *result = L0;
    RULE          *rule;
    profile_frame prof[1];
    module_t    *prev_module = frame->module;
    
    LIST      *l;
    {
        LOL arg_context_, *arg_context = &arg_context_;
        if ( !frame->prev )
            lol_init(arg_context);
        else
            arg_context = frame->prev->args;
        
        l = var_expand( L0, rulename, rulename+strlen(rulename), arg_context, 0 );
    }

    if ( !l )
    {
        backtrace_line( frame->prev );
        printf( "warning: rulename %s expands to empty string\n", rulename );
        backtrace( frame->prev );
        return result;
    }

    rulename = l->string;
    rule = bindrule( l->string, frame->module );

#ifdef HAVE_PYTHON
    if (rule->python_function)
    {
        return call_python_function(rule, frame);
    }
#endif

    /* drop the rule name */
    l = list_pop_front( l );

    /* tack the rest of the expansion onto the front of the first argument */
    frame->args->list[0] = list_append( l, lol_get( frame->args, 0 ) );

    if ( DEBUG_COMPILE )
    {
        /* Try hard to indicate in which module the rule is going to execute */
        if ( rule->module != frame->module
             && rule->procedure != 0 && strcmp(rulename, rule->procedure->rulename) )
        {
            char buf[256] = "";
            strncat( buf, rule->module->name, sizeof(buf) - 1 );
            strncat( buf, rule->name, sizeof(buf) - 1 );
            debug_compile( 1, buf, frame);
        }
        else
        {
            debug_compile( 1, rulename, frame);
        }

        lol_print( frame->args );
        printf( "\n" );
    }
    
    if ( rule->procedure && rule->module != prev_module )
    {
        /* propagate current module to nested rule invocations */
        frame->module = rule->module;
        
        /* swap variables */
        exit_module( prev_module );
        enter_module( rule->module );
    }
        
    /* record current rule name in frame */
    if ( rule->procedure )
    {
        frame->rulename = rulename;
        /* and enter record profile info */
        if ( DEBUG_PROFILE )
            profile_enter( rule->procedure->rulename, prof );
    }

    /* Check traditional targets $(<) and sources $(>) */

    if( !rule->actions && !rule->procedure )
    {
        backtrace_line( frame->prev );
        printf( "rule %s unknown in module %s\n", rule->name, frame->module->name );
        backtrace( frame->prev );
        exit(1);
    }

    /* If this rule will be executed for updating the targets */
    /* then construct the action for make(). */

    if( rule->actions )
    {
        TARGETS *t;
        ACTION  *action;

        /* The action is associated with this instance of this rule */

        action = (ACTION *)malloc( sizeof( ACTION ) );
        memset( (char *)action, '\0', sizeof( *action ) );

        action->rule = rule;
        action->targets = targetlist( (TARGETS *)0, lol_get( frame->args, 0 ) );
        action->sources = targetlist( (TARGETS *)0, lol_get( frame->args, 1 ) );

        /* Append this action to the actions of each target */

        for( t = action->targets; t; t = t->next )
            t->target->actions = actionlist( t->target->actions, action );
    }

    /* Now recursively compile any parse tree associated with this rule */
    /* refer/free to ensure rule not freed during use */

    if( rule->procedure )
    {
        SETTINGS *local_args = collect_arguments( rule, frame );
        PARSE *parse = rule->procedure;
        parse_refer( parse );
        
        pushsettings( local_args );
        result = parse_evaluate( parse, frame );
        popsettings( local_args );
        freesettings( local_args );
        
        parse_free( parse );
    }

    if ( frame->module != prev_module )
    {
        exit_module( frame->module );
        enter_module( prev_module );
    }

    if ( DEBUG_PROFILE && rule->procedure )
        profile_exit( prof );

    if( DEBUG_COMPILE )
        debug_compile( -1, 0, frame);

    return result;
}
Beispiel #14
0
static LIST*
call_python_function(RULE* r, FRAME* frame)
{
    LIST* result = 0;
    PyObject* arguments = PyTuple_New(frame->args->count);
    int i ;
    PyObject* py_result;

    for(i = 0; i < frame->args->count; ++i)
    {
        PyObject* arg = PyList_New(0);
        LIST* l = lol_get( frame->args, i);

        for(; l; l = l->next)
        {
            PyObject* v = PyString_FromString(l->string);
            /* Steals reference to 'v' */
            PyList_Append(arg, v);            
        }
        /* Steals reference to 'arg' */
        PyTuple_SetItem(arguments, i, arg);
    }

    py_result = PyObject_CallObject(r->python_function, arguments);
    Py_DECREF(arguments);
    if (py_result != NULL) {
        
        if (PyList_Check(py_result)) {
            int size = PyList_Size(py_result);
            int i;
            for(i = 0; i < size; ++i)
            {
                PyObject* item = PyList_GetItem(py_result, i);
                if (PyString_Check(item))
                {
                    result = list_new(result, 
                                      newstr(PyString_AsString(item)));
                }
                else
                {
                    fprintf(stderr, "Non-string object returned by Python call\n");
                }
            }
        }
        else if (PyInstance_Check(py_result))
        {
            static char instance_name[1000];
            static char imported_method_name[1000];
            module_t* m;
            PyObject* method;
            PyObject* method_name = PyString_FromString("foo");
            RULE* r;

            fprintf(stderr, "Got instance!\n");

            snprintf(instance_name, 1000,
                     "pyinstance%d", python_instance_number);
            snprintf(imported_method_name, 1000,
                     "pyinstance%d.foo", python_instance_number);
            ++python_instance_number;
            
            m = bindmodule(instance_name);

            /* This is expected to get bound method. */
            method = PyObject_GetAttr(py_result, method_name);
            
            r = bindrule( imported_method_name, root_module() );

            r->python_function = method;

            result = list_new(0, newstr(instance_name));    

            Py_DECREF(method_name);
        }
        else if (py_result == Py_None)
        {
            result = L0;
        }
        else
        {
            fprintf(stderr, "Non-list object returned by Python call\n");
        }

        Py_DECREF(py_result);
    }
    else {
        PyErr_Print();
        fprintf(stderr,"Call failed\n");
    }
    
    return result;
}
Beispiel #15
0
void
load_builtins()
{
    bindrule( "Always" )->procedure =
    bindrule( "ALWAYS" )->procedure =
	parse_make( builtin_flags, P0, P0, P0, C0, C0, T_FLAG_TOUCHED );

    bindrule( "Depends" )->procedure =
    bindrule( "DEPENDS" )->procedure =
	parse_make( builtin_depends, P0, P0, P0, C0, C0, 0 );

    bindrule( "echo" )->procedure =
    bindrule( "Echo" )->procedure =
    bindrule( "ECHO" )->procedure =
	parse_make( builtin_echo, P0, P0, P0, C0, C0, 0 );

    bindrule( "exit" )->procedure =
    bindrule( "Exit" )->procedure =
    bindrule( "EXIT" )->procedure =
	parse_make( builtin_exit, P0, P0, P0, C0, C0, 0 );

    bindrule( "Glob" )->procedure =
    bindrule( "GLOB" )->procedure =
	parse_make( builtin_glob, P0, P0, P0, C0, C0, 0 );

    bindrule( "Includes" )->procedure =
    bindrule( "INCLUDES" )->procedure =
	parse_make( builtin_depends, P0, P0, P0, C0, C0, 1 );

    bindrule( "Leaves" )->procedure =
    bindrule( "LEAVES" )->procedure =
	parse_make( builtin_flags, P0, P0, P0, C0, C0, T_FLAG_LEAVES );

    bindrule( "Match" )->procedure =
    bindrule( "MATCH" )->procedure =
	parse_make( builtin_match, P0, P0, P0, C0, C0, 0 );

    bindrule( "ForceCare" )->procedure =
	parse_make( builtin_flags_forcecare, P0, P0, P0, C0, C0, T_FLAG_FORCECARE );

    bindrule( "NoCare" )->procedure =
    bindrule( "NOCARE" )->procedure =
	parse_make( builtin_flags_nocare, P0, P0, P0, C0, C0, T_FLAG_NOCARE );

    bindrule( "NOTIME" )->procedure =
    bindrule( "NotFile" )->procedure =
    bindrule( "NOTFILE" )->procedure =
	parse_make( builtin_flags, P0, P0, P0, C0, C0, T_FLAG_NOTFILE );

    bindrule( "NoUpdate" )->procedure =
    bindrule( "NOUPDATE" )->procedure =
	parse_make( builtin_flags, P0, P0, P0, C0, C0, T_FLAG_NOUPDATE );

#ifdef OPT_BUILTIN_SUBST_EXT
	bindrule( "Subst" )->procedure =
		parse_make( builtin_subst, P0, P0, P0, C0, C0, 0 );
	bindrule( "SubstLiteralize" )->procedure =
		parse_make( builtin_subst_literalize, P0, P0, P0, C0, C0, 0 );
#endif

    bindrule( "Temporary" )->procedure =
    bindrule( "TEMPORARY" )->procedure =
	parse_make( builtin_flags, P0, P0, P0, C0, C0, T_FLAG_TEMP );

#ifdef OPT_MULTIPASS_EXT
    bindrule( "QueueJamfile" )->procedure =
	parse_make( builtin_queuejamfile, P0, P0, P0, C0, C0, 0 );
#endif

#ifdef OPT_BUILTIN_MD5_EXT
    bindrule( "MD5" )->procedure =
	parse_make( builtin_md5, P0, P0, P0, C0, C0, 0 );
    bindrule( "MD5File" )->procedure =
	parse_make( builtin_md5file, P0, P0, P0, C0, C0, 0 );
#endif /* OPT_BUILTIN_MD5_EXT */
#ifdef OPT_BUILTIN_MATH_EXT
    bindrule( "Math" )->procedure =
	parse_make( builtin_math, P0, P0, P0, C0, C0, 0 );
#endif
#ifdef NT
#ifdef OPT_BUILTIN_W32_GETREG_EXT
	bindrule( "W32_GETREG" )->procedure =
		parse_make( builtin_w32_getreg, P0, P0, P0, C0, C0, 0 );
#endif
#ifdef OPT_BUILTIN_W32_GETREG64_EXT
	bindrule( "W32_GETREG64" )->procedure =
		parse_make( builtin_w32_getreg64, P0, P0, P0, C0, C0, 0 );
#endif
#ifdef OPT_BUILTIN_W32_SHORTNAME_EXT
	bindrule( "W32_SHORTNAME" )->procedure =
		parse_make( builtin_w32_shortname, P0, P0, P0, C0, C0, 0 );
#endif
#endif

#ifdef OPT_HEADER_CACHE_EXT
    bindrule( "UseDepCache" )->procedure =
 parse_make( builtin_usedepcache, P0, P0, P0, C0, C0, T_FLAG_USEDEPCACHE );
#endif

#ifdef OPT_BUILTIN_MD5CACHE_EXT
    bindrule( "UseFileCache" )->procedure =
 parse_make( builtin_usefilecache, P0, P0, P0, C0, C0, T_FLAG_USEFILECACHE );

    bindrule( "OptionalFileCache" )->procedure =
 parse_make( builtin_usefilecache, P0, P0, P0, C0, C0, T_FLAG_USEFILECACHE | T_FLAG_OPTIONALFILECACHE );

    bindrule( "UseCommandLine" )->procedure =
	parse_make( builtin_usecommandline, P0, P0, P0, C0, C0, T_FLAG_USECOMMANDLINE );

    bindrule( "ScanContents" )->procedure =
    bindrule( "SCANCONTENTS" )->procedure =
	parse_make( builtin_flags, P0, P0, P0, C0, C0, T_FLAG_SCANCONTENTS );
#endif

#ifdef OPT_BUILTIN_NEEDS_EXT
    bindrule( "MightNotUpdate" )->procedure =
    	parse_make( builtin_flags, P0, P0, P0, C0, C0, T_FLAG_MIGHTNOTUPDATE );

    bindrule( "Needs" )->procedure =
    bindrule( "NEEDS" )->procedure =
	parse_make( builtin_depends, P0, P0, P0, C0, C0, 2 );
#endif

#ifdef OPT_BUILTIN_LUA_SUPPORT_EXT
    bindrule( "LuaString" )->procedure =
	parse_make( builtin_luastring, P0, P0, P0, C0, C0, 0 );

    bindrule( "LuaFile" )->procedure =
	parse_make( builtin_luafile, P0, P0, P0, C0, C0, 0 );

    bindrule( "UseMD5Callback" )->procedure =
	parse_make( builtin_usemd5callback, P0, P0, P0, C0, C0, 0 );
#endif
#ifdef OPT_SERIAL_OUTPUT_EXT
    bindrule( "Shell" )->procedure =
	parse_make( builtin_shell, P0, P0, P0, C0, C0, 0 );
#endif

#ifdef OPT_BUILTIN_GROUPBYVAR_EXT
	bindrule( "GroupByVar" )->procedure =
		parse_make( builtin_groupbyvar, P0, P0, P0, C0, C0, 0 );
#endif

#ifdef OPT_BUILTIN_SPLIT_EXT
	bindrule( "Split" )->procedure =
		parse_make( builtin_split, P0, P0, P0, C0, C0, 0 );
#endif

	bindrule( "ExpandFileList" )->procedure =
		parse_make( builtin_expandfilelist, P0, P0, P0, C0, C0, 0 );
	bindrule( "ListSort" )->procedure =
		parse_make( builtin_listsort, P0, P0, P0, C0, C0, 0 );
}