static void bad_dynamic_variable(int idx) { Location origin; Parse_FillLocation(&origin); if (idx >= LOCAL_SIZE) idx = EXTENDED2SIMPLE(idx); switch(idx) { case IMPSRC_INDEX: if (origin.fname) Fatal(ERRMSG1 "(%s:%lu)", origin.fname, origin.lineno); else if (current_node) Fatal(ERRMSG1 "(prereq of %s)", current_node->name); else Fatal(ERRMSG1 "(?)"); break; default: if (origin.fname) Error(ERRMSG2 "(%s:%lu)", varnames[idx], origin.fname, origin.lineno); else if (current_node) Error(ERRMSG2 "(prereq of %s)", varnames[idx], current_node->name); else Error(ERRMSG2 "(?)", varnames[idx]); break; } }
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; }
char * Var_Parse(const char *str, /* The string to parse */ SymTable *ctxt, /* The context for the variable */ bool err, /* true if undefined variables are an error */ size_t *lengthPtr, /* OUT: The length of the specification */ bool *freePtr) /* OUT: true if caller should free result */ { const char *tstr; struct Name name; char *val; uint32_t k; int idx; bool has_modifier; *freePtr = false; tstr = str; has_modifier = parse_base_variable_name(&tstr, &name, ctxt); idx = classify_var(name.s, &name.e, &k); val = get_expanded_value(name.s, name.e, idx, k, ctxt, err, freePtr); if (has_modifier) { val = VarModifiers_Apply(val, &name, ctxt, err, freePtr, &tstr, str[1]); } if (val == NULL) { val = err ? var_Error : varNoError; /* Dynamic source */ if (idx != GLOBAL_INDEX) { /* can't be expanded for now: copy the spec instead. */ if (ctxt == NULL) { *freePtr = true; val = Str_dupi(str, tstr); } else { /* somehow, this should have been expanded already. */ GNode *n; /* XXX */ n = (GNode *)(((char *)ctxt) - offsetof(GNode, context)); if (idx >= LOCAL_SIZE) idx = EXTENDED2SIMPLE(idx); switch(idx) { case IMPSRC_INDEX: Fatal( "Using $< in a non-suffix rule context is a GNUmake idiom (line %lu of %s)", n->origin.lineno, n->origin.fname); break; default: Error( "Using undefined dynamic variable $%s (line %lu of %s)", varnames[idx], n->origin.lineno, n->origin.fname); break; } } } } VarName_Free(&name); *lengthPtr = tstr - str; return val; }