changeset 6323:ea65de49e18e

[project @ 2007-02-17 02:51:02 by jwe]
author jwe
date Sat, 17 Feb 2007 02:51:03 +0000
parents 723a32c8ee10
children d5904124b917
files liboctave/ChangeLog liboctave/oct-shlib.h scripts/ChangeLog scripts/miscellaneous/Makefile.in src/ChangeLog src/defun-int.h src/defun.cc src/dirfns.cc src/dirfns.h src/dynamic-ld.cc src/dynamic-ld.h src/ov-fcn-handle.cc src/ov-fcn.h src/ov-usr-fcn.cc src/ov-usr-fcn.h src/parse.y src/utils.cc src/utils.h src/variables.cc src/variables.h
diffstat 20 files changed, 320 insertions(+), 103 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/ChangeLog	Fri Feb 16 21:48:21 2007 +0000
+++ b/liboctave/ChangeLog	Sat Feb 17 02:51:03 2007 +0000
@@ -1,3 +1,9 @@
+2007-02-16  John W. Eaton  <jwe@octave.org>
+
+	* oct-shlib.h (octave_shlib::relative): New data member.
+	(octave_shlib::mark_relative, octave_shlib::is_relative):
+	New functions.
+
 2007-02-16  Michael Goffioul  <michael.goffioul@swing.be>
 
 	* lo-sysdep.cc (octave_popen2): New function to simulate popen2 on
--- a/liboctave/oct-shlib.h	Fri Feb 16 21:48:21 2007 +0000
+++ b/liboctave/oct-shlib.h	Sat Feb 17 02:51:03 2007 +0000
@@ -50,9 +50,10 @@
 
   typedef void (*close_hook) (const std::string&);
 
-  octave_shlib (void) : rep (make_shlib ()) { }
+  octave_shlib (void) : relative (false), rep (make_shlib ()) { }
 
-  octave_shlib (const std::string& f) : rep (make_shlib ()) { open (f); }
+  octave_shlib (const std::string& f)
+    : relative (false), rep (make_shlib ()) { open (f); }
 
   virtual ~octave_shlib (void)
     {
@@ -102,6 +103,10 @@
   virtual bool is_out_of_date (void) const
     { return rep->is_out_of_date (); }
 
+  void mark_relative (void) { relative = true; }
+
+  bool is_relative (void) const { return relative; }
+
   virtual int number_of_functions_loaded (void) const
     { return rep->number_of_functions_loaded (); }
 
@@ -119,6 +124,9 @@
 
   static octave_shlib *make_shlib (void);
 
+  // TRUE if this function was found from a relative path element.
+  bool relative;
+
   union
     {
       octave_shlib *rep;
--- a/scripts/ChangeLog	Fri Feb 16 21:48:21 2007 +0000
+++ b/scripts/ChangeLog	Sat Feb 17 02:51:03 2007 +0000
@@ -1,3 +1,7 @@
+2007-02-16  John W. Eaton  <jwe@octave.org>
+
+	* miscellaneous/Makefile.in (SOURCES): Remove popen2.m from the list.
+
 2007-02-16  Michael Goffioul  <michael.goffioul@swing.be>
 
 	* miscellaneous/popen2.m: Remove as replaced with builtin.
--- a/scripts/miscellaneous/Makefile.in	Fri Feb 16 21:48:21 2007 +0000
+++ b/scripts/miscellaneous/Makefile.in	Sat Feb 17 02:51:03 2007 +0000
@@ -27,7 +27,7 @@
   inputname.m ispc.m isunix.m license.m list_primes.m ls.m \
   ls_command.m menu.m mex.m mexext.m mkoctfile.m movefile.m \
   news.m not.m orderfields.m pack.m paren.m parseparams.m \
-  popen2.m semicolon.m setfield.m single.m substruct.m tar.m \
+  semicolon.m setfield.m single.m substruct.m tar.m \
   tempdir.m tempname.m texas_lotto.m unix.m unpack.m untar.m \
   unzip.m ver.m version.m warning_ids.m xor.m zip.m
 
--- a/src/ChangeLog	Fri Feb 16 21:48:21 2007 +0000
+++ b/src/ChangeLog	Sat Feb 17 02:51:03 2007 +0000
@@ -1,15 +1,86 @@
+2007-02-16  John W. Eaton  <jwe@octave.org>
+
+	* dynamic-ld.cc (octave_dynamic_loader::do_load_oct): Clear
+	function if original was loaded from relative path and the name
+	can no longer be found in path.  Mark files found from relative
+	path as relative.
+	(clear): Only warn if there is more than one function to clear.
+
+	* variables.cc (symbol_out_of_date): Don't ignore return value in
+	call to octave_env::make_absolute.
+	(symbol_out_of_date): Clear symbol if original was loaded from
+	relative path and name can no longer be found in path.
+
+	* dynamic-ld.cc (octave_dynamic_loader::do_load_oct):
+	Also check whether new file is same as the old file.
+
+	* utils.cc (same_file): Move here from variables.cc.
+	* utils.h: (same_file): Provide decl.
+
+	* parse.y (frob_function): Stash parent function name if parsing
+	nested function.
+
+	* ov-fcn-handle.cc (make_fcn_handle): Pass current function name
+	as parent in call to lookup_function.
+
+	* ov-fcn.h (octave_function::parent_fcn_name): New virtual function.
+
+	* ov-usr-fcn.h (octave_user_function::parent_name): New data member.
+	(octave_user_function::stash_parent_function_name,
+	octave_user_function::parent_function_name): New methods.
+	* ov-usr-fcn.cc (octave_user_function::octave_user_function):
+	Initialize parent_name.
+
+	* variables.h, variables.cc (lookup_function): New arg, parent.
+	If not empty, try this first for lookup.
+
+	* dynamic-ld.cc (octave_dynamic_loader::do_load_mex): If doing
+	path lookup, check relative status. Pass relative to oct_file_in_path.
+	(octave_dynamic_loader::do_load_mex): Likewise, for mex_file_in_path
+
+	* defun-int.h, defun.cc (install_mex_function): New arg, relative.
+	(install_dld_function): Likewise.
+	(octave_dld_fcn_installer): Likewise.
+	(DEFINE_FUNX_INSTALLER_FUN3): Pass relative to install_dld_function.
+
+	* dynamic-ld.h (octave_dynamic_loader::load_oct,
+	octave_dynamic_loader::load_mex,
+	octave_dynamic_loader::do_load_oct
+	octave_dynamic_loader::do_load_mex): New arg, relative.
+
+	* dirfns.h (Vcurrent_directory): Delete unused variable.
+
+	* variables.cc (symbol_out_of_date): Also compare function time
+	stamp to Vlast_chdir_time if function is from relative lookup.
+
+	* dirfns.cc (Vlast_chdir_time): New variable.
+	(octave_change_to_directory): Update it if chdir succeeds.
+	* dirfns.h (Vlast_chdir_time): Provide decl.
+
+	* ov-fcn.h (octave_function::relative): New data member.
+	(octave_function::mark_relative, octave_function::is_relative):
+	New functions.
+
+	* parse.y (fcn_file_from_relative_lookup): New static variable.
+	(load_fcn_from_file): Note whether function file was found from
+	relative path element.
+	(frob_function): Maybe mark function as relative.
+
+	* parse.y (lookup_autoload): Don't call octave_env::make_absolute
+	on return value.
+	* variables.cc (symbol_out_of_date): Make name absolute after call
+	to lookup_autoload.
+
+	* input.cc (interactive_input): New arg, DEBUG.  Don't call
+	drawnow if debugging.
+	(get_user_input): Pass DEBUG to interactive_input.
+
 2007-02-16  Michael Goffioul  <michael.goffioul@swing.be>
 
 	* syscalls.cc (Fpopen2): New function.
 	(pipe): Modify to return input and output file descriptor
 	seperately rather than in a list.
 	
-2007-02-16  John W. Eaton  <jwe@octave.org>
-
-	* input.cc (interactive_input): New arg, DEBUG.  Don't call
-	drawnow if debugging.
-	(get_user_input): Pass DEBUG to interactive_input.
-
 2007-02-16  Muthiah Annamalai  <muthuspost@gmail.com>
 
 	* debug.cc (Fdbtype): Improve compatibility.
--- a/src/defun-int.h	Fri Feb 16 21:48:21 2007 +0000
+++ b/src/defun-int.h	Sat Feb 17 02:51:03 2007 +0000
@@ -50,11 +50,13 @@
 extern OCTINTERP_API void
 install_dld_function (octave_dld_function::fcn f, const std::string& name,
 		      const octave_shlib& shl,
-		      const std::string& doc, bool is_text_fcn = false);
+		      const std::string& doc, bool is_text_fcn = false,
+		      bool relative = false);
 
 extern OCTINTERP_API void
 install_mex_function (void *fptr, bool fmex, const std::string& name,
-		      const octave_shlib& shl, bool is_text_fcn = false);
+		      const octave_shlib& shl, bool is_text_fcn = false,
+		      bool relative = false);
 
 extern OCTINTERP_API void
 alias_builtin (const std::string& alias, const std::string& name);
@@ -70,7 +72,7 @@
 // the symbol table.  We look for this name instead of the actual
 // function so that we can easily install the doc std::string too.
 
-typedef bool (*octave_dld_fcn_installer) (const octave_shlib&);
+typedef bool (*octave_dld_fcn_installer) (const octave_shlib&, bool relative);
 
 #define DEFINE_FUN_INSTALLER_FUN(name, doc) \
   DEFINE_FUN_INSTALLER_FUN2(name, doc, CXX_ABI)
@@ -91,10 +93,10 @@
   extern "C" \
   OCTAVE_EXPORT \
   bool \
-  fsname ## _ ## cxx_abi (const octave_shlib& shl) \
+  fsname ## _ ## cxx_abi (const octave_shlib& shl, bool relative) \
   { \
     check_version (OCTAVE_API_VERSION, name); \
-    install_dld_function (fname, name, shl, doc); \
+    install_dld_function (fname, name, shl, doc, false, relative); \
     return error_state ? false : true; \
   }
 
--- a/src/defun.cc	Fri Feb 16 21:48:21 2007 +0000
+++ b/src/defun.cc	Sat Feb 17 02:51:03 2007 +0000
@@ -165,7 +165,8 @@
 void
 install_dld_function (octave_dld_function::fcn f, const std::string& name,
 		      const octave_shlib& shl,
-		      const std::string& doc, bool is_text_fcn)
+		      const std::string& doc, bool is_text_fcn,
+		      bool relative)
 {
   symbol_record *sym_rec = fbi_sym_tab->lookup (name, true);
 
@@ -175,7 +176,13 @@
     t |= symbol_record::COMMAND;
 
   sym_rec->unprotect ();
-  sym_rec->define (new octave_dld_function (f, shl, name, doc), t);
+
+  octave_dld_function *df = new octave_dld_function (f, shl, name, doc);
+
+  if (relative)
+    df->mark_relative ();
+
+  sym_rec->define (df, t);
   sym_rec->document (doc);
 
   // Also insert the full name in the symbol table.  This way, we can
@@ -189,7 +196,8 @@
 
 void
 install_mex_function (void *fptr, bool fmex, const std::string& name,
-		      const octave_shlib& shl, bool is_text_fcn)
+		      const octave_shlib& shl, bool is_text_fcn,
+		      bool relative)
 {
   symbol_record *sym_rec = fbi_sym_tab->lookup (name, true);
 
@@ -199,7 +207,13 @@
     t |= symbol_record::COMMAND;
 
   sym_rec->unprotect ();
-  sym_rec->define (new octave_mex_function (fptr, fmex, shl, name), t);
+
+  octave_mex_function *mf = new octave_mex_function (fptr, fmex, shl, name);
+
+  if (relative)
+    mf->mark_relative ();
+
+  sym_rec->define (mf, t);
 
   // Also insert the full name in the symbol table.  This way, we can
   // properly cope with changes to LOAD_PATH.
--- a/src/dirfns.cc	Fri Feb 16 21:48:21 2007 +0000
+++ b/src/dirfns.cc	Sat Feb 17 02:51:03 2007 +0000
@@ -69,6 +69,9 @@
 // directory tree.
 static bool Vconfirm_recursive_rmdir = true;
 
+// The time we last time we changed directories.
+octave_time Vlast_chdir_time = 0.0;
+
 static int
 octave_change_to_directory (const std::string& newdir)
 {
@@ -76,6 +79,8 @@
 
   if (cd_ok)
     {
+      Vlast_chdir_time.stamp ();
+
       // FIXME -- should this be handled as a list of functions
       // to call so users can add their own chdir handlers?
 
--- a/src/dirfns.h	Fri Feb 16 21:48:21 2007 +0000
+++ b/src/dirfns.h	Sat Feb 17 02:51:03 2007 +0000
@@ -28,12 +28,15 @@
 
 #include <string>
 
+#include "oct-time.h"
+
 extern std::string polite_directory_format (const std::string&);
 extern std::string base_pathname (const std::string&);
 extern std::string make_absolute (const std::string&, const std::string&);
 extern std::string get_working_directory (const std::string&);
 
-extern std::string Vcurrent_directory;
+// The time we last time we changed directories.
+extern octave_time Vlast_chdir_time;
 
 #endif
 
--- a/src/dynamic-ld.cc	Fri Feb 16 21:48:21 2007 +0000
+++ b/src/dynamic-ld.cc	Sat Feb 17 02:51:03 2007 +0000
@@ -27,6 +27,7 @@
 
 #include <list>
 
+#include "oct-env.h"
 #include "oct-time.h"
 #include "file-stat.h"
 
@@ -302,9 +303,21 @@
   fbi_sym_tab->clear (fcn_name);
 }
 
+static void
+clear (octave_shlib& oct_file)
+{
+  if (oct_file.number_of_functions_loaded () > 1)
+    warning_with_id ("Octave:reload-forces-clear",
+		     "reloading %s clears the following functions:",
+		     oct_file.file_name().c_str ());
+
+  octave_shlib_list::remove (oct_file, do_clear_function);
+}
+
 bool
 octave_dynamic_loader::do_load_oct (const std::string& fcn_name,
-				    const std::string& file_name)
+				    const std::string& file_name,
+				    bool relative)
 {
   bool retval = false;
 
@@ -321,26 +334,37 @@
 
   if (! error_state)
     {
-      if (function && oct_file.is_out_of_date ())
+      if (function
+	  && (! same_file (file_name, oct_file.file_name ())
+	      || oct_file.is_out_of_date ()))
 	{
-	  int n = oct_file.number_of_functions_loaded ();
-
-	  if (n > 0)
-	    warning_with_id ("Octave:reload-forces-clear",
-			     "reloading %s clears the following functions:",
-			     oct_file.file_name().c_str ());
-
-	  octave_shlib_list::remove (oct_file, do_clear_function);
-
+	  clear (oct_file);
 	  function = 0;
 	}
 
       if (! function)
 	{
-	  std::string oct_file_name
-	    = file_name.empty () ? oct_file_in_path (fcn_name) : file_name;
+	  std::string oct_file_name = file_name;
+
+	  if (oct_file_name.empty ())
+	    {
+	      oct_file_name = oct_file_in_path (fcn_name);
+
+	      if (! oct_file_name.empty ())
+		relative = ! octave_env::absolute_pathname (oct_file_name);
+	    }
 
-	  if (! oct_file_name.empty ())
+	  if (oct_file_name.empty ())
+	    {
+	      if (oct_file.is_relative ())
+		{
+		  // Can't see this function from current
+		  // directory, so we should clear it.
+		  clear (oct_file);
+		  function = 0;
+		}
+	    }
+	  else
 	    {
 	      oct_file.open (oct_file_name);
 
@@ -348,6 +372,9 @@
 		{
 		  if (oct_file)
 		    {
+		      if (relative)
+			oct_file.mark_relative ();
+
 		      octave_shlib_list::append (oct_file);
 
 		      function = oct_file.search (fcn_name, mangle_name);
@@ -357,7 +384,6 @@
 			     oct_file_name.c_str ());
 		}
 	    }
-
 	}
     }
 
@@ -366,7 +392,7 @@
       octave_dld_fcn_installer f
 	= FCN_PTR_CAST (octave_dld_fcn_installer, function);
 
-      retval = f (oct_file);
+      retval = f (oct_file, relative);
 
       if (! retval)
 	::error ("failed to install .oct file function `%s'",
@@ -380,7 +406,8 @@
 
 bool
 octave_dynamic_loader::do_load_mex (const std::string& fcn_name,
-				    const std::string& file_name)
+				    const std::string& file_name,
+				    bool relative)
 {
   bool retval = false;
 
@@ -392,8 +419,15 @@
 
   doing_load = true;
 
-  std::string mex_file_name
-    = file_name.empty () ? mex_file_in_path (fcn_name) : file_name;
+  std::string mex_file_name = file_name;
+
+  if (mex_file_name.empty ())
+    {
+      mex_file_name = mex_file_in_path (fcn_name);
+
+      if (! mex_file_name.empty ())
+	relative = ! octave_env::absolute_pathname (mex_file_name);
+    }
 
   void *function = 0;
 
@@ -434,7 +468,7 @@
 
   if (function)
     {
-      install_mex_function (function, have_fmex, fcn_name, mex_file);
+      install_mex_function (function, have_fmex, fcn_name, mex_file, relative);
 
       retval = true;
     }
@@ -467,16 +501,20 @@
 
 bool
 octave_dynamic_loader::load_oct (const std::string& fcn_name,
-				 const std::string& file_name)
+				 const std::string& file_name,
+				 bool relative)
 {
-  return (instance_ok ()) ? instance->do_load_oct (fcn_name, file_name) : false;
+  return (instance_ok ())
+    ? instance->do_load_oct (fcn_name, file_name, relative) : false;
 }
 
 bool
 octave_dynamic_loader::load_mex (const std::string& fcn_name,
-				 const std::string& file_name)
+				 const std::string& file_name,
+				 bool relative)
 {
-  return (instance_ok ()) ? instance->do_load_mex (fcn_name, file_name) : false;
+  return (instance_ok ())
+    ? instance->do_load_mex (fcn_name, file_name, relative) : false;
 }
 
 bool
--- a/src/dynamic-ld.h	Fri Feb 16 21:48:21 2007 +0000
+++ b/src/dynamic-ld.h	Sat Feb 17 02:51:03 2007 +0000
@@ -40,10 +40,12 @@
   virtual ~octave_dynamic_loader (void) { }
 
   static bool load_oct (const std::string& fcn_name,
-			const std::string& file_name = std::string ());
+			const std::string& file_name = std::string (),
+			bool relative = false);
 
   static bool load_mex (const std::string& fcn_name,
-			const std::string& file_name = std::string ());
+			const std::string& file_name = std::string (),
+			bool relative = false);
 
   static bool remove (const std::string& fcn_name, octave_shlib& shl);
 
@@ -60,10 +62,12 @@
   static bool instance_ok (void);
 
   bool do_load_oct (const std::string& fcn_name,
-		    const std::string& file_name = std::string ());
+		    const std::string& file_name = std::string (),
+		    bool relative = false);
 
   bool do_load_mex (const std::string& fcn_name,
-		    const std::string& file_name = std::string ());
+		    const std::string& file_name = std::string (),
+		    bool relative = false);
 
   bool do_remove (const std::string& fcn_name, octave_shlib& shl);
 
--- a/src/ov-fcn-handle.cc	Fri Feb 16 21:48:21 2007 +0000
+++ b/src/ov-fcn-handle.cc	Sat Feb 17 02:51:03 2007 +0000
@@ -612,7 +612,9 @@
 {
   octave_value retval;
 
-  octave_value f = lookup_function (nm);
+  octave_function *fcn = octave_call_stack::current ();
+
+  octave_value f = lookup_function (nm, fcn->name ());
 
   if (f.is_function ())
     retval = octave_value (new octave_fcn_handle (f, nm));
--- a/src/ov-fcn.h	Fri Feb 16 21:48:21 2007 +0000
+++ b/src/ov-fcn.h	Sat Feb 17 02:51:03 2007 +0000
@@ -61,6 +61,8 @@
 
   virtual std::string fcn_file_name (void) const { return std::string (); }
 
+  virtual std::string parent_fcn_name (void) const { return std::string (); }
+
   virtual void mark_fcn_file_up_to_date (const octave_time&) { }
 
   virtual octave_time time_parsed (void) const
@@ -79,6 +81,10 @@
 
   virtual bool takes_var_return (void) const { return false; }
 
+  void mark_relative (void) { relative = true; }
+
+  bool is_relative (void) const { return relative; }
+
   std::string name (void) const { return my_name; }
 
   void document (const std::string& ds) { doc = ds; }
@@ -93,7 +99,10 @@
 
   octave_function (const std::string& nm,
 		   const std::string& ds = std::string ())
-    : my_name (nm), doc (ds) { }
+    : relative (false), my_name (nm), doc (ds) { }
+
+  // TRUE if this function was found from a relative path element.
+  bool relative;
 
   // The name of this function.
   std::string my_name;
--- a/src/ov-usr-fcn.cc	Fri Feb 16 21:48:21 2007 +0000
+++ b/src/ov-usr-fcn.cc	Sat Feb 17 02:51:03 2007 +0000
@@ -74,7 +74,7 @@
   : octave_function (std::string (), std::string ()),
     param_list (pl), ret_list (rl), cmd_list (cl),
     sym_tab (st), lead_comm (), trail_comm (), file_name (),
-    t_parsed (static_cast<time_t> (0)),
+    parent_name (), t_parsed (static_cast<time_t> (0)),
     t_checked (static_cast<time_t> (0)),
     system_fcn_file (false), call_depth (0), num_named_args (0),
     nested_function (false), inline_function (false), args_passed (),
--- a/src/ov-usr-fcn.h	Fri Feb 16 21:48:21 2007 +0000
+++ b/src/ov-usr-fcn.h	Sat Feb 17 02:51:03 2007 +0000
@@ -108,6 +108,8 @@
 
   void stash_fcn_file_name (const std::string& nm);
 
+  void stash_parent_fcn_name (const std::string& p) { parent_name = p; }
+
   void stash_leading_comment (octave_comment_list *lc) { lead_comm = lc; }
 
   void stash_trailing_comment (octave_comment_list *tc) { trail_comm = tc; }
@@ -124,6 +126,8 @@
 
   std::string fcn_file_name (void) const { return file_name; }
 
+  std::string parent_fcn_name (void) const { return parent_name; }
+
   octave_time time_parsed (void) const { return t_parsed; }
 
   octave_time time_checked (void) const { return t_checked; }
@@ -220,9 +224,12 @@
   // The comments preceding the ENDFUNCTION token.
   octave_comment_list *trail_comm;
 
-  // The name of the file we parsed
+  // The name of the file we parsed.
   std::string file_name;
 
+  // The name of the parent function, if any.
+  std::string parent_name;
+
   // The time the file was parsed.
   octave_time t_parsed;
 
--- a/src/parse.y	Fri Feb 16 21:48:21 2007 +0000
+++ b/src/parse.y	Sat Feb 17 02:51:03 2007 +0000
@@ -118,6 +118,10 @@
 // TRUE means we are in the process of autoloading a function.
 static bool autoloading = false;
 
+// TRUE means the current function file was found in a relative path
+// element.
+static bool fcn_file_from_relative_lookup = false;
+
 // List of autoloads (function -> file mapping).
 static std::map<std::string, std::string> autoload_map;
 
@@ -2483,6 +2487,12 @@
       fcn->stash_fcn_file_time (now);
       fcn->mark_as_system_fcn_file ();
 
+      if (fcn_file_from_relative_lookup)
+	fcn->mark_relative ();
+
+      if (lexer_flags.parsing_nested_function)
+        fcn->stash_parent_fcn_name (parent_function_name);
+
       std::string nm = fcn->fcn_file_name ();
 
       file_stat fs (nm);
@@ -3229,7 +3239,8 @@
 }
 
 static bool
-parse_fcn_file (const std::string& ff, bool exec_script, bool force_script = false)
+parse_fcn_file (const std::string& ff, bool exec_script,
+		bool force_script = false)
 {
   unwind_protect::begin_frame ("parse_fcn_file");
 
@@ -3366,8 +3377,7 @@
   am_iter p = autoload_map.find (nm);
 
   if (p != autoload_map.end ())
-    retval = octave_env::make_absolute (load_path::find_file (p->second),
-					octave_env::getcwd ());
+    retval = load_path::find_file (p->second);
 
   return retval;
 }
@@ -3411,6 +3421,10 @@
 
   std::string file;
 
+  unwind_protect_bool (fcn_file_from_relative_lookup);
+
+  fcn_file_from_relative_lookup = false;
+
   if (octave_env::absolute_pathname (nm)
       && ((nm_len > 4 && nm.substr (nm_len-4) == ".oct")
 	  || (nm_len > 4 && nm.substr (nm_len-4) == ".mex")
@@ -3433,20 +3447,23 @@
 	  exec_script = true;
 	}
       else
-	file = octave_env::make_absolute
-	  (load_path::find_fcn (nm), octave_env::getcwd ());
+        file = load_path::find_fcn (nm);
+
+      fcn_file_from_relative_lookup = ! octave_env::absolute_pathname (file);
+
+      file = octave_env::make_absolute (file, octave_env::getcwd ());
     }
 
   int len = file.length ();
 
   if (len > 4 && file.substr (len-4, len-1) == ".oct")
     {
-      if (octave_dynamic_loader::load_oct (nm, file))
+      if (octave_dynamic_loader::load_oct (nm, file, fcn_file_from_relative_lookup))
         force_link_to_function (nm);
     }
   else if (len > 4 && file.substr (len-4, len-1) == ".mex")
     {
-      if (octave_dynamic_loader::load_mex (nm, file))
+      if (octave_dynamic_loader::load_mex (nm, file, fcn_file_from_relative_lookup))
         force_link_to_function (nm);
     }
   else if (len > 2)
--- a/src/utils.cc	Fri Feb 16 21:48:21 2007 +0000
+++ b/src/utils.cc	Sat Feb 17 02:51:03 2007 +0000
@@ -113,6 +113,20 @@
   return retval;
 }
 
+// Return TRUE if F and G are both names for the same file.
+
+bool
+same_file (const std::string& f, const std::string& g)
+{
+  std::string c_f = file_ops::canonicalize_file_name (f);
+  std::string c_g = file_ops::canonicalize_file_name (g);
+
+  file_stat f_fs (c_f);
+  file_stat g_fs (c_g);
+
+  return (f_fs.ino () == g_fs.ino () && f_fs.dev () == g_fs.dev ());
+}
+
 int
 almost_match (const std::string& std, const std::string& s, int min_match_len,
 	      int case_sens)
--- a/src/utils.h	Fri Feb 16 21:48:21 2007 +0000
+++ b/src/utils.h	Sat Feb 17 02:51:03 2007 +0000
@@ -39,15 +39,21 @@
 extern OCTINTERP_API bool valid_identifier (const char *s);
 extern OCTINTERP_API bool valid_identifier (const std::string& s);
 
-extern OCTINTERP_API int almost_match (const std::string& std, const std::string& s,
-			 int min_match_len = 1, int case_sens = 1);
+extern OCTINTERP_API bool
+same_file (const std::string& f, const std::string& g);
+
+extern OCTINTERP_API int almost_match (const std::string& std,
+				       const std::string& s,
+				       int min_match_len = 1,
+				       int case_sens = 1);
 
 extern OCTINTERP_API int
 keyword_almost_match (const char * const *std, int *min_len,
 		      const std::string& s, int min_toks_to_match,
 		      int max_toks);
 
-extern OCTINTERP_API int empty_arg (const char *name, octave_idx_type nr, octave_idx_type nc);
+extern OCTINTERP_API int empty_arg (const char *name, octave_idx_type nr,
+				    octave_idx_type nc);
 
 extern OCTINTERP_API std::string
 search_path_for_file (const std::string&, const string_vector&);
@@ -55,7 +61,9 @@
 extern OCTINTERP_API string_vector
 search_path_for_all_files (const std::string&, const string_vector&);
 
-extern OCTINTERP_API std::string file_in_path (const std::string&, const std::string&);
+extern OCTINTERP_API std::string
+file_in_path (const std::string&, const std::string&);
+
 extern OCTINTERP_API std::string fcn_file_in_path (const std::string&);
 extern OCTINTERP_API std::string oct_file_in_path (const std::string&);
 extern OCTINTERP_API std::string mex_file_in_path (const std::string&);
@@ -75,13 +83,15 @@
 
 extern OCTINTERP_API void
 get_dimensions (const octave_value& a, const octave_value& b,
-		const char *warn_for, octave_idx_type& nr, octave_idx_type& nc);
+		const char *warn_for, octave_idx_type& nr,
+		octave_idx_type& nc);
 
 extern OCTINTERP_API void
-get_dimensions (const octave_value& a,
-		const char *warn_for, octave_idx_type& nr, octave_idx_type& nc);
+get_dimensions (const octave_value& a,const char *warn_for,
+		octave_idx_type& nr, octave_idx_type& nc);
 
-extern OCTINTERP_API Matrix identity_matrix (octave_idx_type nr, octave_idx_type nc);
+extern OCTINTERP_API Matrix
+identity_matrix (octave_idx_type nr, octave_idx_type nc);
 
 extern OCTINTERP_API int
 octave_format (std::ostream& os, const char *fmt, ...);
@@ -99,8 +109,8 @@
 
 extern "C" OCTINTERP_API void octave_usleep (unsigned int useconds);
 
-extern "C" OCTINTERP_API int octave_raw_vsnprintf (char *buf, size_t n, const char *fmt,
-				     va_list args);
+extern "C" OCTINTERP_API int
+octave_raw_vsnprintf (char *buf, size_t n, const char *fmt, va_list args);
 
 #endif
 
--- a/src/variables.cc	Fri Feb 16 21:48:21 2007 +0000
+++ b/src/variables.cc	Sat Feb 17 02:51:03 2007 +0000
@@ -962,20 +962,6 @@
   return retval;
 }
 
-// Return TRUE if F and G are both names for the same file.
-
-static bool
-same_file (const std::string& f, const std::string& g)
-{
-  std::string c_f = file_ops::canonicalize_file_name (f);
-  std::string c_g = file_ops::canonicalize_file_name (g);
-
-  file_stat f_fs (c_f);
-  file_stat g_fs (c_g);
-
-  return (f_fs.ino () == g_fs.ino () && f_fs.dev () == g_fs.dev ());
-}
-
 bool
 fcn_out_of_date (octave_function *fcn, const std::string& ff, time_t tp)
 {
@@ -1020,7 +1006,12 @@
 
 	  if (! ff.empty ())
 	    {
-	      if (fcn->time_checked () < Vlast_prompt_time)
+	      octave_time tc = fcn->time_checked ();
+
+	      bool relative = fcn->is_relative ();
+
+	      if (tc < Vlast_prompt_time
+		  || (relative && tc < Vlast_chdir_time))
 		{
 		  time_t tp = fcn->time_parsed ();
 
@@ -1047,19 +1038,27 @@
 		      file = lookup_autoload (nm);
 
 		      if (file.empty ())
-			{
-			  file = octave_env::make_absolute
-			    (load_path::find_fcn (nm), octave_env::getcwd ());
-			}
+			file = load_path::find_fcn (nm);
+
+		      file = octave_env::make_absolute (file, octave_env::getcwd ());
 		    }
 
-		  if (same_file (file, ff))
+		  if (relative && file.empty ())
+		    {
+		      // Can't see this function from current
+		      // directory, so we should clear it.
+
+		      sr->clear ();
+
+		      retval = true;
+		    }
+		  else if (same_file (file, ff))
 		    {
 		      retval = fcn_out_of_date (fcn, ff, tp);
 		    }
 		  else
 		    {
-		      // Check the full function name.  Maybe we alrady
+		      // Check the full function name.  Maybe we already
 		      // parsed it.
 
 		      symbol_record *full_sr = fbi_sym_tab->lookup (file);
@@ -1147,18 +1146,17 @@
 }
 
 octave_value
-lookup_function (const std::string& nm)
+lookup_function (const std::string& nm, const std::string& parent)
 {
   octave_value retval;
 
   symbol_record *sr = 0;
 
-  if (curr_parent_function)
-    {
-      std::string parent = curr_parent_function->name ();
-
-      sr = fbi_sym_tab->lookup (parent + ":" + nm);
-    }
+  if (! parent.empty ())
+    sr = fbi_sym_tab->lookup (parent + ":" + nm);
+
+  if (! sr || ! sr->is_function () && curr_parent_function)
+    sr = fbi_sym_tab->lookup (curr_parent_function->name () + ":" + nm);
 
   if (! sr || ! sr->is_function ())
     {
@@ -1464,12 +1462,15 @@
 
   symbol_record *tmp_sym = 0;
 
-  if (curr_parent_function)
-    {
-      std::string parent = curr_parent_function->name ();
-
-      tmp_sym = fbi_sym_tab->lookup (parent + ":" + nm);
-    }
+  octave_function *fcn = octave_call_stack::current ();
+
+  std::string parent = fcn ? fcn->parent_fcn_name () : std::string ();
+
+  if (! parent.empty ())
+    tmp_sym = fbi_sym_tab->lookup (parent + ":" + nm);
+
+  if (! tmp_sym && curr_parent_function)
+    tmp_sym = fbi_sym_tab->lookup (curr_parent_function->name () + ":" + nm);
 
   if (! tmp_sym)
     tmp_sym = fbi_sym_tab->lookup (nm);
--- a/src/variables.h	Fri Feb 16 21:48:21 2007 +0000
+++ b/src/variables.h	Sat Feb 17 02:51:03 2007 +0000
@@ -99,7 +99,9 @@
 extern OCTINTERP_API symbol_record *
 lookup_by_name (const std::string& nm, bool exec_script = true);
 
-extern OCTINTERP_API octave_value lookup_function (const std::string& nm);
+extern OCTINTERP_API octave_value
+lookup_function (const std::string& nm,
+		 const std::string& parent = std::string ());
 
 extern OCTINTERP_API octave_value lookup_user_function (const std::string& nm);