function [pth, fn] = fwhich(filename, type, search)
%FWHICH  Locates files and directories in the MATLAB path.
%       [FILEPATH] = FWHICH(FILENAME) returns the full path (FILEPATH) to the
%       file or directory FILENAME.  FILEPATH includes the path as well as
%       the name of the file that was found.  If a file name extension is
%       given, the search is done for that specific file alone.  If no file
%       name extension is given, extentions of '.mex' (platform appropriate)
%       and '.m' are assumed.  Finally, if FILENAME is a directory, the path
%       to that directory is returned after any files of the same name.
%       Only directories at the bottom of a directory tree are found.
%
%       [PTH, FN] = FWHICH(FILENAME) returns the full path (PTH) and file
%       name (FN) in separate arguments.  If FILENAME is a directory, the
%       path to that directory is returned in PTH, and FN is returned as an
%       empty string.
%
%       [FILEPATH] = FWHICH(FILENAME, FILETYPE, SEARCHOPT) allows more
%       control over the files and directories found by FWHICH.  The
%       following are valid entries for FILETYPE: 'any', 'file', 'dir'.  The
%       type 'any' will allow searches for either files or directories.  The
%       types 'file' and 'dir' restrict the search to either files only or
%       directories only, respectively.  The following are valid entries for
%       SEARCHOPT: 'first', 'all'.  The 'first' option restricts the search
%       to the first item found in the MATLAB path that matches the
%       FILENAME.  The 'all' option allows the search to proceed through the
%       whole MATLAB path finding all occurances of the item FILENAME.
%
%       Note that more restrictive searches (using the specific FILETYPEs of
%       'file' and 'dir' and using 'first' as the SEARCHOPT) will result in
%       much faster execution speeds for FWHICH.  Additionally, execution
%       time is decreased if the file name extention is given.  Execution
%       time can be very long if the complete MATLAB path is searched.

%       P. Barnard 1-10-95
%       Copyright (c) 1995 The MathWorks, Inc.
%       $Revision: 1.5 $  $Date: 1995/02/15 18:19:16 $

% Check the input arguments.
if ~isstr(filename) error('FILENAME must be a string.'), end
if nargin > 1
   if nargin > 2
      if strcmp(search, 'all')
         findall = 1;
      else
         findall = 0;
      end
   else
      findall = 0;
   end
   if strcmp(type, 'any')
      ftype = 0;
   elseif strcmp(type, 'file')
      ftype = 1;
   else
      ftype = 2;
   end
else
   findall = 0;
   ftype = 0;
end

% Get the MATLAB path and set up the machine specific parameters.
pathsep = ':';
filesep = '/';
c = computer;
sys = 'u';
if strcmp(c(1:2),'PC')
   pathsep = ';';
   filesep = '\';
   sys = 'p';
elseif strcmp(c(1:2),'MA')
   pathsep = ';';
   filesep = ':';
   sys = 'm';
elseif isvms
   pathsep = ',';
   filesep = '.]';
   sys = 'v';
end

% Initialize the first row which; is blank.
pthmat = [];
pth = [];
fn = [];
fpth = setstr(zeros(3,1));
ffn = setstr(zeros(3,1));

% For the case where the first file found is all that is necessary.
if (ftype ~= 2 & ~findall & any(filename == '.'))
   fid = fopen(filename);
   if fid ~= -1
      fullpath = fopen(fid); fclose(fid);
      if sys(1)=='p'
         indx=find(fullpath=='/');  % For PC, make all slashes '\'.
         if ~isempty(indx), fullpath(indx) = setstr(ones(1,length(indx))*real('\')); end
      end
      p = find(fullpath == filesep(length(filesep)));
      if isempty(p)
         if sys(1)=='v',
            fullpath = [cd fullpath];
         else
            fullpath = [cd filesep(1) fullpath];
         end
         p = find(fullpath == filesep(length(filesep)));
      end
      p = max(p);

      % Load results up into pth and fn if it is not a directory.
      if ~isdir(fullpath)
         pth = fullpath(1:p);
         fn = fullpath(p+1:length(fullpath));
      end
   end
   % Return the arguments.
   if (nargout < 2)
      pth = [pth fn];
   end
   return  % End quickly for this case.
end

% Initialize path variables.
allpath = [path pathsep];   % Add pathseps and cd to make searching easier.

% Check to see if cd is already in path, eliminate it, and add cd at beginning.
curdir = cd;
p = findstr(curdir, allpath);
if p
   allpath(p:p-1+min(find(allpath(p:length(allpath)) == pathsep))) = [];
end
allpath = [cd pathsep allpath];

% For PC, make all slashes '\'.
if sys(1)=='p'
   indx=find(allpath=='/');
   if ~isempty(indx), allpath(indx) = setstr(ones(1,length(indx))*real('\')); end
end

% Find all of the path separators.
seps = find(allpath == pathsep);

% Do the following only if files are to be found.
if ftype ~= 2

   % Create a strmat for the path.
   q = 1;
   for r = seps
      if sys(1)=='v',
         pthmat = str2mat(pthmat,allpath(q:r-1));
      else
         pthmat = str2mat(pthmat,[allpath(q:r-1) filesep]);
      end
      q = r + 1;
   end;

   % Get MEX file extension.
   mexstr = mexext;

   if findall
      % Loop through every path finding files.
      [r,c] = size(pthmat);
      for i = 2:r  % Starts at 2 because the first line is blank.
         % Find each occurance of the given filename, .mex, and .m files.
         fid = fopen([deblank(pthmat(i,:)) filename]);
         mexfid = fopen([deblank(pthmat(i,:)) filename '.' mexstr]);
         mfid = fopen([deblank(pthmat(i,:)) filename '.m']);

         tmpid = [fid mexfid mfid];
         if any(tmpid > 0)
            for i = 1:3
               if tmpid(i) ~= -1
                  fullpath = fopen(tmpid(i)); fclose(tmpid(i));
                  p = find(fullpath == filesep(length(filesep)));
                  p = max(p);

                  % Load results up into pth and fn if it is not a directory.
                  if ~isdir(fullpath)
                     pth = str2mat(pth,fullpath(1:p));
                     ln = length(fullpath);
                     fn = str2mat(fn,fullpath(p+1:ln));
                  end
               end
            end
   
         end % end if

      end % for loop on pthmat

   else
      % Find first occurance of the given filename, .mex, and .m files.
      fid = fopen(filename);
      mexfid = fopen([filename '.' mexstr]);
      mfid = fopen([filename '.m']);

      tmpid = [fid mexfid mfid];
      if any(tmpid > 0)
         for i = 1:3
            if tmpid(i) ~= -1
               fullpath = fopen(tmpid(i)); fclose(tmpid(i));
               p = find(fullpath == filesep(length(filesep)));
               if isempty(p)
                  if sys(1)=='v',
                     fullpath = [cd fullpath];
                  else
                     fullpath = [cd filesep fullpath];
                  end
                  p = find(fullpath == filesep(length(filesep)));
               end
               p = max(p);
               if ~isdir(fullpath)
                  fpth(i,1:p) = fullpath(1:p);
                  ln = length(fullpath);
                  ffn(i,1:ln-p) = fullpath(p+1:ln);
               end

            end
         end

         % Loop through the path to find the 'first' entry.
         [r,c] = size(pthmat);
         for i = 1:r
            if strcmp(deblank(pthmat(i,:)),fpth(1,:))
               pth = str2mat(pth,fpth(1,:));
               fn = str2mat(fn,ffn(1,:));
            elseif strcmp(deblank(pthmat(i,:)),fpth(2,:))
               pth = str2mat(pth,fpth(2,:));
               fn = str2mat(fn,ffn(2,:));
            elseif strcmp(deblank(pthmat(i,:)),fpth(3,:))
               pth = str2mat(pth,fpth(3,:));
               fn = str2mat(fn,ffn(3,:));
            end
         end % for
   
      end % if any(tmpid > 0)

   end % if findall

end % if ftype ~= 2

% Find directories of name filename (if directories are to be found).
if ftype ~= 1
   lfn = length(filename);
   if sys(1)=='v', lfn = lfn + 1; end
   pp = findstr(filename,allpath);
   for i=1:length(pp)
      if ( (allpath(pp(i)-1)==filesep(1)) | (sys(1)=='v' & allpath(pp(i)-1)=='[') ) ...
         & (allpath(pp(i)+lfn)==pathsep)
         if sys(1)=='v',
            pth = str2mat(pth, allpath(max(seps.*(seps < pp(i)))+1:pp(i) + lfn-1));
         else
            pth = str2mat(pth, [allpath(max(seps.*(seps < pp(i)))+1:pp(i) + lfn-1) filesep]);
         end
         fn = str2mat(fn, []);
         if ~findall, break; end
      end
   end
end

% Removes the first row which; is blank.
if ~isempty(pth) pth(1,:) = []; end
if ~isempty(fn) fn(1,:) = []; end

% Empty pth and fn rows that contain a single blank.
[r,c] = size(pth);
for i = r:-1:1
   if isspace(fn(i,:))
      fn(i,:) = setstr(zeros(size(fn(i,:))));
   end
   if isspace(pth(i,:))
      pth(i,:) = setstr(zeros(size(pth(i,:))));
   end
end

% Return the arguments.
if (nargout < 2)
   pth = [pth fn];
end   

