string file and functions renamed
[k8jam.git] / rules.c
blob7d054ae03d2756aa83fe35ed806d88af05b9f067
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
51 RULE *bindrule (const char *rulename) {
52 RULE rule, *r = &rule;
54 if (!rulehash) rulehash = hashinit(sizeof(RULE), "rules");
55 r->name = rulename;
56 if (hashenter(rulehash, (HASHDATA **)&r)) {
57 r->name = newstr(rulename); /* never freed */
58 r->procedure = (PARSE *)0;
59 r->actions = (char *)0;
60 r->bindlist = L0;
61 r->params = L0;
62 r->flags = 0;
64 return r;
69 * bindtarget() - return pointer to TARGET, creating it if necessary
71 TARGET *bindtarget (const char *targetname) {
72 TARGET target, *t = ⌖
74 if (!targethash) targethash = hashinit(sizeof(TARGET), "targets");
75 t->name = targetname;
76 if (hashenter(targethash, (HASHDATA **)&t)) {
77 memset((char *)t, '\0', sizeof(*t));
78 t->name = newstr(targetname); /* never freed */
79 t->boundname = t->name; /* default for T_FLAG_NOTFILE */
81 return t;
86 * copytarget() - make a new target with the old target's name
88 * Not entered into hash table -- for internal nodes.
90 TARGET *copytarget (const TARGET *ot) {
91 TARGET *t;
93 t = (TARGET *)malloc(sizeof(*t));
94 memset((char *)t, '\0', sizeof(*t));
95 t->name = copystr(ot->name);
96 t->boundname = t->name;
97 t->flags |= T_FLAG_NOTFILE | T_FLAG_INTERNAL;
98 return t;
103 * touchtarget() - mark a target to simulate being new
105 void touchtarget (const char *t) {
106 bindtarget(t)->flags |= T_FLAG_TOUCHED;
111 * targetlist() - turn list of target names into a TARGET chain
113 * Inputs:
114 * chain existing TARGETS to append to
115 * targets list of target names
117 TARGETS *targetlist (TARGETS *chain, LIST *targets) {
118 for (; targets; targets = list_next(targets)) chain = targetentry(chain, bindtarget(targets->string));
119 return chain;
124 * targetentry() - add a TARGET to a chain of TARGETS
126 * Inputs:
127 * chain exisitng TARGETS to append to
128 * target new target to append
130 TARGETS *targetentry (TARGETS *chain, TARGET *target) {
131 TARGETS *c;
133 c = (TARGETS *)malloc(sizeof(TARGETS));
134 c->target = target;
135 if (!chain) chain = c; else chain->tail->next = c;
136 chain->tail = c;
137 c->next = 0;
138 return chain;
143 * targetchain() - append two TARGET chains
145 * Inputs:
146 * chain exisitng TARGETS to append to
147 * target new target to append
149 TARGETS *targetchain (TARGETS *chain, TARGETS *targets) {
150 if (!targets) return chain;
151 else if (!chain) return targets;
152 chain->tail->next = targets;
153 chain->tail = targets->tail;
154 return chain;
159 * actionlist() - append to an ACTION chain
161 ACTIONS *actionlist (ACTIONS *chain, ACTION *action) {
162 ACTIONS *actions = (ACTIONS *)malloc(sizeof(ACTIONS));
164 actions->action = action;
165 if (!chain) chain = actions; else chain->tail->next = actions;
166 chain->tail = actions;
167 actions->next = 0;
168 return chain;
173 * addsettings() - add a deferred "set" command to a target
175 * Adds a variable setting (varname=list) onto a chain of settings
176 * for a particular target. Replaces the previous previous value,
177 * if any, unless 'append' says to append the new list onto the old.
178 * Returns the head of the chain of settings.
180 SETTINGS *addsettings (SETTINGS *head, int setflag, const char *symbol, LIST *value) {
181 SETTINGS *v;
183 /* Look for previous setting */
184 for (v = head; v; v = v->next) {
185 if (!strcmp(v->symbol, symbol)) break;
187 /* If not previously set, alloc a new. */
188 /* If appending, do so. */
189 /* Else free old and set new. */
190 if (!v) {
191 v = (SETTINGS *)malloc(sizeof(*v));
192 v->symbol = newstr(symbol);
193 v->value = value;
194 v->next = head;
195 head = v;
196 } else {
197 switch (setflag) {
198 case VAR_SET:
199 /* Toss old, set new */
200 list_free(v->value);
201 v->value = value;
202 break;
203 case VAR_APPEND:
204 /* Append new to old */
205 v->value = list_append(v->value, value);
206 break;
207 case VAR_DEFAULT:
208 /* Toss new, old already set */
209 list_free(value);
210 break;
213 /* Return (new) head of list. */
214 return head;
219 * copysettings() - copy a settings list for temp use
221 * When target-specific variables are pushed into place with pushsettings(),
222 * any global variables with the same name are swapped onto the target's
223 * SETTINGS chain. If that chain gets modified (by using the "on target"
224 * syntax), popsettings() would wrongly swap those modified values back
225 * as the new global values.
227 * copysettings() protects the target's SETTINGS chain by providing a
228 * copy of the chain to pass to pushsettings() and popsettings(), so that
229 * the target's original SETTINGS chain can be modified using the usual
230 * "on target" syntax.
232 SETTINGS *copysettings (SETTINGS *from) {
233 SETTINGS *head = 0;
235 for (; from; from = from->next) {
236 SETTINGS *v = (SETTINGS *)malloc(sizeof(*v));
237 v->symbol = copystr(from->symbol);
238 v->value = list_copy(0, from->value);
239 v->next = head;
240 head = v;
242 return head;
247 * pushsettings() - set all target specific variables
249 void pushsettings (SETTINGS *v) {
250 for (; v; v = v->next) v->value = var_swap(v->symbol, v->value);
255 * popsettings() - reset target specific variables to their pre-push values
257 void popsettings (SETTINGS *v) {
258 pushsettings(v); /* just swap again */
263 * freesettings() - delete a settings list
265 void freesettings (SETTINGS *v) {
266 while (v) {
267 SETTINGS *n = v->next;
269 freestr(v->symbol);
270 list_free(v->value);
271 free((char *)v);
272 v = n;
278 * donerules() - free RULE and TARGET tables
280 void donerules (void) {
281 hashdone(rulehash);
282 hashdone(targethash);