source tree restructured a little (should i move *.[ch] to src/ ?)
[k8jam.git] / rules.c
blobba1115af1804e92990043820956c79e14aae7595
1 /*
2 * Copyright 1993, 1995 Christopher Seiwald.
4 * This file is part of Jam - see jam.c for Copyright information.
5 */
7 /*
8 * rules.c - access to RULEs, TARGETs, and ACTIONs
10 * External routines:
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
36 # include "jam.h"
37 # include "lists.h"
38 # include "parse.h"
39 # include "variable.h"
40 # include "rules.h"
41 # include "newstr.h"
42 # include "hash.h"
44 static struct hash *rulehash = 0;
45 static struct hash *targethash = 0;
49 * bindrule() - return pointer to RULE, creating it if necessary
52 RULE *
53 bindrule( const char *rulename )
55 RULE rule, *r = &rule;
57 if( !rulehash )
58 rulehash = hashinit( sizeof( RULE ), "rules" );
60 r->name = rulename;
62 if( hashenter( rulehash, (HASHDATA **)&r ) )
64 r->name = newstr( rulename ); /* never freed */
65 r->procedure = (PARSE *)0;
66 r->actions = (char *)0;
67 r->bindlist = L0;
68 r->params = L0;
69 r->flags = 0;
72 return r;
76 * bindtarget() - return pointer to TARGET, creating it if necessary
79 TARGET *
80 bindtarget( const char *targetname )
82 TARGET target, *t = ⌖
84 if( !targethash )
85 targethash = hashinit( sizeof( TARGET ), "targets" );
87 t->name = targetname;
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 */
96 return t;
100 * copytarget() - make a new target with the old target's name
102 * Not entered into hash table -- for internal nodes.
105 TARGET *
106 copytarget( const TARGET *ot )
108 TARGET *t;
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;
117 return t;
121 * touchtarget() - mark a target to simulate being new
124 void
125 touchtarget( const char *t )
127 bindtarget( t )->flags |= T_FLAG_TOUCHED;
131 * targetlist() - turn list of target names into a TARGET chain
133 * Inputs:
134 * chain existing TARGETS to append to
135 * targets list of target names
138 TARGETS *
139 targetlist(
140 TARGETS *chain,
141 LIST *targets )
143 for( ; targets; targets = list_next( targets ) )
144 chain = targetentry( chain, bindtarget( targets->string ) );
146 return chain;
150 * targetentry() - add a TARGET to a chain of TARGETS
152 * Inputs:
153 * chain exisitng TARGETS to append to
154 * target new target to append
157 TARGETS *
158 targetentry(
159 TARGETS *chain,
160 TARGET *target )
162 TARGETS *c;
164 c = (TARGETS *)malloc( sizeof( TARGETS ) );
165 c->target = target;
167 if( !chain ) chain = c;
168 else chain->tail->next = c;
169 chain->tail = c;
170 c->next = 0;
172 return chain;
176 * targetchain() - append two TARGET chains
178 * Inputs:
179 * chain exisitng TARGETS to append to
180 * target new target to append
183 TARGETS *
184 targetchain(
185 TARGETS *chain,
186 TARGETS *targets )
188 /*k8: TARGETS *c;*/
190 if( !targets )
191 return chain;
192 else if( !chain )
193 return targets;
195 chain->tail->next = targets;
196 chain->tail = targets->tail;
198 return chain;
202 * actionlist() - append to an ACTION chain
205 ACTIONS *
206 actionlist(
207 ACTIONS *chain,
208 ACTION *action )
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;
217 actions->next = 0;
219 return chain;
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.
231 SETTINGS *
232 addsettings(
233 SETTINGS *head,
234 int setflag,
235 const char *symbol,
236 LIST *value )
238 SETTINGS *v;
240 /* Look for previous setting */
242 for( v = head; v; v = v->next )
243 if( !strcmp( v->symbol, symbol ) )
244 break;
246 /* If not previously set, alloc a new. */
247 /* If appending, do so. */
248 /* Else free old and set new. */
250 if( !v )
252 v = (SETTINGS *)malloc( sizeof( *v ) );
253 v->symbol = newstr( symbol );
254 v->value = value;
255 v->next = head;
256 head = v;
258 else switch( setflag )
260 case VAR_SET:
261 /* Toss old, set new */
262 list_free( v->value );
263 v->value = value;
264 break;
266 case VAR_APPEND:
267 /* Append new to old */
268 v->value = list_append( v->value, value );
269 break;
271 case VAR_DEFAULT:
272 /* Toss new, old already set */
273 list_free( value );
274 break;
277 /* Return (new) head of list. */
279 return head;
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.
297 SETTINGS *
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 );
307 v->next = head;
308 head = v;
311 return head;
315 * pushsettings() - set all target specific variables
318 void
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
329 void
330 popsettings( SETTINGS *v )
332 pushsettings( v ); /* just swap again */
336 * freesettings() - delete a settings list
339 void
340 freesettings( SETTINGS *v )
342 while( v )
344 SETTINGS *n = v->next;
346 freestr( v->symbol );
347 list_free( v->value );
348 free( (char *)v );
350 v = n;
355 * donerules() - free RULE and TARGET tables
358 void
359 donerules()
361 hashdone( rulehash );
362 hashdone( targethash );