changeset 28901:3c37ae43996a

maint: Code cleanup associated with varargin checking. * runtests.m, flipdim.m: Add newline before "endfunction" for looks. * check_default_input.m: Replace varargin in function prototype with explicit variables y0, yp0. Add input validation on nargin. * annotation.m: Use standard "mod (numel (), 2) != 0" test to check for even number of PROP/VAL pairs. * comet.m: Validate nargin does not exceed number of possible args. * cylinder.m: Move input validation for nargin to top of function. * ostreamtube.m, stream2.m, stream3.m, streamribbon.m, streamtube.m: Call print_usage() if number of input arguments is incorrect rather than homegrown error text. Make error() message for OPTIONS input more specific about what is wrong. Adjust input validation tests to pass again. * __plt__.m: Move input validation for number of inputs to top of function. * rectangle.m: Hyphenate "4-element vector" in error() message. * rose.m: Add input validation for maximum number of inputs. Add BIST test to check new code. * tetramesh.m: Use numel() in preference to length(). * pan.m, rotate3d.m, zoom.m: Switch from using varargin to explictly named input arguments. * etreeplot.m: Add check on maximum number of input arguments. Add BIST tests for input validation code. * strchr.m: Add check on maximum number of input arguments. Add BIST test for new input validation code.
author Rik <rik@octave.org>
date Tue, 13 Oct 2020 11:36:33 -0700
parents f8efd03a553e
children 69bd3e52d0b8
files scripts/deprecated/runtests.m scripts/legacy/flipdim.m scripts/ode/private/check_default_input.m scripts/plot/appearance/annotation.m scripts/plot/draw/comet.m scripts/plot/draw/cylinder.m scripts/plot/draw/ostreamtube.m scripts/plot/draw/private/__plt__.m scripts/plot/draw/rectangle.m scripts/plot/draw/rose.m scripts/plot/draw/stream2.m scripts/plot/draw/stream3.m scripts/plot/draw/streamribbon.m scripts/plot/draw/streamtube.m scripts/plot/draw/tetramesh.m scripts/plot/util/pan.m scripts/plot/util/rotate3d.m scripts/plot/util/zoom.m scripts/sparse/etreeplot.m scripts/strings/strchr.m
diffstat 20 files changed, 256 insertions(+), 284 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/deprecated/runtests.m	Tue Oct 13 20:08:05 2020 +0200
+++ b/scripts/deprecated/runtests.m	Tue Oct 13 11:36:33 2020 -0700
@@ -53,4 +53,5 @@
   endif
 
   oruntests (varargin{:});
+
 endfunction
--- a/scripts/legacy/flipdim.m	Tue Oct 13 20:08:05 2020 +0200
+++ b/scripts/legacy/flipdim.m	Tue Oct 13 11:36:33 2020 -0700
@@ -40,4 +40,5 @@
   endif
 
   y = flip (varargin{:});
+
 endfunction
--- a/scripts/ode/private/check_default_input.m	Tue Oct 13 20:08:05 2020 +0200
+++ b/scripts/ode/private/check_default_input.m	Tue Oct 13 11:36:33 2020 -0700
@@ -23,7 +23,11 @@
 ##
 ########################################################################
 
-function [fun] = check_default_input (fun, trange, solver, varargin);
+function fun = check_default_input (fun, trange, solver, y0, yp0);
+
+  if (nargin != 4)
+    print_usage ();
+  endif
 
   ## Check fun
   validateattributes (fun, {"function_handle", "char"}, {}, solver, "fun");
@@ -57,7 +61,6 @@
   endif
 
   ## Check y0 and yp0
-  y0 = varargin{1};
   if (! isnumeric (y0) || ! isvector (y0))
     error ("Octave:invalid-input-arg",
            [solver ": Y0 must be a numeric vector"]);
@@ -65,7 +68,6 @@
   y0 = y0(:);
 
   if (nargin == 5)
-    yp0 = varargin{2};
     if (! isnumeric (yp0) || ! isvector (yp0))
       error ("Octave:invalid-input-arg",
              [solver ": YP0 must be a numeric vector"]);
--- a/scripts/plot/appearance/annotation.m	Tue Oct 13 20:08:05 2020 +0200
+++ b/scripts/plot/appearance/annotation.m	Tue Oct 13 11:36:33 2020 -0700
@@ -217,9 +217,8 @@
 
   ## options
   opts = varargin;
-  nopts = numel (opts);
   if (! isempty (opts))
-    if (fix (nopts/2) != nopts/2 || ! all (cellfun (@ischar, opts(1:2:end))))
+    if (mod (numel (opts), 2) != 0 || ! all (cellfun (@ischar, opts(1:2:end))))
       warning ("annotation: couldn't parse PROP/VAL pairs, skipping");
       opts = {};
     endif
--- a/scripts/plot/draw/comet.m	Tue Oct 13 20:08:05 2020 +0200
+++ b/scripts/plot/draw/comet.m	Tue Oct 13 11:36:33 2020 -0700
@@ -46,9 +46,11 @@
 
   [hax, varargin, nargin] = __plt_get_axis_arg__ ("comet", varargin{:});
 
-  if (nargin == 0)
+  if (nargin == 0 || nargin > 3)
     print_usage ();
-  elseif (nargin == 1)
+  endif
+
+  if (nargin == 1)
     y = varargin{1};
     x = 1:numel (y);
     p = 5 / numel (y);
--- a/scripts/plot/draw/cylinder.m	Tue Oct 13 20:08:05 2020 +0200
+++ b/scripts/plot/draw/cylinder.m	Tue Oct 13 11:36:33 2020 -0700
@@ -61,17 +61,17 @@
 
   [hax, args, nargs] = __plt_get_axis_arg__ ("cylinder", varargin{:});
 
-  if (nargs == 0)
+  if (nargs > 2)
+    print_usage ();
+  elseif (nargs == 0)
     r = [1, 1];
     n = 20;
   elseif (nargs == 1)
     r = args{1};
     n = 20;
-  elseif (nargs == 2)
+  else
     r = args{1};
     n = args{2};
-  else
-    print_usage ();
   endif
 
   if (length (r) < 2)
--- a/scripts/plot/draw/ostreamtube.m	Tue Oct 13 20:08:05 2020 +0200
+++ b/scripts/plot/draw/ostreamtube.m	Tue Oct 13 11:36:33 2020 -0700
@@ -97,8 +97,6 @@
   options = [];
   xyz = [];
   switch (nargin)
-    case 0
-      print_usage ();
     case 6
       [u, v, w, spx, spy, spz] = varargin{:};
       [m, n, p] = size (u);
@@ -118,7 +116,7 @@
     case 10
       [x, y, z, u, v, w, spx, spy, spz, options] = varargin{:};
     otherwise
-      error ("ostreamtube: invalid number of inputs");
+      print_usage ();
   endswitch
 
   scale = 1;
@@ -131,7 +129,7 @@
         scale = options(1);
         num_circum = options(2);
       otherwise
-        error ("ostreamtube: invalid number of OPTIONS elements");
+        error ("ostreamtube: OPTIONS must be a 1- or 2-element vector");
     endswitch
 
     if (! isreal (scale) || scale <= 0)
@@ -358,12 +356,12 @@
 
 ## Test input validation
 %!error <Invalid call> ostreamtube ()
-%!error <invalid number of inputs> ostreamtube (1)
-%!error <invalid number of inputs> ostreamtube (1,2)
-%!error <invalid number of inputs> ostreamtube (1,2,3)
-%!error <invalid number of inputs> ostreamtube (1,2,3,4)
-%!error <invalid number of inputs> ostreamtube (1,2,3,4,5)
-%!error <invalid number of OPTIONS> ostreamtube (1,2,3,4,5,6,[1,2,3])
+%!error <Invalid call> ostreamtube (1)
+%!error <Invalid call> ostreamtube (1,2)
+%!error <Invalid call> ostreamtube (1,2,3)
+%!error <Invalid call> ostreamtube (1,2,3,4)
+%!error <Invalid call> ostreamtube (1,2,3,4,5)
+%!error <OPTIONS must be a 1- or 2-element> ostreamtube (1,2,3,4,5,6,[1,2,3])
 %!error <SCALE must be a real scalar . 0> ostreamtube (1,2,3,4,5,6,[1i])
 %!error <SCALE must be a real scalar . 0> ostreamtube (1,2,3,4,5,6,[0])
 %!error <N must be greater than 2> ostreamtube (1,2,3,4,5,6,[1,1i])
--- a/scripts/plot/draw/private/__plt__.m	Tue Oct 13 20:08:05 2020 +0200
+++ b/scripts/plot/draw/private/__plt__.m	Tue Oct 13 11:36:33 2020 -0700
@@ -33,125 +33,124 @@
   persistent warned_callers = {};
   nargs = nargin - 2;
 
-  if (nargs > 0)
+  if (nargs < 1)
+    error ("__plt__: invalid number of arguments");
+  endif
 
-    k = 1;
+  k = 1;
 
-    x_set = false;
-    y_set = false;
-    property_set = false;
-    properties = {};
+  x_set = false;
+  y_set = false;
+  property_set = false;
+  properties = {};
+
+  ## Find any legend associated with this axes
+  try
+    hlegend = get (hp, "__legend_handle__");
+  catch
+    hlegend = [];
+  end_try_catch
 
-    ## Find any legend associated with this axes
-    try
-      hlegend = get (hp, "__legend_handle__");
-    catch
-      hlegend = [];
-    end_try_catch
+  setlgnd = false;
+  if (isempty (hlegend))
+    hlgnd = [];
+    tlgnd = {};
+  else
+    [hlgnd, tlgnd] = __getlegenddata__ (hlegend);
+  endif
+
+  ## Gather arguments, decode format, gather plot strings, and plot lines.
 
-    setlgnd = false;
-    if (isempty (hlegend))
-      hlgnd = [];
-      tlgnd = {};
+  retval = [];
+
+  while (nargs > 0 || x_set)
+
+    if (nargs == 0)
+      ## Force the last plot when input variables run out.
+      next_cell = {};
+      next_arg = {""};
     else
-      [hlgnd, tlgnd] = __getlegenddata__ (hlegend);
+      next_cell = varargin(k);
+      next_arg = varargin{k++};
     endif
 
-    ## Gather arguments, decode format, gather plot strings, and plot lines.
-
-    retval = [];
-
-    while (nargs > 0 || x_set)
-
-      if (nargs == 0)
-        ## Force the last plot when input variables run out.
-        next_cell = {};
-        next_arg = {""};
-      else
-        next_cell = varargin(k);
-        next_arg = varargin{k++};
+    if (isnumeric (next_arg) && ndims (next_arg) > 2
+        && any (size (next_arg) == 1))
+      next_arg = squeeze (next_arg);
+      if (! any (strcmp (caller, warned_callers)) && ndims (next_arg) < 3)
+        warning (["%s: N-d inputs have been squeezed to less than " ...
+                  "three dimensions"], caller);
+        warned_callers(end+1) = caller;
       endif
+    endif
+    if (isnumeric (next_arg) && ndims (next_arg) > 2)
+      error ("%s: plot arrays must have less than 2 dimensions", caller);
+    endif
 
-      if (isnumeric (next_arg) && ndims (next_arg) > 2
-          && any (size (next_arg) == 1))
-        next_arg = squeeze (next_arg);
-        if (! any (strcmp (caller, warned_callers)) && ndims (next_arg) < 3)
-          warning (["%s: N-d inputs have been squeezed to less than " ...
-                    "three dimensions"], caller);
-          warned_callers(end+1) = caller;
-        endif
-      endif
-      if (isnumeric (next_arg) && ndims (next_arg) > 2)
-        error ("%s: plot arrays must have less than 2 dimensions", caller);
-      endif
-
-      nargs -= 1;
+    nargs -= 1;
 
-      if (ischar (next_arg) || iscellstr (next_arg))
-        if (x_set)
-          [options, valid] = __pltopt__ (caller, next_arg, false);
-          if (! valid)
-            if (nargs == 0)
-              error ("%s: properties must appear followed by a value", caller);
-            endif
-            properties = [properties, [next_cell, varargin(k++)]];
-            nargs -= 1;
-            continue;
-          else
-            while (nargs > 0 && ischar (varargin{k}))
-              if (nargs < 2)
-                error ("%s: properties must appear followed by a value",
-                       caller);
-              endif
-              properties = [properties, varargin(k:k+1)];
-              k += 2;
-              nargs -= 2;
-            endwhile
+    if (ischar (next_arg) || iscellstr (next_arg))
+      if (x_set)
+        [options, valid] = __pltopt__ (caller, next_arg, false);
+        if (! valid)
+          if (nargs == 0)
+            error ("%s: properties must appear followed by a value", caller);
           endif
-          if (y_set)
-            htmp = __plt2__ (hp, x, y, options, properties);
-            [hlgnd, tlgnd, setlgnd] = ...
-              __plt_key__ (htmp, options, hlgnd, tlgnd, setlgnd);
-            properties = {};
-            retval = [retval; htmp];
-          else
-            htmp = __plt1__ (hp, x, options, properties);
-            [hlgnd, tlgnd, setlgnd] = ...
-               __plt_key__ (htmp, options, hlgnd, tlgnd, setlgnd);
-            properties = {};
-            retval = [retval; htmp];
-          endif
-          x_set = false;
-          y_set = false;
+          properties = [properties, [next_cell, varargin(k++)]];
+          nargs -= 1;
+          continue;
         else
-          error ("plot: no data to plot");
+          while (nargs > 0 && ischar (varargin{k}))
+            if (nargs < 2)
+              error ("%s: properties must appear followed by a value",
+                     caller);
+            endif
+            properties = [properties, varargin(k:k+1)];
+            k += 2;
+            nargs -= 2;
+          endwhile
         endif
-      elseif (x_set)
         if (y_set)
-          options = __pltopt__ (caller, {""});
           htmp = __plt2__ (hp, x, y, options, properties);
           [hlgnd, tlgnd, setlgnd] = ...
             __plt_key__ (htmp, options, hlgnd, tlgnd, setlgnd);
+          properties = {};
           retval = [retval; htmp];
-          x = next_arg;
-          y_set = false;
-          properties = {};
         else
-          y = next_arg;
-          y_set = true;
+          htmp = __plt1__ (hp, x, options, properties);
+          [hlgnd, tlgnd, setlgnd] = ...
+             __plt_key__ (htmp, options, hlgnd, tlgnd, setlgnd);
+          properties = {};
+          retval = [retval; htmp];
         endif
+        x_set = false;
+        y_set = false;
       else
+        error ("plot: no data to plot");
+      endif
+    elseif (x_set)
+      if (y_set)
+        options = __pltopt__ (caller, {""});
+        htmp = __plt2__ (hp, x, y, options, properties);
+        [hlgnd, tlgnd, setlgnd] = ...
+          __plt_key__ (htmp, options, hlgnd, tlgnd, setlgnd);
+        retval = [retval; htmp];
         x = next_arg;
-        x_set = true;
+        y_set = false;
+        properties = {};
+      else
+        y = next_arg;
+        y_set = true;
       endif
-
-    endwhile
+    else
+      x = next_arg;
+      x_set = true;
+    endif
 
-    if (setlgnd)
-      legend (gca (), hlgnd, tlgnd);
-    endif
-  else
-    error ("__plt__: invalid number of arguments");
+  endwhile
+
+  if (setlgnd)
+    legend (gca (), hlgnd, tlgnd);
   endif
 
 endfunction
--- a/scripts/plot/draw/rectangle.m	Tue Oct 13 20:08:05 2020 +0200
+++ b/scripts/plot/draw/rectangle.m	Tue Oct 13 11:36:33 2020 -0700
@@ -107,7 +107,7 @@
         pos = varargin{iarg+1};
         varargin(iarg:iarg+1) = [];
         if (! isvector (pos) || numel (pos) != 4)
-          error ("rectangle: position must be a 4 element vector");
+          error ("rectangle: position must be a 4-element vector");
         endif
       elseif (strcmpi (arg, "curvature"))
         curv2 = varargin{iarg+1};
--- a/scripts/plot/draw/rose.m	Tue Oct 13 20:08:05 2020 +0200
+++ b/scripts/plot/draw/rose.m	Tue Oct 13 11:36:33 2020 -0700
@@ -72,7 +72,7 @@
 
   [hax, varargin, nargin] = __plt_get_axis_arg__ ("rose", varargin{:});
 
-  if (nargin < 1)
+  if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
 
@@ -167,6 +167,7 @@
 
 ## Test input validation
 %!error <Invalid call> rose ()
+%!error <Invalid call> rose (1,2,3)
 %!warning <bin sizes .= pi will not plot correctly>
 %! [th, r] = rose ([1 2 2 4 4 4], 2);
 %!warning <bin 1 and bin 3 are not centered>
--- a/scripts/plot/draw/stream2.m	Tue Oct 13 20:08:05 2020 +0200
+++ b/scripts/plot/draw/stream2.m	Tue Oct 13 11:36:33 2020 -0700
@@ -82,8 +82,6 @@
 
   options = [];
   switch (numel (varargin))
-    case 0
-      print_usage ();
     case {4,5}
       if (numel (varargin) == 4)
         [u, v, spx, spy] = varargin{:};
@@ -97,7 +95,7 @@
     case 7
       [x, y, u, v, spx, spy, options] = varargin{:};
     otherwise
-      error ("stream2: invalid number of inputs");
+      print_usage ();
   endswitch
 
   stepsize = 0.1;
@@ -110,7 +108,7 @@
         stepsize = options(1);
         max_vertices = options(2);
       otherwise
-        error ("stream2: invalid number of OPTIONS elements");
+        error ("stream2: OPTIONS must be a 1- or 2-element vector");
     endswitch
 
     if (! isreal (stepsize) || stepsize == 0)
@@ -208,10 +206,10 @@
 
 ## Test input validation
 %!error <Invalid call> stream2 ()
-%!error <invalid number of inputs> stream2 (1)
-%!error <invalid number of inputs> stream2 (1,2)
-%!error <invalid number of inputs> stream2 (1,2,3)
-%!error <invalid number of OPTIONS> stream2 (1,2,3,4, [1,2,3])
+%!error <Invalid call> stream2 (1)
+%!error <Invalid call> stream2 (1,2)
+%!error <Invalid call> stream2 (1,2,3)
+%!error <OPTIONS must be a 1- or 2-element> stream2 (1,2,3,4, [1,2,3])
 %!error <STEPSIZE must be a real scalar != 0> stream2 (1,2,3,4, [1i])
 %!error <STEPSIZE must be a real scalar != 0> stream2 (1,2,3,4, [0])
 %!error <MAX_VERTICES must be an integer> stream2 (1,2,3,4, [1, 1i])
--- a/scripts/plot/draw/stream3.m	Tue Oct 13 20:08:05 2020 +0200
+++ b/scripts/plot/draw/stream3.m	Tue Oct 13 11:36:33 2020 -0700
@@ -83,8 +83,6 @@
 
   options = [];
   switch (numel (varargin))
-    case 0
-      print_usage ();
     case {6,7}
       if (numel (varargin) == 6)
         [u, v, w, spx, spy, spz] = varargin{:};
@@ -98,7 +96,7 @@
     case 10
       [x, y, z, u, v, w, spx, spy, spz, options] = varargin{:};
     otherwise
-      error ("stream3: invalid number of inputs");
+      print_usage ();
   endswitch
 
   stepsize = 0.1;
@@ -111,7 +109,7 @@
         stepsize = options(1);
         max_vertices = options(2);
       otherwise
-        error ("stream3: invalid number of OPTIONS elements");
+        error ("stream3: OPTIONS must be a 1- or 2-element vector");
     endswitch
 
     if (! isreal (stepsize) || stepsize == 0)
@@ -232,13 +230,13 @@
 
 ## Test input validation
 %!error <Invalid call> stream3 ()
-%!error <invalid number of inputs> stream3 (1)
-%!error <invalid number of inputs> stream3 (1,2)
-%!error <invalid number of inputs> stream3 (1,2,3)
-%!error <invalid number of inputs> stream3 (1,2,3,4)
-%!error <invalid number of inputs> stream3 (1,2,3,4,5)
-%!error <invalid number of inputs> stream3 (1,2,3,4,5,6,7,8)
-%!error <invalid number of OPTIONS> stream3 (1,2,3,4,5,6, [1,2,3])
+%!error <Invalid call> stream3 (1)
+%!error <Invalid call> stream3 (1,2)
+%!error <Invalid call> stream3 (1,2,3)
+%!error <Invalid call> stream3 (1,2,3,4)
+%!error <Invalid call> stream3 (1,2,3,4,5)
+%!error <Invalid call> stream3 (1,2,3,4,5,6,7,8)
+%!error <OPTIONS must be a 1- or 2-element> stream3 (1,2,3,4,5,6, [1,2,3])
 %!error <STEPSIZE must be a real scalar != 0> stream3 (1,2,3,4,5,6, [1i])
 %!error <STEPSIZE must be a real scalar != 0> stream3 (1,2,3,4,5,6, [0])
 %!error <MAX_VERTICES must be an integer> stream3 (1,2,3,4,5,6, [1, 1i])
--- a/scripts/plot/draw/streamribbon.m	Tue Oct 13 20:08:05 2020 +0200
+++ b/scripts/plot/draw/streamribbon.m	Tue Oct 13 11:36:33 2020 -0700
@@ -134,8 +134,6 @@
   lin_spd = [];
   anlr_rot = [];
   switch (nargin)
-    case 0
-      print_usage ();
     case 2
       [xyz, anlr_rot] = varargin{:};
     case 3
@@ -171,7 +169,7 @@
     case 10
       [x, y, z, u, v, w, spx, spy, spz, width] = varargin{:};
     otherwise
-      error ("streamribbon: invalid number of inputs");
+      print_usage ();
   endswitch
 
   if (isempty (xyz))
@@ -434,10 +432,10 @@
 
 ## Test input validation
 %!error <Invalid call> streamribbon ()
-%!error <invalid number of inputs> streamribbon (1)
-%!error <invalid number of inputs> streamribbon (1,2,3,4,5)
-%!error <invalid number of inputs> streamribbon (1,2,3,4,5,6,7,8)
-%!error <invalid number of inputs> streamribbon (1,2,3,4,5,6,7,8,9,10,11)
+%!error <Invalid call> streamribbon (1)
+%!error <Invalid call> streamribbon (1,2,3,4,5)
+%!error <Invalid call> streamribbon (1,2,3,4,5,6,7,8)
+%!error <Invalid call> streamribbon (1,2,3,4,5,6,7,8,9,10,11)
 %!error <WIDTH must be a real scalar . 0> streamribbon (1,2,3,1i)
 %!error <WIDTH must be a real scalar . 0> streamribbon (1,2,3,0)
 %!error <WIDTH must be a real scalar . 0> streamribbon (1,2,3,-1)
--- a/scripts/plot/draw/streamtube.m	Tue Oct 13 20:08:05 2020 +0200
+++ b/scripts/plot/draw/streamtube.m	Tue Oct 13 11:36:33 2020 -0700
@@ -78,8 +78,6 @@
   div = [];
   dia = [];
   switch (nargin)
-    case 0
-      print_usage ();
     case 2
       ## "dia" can be a cell array or a constant
       if (iscell (varargin{2}) || numel (varargin{2}) == 1)
@@ -116,7 +114,7 @@
     case 10
       [x, y, z, u, v, w, spx, spy, spz, options] = varargin{:};
     otherwise
-      error ("streamtube: invalid number of inputs");
+      print_usage ();
   endswitch
 
   scale = 1;
@@ -129,7 +127,7 @@
         scale = options(1);
         num_circum = options(2);
       otherwise
-        error ("streamtube: invalid number of OPTIONS elements");
+        error ("streamtube: OPTIONS must be a 1- or 2-element vector");
     endswitch
 
     if (! isreal (scale) || scale <= 0)
@@ -368,11 +366,11 @@
 
 ## Test input validation
 %!error <Invalid call> streamtube ()
-%!error <invalid number of inputs> streamtube (1)
-%!error <invalid number of inputs> streamtube (1,2,3,4)
-%!error <invalid number of inputs> streamtube (1,2,3,4,5,6,7,8)
-%!error <invalid number of inputs> streamtube (1,2,3,4,5,6,7,8,9,10,11)
-%!error <invalid number of OPTIONS elements> streamtube (1,2,[1,2,3])
+%!error <Invalid call> streamtube (1)
+%!error <Invalid call> streamtube (1,2,3,4)
+%!error <Invalid call> streamtube (1,2,3,4,5,6,7,8)
+%!error <Invalid call> streamtube (1,2,3,4,5,6,7,8,9,10,11)
+%!error <OPTIONS must be a 1- or 2-element vector> streamtube (1,2,[1,2,3])
 %!error <SCALE must be a real scalar . 0> streamtube (1,2,[1i])
 %!error <SCALE must be a real scalar . 0> streamtube (1,2,[0])
 %!error <SCALE must be a real scalar . 0> streamtube (1,2,[-1])
--- a/scripts/plot/draw/tetramesh.m	Tue Oct 13 20:08:05 2020 +0200
+++ b/scripts/plot/draw/tetramesh.m	Tue Oct 13 11:36:33 2020 -0700
@@ -59,7 +59,7 @@
 
   [reg, prop] = parseparams (varargin);
 
-  if (length (reg) < 2 || length (reg) > 3)
+  if (numel (reg) < 2 || numel (reg) > 3)
     print_usage ();
   endif
 
--- a/scripts/plot/util/pan.m	Tue Oct 13 20:08:05 2020 +0200
+++ b/scripts/plot/util/pan.m	Tue Oct 13 11:36:33 2020 -0700
@@ -46,35 +46,31 @@
 ## @seealso{rotate3d, zoom}
 ## @end deftypefn
 
-function pan (varargin)
-
-  hfig = NaN;
-
-  nargs = nargin;
+function h = pan (hfig, option)
 
-  if (nargs > 2)
-    print_usage ();
-  endif
-
-  if (nargin == 1 && nargout > 0 && isfigure (varargin{1}))
+  ## FIXME: Presumably should implement this for Matlab compatibility.
+  if (nargin == 1 && nargout > 0 && isfigure (hfig))
     error ("pan: syntax 'handle = pan (hfig)' not implemented");
   endif
 
-  if (nargs == 2)
-    hfig = varargin{1};
-    if (isfigure (hfig))
-      varargin(1) = [];
-      nargs -= 1;
+  if (nargin == 0)
+    hfig = gcf ();
+  else
+    if (nargin == 1)
+      option = hfig;
+      hfig = gcf ();
     else
-      error ("pan: invalid figure handle HFIG");
+      if (! isfigure (hfig))
+        error ("pan: invalid figure handle HFIG");
+      endif
+    endif
+
+    if (! ischar (option))
+      error ("pan: OPTION must be a string");
     endif
   endif
 
-  if (isnan (hfig))
-    hfig = gcf ();
-  endif
-
-  if (nargs == 0)
+  if (nargin == 0)
     pm = get (hfig, "__pan_mode__");
     if (strcmp (pm.Enable, "on"))
       pm.Enable = "off";
@@ -83,31 +79,26 @@
     endif
     set (hfig, "__pan_mode__", pm);
     update_mouse_mode (hfig, pm.Enable);
-  elseif (nargs == 1)
-    arg = varargin{1};
-    if (ischar (arg))
-      switch (arg)
-        case {"on", "off", "xon", "yon"}
-          pm = get (hfig, "__pan_mode__");
-          switch (arg)
-            case {"on", "off"}
-              pm.Enable = arg;
-              pm.Motion = "both";
-            case "xon"
-              pm.Enable = "on";
-              pm.Motion = "horizontal";
-            case "yon"
-              pm.Enable = "on";
-              pm.Motion = "vertical";
-          endswitch
-          set (hfig, "__pan_mode__", pm);
-          update_mouse_mode (hfig, arg);
-        otherwise
-          error ("pan: unrecognized OPTION '%s'", arg);
-      endswitch
-    else
-      error ("pan: wrong type argument '%s'", class (arg));
-    endif
+  else
+    switch (option)
+      case {"on", "off", "xon", "yon"}
+        pm = get (hfig, "__pan_mode__");
+        switch (option)
+          case {"on", "off"}
+            pm.Enable = option;
+            pm.Motion = "both";
+          case "xon"
+            pm.Enable = "on";
+            pm.Motion = "horizontal";
+          case "yon"
+            pm.Enable = "on";
+            pm.Motion = "vertical";
+        endswitch
+        set (hfig, "__pan_mode__", pm);
+        update_mouse_mode (hfig, option);
+      otherwise
+        error ("pan: unrecognized OPTION '%s'", option);
+    endswitch
   endif
 
 endfunction
@@ -119,8 +110,8 @@
   else
     ## FIXME: Is there a better way other than calling these functions
     ##        to set the other mouse mode Enable fields to "off"?
-    rotate3d ("off");
-    zoom ("off");
+    rotate3d (hfig, "off");
+    zoom (hfig, "off");
     set (hfig, "__mouse_mode__", "pan");
   endif
 
--- a/scripts/plot/util/rotate3d.m	Tue Oct 13 20:08:05 2020 +0200
+++ b/scripts/plot/util/rotate3d.m	Tue Oct 13 11:36:33 2020 -0700
@@ -41,35 +41,31 @@
 ## @seealso{pan, zoom}
 ## @end deftypefn
 
-function rotate3d (varargin)
-
-  hfig = NaN;
-
-  nargs = nargin;
+function h = rotate3d (hfig, option)
 
-  if (nargs > 2)
-    print_usage ();
-  endif
-
-  if (nargin == 1 && nargout > 0 && isfigure (varargin{1}))
+  ## FIXME: Presumably should implement this for Matlab compatibility.
+  if (nargin == 1 && nargout > 0 && isfigure (hfig))
     error ("rotate3d: syntax 'handle = rotate3d (hfig)' not implemented");
   endif
 
-  if (nargs == 2)
-    hfig = varargin{1};
-    if (isfigure (hfig))
-      varargin(1) = [];
-      nargs -= 1;
+  if (nargin == 0)
+    hfig = gcf ();
+  else
+    if (nargin == 1)
+      option = hfig;
+      hfig = gcf ();
     else
-      error ("rotate3d: invalid figure handle HFIG");
+      if (! isfigure (hfig))
+        error ("rotate3d: invalid figure handle HFIG");
+      endif
+    endif
+
+    if (! ischar (option))
+      error ("rotate3d: OPTION must be a string");
     endif
   endif
 
-  if (isnan (hfig))
-    hfig = gcf ();
-  endif
-
-  if (nargs == 0)
+  if (nargin == 0)
     rm = get (hfig, "__rotate_mode__");
     if (strcmp (rm.Enable, "on"))
       rm.Enable = "off";
@@ -78,25 +74,17 @@
     endif
     set (hfig, "__rotate_mode__", rm);
     update_mouse_mode (hfig, rm.Enable);
-  elseif (nargs == 1)
-    arg = varargin{1};
-    if (ischar (arg))
-      switch (arg)
-        case {"on", "off"}
-          rm = get (hfig, "__rotate_mode__");
-          switch (arg)
-            case {"on", "off"}
-              rm.Enable = arg;
-              rm.Motion = "both";
-          endswitch
-          set (hfig, "__rotate_mode__", rm);
-          update_mouse_mode (hfig, arg);
-        otherwise
-          error ("rotate3d: unrecognized OPTION '%s'", arg);
-      endswitch
-    else
-      error ("rotate3d: wrong type argument '%s'", class (arg));
-    endif
+  else
+    switch (option)
+      case {"on", "off"}
+        rm = get (hfig, "__rotate_mode__");
+        rm.Enable = option;
+        rm.Motion = "both";
+        set (hfig, "__rotate_mode__", rm);
+        update_mouse_mode (hfig, option);
+      otherwise
+        error ("rotate3d: unrecognized OPTION '%s'", option);
+    endswitch
   endif
 
 endfunction
@@ -106,11 +94,10 @@
   if (strcmp (arg, "off"))
     set (hfig, "__mouse_mode__", "none");
   else
-    ## FIXME: Is there a better way other than calling these
-    ## functions to set the other mouse mode Enable fields to
-    ## "off"?
-    pan ("off");
-    zoom ("off");
+    ## FIXME: Is there a better way other than calling these functions
+    ##        to set the other mouse mode Enable fields to "off"?
+    pan (hfig, "off");
+    zoom (hfig, "off");
     set (hfig, "__mouse_mode__", "rotate");
   endif
 
--- a/scripts/plot/util/zoom.m	Tue Oct 13 20:08:05 2020 +0200
+++ b/scripts/plot/util/zoom.m	Tue Oct 13 11:36:33 2020 -0700
@@ -64,33 +64,27 @@
 ## Eventually we need to also support these features:
 ## @deftypefnx {} {zoom_object_handle =} zoom (@var{hfig})
 
-function zoom (varargin)
+function h = zoom (hfig, option)
 
-  nargs = nargin;
-  if (nargs > 2)
-    print_usage ();
-  endif
-
-  if (nargs == 1 && nargout > 0 && isfigure (varargin{1}))
+  ## FIXME: Presumably should implement this for Matlab compatibility.
+  if (nargin == 1 && nargout > 0 && isfigure (hfig))
     error ("zoom: syntax 'handle = zoom (hfig)' not implemented");
   endif
 
-  hfig = NaN;
-  if (nargs == 2)
-    hfig = varargin{1};
-    if (isfigure (hfig))
-      varargin(1) = [];
-      nargs -= 1;
+  if (nargin == 0)
+    hfig = gcf ();
+  else
+    if (nargin == 1)
+      option = hfig;
+      hfig = gcf ();
     else
-      error ("zoom: invalid figure handle HFIG");
+      if (! isfigure (hfig))
+        error ("zoom: invalid figure handle HFIG");
+      endif
     endif
   endif
 
-  if (isnan (hfig))
-    hfig = gcf ();
-  endif
-
-  if (nargs == 0)
+  if (nargin == 0)
     zm = get (hfig, "__zoom_mode__");
     if (strcmp (zm.Enable, "on"))
       zm.Enable = "off";
@@ -99,10 +93,9 @@
     endif
     set (hfig, "__zoom_mode__", zm);
     update_mouse_mode (hfig, zm.Enable);
-  elseif (nargs == 1)
-    arg = varargin{1};
-    if (isnumeric (arg))
-      factor = arg;
+  else
+    if (isnumeric (option))
+      factor = option;
       switch (numel (factor))
         case 2
           xfactor = factor(1);
@@ -110,10 +103,10 @@
         case 1
           xfactor = yfactor = factor;
         otherwise
-          error ("zoom: invalid FACTOR");
+          error ("zoom: FACTOR must be a 1- or 2-element vector");
       endswitch
-      if (xfactor < 0 || yfactor < 0)
-        error ("zoom: FACTOR must be greater than 1");
+      if (xfactor <= 0 || yfactor <= 0)
+        error ("zoom: FACTOR must be greater than 0");
       elseif (xfactor == 1 && yfactor == 1)
         return;
       endif
@@ -132,13 +125,13 @@
         endif
         __zoom__ (cax, mode, factor);
       endif
-    elseif (ischar (arg))
-      switch (arg)
+    elseif (ischar (option))
+      switch (option)
         case {"on", "off", "xon", "yon"}
           zm = get (hfig, "__zoom_mode__");
-          switch (arg)
+          switch (option)
             case {"on", "off"}
-              zm.Enable = arg;
+              zm.Enable = option;
               zm.Motion = "both";
             case "xon"
               zm.Enable = "on";
@@ -148,7 +141,7 @@
               zm.Motion = "vertical";
           endswitch
           set (hfig, "__zoom_mode__", zm);
-          update_mouse_mode (hfig, arg);
+          update_mouse_mode (hfig, option);
         case "out"
           cax = get (hfig, "currentaxes");
           if (! isempty (cax))
@@ -160,10 +153,10 @@
             __zoom__ (cax, "reset");
           endif
         otherwise
-          error ("zoom: unrecognized OPTION '%s'", arg);
+          error ("zoom: unrecognized OPTION '%s'", option);
       endswitch
     else
-      error ("zoom: wrong type argument '%s'", class (arg));
+      error ("zoom: OPTION must be a number or a string");
     endif
   endif
 
@@ -176,8 +169,8 @@
   else
     ## FIXME: Is there a better way other than calling these functions
     ##        to set the other mouse mode Enable fields to "off"?
-    pan ("off");
-    rotate3d ("off");
+    pan (hfig, "off");
+    rotate3d (hfig, "off");
     set (hfig, "__mouse_mode__", "zoom");
   endif
 
--- a/scripts/sparse/etreeplot.m	Tue Oct 13 20:08:05 2020 +0200
+++ b/scripts/sparse/etreeplot.m	Tue Oct 13 11:36:33 2020 -0700
@@ -36,10 +36,15 @@
 
 function etreeplot (A, varargin)
 
-  if (nargin < 1)
+  if (nargin < 1 || nargin > 3)
     print_usage ();
   endif
 
   treeplot (etree (A+A'), varargin{:});
 
 endfunction
+
+
+## Test input validation
+%!error <Invalid call> etreeplot ()
+%!error <Invalid call> etreeplot (1,2,3,4)
--- a/scripts/strings/strchr.m	Tue Oct 13 20:08:05 2020 +0200
+++ b/scripts/strings/strchr.m	Tue Oct 13 11:36:33 2020 -0700
@@ -41,7 +41,7 @@
 
 function varargout = strchr (str, chars, varargin)
 
-  if (nargin < 2)
+  if (nargin < 2 || nargin > 4)
     print_usage ();
   elseif (! ischar (str))
     error ("strchr: STR argument must be a string or string array");
@@ -84,5 +84,6 @@
 ## Test input validation
 %!error <Invalid call> strchr ()
 %!error <Invalid call> strchr (1)
+%!error <Invalid call> strchr ("s", "a", 1, "last", 5)
 %!error <STR argument must be a string> strchr (1, "aeiou")
 %!error <CHARS argument must be a string> strchr ("aeiou", 1)