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