lexer rules relaxed a little; please, don't use tokens like abc: -- use "abc:" instead
[k8jam.git] / src / variable.c
blob57093f2a5f82530fbc719cdd3a169f1300797596
1 /*
2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
4 * This file is part of Jam - see jam.c for Copyright information.
5 */
6 /*
7 * variable.c - handle jam multi-element variables
9 * External routines:
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
18 * Internal routines:
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
31 #include "jam.h"
32 #include "lists.h"
33 #include "parse.h"
34 #include "variable.h"
35 #include "expand.h"
36 #include "hash.h"
37 #include "newstr.h"
40 static struct hash *varhash = NULL;
44 * VARIABLE - a user defined multi-value variable
47 typedef struct _variable VARIABLE;
48 struct _variable {
49 const char *symbol;
50 LIST *value;
54 static VARIABLE *var_enter (const char *symbol);
55 static void var_dump (const char *symbol, LIST *value, const char *what);
59 * var_defines() - load a bunch of variable=value settings
61 * If variable name ends in PATH, split value at :'s.
62 * Otherwise, split at blanks.
64 void var_defines (const char **e) {
65 for (; *e; ++e) {
66 const char *val;
67 /* just say "no": windows defines this in the env, but we don't want it to override our notion of OS */
68 if (!strcmp(*e, "OS=Windows_NT")) continue;
69 /* Just say "no": on Unix, variables can contain function
70 * definitions. their value begins with "()"
72 if ((val = strchr(*e, '=')) && val[1] == '(' && val[2] == ')') continue;
73 if ((val = strchr(*e, '='))) {
74 LIST *l = L0;
75 const char *pp, *p;
76 char split = ' ';
77 char buf[MAXSYM];
78 /* split *PATH at :'s, not spaces */
79 if (val-4 >= *e) {
80 if (!strncmp(val-4, "PATH", 4) || !strncmp(val-4, "Path", 4) || !strncmp(val-4, "path", 4)) split = SPLITPATH;
82 /* do the split */
83 for (pp = val+1; (p = strchr(pp, split)); pp = p+1) {
84 int len = p-pp;
86 if (len >= sizeof(buf)) len = sizeof(buf)-1;
87 strncpy(buf, pp, len);
88 buf[len] = '\0';
89 l = list_new(l, buf, 0);
91 l = list_new(l, pp, 0);
92 /* get name */
93 strncpy(buf, *e, val-*e);
94 buf[val-*e] = '\0';
95 var_set(buf, l, VAR_SET);
102 * var_string() - expand a string with variables in it
104 * Copies in to out; doesn't modify targets & sources.
106 int var_string (const char *in, char *out, int outsize, LOL *lol) {
107 char *out0 = out;
108 char *oute = out+outsize-1;
110 while (*in) {
111 char *lastword;
112 int dollar = 0;
113 /* copy white space */
114 while (isspace(*in)) {
115 if (out >= oute) return -1;
116 *out++ = *in++;
118 lastword = out;
119 /* copy non-white space, watching for variables */
120 while (*in && !isspace(*in)) {
121 if (out >= oute) return -1;
122 if (in[0] == '$' && in[1] == '(') ++dollar;
123 *out++ = *in++;
125 /* if a variable encountered, expand it and and embed the space-separated members of the list in the output */
126 if (dollar) {
127 LIST *l = var_expand(L0, lastword, out, lol, 0);
128 out = lastword;
129 while (l) {
130 int so = strlen(l->string);
131 if (out+so >= oute) return -1;
132 strcpy(out, l->string);
133 out += so;
134 /* separate with space */
135 if ((l = list_next(l)))
136 *out++ = ' ';
138 list_free(l);
141 if (out >= oute) return -1;
142 *out++ = '\0';
143 return out-out0;
148 * var_get() - get value of a user defined symbol
150 * Returns NULL if symbol unset.
152 LIST *var_get (const char *symbol) {
153 VARIABLE var, *v = &var;
155 v->symbol = symbol;
156 if (varhash && hashcheck(varhash, (HASHDATA **)&v)) {
157 if (DEBUG_VARGET) var_dump(v->symbol, v->value, "get");
158 return v->value;
160 return 0;
165 * var_set() - set a variable in jam's user defined symbol table
167 * 'flag' controls the relationship between new and old values of
168 * the variable: SET replaces the old with the new; APPEND appends
169 * the new to the old; DEFAULT only uses the new if the variable
170 * was previously unset.
172 * Copies symbol. Takes ownership of value.
174 void var_set (const char *symbol, LIST *value, int flag) {
175 VARIABLE *v = var_enter(symbol);
177 if (DEBUG_VARSET) var_dump(symbol, value, "set");
178 switch(flag) {
179 case VAR_SET:
180 /* Replace value */
181 list_free(v->value);
182 v->value = value;
183 break;
184 case VAR_APPEND:
185 /* Append value */
186 v->value = list_append(v->value, value);
187 break;
188 case VAR_REMOVE:
189 /* Remove all values */
190 v->value = list_removeall(v->value, value);
191 list_free(value);
192 break;
193 case VAR_DEFAULT:
194 /* Set only if unset */
195 if (!v->value) v->value = value; else list_free(value);
196 break;
202 * var_swap() - swap a variable's value with the given one
204 LIST *var_swap (const char *symbol, LIST *value) {
205 VARIABLE *v = var_enter(symbol);
206 LIST *oldvalue = v->value;
208 if (DEBUG_VARSET) var_dump(symbol, value, "set");
209 v->value = value;
210 return oldvalue;
215 * var_enter() - make new var symbol table entry, returning var ptr
217 static VARIABLE *var_enter (const char *symbol) {
218 VARIABLE var, *v = &var;
220 if (!varhash) varhash = hashinit(sizeof(VARIABLE), "variables");
221 v->symbol = symbol;
222 v->value = 0;
223 if (hashenter(varhash, (HASHDATA **)&v)) v->symbol = newstr(symbol); /* never freed */
224 return v;
229 * var_dump() - dump a variable to stdout
231 static void var_dump (const char *symbol, LIST *value, const char *what) {
232 printf("%s %s = ", what, symbol);
233 list_print(value);
234 printf("\n");
239 * var_done() - free variable tables
241 void var_done (void) {
242 hashdone(varhash);