got rid of trailing spaces in k8jam output
[k8jam.git] / src / variable.c
blob7c9bec1d4b8d32eeaaeec33632fb6e1a28da4fda
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(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
112 for (; *e; ++e) {
113 const char *val = strchr(*e, '=');
114 /* Just say "no": on Unix, variables can contain function
115 * definitions. their value begins with "()"
117 if (val != NULL && val[1] == '(' && val[2] == ')') continue;
118 if (val != NULL) {
119 LIST *l = L0;
120 const char *pp, *p;
121 char split = ' ';
122 dstring_t buf;
123 /* get name */
124 dstr_init_buf(&buf, *e, val-*e);
125 if (!dontignore && globhit(varignores, dstr_cstr(&buf))) continue; /* ignore this */
126 /* split *PATH at :'s, not spaces */
127 if (val-4 >= *e) {
128 if (globhit(pathsplits, dstr_cstr(&buf))) {
129 split = (strncmp(dstr_cstr(&buf), "LUA_", 4) == 0 ? ';' : SPLITPATH); /* special for LUA_XXX */
132 /* do the split */
133 for (pp = val+1; (p = strchr(pp, split)); pp = p+1) {
134 int len = p-pp;
135 if (len > 0) {
136 dstr_clear(&buf);
137 dstr_push_buf(&buf, pp, len);
138 l = list_new(l, dstr_cstr(&buf), 0);
141 /* get name */
142 dstr_clear(&buf);
143 dstr_push_buf(&buf, *e, val-*e);
144 l = list_new(l, pp, 0);
145 var_set(dstr_cstr(&buf), l, VAR_SET);
146 dstr_done(&buf);
153 * var_string()
155 int var_string (const char *in, dstring_t *out, LOL *lol, char separator) {
156 int osz = dstr_len(out), lwpos;
157 const char *st;
158 while (*in) {
159 int dollar = 0;
160 /* copy white space */
161 st = in;
162 while (isspace(*in)) ++in;
163 dstr_push_memrange(out, st, in);
164 lwpos = dstr_len(out);
165 /* copy non-white space, watching for variables */
166 st = in;
167 while (*in && !isspace(*in)) {
168 if (in[0] == '$' && in[1] == '(') ++dollar;
169 ++in;
171 dstr_push_memrange(out, st, in);
172 /* if a variable encountered, expand it and and embed the space-separated members of the list in the output */
173 if (dollar) {
174 LIST *l = var_expand(L0, dstr_cstr(out)+lwpos, dstr_cstr(out)+dstr_len(out), lol, 0), *hd = l;
175 dstr_chop(out, lwpos);
176 while (l != NULL) {
177 dstr_push_cstr(out, l->string);
178 /* separate with space */
179 if ((l = list_next(l)) != NULL) dstr_push_char(out, separator);
181 list_free(hd);
184 return dstr_len(out)-osz;
189 * var_get()
191 LIST *var_get (const char *symbol) {
192 VARIABLE var, *v = &var;
193 v->symbol = symbol;
194 if (varhash && hashcheck(varhash, (HASHDATA **)&v)) {
195 if (DEBUG_VARGET) var_dump(v->symbol, v->value, "get");
196 return v->value;
198 return 0;
203 * var_set()
205 void var_set (const char *symbol, LIST *value, int flag) {
206 VARIABLE *v = var_enter(symbol);
207 if (DEBUG_VARSET) var_dump(symbol, value, "set");
208 switch(flag) {
209 case VAR_SET:
210 /* Replace value */
211 list_free(v->value);
212 v->value = value;
213 break;
214 case VAR_APPEND:
215 /* Append value */
216 v->value = list_append(v->value, value);
217 break;
218 case VAR_REMOVE:
219 /* Remove all values */
220 v->value = list_removeall(v->value, value);
221 list_free(value);
222 break;
223 case VAR_DEFAULT:
224 /* Set only if unset */
225 if (!v->value) v->value = value; else list_free(value);
226 break;
232 * var_swap()
234 LIST *var_swap (const char *symbol, LIST *value) {
235 VARIABLE *v = var_enter(symbol);
236 LIST *oldvalue = v->value;
237 if (DEBUG_VARSET) var_dump(symbol, value, "set");
238 v->value = value;
239 return oldvalue;
244 * var_done()
246 void var_done (void) {
247 hashdone(varhash);