option.c: fixed warnings
[k8jam.git] / src / variable.c
blobce78bc997cd4ac3b6319bb1fbf7f05402d9431f1
1 /*
2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
3 * This file is part of Jam - see jam.c for Copyright information.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License ONLY.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 * variable.c - handle jam multi-element variables
20 * External routines:
22 * var_defines() - load a bunch of variable=value settings
23 * var_string() - expand a string with variables in it
24 * var_get() - get value of a user defined symbol
25 * var_set() - set a variable in jam's user defined symbol table
26 * var_swap() - swap a variable's value with the given one
27 * var_done() - free variable tables
29 * Internal routines:
31 * var_enter() - make new var symbol table entry, returning var ptr
32 * var_dump() - dump a variable to stdout
34 #include "jam.h"
35 #include "lists.h"
36 #include "parse.h"
37 #include "variable.h"
38 #include "expand.h"
39 #include "hash.h"
40 #include "newstr.h"
41 #include "matchglob.h"
42 #include "dstrings.h"
45 static struct hash *varhash = NULL;
49 * VARIABLE - a user defined multi-value variable
52 typedef struct _variable VARIABLE;
53 struct _variable {
54 const char *symbol;
55 LIST *value;
60 * var_dump() - dump a variable to stdout
62 static void var_dump (const char *symbol, LIST *value, const char *what) {
63 printf("%s %s = ", what, symbol);
64 list_print_ex(stdout, value, LPFLAG_NO_TRSPACE);
65 printf("\n");
70 * var_enter() - make new var symbol table entry, returning var ptr
72 static VARIABLE *var_enter (const char *symbol) {
73 VARIABLE var, *v = &var;
74 if (!varhash) varhash = hashinit(sizeof(VARIABLE), "variables");
75 v->symbol = symbol;
76 v->value = 0;
77 if (hashenter(varhash, (HASHDATA **)&v)) v->symbol = newstr(symbol); /* never freed */
78 return v;
82 /* case-insensitive */
83 static inline int globhit (const char *list[], const char *str) {
84 for (; *list; ++list) {
85 //fprintf(stderr, "[%s]:[%s]:%d\n", *list, str, matchglobex(*list, str, 0));
86 if (matchglobex(*list, str, 0) == 0) return 1;
88 return 0;
93 * var_defines()
95 void var_defines (const char **e, int dontignore) {
96 static const char *pathsplits[] = {
97 "*PATH",
98 "INCLUDE",
99 "LIBS",
100 NULL
102 static const char *varignores[] = {
103 "ANT_*",
104 "BASH*",
105 "LS_*", /* various options for ls */
106 "PROMPT_*",
107 "PS[0-9]",
108 "WINDOWPATH",
109 "OS",
110 "OSPLAT",
111 "_",
112 NULL
114 for (; *e; ++e) {
115 const char *val = strchr(*e, '=');
116 /* Just say "no": on Unix, variables can contain function
117 * definitions. their value begins with "()"
119 if (val != NULL && val[1] == '(' && val[2] == ')') continue;
120 if (val != NULL) {
121 LIST *l = L0;
122 const char *pp, *p;
123 char split = ' ';
124 int op = VAR_SET;
125 dstring_t buf, name;
126 dstr_init_buf(&buf, *e, val-*e);
127 /* get name */
128 dstr_init_buf(&name, *e, val-*e);
129 if (val > *e) {
130 /* is this '+=', '-=' or '?=' operator? */
131 switch (val[-1]) {
132 case '+': op = VAR_APPEND; break;
133 case '-': op = VAR_REMOVE; break;
134 case '?': op = VAR_DEFAULT; break;
136 if (op != VAR_SET) dstr_pop_char(&name);
138 if (!dontignore && globhit(varignores, dstr_cstr(&name))) continue; /* ignore this */
139 /* split *PATH at :'s, not spaces */
140 if (val-4 >= *e) {
141 if (globhit(pathsplits, dstr_cstr(&name))) {
142 split = (strncmp(dstr_cstr(&name), "LUA_", 4) == 0 ? ';' : SPLITPATH); /* special for LUA_XXX */
145 /* do the split */
146 for (pp = val+1; (p = strchr(pp, split)); pp = p+1) {
147 int len = p-pp;
148 if (len > 0) {
149 dstr_clear(&buf);
150 dstr_push_buf(&buf, pp, len);
151 l = list_new(l, dstr_cstr(&buf), 0);
154 /* get name */
155 l = list_new(l, pp, 0);
156 var_set(dstr_cstr(&name), l, op);
157 dstr_done(&buf);
158 dstr_done(&name);
165 * var_string()
167 int var_string (const char *in, dstring_t *out, LOL *lol, char separator) {
168 int osz = dstr_len(out), lwpos;
169 const char *st;
170 while (*in) {
171 int dollar = 0;
172 /* copy white space */
173 st = in;
174 while (isspace(*in)) ++in;
175 dstr_push_memrange(out, st, in);
176 lwpos = dstr_len(out);
177 /* copy non-white space, watching for variables */
178 st = in;
179 while (*in && !isspace(*in)) {
180 if (in[0] == '$' && in[1] == '(') ++dollar;
181 ++in;
183 dstr_push_memrange(out, st, in);
184 /* if a variable encountered, expand it and and embed the space-separated members of the list in the output */
185 if (dollar) {
186 LIST *l = var_expand(dstr_cstr(out)+lwpos, dstr_cstr(out)+dstr_len(out), lol, 0), *hd = l;
187 dstr_chop(out, lwpos);
188 while (l != NULL) {
189 dstr_push_cstr(out, l->string);
190 /* separate with space */
191 if ((l = list_next(l)) != NULL) dstr_push_char(out, separator);
193 list_free(hd);
196 return dstr_len(out)-osz;
201 * var_get()
203 LIST *var_get (const char *symbol) {
204 VARIABLE var, *v = &var;
205 v->symbol = symbol;
206 if (varhash && hashcheck(varhash, (HASHDATA **)&v)) {
207 if (DEBUG_VARGET) var_dump(v->symbol, v->value, "get");
208 return v->value;
210 return 0;
215 * var_set()
217 void var_set (const char *symbol, LIST *value, int flag) {
218 VARIABLE *v = var_enter(symbol);
219 if (DEBUG_VARSET) var_dump(symbol, value, "set");
220 switch(flag) {
221 case VAR_SET:
222 /* replace value */
223 list_free(v->value);
224 v->value = value;
225 break;
226 case VAR_APPEND:
227 /* append value */
228 v->value = list_append(v->value, value);
229 break;
230 case VAR_REMOVE:
231 /* remove all values */
232 v->value = list_removeall(v->value, value);
233 list_free(value);
234 break;
235 case VAR_DEFAULT:
236 /* set only if unset */
237 if (!v->value) v->value = value; else list_free(value);
238 break;
244 * var_swap()
246 LIST *var_swap (const char *symbol, LIST *value) {
247 VARIABLE *v = var_enter(symbol);
248 LIST *oldvalue = v->value;
249 if (DEBUG_VARSET) var_dump(symbol, value, "set");
250 v->value = value;
251 return oldvalue;
256 * var_done()
258 void var_done (void) {
259 hashdone(varhash);