GNU Octave  4.4.1
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-2018 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
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License 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, see
19 <https://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include <iostream>
28 #include <list>
29 
30 #include "file-stat.h"
31 #include "oct-env.h"
32 #include "oct-time.h"
33 
34 #include "defaults.h"
35 #include "defun.h"
36 #include "dynamic-ld.h"
37 #include "interpreter-private.h"
38 #include "interpreter.h"
39 #include "ov-fcn.h"
40 #include "ov-dld-fcn.h"
41 #include "ov-mex-fcn.h"
42 #include "parse.h"
43 #include "unwind-prot.h"
44 #include "utils.h"
45 #include "variables.h"
46 
47 #define STRINGIFY(s) STRINGIFY1(s)
48 #define STRINGIFY1(s) #s
49 
50 namespace octave
51 {
52  void
54  {
55  m_lib_list.push_back (shl);
56  }
57 
58  std::list<std::string>
60  {
61  std::list<std::string> removed_fcns;
62 
63  for (iterator p = m_lib_list.begin (); p != m_lib_list.end (); p++)
64  {
65  if (*p == shl)
66  {
67  m_lib_list.erase (p);
68 
69  removed_fcns = shl.close ();
70 
71  break;
72  }
73  }
74 
75  return removed_fcns;
76  }
77 
80  {
82 
83  for (const auto& lib : m_lib_list)
84  {
85  if (lib.file_name () == file_name)
86  {
87  retval = lib;
88  break;
89  }
90  }
91 
92  return retval;
93  }
94 
95  void
97  {
98  std::cerr << "current shared libraries:" << std::endl;
99  for (const auto& lib : m_lib_list)
100  std::cerr << " " << lib.file_name () << std::endl;
101  }
102 
103  void
105  {
106  warning_with_id ("Octave:reload-forces-clear", " %s", fcn_name.c_str ());
107 
108  // FIXME: is there a way to avoid this? Can we manage the list of
109  // functions that are loaded in the symbol table completely outside
110  // of the dynamic_loader class?
111 
113 
114  symtab.clear_dld_function (fcn_name);
115  }
116 
117  void
119  {
120  if (oct_file.number_of_functions_loaded () > 1)
121  {
122  warning_with_id ("Octave:reload-forces-clear",
123  "reloading %s clears the following functions:",
124  oct_file.file_name ().c_str ());
125 
126  std::list<std::string> removed_fcns = m_loaded_shlibs.remove (oct_file);
127 
128  for (const auto& fcn_name : removed_fcns)
129  clear_function (fcn_name);
130  }
131  else
132  {
133  std::list<std::string> removed_fcns = m_loaded_shlibs.remove (oct_file);
134 
135  // FIXME: is there a way to avoid this? Can we manage the list
136  // of functions that are loaded in the symbol table completely
137  // outside of the dynamic_loader class?
138 
140 
141  for (const auto& fcn_name : removed_fcns)
142  symtab.clear_dld_function (fcn_name);
143  }
144  }
145 
148  const std::string& file_name,
149  bool relative)
150  {
151  octave_function *retval = nullptr;
152 
154 
156 
157  m_doing_load = true;
158 
159  dynamic_library oct_file = m_loaded_shlibs.find_file (file_name);
160 
161  if (oct_file && oct_file.is_out_of_date ())
162  clear (oct_file);
163 
164  if (! oct_file)
165  {
166  oct_file.open (file_name);
167 
168  if (oct_file)
169  m_loaded_shlibs.append (oct_file);
170  }
171 
172  if (! oct_file)
173  error ("%s is not a valid shared library", file_name.c_str ());
174 
175  void *function = oct_file.search (fcn_name, name_mangler);
176 
177  if (! function)
178  {
179  // FIXME: can we determine this C mangling scheme
180  // automatically at run time or configure time?
181 
182  function = oct_file.search (fcn_name, name_uscore_mangler);
183  }
184 
185  if (function)
186  {
188  = reinterpret_cast<octave_dld_fcn_getter> (function);
189 
190  retval = f (oct_file, relative);
191 
192  if (! retval)
193  error ("failed to install .oct file function '%s'",
194  fcn_name.c_str ());
195  }
196 
197  return retval;
198  }
199 
202  const std::string& file_name,
203  bool /*relative*/)
204  {
205  octave_function *retval = nullptr;
206 
208 
210 
211  m_doing_load = true;
212 
213  dynamic_library mex_file = m_loaded_shlibs.find_file (file_name);
214 
215  if (mex_file && mex_file.is_out_of_date ())
216  clear (mex_file);
217 
218  if (! mex_file)
219  {
220  mex_file.open (file_name);
221 
222  if (mex_file)
223  m_loaded_shlibs.append (mex_file);
224  }
225 
226  if (! mex_file)
227  error ("%s is not a valid shared library", file_name.c_str ());
228 
229  void *function = nullptr;
230 
231  bool have_fmex = false;
232 
233  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 
240  function = mex_file.search (fcn_name, mex_uscore_mangler);
241 
242  if (! function)
243  {
244  function = mex_file.search (fcn_name, mex_f77_mangler);
245 
246  if (function)
247  have_fmex = true;
248  }
249  }
250 
251  if (function)
252  retval = new octave_mex_function (function, have_fmex, mex_file, fcn_name);
253  else
254  error ("failed to install .mex file function '%s'", fcn_name.c_str ());
255 
256  return retval;
257  }
258 
259  bool
261  dynamic_library& shl)
262  {
263  bool retval = false;
264 
265  // We don't need to do anything if this is called because we are in
266  // the process of reloading a .oct file that has changed.
267 
268  if (! m_doing_load)
269  {
270  retval = shl.remove (fcn_name);
271 
272  if (shl.number_of_functions_loaded () == 0)
273  m_loaded_shlibs.remove (shl);
274  }
275 
276  return retval;
277  }
278 
279  bool
281  dynamic_library& shl)
282  {
283  bool retval = false;
284 
285  // We don't need to do anything if this is called because we are in
286  // the process of reloading a .oct file that has changed.
287 
288  if (! m_doing_load)
289  {
290  retval = shl.remove (fcn_name);
291 
292  if (shl.number_of_functions_loaded () == 0)
293  m_loaded_shlibs.remove (shl);
294  }
295 
296  return retval;
297  }
298 
301  {
302  return 'G' + name;
303  }
304 
307  {
308  return "_G" + name;
309  }
310 
313  {
314  return "mexFunction";
315  }
316 
319  {
320  return "_mexFunction";
321  }
322 
325  {
326  return STRINGIFY (F77_FUNC (mexfunction, MEXFUNCTION));
327  }
328 }
void warning_with_id(const char *id, const char *fmt,...)
Definition: error.cc:816
size_t number_of_functions_loaded(void) const
Definition: oct-shlib.h:187
std::string file_name(void) const
Definition: oct-shlib.h:193
std::list< dynamic_library >::iterator iterator
Definition: dynamic-ld.h:49
void clear_dld_function(const std::string &name)
Definition: symtab.h:448
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE * f
void error(const char *fmt,...)
Definition: error.cc:578
bool is_out_of_date(void) const
Definition: oct-shlib.h:190
bool remove_oct(const std::string &fcn_name, dynamic_library &shl)
Definition: dynamic-ld.cc:260
std::list< dynamic_library > m_lib_list
Definition: dynamic-ld.h:73
static std::string name_uscore_mangler(const std::string &name)
Definition: dynamic-ld.cc:306
std::list< std::string > close(void)
Definition: oct-shlib.h:161
dynamic_library find_file(const std::string &file_name) const
Definition: dynamic-ld.cc:79
#define STRINGIFY(s)
Definition: dynamic-ld.cc:47
static std::string mex_mangler(const std::string &name)
Definition: dynamic-ld.cc:312
nd deftypefn *std::string name
Definition: sysdep.cc:647
interpreter & m_interpreter
Definition: dynamic-ld.h:113
shlibs_list m_loaded_shlibs
Definition: dynamic-ld.h:115
void clear_function(const std::string &fcn_name)
Definition: dynamic-ld.cc:104
static std::string mex_uscore_mangler(const std::string &name)
Definition: dynamic-ld.cc:318
octave_value retval
Definition: data.cc:6246
void clear(dynamic_library &oct_file)
Definition: dynamic-ld.cc:118
octave_function *(* octave_dld_fcn_getter)(const octave::dynamic_library &, bool relative)
Definition: defun-int.h:169
static std::string name_mangler(const std::string &name)
Definition: dynamic-ld.cc:300
F77_RET_T F77_FUNC(xerbla, XERBLA)
Definition: xerbla.c:57
symbol_table & get_symbol_table(void)
Definition: interpreter.h:169
bool remove_mex(const std::string &fcn_name, dynamic_library &shl)
Definition: dynamic-ld.cc:280
octave::unwind_protect frame
Definition: graphics.cc:12190
octave_function * load_mex(const std::string &fcn_name, const std::string &file_name="", bool relative=false)
Definition: dynamic-ld.cc:201
p
Definition: lu.cc:138
void open(const std::string &f)
Definition: oct-shlib.h:158
octave_function * load_oct(const std::string &fcn_name, const std::string &file_name="", bool relative=false)
Definition: dynamic-ld.cc:147
bool remove(const std::string &name)
Definition: oct-shlib.h:184
std::list< std::string > remove(dynamic_library &shl)
Definition: dynamic-ld.cc:59
void append(const dynamic_library &shl)
Definition: dynamic-ld.cc:53
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:888
void * search(const std::string &nm, name_mangler mangler=nullptr) const
Definition: oct-shlib.h:172
static std::string mex_f77_mangler(const std::string &name)
Definition: dynamic-ld.cc:324