changeset 247:d06717c3ce7b octave-forge

complete rewrite. Was a script, is now a function
author etienne
date Sat, 30 Mar 2002 21:17:46 +0000
parents 923dc905eac4
children c6758e9ff059
files main/miscellaneous/read_options.m
diffstat 1 files changed, 118 insertions(+), 105 deletions(-) [+]
line wrap: on
line diff
--- a/main/miscellaneous/read_options.m	Sat Mar 30 21:16:57 2002 +0000
+++ b/main/miscellaneous/read_options.m	Sat Mar 30 21:17:46 2002 +0000
@@ -10,116 +10,129 @@
 ## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 ## for more details.
 
-## read_options is a script that can be called to read options from
-## within a function. Variables in the function's namespace, with same
-## name as the options will be set. read_options stops reading options
-## as soon as it reads an argument that it does not recognize.
-##
-## nargin   : Should be set to the number of remaining arguments.
-##
-## opt0     : A single-space-separated string of boolean options. Should
-##            be padded with a single space at both extremities.
-##             Default is " ".
+## [ops,nread] = read_opts (args,...) - Read options
 ##
-## opt1     : String of options taking one argument. Default is " ".
-##
-## filename : Name of the function, for verbose output or griping.
-##            Default is "unknown_func"
-##
-## verbose  : in {0,1} : be more or less verbose. Default is 0.
-##
-## opt_quiet: in {0,1} : If set, read_options will gripe when it
-##            encounters an unknown option. Otherwise, it just returns
-##
-## Also,  read_options  sets some variables that can be accessed from
-## the calling function :
+## INPUT -------------
+## args     : list   : Options and values
 ##
-## last_option_name : The name of the last option name, OR whatever
-##                    unrecognized argument that caused read_options to
-##                    stop reading the arguments (if any).
-##
-## last_option_value: The value of the last option taking a single
-##                    argument (if any).
+## OPTIONS -------
+## 'op0'    , string : Space-separated names of opt taking no argument  <''>
+## 'op1'    , string : Space-separated names of opt taking one argument <''>
+## 'default', struct : Struct holding default option values           <none>
+## 'prefix' , int    : If set, recognize opt from first chars. Else,     <0>
+##                     only accept whole opt names                       
+## 'nocase' , int    : If set, ignore case in option names               <0>
+## 'quiet'  , int    : Behavior when a non-string or unknown opt is met  <0>
+##              0    - Produce an error
+##              1    - Return quietly (can be diagnosed by checking 'rem')
+##      
+##     Note : At least one of 'op0' or 'op1' should be specified.
 ## 
-## option_number    : The number of arguments that have been read.
+## OUTPUT ------------
+## ops      : struct : Struct whose key/values are option names/values
+## nread    : int    : Number of elements of args that were read
 ##
-## read_options assumes that a script called from a function is executed
-## as if its code was written within the function body. (like a #define
-## in C). I don't think this feature is documented in octave, so it
-## might stop working on some versions of octave. Works with 2.1.19.
-
-#  if exist("filename","var")!=1  , filename="unkown_func" ; end
-#  if exist("verbose","var")!=1   , verbose=0 ; end
-#  if exist("opt0","var")!=1      , opt0=" "  ; end
-#  if exist("opt1","var")!=1      , opt1=" "  ; end
-# if exist("opt_quiet","var")!=1 , opt_quiet=0  ; end
-if exist("filename")!=1  , filename="unkown_func" ; end
-if exist("verbose")!=1   , verbose=0 ; end
-if exist("opt0")!=1      , opt0=" "  ; end
-if exist("opt1")!=1      , opt1=" "  ; end
-if exist("opt_quiet")!=1 , opt_quiet=0  ; end
+## USAGE -------------
+##
+##                              # Define options and defaults
+## op0 = "is_man is_plane flies"
+## default = struct ("is_man",1, "flies",0);
+##
+##                              # Read the options
+##
+## s = read_opts (list (all_va_arg), "op0",op0,"default",default)
+##
+##                              # Create variables w/ same name as options
+##
+## [is_man, is_plane, flies] = getfield (s,"is_man", "is_plane", "flies")
+function [op,nread] = read_opts (args, ...)
 
-## opt0 
-## opt1
-## Commented 2000/08/13 ... break anything?
-## va_start() ;
-nargin_orig = nargin ;
-option_number = 0 ;
-## igncnt = 0 ;
-while nargin>0 ,
-  last_option_name = va_arg() ;
-  ## opt0
-  nargin-- ;
-  option_number++ ;
-  if ! isstr(last_option_name) ,
-    if ! opt_quiet ,
-      printf("%s : Non-string option : \n",filename) ;
-      keyboard
-    else
-      if verbose,
-	printf("read_options : ignoring non-string option number %d\n",\
-	       option_number) ;
-	## last_option_name 
-      end
-    end
-    ## ignopt(++igncnt) = option_number ;
-    ## if opt_quit_early, break ; end
-    break ;
-  end
-  read_options_foo = [" ",last_option_name," "] ;
-  ## keyboard
-  if index(opt1,read_options_foo) ,
-    
-    last_option_value = va_arg() ;		#nargin-- ;
-    ## last_option_value
-    nargin-- ;
-    option_number++ ;
-    eval([last_option_name,"=last_option_value;"]) ;
+op = setfield ();		# Empty struct
+op0 = op1 = " ";
+guess = quiet = nocase = quiet = 0;
+
+nargin--;
+if rem (nargin, 2), error ("odd number of optional args"); end
 
-    if verbose
-      printf ("%s : Read option : %s.\n",filename,last_option_name);
-    end
-
-  elseif index(opt0,read_options_foo) ,
-    eval([last_option_name,"=1;"]) ;
-    if verbose 
-      printf ("%s : Read boolean option : %s\n",filename,last_option_name);
-    end
-
-  else
-    if ! opt_quiet ,
-      printf("%s : Unknown option : %s\n",filename,last_option_name) ;
-      keyboard
-    else
-      if verbose,
-	printf("read_options : ignoring option number %d, '%s'\n",\
-	       option_number,last_option_name) ;
-	last_option_name 
-      end
-
-    end
-    ## ignopt(++igncnt) = option_number ;
-    ## if opt_quit_early, break ; end
-    break
+while nargin
+  nargin -= 2;
+  if ! isstr (tmp = va_arg ()), error ("non-string option"); end
+  if     strcmp (tmp, "op0")    , op0     = va_arg ();
+  elseif strcmp (tmp, "op1")    , op1     = va_arg ();
+  elseif strcmp (tmp, "default"), op      = va_arg ();
+  elseif strcmp (tmp, "prefix") , prefix  = va_arg ();
+  elseif strcmp (tmp, "nocase") , nocase  = va_arg ();
+  elseif strcmp (tmp, "quiet")  , quiet   = va_arg ();
+  else 
+    error ("unknown option '%s' for option-reading function!",tmp);
   end
 end
+
+if length (op0) + length (op1) < 3
+  error ("Either 'op0' or 'op1' should be specified");
+end
+
+###
+
+if length (op0)
+  if op0(1) != " ", op0 = [" ",op0]; end;
+  if op0(length(op0)) != " ", op0 = [op0," "]; end;
+end
+
+if length (op1)
+  if op1(1) != " ", op1 = [" ",op1]; end;
+  if op1(length(op1)) != " ", op1 = [op1," "]; end;
+end
+
+opts = [op0,op1];		# Join options
+				# Before iend : opts w/out arg. After, opts
+iend = length (op0);		# w/ arg
+
+spi = find (opts == " ");
+
+opts_orig = opts;
+
+if nocase, opts = tolower (opts); end
+
+nread = 0;
+while nread < length (args)
+  
+  oname = name = nth (args, ++nread);
+  if ! isstr (name)		# Whoa! Option name is not a string
+    if quiet, nread--; return;
+    else      error ("option name in pos %i is not a string",nread);
+    end
+  end
+  if nocase, name = tolower (name); end
+  
+  ii = findstr (name, opts);
+  
+  if isempty (ii)		# Whoa! Unknown option name
+    if quiet, nread--; return;
+    else      error ("unknown option '%s'",oname);
+    end
+  end
+  
+  if length (ii) > 1		# Ambiguous option name
+    tmp = "";
+    for i = ii
+      tmp = [tmp,"', '",opts(i:spi(find (spi > i)(1))-1)];
+    end
+    tmp = tmp(1:length(tmp)-3);
+    error ("ambiguous option '%s'. Could be '%s'",oname,tmp);
+  end
+
+				# Full name of option (w/ correct case)
+
+  fullname = opts_orig(ii:spi(find (spi > ii)(1))-1);
+
+  if ii < iend
+    op = setfield (op, fullname, 1);
+  else
+    if nread < length (args)
+      op = setfield (op, fullname, nth (args,++nread));
+    else
+      error ("options end before I can read value of option '%s'",oname);
+    end
+  end
+end