cosmetix
[k8jam.git] / src / variable.c
blobd069bcf21510b0abc44be77659ee13a931e65b91
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;
55 * var_dump() - dump a variable to stdout
57 static void var_dump (const char *symbol, LIST *value, const char *what) {
58 printf("%s %s = ", what, symbol);
59 list_print(value);
60 printf("\n");
65 * var_enter() - make new var symbol table entry, returning var ptr
67 static VARIABLE *var_enter (const char *symbol) {
68 VARIABLE var, *v = &var;
70 if (!varhash) varhash = hashinit(sizeof(VARIABLE), "variables");
71 v->symbol = symbol;
72 v->value = 0;
73 if (hashenter(varhash, (HASHDATA **)&v)) v->symbol = newstr(symbol); /* never freed */
74 return v;
79 * var_defines()
81 void var_defines (const char **e) {
82 for (; *e; ++e) {
83 const char *val;
84 /* just say "no": windows defines this in the env, but we don't want it to override our notion of OS */
85 if (!strcmp(*e, "OS=Windows_NT")) continue;
86 /* Just say "no": on Unix, variables can contain function
87 * definitions. their value begins with "()"
89 if ((val = strchr(*e, '=')) && val[1] == '(' && val[2] == ')') continue;
90 if ((val = strchr(*e, '='))) {
91 LIST *l = L0;
92 const char *pp, *p;
93 char split = ' ';
94 char buf[MAXSYM];
95 /* split *PATH at :'s, not spaces */
96 if (val-4 >= *e) {
97 if (!strncmp(val-4, "PATH", 4) || !strncmp(val-4, "Path", 4) || !strncmp(val-4, "path", 4)) split = SPLITPATH;
99 /* do the split */
100 for (pp = val+1; (p = strchr(pp, split)); pp = p+1) {
101 int len = p-pp;
103 if (len >= sizeof(buf)) len = sizeof(buf)-1;
104 strncpy(buf, pp, len);
105 buf[len] = '\0';
106 l = list_new(l, buf, 0);
108 l = list_new(l, pp, 0);
109 /* get name */
110 strncpy(buf, *e, val-*e);
111 buf[val-*e] = '\0';
112 var_set(buf, l, VAR_SET);
119 * var_string()
121 int var_string (const char *in, tKString *out, LOL *lol, char separator) {
122 int osz = kStringLen(out), lwpos;
123 const char *st;
125 while (*in) {
126 //char *lastword;
127 int dollar = 0;
128 /* copy white space */
129 st = in;
130 while (isspace(*in)) ++in;
131 kStringAppendRange(out, st, in);
133 lwpos = kStringLen(out);
134 /* copy non-white space, watching for variables */
135 st = in;
136 while (*in && !isspace(*in)) {
137 if (in[0] == '$' && in[1] == '(') ++dollar;
138 ++in;
140 kStringAppendRange(out, st, in);
141 /* if a variable encountered, expand it and and embed the space-separated members of the list in the output */
142 if (dollar) {
143 LIST *l = var_expand(L0, kStringCStr(out)+lwpos, kStringCStr(out)+kStringLen(out), lol, 0), *hd = l;
144 kStringTruncate(out, lwpos);
145 while (l != NULL) {
146 kStringAppendCStr(out, l->string);
147 /* separate with space */
148 if ((l = list_next(l)) != NULL) kStringPushBack(out, separator);
150 list_free(hd);
153 return kStringLen(out)-osz;
158 * var_get()
160 LIST *var_get (const char *symbol) {
161 VARIABLE var, *v = &var;
163 v->symbol = symbol;
164 if (varhash && hashcheck(varhash, (HASHDATA **)&v)) {
165 if (DEBUG_VARGET) var_dump(v->symbol, v->value, "get");
166 return v->value;
168 return 0;
173 * var_set()
175 void var_set (const char *symbol, LIST *value, int flag) {
176 VARIABLE *v = var_enter(symbol);
178 if (DEBUG_VARSET) var_dump(symbol, value, "set");
179 switch(flag) {
180 case VAR_SET:
181 /* Replace value */
182 list_free(v->value);
183 v->value = value;
184 break;
185 case VAR_APPEND:
186 /* Append value */
187 v->value = list_append(v->value, value);
188 break;
189 case VAR_REMOVE:
190 /* Remove all values */
191 v->value = list_removeall(v->value, value);
192 list_free(value);
193 break;
194 case VAR_DEFAULT:
195 /* Set only if unset */
196 if (!v->value) v->value = value; else list_free(value);
197 break;
203 * var_swap()
205 LIST *var_swap (const char *symbol, LIST *value) {
206 VARIABLE *v = var_enter(symbol);
207 LIST *oldvalue = v->value;
209 if (DEBUG_VARSET) var_dump(symbol, value, "set");
210 v->value = value;
211 return oldvalue;
216 * var_done()
218 void var_done (void) {
219 hashdone(varhash);