📄 rules.c
字号:
/* * 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;}voidrule_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 **)<a ) ) { 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 *)BJAM_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 */voidtouchtarget( 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 *)BJAM_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 *)BJAM_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. * '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. */SETTINGS *addsettings( SETTINGS *head, int flag, char *symbol, LIST *value )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -