00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include <iostream>
00028 #include <list>
00029
00030 #include "file-stat.h"
00031 #include "oct-env.h"
00032 #include "oct-time.h"
00033 #include "singleton-cleanup.h"
00034
00035 #include <defaults.h>
00036
00037 #include "defun.h"
00038 #include "dynamic-ld.h"
00039 #include "ov-fcn.h"
00040 #include "ov-dld-fcn.h"
00041 #include "ov-mex-fcn.h"
00042 #include "parse.h"
00043 #include "unwind-prot.h"
00044 #include "utils.h"
00045 #include "variables.h"
00046
00047 #define STRINGIFY(s) STRINGIFY1(s)
00048 #define STRINGIFY1(s) #s
00049
00050 class
00051 octave_shlib_list
00052 {
00053 public:
00054
00055 typedef std::list<octave_shlib>::iterator iterator;
00056 typedef std::list<octave_shlib>::const_iterator const_iterator;
00057
00058 static void append (const octave_shlib& shl);
00059
00060 static void remove (octave_shlib& shl, octave_shlib::close_hook cl_hook = 0);
00061
00062 static octave_shlib find_file (const std::string& file_name);
00063
00064 static void display (void);
00065
00066 private:
00067
00068 octave_shlib_list (void) : lib_list () { }
00069
00070 ~octave_shlib_list (void) { }
00071
00072 void do_append (const octave_shlib& shl);
00073
00074 void do_remove (octave_shlib& shl, octave_shlib::close_hook cl_hook = 0);
00075
00076 octave_shlib do_find_file (const std::string& file_name) const;
00077
00078 void do_display (void) const;
00079
00080 static octave_shlib_list *instance;
00081
00082 static void cleanup_instance (void) { delete instance; instance = 0; }
00083
00084 static bool instance_ok (void);
00085
00086
00087 std::list<octave_shlib> lib_list;
00088
00089
00090
00091 octave_shlib_list (const octave_shlib_list&);
00092
00093 octave_shlib_list& operator = (const octave_shlib_list&);
00094 };
00095
00096 octave_shlib_list *octave_shlib_list::instance = 0;
00097
00098 void
00099 octave_shlib_list::do_append (const octave_shlib& shl)
00100 {
00101 lib_list.push_back (shl);
00102 }
00103
00104 void
00105 octave_shlib_list::do_remove (octave_shlib& shl,
00106 octave_shlib::close_hook cl_hook)
00107 {
00108 for (iterator p = lib_list.begin (); p != lib_list.end (); p++)
00109 {
00110 if (*p == shl)
00111 {
00112
00113
00114 lib_list.erase (p);
00115
00116 shl.close (cl_hook);
00117
00118 break;
00119 }
00120 }
00121 }
00122
00123 octave_shlib
00124 octave_shlib_list::do_find_file (const std::string& file_name) const
00125 {
00126 octave_shlib retval;
00127
00128 for (const_iterator p = lib_list.begin (); p != lib_list.end (); p++)
00129 {
00130 if (p->file_name () == file_name)
00131 {
00132 retval = *p;
00133 break;
00134 }
00135 }
00136
00137 return retval;
00138 }
00139
00140 void
00141 octave_shlib_list::do_display (void) const
00142 {
00143 std::cerr << "current shared libraries:" << std::endl;
00144 for (const_iterator p = lib_list.begin (); p != lib_list.end (); p++)
00145 std::cerr << " " << p->file_name () << std::endl;
00146 }
00147
00148 bool
00149 octave_shlib_list::instance_ok (void)
00150 {
00151 bool retval = true;
00152
00153 if (! instance)
00154 {
00155 instance = new octave_shlib_list ();
00156
00157 if (instance)
00158 singleton_cleanup_list::add (cleanup_instance);
00159 }
00160
00161 if (! instance)
00162 {
00163 ::error ("unable to create shared library list object!");
00164
00165 retval = false;
00166 }
00167
00168 return retval;
00169 }
00170
00171 void
00172 octave_shlib_list::append (const octave_shlib& shl)
00173 {
00174 if (instance_ok ())
00175 instance->do_append (shl);
00176 }
00177
00178 void
00179 octave_shlib_list::remove (octave_shlib& shl,
00180 octave_shlib::close_hook cl_hook)
00181 {
00182 if (instance_ok ())
00183 instance->do_remove (shl, cl_hook);
00184 }
00185
00186 octave_shlib
00187 octave_shlib_list::find_file (const std::string& file_name)
00188 {
00189 return (instance_ok ())
00190 ? instance->do_find_file (file_name) : octave_shlib ();
00191 }
00192
00193 void
00194 octave_shlib_list::display (void)
00195 {
00196 if (instance_ok ())
00197 instance->do_display ();
00198 }
00199
00200 class
00201 octave_mex_file_list
00202 {
00203 public:
00204
00205 typedef std::list<octave_shlib>::iterator iterator;
00206 typedef std::list<octave_shlib>::const_iterator const_iterator;
00207
00208 static void append (const octave_shlib& shl);
00209
00210 static void remove (octave_shlib& shl, octave_shlib::close_hook cl_hook = 0);
00211
00212 private:
00213
00214 octave_mex_file_list (void) : file_list () { }
00215
00216 ~octave_mex_file_list (void) { }
00217
00218 void do_append (const octave_shlib& shl);
00219
00220 void do_remove (octave_shlib& shl, octave_shlib::close_hook cl_hook = 0);
00221
00222 static octave_mex_file_list *instance;
00223
00224 static void cleanup_instance (void) { delete instance; instance = 0; }
00225
00226 static bool instance_ok (void);
00227
00228
00229 std::list<octave_shlib> file_list;
00230
00231
00232
00233 octave_mex_file_list (const octave_mex_file_list&);
00234
00235 octave_mex_file_list& operator = (const octave_mex_file_list&);
00236 };
00237
00238 octave_mex_file_list *octave_mex_file_list::instance = 0;
00239
00240 void
00241 octave_mex_file_list::do_append (const octave_shlib& shl)
00242 {
00243 file_list.push_back (shl);
00244 }
00245
00246 void
00247 octave_mex_file_list::do_remove (octave_shlib& shl,
00248 octave_shlib::close_hook cl_hook)
00249 {
00250 for (iterator p = file_list.begin (); p != file_list.end (); p++)
00251 {
00252 if (*p == shl)
00253 {
00254
00255
00256 file_list.erase (p);
00257
00258 shl.close (cl_hook);
00259
00260 break;
00261 }
00262 }
00263 }
00264
00265 bool
00266 octave_mex_file_list::instance_ok (void)
00267 {
00268 bool retval = true;
00269
00270 if (! instance)
00271 {
00272 instance = new octave_mex_file_list ();
00273
00274 if (instance)
00275 singleton_cleanup_list::add (cleanup_instance);
00276 }
00277
00278 if (! instance)
00279 {
00280 ::error ("unable to create shared library list object!");
00281
00282 retval = false;
00283 }
00284
00285 return retval;
00286 }
00287
00288 void
00289 octave_mex_file_list::append (const octave_shlib& shl)
00290 {
00291 if (instance_ok ())
00292 instance->do_append (shl);
00293 }
00294
00295 void
00296 octave_mex_file_list::remove (octave_shlib& shl,
00297 octave_shlib::close_hook cl_hook)
00298 {
00299 if (instance_ok ())
00300 instance->do_remove (shl, cl_hook);
00301 }
00302
00303 octave_dynamic_loader *octave_dynamic_loader::instance = 0;
00304
00305 bool octave_dynamic_loader::doing_load = false;
00306
00307 bool
00308 octave_dynamic_loader::instance_ok (void)
00309 {
00310 bool retval = true;
00311
00312 if (! instance)
00313 {
00314 instance = new octave_dynamic_loader ();
00315
00316 if (instance)
00317 singleton_cleanup_list::add (cleanup_instance);
00318 }
00319
00320 if (! instance)
00321 {
00322 ::error ("unable to create dynamic loader object!");
00323
00324 retval = false;
00325 }
00326
00327 return retval;
00328 }
00329
00330 static void
00331 do_clear_function (const std::string& fcn_name)
00332 {
00333 warning_with_id ("Octave:reload-forces-clear", " %s", fcn_name.c_str ());
00334
00335 symbol_table::clear_dld_function (fcn_name);
00336 }
00337
00338 static void
00339 clear (octave_shlib& oct_file)
00340 {
00341 if (oct_file.number_of_functions_loaded () > 1)
00342 {
00343 warning_with_id ("Octave:reload-forces-clear",
00344 "reloading %s clears the following functions:",
00345 oct_file.file_name().c_str ());
00346
00347 octave_shlib_list::remove (oct_file, do_clear_function);
00348 }
00349 else
00350 octave_shlib_list::remove (oct_file, symbol_table::clear_dld_function);
00351 }
00352
00353 octave_function *
00354 octave_dynamic_loader::do_load_oct (const std::string& fcn_name,
00355 const std::string& file_name,
00356 bool relative)
00357 {
00358 octave_function *retval = 0;
00359
00360 unwind_protect frame;
00361
00362 frame.protect_var (octave_dynamic_loader::doing_load);
00363
00364 doing_load = true;
00365
00366 octave_shlib oct_file = octave_shlib_list::find_file (file_name);
00367
00368 if (oct_file && oct_file.is_out_of_date ())
00369 clear (oct_file);
00370
00371 if (! oct_file)
00372 {
00373 oct_file.open (file_name);
00374
00375 if (! error_state && oct_file)
00376 octave_shlib_list::append (oct_file);
00377 }
00378
00379 if (! error_state)
00380 {
00381 if (oct_file)
00382 {
00383 void *function = oct_file.search (fcn_name, name_mangler);
00384
00385 if (! function)
00386 {
00387
00388
00389
00390 function = oct_file.search (fcn_name, name_uscore_mangler);
00391 }
00392
00393 if (function)
00394 {
00395 octave_dld_fcn_getter f
00396 = FCN_PTR_CAST (octave_dld_fcn_getter, function);
00397
00398 retval = f (oct_file, relative);
00399
00400 if (! retval)
00401 ::error ("failed to install .oct file function '%s'",
00402 fcn_name.c_str ());
00403 }
00404 }
00405 else
00406 ::error ("%s is not a valid shared library",
00407 file_name.c_str ());
00408 }
00409
00410 return retval;
00411 }
00412
00413 octave_function *
00414 octave_dynamic_loader::do_load_mex (const std::string& fcn_name,
00415 const std::string& file_name,
00416 bool )
00417 {
00418 octave_function *retval = 0;
00419
00420 unwind_protect frame;
00421
00422 frame.protect_var (octave_dynamic_loader::doing_load);
00423
00424 doing_load = true;
00425
00426 octave_shlib mex_file = octave_shlib_list::find_file (file_name);
00427
00428 if (mex_file && mex_file.is_out_of_date ())
00429 clear (mex_file);
00430
00431 if (! mex_file)
00432 {
00433 mex_file.open (file_name);
00434
00435 if (! error_state && mex_file)
00436 octave_shlib_list::append (mex_file);
00437 }
00438
00439 if (! error_state)
00440 {
00441 if (mex_file)
00442 {
00443 void *function = 0;
00444
00445 bool have_fmex = false;
00446
00447 octave_mex_file_list::append (mex_file);
00448
00449 function = mex_file.search (fcn_name, mex_mangler);
00450
00451 if (! function)
00452 {
00453
00454
00455
00456 function = mex_file.search (fcn_name, mex_uscore_mangler);
00457
00458 if (! function)
00459 {
00460 function = mex_file.search (fcn_name, mex_f77_mangler);
00461
00462 if (function)
00463 have_fmex = true;
00464 }
00465 }
00466
00467 if (function)
00468 retval = new octave_mex_function (function, have_fmex,
00469 mex_file, fcn_name);
00470 else
00471 ::error ("failed to install .mex file function '%s'",
00472 fcn_name.c_str ());
00473 }
00474 else
00475 ::error ("%s is not a valid shared library",
00476 file_name.c_str ());
00477 }
00478
00479 return retval;
00480 }
00481
00482 bool
00483 octave_dynamic_loader::do_remove_oct (const std::string& fcn_name,
00484 octave_shlib& shl)
00485 {
00486 bool retval = false;
00487
00488
00489
00490
00491 if (! doing_load)
00492 {
00493 retval = shl.remove (fcn_name);
00494
00495 if (shl.number_of_functions_loaded () == 0)
00496 octave_shlib_list::remove (shl);
00497 }
00498
00499 return retval;
00500 }
00501
00502 bool
00503 octave_dynamic_loader::do_remove_mex (const std::string& fcn_name,
00504 octave_shlib& shl)
00505 {
00506 bool retval = false;
00507
00508
00509
00510
00511 if (! doing_load)
00512 {
00513 retval = shl.remove (fcn_name);
00514
00515 if (shl.number_of_functions_loaded () == 0)
00516 octave_mex_file_list::remove (shl);
00517 }
00518
00519 return retval;
00520 }
00521
00522 octave_function *
00523 octave_dynamic_loader::load_oct (const std::string& fcn_name,
00524 const std::string& file_name,
00525 bool relative)
00526 {
00527 return (instance_ok ())
00528 ? instance->do_load_oct (fcn_name, file_name, relative) : 0;
00529 }
00530
00531 octave_function *
00532 octave_dynamic_loader::load_mex (const std::string& fcn_name,
00533 const std::string& file_name,
00534 bool relative)
00535 {
00536 return (instance_ok ())
00537 ? instance->do_load_mex (fcn_name, file_name, relative) : 0;
00538 }
00539
00540 bool
00541 octave_dynamic_loader::remove_oct (const std::string& fcn_name,
00542 octave_shlib& shl)
00543 {
00544 return (instance_ok ()) ? instance->do_remove_oct (fcn_name, shl) : false;
00545 }
00546
00547 bool
00548 octave_dynamic_loader::remove_mex (const std::string& fcn_name,
00549 octave_shlib& shl)
00550 {
00551 return (instance_ok ()) ? instance->do_remove_mex (fcn_name, shl) : false;
00552 }
00553
00554 std::string
00555 octave_dynamic_loader::name_mangler (const std::string& name)
00556 {
00557 return "G" + name;
00558 }
00559
00560 std::string
00561 octave_dynamic_loader::name_uscore_mangler (const std::string& name)
00562 {
00563 return "_G" + name;
00564 }
00565
00566 std::string
00567 octave_dynamic_loader::mex_mangler (const std::string&)
00568 {
00569 return "mexFunction";
00570 }
00571
00572 std::string
00573 octave_dynamic_loader::mex_uscore_mangler (const std::string&)
00574 {
00575 return "_mexFunction";
00576 }
00577
00578 std::string
00579 octave_dynamic_loader::mex_f77_mangler (const std::string&)
00580 {
00581 return STRINGIFY (F77_FUNC (mexfunction, MEXFUNCTION));
00582 }