diff liboctave/oct-shlib.cc @ 3326:c19f4b9484af

[project @ 1999-10-29 21:52:12 by jwe]
author jwe
date Fri, 29 Oct 1999 21:52:30 +0000
parents
children d14c483b3c12
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/liboctave/oct-shlib.cc
@@ -0,0 +1,420 @@
+/*
+
+Copyright (C) 1999 John W. Eaton
+
+This file is part of Octave.
+
+Octave 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.
+
+Octave 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.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined (WITH_SHL)
+#include <cerrno>
+#include <cstring>
+#endif
+
+#include <strstream.h>
+
+extern "C"
+{
+#if defined (WITH_DL)
+#if defined (HAVE_DLFCN_H)
+#include <dlfcn.h>
+#else
+extern void *dlopen (const char *, int);
+extern const char *dlerror (void);
+extern void *dlsym (void *, const char *);
+extern int dlclose (void *);
+#endif
+#ifndef RTLD_LAZY
+#define RTLD_LAZY 1
+#endif
+#elif defined (WITH_SHL)
+#include <dl.h>
+#endif
+}
+
+#include "file-stat.h"
+#include "lo-error.h"
+#include "oct-shlib.h"
+#include "str-vec.h"
+
+class
+octave_base_shlib : public octave_shlib
+{
+public:
+
+  octave_base_shlib (void)
+    : octave_shlib (octave_xshlib ()), file (), fcn_names (),
+      tm_loaded (static_cast<time_t> (0))
+  { count = 1; }
+
+  octave_base_shlib (const string& f)
+    : octave_shlib (octave_xshlib ()), file (f), fcn_names (),
+      tm_loaded (static_cast<time_t> (0))
+  { count = 1; }
+
+  ~octave_base_shlib (void) { }
+
+  void open (const string&, bool = false) { }
+
+  void *search (const string&, name_mangler = 0) { return 0; }
+
+  void close (octave_shlib::close_hook = 0) { }
+
+  bool remove (const string& fcn_name);
+
+  bool is_open (void) const { return false; }
+
+  bool is_out_of_date (void) const;
+
+  int number_of_functions_loaded (void) const { return fcn_names.length (); }
+
+  string file_name (void) const { return file; }
+
+  octave_time time_loaded (void) const { return tm_loaded; }
+
+protected:
+
+  string file;
+
+  string_vector fcn_names;
+
+  octave_time tm_loaded;
+
+  void stamp_time (bool warn_future = false);
+
+  void add_to_fcn_names (const string& name);
+
+  void do_close_hook (octave_shlib::close_hook = 0);
+
+  void tabula_rasa (void);
+
+  // No copying!
+
+  octave_base_shlib (const octave_base_shlib&);
+
+  octave_base_shlib& operator = (const octave_base_shlib&);
+};
+
+bool
+octave_base_shlib::remove (const string& fcn_name)
+{
+  bool retval = false;
+
+  int n = number_of_functions_loaded ();
+
+  string_vector new_fcn_names (n);
+
+  int k = 0;
+
+  for (int i = 0; i < n; i++)
+    {
+      if (fcn_names(i) == fcn_name)
+	retval = true;
+      else
+	new_fcn_names(k++) = fcn_names(i);
+    }
+
+  new_fcn_names.resize (k);
+
+  fcn_names = new_fcn_names;
+
+  return retval;
+}
+
+bool
+octave_base_shlib::is_out_of_date (void) const
+{
+  file_stat fs (file);
+
+  return fs.is_newer (tm_loaded);
+}
+
+void
+octave_base_shlib::stamp_time (bool warn_future)
+{
+  tm_loaded.stamp ();
+
+  if (warn_future)
+    {
+      file_stat fs (file);
+
+      if (fs.is_newer (tm_loaded))
+	(*current_liboctave_warning_handler)
+	  ("timestamp on file %s is in the future", file.c_str ());
+    }
+}
+
+void
+octave_base_shlib::add_to_fcn_names (const string& name)
+{
+  int n = number_of_functions_loaded ();
+
+  for (int i = 0; i < n; i++)
+    if (fcn_names(i) == name)
+      return;
+
+  fcn_names.resize (n+1);
+
+  fcn_names(n) = name;
+}
+
+void
+octave_base_shlib::do_close_hook (octave_shlib::close_hook cl_hook)
+{
+  int n = number_of_functions_loaded ();
+
+  for (int i = 0; i < n; i++)
+    cl_hook (fcn_names(i));
+}
+
+void
+octave_base_shlib::tabula_rasa (void)
+{
+  file = "";
+
+  fcn_names.resize (0);
+
+  tm_loaded = static_cast<time_t> (0);
+}
+
+#if defined (WITH_DL)
+
+class
+octave_dlopen_shlib : public octave_base_shlib
+{
+public:
+
+  octave_dlopen_shlib (void);
+
+  ~octave_dlopen_shlib (void);
+
+  void open (const string& f, bool warn_future = false);
+
+  void *search (const string& name, name_mangler mangler = 0);
+
+  void close (octave_shlib::close_hook cl_hook = 0);
+
+  bool is_open (void) const { return (library != 0); }
+
+private:
+
+  // No copying!
+
+  octave_dlopen_shlib (const octave_dlopen_shlib&);
+
+  octave_dlopen_shlib& operator = (const octave_dlopen_shlib&);
+
+  void *library;
+};
+
+octave_dlopen_shlib::octave_dlopen_shlib (void)
+  : octave_base_shlib (), library (0)
+{
+}
+
+octave_dlopen_shlib::~octave_dlopen_shlib (void)
+{
+  close ();
+}
+
+void
+octave_dlopen_shlib::open (const string& f, bool warn_future)
+{
+  if (! is_open ())
+    {
+      file = f;
+
+      library = dlopen (file.c_str (), RTLD_LAZY);
+
+      if (library)
+	stamp_time (warn_future);
+      else
+	{
+	  const char *msg = dlerror ();
+
+	  if (msg)
+	    (*current_liboctave_error_handler) ("%s", msg);
+	}
+    }
+  else
+    (*current_liboctave_error_handler)
+      ("shared library %s is already open", file.c_str ());
+}
+
+void *
+octave_dlopen_shlib::search (const string& name,
+			     octave_shlib::name_mangler mangler)
+{
+  void *function = 0;
+
+  if (is_open ())
+    {
+      string sym_name = name;
+
+      if (mangler)
+	sym_name = mangler (name);
+
+      function = dlsym (library, sym_name.c_str ());
+
+      if (function)
+	add_to_fcn_names (name);
+    }
+  else
+    (*current_liboctave_error_handler)
+      ("shared library %s is not open", file.c_str ());
+
+  return function;
+}
+
+void
+octave_dlopen_shlib::close (octave_shlib::close_hook cl_hook)
+{
+  if (is_open ())
+    {
+      do_close_hook (cl_hook);
+
+      dlclose (library);
+
+      library = 0;
+
+      tabula_rasa ();
+    }
+}
+
+#elif defined (WITH_SHL)
+
+class
+octave_shl_load_shlib : public octave_base_shlib
+{
+public:
+
+  octave_shl_load_shlib (void);
+
+  ~octave_shl_load_shlib (void);
+
+  void open (const string& f, bool warn_future = false);
+
+  void *search (const string& name, name_mangler mangler = 0);
+
+  void close (octave_shlib::close_hook cl_hook = 0);
+
+  bool is_open (void) const { return { library != 0); }
+
+private:
+
+  // No copying!
+
+  octave_shl_load_shlib (const octave_shl_load_shlib&);
+
+  octave_shl_load_shlib& operator = (const octave_shl_load_shlib&);
+
+  shl_t library;
+};
+
+octave_shl_load_shlib::octave_shl_load_shlib (void)
+  : octave_base_shlib (), library (0)
+{
+}
+
+octave_shl_load_shlib::~octave_shl_load_shlib (void)
+{
+  close ();
+}
+
+void
+octave_shl_load_shlib::open (const string& f, bool warn_future)
+{
+  if (! is_open ())
+    {
+      file = f;
+
+      library = shl_load (file.c_str (), BIND_DEFERRED, 0L);
+
+      if (library)
+	stamp_time (warn_future);
+      else
+	(*current_liboctave_error_handler) ("%s", strerror (errno));
+    }
+  else
+    (*current_liboctave_error_handler)
+      ("shared library %s is already open", file.c_str ());
+}
+
+void *
+octave_shl_load_shlib::search (const string& name,
+			       octave_shlib::name_mangler mangler)
+{
+  void *function = 0;
+
+  if (is_open ())
+    {
+      string sym_name = name;
+
+      if (mangler)
+	sym_name = mangler (name);
+	
+      int status = shl_findsym (&library, sym_name.c_str (),
+				TYPE_UNDEFINED, &function);
+
+      if (status == 0)
+	add_to_fcn_names (name);
+    }
+  else
+    (*current_liboctave_error_handler)
+      ("shared library %s is not open", file.c_str ());
+
+  return function;
+}
+
+void
+octave_shl_load_shlib::close (octave_shlib::close_hook cl_hook)
+{
+  if (is_open ())
+    {
+      do_close_hook (cl_hook);
+
+      shl_unload (library);
+
+      library = 0;
+
+      tabula_rasa ();
+    }
+}
+
+#endif
+
+octave_shlib *
+octave_shlib::make_shlib (void)
+{
+#if defined (WITH_DL)
+  return new octave_dlopen_shlib ();
+#elif defined (WITH_SHL)
+  return new octave_shl_load_shlib ();
+#else
+  return new octave_base_shlib ();
+#endif
+}
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/