bool Var_ParseSkip(const char **pstr, SymTable *ctxt) { const char *str = *pstr; struct Name name; bool result; bool has_modifier; const char *tstr = str; if (str[1] == 0) { *pstr = str+1; return false; } has_modifier = parse_base_variable_name(&tstr, &name, ctxt); VarName_Free(&name); result = true; if (has_modifier) { bool freePtr = false; char *s = VarModifiers_Apply(NULL, NULL, ctxt, true, &freePtr, &tstr, str[1]); if (s == var_Error) result = false; if (freePtr) free(s); } *pstr = tstr; return result; }
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; if (str[1] == 0) { *lengthPtr = 1; *freePtr = false; return err ? var_Error : varNoError; } 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; /* If it comes from a dynamic source, and it doesn't have * a context, copy the spec instead. * Specifically, this make allows constructs like: * target.o: $*.c * Absence of a context means "parsing". But these can't * be expanded during parsing, to be consistent with the * way .SUFFIXES work. * .SUFFIXES may be added/reset/removed during parsing, * but in the end, the final list is what's considered for * handling targets. So those dynamic variables must be * handled lazily too. */ if (idx != GLOBAL_INDEX) { if (ctxt == NULL) { *freePtr = true; val = Str_dupi(str, tstr); } else { bad_dynamic_variable(idx); } } } VarName_Free(&name); *lengthPtr = tstr - str; return val; }
/* Very quick version of the variable scanner that just looks for target * variables, and never ever errors out */ bool Var_Check_for_target(const char *str) { bool seen_target = false; for (;;) { const char *tstr; uint32_t k; int idx; bool has_modifier; struct Name name; /* skip over uninteresting stuff */ for (; *str != '\0' && *str != '$'; str++) ; if (*str == '\0') break; if (str[1] == '$') { /* A $ may be escaped with another $. */ str += 2; continue; } tstr = str; has_modifier = parse_base_variable_name(&tstr, &name, NULL); idx = classify_var(name.s, &name.e, &k); if (has_modifier) { bool doFree = false; char *val = VarModifiers_Apply(NULL, NULL, NULL, false, &doFree, &tstr, str[1]); if (doFree) free(val); } if (tlist[idx]) seen_target = true; VarName_Free(&name); str = tstr; } return seen_target; }
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; }