Code covered by the BSD License  

Highlights from
evalf.m v2.0 (Sep, 2009)

from evalf.m v2.0 (Sep, 2009) by Carlos Adrian Vargas Aguilera
Evaluates any function (handle, anonymous, name, full-name) even if not in the MATLAB PATH!

evalf(varargin)
function varargout = evalf(varargin)
%EVALF   Evaluates specified function in specified directory if required.
%
%   SYNTAX:
%                       evalf(FUNC)
%                       evalf(FUNC,ARG1,ARG2,ARG3,...)
%                       evalf('-there',...)
%                       evalf('-DIR',...)
%     [OUT1,OUT2,...] = evalf(...);
%
%   INPUT:
%     FUNC     - Unique MATLAB function/script handle, anonymous handle,
%                file name or full-name to be evaluated.
%     ARG1,... - Comma separated input argument(s) of the function FUNC. 
%                DEFAULT: (non inputs)
%     '-there' - Evaluates FUNC in the directory it is located, returning
%                to the current one when is done.
%                DEFAULT: '-here' ('-there' if FUNC is a fullname) 
%     '-DIR'   - Evaluates FUNC in the specified directory as momentarily
%                current. For example: '-C:\MATLAB'.
%                DEFAULT: ['-' pwd] (or the specified on full-name)
%
%   OUTPUT:
%     OUT1,... - Comma separated output argument(s) of FUNC.
%                DEFAULT: (none)
%
%   DESCRIPTION:
%     MATLAB evaluates functions and scripts located only on the Current
%     Directory (see PWD) or its list of directories (see PATH). This
%     function allows the user to run any MATLAB function located in any
%     location (specified by its full-name). 
%
%     Besides, while evaluating the function the Current Directory may be
%     changed to the one specified on the full-name, or the one by
%     '-DIR'.
%
%     Another important difference from MATLAB's FEVAL function, is that
%     this function works correctly with anonymous function handles. In
%     fact, functions given by name (strings) are converted into a function
%     handle.
%
%     Variables defined on M-files scripts are returned in the MATLAB
%     workspace ('base').
%     
%   NOTE:
%     * Optional inputs use its DEFAULT value when not given or [].
%     * Optional outputs may or not be called.
%     * Only '-t' and '-h' are considered, instead of '-there' and '-here'.
%     * ADDITIONAL NOTES are included inside this file.
%
%   EXAMPLE:
%     x = linspace(0,4*pi);
%     y = sin(x);
%     % 1) Function and inputs versatility:
%          hold on
%           % By function name:
%            evalf('plot',x,y,'b*')
%           % By handle function:
%            evalf(@plot,x,y,'ro');
%           % By anonymous handle function:
%            evalf(@(z)plot(x,z,'g'),y);
%          hold off
%          legend('''plot''','@plot','@(z)plot(x,z,''g'')')
%     % 2) Multiple outputs versatility:
%          [vmax,imax] = evalf('max',[10 20 30 40 30 20 10])
%     % 3) Directories versatility:
%          % i) Evaluates "LS" MATLAB function on Current Directory:
%            disp('i)')
%            evalf ls
%          % ii) Evaluates LS on previous directory:
%            disp('ii)')
%            evalf -.. ls
%          % iii) Evaluates in its directory:
%            disp('ii)')
%            evalf([matlabroot '\toolbox\matlab\general\ls'])
%          In i) and ii) LS must be on MATLAB PATH.
%
%   SEE ALSO:
%     FEVAL, EVALIN, RUN, PATH, PWD
%     and
%     FUNC2FUNC by Carlos Vargas
%     at http://www.mathworks.com/matlabcentral/fileexchange
%
%
%   ---
%   MFILE:   evalf.m
%   VERSION: 2.0 (Sep 21, 2009) (<a href="matlab:web('http://www.mathworks.com/matlabcentral/fileexchange/authors/11258')">download</a>) 
%   MATLAB:  7.7.0.471 (R2008b)
%   AUTHOR:  Carlos Adrian Vargas Aguilera (MEXICO)
%   CONTACT: nubeobscura@hotmail.com

%   ADDITIONAL NOTES:
%     * In order to make the function compatible with previous MATLAB
%       releases (although I couldn't test this), I avoided the use of some
%       functions like FILESEP, RETHROW, STRCMPI, SWITCH-CASE short-circuit
%       logicals, etc. I don't know if the TRY-CATCH is new, anyway I try
%       to avoid it too. If there is some problem just let me know to make
%       the appropiate changes. With VARARGIN, VARARGOUT, NARGIN and 
%       NARGOUT I cannot do too much. By the way, I don't know if ERROR and
%       EXIST allow 2 inputs in previous releases.

%   REVISIONS:
%   1.0      Released (Nov 10, 2008)
%   2.0      Fixed bug with reading name file and extension. Now works with
%            scripts. (Sep 21, 2009)

%   Copyright 2008,2009 Carlos Adrian Vargas Aguilera


% INPUTS CHECK-IN
% -------------------------------------------------------------------------

% Sets defaults.
dothere = NaN;
DIR     = [];

% Sets parameters.
currDir = cd;                    % Current Directory.
sep     = findstr(currDir,'\');  % NOTE: I avoided the use of FILESEP.
if ~isempty(sep)
 sep  = '\'; % Windows
else
 sep  = '/'; % Linux
end
if ~strcmp(currDir(end),sep), currDir = [currDir sep]; end
iscript = false;              % SCRIPT file instead of function.

% Checks number of inputs.
if (nargin<1)
 error('CVARGAS:evalf:notEnoughInputs', ...
  'No function was specified.')
end

% Checks number of outputs.
if (nargout~=0)
 varargout = cell(nargout,1);
end

% Checks '-t' or '-h' or '-DIR' input.
if ischar(varargin{1})
 if     isempty(varargin{1})
  error('CVARGAS:evalf:incorrectFirstInput',...
   'First input cannot be empty.')
 elseif strcmp(varargin{1}(1),'-')
  % NOTE: I avoided the use of SWITCH-CASE.
  if length(varargin{1})==1
   error('CVARGAS:evalf:incorrectOptionalInput',...
    'Optional first input must be ''-t'', ''-h'' or a valid ''-DIR''.')
  elseif strcmp(lower(varargin{1}(2)),'t')
   % '-there'.
   dothere     = true;
   varargin(1) = [];
  elseif strcmp(lower(varargin{1}(2)),'h')
   % '-here'.
   dothere     = false;
   varargin(1) = [];
  else
   % '-DIR'.
   % NOTE: I avoided the use of short-circuit logical: ||.
   DIR  = varargin{1}(2:end);
   if ~strcmp(DIR(end),sep), DIR = [DIR sep]; end
   if  strcmp(lower(DIR),lower(currDir))
    DIR = [];
   elseif strcmp(DIR,['.' sep])
    DIR = [];
   elseif ~(exist(DIR,'dir')==7)
    error('CVARGAS:evalf:incorrectOptionalInput',...
    'Optional first input must be ''-t'', ''-h'' or a valid ''-DIR''.')
   else
    dothere = true;
   end
   varargin(1) = []; 
  end
 end
 % Checks if any input was left.
 if isempty(varargin)
  error('CVARGAS:evalf:notEnoughInputs',...
        'No function was specified.')
 end
end

% Checks FUNC input.
FUNC      = varargin{1};
varargin(1) = [];
if     isempty(FUNC)
 error('CVARGAS:evalf:notEnoughInputs',...
  'No function was specified.')
 
elseif ischar(FUNC)
 % Function name.
 
 % Looks if the function exist on its specified direction or, if not
 % specified, in the Current Directory or PATH.
 % NOTE: I avoided the use of ISMEMBER.
 if ~(exist(FUNC,'file')==2)
  if ~(exist(FUNC,'builtin')==5)
   % Adds extra '\' and '%' chars to be printed on error display.
   ind1       = findstr(FUNC,'\');
   if ~isempty(ind1)
    N          = length(FUNC);
    ind2       = zeros(1,N);
    ind2(ind1) = 1;
    temp( ind1+cumsum(ind2(ind1))-1) = '\';
    temp((1:N)+cumsum(ind2)) = FUNC;
    FUNC = temp;
   end
   ind1       = findstr(FUNC,'%');
   if ~isempty(ind1)
    N          = length(FUNC);
    ind2       = zeros(1,N);
    ind2(ind1) = 1;
    temp( ind1+cumsum(ind2(ind1))-1) = '%';
    temp((1:N)+cumsum(ind2)) = FUNC;
    FUNC = temp;
   end
   error('CVARGAS:evalf:incorrectFuncInput', ...
    ['The function ''' FUNC ''' was not found.'])
  end
 end
  
 % Gets funcDir, funcNam and funcExt manually.
 % NOTE: I avoided the use of FILEPARTS.
 indsep  = findstr(FUNC,sep);
 if isempty(indsep)
  indsep  = 0;
  funcDir = [];
 else
  indsep  = indsep(end);
  funcDir = FUNC(1:indsep);
 end
 indext   = findstr(FUNC(indsep+1:end),'.');
 if isempty(indext)
  indext  = length(FUNC)-indsep+1; 
  funcExt = [];
 else
  indext  = indext(end);
  funcExt = FUNC(indsep+indext:end);   % Fixed bug, Sep 2009
 end 
 funcNam  = FUNC(indsep+(1:indext-1)); % Fixed bug, Sep 2009

 % Checks funcExt.
 if ~isempty(funcExt)
  % NOTE: I avoided the use of SWITCH-CASE.
  if strcmp(lower(funcExt),'.m')
   % Checks if function or script, Sep 2009
   fid = fopen(FUNC);
   while 1
    tline = fgetl(fid);
    if ~ischar(tline), break, end
    tline = fliplr(deblank(fliplr(tline)));
    if isempty(tline), continue, end
    if ~strcmp(tline(1),'%')
     if length(tline)>9
      if strcmp(tline(1:9),'function ')
       break 
      end
     end
    end
    iscript = true;
   end
   fclose(fid);
   if iscript
    if nargout | ~isempty(varargin)
     error('CVARGAS:evalf:noOutputsInputsOnScripts',...
      'Scripts files cannot have inputs/outputs.')
    end
   end
  elseif strcmp(lower(funcExt),'.p')
   % continue
  else
   error('CVARGAS:evalf:incorrectFileExtension',...
    'Function must be an M- or P-file.')
  end
 end
 
 % Checks funcDir.
 if ~isempty(funcDir)
  if isnan(dothere)
   dothere = true;
  end
  if dothere
   DIR = funcDir;
  end
 end
 
 % Gets the function handle.
 if (exist('str2func','builtin')==5)
  FUNC = str2func(funcNam);
 else
  FUNC = feval(['@' funcNam]);
 end
   
elseif isa(FUNC,'function_handle')
 % Function handle.
 
 % Just get the function name and dir.
 if exist('func2str','builtin')==5
  funcNam = func2str(FUNC);
 else
  funcNam = [];
 end
 funcDir = '';
 
else
 error('CVARGAS:evalf:incorrectFuncInput',...
 'FUNC must be a function name, handle or anonymous handle.')
end


% -------------------------------------------------------------------------
% MAIN
% -------------------------------------------------------------------------

% Go to evaluation directory.
if ~isempty(DIR)
 if strcmp(lower(DIR),lower(currDir)) | strcmp(DIR,['.' sep])
  DIR     = [];
  dothere = false;
 end
end
if ~dothere
 % Evaluates on Current Directory.
 currDir = [];
else
 % Evaluates on DIR.
 cd(DIR)
end
 
% Evaluation.
if (exist('try','builtin')==5)
 % Tries to evaluate in given directory, catching any error during
 % evaluation to be able to return to previous Current Directory.
 try
  if nargout==0
   if iscript % Sep 2009
    % Uses EVALIN to export any variable definition on the function to the
    % MATLAB workspace intead of the workspace of this function.
    evalin('base',funcNam)
   else
    FUNC(varargin{:})
   end
  else
   [varargout{:}] = FUNC(varargin{:});
  end
 catch
  if ~isempty(currDir)
   cd(currDir)
  end
  if (exist('lasterror','builtin')==5)
   message = lasterror;
   message = message.message;
  else
   message = theerror;
  end
  error('CVARGAS:evalf:errorWhileEvauating',...
   ['Error during ' [funcDir funcNam] ' function evaluation. \n\n' ...
    message]) 
 end
else
 if nargout==0
  if iscript % Sep 2009
   % Uses EVALIN to export any variable definition on the function to the
   % MATLAB workspace intead of the workspace of this function.
   evalin('base',funcNam)
  else
   FUNC(varargin{:})
  end
 else
  [varargout{:}] = FUNC(varargin{:});
 end 
end

% Returns to previous directory.
if ~isempty(currDir)
 cd(currDir)
end


% [EOF]   evalf.m

Contact us at files@mathworks.com