2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
4 * This file is part of Jam - see jam.c for Copyright information.
8 * variable.c - handle jam multi-element variables
12 * var_defines() - load a bunch of variable=value settings
13 * var_string() - expand a string with variables in it
14 * var_get() - get value of a user defined symbol
15 * var_set() - set a variable in jam's user defined symbol table
16 * var_swap() - swap a variable's value with the given one
17 * var_done() - free variable tables
21 * var_enter() - make new var symbol table entry, returning var ptr
22 * var_dump() - dump a variable to stdout
24 * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
25 * 08/23/94 (seiwald) - Support for '+=' (append to variable)
26 * 01/22/95 (seiwald) - split environment variables at blanks or :'s
27 * 05/10/95 (seiwald) - split path variables at SPLITPATH (not :)
28 * 09/11/00 (seiwald) - defunct var_list() removed
29 * 10/22/02 (seiwald) - list_new() now does its own newstr()/copystr()
30 * 11/04/02 (seiwald) - const-ing for string literals
36 # include "variable.h"
41 static struct hash
*varhash
= 0;
44 * VARIABLE - a user defined multi-value variable
47 typedef struct _variable VARIABLE
;
55 static VARIABLE
*var_enter (const char *symbol
);
56 static void var_dump (const char *symbol
, LIST
*value
, const char *what
);
60 * var_defines() - load a bunch of variable=value settings
62 * If variable name ends in PATH, split value at :'s.
63 * Otherwise, split at blanks.
65 void var_defines (const char **e
) {
68 /* Just say "no": windows defines this in the env, */
69 /* but we don't want it to override our notion of OS. */
70 if (!strcmp(*e
, "OS=Windows_NT")) continue;
71 /* Just say "no": on Unix, variables can contain function
72 * definitions. their value begins with "()"
74 if ((val
= strchr(*e
, '=')) && val
[1] == '(' && val
[2] == ')') continue;
76 /* On the mac (MPW), the var=val is actually var\0val */
77 /* Think different. */
78 if ((val
= strchr(*e
, '=')) || (val
= *e
+ strlen(*e
))) {
80 if ((val
= strchr(*e
, '='))) {
90 /* Split *PATH at :'s, not spaces */
92 if (!strncmp(val
- 4, "PATH", 4) || !strncmp(val
- 4, "Path", 4) || !strncmp(val
- 4, "path", 4))
96 for (pp
= val
+1; (p
= strchr(pp
, split
)); pp
= p
+1) {
99 if (len
>= sizeof(buf
)) len
= sizeof(buf
)-1;
100 strncpy(buf
, pp
, len
);
102 l
= list_new(l
, buf
, 0);
104 l
= list_new(l
, pp
, 0);
106 strncpy(buf
, *e
, val
-*e
);
108 var_set(buf
, l
, VAR_SET
);
115 * var_string() - expand a string with variables in it
117 * Copies in to out; doesn't modify targets & sources.
119 int var_string (const char *in
, char *out
, int outsize
, LOL
*lol
) {
121 char *oute
= out
+outsize
-1;
126 /* Copy white space */
127 while (isspace(*in
)) {
128 if (out
>= oute
) return -1;
132 /* Copy non-white space, watching for variables */
133 while (*in
&& !isspace(*in
)) {
134 if (out
>= oute
) return -1;
135 if (in
[0] == '$' && in
[1] == '(') dollar
++;
138 /* If a variable encountered, expand it and and embed the */
139 /* space-separated members of the list in the output. */
141 LIST
*l
= var_expand(L0
, lastword
, out
, lol
, 0);
144 int so
= strlen(l
->string
);
145 if (out
+so
>= oute
) return -1;
146 strcpy(out
, l
->string
);
148 /* Separate with space */
149 if ((l
= list_next(l
)))
155 if (out
>= oute
) return -1;
162 * var_get() - get value of a user defined symbol
164 * Returns NULL if symbol unset.
166 LIST
*var_get (const char *symbol
) {
167 VARIABLE var
, *v
= &var
;
170 if (varhash
&& hashcheck(varhash
, (HASHDATA
**)&v
)) {
171 if (DEBUG_VARGET
) var_dump(v
->symbol
, v
->value
, "get");
179 * var_set() - set a variable in jam's user defined symbol table
181 * 'flag' controls the relationship between new and old values of
182 * the variable: SET replaces the old with the new; APPEND appends
183 * the new to the old; DEFAULT only uses the new if the variable
184 * was previously unset.
186 * Copies symbol. Takes ownership of value.
188 void var_set (const char *symbol
, LIST
*value
, int flag
) {
189 VARIABLE
*v
= var_enter(symbol
);
191 if (DEBUG_VARSET
) var_dump(symbol
, value
, "set");
200 v
->value
= list_append(v
->value
, value
);
203 /* Set only if unset */
204 if (!v
->value
) v
->value
= value
; else list_free(value
);
211 * var_swap() - swap a variable's value with the given one
213 LIST
*var_swap (const char *symbol
, LIST
*value
) {
214 VARIABLE
*v
= var_enter(symbol
);
215 LIST
*oldvalue
= v
->value
;
217 if (DEBUG_VARSET
) var_dump(symbol
, value
, "set");
224 * var_enter() - make new var symbol table entry, returning var ptr
226 static VARIABLE
*var_enter (const char *symbol
) {
227 VARIABLE var
, *v
= &var
;
229 if (!varhash
) varhash
= hashinit(sizeof(VARIABLE
), "variables");
232 if (hashenter(varhash
, (HASHDATA
**)&v
)) v
->symbol
= newstr(symbol
); /* never freed */
238 * var_dump() - dump a variable to stdout
240 static void var_dump (const char *symbol
, LIST
*value
, const char *what
) {
241 printf("%s %s = ", what
, symbol
);
248 * var_done() - free variable tables
250 void var_done (void) {