fixed pkg-config rule
[k8jam.git] / src / variable.c
blobce312d2b0a9187ebccd1996230d693c418e66c14
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"
38 #include "matchglob.h"
41 static struct hash *varhash = NULL;
45 * VARIABLE - a user defined multi-value variable
48 typedef struct _variable VARIABLE;
49 struct _variable {
50 const char *symbol;
51 LIST *value;
56 * var_dump() - dump a variable to stdout
58 static void var_dump (const char *symbol, LIST *value, const char *what) {
59 printf("%s %s = ", what, symbol);
60 list_print(value);
61 printf("\n");
66 * var_enter() - make new var symbol table entry, returning var ptr
68 static VARIABLE *var_enter (const char *symbol) {
69 VARIABLE var, *v = &var;
71 if (!varhash) varhash = hashinit(sizeof(VARIABLE), "variables");
72 v->symbol = symbol;
73 v->value = 0;
74 if (hashenter(varhash, (HASHDATA **)&v)) v->symbol = newstr(symbol); /* never freed */
75 return v;
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;
85 return 0;
90 * var_defines()
92 void var_defines (const char **e, int dontignore) {
93 static const char *pathsplits[] = {
94 "*PATH",
95 "INCLUDE",
96 "LIBS",
97 NULL
99 static const char *varignores[] = {
100 "ANT_*",
101 "BASH*",
102 "LS_*", /* various options for ls */
103 "PROMPT_*",
104 "PS[0-9]",
105 "WINDOWPATH",
106 NULL
109 //fprintf(stderr, "---\n");
110 for (; *e; ++e) {
111 const char *val;
112 //fprintf(stderr, "[%s]\n", *e);
113 /* just say "no": windows defines this in the env, but we don't want it to override our notion of OS */
114 if (!strcmp(*e, "OS=Windows_NT")) continue;
115 /* Just say "no": on Unix, variables can contain function
116 * definitions. their value begins with "()"
118 if ((val = strchr(*e, '=')) && val[1] == '(' && val[2] == ')') continue;
119 if ((val = strchr(*e, '='))) {
120 LIST *l = L0;
121 const char *pp, *p;
122 char split = ' ';
123 char buf[MAXSYM];
124 /* get name */
125 strncpy(buf, *e, val-*e);
126 buf[val-*e] = '\0';
127 if (!dontignore && globhit(varignores, buf)) {
128 /* ignore this */
129 //fprintf(stderr, "IGN: [%s]\n", buf);
130 continue;
132 /* split *PATH at :'s, not spaces */
133 if (val-4 >= *e) {
134 if (globhit(pathsplits, buf)) {
135 //fprintf(stderr, "PATH: [%s]\n", buf);
136 split =
137 (buf[0]=='l'||buf[0]=='L')&&(buf[1]=='u'||buf[1]=='U') ? ';' /* special for LUA_XXX */
138 : SPLITPATH;
141 /* do the split */
142 for (pp = val+1; (p = strchr(pp, split)); pp = p+1) {
143 int len = p-pp;
145 if (len >= sizeof(buf)) len = sizeof(buf)-1;
146 if (len < 1) continue; /* ignore empty elements */
147 strncpy(buf, pp, len);
148 buf[len] = '\0';
149 //fprintf(stderr, " [%s]\n", buf);
150 l = list_new(l, buf, 0);
152 /* get name */
153 strncpy(buf, *e, val-*e);
154 buf[val-*e] = '\0';
155 l = list_new(l, pp, 0);
156 var_set(buf, l, VAR_SET);
163 * var_string()
165 int var_string (const char *in, tKString *out, LOL *lol, char separator) {
166 int osz = kStringLen(out), lwpos;
167 const char *st;
169 while (*in) {
170 //char *lastword;
171 int dollar = 0;
172 /* copy white space */
173 st = in;
174 while (isspace(*in)) ++in;
175 kStringAppendRange(out, st, in);
177 lwpos = kStringLen(out);
178 /* copy non-white space, watching for variables */
179 st = in;
180 while (*in && !isspace(*in)) {
181 if (in[0] == '$' && in[1] == '(') ++dollar;
182 ++in;
184 kStringAppendRange(out, st, in);
185 /* if a variable encountered, expand it and and embed the space-separated members of the list in the output */
186 if (dollar) {
187 LIST *l = var_expand(L0, kStringCStr(out)+lwpos, kStringCStr(out)+kStringLen(out), lol, 0), *hd = l;
188 kStringTruncate(out, lwpos);
189 while (l != NULL) {
190 kStringAppendCStr(out, l->string);
191 /* separate with space */
192 if ((l = list_next(l)) != NULL) kStringPushBack(out, separator);
194 list_free(hd);
197 return kStringLen(out)-osz;
202 * var_get()
204 LIST *var_get (const char *symbol) {
205 VARIABLE var, *v = &var;
207 v->symbol = symbol;
208 if (varhash && hashcheck(varhash, (HASHDATA **)&v)) {
209 if (DEBUG_VARGET) var_dump(v->symbol, v->value, "get");
210 return v->value;
212 return 0;
217 * var_set()
219 void var_set (const char *symbol, LIST *value, int flag) {
220 VARIABLE *v = var_enter(symbol);
222 if (DEBUG_VARSET) var_dump(symbol, value, "set");
223 switch(flag) {
224 case VAR_SET:
225 /* Replace value */
226 list_free(v->value);
227 v->value = value;
228 break;
229 case VAR_APPEND:
230 /* Append value */
231 v->value = list_append(v->value, value);
232 break;
233 case VAR_REMOVE:
234 /* Remove all values */
235 v->value = list_removeall(v->value, value);
236 list_free(value);
237 break;
238 case VAR_DEFAULT:
239 /* Set only if unset */
240 if (!v->value) v->value = value; else list_free(value);
241 break;
247 * var_swap()
249 LIST *var_swap (const char *symbol, LIST *value) {
250 VARIABLE *v = var_enter(symbol);
251 LIST *oldvalue = v->value;
253 if (DEBUG_VARSET) var_dump(symbol, value, "set");
254 v->value = value;
255 return oldvalue;
260 * var_done()
262 void var_done (void) {
263 hashdone(varhash);