extern "C" POETCode* make_varRef(POETCode* name, int config) { try { ASTFactory* fac = ASTFactory::inst(); if (name == fac->make_any()) return name; switch (config) { case CODE_VAR: return curfile->make_codeRef(name, 0); case XFORM_VAR: return curfile->make_xformVar(name); case CODE_OR_XFORM_VAR: { POETCode* res = find_code_or_xform_var(name); if (res != 0) return res; CODE_OR_XFORM_UNDEFINED(name->toString()); } case GLOBAL_SCOPE: { POETCode* res = find_code_or_xform_var(name); if (res != 0) return res; res = find_global_var(name); if (res != 0) return res; SYM_UNDEFINED(name->toString()); } case GLOBAL_VAR: { POETCode* res = find_code_or_xform_var(name); if (res != 0) return res; res = find_global_var(name); if (res != 0) return res; return curfile->make_evalVar(name); } case ID_DEFAULT: { LvarSymbolTable* local = top_scope(); POETCode* res = find_code_or_xform_var(name); if (res != 0) return res; if (local == 0) { res = find_global_var(name); if (res != 0) return res; return curfile->make_evalVar(name); } return POETProgram::make_localVar(local, name, LVAR_REG); } case ASSIGN_VAR: { LvarSymbolTable* local = top_scope(); POETCode* res = find_code_or_xform_var(name); if (res != 0) VAR_ASSIGN_ERROR(name->toString()); if (local == 0) { res = find_global_var(name); if (res != 0) return res; return curfile->make_evalVar(name); } return POETProgram::make_localVar(local, name, LVAR_REG); } default: std::cerr << "something is wrong with variable creation config: " << name->toString() << " config = " << config << "\n"; std::cerr << "At line " << yylineno << " of file " << curfile->get_filename() << "\n"; assert(0); } } catch (Error err) { std::cerr << "At line " << yylineno << " of file " << curfile->get_filename() << "\n"; exit(1); } }
/* mark variable as poisoned, in a given setup. */ void Var_MarkPoisoned(const char *name, const char *ename, unsigned int type) { Var *v; uint32_t k; int idx; idx = classify_var(name, &ename, &k); if (idx != GLOBAL_INDEX) { Parse_Error(PARSE_FATAL, "Trying to poison dynamic variable $%s", varnames[idx]); return; } v = find_global_var(name, ename, k); v->flags |= type; /* POISON_NORMAL is not lazy: if the variable already exists in * the Makefile, then it's a mistake. */ 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 Errcode po_gvar_del(Popot name) /***************************************************************************** * Errcode GlobalVarDelete(char *name); * delete the named variable. ****************************************************************************/ { Errcode err; Globalv *var; if (NULL == varlist) if (Success != (err = load_global_vars())) return err; if (name.pt == NULL) return builtin_err = Err_null_ref; if ((*(char *)name.pt) == 0x00) return Err_not_found; // naughty caller passed an empty string! if (NULL == (var = find_global_var(name.pt))) return Err_not_found; pj_free(var->value); var->name[0] = 0x00; if (++listchangecount) po_compact_global_vars(); return Success; }
static Errcode po_gvar_get(Popot name, Popot value) /***************************************************************************** * ErrCode GlobalVarGet(char *name, char *value); * search for the named variable and if found return its value in the * specified string. if not found, the return string is unchanged. ****************************************************************************/ { Globalv *var; Errcode err; if (NULL == varlist) if (Success != (err = load_global_vars())) return err; if (NULL == name.pt) return builtin_err = Err_null_ref; if (NULL == (var = find_global_var(name.pt))) return Err_not_found; if (Popot_bufcheck(&value, 1+strlen(var->value))) return builtin_err; strcpy(value.pt, var->value); return Success; }
static char * get_expanded_value(const char *name, const char *ename, int idx, uint32_t k, SymTable *ctxt, bool err, bool *freePtr) { char *val; /* Before doing any modification, we have to make sure the * value has been fully expanded. If it looks like recursion * might be necessary (there's a dollar sign somewhere in * the variable's value) we just call Var_Subst to do any * other substitutions that are necessary. Note that the * value returned by Var_Subst will have been dynamically * allocated, so it will need freeing when we return. */ 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) { push_used(v); val = Var_Subst(val, ctxt, err); pop_used(v); *freePtr = true; } } else { if (ctxt != NULL) { if (idx < LOCAL_SIZE) val = ctxt->locals[idx]; else 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; }
extern "C" POETCode* make_traceVar(POETCode* name, POETCode* inside) { assert(name != 0); try { POETCode* res = find_code_or_xform_var(name); if (res != 0) SYM_ALREADY_DEFINED(name->toString()); res = find_global_var(name); if (res != 0) SYM_ALREADY_DEFINED(name->toString()); LocalVar* var1 = curfile->make_traceVar(name); if (inside != 0) { LocalVar* var2 = dynamic_cast<LocalVar*>(inside); assert (var1 != 0 && var2 != 0); var1->get_entry().set_restr(var2); } return var1; } catch (Error err) { std::cerr << "At line " << yylineno << " of file " << curfile->get_filename() << "\n"; exit(1); } }
bool Var_Definedi(const char *name, const char *ename) { Var *v; uint32_t k; int idx; idx = classify_var(name, &ename, &k); /* We don't bother writing an error message for dynamic variables, * these will be caught when getting set later, usually. */ if (idx == GLOBAL_INDEX) { v = find_global_var(name, ename, k); if (v->flags & POISON_NORMAL) poison_check(v); if ((v->flags & VAR_DUMMY) == 0) return true; } return false; }
/* Set or add a global variable, in VAR_CMD or VAR_GLOBAL context. */ static void var_set_append(const char *name, const char *ename, const char *val, int ctxt, bool append) { Var *v; uint32_t k; int idx; idx = classify_var(name, &ename, &k); if (idx != GLOBAL_INDEX) { Parse_Error(PARSE_FATAL, "Trying to %s dynamic variable $%s", append ? "append to" : "set", varnames[idx]); return; } v = find_global_var(name, ename, k); if (v->flags & POISON_NORMAL) Parse_Error(PARSE_FATAL, "Trying to %s poisoned variable %s\n", append ? "append to" : "set", v->name); /* so can we write to it ? */ if (ctxt == VAR_CMD) { /* always for command line */ (append ? var_append_value : var_set_value)(v, val); v->flags |= VAR_FROM_CMD; if ((v->flags & VAR_SHELL) == 0) { /* Any variables given on the command line are * automatically exported to the environment, * except for SHELL (as per POSIX standard). */ esetenv(v->name, val); } if (DEBUG(VAR)) printf("command:%s = %s\n", v->name, var_get_value(v)); } else if ((v->flags & VAR_FROM_CMD) == 0 && (!checkEnvFirst || (v->flags & VAR_FROM_ENV) == 0)) { (append ? var_append_value : var_set_value)(v, val); if (DEBUG(VAR)) printf("global:%s = %s\n", v->name, var_get_value(v)); } else if (DEBUG(VAR)) printf("overridden:%s = %s\n", v->name, var_get_value(v)); }
/* XXX different semantics for Var_Valuei() and Var_Definedi(): * references to poisoned value variables will error out in Var_Valuei(), * but not in Var_Definedi(), so the following construct works: * .poison BINDIR * BINDIR ?= /usr/bin */ char * Var_Valuei(const char *name, const char *ename) { Var *v; uint32_t k; int idx; idx = classify_var(name, &ename, &k); if (idx != GLOBAL_INDEX) { Parse_Error(PARSE_FATAL, "Trying to get value of dynamic variable $%s", varnames[idx]); return NULL; } v = find_global_var(name, ename, k); if (v->flags & POISONS) poison_check(v); if ((v->flags & VAR_DUMMY) == 0) return var_get_value(v); else return NULL; }
static Errcode po_gvar_set(Popot name, Popot value) /***************************************************************************** * ErrCode GlobalVarSet(char *name, char *value); * set the named variable to the specified value. ****************************************************************************/ { Errcode err; Globalv *var; char *newvalue; if (NULL == varlist) if (Success != (err = load_global_vars())) return err; if (NULL == name.pt || NULL == value.pt) return builtin_err = Err_null_ref; if (strlen(name.pt) > MAX_VNAME_LEN || strlen(value.pt) > MAX_VVALUE_LEN) return builtin_err = Err_truncated; if (NULL == (var = find_global_var(name.pt))) { if (NULL == new_global_var(name.pt, value.pt)) return Err_no_memory; } else { if (strlen(value.pt) <= strlen(var->value)) { // copy in place if strcpy(var->value, value.pt); // it fits. } else { if (NULL == (newvalue = new_value(value.pt))) return Err_no_memory; pj_free(var->value); var->value = newvalue; } } if (++listchangecount > CHANGE_COUNT_LIMIT) po_compact_global_vars(); return Success; }