2 * Copyright 1993, 1995 Christopher Seiwald.
4 * This file is part of Jam - see jam.c for Copyright information.
8 * rules.c - access to RULEs, TARGETs, and ACTIONs
12 * bindrule() - return pointer to RULE, creating it if necessary
13 * bindtarget() - return pointer to TARGET, creating it if necessary
14 * copytarget() - make a new target with the old target's name
15 * touchtarget() - mark a target to simulate being new
16 * targetlist() - turn list of target names into a TARGET chain
17 * targetentry() - add a TARGET to a chain of TARGETS
18 * targetchain() - append two TARGET chains
19 * actionlist() - append to an ACTION chain
20 * addsettings() - add a deferred "set" command to a target
21 * copysettings() - copy a settings list for temp use
22 * pushsettings() - set all target specific variables
23 * popsettings() - reset target specific variables to their pre-push values
24 * freesettings() - delete a settings list
25 * donerules() - free RULE and TARGET tables
27 * 04/12/94 (seiwald) - actionlist() now just appends a single action.
28 * 08/23/94 (seiwald) - Support for '+=' (append to variable)
29 * 06/21/02 (seiwald) - support for named parameters
30 * 11/04/02 (seiwald) - const-ing for string literals
31 * 12/03/02 (seiwald) - fix odd includes support by grafting them onto depends
32 * 12/17/02 (seiwald) - new copysettings() to protect target-specific vars
33 * 01/14/03 (seiwald) - fix includes fix with new internal includes TARGET
39 # include "variable.h"
44 static struct hash
*rulehash
= 0;
45 static struct hash
*targethash
= 0;
49 * bindrule() - return pointer to RULE, creating it if necessary
53 bindrule( const char *rulename
)
55 RULE rule
, *r
= &rule
;
58 rulehash
= hashinit( sizeof( RULE
), "rules" );
62 if( hashenter( rulehash
, (HASHDATA
**)&r
) )
64 r
->name
= newstr( rulename
); /* never freed */
65 r
->procedure
= (PARSE
*)0;
66 r
->actions
= (char *)0;
76 * bindtarget() - return pointer to TARGET, creating it if necessary
80 bindtarget( const char *targetname
)
82 TARGET target
, *t
= &target
;
85 targethash
= hashinit( sizeof( TARGET
), "targets" );
89 if( hashenter( targethash
, (HASHDATA
**)&t
) )
91 memset( (char *)t
, '\0', sizeof( *t
) );
92 t
->name
= newstr( targetname
); /* never freed */
93 t
->boundname
= t
->name
; /* default for T_FLAG_NOTFILE */
100 * copytarget() - make a new target with the old target's name
102 * Not entered into hash table -- for internal nodes.
106 copytarget( const TARGET
*ot
)
110 t
= (TARGET
*)malloc( sizeof( *t
) );
111 memset( (char *)t
, '\0', sizeof( *t
) );
112 t
->name
= copystr( ot
->name
);
113 t
->boundname
= t
->name
;
115 t
->flags
|= T_FLAG_NOTFILE
| T_FLAG_INTERNAL
;
121 * touchtarget() - mark a target to simulate being new
125 touchtarget( const char *t
)
127 bindtarget( t
)->flags
|= T_FLAG_TOUCHED
;
131 * targetlist() - turn list of target names into a TARGET chain
134 * chain existing TARGETS to append to
135 * targets list of target names
143 for( ; targets
; targets
= list_next( targets
) )
144 chain
= targetentry( chain
, bindtarget( targets
->string
) );
150 * targetentry() - add a TARGET to a chain of TARGETS
153 * chain exisitng TARGETS to append to
154 * target new target to append
164 c
= (TARGETS
*)malloc( sizeof( TARGETS
) );
167 if( !chain
) chain
= c
;
168 else chain
->tail
->next
= c
;
176 * targetchain() - append two TARGET chains
179 * chain exisitng TARGETS to append to
180 * target new target to append
195 chain
->tail
->next
= targets
;
196 chain
->tail
= targets
->tail
;
202 * actionlist() - append to an ACTION chain
210 ACTIONS
*actions
= (ACTIONS
*)malloc( sizeof( ACTIONS
) );
212 actions
->action
= action
;
214 if( !chain
) chain
= actions
;
215 else chain
->tail
->next
= actions
;
216 chain
->tail
= actions
;
223 * addsettings() - add a deferred "set" command to a target
225 * Adds a variable setting (varname=list) onto a chain of settings
226 * for a particular target. Replaces the previous previous value,
227 * if any, unless 'append' says to append the new list onto the old.
228 * Returns the head of the chain of settings.
240 /* Look for previous setting */
242 for( v
= head
; v
; v
= v
->next
)
243 if( !strcmp( v
->symbol
, symbol
) )
246 /* If not previously set, alloc a new. */
247 /* If appending, do so. */
248 /* Else free old and set new. */
252 v
= (SETTINGS
*)malloc( sizeof( *v
) );
253 v
->symbol
= newstr( symbol
);
258 else switch( setflag
)
261 /* Toss old, set new */
262 list_free( v
->value
);
267 /* Append new to old */
268 v
->value
= list_append( v
->value
, value
);
272 /* Toss new, old already set */
277 /* Return (new) head of list. */
283 * copysettings() - copy a settings list for temp use
285 * When target-specific variables are pushed into place with pushsettings(),
286 * any global variables with the same name are swapped onto the target's
287 * SETTINGS chain. If that chain gets modified (by using the "on target"
288 * syntax), popsettings() would wrongly swap those modified values back
289 * as the new global values.
291 * copysettings() protects the target's SETTINGS chain by providing a
292 * copy of the chain to pass to pushsettings() and popsettings(), so that
293 * the target's original SETTINGS chain can be modified using the usual
294 * "on target" syntax.
298 copysettings( SETTINGS
*from
)
300 SETTINGS
*head
= 0 /*k8:, *v*/;
302 for( ; from
; from
= from
->next
)
304 SETTINGS
*v
= (SETTINGS
*)malloc( sizeof( *v
) );
305 v
->symbol
= copystr( from
->symbol
);
306 v
->value
= list_copy( 0, from
->value
);
315 * pushsettings() - set all target specific variables
319 pushsettings( SETTINGS
*v
)
321 for( ; v
; v
= v
->next
)
322 v
->value
= var_swap( v
->symbol
, v
->value
);
326 * popsettings() - reset target specific variables to their pre-push values
330 popsettings( SETTINGS
*v
)
332 pushsettings( v
); /* just swap again */
336 * freesettings() - delete a settings list
340 freesettings( SETTINGS
*v
)
344 SETTINGS
*n
= v
->next
;
346 freestr( v
->symbol
);
347 list_free( v
->value
);
355 * donerules() - free RULE and TARGET tables
361 hashdone( rulehash
);
362 hashdone( targethash
);