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
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
32 * var_enter() - make new var symbol table entry, returning var ptr
33 * var_dump() - dump a variable to stdout
42 #include "matchglob.h"
46 static struct hash
*varhash
= NULL
;
50 * VARIABLE - a user defined multi-value variable
53 typedef struct _variable VARIABLE
;
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
);
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");
78 if (hashenter(varhash
, (HASHDATA
**)&v
)) v
->symbol
= newstr(symbol
); /* never freed */
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;
96 void var_defines (const char **e
, int dontignore
) {
97 static const char *pathsplits
[] = {
103 static const char *varignores
[] = {
106 "LS_*", /* various options for ls */
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;
127 dstr_init_buf(&buf
, *e
, val
-*e
);
129 dstr_init_buf(&name
, *e
, val
-*e
);
131 /* is this '+=', '-=' or '?=' operator? */
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 */
142 if (globhit(pathsplits
, dstr_cstr(&name
))) {
143 split
= (strncmp(dstr_cstr(&name
), "LUA_", 4) == 0 ? ';' : SPLITPATH
); /* special for LUA_XXX */
147 for (pp
= val
+1; (p
= strchr(pp
, split
)); pp
= p
+1) {
151 dstr_push_buf(&buf
, pp
, len
);
152 l
= list_new(l
, dstr_cstr(&buf
), 0);
156 l
= list_new(l
, pp
, 0);
157 var_set(dstr_cstr(&name
), l
, op
);
168 int var_string (const char *in
, dstring_t
*out
, LOL
*lol
, char separator
) {
169 int osz
= dstr_len(out
), lwpos
;
173 /* copy white space */
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 */
180 while (*in
&& !isspace(*in
)) {
181 if (in
[0] == '$' && in
[1] == '(') ++dollar
;
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 */
187 LIST
*l
= var_expand(dstr_cstr(out
)+lwpos
, dstr_cstr(out
)+dstr_len(out
), lol
, 0), *hd
= l
;
188 dstr_chop(out
, lwpos
);
190 dstr_push_cstr(out
, l
->string
);
191 /* separate with space */
192 if ((l
= list_next(l
)) != NULL
) dstr_push_char(out
, separator
);
197 return dstr_len(out
)-osz
;
204 LIST
*var_get (const char *symbol
) {
205 VARIABLE var
, *v
= &var
;
207 if (varhash
&& hashcheck(varhash
, (HASHDATA
**)&v
)) {
208 if (DEBUG_VARGET
) var_dump(v
->symbol
, v
->value
, "get");
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");
229 v
->value
= list_append(v
->value
, value
);
232 /* remove all values */
233 v
->value
= list_removeall(v
->value
, value
);
237 /* set only if unset */
238 if (!v
->value
) v
->value
= value
; else list_free(value
);
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");
259 void var_done (void) {