Boolean		hasSlash;
bool		hasSlash;
Dir_FindFilei(name, end, path)    const char		*name;	/* the file to find */    const char		*end;	/* end of file name */    Lst 		path;	/* List of directories to search */{    char		*p1;	/* pointer into p->name */    const char		*p2;	/* pointer into name */    LstNode		ln;	/* a list element */    char		*file;	/* the current filename to check */    char		*temp;	/* index into file */    Path		*p;	/* current path member */    const char		*cp;	/* index of first slash, if any */    Boolean		hasSlash;    struct stat 	stb;	/* Buffer for stat, if necessary */    struct file_stamp	*entry; /* Entry for mtimes table */    u_int32_t		hv;    char		*q;	/* Copy of name, end */    /* Find the final component of the name and note whether it has a     * slash in it (the name, I mean).	*/    cp = lastchar(name, end, '/');    if (cp) {	hasSlash = TRUE;	cp++;    } else {	hasSlash = FALSE;	cp = name;    }    hv = ohash_interval(cp, &end);    if (DEBUG(DIR))	printf("Searching for %s...", name);    /* No matter what, we always look for the file in the current directory     * before anywhere else and we *do not* add the ./ to it if it exists.     * This is so there are no conflicts between what the user specifies     * (fish.c) and what pmake finds (./fish.c).  */    if ((!hasSlash || (cp - name == 2 && *name == '.')) &&	find_file_hash(dot, cp, end, hv) != NULL) {	    if (DEBUG(DIR))		printf("in '.'\n");	    hits++;	    dot->hits++;	    return interval_dup(name, end);    }    /* We look through all the directories on the path seeking one which     * contains the final component of the given name and whose final     * component(s) match the name's initial component(s). If such a beast     * is found, we concatenate the directory name and the final component     * and return the resulting string. If we don't find any such thing,     * we go on to phase two...  */    for (ln = Lst_First(path); ln != NULL; ln = Lst_Adv(ln)) {	p = (Path *)Lst_Datum(ln);	if (DEBUG(DIR))	    printf("%s...", p->name);	if (find_file_hash(p, cp, end, hv) != NULL) {	    if (DEBUG(DIR))		printf("here...");	    if (hasSlash) {		/* If the name had a slash, its initial components and p's		 * final components must match. This is false if a mismatch		 * is encountered before all of the initial components		 * have been checked (p2 > name at the end of the loop), or		 * we matched only part of one of the components of p		 * along with all the rest of them (*p1 != '/').  */		p1 = p->name + strlen(p->name) - 1;		p2 = cp - 2;		while (p2 >= name && p1 >= p->name && *p1 == *p2) {		    p1--;		    p2--;		}		if (p2 >= name || (p1 >= p->name && *p1 != '/')) {		    if (DEBUG(DIR))			printf("component mismatch -- continuing...");		    continue;		}	    }	    file = str_concati(p->name, cp, end, '/');	    if (DEBUG(DIR))		printf("returning %s\n", file);	    p->hits++;	    hits++;	    return file;	} else if (hasSlash) {	    /* If the file has a leading path component and that component	     * exactly matches the entire name of the current search	     * directory, we assume the file doesn't exist and return NULL.  */	    for (p1 = p->name, p2 = name; *p1 && *p1 == *p2; p1++, p2++)		continue;	    if (*p1 == '\0' && p2 == cp - 1) {		if (DEBUG(DIR))		    printf("has to be here but isn't -- returning NULL\n");		return NULL;	    }	}    }    /* We didn't find the file on any existing members of the directory.     * If the name doesn't contain a slash, that means it doesn't exist.     * If it *does* contain a slash, however, there is still hope: it     * could be in a subdirectory of one of the members of the search     * path. (eg. /usr/include and sys/types.h. The above search would     * fail to turn up types.h in /usr/include, but it *is* in     * /usr/include/sys/types.h) If we find such a beast, we assume there     * will be more (what else can we assume?) and add all but the last     * component of the resulting name onto the search path (at the     * end). This phase is only performed if the file is *not* absolute.  */    if (!hasSlash) {	if (DEBUG(DIR))	    printf("failed.\n");	misses++;	return NULL;    }    if (*name != '/') {	Boolean checkedDot = FALSE;	if (DEBUG(DIR))	    printf("failed. Trying subdirectories...");	for (ln = Lst_First(path); ln != NULL; ln = Lst_Adv(ln)) {	    p = (Path *)Lst_Datum(ln);	    if (p != dot)		file = str_concati(p->name, name, end, '/');	    else {		/* Checking in dot -- DON'T put a leading ./ on the thing.  */		file = interval_dup(name, end);		checkedDot = TRUE;	    }	    if (DEBUG(DIR))		printf("checking %s...", file);	    if (stat(file, &stb) == 0) {		TIMESTAMP mtime;		grab_stat(stb, mtime);		if (DEBUG(DIR))		    printf("got it.\n");		/* We've found another directory to search. We know there's		 * a slash in 'file' because we put one there. We call		 * Dir_AddDir to add this new directory onto the existing		 * search path. Once that's done, we return the file name,		 * knowing that should a file in this directory ever be		 * referenced again in such a manner, we will find it		 * without having to do numerous access calls. Hurrah!	*/		temp = strrchr(file, '/');		Dir_AddDir(path, file, temp);		/* Save the modification time so if it's needed, we don't have		 * to fetch it again.  */		if (DEBUG(DIR))		    printf("Caching %s for %s\n", Targ_FmtTime(mtime),			    file);		record_stamp(file, mtime);		nearmisses++;		return file;	    } else		free(file);	}	if (DEBUG(DIR))	    printf("failed. ");	if (checkedDot) {	    /* Already checked by the given name, since . was in the path,	     * so no point in proceeding...  */	    if (DEBUG(DIR))		printf("Checked . already, returning NULL\n");	    return NULL;	}    }    /* Didn't find it that way, either. Sigh. Phase 3. Add its directory     * onto the search path in any case, just in case, then look for the     * thing in the hash table. If we find it, grand. We return a new     * copy of the name. Otherwise we sadly return a NULL pointer. Sigh.     * Note that if the directory holding the file doesn't exist, this will     * do an extra search of the final directory on the path. Unless something     * weird happens, this search won't succeed and life will be groovy.     *     * Sigh. We cannot add the directory onto the search path because     * of this amusing case:     * $(INSTALLDIR)/$(FILE): $(FILE)     *     * $(FILE) exists in $(INSTALLDIR) but not in the current one.     * When searching for $(FILE), we will find it in $(INSTALLDIR)     * b/c we added it here. This is not good...  */#ifdef notdef    Dir_AddDir(path, name, cp-1);    bigmisses += 1;    ln = Lst_Last(path);    if (ln == NULL)	return NULL;    else	p = (Path *)Lst_Datum(ln);    if (find_file_hash(p, cp, e, hv) != NULL)	return estrdup(name);    else	return NULL;#else /* !notdef */    q = interval_dup(name, end);    if (DEBUG(DIR))	printf("Looking for \"%s\"...", q);    bigmisses++;    entry = find_stampi(name, end);    if (entry != NULL) {	if (DEBUG(DIR))	    printf("got it (in mtime cache)\n");	return q;    } else if (stat(q, &stb) == 0) {	TIMESTAMP mtime;	grab_stat(stb, mtime);	if (DEBUG(DIR))	    printf("Caching %s for %s\n", Targ_FmtTime(mtime),		    q);	record_stamp(q, mtime);	return q;    } else {	if (DEBUG(DIR))	    printf("failed. Returning NULL\n");	free(q);	return NULL;    }#endif /* notdef */}