changeset 4933:cd58733c326b

[project @ 2004-08-05 16:08:28 by jwe]
author jwe
date Thu, 05 Aug 2004 16:08:28 +0000
parents 43f4ebd2704c
children ca6c86504105
files doc/interpreter/func.txi liboctave/ChangeLog liboctave/EIG.cc src/ChangeLog src/Makefile.in src/file-io.cc src/oct-strstrm.cc src/oct-strstrm.h src/ov-base.cc src/ov-base.h src/ov-cell.cc src/ov-fcn-handle.cc src/ov-fcn-handle.h src/ov-fcn-inline.cc src/ov-fcn-inline.h src/ov.cc src/ov.h src/pr-output.cc
diffstat 18 files changed, 620 insertions(+), 303 deletions(-) [+]
line wrap: on
line diff
--- a/doc/interpreter/func.txi	Thu Aug 05 13:26:15 2004 +0000
+++ b/doc/interpreter/func.txi	Thu Aug 05 16:08:28 2004 +0000
@@ -23,6 +23,7 @@
 * Function Files::              
 * Script Files::                
 * Dynamically Linked Functions::  
+* Function Handles and Inline::
 * Organization of Functions::   
 @end menu
 
@@ -323,12 +324,12 @@
 
 @node Variable-length Argument Lists
 @section Variable-length Argument Lists
-@cindex Variable-length argument lists
+@cindex variable-length argument lists
 @cindex @code{...}
 
 @node Variable-length Return Lists
 @section Variable-length Return Lists
-@cindex Variable-length return lists
+@cindex variable-length return lists
 @cindex @code{...}
 
 @node Returning From a Function
@@ -773,6 +774,39 @@
 can call in a built-in function.  For the time being, you will have to
 read the source code for Octave.
 
+@node Function Handles and Inline
+@section Function Handles and Inline
+@cindex handle, function handles
+@cindex inline, inline functions
+
+This is a place holder for the description of function handles and
+inline functions.
+
+@menu
+* Function Handles::
+* Inline Functions::
+@end menu
+
+@node Function Handles
+@subsection Function Handles
+
+@DOCSTRING(functions)
+
+@DOCSTRING(func2str)
+
+@DOCSTRING(str2func)
+
+@node Inline Functions
+@subsection Inline Functions
+
+@DOCSTRING(inline)
+
+@DOCSTRING(argnames)
+
+@DOCSTRING(formula)
+
+@DOCSTRING(vectorize)
+
 @node Organization of Functions
 @section Organization of Functions Distributed with Octave
 
--- a/liboctave/ChangeLog	Thu Aug 05 13:26:15 2004 +0000
+++ b/liboctave/ChangeLog	Thu Aug 05 16:08:28 2004 +0000
@@ -1,5 +1,7 @@
 2004-08-05  John W. Eaton  <jwe@octave.org>
 
+	* EIG.cc (EIG::init): Add volatile qualifier to nvr decl.
+
 	* intNDArray.cc (intNDArray<T>::operator !, intNDArray<T>::all,
 	intNDArray<T>::any): Sprinkle with this-> as needed.
 	* mx-inlines.cc (MX_ND_REDUCTION, MX_ND_CUMULATIVE_OP): Likewise.
--- a/liboctave/EIG.cc	Thu Aug 05 13:26:15 2004 +0000
+++ b/liboctave/EIG.cc	Thu Aug 05 16:08:28 2004 +0000
@@ -95,7 +95,7 @@
   Array<double> wi (n);
   double *pwi = wi.fortran_vec ();
 
-  int nvr = calc_ev ? n : 0;
+  volatile int nvr = calc_ev ? n : 0;
   Matrix vr (nvr, nvr);
   double *pvr = vr.fortran_vec ();
 
--- a/src/ChangeLog	Thu Aug 05 13:26:15 2004 +0000
+++ b/src/ChangeLog	Thu Aug 05 16:08:28 2004 +0000
@@ -1,3 +1,29 @@
+2004-08-05  David Bateman  <dbateman@free.fr>
+
+	* ov.cc (octave_value::fcn_inline_value): New virtual function.
+	* ov.h (octave_value::fcn_inline_value): Provide decl.
+	* ov-base.cc (octave_base_value::fcn_inline_value): New function
+	* ov-base.h (octave_base_value::fcn_inline_value): Provide decl.
+	* ov-fcn-handle.cc (octave_fcn_handle::octave_fcn_handle 
+	(const std::string&, const string_vector&, const std::string&),
+	octave_fcn_handle::convert_to_str_internal, Finline, Fargnames,
+	Fformula, Fvectorize): Delete.
+	(octave_fcn_handle::print_raw): Remove inline case.
+	* ov-fcn-handle.h (octave_fcn_handle::fcn_type,
+	octave_fcn_handle::octave_fcn_handle (const std::string&, const
+	string_vector&, const std::string&),
+	octave_fcn_handle::inline_fcn_name,
+	octave_fcn_handle::inline_fcn_text,
+	octave_fcn_handle::inline_fcn_arg_names,
+	octave_fcn_handle::is_inline,
+	octave_fcn_handle::convert_to_str_internal,
+	octave_fcn_handle::typ, octave_fcn_handle::iftext,
+	octave_fcn_handle::ifargs): Delete constructors,
+	functions, and data members (moved to ov-fcn-inline.h).
+	* Makefile.in: Include ov-fcn-inline.h and ov-fcn-inline.cc where
+	appropriate.
+	* ov-fcn-inline.h, ov-fcn-inline.cc: New class.
+
 2004-08-05  John W. Eaton  <jwe@octave.org>
 
 	* ov-base-int.cc (octave_base_int_matrix<T>::save_ascii,
--- a/src/Makefile.in	Thu Aug 05 13:26:15 2004 +0000
+++ b/src/Makefile.in	Thu Aug 05 16:08:28 2004 +0000
@@ -74,8 +74,8 @@
 	ov-colon.h ov-base.h ov-base-mat.h ov-base-scalar.h \
 	ov-streamoff.h ov-str-mat.h ov-bool-mat.h ov-bool.h \
 	ov-file.h ov-cell.h ov.h ov-fcn.h ov-builtin.h ov-dld-fcn.h \
-	ov-mapper.h ov-usr-fcn.h ov-fcn-handle.h ov-typeinfo.h \
-	ov-type-conv.h \
+	ov-mapper.h ov-usr-fcn.h ov-fcn-handle.h ov-fcn-inline.h \
+	ov-typeinfo.h ov-type-conv.h \
 	$(OV_INTTYPE_INC)
 
 PT_INCLUDES := pt.h pt-all.h pt-arg-list.h pt-assign.h pt-binop.h \
@@ -127,7 +127,7 @@
 	ov-streamoff.cc ov-struct.cc ov-va-args.cc \
 	ov-colon.cc ov-bool-mat.cc ov-bool.cc ov-file.cc ov-cell.cc \
 	ov.cc ov-fcn.cc ov-builtin.cc ov-dld-fcn.cc ov-mapper.cc \
-	ov-usr-fcn.cc ov-fcn-handle.cc ov-typeinfo.cc \
+	ov-usr-fcn.cc ov-fcn-handle.cc ov-fcn-handle.cc ov-typeinfo.cc \
 	$(OV_INTTYPE_SRC)
 
 PT_SRC := pt.cc pt-arg-list.cc pt-assign.cc pt-bp.cc pt-binop.cc \
--- a/src/file-io.cc	Thu Aug 05 13:26:15 2004 +0000
+++ b/src/file-io.cc	Thu Aug 05 16:08:28 2004 +0000
@@ -694,8 +694,6 @@
 
   int result = -1;
 
-  bool return_char_count = true;
-
   int nargin = args.length ();
 
   if (nargin > 1 || (nargin > 0 && args(0).is_string ()))
--- a/src/oct-strstrm.cc	Thu Aug 05 13:26:15 2004 +0000
+++ b/src/oct-strstrm.cc	Thu Aug 05 16:08:28 2004 +0000
@@ -29,7 +29,7 @@
 // Position a stream at OFFSET relative to ORIGIN.
 
 int
-octave_base_strstream::seek (long offset, int origin)
+octave_base_strstream::seek (long, int)
 {
   error ("fseek: invalid operation");
   return -1;
--- a/src/oct-strstrm.h	Thu Aug 05 13:26:15 2004 +0000
+++ b/src/oct-strstrm.h	Thu Aug 05 16:08:28 2004 +0000
@@ -41,7 +41,7 @@
 
   // Position a stream at OFFSET relative to ORIGIN.
 
-  int seek (long offset, int origin);
+  int seek (long, int);
 
   // Return current stream position.
 
--- a/src/ov-base.cc	Thu Aug 05 13:26:15 2004 +0000
+++ b/src/ov-base.cc	Thu Aug 05 16:08:28 2004 +0000
@@ -191,7 +191,7 @@
 }
 
 octave_value
-octave_base_value::resize (const dim_vector& dv) const
+octave_base_value::resize (const dim_vector&) const
 {
   gripe_wrong_type_arg ("octave_base_value::resize ()", type_name ());
   return octave_value ();
@@ -676,6 +676,17 @@
   return retval;
 }
 
+octave_fcn_inline *
+octave_base_value::fcn_inline_value (bool silent)
+{
+  octave_fcn_inline *retval = 0;
+
+  if (! silent)
+    gripe_wrong_type_arg ("octave_base_value::fcn_inline_value()",
+			  type_name ());
+  return retval;
+}
+
 octave_value_list
 octave_base_value::list_value (void) const
 {
--- a/src/ov-base.h	Thu Aug 05 13:26:15 2004 +0000
+++ b/src/ov-base.h	Thu Aug 05 16:08:28 2004 +0000
@@ -102,7 +102,7 @@
 
   octave_value permute (const Array<int>& vec, bool = false) const;
 
-  octave_value resize (const dim_vector& dv) const;
+  octave_value resize (const dim_vector&) const;
 
   bool is_defined (void) const { return false; }
 
@@ -274,6 +274,8 @@
 
   octave_fcn_handle *fcn_handle_value (bool silent = false);
 
+  octave_fcn_inline *fcn_inline_value (bool silent = false);
+
   octave_value_list list_value (void) const;
 
   octave_value convert_to_str_internal (bool pad, bool force) const;
--- a/src/ov-cell.cc	Thu Aug 05 13:26:15 2004 +0000
+++ b/src/ov-cell.cc	Thu Aug 05 16:08:28 2004 +0000
@@ -718,7 +718,7 @@
   OCTAVE_LOCAL_BUFFER (int, hdims, rank);
 
   // Octave uses column-major, while HDF5 uses row-major ordering
-  for (int i = 0; i < rank; i++)
+  for (hsize_t i = 0; i < rank; i++)
     hdims[i] = dv(rank-i-1);
 
   size_hid = H5Dcreate (data_hid, "dims", H5T_NATIVE_INT, space_hid, 
--- a/src/ov-fcn-handle.cc	Thu Aug 05 13:26:15 2004 +0000
+++ b/src/ov-fcn-handle.cc	Thu Aug 05 16:08:28 2004 +0000
@@ -38,7 +38,6 @@
 #include "ov-fcn-handle.h"
 #include "pr-output.h"
 #include "variables.h"
-#include "parse.h"
 
 DEFINE_OCTAVE_ALLOCATOR (octave_fcn_handle);
 
@@ -46,57 +45,6 @@
 				     "function handle",
 				     "function handle");
 
-octave_fcn_handle::octave_fcn_handle (const std::string& f,
-				      const string_vector& a, 
-				      const std::string& n)
-  : typ (fcn_inline), nm (n), iftext (f), ifargs (a) 
-{
-  // Find a function name that isn't already in the symbol table.
-
-  std::string fname = "__inline__";
-
-  while (symbol_exist (fname))
-    fname.append ("X");
-
-  // Form a string representing the function. 
-
-  OSSTREAM buf;
-
-  buf << "function __retval__ = " << fname << "(";
-
-  for (int i = 0; i < ifargs.length (); i++)
-    {
-      if (i > 0)
-	buf << ", ";
-
-      buf << ifargs(i);
-    }
-
-  buf << ")\n  __retval__ = " << iftext << ";\nendfunction" << OSSTREAM_ENDS;
-  
-  // Parse this function and create a user function.
-
-  octave_value eval_args (OSSTREAM_STR (buf)); 
-
-  feval ("eval", eval_args, 0);
-
-  OSSTREAM_FREEZE (buf);
-
-  octave_value tmp = lookup_function (fname);
-
-  if (tmp.is_function ())
-    {
-      fcn = tmp;
-
-      // XXX FIXME XXX -- probably shouldn't be directly altering the
-      // symbol table here.
-
-      fbi_sym_tab->clear_function (fname);
-    }
-  else
-    error ("inline: unable to define function");
-}
-
 octave_value_list
 octave_fcn_handle::subsref (const std::string& type,
 			    const std::list<octave_value_list>& idx,
@@ -146,45 +94,8 @@
 void
 octave_fcn_handle::print_raw (std::ostream& os, bool pr_as_read_syntax) const
 {
-  if (is_inline ())
-    {
-      OSSTREAM buf;
-
-      if (nm.empty ())
-	buf << "@f(";
-      else
-	buf << nm << "(";
-
-      for (int i = 0; i < ifargs.length (); i++)
-	{
-	  if (i)
-	    buf << ", ";
-
-	  buf << ifargs(i);
-	}
-
-      buf << ") = " << iftext << OSSTREAM_ENDS;
-
-      octave_print_internal (os, OSSTREAM_STR (buf), pr_as_read_syntax,
-			     current_print_indent_level ());
-      OSSTREAM_FREEZE (buf);
-    }
-  else
-    octave_print_internal (os, nm, pr_as_read_syntax,
-			   current_print_indent_level ());
-}
-
-octave_value
-octave_fcn_handle::convert_to_str_internal (bool, bool) const
-{
-  octave_value retval;
-
-  if (is_inline ())
-    retval = octave_value (inline_fcn_text ());
-  else
-    error ("convert_to_str_internal: must be an inline function");
-
-  return retval;
+  octave_print_internal (os, nm, pr_as_read_syntax,
+			 current_print_indent_level ());
 }
 
 octave_value
@@ -202,222 +113,103 @@
   return retval;
 }
 
-DEFUN (inline, args, ,
+DEFUN (functions, args, ,
   "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} inline (@var{str})\n\
-@deftypefnx {Built-in Function} {} inline (@var{str}, @var{arg1}, ...)\n\
-@deftypefnx {Built-in Function} {} inline (@var{str}, @var{n})\n\
-Define a function from a string @var{str}.\n\
-\n\
-Create an inline function.  Called with a single argument, the\n\
-function is assumed to have a single argument and will be defined\n\
-as the first isolated lower case character, except i or j.\n\
-\n\
-If the second and subsequent arguments are strings, they are the names of\n\
-the arguments of the function.\n\
-\n\
-If the second argument is an integer @var{n}, the arguments are\n\
-@code{\"x\"}, @code{\"P1\"}, @dots{}, @code{\"P@var{N}\"}.\n\
-@end deftypefn\n\
-@seealso{argnames, formula, vectorize}")
+@deftypefn {Built-in Function} {} functions (@var{fcn_handle})\n\
+Return a struct containing information about the function handle\n\
+@var{fcn_handle}.\n\
+@end deftypefn")
 {
   octave_value retval;
 
-  int nargin = args.length ();
-
-  if (nargin > 0)
+  if (args.length () == 1)
     {
-      std::string fun = args(0).string_value ();
+      octave_fcn_handle *fh = args(0).fcn_handle_value ();
 
       if (! error_state)
 	{
-	  string_vector fargs;
-
-	  if (nargin == 1)
-	    {
-	      fargs.resize (1);
-
-	      // Find the first isolated string as the argument of the
-	      // function.
+	  octave_function *fcn = fh ? fh->function_value (true) : 0;
 
-	      // XXX FIXME XXX -- use just "x" for now.
-	      fargs(0) = "x";
-	    }
-	  else if (nargin == 2 && args(1).is_numeric_type ())
+	  if (fcn)
 	    {
-	      int n = args(1).int_value ();
+	      Octave_map m;
 
-	      if (! error_state)
-		{
-		  if (n >= 0)
-		    {
-		      fargs.resize (n+1);
+	      std::string fh_nm = fh->fcn_name ();
+
+	      m.assign ("function", fh_nm.substr (1));
 
-		      fargs(0) = "x";
+	      if (fcn->is_nested_function ())
+		m.assign ("type", "subfunction");
+	      else
+		m.assign ("type", "simple");
+
+	      std::string nm = fcn->fcn_file_name ();
 
-		      for (int i = 1; i < n+1; i++)
-			{
-			  OSSTREAM buf;
-			  buf << "P" << i << OSSTREAM_ENDS;
-			  fargs(i) = OSSTREAM_STR (buf);
-			  OSSTREAM_FREEZE (buf);
-			}
-		    }
-		  else
-		    {
-		      error ("inline: numeric argument must be nonnegative");
-		      return retval;
-		    }
-		}
+	      if (nm.empty ())
+		m.assign ("file", "built-in function");
 	      else
-		{
-		  error ("inline: expecting second argument to be an integer");
-		  return retval;
-		}
+		m.assign ("file", nm);
+
+	      retval = m;
 	    }
 	  else
-	    {
-	      fargs.resize (nargin - 1);
-
-	      for (int i = 1; i < nargin; i++)
-		{
-		  std::string s = args(i).string_value ();
-
-		  if (! error_state)
-		    fargs(i-1) = s;
-		  else
-		    {
-		      error ("inline: expecting string arguments");
-		      return retval;
-		    }
-		}
-	    }
-
-	  retval = octave_value (new octave_fcn_handle (fun, fargs));
+	    error ("functions: invalid function handle object");
 	}
       else
-	error ("inline: first argument must be a string");
+	error ("functions: argument must be a function handle object");
     }
   else
-    print_usage ("inline");
+    print_usage ("functions");
 
   return retval;
 }
 
-DEFUN (formula, args, ,
+DEFUN (func2str, args, ,
   "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} formula (@var{fun})\n\
-Return a string representing the inline function @var{fun}.\n\
-@end deftypefn\n\
-@seealso{argnames, inline, vectorize}")
+@deftypefn {Built-in Function} {} func2str (@var{fcn_handle})\n\
+Return a string containing the name of the function referenced by\n\
+the function handle @var{fcn_handle}.\n\
+@end deftypefn")
 {
   octave_value retval;
 
-  int nargin = args.length ();
-
-  if (nargin == 1)
+  if (args.length () == 1)
     {
-      octave_fcn_handle* fn = args(0).fcn_handle_value (true);
+      octave_fcn_handle *fh = args(0).fcn_handle_value ();
 
-      if (fn && fn->is_inline ())
-	retval = octave_value (fn->inline_fcn_text ());
+      if (! error_state && fh)
+	{
+	  std::string fh_nm = fh->fcn_name ();
+	  retval = fh_nm.substr (1);
+	}
       else
-	error ("formula: must be an inline function");
+	error ("func2str: expecting valid function handle as first argument");
     }
   else
-    print_usage ("formula");
+    print_usage ("func2str");
 
   return retval;
 }
 
-DEFUN (argnames, args, ,
+DEFUN (str2func, args, ,
   "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} argnames (@var{fun})\n\
-Return a cell array of strings containing the names of the arguments\n\
-of the inline function @var{fun}.\n\
-@end deftypefn\n\
-@seealso{argnames, inline, formula, vectorize}")
+@deftypefn {Built-in Function} {} str2func (@var{fcn_name})\n\
+Return a function handle constructed from the string @var{fcn_name}.\n\
+@end deftypefn")
 {
   octave_value retval;
 
-  int nargin = args.length ();
-
-  if (nargin == 1)
+  if (args.length () == 1)
     {
-      octave_fcn_handle *fn = args(0).fcn_handle_value (true);
-
-      if (fn && fn->is_inline ())
-	{
-	  string_vector t1 = fn->inline_fcn_arg_names ();
+      std::string nm = args(0).string_value ();
 
-	  Cell t2 (dim_vector (t1.length (), 1));
-
-	  for (int i = 0; i < t1.length (); i++)
-	    t2(i) = t1(i);
-
-	  retval = t2;
-	}
+      if (! error_state)
+	retval = make_fcn_handle (nm);
       else
-	error ("argnames: argument must be an inline function");
+	error ("str2func: expecting string as first argument");
     }
   else
-    print_usage ("argnames");
-
-  return retval;
-}
-
-DEFUN (vectorize, args, ,
-  "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} argnames (@var{fun})\n\
-Create a vectorized version of the inline function @var{fun}\n\
-by replacing all occurrences of @code{*}, @code{/}, etc., with\n\
-@code{.*}, @code{./}, etc.\n\
-@end deftypefn\n\
-@seealso{argnames, inline, formula, vectorize}")
-{
-  octave_value retval;
-
-  int nargin = args.length ();
-
-  if (nargin == 1)
-    {
-      octave_fcn_handle* old = args(0).fcn_handle_value (true);
-
-      if (old && old->is_inline ())
-	{
-	  std::string old_func = old->inline_fcn_text ();
-	  std::string new_func;
-
-	  size_t i = 0;
-
-	  while (i < old_func.length ())
-	    {
-	      std::string t1 = old_func.substr (i, 1);
-
-	      if (t1 == "*" || t1 == "/" || t1 == "\\" || t1 == "^")
-		{
-		  if (i && old_func.substr (i-1, 1) != ".")
-		    new_func.append (".");
-
-		  // Special case for ** operator.
-		  if (t1 == "*" && i < (old_func.length () - 1) 
-		      && old_func.substr (i+1, 1) == "*")
-		    {
-		      new_func.append ("*");
-		      i++;
-		    }
-		}
-	      new_func.append (t1);
-	      i++;
-	    }
-
-	  retval = octave_value (new octave_fcn_handle (new_func, old->inline_fcn_arg_names ()));
-	}
-      else
-	error ("vectorize: must be an inline function");
-    }
-  else
-    print_usage ("vectorize");
+    print_usage ("str2func");
 
   return retval;
 }
--- a/src/ov-fcn-handle.h	Thu Aug 05 13:26:15 2004 +0000
+++ b/src/ov-fcn-handle.h	Thu Aug 05 16:08:28 2004 +0000
@@ -36,7 +36,6 @@
 #include "ov-base-mat.h"
 #include "ov-fcn.h"
 #include "ov-typeinfo.h"
-#include "symtab.h"
 
 // Function handles.
 
@@ -44,16 +43,11 @@
 octave_fcn_handle : public octave_base_value
 {
 public:
-  enum fcn_type { fcn_handle = 1, fcn_inline = 2 };
-
   octave_fcn_handle (void)
-    : typ (fcn_handle), fcn (), nm (), iftext (), ifargs () { }
+    : fcn (), nm () { }
 
   octave_fcn_handle (const octave_value& f,  const std::string& n)
-    : typ (fcn_handle), fcn (f), nm (n), iftext (), ifargs () { }
-
-  octave_fcn_handle (const std::string& f, const string_vector& a, 
-		     const std::string& n = std::string ());
+    : fcn (f), nm (n) { }
 
   ~octave_fcn_handle (void) { }
 
@@ -75,17 +69,9 @@
   octave_function *function_value (bool = false)
     { return fcn.function_value (); }
 
-  std::string inline_fcn_name (void) const { return nm; }
-
-  std::string inline_fcn_text (void) const { return iftext; }
-
-  string_vector inline_fcn_arg_names (void) const { return ifargs; }
-
-  bool is_inline (void) const { return (typ == fcn_inline); }
-
   octave_fcn_handle *fcn_handle_value (bool = false) { return this; }
 
-  octave_value convert_to_str_internal (bool, bool) const;
+  std::string fcn_name (void) const { return nm; }
 
   void print (std::ostream& os, bool pr_as_read_syntax = false) const;
 
@@ -103,20 +89,13 @@
 
   DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
 
-  // The type of function handle 
-  fcn_type typ;
+protected:
 
   // The function we are handling.
   octave_value fcn;
 
   // The name of the handle, including the "@".
   std::string nm;
-
-  // The expression of an inline function
-  std::string iftext;
-
-  // The args of an inline function
-  string_vector ifargs;
 };
 
 extern octave_value make_fcn_handle (const std::string& nm);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ov-fcn-inline.cc	Thu Aug 05 16:08:28 2004 +0000
@@ -0,0 +1,368 @@
+/*
+
+Copyright (C) 2004 David Bateman
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+
+In addition to the terms of the GPL, you are permitted to link
+this program with any Open Source program, as defined by the
+Open Source Initiative (www.opensource.org)
+
+*/
+
+#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION)
+#pragma implementation
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <iostream>
+
+#include "defun.h"
+#include "error.h"
+#include "gripes.h"
+#include "oct-map.h"
+#include "ov-base.h"
+#include "ov-fcn-inline.h"
+#include "pr-output.h"
+#include "variables.h"
+#include "parse.h"
+
+DEFINE_OCTAVE_ALLOCATOR (octave_fcn_inline);
+
+DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_fcn_inline,
+				     "inline function",
+				     "inline function");
+
+octave_fcn_inline::octave_fcn_inline (const std::string& f,
+				      const string_vector& a, 
+				      const std::string& n)
+  : octave_fcn_handle (0, n), iftext (f), ifargs (a) 
+{
+  // Find a function name that isn't already in the symbol table.
+
+  std::string fname = "__inline__";
+
+  while (symbol_exist (fname))
+    fname.append ("X");
+
+  // Form a string representing the function. 
+
+  OSSTREAM buf;
+
+  buf << "function __retval__ = " << fname << "(";
+
+  for (int i = 0; i < ifargs.length (); i++)
+    {
+      if (i > 0)
+	buf << ", ";
+
+      buf << ifargs(i);
+    }
+
+  buf << ")\n  __retval__ = " << iftext << ";\nendfunction" << OSSTREAM_ENDS;
+  
+  // Parse this function and create a user function.
+
+  octave_value eval_args (OSSTREAM_STR (buf)); 
+
+  feval ("eval", eval_args, 0);
+
+  OSSTREAM_FREEZE (buf);
+
+  octave_value tmp = lookup_function (fname);
+
+  if (tmp.is_function ())
+    {
+      fcn = tmp;
+
+      // XXX FIXME XXX -- probably shouldn't be directly altering the
+      // symbol table here.
+
+      fbi_sym_tab->clear_function (fname);
+    }
+  else
+    error ("inline: unable to define function");
+}
+
+void
+octave_fcn_inline::print (std::ostream& os, bool pr_as_read_syntax) const
+{
+  print_raw (os, pr_as_read_syntax);
+  newline (os);
+}
+
+void
+octave_fcn_inline::print_raw (std::ostream& os, bool pr_as_read_syntax) const
+{
+  OSSTREAM buf;
+
+  if (nm.empty ())
+    buf << "f(";
+  else
+    buf << nm << "(";
+
+  for (int i = 0; i < ifargs.length (); i++)
+    {
+      if (i)
+	buf << ", ";
+
+      buf << ifargs(i);
+    }
+
+  buf << ") = " << iftext << OSSTREAM_ENDS;
+
+  octave_print_internal (os, OSSTREAM_STR (buf), pr_as_read_syntax,
+			 current_print_indent_level ());
+  OSSTREAM_FREEZE (buf);
+}
+
+octave_value
+octave_fcn_inline::convert_to_str_internal (bool, bool) const
+{
+  return octave_value (fcn_text ());
+}
+
+DEFUN (inline, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} inline (@var{str})\n\
+@deftypefnx {Built-in Function} {} inline (@var{str}, @var{arg1}, ...)\n\
+@deftypefnx {Built-in Function} {} inline (@var{str}, @var{n})\n\
+Create an inline function from the character string @var{str}.\n\
+If called with a single argument, the generated function is\n\
+assumed to have a single argument and will be defined\n\
+as the first isolated lower case character, except i or j.\n\
+\n\
+If the second and subsequent arguments are character strings,\n\
+they are the names of the arguments of the function.\n\
+\n\
+If the second argument is an integer @var{n}, the arguments are\n\
+@code{\"x\"}, @code{\"P1\"}, @dots{}, @code{\"P@var{N}\"}.\n\
+@end deftypefn\n\
+@seealso{argnames, formula, vectorize}")
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargin > 0)
+    {
+      std::string fun = args(0).string_value ();
+
+      if (! error_state)
+	{
+	  string_vector fargs;
+
+	  if (nargin == 1)
+	    {
+	      fargs.resize (1);
+
+	      // Find the first isolated string as the argument of the
+	      // function.
+
+	      // XXX FIXME XXX -- use just "x" for now.
+	      fargs(0) = "x";
+	    }
+	  else if (nargin == 2 && args(1).is_numeric_type ())
+	    {
+	      int n = args(1).int_value ();
+
+	      if (! error_state)
+		{
+		  if (n >= 0)
+		    {
+		      fargs.resize (n+1);
+
+		      fargs(0) = "x";
+
+		      for (int i = 1; i < n+1; i++)
+			{
+			  OSSTREAM buf;
+			  buf << "P" << i << OSSTREAM_ENDS;
+			  fargs(i) = OSSTREAM_STR (buf);
+			  OSSTREAM_FREEZE (buf);
+			}
+		    }
+		  else
+		    {
+		      error ("inline: numeric argument must be nonnegative");
+		      return retval;
+		    }
+		}
+	      else
+		{
+		  error ("inline: expecting second argument to be an integer");
+		  return retval;
+		}
+	    }
+	  else
+	    {
+	      fargs.resize (nargin - 1);
+
+	      for (int i = 1; i < nargin; i++)
+		{
+		  std::string s = args(i).string_value ();
+
+		  if (! error_state)
+		    fargs(i-1) = s;
+		  else
+		    {
+		      error ("inline: expecting string arguments");
+		      return retval;
+		    }
+		}
+	    }
+
+	  retval = octave_value (new octave_fcn_inline (fun, fargs));
+	}
+      else
+	error ("inline: first argument must be a string");
+    }
+  else
+    print_usage ("inline");
+
+  return retval;
+}
+
+DEFUN (formula, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} formula (@var{fun})\n\
+Return a character string representing the inline function @var{fun}.\n\
+Note that @code{char (@var{fun})} is equivalent to\n\
+@code{formula (@var{fun})}.\n\
+@end deftypefn\n\
+@seealso{argnames, inline, vectorize}")
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargin == 1)
+    {
+      octave_fcn_inline* fn = args(0).fcn_inline_value (true);
+
+      if (fn)
+	retval = octave_value (fn->fcn_text ());
+      else
+	error ("formula: must be an inline function");
+    }
+  else
+    print_usage ("formula");
+
+  return retval;
+}
+
+DEFUN (argnames, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} argnames (@var{fun})\n\
+Return a cell array of character strings containing the names of\n\
+the arguments of the inline function @var{fun}.\n\
+@end deftypefn\n\
+@seealso{argnames, inline, formula, vectorize}")
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargin == 1)
+    {
+      octave_fcn_inline *fn = args(0).fcn_inline_value (true);
+
+      if (fn)
+	{
+	  string_vector t1 = fn->fcn_arg_names ();
+
+	  Cell t2 (dim_vector (t1.length (), 1));
+
+	  for (int i = 0; i < t1.length (); i++)
+	    t2(i) = t1(i);
+
+	  retval = t2;
+	}
+      else
+	error ("argnames: argument must be an inline function");
+    }
+  else
+    print_usage ("argnames");
+
+  return retval;
+}
+
+DEFUN (vectorize, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} argnames (@var{fun})\n\
+Create a vectorized version of the inline function @var{fun}\n\
+by replacing all occurrences of @code{*}, @code{/}, etc., with\n\
+@code{.*}, @code{./}, etc.\n\
+@end deftypefn\n\
+@seealso{argnames, inline, formula, vectorize}")
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargin == 1)
+    {
+      octave_fcn_inline* old = args(0).fcn_inline_value (true);
+
+      if (old)
+	{
+	  std::string old_func = old->fcn_text ();
+	  std::string new_func;
+
+	  size_t i = 0;
+
+	  while (i < old_func.length ())
+	    {
+	      std::string t1 = old_func.substr (i, 1);
+
+	      if (t1 == "*" || t1 == "/" || t1 == "\\" || t1 == "^")
+		{
+		  if (i && old_func.substr (i-1, 1) != ".")
+		    new_func.append (".");
+
+		  // Special case for ** operator.
+		  if (t1 == "*" && i < (old_func.length () - 1) 
+		      && old_func.substr (i+1, 1) == "*")
+		    {
+		      new_func.append ("*");
+		      i++;
+		    }
+		}
+	      new_func.append (t1);
+	      i++;
+	    }
+
+	  retval = octave_value (new octave_fcn_inline (new_func, old->fcn_arg_names ()));
+	}
+      else
+	error ("vectorize: must be an inline function");
+    }
+  else
+    print_usage ("vectorize");
+
+  return retval;
+}
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ov-fcn-inline.h	Thu Aug 05 16:08:28 2004 +0000
@@ -0,0 +1,98 @@
+/*
+
+Copyright (C) 2004 David Bateman
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+
+In addition to the terms of the GPL, you are permitted to link
+this program with any Open Source program, as defined by the
+Open Source Initiative (www.opensource.org)
+
+*/
+
+#if !defined (octave_fcn_inline_h)
+#define octave_fcn_inline_h 1
+
+#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION)
+#pragma interface
+#endif
+
+#include <iostream>
+#include <string>
+
+#include "oct-alloc.h"
+
+#include "ov-base.h"
+#include "ov-base-mat.h"
+#include "ov-fcn.h"
+#include "ov-typeinfo.h"
+#include "symtab.h"
+#include "ov-fcn-handle.h"
+
+// Inline functions.
+
+class
+octave_fcn_inline : public octave_fcn_handle
+{
+public:
+
+  octave_fcn_inline (void)
+    : octave_fcn_handle(), iftext (), ifargs () { }
+
+  octave_fcn_inline (const std::string& f, const string_vector& a, 
+		     const std::string& n = std::string ());
+
+  ~octave_fcn_inline (void) { }
+
+  octave_fcn_inline *fcn_inline_value (bool = false) { return this; }
+
+  std::string fcn_text (void) const { return iftext; }
+
+  string_vector fcn_arg_names (void) const { return ifargs; }
+
+  octave_value convert_to_str_internal (bool, bool) const;
+
+  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+
+  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
+
+private:
+
+  // No copying!
+
+  octave_fcn_inline (const octave_fcn_inline& fh);
+
+  octave_fcn_inline& operator = (const octave_fcn_inline& fh);
+
+  DECLARE_OCTAVE_ALLOCATOR
+
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+
+  // The expression of an inline function.
+  std::string iftext;
+
+  // The args of an inline function.
+  string_vector ifargs;
+};
+
+#endif
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
+
--- a/src/ov.cc	Thu Aug 05 13:26:15 2004 +0000
+++ b/src/ov.cc	Thu Aug 05 16:08:28 2004 +0000
@@ -1083,6 +1083,12 @@
   return rep->fcn_handle_value (silent);
 }
 
+octave_fcn_inline *
+octave_value::fcn_inline_value (bool silent)
+{
+  return rep->fcn_inline_value (silent);
+}
+
 octave_value_list
 octave_value::list_value (void) const
 {
--- a/src/ov.h	Thu Aug 05 13:26:15 2004 +0000
+++ b/src/ov.h	Thu Aug 05 16:08:28 2004 +0000
@@ -52,6 +52,7 @@
 class octave_function;
 class octave_user_function;
 class octave_fcn_handle;
+class octave_fcn_inline;
 class octave_value_list;
 class octave_lvalue;
 
@@ -637,6 +638,8 @@
 
   virtual octave_fcn_handle *fcn_handle_value (bool silent = false);
 
+  virtual octave_fcn_inline *fcn_inline_value (bool silent = false);
+
   virtual octave_value_list list_value (void) const;
 
   ColumnVector column_vector_value (bool frc_str_conv = false,
--- a/src/pr-output.cc	Thu Aug 05 13:26:15 2004 +0000
+++ b/src/pr-output.cc	Thu Aug 05 16:08:28 2004 +0000
@@ -2121,8 +2121,7 @@
 template <class T>
 void
 octave_print_internal (std::ostream& os, const intNDArray<T>& nda,
-		       bool pr_as_read_syntax = false,
-		       int extra_indent = 0)
+		       bool pr_as_read_syntax, int)
 {
   // XXX FIXME XXX -- this mostly duplicates the code in the
   // PRINT_ND_ARRAY macro.
@@ -2247,8 +2246,7 @@
 
 template <class T>
 void
-octave_print_internal (std::ostream& os, const octave_int<T>& val,
-		       bool pr_as_read_syntax)
+octave_print_internal (std::ostream& os, const octave_int<T>& val, bool)
 {
   // XXX FIXME XXX -- we need to handle various formats here...