GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
dynamic-ld.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1993-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include <iostream>
31 #include <list>
32 
33 #include "file-stat.h"
34 #include "oct-env.h"
35 #include "oct-time.h"
36 
37 #include "defun.h"
38 #include "dynamic-ld.h"
39 #include "interpreter-private.h"
40 #include "interpreter.h"
41 #include "ov-fcn.h"
42 #include "ov-dld-fcn.h"
43 #include "ov-mex-fcn.h"
44 #include "parse.h"
45 #include "unwind-prot.h"
46 #include "utils.h"
47 #include "variables.h"
48 
49 #define STRINGIFY(s) STRINGIFY1(s)
50 #define STRINGIFY1(s) #s
51 
52 namespace octave
53 {
54  void
56  {
57  m_lib_list.push_back (shl);
58  }
59 
60  std::list<std::string>
62  {
63  std::list<std::string> removed_fcns;
64 
65  for (auto p = m_lib_list.begin (); p != m_lib_list.end (); p++)
66  {
67  if (*p == shl)
68  {
69  m_lib_list.erase (p);
70 
71  removed_fcns = shl.close ();
72 
73  break;
74  }
75  }
76 
77  return removed_fcns;
78  }
79 
81  dynamic_loader::shlibs_list::find_file (const std::string& file_name) const
82  {
84 
85  for (const auto& lib : m_lib_list)
86  {
87  if (lib.file_name () == file_name)
88  {
89  retval = lib;
90  break;
91  }
92  }
93 
94  return retval;
95  }
96 
97  void
99  {
100  std::cerr << "current shared libraries:" << std::endl;
101  for (const auto& lib : m_lib_list)
102  std::cerr << " " << lib.file_name () << std::endl;
103  }
104 
105  void
106  dynamic_loader::clear_function (const std::string& fcn_name)
107  {
108  warning_with_id ("Octave:reload-forces-clear", " %s", fcn_name.c_str ());
109 
110  // FIXME: is there a way to avoid this? Can we manage the list of
111  // functions that are loaded in the symbol table completely outside
112  // of the dynamic_loader class?
113 
115 
116  symtab.clear_dld_function (fcn_name);
117  }
118 
119  void
121  {
122  if (oct_file.number_of_functions_loaded () > 1)
123  {
124  warning_with_id ("Octave:reload-forces-clear",
125  "reloading %s clears the following functions:",
126  oct_file.file_name ().c_str ());
127 
128  std::list<std::string> removed_fcns = m_loaded_shlibs.remove (oct_file);
129 
130  for (const auto& fcn_name : removed_fcns)
131  clear_function (fcn_name);
132  }
133  else
134  {
135  std::list<std::string> removed_fcns = m_loaded_shlibs.remove (oct_file);
136 
137  // FIXME: is there a way to avoid this? Can we manage the list
138  // of functions that are loaded in the symbol table completely
139  // outside of the dynamic_loader class?
140 
142 
143  for (const auto& fcn_name : removed_fcns)
144  symtab.clear_dld_function (fcn_name);
145  }
146  }
147 
149  dynamic_loader::load_oct (const std::string& fcn_name,
150  const std::string& file_name,
151  bool relative)
152  {
153  octave_function *retval = nullptr;
154 
155  unwind_protect frame;
156 
157  frame.protect_var (m_doing_load);
158 
159  m_doing_load = true;
160 
161  dynamic_library oct_file = m_loaded_shlibs.find_file (file_name);
162 
163  if (oct_file && oct_file.is_out_of_date ())
164  clear (oct_file);
165 
166  if (! oct_file)
167  {
168  oct_file.open (file_name);
169 
170  if (oct_file)
171  m_loaded_shlibs.append (oct_file);
172  }
173 
174  if (! oct_file)
175  error ("%s is not a valid shared library", file_name.c_str ());
176 
177  void *function = oct_file.search (fcn_name, name_mangler);
178 
179  if (! function)
180  {
181  // FIXME: can we determine this C mangling scheme
182  // automatically at run time or configure time?
183 
184  function = oct_file.search (fcn_name, name_uscore_mangler);
185  }
186 
187  if (function)
188  {
190  = reinterpret_cast<octave_dld_fcn_getter> (function);
191 
192  retval = f (oct_file, relative);
193 
194  if (! retval)
195  error ("failed to install .oct file function '%s'",
196  fcn_name.c_str ());
197  }
198 
199  return retval;
200  }
201 
203  dynamic_loader::load_mex (const std::string& fcn_name,
204  const std::string& file_name,
205  bool /*relative*/)
206  {
207  octave_function *retval = nullptr;
208 
209  unwind_protect frame;
210 
211  frame.protect_var (m_doing_load);
212 
213  m_doing_load = true;
214 
215  dynamic_library mex_file = m_loaded_shlibs.find_file (file_name);
216 
217  if (mex_file && mex_file.is_out_of_date ())
218  clear (mex_file);
219 
220  if (! mex_file)
221  {
222  mex_file.open (file_name);
223 
224  if (mex_file)
225  m_loaded_shlibs.append (mex_file);
226  }
227 
228  if (! mex_file)
229  error ("%s is not a valid shared library", file_name.c_str ());
230 
231  bool have_fmex = false;
232 
233  void *function = mex_file.search (fcn_name, mex_mangler);
234 
235  if (! function)
236  {
237  // FIXME: Can we determine this C mangling scheme
238  // automatically at run time or configure time?
239  function = mex_file.search (fcn_name, mex_uscore_mangler);
240 
241  if (! function)
242  {
243  function = mex_file.search (fcn_name, mex_f77_mangler);
244 
245  if (function)
246  have_fmex = true;
247  }
248  }
249 
250  if (! function)
251  error ("failed to install .mex file function '%s'", fcn_name.c_str ());
252 
253  retval = new octave_mex_function (function, have_fmex, mex_file, fcn_name);
254 
255  return retval;
256  }
257 
258  bool
259  dynamic_loader::remove_oct (const std::string& fcn_name,
260  dynamic_library& shl)
261  {
262  bool retval = false;
263 
264  // We don't need to do anything if this is called because we are in
265  // the process of reloading a .oct file that has changed.
266 
267  if (! m_doing_load)
268  {
269  retval = shl.remove (fcn_name);
270 
271  if (shl.number_of_functions_loaded () == 0)
272  m_loaded_shlibs.remove (shl);
273  }
274 
275  return retval;
276  }
277 
278  bool
279  dynamic_loader::remove_mex (const std::string& fcn_name,
280  dynamic_library& shl)
281  {
282  // Use the same procedure as for oct files.
283  return remove_oct (fcn_name, shl);
284  }
285 
286  std::string
287  dynamic_loader::name_mangler (const std::string& name)
288  {
289  return 'G' + name;
290  }
291 
292  std::string
294  {
295  return "_G" + name;
296  }
297 
298  std::string
299  dynamic_loader::mex_mangler (const std::string&)
300  {
301  return "mexFunction";
302  }
303 
304  std::string
306  {
307  return "_mexFunction";
308  }
309 
310  std::string
311  dynamic_loader::mex_f77_mangler (const std::string&)
312  {
313  return STRINGIFY (F77_FUNC (mexfunction, MEXFUNCTION));
314  }
315 }
bool remove(const std::string &name)
Definition: oct-shlib.h:188
std::list< std::string > close(void)
Definition: oct-shlib.h:164
bool is_out_of_date(void) const
Definition: oct-shlib.h:194
size_t number_of_functions_loaded(void) const
Definition: oct-shlib.h:191
std::string file_name(void) const
Definition: oct-shlib.h:197
void open(const std::string &f)
Definition: oct-shlib.h:161
void * search(const std::string &nm, const name_mangler &mangler=name_mangler()) const
Definition: oct-shlib.h:175
std::list< dynamic_library > m_lib_list
Definition: dynamic-ld.h:76
dynamic_library find_file(const std::string &file_name) const
Definition: dynamic-ld.cc:81
std::list< std::string > remove(dynamic_library &shl)
Definition: dynamic-ld.cc:61
void append(const dynamic_library &shl)
Definition: dynamic-ld.cc:55
shlibs_list m_loaded_shlibs
Definition: dynamic-ld.h:118
void clear_function(const std::string &fcn_name)
Definition: dynamic-ld.cc:106
static std::string mex_mangler(const std::string &name)
Definition: dynamic-ld.cc:299
interpreter & m_interpreter
Definition: dynamic-ld.h:116
bool remove_mex(const std::string &fcn_name, dynamic_library &shl)
Definition: dynamic-ld.cc:279
static std::string mex_f77_mangler(const std::string &name)
Definition: dynamic-ld.cc:311
void clear(dynamic_library &oct_file)
Definition: dynamic-ld.cc:120
static std::string name_mangler(const std::string &name)
Definition: dynamic-ld.cc:287
static std::string name_uscore_mangler(const std::string &name)
Definition: dynamic-ld.cc:293
static std::string mex_uscore_mangler(const std::string &name)
Definition: dynamic-ld.cc:305
octave_function * load_oct(const std::string &fcn_name, const std::string &file_name="", bool relative=false)
Definition: dynamic-ld.cc:149
octave_function * load_mex(const std::string &fcn_name, const std::string &file_name="", bool relative=false)
Definition: dynamic-ld.cc:203
bool remove_oct(const std::string &fcn_name, dynamic_library &shl)
Definition: dynamic-ld.cc:259
symbol_table & get_symbol_table(void)
Definition: interpreter.h:258
void clear_dld_function(const std::string &name)
Definition: symtab.cc:485
octave_function *(* octave_dld_fcn_getter)(const octave::dynamic_library &, bool relative)
Definition: defun-int.h:137
#define STRINGIFY(s)
Definition: dynamic-ld.cc:49
void warning_with_id(const char *id, const char *fmt,...)
Definition: error.cc:1065
void error(const char *fmt,...)
Definition: error.cc:968
QString name
static double f(double k, double l_nu, double c_pm)
Definition: randpoisson.cc:118
octave_value::octave_value(const Array< char > &chm, char type) return retval
Definition: ov.cc:811
F77_RET_T F77_FUNC(xerbla, XERBLA)(F77_CONST_CHAR_ARG_DEF(s_arg