added "jammod" command and "genman" module
[k8jam.git] / src / variable.c
blob57cf9ade28042ddd3a615edd264835b592bcb151
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, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 * variable.c - handle jam multi-element variables
21 * External routines:
23 * var_defines() - load a bunch of variable=value settings
24 * var_string() - expand a string with variables in it
25 * var_get() - get value of a user defined symbol
26 * var_set() - set a variable in jam's user defined symbol table
27 * var_swap() - swap a variable's value with the given one
28 * var_done() - free variable tables
30 * Internal routines:
32 * var_enter() - make new var symbol table entry, returning var ptr
33 * var_dump() - dump a variable to stdout
35 #include "jam.h"
36 #include "lists.h"
37 #include "parse.h"
38 #include "variable.h"
39 #include "expand.h"
40 #include "hash.h"
41 #include "newstr.h"
42 #include "matchglob.h"
43 #include "dstrings.h"
46 static struct hash *varhash = NULL;
50 * VARIABLE - a user defined multi-value variable
53 typedef struct _variable VARIABLE;
54 struct _variable {
55 const char *symbol;
56 LIST *value;
61 * var_dump() - dump a variable to stdout
63 static void var_dump (const char *symbol, LIST *value, const char *what) {
64 printf("%s %s = ", what, symbol);
65 list_print_ex(stdout, value, LPFLAG_NO_TRSPACE);
66 printf("\n");
71 * var_enter() - make new var symbol table entry, returning var ptr
73 static VARIABLE *var_enter (const char *symbol) {
74 VARIABLE var, *v = &var;
75 if (!varhash) varhash = hashinit(sizeof(VARIABLE), "variables");
76 v->symbol = symbol;
77 v->value = 0;
78 if (hashenter(varhash, (HASHDATA **)&v)) v->symbol = newstr(symbol); /* never freed */
79 return v;
83 /* case-insensitive */
84 static inline int globhit (const char *list[], const char *str) {
85 for (; *list; ++list) {
86 //fprintf(stderr, "[%s]:[%s]:%d\n", *list, str, matchglobex(*list, str, 0));
87 if (matchglobex(*list, str, 0) == 0) return 1;
89 return 0;
94 * var_defines()
96 void var_defines (const char **e, int dontignore) {
97 static const char *pathsplits[] = {
98 "*PATH",
99 "INCLUDE",
100 "LIBS",
101 NULL
103 static const char *varignores[] = {
104 "ANT_*",
105 "BASH*",
106 "LS_*", /* various options for ls */
107 "PROMPT_*",
108 "PS[0-9]",
109 "WINDOWPATH",
110 "OS",
111 "OSPLAT",
112 "_",
113 NULL
115 for (; *e; ++e) {
116 const char *val = strchr(*e, '=');
117 /* Just say "no": on Unix, variables can contain function
118 * definitions. their value begins with "()"
120 if (val != NULL && val[1] == '(' && val[2] == ')') continue;
121 if (val != NULL) {
122 LIST *l = L0;
123 const char *pp, *p;
124 char split = ' ';
125 int op = VAR_SET;
126 dstring_t buf, name;
127 dstr_init_buf(&buf, *e, val-*e);
128 /* get name */
129 dstr_init_buf(&name, *e, val-*e);
130 if (val > *e) {
131 /* is this '+=', '-=' or '?=' operator? */
132 switch (val[-1]) {
133 case '+': op = VAR_APPEND; break;
134 case '-': op = VAR_REMOVE; break;
135 case '?': op = VAR_DEFAULT; break;
137 if (op != VAR_SET) dstr_pop_char(&name);
139 if (!dontignore && globhit(varignores, dstr_cstr(&name))) continue; /* ignore this */
140 /* split *PATH at :'s, not spaces */
141 if (val-4 >= *e) {
142 if (globhit(pathsplits, dstr_cstr(&name))) {
143 split = (strncmp(dstr_cstr(&name), "LUA_", 4) == 0 ? ';' : SPLITPATH); /* special for LUA_XXX */
146 /* do the split */
147 for (pp = val+1; (p = strchr(pp, split)); pp = p+1) {
148 int len = p-pp;
149 if (len > 0) {
150 dstr_clear(&buf);
151 dstr_push_buf(&buf, pp, len);
152 l = list_new(l, dstr_cstr(&buf), 0);
155 /* get name */
156 l = list_new(l, pp, 0);
157 var_set(dstr_cstr(&name), l, op);
158 dstr_done(&buf);
159 dstr_done(&name);
166 * var_string()
168 int var_string (const char *in, dstring_t *out, LOL *lol, char separator) {
169 int osz = dstr_len(out), lwpos;
170 const char *st;
171 while (*in) {
172 int dollar = 0;
173 /* copy white space */
174 st = in;
175 while (isspace(*in)) ++in;
176 dstr_push_memrange(out, st, in);
177 lwpos = dstr_len(out);
178 /* copy non-white space, watching for variables */
179 st = in;
180 while (*in && !isspace(*in)) {
181 if (in[0] == '$' && in[1] == '(') ++dollar;
182 ++in;
184 dstr_push_memrange(out, st, in);
185 /* if a variable encountered, expand it and and embed the space-separated members of the list in the output */
186 if (dollar) {
187 LIST *l = var_expand(dstr_cstr(out)+lwpos, dstr_cstr(out)+dstr_len(out), lol, 0), *hd = l;
188 dstr_chop(out, lwpos);
189 while (l != NULL) {
190 dstr_push_cstr(out, l->string);
191 /* separate with space */
192 if ((l = list_next(l)) != NULL) dstr_push_char(out, separator);
194 list_free(hd);
197 return dstr_len(out)-osz;
202 * var_get()
204 LIST *var_get (const char *symbol) {
205 VARIABLE var, *v = &var;
206 v->symbol = symbol;
207 if (varhash && hashcheck(varhash, (HASHDATA **)&v)) {
208 if (DEBUG_VARGET) var_dump(v->symbol, v->value, "get");
209 return v->value;
211 return 0;
216 * var_set()
218 void var_set (const char *symbol, LIST *value, int flag) {
219 VARIABLE *v = var_enter(symbol);
220 if (DEBUG_VARSET) var_dump(symbol, value, "set");
221 switch(flag) {
222 case VAR_SET:
223 /* replace value */
224 list_free(v->value);
225 v->value = value;
226 break;
227 case VAR_APPEND:
228 /* append value */
229 v->value = list_append(v->value, value);
230 break;
231 case VAR_REMOVE:
232 /* remove all values */
233 v->value = list_removeall(v->value, value);
234 list_free(value);
235 break;
236 case VAR_DEFAULT:
237 /* set only if unset */
238 if (!v->value) v->value = value; else list_free(value);
239 break;
245 * var_swap()
247 LIST *var_swap (const char *symbol, LIST *value) {
248 VARIABLE *v = var_enter(symbol);
249 LIST *oldvalue = v->value;
250 if (DEBUG_VARSET) var_dump(symbol, value, "set");
251 v->value = value;
252 return oldvalue;
257 * var_done()
259 void var_done (void) {
260 hashdone(varhash);