メインページ   クラス階層   構成   ファイル一覧   構成メンバ   ファイルメンバ  

oct-shlib.cc

解説を見る。
00001 /*
00002 
00003 Copyright (C) 1999 John W. Eaton
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 2, or (at your option) any
00010 later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, write to the Free
00019 Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00020 
00021 */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #if defined (HAVE_SHL_LOAD_API)
00028 #include <cerrno>
00029 #include <cstring>
00030 #endif
00031 
00032 #if defined (HAVE_DYLD_API)
00033 #include <mach-o/dyld.h>
00034 #endif
00035 
00036 extern "C"
00037 {
00038 #if defined (HAVE_DLOPEN_API)
00039 #if defined (HAVE_DLFCN_H)
00040 #include <dlfcn.h>
00041 #else
00042 extern void *dlopen (const char *, int);
00043 extern const char *dlerror (void);
00044 extern void *dlsym (void *, const char *);
00045 extern int dlclose (void *);
00046 #endif
00047 #elif defined (HAVE_SHL_LOAD_API)
00048 #include <dl.h>
00049 #endif
00050 }
00051 
00052 #include "file-stat.h"
00053 #include "lo-error.h"
00054 #include "oct-shlib.h"
00055 #include "str-vec.h"
00056 
00057 class
00058 octave_base_shlib : public octave_shlib
00059 {
00060 public:
00061 
00062   octave_base_shlib (void)
00063     : octave_shlib (octave_xshlib ()), file (), fcn_names (),
00064       tm_loaded (static_cast<time_t> (0))
00065   { count = 1; }
00066 
00067   octave_base_shlib (const std::string& f)
00068     : octave_shlib (octave_xshlib ()), file (f), fcn_names (),
00069       tm_loaded (static_cast<time_t> (0))
00070   { count = 1; }
00071 
00072   ~octave_base_shlib (void) { }
00073 
00074   void open (const std::string&, bool = false) { }
00075 
00076   void *search (const std::string&, name_mangler = 0) { return 0; }
00077 
00078   void close (octave_shlib::close_hook = 0) { }
00079 
00080   bool remove (const std::string& fcn_name);
00081 
00082   bool is_open (void) const { return false; }
00083 
00084   bool is_out_of_date (void) const;
00085 
00086   int number_of_functions_loaded (void) const { return fcn_names.length (); }
00087 
00088   std::string file_name (void) const { return file; }
00089 
00090   octave_time time_loaded (void) const { return tm_loaded; }
00091 
00092 protected:
00093 
00094   std::string file;
00095 
00096   string_vector fcn_names;
00097 
00098   octave_time tm_loaded;
00099 
00100   void stamp_time (bool warn_future = false);
00101 
00102   void add_to_fcn_names (const std::string& name);
00103 
00104   void do_close_hook (octave_shlib::close_hook = 0);
00105 
00106   void tabula_rasa (void);
00107 
00108   // No copying!
00109 
00110   octave_base_shlib (const octave_base_shlib&);
00111 
00112   octave_base_shlib& operator = (const octave_base_shlib&);
00113 };
00114 
00115 bool
00116 octave_base_shlib::remove (const std::string& fcn_name)
00117 {
00118   bool retval = false;
00119 
00120   int n = number_of_functions_loaded ();
00121 
00122   string_vector new_fcn_names (n);
00123 
00124   int k = 0;
00125 
00126   for (int i = 0; i < n; i++)
00127     {
00128       if (fcn_names(i) == fcn_name)
00129         retval = true;
00130       else
00131         new_fcn_names(k++) = fcn_names(i);
00132     }
00133 
00134   new_fcn_names.resize (k);
00135 
00136   fcn_names = new_fcn_names;
00137 
00138   return retval;
00139 }
00140 
00141 bool
00142 octave_base_shlib::is_out_of_date (void) const
00143 {
00144   file_stat fs (file);
00145 
00146   return fs.is_newer (tm_loaded);
00147 }
00148 
00149 void
00150 octave_base_shlib::stamp_time (bool warn_future)
00151 {
00152   tm_loaded.stamp ();
00153 
00154   if (warn_future)
00155     {
00156       file_stat fs (file);
00157 
00158       if (fs.is_newer (tm_loaded))
00159         (*current_liboctave_warning_handler)
00160           ("timestamp on file %s is in the future", file.c_str ());
00161     }
00162 }
00163 
00164 void
00165 octave_base_shlib::add_to_fcn_names (const std::string& name)
00166 {
00167   int n = number_of_functions_loaded ();
00168 
00169   for (int i = 0; i < n; i++)
00170     if (fcn_names(i) == name)
00171       return;
00172 
00173   fcn_names.resize (n+1);
00174 
00175   fcn_names(n) = name;
00176 }
00177 
00178 void
00179 octave_base_shlib::do_close_hook (octave_shlib::close_hook cl_hook)
00180 {
00181   int n = number_of_functions_loaded ();
00182 
00183   for (int i = 0; i < n; i++)
00184     cl_hook (fcn_names(i));
00185 }
00186 
00187 void
00188 octave_base_shlib::tabula_rasa (void)
00189 {
00190   file = "";
00191 
00192   fcn_names.resize (0);
00193 
00194   tm_loaded = static_cast<time_t> (0);
00195 }
00196 
00197 #if defined (HAVE_DLOPEN_API)
00198 
00199 class
00200 octave_dlopen_shlib : public octave_base_shlib
00201 {
00202 public:
00203 
00204   octave_dlopen_shlib (void);
00205 
00206   ~octave_dlopen_shlib (void);
00207 
00208   void open (const std::string& f, bool warn_future = false);
00209 
00210   void *search (const std::string& name, name_mangler mangler = 0);
00211 
00212   void close (octave_shlib::close_hook cl_hook = 0);
00213 
00214   bool is_open (void) const { return (library != 0); }
00215 
00216 private:
00217 
00218   // No copying!
00219 
00220   octave_dlopen_shlib (const octave_dlopen_shlib&);
00221 
00222   octave_dlopen_shlib& operator = (const octave_dlopen_shlib&);
00223 
00224   void *library;
00225 };
00226 
00227 octave_dlopen_shlib::octave_dlopen_shlib (void)
00228   : octave_base_shlib (), library (0)
00229 {
00230 }
00231 
00232 octave_dlopen_shlib::~octave_dlopen_shlib (void)
00233 {
00234   close ();
00235 }
00236 
00237 void
00238 octave_dlopen_shlib::open (const std::string& f, bool warn_future)
00239 {
00240   if (! is_open ())
00241     {
00242       file = f;
00243 
00244       int flags = 0;
00245 
00246 #if defined (RTLD_LAZY)
00247       flags |= RTLD_LAZY;
00248 #endif
00249 
00250 #if defined (RTLD_GLOBAL)
00251       flags |= RTLD_GLOBAL;
00252 #endif
00253       
00254       library = dlopen (file.c_str (), flags);
00255 
00256       if (library)
00257         stamp_time (warn_future);
00258       else
00259         {
00260           const char *msg = dlerror ();
00261 
00262           if (msg)
00263             (*current_liboctave_error_handler) ("%s", msg);
00264         }
00265     }
00266   else
00267     (*current_liboctave_error_handler)
00268       ("shared library %s is already open", file.c_str ());
00269 }
00270 
00271 void *
00272 octave_dlopen_shlib::search (const std::string& name,
00273                              octave_shlib::name_mangler mangler)
00274 {
00275   void *function = 0;
00276 
00277   if (is_open ())
00278     {
00279       std::string sym_name = name;
00280 
00281       if (mangler)
00282         sym_name = mangler (name);
00283 
00284       function = dlsym (library, sym_name.c_str ());
00285 
00286       if (function)
00287         add_to_fcn_names (name);
00288     }
00289   else
00290     (*current_liboctave_error_handler)
00291       ("shared library %s is not open", file.c_str ());
00292 
00293   return function;
00294 }
00295 
00296 void
00297 octave_dlopen_shlib::close (octave_shlib::close_hook cl_hook)
00298 {
00299   if (is_open ())
00300     {
00301       do_close_hook (cl_hook);
00302 
00303       dlclose (library);
00304 
00305       library = 0;
00306 
00307       tabula_rasa ();
00308     }
00309 }
00310 
00311 #elif defined (HAVE_SHL_LOAD_API)
00312 
00313 class
00314 octave_shl_load_shlib : public octave_base_shlib
00315 {
00316 public:
00317 
00318   octave_shl_load_shlib (void);
00319 
00320   ~octave_shl_load_shlib (void);
00321 
00322   void open (const std::string& f, bool warn_future = false);
00323 
00324   void *search (const std::string& name, name_mangler mangler = 0);
00325 
00326   void close (octave_shlib::close_hook cl_hook = 0);
00327 
00328   bool is_open (void) const { return (library != 0); }
00329 
00330 private:
00331 
00332   // No copying!
00333 
00334   octave_shl_load_shlib (const octave_shl_load_shlib&);
00335 
00336   octave_shl_load_shlib& operator = (const octave_shl_load_shlib&);
00337 
00338   shl_t library;
00339 };
00340 
00341 octave_shl_load_shlib::octave_shl_load_shlib (void)
00342   : octave_base_shlib (), library (0)
00343 {
00344 }
00345 
00346 octave_shl_load_shlib::~octave_shl_load_shlib (void)
00347 {
00348   close ();
00349 }
00350 
00351 void
00352 octave_shl_load_shlib::open (const std::string& f, bool warn_future)
00353 {
00354   if (! is_open ())
00355     {
00356       file = f;
00357 
00358       library = shl_load (file.c_str (), BIND_DEFERRED, 0L);
00359 
00360       if (library)
00361         stamp_time (warn_future);
00362       else
00363         {
00364           using namespace std;
00365           (*current_liboctave_error_handler) ("%s", strerror (errno));
00366         }
00367     }
00368   else
00369     (*current_liboctave_error_handler)
00370       ("shared library %s is already open", file.c_str ());
00371 }
00372 
00373 void *
00374 octave_shl_load_shlib::search (const std::string& name,
00375                                octave_shlib::name_mangler mangler)
00376 {
00377   void *function = 0;
00378 
00379   if (is_open ())
00380     {
00381       std::string sym_name = name;
00382 
00383       if (mangler)
00384         sym_name = mangler (name);
00385         
00386       int status = shl_findsym (&library, sym_name.c_str (),
00387                                 TYPE_UNDEFINED, &function);
00388 
00389       if (status == 0)
00390         add_to_fcn_names (name);
00391     }
00392   else
00393     (*current_liboctave_error_handler)
00394       ("shared library %s is not open", file.c_str ());
00395 
00396   return function;
00397 }
00398 
00399 void
00400 octave_shl_load_shlib::close (octave_shlib::close_hook cl_hook)
00401 {
00402   if (is_open ())
00403     {
00404       do_close_hook (cl_hook);
00405 
00406       shl_unload (library);
00407 
00408       library = 0;
00409 
00410       tabula_rasa ();
00411     }
00412 }
00413 
00414 #elif defined (HAVE_LOADLIBRARY_API)
00415 
00416 class
00417 octave_w32_shlib: public octave_base_shlib
00418 {
00419 public:
00420 
00421   octave_w32_shlib (void);
00422 
00423   ~octave_w32_shlib (void);
00424 
00425   void open (const std::string& f, bool warn_future = false);
00426 
00427   void *search (const std::string& name, name_mangler mangler = 0);
00428 
00429   void close (octave_shlib::close_hook cl_hook = 0);
00430 
00431   bool is_open (void) const { return (handle != 0); }
00432 
00433 private:
00434 
00435   // No copying!
00436 
00437   octave_w32_shlib (const octave_w32_shlib&);
00438 
00439   octave_w32_shlib& operator = (const octave_w32_shlib&);
00440 
00441   HINSTANCE handle; 
00442 };
00443 
00444 octave_w32_shlib::octave_w32_shlib (void)
00445   : octave_base_shlib (), handle (0)
00446 {
00447 }
00448 
00449 octave_w32_shlib::~octave_w32_shlib (void)
00450 {
00451   close ();
00452 }
00453 
00454 void
00455 octave_w32_shlib::open (const std::string& f, bool warn_future)
00456 {
00457   if (! is_open ())
00458     {
00459       file = f;
00460 
00461       handle = LoadLibrary (file.c_str ());
00462 
00463       if (handle != NULL)
00464         stamp_time (warn_future);
00465       else
00466         {
00467           DWORD lastError = GetLastError ();
00468           char *msg;
00469 
00470           switch (lastError)
00471             {
00472             case ERROR_MOD_NOT_FOUND:
00473             case ERROR_DLL_NOT_FOUND:
00474               msg = "could not find library or dependents";
00475               break;
00476 
00477             case ERROR_INVALID_DLL:
00478               msg = "library or its dependents are damaged";
00479               break;
00480 
00481             case ERROR_DLL_INIT_FAILED:
00482               msg = "library initialization routine failed";
00483               break;
00484 
00485             default:
00486               msg = "library open failed";
00487             }
00488 
00489           (*current_liboctave_error_handler) ("%s: %s", msg, file.c_str ());
00490         }
00491     }
00492   else
00493     (*current_liboctave_error_handler)
00494       ("shared library %s is already open", file.c_str ());
00495 }
00496 
00497 void *
00498 octave_w32_shlib::search (const std::string& name,
00499                           octave_shlib::name_mangler mangler)
00500 {
00501   void *function = 0;
00502 
00503   if (is_open ())
00504     {
00505       std::string sym_name = name;
00506 
00507       if (mangler)
00508         sym_name = mangler (name);
00509 
00510       function
00511         = static_cast<void *> (GetProcAddress (handle, sym_name.c_str ()));
00512 
00513       if (function)
00514         add_to_fcn_names (name);
00515     }
00516   else
00517     (*current_liboctave_error_handler)
00518       ("shared library %s is not open", file.c_str ());
00519 
00520   return function;
00521 }
00522 
00523 void
00524 octave_w32_shlib::close (octave_shlib::close_hook cl_hook)
00525 {
00526   if (is_open ())
00527     {
00528       do_close_hook (cl_hook);
00529 
00530       FreeLibrary (handle);
00531 
00532       handle = 0;
00533 
00534       tabula_rasa ();
00535     }
00536 }
00537 
00538 #elif defined (HAVE_DYLD_API)
00539 
00540 class
00541 octave_dyld_shlib : public octave_base_shlib
00542 {
00543 public:
00544 
00545   octave_dyld_shlib (void);
00546 
00547   ~octave_dyld_shlib (void);
00548 
00549   void open (const std::string& f, bool warn_future = false);
00550 
00551   void *search (const std::string& name, name_mangler mangler = 0);
00552 
00553   void close (octave_shlib::close_hook cl_hook = 0);
00554 
00555   bool is_open (void) const {return (isOpen); }
00556 
00557 private:
00558 
00559   // No copying!
00560 
00561   octave_dyld_shlib (const octave_dyld_shlib&);
00562 
00563   octave_dyld_shlib& operator = (const octave_dyld_shlib&);
00564 
00565   bool isOpen;
00566   NSObjectFileImage img;
00567   NSModule handle;
00568 };
00569 
00570 octave_dyld_shlib::octave_dyld_shlib (void)
00571   : octave_base_shlib (), isOpen (false), handle (0)
00572 {
00573 }
00574 
00575 octave_dyld_shlib::~octave_dyld_shlib (void)
00576 {
00577   close ();
00578 }
00579 
00580 void
00581 octave_dyld_shlib::open (const std::string& f, bool warn_future)
00582 {
00583   int returnCode;
00584 
00585   if (! is_open ())
00586     {
00587       file = f;
00588 
00589       returnCode = NSCreateObjectFileImageFromFile (file.c_str (), &img);
00590 
00591       if (NSObjectFileImageSuccess == returnCode)
00592         {
00593           handle = NSLinkModule (img, file.c_str (),
00594                                  (NSLINKMODULE_OPTION_RETURN_ON_ERROR
00595                                   | NSLINKMODULE_OPTION_PRIVATE));
00596           if (handle)
00597             {
00598               stamp_time (warn_future);
00599               isOpen = true;
00600             }
00601           else
00602             {
00603               (*current_liboctave_error_handler)
00604                 ("couldn't link module %s", file.c_str ());     
00605             }
00606         }
00607       else
00608         {
00609           (*current_liboctave_error_handler)
00610             ("got NSObjectFileImageReturnCode %d", returnCode);
00611 
00612           // XXX FIXME XXX -- should use NSLinkEditError () to get
00613           // more info on what went wrong.
00614         }
00615     }
00616   else
00617     {
00618       (*current_liboctave_error_handler)
00619         ("bundle %s is already open", file.c_str ());
00620     }
00621 }
00622 
00623 void *
00624 octave_dyld_shlib::search (const std::string& name,
00625                            octave_shlib::name_mangler mangler)
00626 {
00627   void *function = 0;
00628 
00629   if (is_open ())
00630     {
00631       std::string sym_name = name;
00632 
00633       if (mangler)
00634         sym_name = mangler (name);
00635 
00636       NSSymbol symbol = NSLookupSymbolInModule (handle, sym_name.c_str ());
00637 
00638       if (symbol)
00639         {
00640           function = NSAddressOfSymbol (symbol);
00641           add_to_fcn_names (name);
00642         }
00643     }
00644   else
00645     (*current_liboctave_error_handler)
00646       ("bundle %s is not open", file.c_str ());
00647 
00648   return function;
00649 }
00650 
00651 void
00652 octave_dyld_shlib::close (octave_shlib::close_hook cl_hook)
00653 {
00654   if (is_open ())
00655     {
00656       do_close_hook (cl_hook);
00657 
00658       NSUnLinkModule (handle, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES);
00659 
00660       handle = 0;
00661 
00662       if (NSDestroyObjectFileImage (img))
00663         isOpen = false;
00664 
00665       tabula_rasa ();
00666     }
00667 }
00668 
00669 #endif
00670 
00671 octave_shlib *
00672 octave_shlib::make_shlib (void)
00673 {
00674 #if defined (HAVE_DLOPEN_API)
00675   return new octave_dlopen_shlib ();
00676 #elif defined (HAVE_SHL_LOAD_API)
00677   return new octave_shl_load_shlib ();
00678 #elif defined (HAVE_LOADLIBRARY_API)
00679   return new octave_w32_shlib ();
00680 #elif defined (HAVE_DYLD_API)
00681   return new octave_dyld_shlib ();
00682 #else
00683   return new octave_base_shlib ();
00684 #endif
00685 }
00686 
00687 /*
00688 ;;; Local Variables: ***
00689 ;;; mode: C++ ***
00690 ;;; End: ***
00691 */

Wed Dec 29 11:52:11 2004に生成されました。 doxygen1.2.18
SEO [PR] 爆速!無料ブログ 無料ホームページ開設 無料ライブ放送