mathieu@14: % PROCESS_OPTIONS - Processes options passed to a Matlab function. mathieu@14: % This function provides a simple means of mathieu@14: % parsing attribute-value options. Each option is mathieu@14: % named by a unique string and is given a default mathieu@14: % value. mathieu@14: % mathieu@14: % Usage: [var1, var2, ..., varn[, unused]] = ... mathieu@14: % process_options(args, ... mathieu@14: % str1, def1, str2, def2, ..., strn, defn) mathieu@14: % mathieu@14: % Arguments: mathieu@14: % args - a cell array of input arguments, such mathieu@14: % as that provided by VARARGIN. Its contents mathieu@14: % should alternate between strings and mathieu@14: % values. mathieu@14: % str1, ..., strn - Strings that are associated with a mathieu@14: % particular variable mathieu@14: % def1, ..., defn - Default values returned if no option mathieu@14: % is supplied mathieu@14: % NOTE: this version (modified by dpwe) will run str2num on mathieu@14: % string arguments if the default value is numeric mathieu@14: % (to support passing in numbers from the command line). mathieu@14: % mathieu@14: % Returns: mathieu@14: % var1, ..., varn - values to be assigned to variables mathieu@14: % unused - an optional cell array of those mathieu@14: % string-value pairs that were unused; mathieu@14: % if this is not supplied, then a mathieu@14: % warning will be issued for each mathieu@14: % option in args that lacked a match. mathieu@14: % mathieu@14: % Examples: mathieu@14: % mathieu@14: % Suppose we wish to define a Matlab function 'func' that has mathieu@14: % required parameters x and y, and optional arguments 'u' and 'v'. mathieu@14: % With the definition mathieu@14: % mathieu@14: % function y = func(x, y, varargin) mathieu@14: % mathieu@14: % [u, v] = process_options(varargin, 'u', 0, 'v', 1); mathieu@14: % mathieu@14: % calling func(0, 1, 'v', 2) will assign 0 to x, 1 to y, 0 to u, and 2 mathieu@14: % to v. The parameter names are insensitive to case; calling mathieu@14: % func(0, 1, 'V', 2) has the same effect. The function call mathieu@14: % mathieu@14: % func(0, 1, 'u', 5, 'z', 2); mathieu@14: % mathieu@14: % will result in u having the value 5 and v having value 1, but mathieu@14: % will issue a warning that the 'z' option has not been used. On mathieu@14: % the other hand, if func is defined as mathieu@14: % mathieu@14: % function y = func(x, y, varargin) mathieu@14: % mathieu@14: % [u, v, unused_args] = process_options(varargin, 'u', 0, 'v', 1); mathieu@14: % mathieu@14: % then the call func(0, 1, 'u', 5, 'z', 2) will yield no warning, mathieu@14: % and unused_args will have the value {'z', 2}. This behaviour is mathieu@14: % useful for functions with options that invoke other functions mathieu@14: % with options; all options can be passed to the outer function and mathieu@14: % its unprocessed arguments can be passed to the inner function. mathieu@14: mathieu@14: % Copyright (C) 2002 Mark A. Paskin mathieu@14: % mathieu@14: % This program is free software; you can redistribute it and/or modify mathieu@14: % it under the terms of the GNU General Public License as published by mathieu@14: % the Free Software Foundation; either version 2 of the License, or mathieu@14: % (at your option) any later version. mathieu@14: % mathieu@14: % This program is distributed in the hope that it will be useful, but mathieu@14: % WITHOUT ANY WARRANTY; without even the implied warranty of mathieu@14: % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU mathieu@14: % General Public License for more details. mathieu@14: % mathieu@14: % You should have received a copy of the GNU General Public License mathieu@14: % along with this program; if not, write to the Free Software mathieu@14: % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 mathieu@14: % USA. mathieu@14: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% mathieu@14: mathieu@14: function [varargout] = process_options(args, varargin) mathieu@14: mathieu@14: % Check the number of input arguments mathieu@14: n = length(varargin); mathieu@14: if (mod(n, 2)) mathieu@14: error('Each option must be a string/value pair.'); mathieu@14: end mathieu@14: mathieu@14: % Check the number of supplied output arguments mathieu@14: if (nargout < (n / 2)) mathieu@14: error('Insufficient number of output arguments given'); mathieu@14: elseif (nargout == (n / 2)) mathieu@14: warn = 1; mathieu@14: nout = n / 2; mathieu@14: else mathieu@14: warn = 0; mathieu@14: nout = n / 2 + 1; mathieu@14: end mathieu@14: mathieu@14: % Set outputs to be defaults mathieu@14: varargout = cell(1, nout); mathieu@14: for i=2:2:n mathieu@14: varargout{i/2} = varargin{i}; mathieu@14: end mathieu@14: mathieu@14: % Now process all arguments mathieu@14: nunused = 0; mathieu@14: for i=1:2:length(args) mathieu@14: found = 0; mathieu@14: for j=1:2:n mathieu@14: if strcmpi(args{i}, varargin{j}) mathieu@14: % dpwe: promote string args to numeric if default arg is mathieu@14: % numeric mathieu@14: if isnumeric(varargin{j+1}) && ischar(args{i+1}) mathieu@14: varargout{(j + 1)/2} = str2num(args{i + 1}); mathieu@14: % this occurs when specifying arguments from command line mathieu@14: else mathieu@14: % in all other cases, take what you get mathieu@14: varargout{(j + 1)/2} = args{i + 1}; mathieu@14: end mathieu@14: found = 1; mathieu@14: break; mathieu@14: end mathieu@14: end mathieu@14: if (~found) mathieu@14: if (warn) mathieu@32: fprintf(2, sprintf('Option ''%s'' not used.', args{i})); mathieu@14: args{i} mathieu@14: else mathieu@14: nunused = nunused + 1; mathieu@14: unused{2 * nunused - 1} = args{i}; mathieu@14: if length(args) > i mathieu@14: % don't demand a value for the last, unused tag (e.g. -help) mathieu@14: unused{2 * nunused} = args{i + 1}; mathieu@14: end mathieu@14: end mathieu@14: end mathieu@14: end mathieu@14: mathieu@14: % Assign the unused arguments mathieu@14: if (~warn) mathieu@14: if (nunused) mathieu@14: varargout{nout} = unused; mathieu@14: else mathieu@14: varargout{nout} = cell(0); mathieu@14: end mathieu@14: end