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
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
31 * var_enter() - make new var symbol table entry, returning var ptr
32 * var_dump() - dump a variable to stdout
41 #include "matchglob.h"
45 static struct hash
*varhash
= NULL
;
49 * VARIABLE - a user defined multi-value variable
52 typedef struct _variable VARIABLE
;
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
);
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");
77 if (hashenter(varhash
, (HASHDATA
**)&v
)) v
->symbol
= newstr(symbol
); /* never freed */
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;
95 void var_defines (const char **e
, int dontignore
) {
96 static const char *pathsplits
[] = {
102 static const char *varignores
[] = {
105 "LS_*", /* various options for ls */
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;
126 dstr_init_buf(&buf
, *e
, val
-*e
);
128 dstr_init_buf(&name
, *e
, val
-*e
);
130 /* is this '+=', '-=' or '?=' operator? */
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 */
141 if (globhit(pathsplits
, dstr_cstr(&name
))) {
142 split
= (strncmp(dstr_cstr(&name
), "LUA_", 4) == 0 ? ';' : SPLITPATH
); /* special for LUA_XXX */
146 for (pp
= val
+1; (p
= strchr(pp
, split
)); pp
= p
+1) {
150 dstr_push_buf(&buf
, pp
, len
);
151 l
= list_new(l
, dstr_cstr(&buf
), 0);
155 l
= list_new(l
, pp
, 0);
156 var_set(dstr_cstr(&name
), l
, op
);
167 int var_string (const char *in
, dstring_t
*out
, LOL
*lol
, char separator
) {
168 int osz
= dstr_len(out
), lwpos
;
172 /* copy white space */
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 */
179 while (*in
&& !isspace(*in
)) {
180 if (in
[0] == '$' && in
[1] == '(') ++dollar
;
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 */
186 LIST
*l
= var_expand(dstr_cstr(out
)+lwpos
, dstr_cstr(out
)+dstr_len(out
), lol
, 0), *hd
= l
;
187 dstr_chop(out
, lwpos
);
189 dstr_push_cstr(out
, l
->string
);
190 /* separate with space */
191 if ((l
= list_next(l
)) != NULL
) dstr_push_char(out
, separator
);
196 return dstr_len(out
)-osz
;
203 LIST
*var_get (const char *symbol
) {
204 VARIABLE var
, *v
= &var
;
206 if (varhash
&& hashcheck(varhash
, (HASHDATA
**)&v
)) {
207 if (DEBUG_VARGET
) var_dump(v
->symbol
, v
->value
, "get");
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");
228 v
->value
= list_append(v
->value
, value
);
231 /* remove all values */
232 v
->value
= list_removeall(v
->value
, value
);
236 /* set only if unset */
237 if (!v
->value
) v
->value
= value
; else list_free(value
);
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");
258 void var_done (void) {