Back to index

texmacs  1.0.7.15
dyn_link.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : dyn_link.cpp
00004 * DESCRIPTION: Dynamic linking of extern routines
00005 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include "dyn_link.hpp"
00013 #include "url.hpp"
00014 #include "hashmap.hpp"
00015 #ifndef __MINGW32__
00016 #include <dlfcn.h>
00017 #endif
00018 #include <TeXmacs.h>
00019 
00020 static hashmap<string,pointer> dyn_linked (NULL);
00021 
00022 /******************************************************************************
00023 * Linking symbols from dynamic libraries
00024 ******************************************************************************/
00025 
00026 string
00027 symbol_install (string lib, string symb, pointer& f) {
00028 #ifndef __MINGW32__
00029   // f becomes NULL in case of failure
00030   // status message returned
00031   string out;
00032 
00033   if (!dyn_linked->contains (lib)) {
00034     url name= resolve (url ("$LD_LIBRARY_PATH", lib));
00035     if (is_none (name)) out= "Library '" * lib * "' not found";
00036     else {
00037       lib= concretize (name);
00038       char* _lib = as_charp (lib);
00039       dyn_linked (lib)= dlopen (_lib, RTLD_LAZY);
00040       if (dyn_linked [lib] == NULL) {
00041        const char *err = dlerror();
00042        if (err != NULL) out= string ((char *) err);
00043       }
00044       tm_delete_array (_lib);
00045     }
00046   }
00047 
00048   pointer handle= dyn_linked [lib];
00049   if (handle) {
00050     char* _symb= as_charp (symb);
00051     string tag= lib * ":" * symb;
00052     if (!dyn_linked->contains (tag))
00053       dyn_linked (tag)= dlsym (handle, _symb);
00054     f= dyn_linked [tag];
00055     if (f != NULL) out= "Dynamically linked symbol '" * symb * "'";
00056     else out= "Can not find symbol '" * symb * "' in  '" * lib * "'";
00057     tm_delete_array (_symb);
00058   }
00059   else {
00060     f= NULL;
00061     if (out == "") out= "Couldn't find dynamic library '" * lib * "'";
00062   }
00063 
00064   if (DEBUG_AUTO) cout << "TeXmacs] " << out << "\n";
00065   return out;
00066 #else
00067   return "Dynamic linking not implemented";
00068 #endif
00069 }
00070 
00071 string
00072 symbols_install (string lib, string* symb, pointer* f, int n) {
00073 #ifndef __MINGW32__
00074   int i;
00075   for (i=0; i<n; i++) f[i]= NULL;
00076   for (i=0; i<n; i++) {
00077     string message= symbol_install (lib, symb[i], f[i]);
00078     if (f[i] == NULL) return message;
00079   }
00080   return "Symbols installed for library '" * lib * "'";
00081 #else
00082   return "Dynamic linking not implemented";
00083 #endif
00084 }
00085 
00086 /******************************************************************************
00087 * Dynamic links
00088 ******************************************************************************/
00089 
00090 dyn_link_rep::dyn_link_rep (string l, string s, string i, string ses):
00091   lib (l), symbol (s), init (i), routs (NULL), session (ses)
00092 {
00093   alive= false;
00094 }
00095 
00096 dyn_link_rep::~dyn_link_rep () {
00097   // FIXME: should we 'unlink' the package?
00098 }
00099 
00100 tm_link
00101 make_dynamic_link (string lib, string symb, string init, string session) {
00102   return tm_new<dyn_link_rep> (lib, symb, init, session);
00103 }
00104 
00105 static TeXmacs_exports_1 TeXmacs= {
00106   const_cast<char*> ("TeXmacs communication protocol 1"),
00107   const_cast<char*> ("TeXmacs " TEXMACS_VERSION),
00108 };
00109 
00110 string
00111 dyn_link_rep::start () {
00112 #ifndef __MINGW32__
00113   string name= lib * ":" * symbol * "-package";
00114   if (dyn_linked->contains (name))
00115     routs= dyn_linked [name];
00116   if (routs != NULL)
00117     return "continuation of#'" * lib * "'";
00118   if (DEBUG_AUTO)
00119     cout << "TeXmacs] Installing dynamic link '" << lib << "'\n";
00120 
00121   string message= symbol_install (lib, symbol, routs);
00122   if (routs != NULL) {
00123     dyn_linked (name)= routs;
00124     package_exports_1* pack= (package_exports_1*) routs;
00125     char* _init  = as_charp (init);
00126     char* _errors= NULL;
00127     char* _message= pack->install (&TeXmacs, _init, &_errors);
00128     if (_errors != NULL) {
00129       routs= NULL;
00130       ret= "Error: " * string (_errors);
00131     }
00132     else {
00133       ret= string (_message == NULL? ((char*) ""): _message);
00134       alive= true;
00135     }
00136     tm_delete_array (_init);
00137     return ret;
00138   }
00139   else return message;
00140 #else
00141   return "Error: dynamic linking not implemented";
00142 #endif
00143 }
00144 
00145 void
00146 dyn_link_rep::write (string s, int channel) {
00147 #ifndef __MINGW32__
00148   if ((!alive) || (channel != LINK_IN)) return;
00149   if (routs==NULL) {
00150     cerr << "Library= " << lib << "\n";
00151     FAILED ("library not installed");
00152   }
00153   package_exports_1* pack= (package_exports_1*) routs;
00154 
00155   char* _session= as_charp (session);
00156   char* _s= as_charp (s);
00157   char* _errors= NULL;
00158   char* _r= pack->evaluate (_s, _session, &_errors);
00159   ret= string (_r==NULL? (_errors==NULL? ((char*) "Error"): _errors): _r);
00160   tm_delete_array (_s);
00161   tm_delete_array (_session);
00162   if (!is_nil (this->feed_cmd)) this->feed_cmd->apply ();
00163 #endif
00164 }
00165 
00166 string&
00167 dyn_link_rep::watch (int channel) {
00168   static string empty_string= "";
00169   if (channel == LINK_OUT) return ret;
00170   else return empty_string;
00171 }
00172 
00173 string
00174 dyn_link_rep::read (int channel) {
00175   if (channel == LINK_OUT) {
00176     string r= ret;
00177     ret= "";
00178     return r;
00179   }
00180   else return "";
00181 }
00182 
00183 void dyn_link_rep::listen (int msecs) { (void) msecs; }
00184 void dyn_link_rep::interrupt () {}
00185 void dyn_link_rep::stop () {}