GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
dynamic-ld.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1993-2013 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 3 of the License, or (at your
10 option) any 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, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef 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 #include "singleton-cleanup.h"
34 
35 #include <defaults.h>
36 
37 #include "defun.h"
38 #include "dynamic-ld.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 class
52 {
53 public:
54 
55  typedef std::list<octave_shlib>::iterator iterator;
56  typedef std::list<octave_shlib>::const_iterator const_iterator;
57 
58  static void append (const octave_shlib& shl);
59 
60  static void remove (octave_shlib& shl, octave_shlib::close_hook cl_hook = 0);
61 
62  static octave_shlib find_file (const std::string& file_name);
63 
64  static void display (void);
65 
66 private:
67 
68  octave_shlib_list (void) : lib_list () { }
69 
70  ~octave_shlib_list (void) { }
71 
72  void do_append (const octave_shlib& shl);
73 
74  void do_remove (octave_shlib& shl, octave_shlib::close_hook cl_hook = 0);
75 
76  octave_shlib do_find_file (const std::string& file_name) const;
77 
78  void do_display (void) const;
79 
81 
82  static void cleanup_instance (void) { delete instance; instance = 0; }
83 
84  static bool instance_ok (void);
85 
86  // List of libraries we have loaded.
87  std::list<octave_shlib> lib_list;
88 
89  // No copying!
90 
92 
94 };
95 
97 
98 void
100 {
101  lib_list.push_back (shl);
102 }
103 
104 void
106  octave_shlib::close_hook cl_hook)
107 {
108  for (iterator p = lib_list.begin (); p != lib_list.end (); p++)
109  {
110  if (*p == shl)
111  {
112  // Erase first to avoid potentially invalidating the pointer by the
113  // following hooks.
114  lib_list.erase (p);
115 
116  shl.close (cl_hook);
117 
118  break;
119  }
120  }
121 }
122 
124 octave_shlib_list::do_find_file (const std::string& file_name) const
125 {
126  octave_shlib retval;
127 
128  for (const_iterator p = lib_list.begin (); p != lib_list.end (); p++)
129  {
130  if (p->file_name () == file_name)
131  {
132  retval = *p;
133  break;
134  }
135  }
136 
137  return retval;
138 }
139 
140 void
142 {
143  std::cerr << "current shared libraries:" << std::endl;
144  for (const_iterator p = lib_list.begin (); p != lib_list.end (); p++)
145  std::cerr << " " << p->file_name () << std::endl;
146 }
147 
148 bool
150 {
151  bool retval = true;
152 
153  if (! instance)
154  {
155  instance = new octave_shlib_list ();
156 
157  if (instance)
159  }
160 
161  if (! instance)
162  {
163  ::error ("unable to create shared library list object!");
164 
165  retval = false;
166  }
167 
168  return retval;
169 }
170 
171 void
173 {
174  if (instance_ok ())
175  instance->do_append (shl);
176 }
177 
178 void
180  octave_shlib::close_hook cl_hook)
181 {
182  if (instance_ok ())
183  instance->do_remove (shl, cl_hook);
184 }
185 
187 octave_shlib_list::find_file (const std::string& file_name)
188 {
189  return (instance_ok ())
190  ? instance->do_find_file (file_name) : octave_shlib ();
191 }
192 
193 void
195 {
196  if (instance_ok ())
197  instance->do_display ();
198 }
199 
201 
203 
204 bool
206 {
207  bool retval = true;
208 
209  if (! instance)
210  {
212 
213  if (instance)
215  }
216 
217  if (! instance)
218  {
219  ::error ("unable to create dynamic loader object!");
220 
221  retval = false;
222  }
223 
224  return retval;
225 }
226 
227 static void
228 do_clear_function (const std::string& fcn_name)
229 {
230  warning_with_id ("Octave:reload-forces-clear", " %s", fcn_name.c_str ());
231 
233 }
234 
235 static void
236 clear (octave_shlib& oct_file)
237 {
238  if (oct_file.number_of_functions_loaded () > 1)
239  {
240  warning_with_id ("Octave:reload-forces-clear",
241  "reloading %s clears the following functions:",
242  oct_file.file_name ().c_str ());
243 
245  }
246  else
248 }
249 
251 octave_dynamic_loader::do_load_oct (const std::string& fcn_name,
252  const std::string& file_name,
253  bool relative)
254 {
255  octave_function *retval = 0;
256 
257  unwind_protect frame;
258 
260 
261  doing_load = true;
262 
263  octave_shlib oct_file = octave_shlib_list::find_file (file_name);
264 
265  if (oct_file && oct_file.is_out_of_date ())
266  clear (oct_file);
267 
268  if (! oct_file)
269  {
270  oct_file.open (file_name);
271 
272  if (! error_state && oct_file)
273  octave_shlib_list::append (oct_file);
274  }
275 
276  if (! error_state)
277  {
278  if (oct_file)
279  {
280  void *function = oct_file.search (fcn_name, name_mangler);
281 
282  if (! function)
283  {
284  // FIXME: can we determine this C mangling scheme
285  // automatically at run time or configure time?
286 
287  function = oct_file.search (fcn_name, name_uscore_mangler);
288  }
289 
290  if (function)
291  {
293  = FCN_PTR_CAST (octave_dld_fcn_getter, function);
294 
295  retval = f (oct_file, relative);
296 
297  if (! retval)
298  ::error ("failed to install .oct file function '%s'",
299  fcn_name.c_str ());
300  }
301  }
302  else
303  ::error ("%s is not a valid shared library",
304  file_name.c_str ());
305  }
306 
307  return retval;
308 }
309 
311 octave_dynamic_loader::do_load_mex (const std::string& fcn_name,
312  const std::string& file_name,
313  bool /*relative*/)
314 {
315  octave_function *retval = 0;
316 
317  unwind_protect frame;
318 
320 
321  doing_load = true;
322 
323  octave_shlib mex_file = octave_shlib_list::find_file (file_name);
324 
325  if (mex_file && mex_file.is_out_of_date ())
326  clear (mex_file);
327 
328  if (! mex_file)
329  {
330  mex_file.open (file_name);
331 
332  if (! error_state && mex_file)
333  octave_shlib_list::append (mex_file);
334  }
335 
336  if (! error_state)
337  {
338  if (mex_file)
339  {
340  void *function = 0;
341 
342  bool have_fmex = false;
343 
344  function = mex_file.search (fcn_name, mex_mangler);
345 
346  if (! function)
347  {
348  // FIXME: can we determine this C mangling scheme
349  // automatically at run time or configure time?
350 
351  function = mex_file.search (fcn_name, mex_uscore_mangler);
352 
353  if (! function)
354  {
355  function = mex_file.search (fcn_name, mex_f77_mangler);
356 
357  if (function)
358  have_fmex = true;
359  }
360  }
361 
362  if (function)
363  retval = new octave_mex_function (function, have_fmex,
364  mex_file, fcn_name);
365  else
366  ::error ("failed to install .mex file function '%s'",
367  fcn_name.c_str ());
368  }
369  else
370  ::error ("%s is not a valid shared library",
371  file_name.c_str ());
372  }
373 
374  return retval;
375 }
376 
377 bool
378 octave_dynamic_loader::do_remove_oct (const std::string& fcn_name,
379  octave_shlib& shl)
380 {
381  bool retval = false;
382 
383  // We don't need to do anything if this is called because we are in
384  // the process of reloading a .oct file that has changed.
385 
386  if (! doing_load)
387  {
388  retval = shl.remove (fcn_name);
389 
390  if (shl.number_of_functions_loaded () == 0)
392  }
393 
394  return retval;
395 }
396 
397 bool
398 octave_dynamic_loader::do_remove_mex (const std::string& fcn_name,
399  octave_shlib& shl)
400 {
401  bool retval = false;
402 
403  // We don't need to do anything if this is called because we are in
404  // the process of reloading a .oct file that has changed.
405 
406  if (! doing_load)
407  {
408  retval = shl.remove (fcn_name);
409 
410  if (shl.number_of_functions_loaded () == 0)
412  }
413 
414  return retval;
415 }
416 
418 octave_dynamic_loader::load_oct (const std::string& fcn_name,
419  const std::string& file_name,
420  bool relative)
421 {
422  return (instance_ok ())
423  ? instance->do_load_oct (fcn_name, file_name, relative) : 0;
424 }
425 
427 octave_dynamic_loader::load_mex (const std::string& fcn_name,
428  const std::string& file_name,
429  bool relative)
430 {
431  return (instance_ok ())
432  ? instance->do_load_mex (fcn_name, file_name, relative) : 0;
433 }
434 
435 bool
436 octave_dynamic_loader::remove_oct (const std::string& fcn_name,
437  octave_shlib& shl)
438 {
439  return (instance_ok ()) ? instance->do_remove_oct (fcn_name, shl) : false;
440 }
441 
442 bool
443 octave_dynamic_loader::remove_mex (const std::string& fcn_name,
444  octave_shlib& shl)
445 {
446  return (instance_ok ()) ? instance->do_remove_mex (fcn_name, shl) : false;
447 }
448 
449 std::string
450 octave_dynamic_loader::name_mangler (const std::string& name)
451 {
452  return "G" + name;
453 }
454 
455 std::string
457 {
458  return "_G" + name;
459 }
460 
461 std::string
463 {
464  return "mexFunction";
465 }
466 
467 std::string
469 {
470  return "_mexFunction";
471 }
472 
473 std::string
475 {
476  return STRINGIFY (F77_FUNC (mexfunction, MEXFUNCTION));
477 }