2 * Copyright 1993, 1995 Christopher Seiwald.
4 * This file is part of Jam - see jam.c for Copyright information.
7 * rules.c - access to RULEs, TARGETs, and ACTIONs
11 * bindrule() - return pointer to RULE, creating it if necessary
12 * bindtarget() - return pointer to TARGET, creating it if necessary
13 * copytarget() - make a new target with the old target's name
14 * touchtarget() - mark a target to simulate being new
15 * targetlist() - turn list of target names into a TARGET chain
16 * targetentry() - add a TARGET to a chain of TARGETS
17 * targetchain() - append two TARGET chains
18 * actionlist() - append to an ACTION chain
19 * addsettings() - add a deferred "set" command to a target
20 * copysettings() - copy a settings list for temp use
21 * pushsettings() - set all target specific variables
22 * popsettings() - reset target specific variables to their pre-push values
23 * freesettings() - delete a settings list
24 * donerules() - free RULE and TARGET tables
26 * 04/12/94 (seiwald) - actionlist() now just appends a single action.
27 * 08/23/94 (seiwald) - Support for '+=' (append to variable)
28 * 06/21/02 (seiwald) - support for named parameters
29 * 11/04/02 (seiwald) - const-ing for string literals
30 * 12/03/02 (seiwald) - fix odd includes support by grafting them onto depends
31 * 12/17/02 (seiwald) - new copysettings() to protect target-specific vars
32 * 01/14/03 (seiwald) - fix includes fix with new internal includes TARGET
43 static struct hash
*rulehash
= NULL
;
44 static struct hash
*targethash
= NULL
;
48 * haverule() - return !0 if rule exists
50 int haverule (const char *rulename
) {
51 RULE rule
, *r
= &rule
;
53 if (!rulehash
) return 0;
55 return hashcheck(rulehash
, (HASHDATA
**)&r
) ? 1 : 0; /* just in case */
60 * bindrule() - return pointer to RULE, creating it if necessary
62 RULE
*bindrule (const char *rulename
) {
63 RULE rule
, *r
= &rule
;
65 if (!rulehash
) rulehash
= hashinit(sizeof(RULE
), "rules");
67 if (hashenter(rulehash
, (HASHDATA
**)&r
)) {
68 r
->name
= newstr(rulename
); /* never freed */
69 r
->procedure
= (PARSE
*)0;
70 r
->actions
= (char *)0;
80 * bindtarget() - return pointer to TARGET, creating it if necessary
82 TARGET
*bindtarget (const char *targetname
) {
83 TARGET target
, *t
= &target
;
85 if (!targethash
) targethash
= hashinit(sizeof(TARGET
), "targets");
87 if (hashenter(targethash
, (HASHDATA
**)&t
)) {
88 memset((char *)t
, '\0', sizeof(*t
));
89 t
->name
= newstr(targetname
); /* never freed */
90 t
->boundname
= t
->name
; /* default for T_FLAG_NOTFILE */
97 * copytarget() - make a new target with the old target's name
99 * Not entered into hash table -- for internal nodes.
101 TARGET
*copytarget (const TARGET
*ot
) {
102 TARGET
*t
= (TARGET
*)malloc(sizeof(*t
));
103 memset((char *)t
, '\0', sizeof(*t
));
104 t
->name
= copystr(ot
->name
);
105 t
->boundname
= t
->name
;
106 t
->flags
|= T_FLAG_NOTFILE
|T_FLAG_INTERNAL
;
112 * touchtarget() - mark a target to simulate being new
114 void touchtarget (const char *t
) {
115 bindtarget(t
)->flags
|= T_FLAG_TOUCHED
;
120 * targetlist() - turn list of target names into a TARGET chain
123 * chain existing TARGETS to append to
124 * targets list of target names
126 TARGETS
*targetlist (TARGETS
*chain
, LIST
*targets
) {
127 for (; targets
; targets
= list_next(targets
)) chain
= targetentry(chain
, bindtarget(targets
->string
));
133 * targetentry() - add a TARGET to a chain of TARGETS
136 * chain exisitng TARGETS to append to
137 * target new target to append
139 TARGETS
*targetentry (TARGETS
*chain
, TARGET
*target
) {
140 TARGETS
*c
= (TARGETS
*)malloc(sizeof(TARGETS
));
142 if (!chain
) chain
= c
; else chain
->tail
->next
= c
;
150 * targetchain() - append two TARGET chains
153 * chain exisitng TARGETS to append to
154 * target new target to append
156 TARGETS
*targetchain (TARGETS
*chain
, TARGETS
*targets
) {
157 if (!targets
) return chain
;
158 if (!chain
) return targets
;
159 chain
->tail
->next
= targets
;
160 chain
->tail
= targets
->tail
;
166 * actionlist() - append to an ACTION chain
168 ACTIONS
*actionlist (ACTIONS
*chain
, ACTION
*action
) {
169 ACTIONS
*actions
= (ACTIONS
*)malloc(sizeof(ACTIONS
));
170 actions
->action
= action
;
171 if (!chain
) chain
= actions
; else chain
->tail
->next
= actions
;
172 chain
->tail
= actions
;
179 * addsettings() - add a deferred "set" command to a target
181 * Adds a variable setting (varname=list) onto a chain of settings
182 * for a particular target. Replaces the previous previous value,
183 * if any, unless 'append' says to append the new list onto the old.
184 * Returns the head of the chain of settings.
186 SETTINGS
*addsettings (SETTINGS
*head
, int setflag
, const char *symbol
, LIST
*value
) {
188 /* look for previous setting */
189 for (v
= head
; v
; v
= v
->next
) if (!strcmp(v
->symbol
, symbol
)) break;
190 /* if not previously set, alloc a new */
191 /* if appending, do so */
192 /* else free old and set new */
194 v
= (SETTINGS
*)malloc(sizeof(*v
));
195 v
->symbol
= newstr(symbol
);
202 /* toss old, set new */
207 /* append new to old */
208 v
->value
= list_append(v
->value
, value
);
211 v
->value
= list_removeall(v
->value
, value
);
215 /* toss new, old already set */
220 /* return (new) head of list */
226 * copysettings() - copy a settings list for temp use
228 * When target-specific variables are pushed into place with pushsettings(),
229 * any global variables with the same name are swapped onto the target's
230 * SETTINGS chain. If that chain gets modified (by using the "on target"
231 * syntax), popsettings() would wrongly swap those modified values back
232 * as the new global values.
234 * copysettings() protects the target's SETTINGS chain by providing a
235 * copy of the chain to pass to pushsettings() and popsettings(), so that
236 * the target's original SETTINGS chain can be modified using the usual
237 * "on target" syntax.
239 SETTINGS
*copysettings (SETTINGS
*from
) {
242 for (; from
; from
= from
->next
) {
243 SETTINGS
*v
= (SETTINGS
*)malloc(sizeof(*v
));
244 v
->symbol
= copystr(from
->symbol
);
245 v
->value
= list_copy(0, from
->value
);
254 * pushsettings() - set all target specific variables
256 void pushsettings (SETTINGS
*v
) {
257 for (; v
; v
= v
->next
) v
->value
= var_swap(v
->symbol
, v
->value
);
262 * popsettings() - reset target specific variables to their pre-push values
264 void popsettings (SETTINGS
*v
) {
265 pushsettings(v
); /* just swap again */
270 * freesettings() - delete a settings list
272 void freesettings (SETTINGS
*v
) {
274 SETTINGS
*n
= v
->next
;
285 * donerules() - free RULE and TARGET tables
287 void donerules (void) {
289 hashdone(targethash
);