2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
4 * This file is part of Jam - see jam.c for Copyright information.
7 * variable.c - handle jam multi-element variables
11 * var_defines() - load a bunch of variable=value settings
12 * var_string() - expand a string with variables in it
13 * var_get() - get value of a user defined symbol
14 * var_set() - set a variable in jam's user defined symbol table
15 * var_swap() - swap a variable's value with the given one
16 * var_done() - free variable tables
20 * var_enter() - make new var symbol table entry, returning var ptr
21 * var_dump() - dump a variable to stdout
23 * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
24 * 08/23/94 (seiwald) - Support for '+=' (append to variable)
25 * 01/22/95 (seiwald) - split environment variables at blanks or :'s
26 * 05/10/95 (seiwald) - split path variables at SPLITPATH (not :)
27 * 09/11/00 (seiwald) - defunct var_list() removed
28 * 10/22/02 (seiwald) - list_new() now does its own newstr()/copystr()
29 * 11/04/02 (seiwald) - const-ing for string literals
38 #include "matchglob.h"
42 static struct hash
*varhash
= NULL
;
46 * VARIABLE - a user defined multi-value variable
49 typedef struct _variable VARIABLE
;
57 * var_dump() - dump a variable to stdout
59 static void var_dump (const char *symbol
, LIST
*value
, const char *what
) {
60 printf("%s %s = ", what
, symbol
);
61 list_print_ex(value
, LPFLAG_NO_TRSPACE
);
67 * var_enter() - make new var symbol table entry, returning var ptr
69 static VARIABLE
*var_enter (const char *symbol
) {
70 VARIABLE var
, *v
= &var
;
71 if (!varhash
) varhash
= hashinit(sizeof(VARIABLE
), "variables");
74 if (hashenter(varhash
, (HASHDATA
**)&v
)) v
->symbol
= newstr(symbol
); /* never freed */
79 /* case-insensitive */
80 static inline int globhit (const char *list
[], const char *str
) {
81 for (; *list
; ++list
) {
82 //fprintf(stderr, "[%s]:[%s]:%d\n", *list, str, matchglobex(*list, str, 0));
83 if (matchglobex(*list
, str
, 0) == 0) return 1;
92 void var_defines (const char **e
, int dontignore
) {
93 static const char *pathsplits
[] = {
99 static const char *varignores
[] = {
102 "LS_*", /* various options for ls */
113 const char *val
= strchr(*e
, '=');
114 /* Just say "no": on Unix, variables can contain function
115 * definitions. their value begins with "()"
117 if (val
!= NULL
&& val
[1] == '(' && val
[2] == ')') continue;
124 dstr_init_buf(&buf
, *e
, val
-*e
);
125 if (!dontignore
&& globhit(varignores
, dstr_cstr(&buf
))) continue; /* ignore this */
126 /* split *PATH at :'s, not spaces */
128 if (globhit(pathsplits
, dstr_cstr(&buf
))) {
129 split
= (strncmp(dstr_cstr(&buf
), "LUA_", 4) == 0 ? ';' : SPLITPATH
); /* special for LUA_XXX */
133 for (pp
= val
+1; (p
= strchr(pp
, split
)); pp
= p
+1) {
137 dstr_push_buf(&buf
, pp
, len
);
138 l
= list_new(l
, dstr_cstr(&buf
), 0);
143 dstr_push_buf(&buf
, *e
, val
-*e
);
144 l
= list_new(l
, pp
, 0);
145 var_set(dstr_cstr(&buf
), l
, VAR_SET
);
155 int var_string (const char *in
, dstring_t
*out
, LOL
*lol
, char separator
) {
156 int osz
= dstr_len(out
), lwpos
;
160 /* copy white space */
162 while (isspace(*in
)) ++in
;
163 dstr_push_memrange(out
, st
, in
);
164 lwpos
= dstr_len(out
);
165 /* copy non-white space, watching for variables */
167 while (*in
&& !isspace(*in
)) {
168 if (in
[0] == '$' && in
[1] == '(') ++dollar
;
171 dstr_push_memrange(out
, st
, in
);
172 /* if a variable encountered, expand it and and embed the space-separated members of the list in the output */
174 LIST
*l
= var_expand(L0
, dstr_cstr(out
)+lwpos
, dstr_cstr(out
)+dstr_len(out
), lol
, 0), *hd
= l
;
175 dstr_chop(out
, lwpos
);
177 dstr_push_cstr(out
, l
->string
);
178 /* separate with space */
179 if ((l
= list_next(l
)) != NULL
) dstr_push_char(out
, separator
);
184 return dstr_len(out
)-osz
;
191 LIST
*var_get (const char *symbol
) {
192 VARIABLE var
, *v
= &var
;
194 if (varhash
&& hashcheck(varhash
, (HASHDATA
**)&v
)) {
195 if (DEBUG_VARGET
) var_dump(v
->symbol
, v
->value
, "get");
205 void var_set (const char *symbol
, LIST
*value
, int flag
) {
206 VARIABLE
*v
= var_enter(symbol
);
207 if (DEBUG_VARSET
) var_dump(symbol
, value
, "set");
216 v
->value
= list_append(v
->value
, value
);
219 /* Remove all values */
220 v
->value
= list_removeall(v
->value
, value
);
224 /* Set only if unset */
225 if (!v
->value
) v
->value
= value
; else list_free(value
);
234 LIST
*var_swap (const char *symbol
, LIST
*value
) {
235 VARIABLE
*v
= var_enter(symbol
);
236 LIST
*oldvalue
= v
->value
;
237 if (DEBUG_VARSET
) var_dump(symbol
, value
, "set");
246 void var_done (void) {