first in 2.5.10 series
[k8jam.git] / src / variable.c
blob09c5d4eca6c9f1cf7c88fc27660de339181b26c5
1 /*
2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
4 * This file is part of Jam - see jam.c for Copyright information.
5 */
7 /*
8 * variable.c - handle jam multi-element variables
10 * External routines:
12 * var_defines() - load a bunch of variable=value settings
13 * var_string() - expand a string with variables in it
14 * var_get() - get value of a user defined symbol
15 * var_set() - set a variable in jam's user defined symbol table
16 * var_swap() - swap a variable's value with the given one
17 * var_done() - free variable tables
19 * Internal routines:
21 * var_enter() - make new var symbol table entry, returning var ptr
22 * var_dump() - dump a variable to stdout
24 * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
25 * 08/23/94 (seiwald) - Support for '+=' (append to variable)
26 * 01/22/95 (seiwald) - split environment variables at blanks or :'s
27 * 05/10/95 (seiwald) - split path variables at SPLITPATH (not :)
28 * 09/11/00 (seiwald) - defunct var_list() removed
29 * 10/22/02 (seiwald) - list_new() now does its own newstr()/copystr()
30 * 11/04/02 (seiwald) - const-ing for string literals
33 # include "jam.h"
34 # include "lists.h"
35 # include "parse.h"
36 # include "variable.h"
37 # include "expand.h"
38 # include "hash.h"
39 # include "newstr.h"
41 static struct hash *varhash = 0;
44 * VARIABLE - a user defined multi-value variable
47 typedef struct _variable VARIABLE;
49 struct _variable {
50 const char *symbol;
51 LIST *value;
55 static VARIABLE *var_enter (const char *symbol);
56 static void var_dump (const char *symbol, LIST *value, const char *what);
60 * var_defines() - load a bunch of variable=value settings
62 * If variable name ends in PATH, split value at :'s.
63 * Otherwise, split at blanks.
65 void var_defines (const char **e) {
66 for (; *e; e++) {
67 const char *val;
68 /* Just say "no": windows defines this in the env, */
69 /* but we don't want it to override our notion of OS. */
70 if (!strcmp(*e, "OS=Windows_NT")) continue;
71 /* Just say "no": on Unix, variables can contain function
72 * definitions. their value begins with "()"
74 if ((val = strchr(*e, '=')) && val[1] == '(' && val[2] == ')') continue;
75 # ifdef OS_MAC
76 /* On the mac (MPW), the var=val is actually var\0val */
77 /* Think different. */
78 if ((val = strchr(*e, '=')) || (val = *e + strlen(*e))) {
79 # else
80 if ((val = strchr(*e, '='))) {
81 # endif
82 LIST *l = L0;
83 const char *pp, *p;
84 # ifdef OS_MAC
85 char split = ',';
86 # else
87 char split = ' ';
88 # endif
89 char buf[MAXSYM];
90 /* Split *PATH at :'s, not spaces */
91 if (val-4 >= *e) {
92 if (!strncmp(val - 4, "PATH", 4) || !strncmp(val - 4, "Path", 4) || !strncmp(val - 4, "path", 4))
93 split = SPLITPATH;
95 /* Do the split */
96 for (pp = val+1; (p = strchr(pp, split)); pp = p+1) {
97 int len = p-pp;
99 if (len >= sizeof(buf)) len = sizeof(buf)-1;
100 strncpy(buf, pp, len);
101 buf[len] = '\0';
102 l = list_new(l, buf, 0);
104 l = list_new(l, pp, 0);
105 /* Get name */
106 strncpy(buf, *e, val-*e);
107 buf[val-*e] = '\0';
108 var_set(buf, l, VAR_SET);
115 * var_string() - expand a string with variables in it
117 * Copies in to out; doesn't modify targets & sources.
119 int var_string (const char *in, char *out, int outsize, LOL *lol) {
120 char *out0 = out;
121 char *oute = out+outsize-1;
123 while (*in) {
124 char *lastword;
125 int dollar = 0;
126 /* Copy white space */
127 while (isspace(*in)) {
128 if (out >= oute) return -1;
129 *out++ = *in++;
131 lastword = out;
132 /* Copy non-white space, watching for variables */
133 while (*in && !isspace(*in)) {
134 if (out >= oute) return -1;
135 if (in[0] == '$' && in[1] == '(') dollar++;
136 *out++ = *in++;
138 /* If a variable encountered, expand it and and embed the */
139 /* space-separated members of the list in the output. */
140 if (dollar) {
141 LIST *l = var_expand(L0, lastword, out, lol, 0);
142 out = lastword;
143 while (l) {
144 int so = strlen(l->string);
145 if (out+so >= oute) return -1;
146 strcpy(out, l->string);
147 out += so;
148 /* Separate with space */
149 if ((l = list_next(l)))
150 *out++ = ' ';
152 list_free(l);
155 if (out >= oute) return -1;
156 *out++ = '\0';
157 return out - out0;
162 * var_get() - get value of a user defined symbol
164 * Returns NULL if symbol unset.
166 LIST *var_get (const char *symbol) {
167 VARIABLE var, *v = &var;
169 v->symbol = symbol;
170 if (varhash && hashcheck(varhash, (HASHDATA **)&v)) {
171 if (DEBUG_VARGET) var_dump(v->symbol, v->value, "get");
172 return v->value;
174 return 0;
179 * var_set() - set a variable in jam's user defined symbol table
181 * 'flag' controls the relationship between new and old values of
182 * the variable: SET replaces the old with the new; APPEND appends
183 * the new to the old; DEFAULT only uses the new if the variable
184 * was previously unset.
186 * Copies symbol. Takes ownership of value.
188 void var_set (const char *symbol, LIST *value, int flag) {
189 VARIABLE *v = var_enter(symbol);
191 if (DEBUG_VARSET) var_dump(symbol, value, "set");
192 switch(flag) {
193 case VAR_SET:
194 /* Replace value */
195 list_free(v->value);
196 v->value = value;
197 break;
198 case VAR_APPEND:
199 /* Append value */
200 v->value = list_append(v->value, value);
201 break;
202 case VAR_REMOVE:
203 /* Remove all values */
204 v->value = list_removeall(v->value, value);
205 list_free(value);
206 break;
207 case VAR_DEFAULT:
208 /* Set only if unset */
209 if (!v->value) v->value = value; else list_free(value);
210 break;
216 * var_swap() - swap a variable's value with the given one
218 LIST *var_swap (const char *symbol, LIST *value) {
219 VARIABLE *v = var_enter(symbol);
220 LIST *oldvalue = v->value;
222 if (DEBUG_VARSET) var_dump(symbol, value, "set");
223 v->value = value;
224 return oldvalue;
229 * var_enter() - make new var symbol table entry, returning var ptr
231 static VARIABLE *var_enter (const char *symbol) {
232 VARIABLE var, *v = &var;
234 if (!varhash) varhash = hashinit(sizeof(VARIABLE), "variables");
235 v->symbol = symbol;
236 v->value = 0;
237 if (hashenter(varhash, (HASHDATA **)&v)) v->symbol = newstr(symbol); /* never freed */
238 return v;
243 * var_dump() - dump a variable to stdout
245 static void var_dump (const char *symbol, LIST *value, const char *what) {
246 printf("%s %s = ", what, symbol);
247 list_print(value);
248 printf("\n");
253 * var_done() - free variable tables
255 void var_done (void) {
256 hashdone(varhash);