version 1.64, 2007/07/08 17:53:15 |
version 1.65, 2007/07/20 12:18:47 |
|
|
#include "symtable.h" |
#include "symtable.h" |
#include "gnode.h" |
#include "gnode.h" |
|
|
/* extended indices for System V stuff */ |
|
#define FTARGET_INDEX 7 |
|
#define DTARGET_INDEX 8 |
|
#define FPREFIX_INDEX 9 |
|
#define DPREFIX_INDEX 10 |
|
#define FARCHIVE_INDEX 11 |
|
#define DARCHIVE_INDEX 12 |
|
#define FMEMBER_INDEX 13 |
|
#define DMEMBER_INDEX 14 |
|
|
|
#define EXTENDED2SIMPLE(i) (((i)-LOCAL_SIZE)/2) |
|
#define IS_EXTENDED_F(i) ((i)%2 == 1) |
|
|
|
/* |
/* |
* This is a harmless return value for Var_Parse that can be used by Var_Subst |
* This is a harmless return value for Var_Parse that can be used by Var_Subst |
* to determine if there was an error in parsing -- easier than returning |
* to determine if there was an error in parsing -- easier than returning |
|
|
* listed. |
* listed. |
*/ |
*/ |
|
|
static struct ohash global_variables; |
|
|
|
static char *varnames[] = { |
static char *varnames[] = { |
TARGET, |
TARGET, |
PREFIX, |
PREFIX, |
|
|
DMEMBER |
DMEMBER |
}; |
}; |
|
|
|
/* retrieve the hashed values for well-known variables. */ |
|
#include "varhashconsts.h" |
|
|
|
/* extended indices for System V stuff */ |
|
#define FTARGET_INDEX 7 |
|
#define DTARGET_INDEX 8 |
|
#define FPREFIX_INDEX 9 |
|
#define DPREFIX_INDEX 10 |
|
#define FARCHIVE_INDEX 11 |
|
#define DARCHIVE_INDEX 12 |
|
#define FMEMBER_INDEX 13 |
|
#define DMEMBER_INDEX 14 |
|
|
|
#define EXTENDED2SIMPLE(i) (((i)-LOCAL_SIZE)/2) |
|
#define IS_EXTENDED_F(i) ((i)%2 == 1) |
|
|
|
static struct ohash global_variables; |
|
|
typedef struct Var_ { |
typedef struct Var_ { |
BUFFER val; /* its value */ |
BUFFER val; /* its value */ |
unsigned int flags; /* miscellaneous status flags */ |
unsigned int flags; /* miscellaneous status flags */ |
|
|
typedef const char * (*find_t)(const char *); |
typedef const char * (*find_t)(const char *); |
static find_t find_pos(int); |
static find_t find_pos(int); |
|
|
/* retrieve the hashed values for well-known variables. */ |
|
#include "varhashconsts.h" |
|
|
|
void |
|
SymTable_Init(SymTable *ctxt) |
|
{ |
|
static SymTable sym_template; |
|
memcpy(ctxt, &sym_template, sizeof(*ctxt)); |
|
} |
|
|
|
#ifdef CLEANUP |
|
void |
|
SymTable_Destroy(SymTable *ctxt) |
|
{ |
|
int i; |
|
|
|
for (i = 0; i < LOCAL_SIZE; i++) |
|
if (ctxt->locals[i] != NULL) |
|
VarDelete(ctxt->locals[i]); |
|
} |
|
#endif |
|
|
|
static int |
static int |
quick_lookup(const char *name, const char **enamePtr, uint32_t *pk) |
quick_lookup(const char *name, const char **enamePtr, uint32_t *pk) |
{ |
{ |
|
|
return -1; |
return -1; |
} |
} |
|
|
|
static Var * |
|
create_var(const char *name, const char *ename) |
|
{ |
|
return ohash_create_entry(&var_info, name, &ename); |
|
} |
|
|
|
/* Set the initial value a var should have */ |
static void |
static void |
|
var_init_string(Var *v, const char *val) |
|
{ |
|
size_t len; |
|
|
|
len = strlen(val); |
|
Buf_Init(&(v->val), len+1); |
|
Buf_AddChars(&(v->val), len, val); |
|
} |
|
|
|
static void |
|
var_set_string(Var *v, const char *val) |
|
{ |
|
if ((v->flags & VAR_DUMMY) == 0) { |
|
Buf_Reset(&(v->val)); |
|
Buf_AddString(&(v->val), val); |
|
} else { |
|
var_init_string(v, val); |
|
v->flags &= ~VAR_DUMMY; |
|
} |
|
} |
|
|
|
static void |
|
var_append_string(Var *v, const char *val) |
|
{ |
|
if ((v->flags & VAR_DUMMY) == 0) { |
|
Buf_AddSpace(&(v->val)); |
|
Buf_AddString(&(v->val), val); |
|
} else { |
|
var_init_string(v, val); |
|
v->flags &= ~VAR_DUMMY; |
|
} |
|
} |
|
|
|
/*- |
|
*----------------------------------------------------------------------- |
|
* VarDelete -- |
|
* Delete a variable and all the space associated with it. |
|
*----------------------------------------------------------------------- |
|
*/ |
|
static void |
|
VarDelete(Var *v) |
|
{ |
|
if ((v->flags & VAR_DUMMY) == 0) |
|
Buf_Destroy(&(v->val)); |
|
free(v); |
|
} |
|
|
|
|
|
|
|
void |
|
SymTable_Init(SymTable *ctxt) |
|
{ |
|
static SymTable sym_template; |
|
memcpy(ctxt, &sym_template, sizeof(*ctxt)); |
|
} |
|
|
|
#ifdef CLEANUP |
|
void |
|
SymTable_Destroy(SymTable *ctxt) |
|
{ |
|
int i; |
|
|
|
for (i = 0; i < LOCAL_SIZE; i++) |
|
if (ctxt->locals[i] != NULL) |
|
VarDelete(ctxt->locals[i]); |
|
} |
|
#endif |
|
|
|
static void |
varq_set_append(int idx, const char *val, GNode *gn, bool append) |
varq_set_append(int idx, const char *val, GNode *gn, bool append) |
{ |
{ |
Var *v = gn->context.locals[idx]; |
Var *v = gn->context.locals[idx]; |
|
|
} |
} |
|
|
static Var * |
static Var * |
create_var(const char *name, const char *ename) |
obtain_global_var(const char *name, const char *ename, uint32_t k) |
{ |
{ |
return ohash_create_entry(&var_info, name, &ename); |
unsigned int slot; |
} |
Var *v; |
|
|
/* Set the initial value a var should have */ |
slot = ohash_lookup_interval(&global_variables, name, ename, k); |
static void |
v = ohash_find(&global_variables, slot); |
var_init_string(Var *v, const char *val) |
if (v == NULL) { |
{ |
v = create_var(name, ename); |
size_t len; |
v->flags = VAR_DUMMY; |
|
ohash_insert(&global_variables, slot, v); |
len = strlen(val); |
} |
Buf_Init(&(v->val), len+1); |
return v; |
Buf_AddChars(&(v->val), len, val); |
|
} |
} |
|
|
static void |
static void |
var_set_string(Var *v, const char *val) |
|
{ |
|
if ((v->flags & VAR_DUMMY) == 0) { |
|
Buf_Reset(&(v->val)); |
|
Buf_AddString(&(v->val), val); |
|
} else { |
|
var_init_string(v, val); |
|
v->flags &= ~VAR_DUMMY; |
|
} |
|
} |
|
|
|
static void |
|
var_append_string(Var *v, const char *val) |
|
{ |
|
if ((v->flags & VAR_DUMMY) == 0) { |
|
Buf_AddSpace(&(v->val)); |
|
Buf_AddString(&(v->val), val); |
|
} else { |
|
var_init_string(v, val); |
|
v->flags &= ~VAR_DUMMY; |
|
} |
|
} |
|
|
|
static void |
|
fill_from_env(Var *v) |
fill_from_env(Var *v) |
{ |
{ |
char *env; |
char *env; |
|
|
} |
} |
|
|
static Var * |
static Var * |
obtain_global_var(const char *name, const char *ename, uint32_t k) |
find_global_var(const char *name, const char *ename, uint32_t k) |
{ |
{ |
unsigned int slot; |
Var *v; |
Var *v; |
|
|
|
slot = ohash_lookup_interval(&global_variables, name, ename, k); |
v = obtain_global_var(name, ename, k); |
v = ohash_find(&global_variables, slot); |
|
if (v == NULL) { |
if ((v->flags & VAR_SEEN_ENV) == 0 && |
v = create_var(name, ename); |
(checkEnvFirst && (v->flags & VAR_FROM_CMD) == 0 || |
v->flags = VAR_DUMMY; |
(v->flags & VAR_DUMMY) != 0)) |
ohash_insert(&global_variables, slot, v); |
fill_from_env(v); |
|
|
|
return v; |
|
} |
|
|
|
|
|
void |
|
Var_MarkPoisoned(const char *name, const char *ename, unsigned int type) |
|
{ |
|
Var *v; |
|
uint32_t k; |
|
int idx; |
|
idx = quick_lookup(name, &ename, &k); |
|
|
|
if (idx != -1) { |
|
Parse_Error(PARSE_FATAL, |
|
"Trying to poison dynamic variable $%s", |
|
varnames[idx]); |
|
return; |
} |
} |
return v; |
|
|
v = find_global_var(name, ename, k); |
|
v->flags |= type; |
|
if (v->flags & POISON_NORMAL) { |
|
if (v->flags & VAR_DUMMY) |
|
return; |
|
if (v->flags & VAR_FROM_ENV) |
|
return; |
|
Parse_Error(PARSE_FATAL, |
|
"Poisoned variable %s is already set\n", v->name); |
|
} |
} |
} |
|
|
static void |
static void |
|
|
"Poisoned variable %s is empty\n", v->name); |
"Poisoned variable %s is empty\n", v->name); |
} |
} |
|
|
static Var * |
|
find_global_var(const char *name, const char *ename, uint32_t k) |
|
{ |
|
Var *v; |
|
|
|
v = obtain_global_var(name, ename, k); |
|
|
|
if ((v->flags & VAR_SEEN_ENV) == 0 && |
|
(checkEnvFirst && (v->flags & VAR_FROM_CMD) == 0 || |
|
(v->flags & VAR_DUMMY) != 0)) |
|
fill_from_env(v); |
|
|
|
return v; |
|
} |
|
|
|
static Var * |
|
varfind(const char *name, const char *ename, SymTable *ctxt, |
|
int idx, uint32_t k) |
|
{ |
|
/* Handle local variables first */ |
|
if (idx != -1) { |
|
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); |
|
} |
|
} |
|
|
|
/*- |
|
*----------------------------------------------------------------------- |
|
* VarDelete -- |
|
* Delete a variable and all the space associated with it. |
|
*----------------------------------------------------------------------- |
|
*/ |
|
static void |
|
VarDelete(Var *v) |
|
{ |
|
if ((v->flags & VAR_DUMMY) == 0) |
|
Buf_Destroy(&(v->val)); |
|
free(v); |
|
} |
|
|
|
|
|
|
|
void |
void |
Var_Delete(const char *name) |
Var_Delete(const char *name) |
{ |
{ |
|
|
var_set_append(name, ename, val, ctxt, true); |
var_set_append(name, ename, val, ctxt, true); |
} |
} |
|
|
void |
|
Var_MarkPoisoned(const char *name, const char *ename, unsigned int type) |
|
{ |
|
Var *v; |
|
uint32_t k; |
|
int idx; |
|
idx = quick_lookup(name, &ename, &k); |
|
|
|
if (idx != -1) { |
|
Parse_Error(PARSE_FATAL, |
|
"Trying to poison dynamic variable $%s", |
|
varnames[idx]); |
|
return; |
|
} |
|
|
|
v = find_global_var(name, ename, k); |
|
v->flags |= type; |
|
if (v->flags & POISON_NORMAL) { |
|
if (v->flags & VAR_DUMMY) |
|
return; |
|
if (v->flags & VAR_FROM_ENV) |
|
return; |
|
Parse_Error(PARSE_FATAL, |
|
"Poisoned variable %s is already set\n", v->name); |
|
} |
|
} |
|
|
|
char * |
char * |
Var_Valuei(const char *name, const char *ename) |
Var_Valuei(const char *name, const char *ename) |
{ |
{ |
|
|
} |
} |
|
|
return false; |
return false; |
|
} |
|
|
|
static Var * |
|
varfind(const char *name, const char *ename, SymTable *ctxt, |
|
int idx, uint32_t k) |
|
{ |
|
/* Handle local variables first */ |
|
if (idx != -1) { |
|
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); |
|
} |
} |
} |
|
|
static const char * |
static const char * |