home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / octa21fs.zip / octave / octave-2.1.23 / src / dynamic-ld.cc < prev    next >
C/C++ Source or Header  |  2000-01-15  |  8KB  |  352 lines

  1. /*
  2.  
  3. Copyright (C) 1996, 1997 John W. Eaton
  4.  
  5. This file is part of Octave.
  6.  
  7. Octave is free software; you can redistribute it and/or modify it
  8. under the terms of the GNU General Public License as published by the
  9. Free Software Foundation; either version 2, or (at your option) any
  10. later version.
  11.  
  12. Octave is distributed in the hope that it will be useful, but WITHOUT
  13. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with Octave; see the file COPYING.  If not, write to the Free
  19. Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  
  21. */
  22.  
  23. #ifdef HAVE_CONFIG_H
  24. #include <config.h>
  25. #endif
  26.  
  27. #include "oct-time.h"
  28. #include "file-stat.h"
  29.  
  30. #include "DLList.h"
  31.  
  32. #include <defaults.h>
  33.  
  34. #include "defun.h"
  35. #include "dynamic-ld.h"
  36. #include "parse.h"
  37. #include "unwind-prot.h"
  38. #include "utils.h"
  39. #include "variables.h"
  40.  
  41. // TRUE means we print a warning if reloading a .oct file forces other
  42. // functions to be cleared.
  43. static bool Vwarn_reload_forces_clear;
  44.  
  45. template class DLNode<octave_shlib>;
  46. template class DLList<octave_shlib>;
  47.  
  48. class
  49. octave_shlib_list
  50. {
  51. public:
  52.  
  53.   static void append (const octave_shlib& shl);
  54.  
  55.   static void remove (octave_shlib& shl);
  56.  
  57.   static void *search (const string& fcn_name, octave_shlib& shl,
  58.                octave_shlib::name_mangler mangler = 0);
  59.  
  60. protected:
  61.  
  62.   octave_shlib_list (void) { }
  63.  
  64.   ~octave_shlib_list (void) { }
  65.  
  66. private:
  67.  
  68.   void do_append (const octave_shlib& shl);
  69.  
  70.   void do_remove (octave_shlib& shl);
  71.  
  72.   void *do_search (const string& fcn_name, octave_shlib& shl,
  73.            octave_shlib::name_mangler mangler = 0);
  74.  
  75.   static octave_shlib_list *instance;
  76.  
  77.   static bool instance_ok (void);
  78.  
  79.   // List of libraries we have loaded.
  80.   DLList<octave_shlib> lib_list;
  81.  
  82.   // No copying!
  83.  
  84.   octave_shlib_list (const octave_shlib_list&);
  85.  
  86.   octave_shlib_list& operator = (const octave_shlib_list&);
  87. };
  88.  
  89. octave_shlib_list *octave_shlib_list::instance = 0;
  90.  
  91. void
  92. octave_shlib_list::do_append (const octave_shlib& shl)
  93. {
  94.   lib_list.append (shl);
  95. }
  96.  
  97. void
  98. octave_shlib_list::do_remove (octave_shlib& shl)
  99. {
  100.   for (Pix p = lib_list.first (); p != 0; lib_list.next (p))
  101.     {
  102.       if (lib_list(p) == shl)
  103.     {
  104.       shl.close ();
  105.  
  106.       lib_list.del (p);
  107.  
  108.       break;
  109.     }
  110.     }
  111. }
  112.  
  113. void *
  114. octave_shlib_list::do_search (const string& fcn_name, octave_shlib& shl,
  115.                   octave_shlib::name_mangler mangler)
  116. {
  117.   void *function = 0;
  118.  
  119.   shl = octave_shlib ();
  120.  
  121.   for (Pix p = lib_list.first (); p != 0; lib_list.next (p))
  122.     {
  123.       function = lib_list(p).search (fcn_name, mangler);
  124.  
  125.       if (function)
  126.     {
  127.       shl = lib_list(p);
  128.  
  129.       break;
  130.     }
  131.     }
  132.  
  133.   return function;
  134. }
  135.  
  136. bool
  137. octave_shlib_list::instance_ok (void)
  138. {
  139.   bool retval = true;
  140.  
  141.   if (! instance)
  142.     instance = new octave_shlib_list ();
  143.  
  144.   if (! instance)
  145.     {
  146.       ::error ("unable to create shared library list object!");
  147.  
  148.       retval = false;
  149.     }
  150.  
  151.   return retval;
  152. }
  153.  
  154. void
  155. octave_shlib_list::append (const octave_shlib& shl)
  156. {
  157.   if (instance_ok ())
  158.     instance->do_append (shl);
  159. }
  160.  
  161. void
  162. octave_shlib_list::remove (octave_shlib& shl)
  163. {
  164.   if (instance_ok ())
  165.     instance->do_remove (shl);
  166. }
  167.  
  168. void *
  169. octave_shlib_list::search (const string& fcn_name, octave_shlib& shl,
  170.                octave_shlib::name_mangler mangler)
  171. {
  172.   return (instance_ok ()) ? instance->do_search (fcn_name, shl, mangler) : 0;
  173. }
  174.  
  175. octave_dynamic_loader *octave_dynamic_loader::instance = 0;
  176.  
  177. bool octave_dynamic_loader::doing_load = false;
  178.  
  179. bool
  180. octave_dynamic_loader::instance_ok (void)
  181. {
  182.   bool retval = true;
  183.  
  184.   if (! instance)
  185.     instance = new octave_dynamic_loader ();
  186.  
  187.   if (! instance)
  188.     {
  189.       error ("unable to create dynamic loader object!");
  190.  
  191.       retval = false;
  192.     }
  193.  
  194.   return retval;
  195. }
  196.  
  197. static
  198. void clear_function (const string& fcn_name)
  199. {
  200.   if (Vwarn_reload_forces_clear)
  201.     warning ("  %s", fcn_name.c_str ());
  202.  
  203.   curr_sym_tab->clear (fcn_name);
  204.  
  205.   if (curr_sym_tab != top_level_sym_tab)
  206.     top_level_sym_tab->clear (fcn_name);
  207.  
  208.   global_sym_tab->clear (fcn_name);
  209. }
  210.  
  211. bool
  212. octave_dynamic_loader::do_load (const string& fcn_name)
  213. {
  214.   bool retval = false;
  215.  
  216.   octave_shlib oct_file;
  217.  
  218.   unwind_protect::begin_frame ("octave_dynamic_loader::do_load");
  219.  
  220.   unwind_protect_bool (octave_dynamic_loader::doing_load);
  221.  
  222.   doing_load = true;
  223.  
  224.   void *function
  225.     = octave_shlib_list::search (fcn_name, oct_file, mangle_name);
  226.  
  227.   if (! error_state)
  228.     {
  229.       if (function && oct_file.is_out_of_date ())
  230.     {
  231.       int n = oct_file.number_of_functions_loaded ();
  232.  
  233.       if (n > 0 && Vwarn_reload_forces_clear)
  234.         warning ("reloading %s clears the following functions:",
  235.              oct_file.file_name().c_str ());
  236.  
  237.       oct_file.close (clear_function);
  238.  
  239.       function = 0;
  240.     }
  241.  
  242.       if (! function)
  243.     {
  244.       string oct_file_name = oct_file_in_path (fcn_name);
  245.  
  246.       if (! oct_file_name.empty ())
  247.         {
  248.           oct_file.open (oct_file_name, Vwarn_future_time_stamp);
  249.  
  250.           if (! error_state)
  251.         {
  252.           if (oct_file)
  253.             {
  254.               octave_shlib_list::append (oct_file);
  255.  
  256.               function = oct_file.search (fcn_name, mangle_name);
  257.             }
  258.           else
  259.             error ("%s is not a valid shared library",
  260.                oct_file_name.c_str ());
  261.         }
  262.         }
  263.     }
  264.     }
  265.  
  266.   if (function)
  267.     {
  268.       octave_dld_fcn_installer f
  269.     = X_CAST (octave_dld_fcn_installer, function);
  270.  
  271.       retval = f (oct_file);
  272.  
  273.       if (! retval)
  274.     error ("failed to install dld function `%s'", fcn_name.c_str ());
  275.     }
  276.  
  277.   unwind_protect::run_frame ("octave_dynamic_loader::do_load");
  278.  
  279.   return retval;
  280. }
  281.  
  282. bool
  283. octave_dynamic_loader::do_remove (const string& fcn_name, octave_shlib& shl)
  284. {
  285.   bool retval = false;
  286.  
  287.   // We don't need to do anything if this is called because we are in
  288.   // the process of reloading a .oct file that has changed.
  289.  
  290.   if (! doing_load)
  291.     {
  292.       retval = shl.remove (fcn_name);
  293.  
  294.       if (shl.number_of_functions_loaded () == 0)
  295.     octave_shlib_list::remove (shl);
  296.     }
  297.  
  298.   return retval;
  299. }
  300.  
  301. bool
  302. octave_dynamic_loader::load (const string& fcn_name)
  303. {
  304.   return (instance_ok ()) ? instance->do_load (fcn_name) : false;
  305. }
  306.  
  307. bool
  308. octave_dynamic_loader::remove (const string& fcn_name, octave_shlib& shl)
  309. {
  310.   return (instance_ok ()) ? instance->do_remove (fcn_name, shl) : false;
  311. }
  312.  
  313. string
  314. octave_dynamic_loader::mangle_name (const string& name)
  315. {
  316. #if defined (CXX_PREPENDS_UNDERSCORE)
  317.   string retval ("_FS");
  318. #else
  319.   string retval ("FS");
  320. #endif
  321.   retval.append (name);
  322.   retval.append ("__FRC12octave_shlib");
  323.   return retval;
  324. }
  325.  
  326. static int
  327. warn_reload_forces_clear (void)
  328. {
  329.   Vwarn_reload_forces_clear = check_preference ("warn_reload_forces_clear");
  330.  
  331.   return 0;
  332. }
  333.  
  334. void
  335. symbols_of_dynamic_ld (void)
  336. {
  337.   DEFVAR (warn_reload_forces_clear, 1.0, warn_reload_forces_clear,
  338.     "-*- texinfo -*-\n\
  339. @defvr {Built-in Variable} warn_reload_forces_clear\n\
  340. If several functions have been loaded from the same file, Octave must\n\
  341. clear all the functions before any one of them can be reloaded.  If\n\
  342. @code{warn_reload_forces_clear}, Octave will warn you when this happens,\n\
  343. and print a list of the additional functions that it is forced to clear.\n\
  344. @end defvr");
  345. }
  346.  
  347. /*
  348. ;;; Local Variables: ***
  349. ;;; mode: C++ ***
  350. ;;; End: ***
  351. */
  352.