version 1.104, 2022/06/09 13:13:14 |
version 1.105, 2023/08/10 10:52:43 |
|
|
bool errorIsOkay; |
bool errorIsOkay; |
static bool checkEnvFirst; /* true if environment should be searched for |
static bool checkEnvFirst; /* true if environment should be searched for |
* variables before the global context */ |
* variables before the global context */ |
|
/* do we need to recompute varname_list */ |
|
static bool varname_list_changed = true; |
|
|
void |
void |
Var_setCheckEnvFirst(bool yes) |
Var_setCheckEnvFirst(bool yes) |
|
|
#define VAR_FROM_ENV 8 /* Special source: environment */ |
#define VAR_FROM_ENV 8 /* Special source: environment */ |
#define VAR_SEEN_ENV 16 /* No need to go look up environment again */ |
#define VAR_SEEN_ENV 16 /* No need to go look up environment again */ |
#define VAR_IS_SHELL 32 /* Magic behavior */ |
#define VAR_IS_SHELL 32 /* Magic behavior */ |
|
#define VAR_IS_NAMES 1024 /* Very expensive, only defined when needed */ |
/* XXX there are also some flag values which are part of the visible API |
/* XXX there are also some flag values which are part of the visible API |
* and thus defined inside var.h, don't forget to look there if you want |
* and thus defined inside var.h, don't forget to look there if you want |
* to define some new flags ! |
* to define some new flags ! |
|
|
char name[1]; /* the variable's name */ |
char name[1]; /* the variable's name */ |
} Var; |
} Var; |
|
|
|
/* for GNU make compatibility */ |
|
#define VARNAME_LIST ".VARIABLES" |
|
|
static struct ohash_info var_info = { |
static struct ohash_info var_info = { |
offsetof(Var, name), |
offsetof(Var, name), |
|
|
static Var *create_var(const char *, const char *); |
static Var *create_var(const char *, const char *); |
static void var_set_initial_value(Var *, const char *); |
static void var_set_initial_value(Var *, const char *); |
static void var_set_value(Var *, const char *); |
static void var_set_value(Var *, const char *); |
#define var_get_value(v) ((v)->flags & VAR_EXEC_LATER ? \ |
static char *var_get_value(Var *); |
var_exec_cmd(v) : \ |
static void var_exec_cmd(Var *); |
Buf_Retrieve(&((v)->val))) |
static void varname_list_retrieve(Var *); |
static char *var_exec_cmd(Var *); |
|
|
|
static void var_append_value(Var *, const char *); |
static void var_append_value(Var *, const char *); |
static void poison_check(Var *); |
static void poison_check(Var *); |
static void var_set_append(const char *, const char *, const char *, int, bool); |
static void var_set_append(const char *, const char *, const char *, int, bool); |
|
|
len = strlen(val); |
len = strlen(val); |
Buf_Init(&(v->val), len+1); |
Buf_Init(&(v->val), len+1); |
Buf_AddChars(&(v->val), len, val); |
Buf_AddChars(&(v->val), len, val); |
|
varname_list_changed = true; |
} |
} |
|
|
/* Normal version of var_set_value(), to be called after variable is fully |
/* Normal version of var_set_value(), to be called after variable is fully |
|
|
} |
} |
} |
} |
|
|
|
static char * |
|
var_get_value(Var *v) |
|
{ |
|
if (v->flags & VAR_IS_NAMES) |
|
varname_list_retrieve(v); |
|
else if (v->flags & VAR_EXEC_LATER) |
|
var_exec_cmd(v); |
|
return Buf_Retrieve(&(v->val)); |
|
} |
|
|
/* Add to a variable, insert a separating space if the variable was already |
/* Add to a variable, insert a separating space if the variable was already |
* defined. |
* defined. |
*/ |
*/ |
|
|
|
|
ohash_remove(&global_variables, slot); |
ohash_remove(&global_variables, slot); |
delete_var(v); |
delete_var(v); |
|
varname_list_changed = true; |
} |
} |
|
|
/* Set or add a global variable, either to VAR_CMD or VAR_GLOBAL. |
/* Set or add a global variable, either to VAR_CMD or VAR_GLOBAL. |
|
|
var_set_append(name, ename, val, ctxt, true); |
var_set_append(name, ename, val, ctxt, true); |
} |
} |
|
|
static char * |
static void |
var_exec_cmd(Var *v) |
var_exec_cmd(Var *v) |
{ |
{ |
char *arg = Buf_Retrieve(&(v->val)); |
char *arg = Buf_Retrieve(&(v->val)); |
|
|
var_set_value(v, res1); |
var_set_value(v, res1); |
free(res1); |
free(res1); |
v->flags &= ~VAR_EXEC_LATER; |
v->flags &= ~VAR_EXEC_LATER; |
return Buf_Retrieve(&(v->val)); |
|
} |
} |
|
|
|
static void |
|
varname_list_retrieve(Var *v) |
|
{ |
|
unsigned int i; |
|
void *e; |
|
bool first = true; |
|
|
|
if (!varname_list_changed) |
|
return; |
|
for (e = ohash_first(&global_variables, &i); e != NULL; |
|
e = ohash_next(&global_variables, &i)) { |
|
Var *v2 = e; |
|
if (v2->flags & VAR_DUMMY) |
|
continue; |
|
|
|
if (first) |
|
var_set_value(v, v2->name); |
|
else |
|
var_append_value(v, v2->name); |
|
first = false; |
|
} |
|
varname_list_changed = false; |
|
} |
|
|
/* XXX different semantics for Var_Valuei() and Var_Definedi(): |
/* XXX different semantics for Var_Valuei() and Var_Definedi(): |
* references to poisoned value variables will error out in Var_Valuei(), |
* references to poisoned value variables will error out in Var_Valuei(), |
* but not in Var_Definedi(), so the following construct works: |
* but not in Var_Definedi(), so the following construct works: |
|
|
v->flags = VAR_IS_SHELL | VAR_SEEN_ENV; |
v->flags = VAR_IS_SHELL | VAR_SEEN_ENV; |
} |
} |
|
|
|
static void |
|
set_magic_name_list_variable() |
|
{ |
|
const char *name = VARNAME_LIST; |
|
const char *ename = NULL; |
|
uint32_t k; |
|
Var *v; |
|
|
|
k = ohash_interval(name, &ename); |
|
v = find_global_var_without_env(name, ename, k); |
|
/* XXX We need to set a "dummy" value because that variable can't be |
|
* VAR_DUMMY, since we wouldn't hit var_get_value otherwise. |
|
*/ |
|
var_set_initial_value(v, ""); |
|
v->flags = VAR_IS_NAMES; |
|
} |
/* |
/* |
* Var_Init |
* Var_Init |
* Initialize the module |
* Initialize the module |
|
|
{ |
{ |
ohash_init(&global_variables, 10, &var_info); |
ohash_init(&global_variables, 10, &var_info); |
set_magic_shell_variable(); |
set_magic_shell_variable(); |
|
set_magic_name_list_variable(); |
|
|
|
|
errorIsOkay = true; |
errorIsOkay = true; |
Var_setCheckEnvFirst(false); |
Var_setCheckEnvFirst(false); |
|
|
VarModifiers_Init(); |
VarModifiers_Init(); |
Buf_Init(&subst_buffer, MAKE_BSIZE); |
Buf_Init(&subst_buffer, MAKE_BSIZE); |
} |
} |