⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rules.c

📁 C++的一个好库。。。现在很流行
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright 1993, 1995 Christopher Seiwald.
 *
 * This file is part of Jam - see jam.c for Copyright information.
 */

# include "jam.h"
# include "lists.h"
# include "parse.h"
# include "variable.h"
# include "rules.h"
# include "newstr.h"
# include "hash.h"
# include "modules.h"
# include "search.h"
# include "lists.h"
# include "pathsys.h"
# include "timestamp.h"

/*  This file is ALSO:
 *  Copyright 2001-2004 David Abrahams.
 *  Distributed under the Boost Software License, Version 1.0.
 *  (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 */

/*
 * rules.c - access to RULEs, TARGETs, and ACTIONs
 *
 * External routines:
 *
 *    bindrule() - return pointer to RULE, creating it if necessary
 *    bindtarget() - return pointer to TARGET, creating it if necessary
 *    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
 *
 * 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;

typedef struct _located_target LOCATED_TARGET ;

struct _located_target {
    char* file_name;
    TARGET* target;
};
static struct hash *located_targets = 0;




/*
 * 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, *r = &rule;

    r->name = rulename;

    if ( hashenter( demand_rules( target_module ), (HASHDATA **)&r ) )
    {
        r->name = newstr( rulename );	/* never freed */
        r->procedure = (PARSE *)0;
        r->module = 0;
        r->actions = 0;
        r->arguments = 0;
        r->exported = 0;
        r->module = target_module;
#ifdef HAVE_PYTHON
        r->python_function = 0;
#endif
    }
    return r;
}

/*
 * define_rule() - return pointer to RULE, creating it if necessary in
 * target_module. Prepare it to accept a body or action originating in
 * src_module.
 */
static RULE *
define_rule( module_t *src_module, char *rulename, module_t *target_module )
{
    RULE *r = enter_rule( rulename, target_module );

    if ( r->module != src_module ) /* if the rule was imported from elsewhere, clear it now */
    {
        set_rule_body( r, 0, 0 ); 
        set_rule_actions( r, 0 );
        r->module = src_module; /* r will be executed in the source module */
    }

    return r;
}

void
rule_free( RULE* r )
{
    freestr( r->name );
    r->name = "";
    parse_free( r->procedure );
    r->procedure = 0;
	if ( r->arguments )
	    args_free( r->arguments );
    r->arguments = 0;
    if ( r->actions )
		actions_free( r->actions );
    r->actions = 0;
}

/*
 * bindtarget() - return pointer to TARGET, creating it if necessary
 */

TARGET *
bindtarget( const char *targetname )
{
	TARGET target, *t = ⌖

	if( !targethash )
	    targethash = hashinit( sizeof( TARGET ), "targets" );

    /* Perforce added const everywhere. No time to merge that change. */
	t->name = (char*)targetname;

	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 */
	}

	return t;
}


static void bind_explicitly_located_target(void* xtarget, void* data)
{
    TARGET* t = (TARGET*)xtarget;
    if (! (t->flags & T_FLAG_NOTFILE) )
    {
        /* Check if there's a setting for LOCATE */
        SETTINGS* s = t->settings;
        for(; s ; s = s->next)
        {            
            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. */
                t->boundname = search( t->name, &t->time, 0 );
                popsettings(t->settings);
                break;
            }
        }
    }
}

void bind_explicitly_located_targets()
{
    if (targethash)
        hashenumerate(targethash, bind_explicitly_located_target, (void*)0);
}

/* TODO: this is probably not a good idea to use functions in other modules like
  that. */
void call_bind_rule(char* target, char* boundname);

TARGET* search_for_target ( char * name, LIST* search_path )
{
    PATHNAME f[1];
    string buf[1];
    LOCATED_TARGET lt, *lta = <
    time_t time;
    int found = 0;
    TARGET* result;

    string_new( buf );

	path_parse( name, f );

    f->f_grist.ptr = 0;
    f->f_grist.len = 0;

    while( search_path )
    {
        f->f_root.ptr = search_path->string;
        f->f_root.len = strlen( search_path->string );

        string_truncate( buf, 0 );
        path_build( f, buf, 1 );

        lt.file_name = buf->value ;

        if (! located_targets )
            located_targets = hashinit( sizeof(LOCATED_TARGET),
                                        "located targets" );


        if ( hashcheck( located_targets, (HASHDATA **)&lta ) )
        {
            return lta->target;
        }

        timestamp( buf->value, &time );
        if (time)
        {
            found = 1;
            break;
        }

        search_path = list_next( search_path );
    }

    if ( ! found )
    {
        f->f_root.ptr = 0;
        f->f_root.len = 0;

        string_truncate( buf, 0 );
        path_build( f, buf, 1 );

        timestamp( buf->value, &time );        
    }

    result = bindtarget( name );
    result->boundname = newstr( buf->value );
    result->time = time;
    result->binding = time ? T_BIND_EXISTS : T_BIND_MISSING;

    call_bind_rule( result->name, result->boundname );
    
    string_free( buf );

    return result;

}

/*
 * 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 *)malloc( sizeof( *t ) );
	memset( (char *)t, '\0', sizeof( *t ) );
	t->name = copystr( ot->name );
	t->boundname = t->name;

	t->flags |= T_FLAG_NOTFILE | T_FLAG_INTERNAL;

	return t;
}

/*
 * touchtarget() - mark a target to simulate being new
 */

void
touchtarget( char *t )
{
	bindtarget( t )->flags |= T_FLAG_TOUCHED;
}

/*
 * 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 )
{
	for( ; targets; targets = list_next( targets ) )
	    chain = targetentry( chain, bindtarget( targets->string ) );

	return chain;
}

/*
 * targetentry() - add a TARGET to a chain of TARGETS
 *
 * Inputs:
 *	chain	exisitng TARGETS to append to
 *	target	new target to append
 */

TARGETS *
targetentry( 
	TARGETS	*chain,
	TARGET	*target )
{
	TARGETS *c;

	c = (TARGETS *)malloc( sizeof( TARGETS ) );
	c->target = target;

	if( !chain ) chain = c;
	else chain->tail->next = c;
	chain->tail = c;
	c->next = 0;

	return chain;
}

/*
 * targetchain() - append two TARGET chains
 *
 * Inputs:
 *	chain	exisitng TARGETS to append to
 *	target	new target to append
 */

TARGETS *
targetchain( 
	TARGETS	*chain,
	TARGETS	*targets )
{
	TARGETS *c;

	if( !targets )
	    return chain;
	else if( !chain )
	    return targets;

	chain->tail->next = targets;
	chain->tail = targets->tail;

	return chain;
}

/*
 * actionlist() - append to an ACTION chain
 */

ACTIONS *
actionlist(
	ACTIONS	*chain,
	ACTION	*action )
{
	ACTIONS *actions = (ACTIONS *)malloc( sizeof( ACTIONS ) );

	actions->action = action;

	if( !chain ) chain = actions;
	else chain->tail->next = actions;
	chain->tail = actions;
	actions->next = 0;

	return chain;
}

static SETTINGS* settings_freelist;

/*
 * addsettings() - add a deferred "set" command to a target
 *
 * Adds a variable setting (varname=list) onto a chain of settings
 * for a particular target.  Replaces the previous previous value,
 * if any, unless 'append' says to append the new list onto the old.
 * Returns the head of the chain of settings.
 */

SETTINGS *
addsettings(
	SETTINGS *head,
	int	append,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -