/* * 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; /* * 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; } 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 ) { 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; 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() { hashdone( rulehash ); hashdone( targethash ); }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#6 | 4110 | Craig Mcpheeters | Some of my changes from work. | ||
#5 | 3183 | Craig Mcpheeters | Integration of my jam mainline branch into my work branch. | ||
#4 | 1484 | Craig Mcpheeters |
Integration from my mainline into my branch. Incorporation of the W32_GetReg stuff from Matt to set MSVCNT. Cool |
||
#3 | 1188 | Craig Mcpheeters |
The latest updates from my A|W work copy. Added a -d11 debug mode, which outputs information on fate changes Create jam variables to show job (-jn) information, such as the number of jobs requested, whether or not there is more than one job, and a list of the job slot numbers. These can be used in a variety of ways in supporting multi-job builds Added jobs slot expansion to the action blocks, the sequence !! is replaced by the job slot the action is running in. Modified the special shell handling to include unix. It used to be that on Unix, you could create an action block which exceeded the size that execvp() could handle (perhaps only when the DynamicCommandSize option is enabled.) On NT, all non-default shells are invoked through a intermediate file. This modification does the same for unix shells. Improved the -d+10 debug level, the dependency graph. It now shows the flags on the node as well (NOUPDATE, NOTFILE, etc.) Only issue the '...skipped' messages for nodes which would have been built |
||
#2 | 785 | Craig Mcpheeters |
Integration from //guest/craig_mcpheeters/jam/src/... This work area now contains both the Alias|Wavefront changes, and the latest integrations from the mainline. There are some changes in this area which shouldn't be merged back into the mainline. As I merge this branch back into my jam/src/... branch, I'll leave out a few of the changes. |
||
#1 | 777 | Craig Mcpheeters |
Branch of my jam/src/... area. This new area establishes the integration base for the copy of Jam which has all the changes. |
||
//guest/craig_mcpheeters/jam/src/rules.c | |||||
#2 | 617 | Craig Mcpheeters | Integration from mainline as of @3 | ||
#1 | 616 | Craig Mcpheeters | Integration from Jam mainline, as of @2 |