* addSpace is set to FALSE as soon as a space is added to the
* addSpace is set to false as soon as a space is added to the
VarSubstitute(word, addSpace, buf, patternp)    struct Name *word;    Boolean	addSpace;    Buffer	buf;    void	*patternp;	/* Pattern for substitution */{    size_t	wordLen;    /* Length of word */    const char	*cp;	    /* General pointer */    VarPattern	*pattern = (VarPattern *)patternp;    wordLen = word->e - word->s;    if ((pattern->flags & (VAR_SUB_ONE|VAR_SUB_MATCHED)) !=	(VAR_SUB_ONE|VAR_SUB_MATCHED)) {	/* Still substituting -- break it down into simple anchored cases	 * and if none of them fits, perform the general substitution case.  */	if ((pattern->flags & VAR_MATCH_START) &&	    (strncmp(word->s, pattern->lhs, pattern->leftLen) == 0)) {		/* Anchored at start and beginning of word matches pattern.  */		if ((pattern->flags & VAR_MATCH_END) &&		    (wordLen == pattern->leftLen)) {			/* Also anchored at end and matches to the end (word			 * is same length as pattern) add space and rhs only			 * if rhs is non-null.	*/			if (pattern->rightLen != 0) {			    if (addSpace)				Buf_AddSpace(buf);			    addSpace = TRUE;			    Buf_AddChars(buf, pattern->rightLen,					 pattern->rhs);			}			pattern->flags |= VAR_SUB_MATCHED;		} else if (pattern->flags & VAR_MATCH_END) {		    /* Doesn't match to end -- copy word wholesale.  */		    goto nosub;		} else {		    /* Matches at start but need to copy in		     * trailing characters.  */		    if ((pattern->rightLen + wordLen - pattern->leftLen) != 0){			if (addSpace)			    Buf_AddSpace(buf);			addSpace = TRUE;		    }		    Buf_AddChars(buf, pattern->rightLen, pattern->rhs);		    Buf_AddChars(buf, wordLen - pattern->leftLen,				 word->s + pattern->leftLen);		    pattern->flags |= VAR_SUB_MATCHED;		}	} else if (pattern->flags & VAR_MATCH_START) {	    /* Had to match at start of word and didn't -- copy whole word.  */	    goto nosub;	} else if (pattern->flags & VAR_MATCH_END) {	    /* Anchored at end, Find only place match could occur (leftLen	     * characters from the end of the word) and see if it does. Note	     * that because the $ will be left at the end of the lhs, we have	     * to use strncmp.	*/	    cp = word->s + (wordLen - pattern->leftLen);	    if (cp >= word->s &&		strncmp(cp, pattern->lhs, pattern->leftLen) == 0) {		/* Match found. If we will place characters in the buffer,		 * add a space before hand as indicated by addSpace, then		 * stuff in the initial, unmatched part of the word followed		 * by the right-hand-side.  */		if (((cp - word->s) + pattern->rightLen) != 0) {		    if (addSpace)			Buf_AddSpace(buf);		    addSpace = TRUE;		}		Buf_AddInterval(buf, word->s, cp);		Buf_AddChars(buf, pattern->rightLen, pattern->rhs);		pattern->flags |= VAR_SUB_MATCHED;	    } else {		/* Had to match at end and didn't. Copy entire word.  */		goto nosub;	    }	} else {	    /* Pattern is unanchored: search for the pattern in the word using	     * strstr, copying unmatched portions and the	     * right-hand-side for each match found, handling non-global	     * substitutions correctly, etc. When the loop is done, any	     * remaining part of the word (word and wordLen are adjusted	     * accordingly through the loop) is copied straight into the	     * buffer.	     * addSpace is set to FALSE as soon as a space is added to the	     * buffer.	*/	    Boolean done;	    size_t origSize;	    done = FALSE;	    origSize = Buf_Size(buf);	    while (!done) {		cp = strstr(word->s, pattern->lhs);		if (cp != NULL) {		    if (addSpace && (cp - word->s) + pattern->rightLen != 0){			Buf_AddSpace(buf);			addSpace = FALSE;		    }		    Buf_AddInterval(buf, word->s, cp);		    Buf_AddChars(buf, pattern->rightLen, pattern->rhs);		    wordLen -= (cp - word->s) + pattern->leftLen;		    word->s = cp + pattern->leftLen;		    if (wordLen == 0 || (pattern->flags & VAR_SUB_GLOBAL) == 0)			done = TRUE;		    pattern->flags |= VAR_SUB_MATCHED;		} else		    done = TRUE;	    }	    if (wordLen != 0) {		if (addSpace)		    Buf_AddSpace(buf);		Buf_AddChars(buf, wordLen, word->s);	    }	    /* If added characters to the buffer, need to add a space	     * before we add any more. If we didn't add any, just return	     * the previous value of addSpace.	*/	    return Buf_Size(buf) != origSize || addSpace;	}	return addSpace;    } nosub:    if (addSpace)	Buf_AddSpace(buf);    Buf_AddChars(buf, wordLen, word->s);    return TRUE;}