errorReported = FALSE;
errorReported = false;
Var_Subst(str, ctxt, undefErr)    const char	  *str; 	    /* the string in which to substitute */    SymTable	  *ctxt;	    /* the context wherein to find variables */    Boolean	  undefErr;	    /* TRUE if undefineds are an error */{    BUFFER	  buf;		    /* Buffer for forming things */    static Boolean errorReported;   /* Set true if an error has already				     * been reported to prevent a plethora				     * of messages when recursing */    Buf_Init(&buf, MAKE_BSIZE);    errorReported = FALSE;    for (;;) {	char		*val;		/* Value to substitute for a variable */	size_t		length; 	/* Length of the variable invocation */	Boolean 	doFree; 	/* Set true if val should be freed */	const char *cp;	/* copy uninteresting stuff */	for (cp = str; *str != '\0' && *str != '$'; str++)	    ;	Buf_AddInterval(&buf, cp, str);	if (*str == '\0')	    break;	if (str[1] == '$') {	    /* A dollar sign may be escaped with another dollar sign.  */	    Buf_AddChar(&buf, '$');	    str += 2;	    continue;	}	val = Var_Parse(str, ctxt, undefErr, &length, &doFree);	/* When we come down here, val should either point to the	 * value of this variable, suitably modified, or be NULL.	 * Length should be the total length of the potential	 * variable invocation (from $ to end character...) */	if (val == var_Error || val == varNoError) {	    /* If performing old-time variable substitution, skip over	     * the variable and continue with the substitution. Otherwise,	     * store the dollar sign and advance str so we continue with	     * the string...  */	    if (oldVars)		str += length;	    else if (undefErr) {		/* If variable is undefined, complain and skip the		 * variable. The complaint will stop us from doing anything		 * when the file is parsed.  */		if (!errorReported)		    Parse_Error(PARSE_FATAL,				 "Undefined variable \"%.*s\"",length,str);		str += length;		errorReported = TRUE;	    } else {		Buf_AddChar(&buf, *str);		str++;	    }	} else {	    /* We've now got a variable structure to store in. But first,	     * advance the string pointer.  */	    str += length;	    /* Copy all the characters from the variable value straight	     * into the new string.  */	    Buf_AddString(&buf, val);	    if (doFree)		free(val);	}    }    return  Buf_Retrieve(&buf);}