version 1.82, 2007/11/04 09:31:57 |
version 1.83, 2007/11/17 16:39:45 |
|
|
}; |
}; |
|
|
static int classify_var(const char *, const char **, uint32_t *); |
static int classify_var(const char *, const char **, uint32_t *); |
static Var *find_any_var(const char *, const char *, SymTable *, int, uint32_t); |
|
static Var *find_global_var(const char *, const char *, uint32_t); |
static Var *find_global_var(const char *, const char *, uint32_t); |
static Var *find_global_var_without_env(const char *, const char *, uint32_t); |
static Var *find_global_var_without_env(const char *, const char *, uint32_t); |
static void fill_from_env(Var *); |
static void fill_from_env(Var *); |
|
|
#define var_get_value(v) Buf_Retrieve(&((v)->val)) |
#define var_get_value(v) Buf_Retrieve(&((v)->val)) |
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 varq_set_append(int, const char *, GNode *, bool); |
|
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); |
static void set_magic_shell_variable(void); |
static void set_magic_shell_variable(void); |
|
|
|
|
static find_t find_pos(int); |
static find_t find_pos(int); |
static void push_used(Var *); |
static void push_used(Var *); |
static void pop_used(Var *); |
static void pop_used(Var *); |
static char *get_expanded_value(Var *, int, SymTable *, bool, bool *); |
static char *get_expanded_value(const char *, const char *, int, uint32_t, |
|
SymTable *, bool, bool *); |
static bool parse_base_variable_name(const char **, struct Name *, SymTable *); |
static bool parse_base_variable_name(const char **, struct Name *, SymTable *); |
|
|
|
|
|
|
} |
} |
#endif |
#endif |
|
|
/* set or append to dynamic variable. |
|
*/ |
|
static void |
|
varq_set_append(int idx, const char *val, GNode *gn, bool append) |
|
{ |
|
Var *v = gn->context.locals[idx]; |
|
|
|
if (v == NULL) { |
|
v = create_var(varnames[idx], NULL); |
|
#ifdef STATS_VAR_LOOKUP |
|
STAT_VAR_CREATION++; |
|
#endif |
|
if (val != NULL) |
|
var_set_initial_value(v, val); |
|
else |
|
Buf_Init(&(v->val), 1); |
|
v->flags = 0; |
|
gn->context.locals[idx] = v; |
|
} else { |
|
if (append) |
|
Buf_AddSpace(&(v->val)); |
|
else |
|
Buf_Reset(&(v->val)); |
|
Buf_AddString(&(v->val), val); |
|
} |
|
if (DEBUG(VAR)) |
|
printf("%s:%s = %s\n", gn->name, varnames[idx], |
|
var_get_value(v)); |
|
} |
|
|
|
void |
|
Varq_Set(int idx, const char *val, GNode *gn) |
|
{ |
|
varq_set_append(idx, val, gn, false); |
|
} |
|
|
|
void |
|
Varq_Append(int idx, const char *val, GNode *gn) |
|
{ |
|
varq_set_append(idx, val, gn, true); |
|
} |
|
|
|
char * |
|
Varq_Value(int idx, GNode *gn) |
|
{ |
|
Var *v = gn->context.locals[idx]; |
|
|
|
if (v == NULL) |
|
return NULL; |
|
else |
|
return var_get_value(v); |
|
} |
|
|
|
/*** |
/*** |
*** Global variable handling. |
*** Global variable handling. |
***/ |
***/ |
|
|
***/ |
***/ |
|
|
|
|
/* XXX contrary to find_global_var(), find_any_var() can return NULL pointers. |
|
*/ |
|
static Var * |
|
find_any_var(const char *name, const char *ename, SymTable *ctxt, |
|
int idx, uint32_t k) |
|
{ |
|
/* Handle local variables first */ |
|
if (idx != GLOBAL_INDEX) { |
|
if (ctxt != NULL) { |
|
if (idx < LOCAL_SIZE) |
|
return ctxt->locals[idx]; |
|
else |
|
return ctxt->locals[EXTENDED2SIMPLE(idx)]; |
|
} else |
|
return NULL; |
|
} else { |
|
return find_global_var(name, ename, k); |
|
} |
|
} |
|
|
|
/* All the scanning functions needed to account for all the forms of |
/* All the scanning functions needed to account for all the forms of |
* variable names that exist: |
* variable names that exist: |
* $A, ${AB}, $(ABC), ${A:mod}, $(A:mod) |
* $A, ${AB}, $(ABC), ${A:mod}, $(A:mod) |
|
|
} |
} |
|
|
static char * |
static char * |
get_expanded_value(Var *v, int idx, SymTable *ctxt, bool err, bool *freePtr) |
get_expanded_value(const char *name, const char *ename, int idx, uint32_t k, |
|
SymTable *ctxt, bool err, bool *freePtr) |
{ |
{ |
char *val; |
char *val; |
|
|
if (v == NULL) |
|
return NULL; |
|
|
|
if ((v->flags & POISONS) != 0) |
|
poison_check(v); |
|
if ((v->flags & VAR_DUMMY) != 0) |
|
return NULL; |
|
|
|
/* Before doing any modification, we have to make sure the |
/* Before doing any modification, we have to make sure the |
* value has been fully expanded. If it looks like recursion |
* value has been fully expanded. If it looks like recursion |
* might be necessary (there's a dollar sign somewhere in |
* might be necessary (there's a dollar sign somewhere in |
|
|
* value returned by Var_Subst will have been dynamically |
* value returned by Var_Subst will have been dynamically |
* allocated, so it will need freeing when we return. |
* allocated, so it will need freeing when we return. |
*/ |
*/ |
val = var_get_value(v); |
|
if (idx == GLOBAL_INDEX) { |
if (idx == GLOBAL_INDEX) { |
|
Var *v = find_global_var(name, ename, k); |
|
|
|
if (v == NULL) |
|
return NULL; |
|
|
|
if ((v->flags & POISONS) != 0) |
|
poison_check(v); |
|
if ((v->flags & VAR_DUMMY) != 0) |
|
return NULL; |
|
|
|
val = var_get_value(v); |
if (strchr(val, '$') != NULL) { |
if (strchr(val, '$') != NULL) { |
push_used(v); |
push_used(v); |
val = Var_Subst(val, ctxt, err); |
val = Var_Subst(val, ctxt, err); |
pop_used(v); |
pop_used(v); |
*freePtr = true; |
*freePtr = true; |
} |
} |
} else if (idx >= LOCAL_SIZE) { |
} else { |
if (IS_EXTENDED_F(idx)) |
if (ctxt != NULL) { |
val = Var_GetTail(val); |
if (idx < LOCAL_SIZE) |
else |
val = ctxt->locals[idx]; |
val = Var_GetHead(val); |
else |
*freePtr = true; |
val = ctxt->locals[EXTENDED2SIMPLE(idx)]; |
|
} else |
|
val = NULL; |
|
if (val == NULL) |
|
return NULL; |
|
|
|
if (idx >= LOCAL_SIZE) { |
|
if (IS_EXTENDED_F(idx)) |
|
val = Var_GetTail(val); |
|
else |
|
val = Var_GetHead(val); |
|
*freePtr = true; |
|
} |
} |
} |
return val; |
return val; |
} |
} |
|
|
bool *freePtr) /* OUT: true if caller should free result */ |
bool *freePtr) /* OUT: true if caller should free result */ |
{ |
{ |
const char *tstr; |
const char *tstr; |
Var *v; |
|
struct Name name; |
struct Name name; |
char *val; |
char *val; |
uint32_t k; |
uint32_t k; |
|
|
has_modifier = parse_base_variable_name(&tstr, &name, ctxt); |
has_modifier = parse_base_variable_name(&tstr, &name, ctxt); |
|
|
idx = classify_var(name.s, &name.e, &k); |
idx = classify_var(name.s, &name.e, &k); |
v = find_any_var(name.s, name.e, ctxt, idx, k); |
val = get_expanded_value(name.s, name.e, idx, k, ctxt, err, freePtr); |
val = get_expanded_value(v, idx, ctxt, err, freePtr); |
|
if (has_modifier) { |
if (has_modifier) { |
val = VarModifiers_Apply(val, &name, ctxt, err, freePtr, |
val = VarModifiers_Apply(val, &name, ctxt, err, freePtr, |
&tstr, str[1]); |
&tstr, str[1]); |