cosmetix
[k8jam.git] / src / variable.c
blob3446f36b76f0e360d2e6a56816244af645041a41
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"
39 #include "dstrings.h"
42 static struct hash *varhash = NULL;
46 * VARIABLE - a user defined multi-value variable
49 typedef struct _variable VARIABLE;
50 struct _variable {
51 const char *symbol;
52 LIST *value;
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(stdout, value, LPFLAG_NO_TRSPACE);
62 printf("\n");
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");
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 "OS",
107 "OSPLAT",
108 "_",
109 NULL
111 for (; *e; ++e) {
112 const char *val = strchr(*e, '=');
113 /* Just say "no": on Unix, variables can contain function
114 * definitions. their value begins with "()"
116 if (val != NULL && val[1] == '(' && val[2] == ')') continue;
117 if (val != NULL) {
118 LIST *l = L0;
119 const char *pp, *p;
120 char split = ' ';
121 dstring_t buf;
122 /* get name */
123 dstr_init_buf(&buf, *e, val-*e);
124 if (!dontignore && globhit(varignores, dstr_cstr(&buf))) continue; /* ignore this */
125 /* split *PATH at :'s, not spaces */
126 if (val-4 >= *e) {
127 if (globhit(pathsplits, dstr_cstr(&buf))) {
128 split = (strncmp(dstr_cstr(&buf), "LUA_", 4) == 0 ? ';' : SPLITPATH); /* special for LUA_XXX */
131 /* do the split */
132 for (pp = val+1; (p = strchr(pp, split)); pp = p+1) {
133 int len = p-pp;
134 if (len > 0) {
135 dstr_clear(&buf);
136 dstr_push_buf(&buf, pp, len);
137 l = list_new(l, dstr_cstr(&buf), 0);
140 /* get name */
141 dstr_clear(&buf);
142 dstr_push_buf(&buf, *e, val-*e);
143 l = list_new(l, pp, 0);
144 var_set(dstr_cstr(&buf), l, VAR_SET);
145 dstr_done(&buf);
152 * var_string()
154 int var_string (const char *in, dstring_t *out, LOL *lol, char separator) {
155 int osz = dstr_len(out), lwpos;
156 const char *st;
157 while (*in) {
158 int dollar = 0;
159 /* copy white space */
160 st = in;
161 while (isspace(*in)) ++in;
162 dstr_push_memrange(out, st, in);
163 lwpos = dstr_len(out);
164 /* copy non-white space, watching for variables */
165 st = in;
166 while (*in && !isspace(*in)) {
167 if (in[0] == '$' && in[1] == '(') ++dollar;
168 ++in;
170 dstr_push_memrange(out, st, in);
171 /* if a variable encountered, expand it and and embed the space-separated members of the list in the output */
172 if (dollar) {
173 LIST *l = var_expand(dstr_cstr(out)+lwpos, dstr_cstr(out)+dstr_len(out), lol, 0), *hd = l;
174 dstr_chop(out, lwpos);
175 while (l != NULL) {
176 dstr_push_cstr(out, l->string);
177 /* separate with space */
178 if ((l = list_next(l)) != NULL) dstr_push_char(out, separator);
180 list_free(hd);
183 return dstr_len(out)-osz;
188 * var_get()
190 LIST *var_get (const char *symbol) {
191 VARIABLE var, *v = &var;
192 v->symbol = symbol;
193 if (varhash && hashcheck(varhash, (HASHDATA **)&v)) {
194 if (DEBUG_VARGET) var_dump(v->symbol, v->value, "get");
195 return v->value;
197 return 0;
202 * var_set()
204 void var_set (const char *symbol, LIST *value, int flag) {
205 VARIABLE *v = var_enter(symbol);
206 if (DEBUG_VARSET) var_dump(symbol, value, "set");
207 switch(flag) {
208 case VAR_SET:
209 /* replace value */
210 list_free(v->value);
211 v->value = value;
212 break;
213 case VAR_APPEND:
214 /* append value */
215 v->value = list_append(v->value, value);
216 break;
217 case VAR_REMOVE:
218 /* remove all values */
219 v->value = list_removeall(v->value, value);
220 list_free(value);
221 break;
222 case VAR_DEFAULT:
223 /* set only if unset */
224 if (!v->value) v->value = value; else list_free(value);
225 break;
231 * var_swap()
233 LIST *var_swap (const char *symbol, LIST *value) {
234 VARIABLE *v = var_enter(symbol);
235 LIST *oldvalue = v->value;
236 if (DEBUG_VARSET) var_dump(symbol, value, "set");
237 v->value = value;
238 return oldvalue;
243 * var_done()
245 void var_done (void) {
246 hashdone(varhash);