PageRenderTime 49ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/TeXmacs-1.0.7.11-src/src/System/Link/dyn_link.cpp

#
C++ | 185 lines | 146 code | 21 blank | 18 comment | 42 complexity | 772ccf4be3d5a15156a4e3a18aca93e4 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. /******************************************************************************
  2. * MODULE : dyn_link.cpp
  3. * DESCRIPTION: Dynamic linking of extern routines
  4. * COPYRIGHT : (C) 1999 Joris van der Hoeven
  5. *******************************************************************************
  6. * This software falls under the GNU general public license version 3 or later.
  7. * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
  8. * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
  9. ******************************************************************************/
  10. #include "dyn_link.hpp"
  11. #include "url.hpp"
  12. #include "hashmap.hpp"
  13. #ifndef __MINGW32__
  14. #include <dlfcn.h>
  15. #endif
  16. #include <TeXmacs.h>
  17. static hashmap<string,pointer> dyn_linked (NULL);
  18. /******************************************************************************
  19. * Linking symbols from dynamic libraries
  20. ******************************************************************************/
  21. string
  22. symbol_install (string lib, string symb, pointer& f) {
  23. #ifndef __MINGW32__
  24. // f becomes NULL in case of failure
  25. // status message returned
  26. string out;
  27. if (!dyn_linked->contains (lib)) {
  28. url name= resolve (url ("$LD_LIBRARY_PATH", lib));
  29. if (is_none (name)) out= "Library '" * lib * "' not found";
  30. else {
  31. lib= concretize (name);
  32. char* _lib = as_charp (lib);
  33. dyn_linked (lib)= dlopen (_lib, RTLD_LAZY);
  34. if (dyn_linked [lib] == NULL) {
  35. const char *err = dlerror();
  36. if (err != NULL) out= string ((char *) err);
  37. }
  38. tm_delete_array (_lib);
  39. }
  40. }
  41. pointer handle= dyn_linked [lib];
  42. if (handle) {
  43. char* _symb= as_charp (symb);
  44. string tag= lib * ":" * symb;
  45. if (!dyn_linked->contains (tag))
  46. dyn_linked (tag)= dlsym (handle, _symb);
  47. f= dyn_linked [tag];
  48. if (f != NULL) out= "Dynamically linked symbol '" * symb * "'";
  49. else out= "Can not find symbol '" * symb * "' in '" * lib * "'";
  50. tm_delete_array (_symb);
  51. }
  52. else {
  53. f= NULL;
  54. if (out == "") out= "Couldn't find dynamic library '" * lib * "'";
  55. }
  56. if (DEBUG_AUTO) cout << "TeXmacs] " << out << "\n";
  57. return out;
  58. #else
  59. return "Dynamic linking not implemented";
  60. #endif
  61. }
  62. string
  63. symbols_install (string lib, string* symb, pointer* f, int n) {
  64. #ifndef __MINGW32__
  65. int i;
  66. for (i=0; i<n; i++) f[i]= NULL;
  67. for (i=0; i<n; i++) {
  68. string message= symbol_install (lib, symb[i], f[i]);
  69. if (f[i] == NULL) return message;
  70. }
  71. return "Symbols installed for library '" * lib * "'";
  72. #else
  73. return "Dynamic linking not implemented";
  74. #endif
  75. }
  76. /******************************************************************************
  77. * Dynamic links
  78. ******************************************************************************/
  79. dyn_link_rep::dyn_link_rep (string l, string s, string i, string ses):
  80. lib (l), symbol (s), init (i), routs (NULL), session (ses)
  81. {
  82. alive= false;
  83. }
  84. dyn_link_rep::~dyn_link_rep () {
  85. // FIXME: should we 'unlink' the package?
  86. }
  87. tm_link
  88. make_dynamic_link (string lib, string symb, string init, string session) {
  89. return tm_new<dyn_link_rep> (lib, symb, init, session);
  90. }
  91. static TeXmacs_exports_1 TeXmacs= {
  92. const_cast<char*> ("TeXmacs communication protocol 1"),
  93. const_cast<char*> ("TeXmacs " TEXMACS_VERSION),
  94. };
  95. string
  96. dyn_link_rep::start () {
  97. #ifndef __MINGW32__
  98. string name= lib * ":" * symbol * "-package";
  99. if (dyn_linked->contains (name))
  100. routs= dyn_linked [name];
  101. if (routs != NULL)
  102. return "continuation of#'" * lib * "'";
  103. if (DEBUG_AUTO)
  104. cout << "TeXmacs] Installing dynamic link '" << lib << "'\n";
  105. string message= symbol_install (lib, symbol, routs);
  106. if (routs != NULL) {
  107. dyn_linked (name)= routs;
  108. package_exports_1* pack= (package_exports_1*) routs;
  109. char* _init = as_charp (init);
  110. char* _errors= NULL;
  111. char* _message= pack->install (&TeXmacs, _init, &_errors);
  112. if (_errors != NULL) {
  113. routs= NULL;
  114. ret= "Error: " * string (_errors);
  115. }
  116. else {
  117. ret= string (_message == NULL? ((char*) ""): _message);
  118. alive= true;
  119. }
  120. tm_delete_array (_init);
  121. return ret;
  122. }
  123. else return message;
  124. #else
  125. return "Error: dynamic linking not implemented";
  126. #endif
  127. }
  128. void
  129. dyn_link_rep::write (string s, int channel) {
  130. #ifndef __MINGW32__
  131. if ((!alive) || (channel != LINK_IN)) return;
  132. if (routs==NULL) {
  133. cerr << "Library= " << lib << "\n";
  134. FAILED ("library not installed");
  135. }
  136. package_exports_1* pack= (package_exports_1*) routs;
  137. char* _session= as_charp (session);
  138. char* _s= as_charp (s);
  139. char* _errors= NULL;
  140. char* _r= pack->evaluate (_s, _session, &_errors);
  141. ret= string (_r==NULL? (_errors==NULL? ((char*) "Error"): _errors): _r);
  142. tm_delete_array (_s);
  143. tm_delete_array (_session);
  144. if (!is_nil (this->feed_cmd)) this->feed_cmd->apply ();
  145. #endif
  146. }
  147. string&
  148. dyn_link_rep::watch (int channel) {
  149. static string empty_string= "";
  150. if (channel == LINK_OUT) return ret;
  151. else return empty_string;
  152. }
  153. string
  154. dyn_link_rep::read (int channel) {
  155. if (channel == LINK_OUT) {
  156. string r= ret;
  157. ret= "";
  158. return r;
  159. }
  160. else return "";
  161. }
  162. void dyn_link_rep::listen (int msecs) { (void) msecs; }
  163. void dyn_link_rep::interrupt () {}
  164. void dyn_link_rep::stop () {}