mirror of
https://review.haiku-os.org/buildtools
synced 2024-11-23 07:18:49 +01:00
397 lines
8.0 KiB
C
397 lines
8.0 KiB
C
|
/*
|
|||
|
* Copyright 1993, 1995 Christopher Seiwald.
|
|||
|
*
|
|||
|
* This file is part of Jam - see jam.c for Copyright information.
|
|||
|
*/
|
|||
|
|
|||
|
/*
|
|||
|
* 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
|
|||
|
* copytarget() - make a new target with the old target's name
|
|||
|
* 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
|
|||
|
* targetchain() - append two TARGET chains
|
|||
|
* actionlist() - append to an ACTION chain
|
|||
|
* addsettings() - add a deferred "set" command to a target
|
|||
|
* copysettings() - copy a settings list for temp use
|
|||
|
* 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)
|
|||
|
* 06/21/02 (seiwald) - support for named parameters
|
|||
|
* 11/04/02 (seiwald) - const-ing for string literals
|
|||
|
* 12/03/02 (seiwald) - fix odd includes support by grafting them onto depends
|
|||
|
* 12/17/02 (seiwald) - new copysettings() to protect target-specific vars
|
|||
|
* 01/14/03 (seiwald) - fix includes fix with new internal includes TARGET
|
|||
|
*/
|
|||
|
|
|||
|
# include "jam.h"
|
|||
|
# include "lists.h"
|
|||
|
# include "parse.h"
|
|||
|
# include "variable.h"
|
|||
|
# include "rules.h"
|
|||
|
# include "newstr.h"
|
|||
|
# include "hash.h"
|
|||
|
|
|||
|
static struct hash *rulehash = 0;
|
|||
|
static struct hash *targethash = 0;
|
|||
|
|
|||
|
# ifdef OPT_RULE_PROFILING_EXT
|
|||
|
static RULE *profiling_rule_list = 0;
|
|||
|
# endif
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* bindrule() - return pointer to RULE, creating it if necessary
|
|||
|
*/
|
|||
|
|
|||
|
RULE *
|
|||
|
bindrule( const char *rulename )
|
|||
|
{
|
|||
|
RULE rule, *r = &rule;
|
|||
|
|
|||
|
if( !rulehash )
|
|||
|
rulehash = hashinit( sizeof( RULE ), "rules" );
|
|||
|
|
|||
|
r->name = rulename;
|
|||
|
|
|||
|
if( hashenter( rulehash, (HASHDATA **)&r ) )
|
|||
|
{
|
|||
|
r->name = newstr( rulename ); /* never freed */
|
|||
|
r->procedure = (PARSE *)0;
|
|||
|
r->actions = (char *)0;
|
|||
|
r->bindlist = L0;
|
|||
|
r->params = L0;
|
|||
|
r->flags = 0;
|
|||
|
|
|||
|
# ifdef OPT_RULE_PROFILING_EXT
|
|||
|
if ( DEBUG_PROFILE_RULES )
|
|||
|
{
|
|||
|
r->invocations = 0;
|
|||
|
r->invocation_time = 0;
|
|||
|
r->next_profiling_rule = profiling_rule_list;
|
|||
|
profiling_rule_list = r;
|
|||
|
}
|
|||
|
# endif
|
|||
|
}
|
|||
|
|
|||
|
return r;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* bindtarget() - return pointer to TARGET, creating it if necessary
|
|||
|
*/
|
|||
|
|
|||
|
TARGET *
|
|||
|
bindtarget( const char *targetname )
|
|||
|
{
|
|||
|
TARGET target, *t = ⌖
|
|||
|
|
|||
|
if( !targethash )
|
|||
|
targethash = hashinit( sizeof( TARGET ), "targets" );
|
|||
|
|
|||
|
t->name = targetname;
|
|||
|
|
|||
|
if( hashenter( targethash, (HASHDATA **)&t ) )
|
|||
|
{
|
|||
|
memset( (char *)t, '\0', sizeof( *t ) );
|
|||
|
t->name = newstr( targetname ); /* never freed */
|
|||
|
t->boundname = t->name; /* default for T_FLAG_NOTFILE */
|
|||
|
}
|
|||
|
|
|||
|
return t;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* 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( const 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;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* 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 setflag,
|
|||
|
const char *symbol,
|
|||
|
LIST *value )
|
|||
|
{
|
|||
|
SETTINGS *v;
|
|||
|
|
|||
|
/* Look for previous setting */
|
|||
|
|
|||
|
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 )
|
|||
|
{
|
|||
|
v = (SETTINGS *)malloc( sizeof( *v ) );
|
|||
|
v->symbol = newstr( symbol );
|
|||
|
v->value = value;
|
|||
|
v->next = head;
|
|||
|
head = v;
|
|||
|
}
|
|||
|
else switch( setflag )
|
|||
|
{
|
|||
|
case VAR_SET:
|
|||
|
/* Toss old, set new */
|
|||
|
list_free( v->value );
|
|||
|
v->value = value;
|
|||
|
break;
|
|||
|
|
|||
|
case VAR_APPEND:
|
|||
|
/* Append new to old */
|
|||
|
v->value = list_append( v->value, value );
|
|||
|
break;
|
|||
|
|
|||
|
case VAR_DEFAULT:
|
|||
|
/* Toss new, old already set */
|
|||
|
list_free( value );
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
/* Return (new) head of list. */
|
|||
|
|
|||
|
return head;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* copysettings() - copy a settings list for temp use
|
|||
|
*
|
|||
|
* When target-specific variables are pushed into place with pushsettings(),
|
|||
|
* any global variables with the same name are swapped onto the target's
|
|||
|
* SETTINGS chain. If that chain gets modified (by using the "on target"
|
|||
|
* syntax), popsettings() would wrongly swap those modified values back
|
|||
|
* as the new global values.
|
|||
|
*
|
|||
|
* copysettings() protects the target's SETTINGS chain by providing a
|
|||
|
* copy of the chain to pass to pushsettings() and popsettings(), so that
|
|||
|
* the target's original SETTINGS chain can be modified using the usual
|
|||
|
* "on target" syntax.
|
|||
|
*/
|
|||
|
|
|||
|
SETTINGS *
|
|||
|
copysettings( SETTINGS *from )
|
|||
|
{
|
|||
|
SETTINGS *head = 0, *v;
|
|||
|
|
|||
|
for( ; from; from = from->next )
|
|||
|
{
|
|||
|
SETTINGS *v = (SETTINGS *)malloc( sizeof( *v ) );
|
|||
|
v->symbol = copystr( from->symbol );
|
|||
|
v->value = list_copy( 0, from->value );
|
|||
|
v->next = head;
|
|||
|
head = v;
|
|||
|
}
|
|||
|
|
|||
|
return head;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* pushsettings() - set all target specific variables
|
|||
|
*/
|
|||
|
|
|||
|
void
|
|||
|
pushsettings( SETTINGS *v )
|
|||
|
{
|
|||
|
for( ; v; v = v->next )
|
|||
|
v->value = var_swap( v->symbol, v->value );
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* popsettings() - reset target specific variables to their pre-push values
|
|||
|
*/
|
|||
|
|
|||
|
void
|
|||
|
popsettings( SETTINGS *v )
|
|||
|
{
|
|||
|
pushsettings( v ); /* just swap again */
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* freesettings() - delete a settings list
|
|||
|
*/
|
|||
|
|
|||
|
void
|
|||
|
freesettings( SETTINGS *v )
|
|||
|
{
|
|||
|
while( v )
|
|||
|
{
|
|||
|
SETTINGS *n = v->next;
|
|||
|
|
|||
|
freestr( v->symbol );
|
|||
|
list_free( v->value );
|
|||
|
free( (char *)v );
|
|||
|
|
|||
|
v = n;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* donerules() - free RULE and TARGET tables
|
|||
|
*/
|
|||
|
|
|||
|
void
|
|||
|
donerules()
|
|||
|
{
|
|||
|
# ifdef OPT_RULE_PROFILING_EXT
|
|||
|
if ( DEBUG_PROFILE_RULES )
|
|||
|
{
|
|||
|
RULE *rule;
|
|||
|
|
|||
|
printf("# invoked total time (us) rule\n");
|
|||
|
printf("--------- --------------- "
|
|||
|
"------------------------------------\n");
|
|||
|
|
|||
|
for (rule = profiling_rule_list;
|
|||
|
rule;
|
|||
|
rule = rule->next_profiling_rule)
|
|||
|
{
|
|||
|
printf("%9d %15lld %s\n", rule->invocations,
|
|||
|
(long long)rule->invocation_time, rule->name);
|
|||
|
}
|
|||
|
}
|
|||
|
# endif
|
|||
|
|
|||
|
hashdone( rulehash );
|
|||
|
hashdone( targethash );
|
|||
|
}
|