name.tofree = FALSE;
name.tofree = false;
Var_Parse(str, ctxt, err, lengthPtr, freePtr)    const char	*str;		/* The string to parse */    SymTable	*ctxt;		/* The context for the variable */    Boolean	err;		/* TRUE if undefined variables are an error */    size_t	*lengthPtr;	/* OUT: The length of the specification */    Boolean	*freePtr;	/* OUT: TRUE if caller should free result */{    const char	*tstr;		/* Pointer into str */    Var 	*v;		/* Variable in invocation */    char	endc;		/* Ending character when variable in parens				 * or braces */    struct Name	name;    const char	*start;    char	*val;		/* Variable value  */    u_int32_t	k;    int 	idx;    *freePtr = FALSE;    start = str++;    val = NULL;    v = NULL;    idx = -1;    if (*str != '(' && *str != '{') {    	name.s = str;	name.e = str+1;	name.tofree = FALSE;	tstr = str + 1;	*lengthPtr = 2;	endc = '\0';    } else {	endc = *str == '(' ? ')' : '}';	str++;	/* Find eventual modifiers in the variable */	tstr = Var_Name_Get(str, &name, ctxt, FALSE, find_pos(endc));	*lengthPtr = tstr - start;	if (*tstr != '\0')		(*lengthPtr)++;    }    idx = quick_lookup(name.s, &name.e, &k);    v = varfind(name.s, name.e, ctxt, FIND_ENV | FIND_MINE, idx, k);    if (v != NULL && (v->flags & VAR_DUMMY) == 0) {	if (v->flags & VAR_IN_USE)	    Fatal("Variable %s is recursive.", v->name);	    /*NOTREACHED*/	else	    v->flags |= VAR_IN_USE;	/* 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.  */	val = VarValue(v);	if (idx == -1) {	    if (strchr(val, '$') != NULL) {		val = Var_Subst(val, ctxt, err);		*freePtr = TRUE;	    }	} else if (idx >= LOCAL_SIZE) {	    if (IS_EXTENDED_F(idx))		val = Var_GetTail(val);	    else		val = Var_GetHead(val);	    *freePtr = TRUE;	}	v->flags &= ~VAR_IN_USE;    }    if (*tstr == ':' && endc != '\0')	val = VarModifiers_Apply(val, &name, ctxt, err, freePtr, tstr, endc,	    lengthPtr);    if (val == NULL) {	val = err ? var_Error : varNoError;	/* Dynamic source */	if (idx != -1) {	    /* can't be expanded for now: copy the var spec instead. */	    if (ctxt == NULL || ctxt == CTXT_GLOBAL || ctxt == CTXT_CMD) {		*freePtr = TRUE;		val = interval_dup(start, start+ *lengthPtr);	    } else {	    /* somehow, this should have been expanded already. */		GNode *n;		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->lineno, n->fname);		default:		    Error("Using undefined dynamic variable $%s (line %lu of %s)", 			varnames[idx], n->lineno, n->fname);		    break;		}	    }	}    }    Var_Name_Free(&name);    return val;}